diff --git a/packages/libclaudebox/config.ts b/packages/libclaudebox/config.ts index 8f93441..c7463e9 100644 --- a/packages/libclaudebox/config.ts +++ b/packages/libclaudebox/config.ts @@ -25,7 +25,7 @@ export const BASTION_SSH_KEY = join(homedir(), ".ssh", "build_instance_key"); // ── Interactive session config ────────────────────────────────── export const CLAUDEBOX_HOST = process.env.CLAUDEBOX_HOST || "localhost:3000"; -export const SESSION_PAGE_USER = process.env.CLAUDEBOX_SESSION_USER || "admin"; +export const SESSION_PAGE_USER = process.env.CLAUDEBOX_SESSION_USER || "aztec"; export const SESSION_PAGE_PASS = process.env.CLAUDEBOX_SESSION_PASS || ""; // ── Log URL builder ───────────────────────────────────────────── diff --git a/packages/libclaudebox/docker.ts b/packages/libclaudebox/docker.ts index edbe764..42e0e73 100644 --- a/packages/libclaudebox/docker.ts +++ b/packages/libclaudebox/docker.ts @@ -147,8 +147,6 @@ export class DockerService { const profile = await loadProfile(profileDir); const dockerConfig = profile.docker || {}; const containerImage = dockerConfig.image || DOCKER_IMAGE; - const mountRef = dockerConfig.mountReferenceRepo !== false; // default true - console.log(`[DOCKER] Starting session ${logId} (worktree=${worktreeId} profile=${profileDir})`); console.log(`[DOCKER] Sidecar: ${sidecarName}`); console.log(`[DOCKER] Claude: ${claudeName}`); @@ -218,13 +216,11 @@ export class DockerService { `${claudeProjectsDir}:${CONTAINER_HOME}/.claude/projects/-workspace:ro`, `${CLAUDEBOX_CODE_DIR}:/opt/claudebox:ro`, `${profileHostDir}:/opt/claudebox-profile:rw`, - `${BASTION_SSH_KEY}:${CONTAINER_HOME}/.ssh/build_instance_key:ro`, + `${BASTION_SSH_KEY}:/home/aztec-dev/.ssh/build_instance_key:ro`, `${CLAUDEBOX_STATS_DIR}:/stats:rw`, `${CLAUDEBOX_DIR}:${CONTAINER_HOME}/.claudebox:rw`, ]; - if (mountRef) { - sidecarBinds.push(`${join(REPO_DIR, ".git")}:/reference-repo/.git:ro`); - } + sidecarBinds.push(`${join(REPO_DIR, ".git")}:/reference-repo/.git:ro`); // Server URL for sidecar → server communication (internal port, not exposed to internet) const serverUrl = `http://host.docker.internal:${INTERNAL_PORT}`; @@ -301,7 +297,6 @@ export class DockerService { "-v", `${join(CLAUDEBOX_CODE_DIR, "profiles", profileDir)}:/opt/claudebox-profile:rw`, "-e", `CLAUDEBOX_MCP_URL=${mcpUrl}`, "-e", `SESSION_UUID=${sessionUuid}`, - "-e", `AZTEC_MCP_SERVER=http://${sidecarName}:9801/creds`, "-e", `CLAUDEBOX_SIDECAR_HOST=${sidecarName}`, "-e", `CLAUDEBOX_SIDECAR_PORT=9801`, "-e", `PARENT_LOG_ID=${logId}`, @@ -318,10 +313,8 @@ export class DockerService { if (dockerConfig.extraBinds) { for (const b of dockerConfig.extraBinds) claudeArgs.push("-v", b); } - // Mount reference repo for profiles that use local clone - if (mountRef) { - claudeArgs.push("-v", `${join(REPO_DIR, ".git")}:/reference-repo/.git:ro`); - } + // Mount reference repo for sparse pre-clone + claudeArgs.push("-v", `${join(REPO_DIR, ".git")}:/reference-repo/.git:ro`); // Auto-detect resume if (opts.worktreeId) { diff --git a/packages/libclaudebox/html/workspace.ts b/packages/libclaudebox/html/workspace.ts index 71a0469..6388c30 100644 --- a/packages/libclaudebox/html/workspace.ts +++ b/packages/libclaudebox/html/workspace.ts @@ -525,6 +525,13 @@ function PromptCard({text, time, user, slackLink}){ // ── Artifact helpers ───────────────────────────────────────────── +// Deduplicate artifacts by URL (or full text if no URL), keeping last occurrence +function dedupArtifacts(artifacts){ + var seen=new Map(); + for(var a of artifacts){var t=slackToMd(a.text);var u=t.match(/https?:\\/\\/\\S+/);seen.set(u?u[0]:t,a);} + return[...seen.values()]; +} + // Extract PR number from artifact text function artifactPrNum(text){ var m=text.match(/#(\\d+)/); @@ -534,7 +541,8 @@ function artifactPrNum(text){ // Build compact artifact chips for a run, marking PR updates function ArtifactChips({artifacts, priorPrNums}){ if(!artifacts||!artifacts.length)return null; - return html\`
\${artifacts.map((a,i)=>{ + var unique=dedupArtifacts(artifacts); + return html\`
\${unique.map((a,i)=>{ var text=slackToMd(a.text); var prNum=artifactPrNum(text); var isUpdate=(prNum&&priorPrNums&&priorPrNums.has(prNum))||/updated/i.test(text); @@ -544,20 +552,33 @@ function ArtifactChips({artifacts, priorPrNums}){ } // ── AgentSection — collapsible agent card ───────────────────── -function AgentSection({text, agentLogUrl, time, children}){ - const [expanded,setExpanded]=useState(false); +function AgentSection({text, agentId, time, children}){ + const PREVIEW=6; + const [expanded,setExpanded]=useState(()=>window.location.hash==="#agent-"+agentId); + const [showAll,setShowAll]=useState(false); + const total=children?children.length:0; + const visible=showAll||total<=PREVIEW?children:(children||[]).slice(0,PREVIEW); const linked=linkify(slackToMd(text)); - const agentInner=agentLogUrl - ?''+linked+'' - :linked; - return html\`
-
setExpanded(!expanded)}> + const ref=useRef(null); + useEffect(()=>{if(expanded&&ref.current&&window.location.hash==="#agent-"+agentId)ref.current.scrollIntoView({block:"start"});},[]); + function toggle(){ + const next=!expanded; + setExpanded(next); + if(next){history.replaceState(null,"","#agent-"+agentId);} + else{history.replaceState(null,"",window.location.pathname+window.location.search);} + } + return html\`
+
\u25B6 - + + \${total?html\`(\${total})\`:null} \${time}
- \${children&&children.length?html\`
\${children}
\`:null} + \${expanded&&visible&&visible.length?html\`
+ \${visible} + \${!showAll&&total>PREVIEW?html\`
{e.stopPropagation();setShowAll(true);}}>show all \${total} entries
\`:null} +
\`:null}
\`; } @@ -568,22 +589,23 @@ function renderActivityItems(activity){ var item=activity[i]; var entry=item.entry; var key=item.id||("a"+i); - // Agent sections — collect subsequent tool calls until next non-tool entry + // Agent sections — collect subsequent tool/subagent entries if(entry.type==="agent_start"){ var agentChildren=[]; var j=i+1; while(j\${grouped}\`); - i=j-1; // skip grouped items + var agentId=key.replace(/[^a-z0-9-]/gi,""); + out.push(html\`<\${AgentSection} key=\${key} text=\${entry.text||""} agentId=\${agentId} time=\${entry.ts?timeAgo(entry.ts):""}>\${grouped}\`); + i=j-1; continue; } if(entry.type==="tool_use"){ @@ -778,12 +800,10 @@ function Sidebar({open, status, exitCode, user, baseBranch, sessions, artifacts, \${sessions.length&&sessions[0].started?html\`
started \${timeAgo(sessions[0].started)}
\`:null}
\${artifacts.length?html\`\`;})()}
\`:null} \${sessions.length>1?html\`