@rallycry/conveyor-agent 2.14.1 → 2.14.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -1779,9 +1779,12 @@ var ProjectRunner = class {
1779
1779
  }
1780
1780
  }
1781
1781
  const cliPath = path.resolve(__dirname, "cli.js");
1782
+ const childEnv = { ...process.env };
1783
+ delete childEnv.CONVEYOR_PROJECT_TOKEN;
1784
+ delete childEnv.CONVEYOR_PROJECT_ID;
1782
1785
  const child = fork(cliPath, [], {
1783
1786
  env: {
1784
- ...process.env,
1787
+ ...childEnv,
1785
1788
  CONVEYOR_API_URL: apiUrl,
1786
1789
  CONVEYOR_TASK_TOKEN: taskToken,
1787
1790
  CONVEYOR_TASK_ID: taskId,
@@ -1894,4 +1897,4 @@ export {
1894
1897
  ProjectConnection,
1895
1898
  ProjectRunner
1896
1899
  };
1897
- //# sourceMappingURL=chunk-N6QGELGE.js.map
1900
+ //# sourceMappingURL=chunk-7XJAQPDE.js.map
@@ -1 +1 @@
1
- {"version":3,"sources":["../src/connection.ts","../src/setup.ts","../src/worktree.ts","../src/runner.ts","../src/query-executor.ts","../src/prompt-builder.ts","../src/mcp-tools.ts","../src/project-connection.ts","../src/project-runner.ts"],"sourcesContent":["import { io, type Socket } from \"socket.io-client\";\nimport type { AgentRunnerConfig, TaskContext, AgentEvent } from \"./types.js\";\n\ninterface AgentQuestionOption {\n label: string;\n description: string;\n preview?: string;\n}\n\ninterface AgentQuestion {\n question: string;\n header: string;\n options: AgentQuestionOption[];\n multiSelect?: boolean;\n}\n\nexport class ConveyorConnection {\n private socket: Socket | null = null;\n private config: AgentRunnerConfig;\n private eventBuffer: { taskId: string; event: AgentEvent }[] = [];\n private flushTimer: ReturnType<typeof setTimeout> | null = null;\n private static readonly EVENT_BATCH_MS = 500;\n\n private earlyMessages: {\n content: string;\n userId: string;\n files?: {\n id: string;\n fileName: string;\n mimeType: string;\n downloadUrl: string;\n content?: string;\n contentEncoding?: \"base64\" | \"utf-8\";\n }[];\n }[] = [];\n private earlyStop = false;\n private chatMessageCallback:\n | ((msg: {\n content: string;\n userId: string;\n files?: {\n id: string;\n fileName: string;\n mimeType: string;\n downloadUrl: string;\n content?: string;\n contentEncoding?: \"base64\" | \"utf-8\";\n }[];\n }) => void)\n | null = null;\n private stopCallback: (() => void) | null = null;\n private pendingQuestionResolvers = new Map<string, (answers: Record<string, string>) => void>();\n\n constructor(config: AgentRunnerConfig) {\n this.config = config;\n }\n\n connect(): Promise<void> {\n return new Promise((resolve, reject) => {\n let settled = false;\n let attempts = 0;\n const maxInitialAttempts = 30;\n\n this.socket = io(this.config.conveyorApiUrl, {\n auth: { taskToken: this.config.taskToken, runnerMode: this.config.mode ?? \"task\" },\n transports: [\"websocket\"],\n reconnection: true,\n reconnectionAttempts: Infinity,\n reconnectionDelay: 2000,\n reconnectionDelayMax: 30000,\n randomizationFactor: 0.3,\n extraHeaders: {\n \"ngrok-skip-browser-warning\": \"true\",\n },\n });\n\n // Register listeners immediately so we capture messages the server\n // flushes during registerHandlers (before connect() resolves).\n this.socket.on(\n \"agentRunner:incomingMessage\",\n (msg: {\n content: string;\n userId: string;\n files?: {\n id: string;\n fileName: string;\n mimeType: string;\n downloadUrl: string;\n content?: string;\n contentEncoding?: \"base64\" | \"utf-8\";\n }[];\n }) => {\n if (this.chatMessageCallback) {\n this.chatMessageCallback(msg);\n } else {\n this.earlyMessages.push(msg);\n }\n },\n );\n\n this.socket.on(\"agentRunner:stop\", () => {\n if (this.stopCallback) {\n this.stopCallback();\n } else {\n this.earlyStop = true;\n }\n });\n\n this.socket.on(\n \"agentRunner:questionAnswer\",\n (data: { requestId: string; answers: Record<string, string> }) => {\n const resolver = this.pendingQuestionResolvers.get(data.requestId);\n if (resolver) {\n this.pendingQuestionResolvers.delete(data.requestId);\n resolver(data.answers);\n }\n },\n );\n\n this.socket.on(\"connect\", () => {\n if (!settled) {\n settled = true;\n resolve();\n }\n });\n\n this.socket.io.on(\"reconnect_attempt\", () => {\n attempts++;\n if (!settled && attempts >= maxInitialAttempts) {\n settled = true;\n reject(new Error(`Failed to connect after ${maxInitialAttempts} attempts`));\n }\n });\n });\n }\n\n fetchChatMessages(\n limit?: number,\n ): Promise<\n { role: string; content: string; userId: string | null; userName?: string; createdAt: string }[]\n > {\n const socket = this.socket;\n if (!socket) throw new Error(\"Not connected\");\n\n return new Promise((resolve, reject) => {\n socket.emit(\n \"agentRunner:getChatMessages\",\n { taskId: this.config.taskId, limit },\n (response: {\n success: boolean;\n data?: {\n role: string;\n content: string;\n userId: string | null;\n userName?: string;\n createdAt: string;\n }[];\n error?: string;\n }): void => {\n if (response.success && response.data) {\n resolve(response.data);\n } else {\n reject(new Error(response.error ?? \"Failed to fetch chat messages\"));\n }\n },\n );\n });\n }\n\n fetchTaskContext(): Promise<TaskContext> {\n const socket = this.socket;\n if (!socket) throw new Error(\"Not connected\");\n\n return new Promise((resolve, reject) => {\n socket.emit(\n \"agentRunner:getTaskContext\",\n { taskId: this.config.taskId },\n (response: { success: boolean; data?: TaskContext; error?: string }): void => {\n if (response.success && response.data) {\n resolve(response.data);\n } else {\n reject(new Error(response.error ?? \"Failed to fetch task context\"));\n }\n },\n );\n });\n }\n\n sendEvent(event: AgentEvent): void {\n if (!this.socket) throw new Error(\"Not connected\");\n\n this.eventBuffer.push({ taskId: this.config.taskId, event });\n if (!this.flushTimer) {\n this.flushTimer = setTimeout(() => this.flushEvents(), ConveyorConnection.EVENT_BATCH_MS);\n }\n }\n\n flushEvents(): void {\n if (this.flushTimer) {\n clearTimeout(this.flushTimer);\n this.flushTimer = null;\n }\n if (!this.socket || this.eventBuffer.length === 0) return;\n for (const entry of this.eventBuffer) {\n this.socket.emit(\"agentRunner:event\", entry);\n }\n this.eventBuffer = [];\n }\n\n updateStatus(status: string): void {\n if (!this.socket) throw new Error(\"Not connected\");\n\n this.socket.emit(\"agentRunner:statusUpdate\", {\n taskId: this.config.taskId,\n status,\n });\n }\n\n postChatMessage(content: string): void {\n if (!this.socket) throw new Error(\"Not connected\");\n\n this.socket.emit(\"agentRunner:chatMessage\", {\n taskId: this.config.taskId,\n content,\n });\n }\n\n createPR(params: {\n title: string;\n body: string;\n baseBranch?: string;\n }): Promise<{ url: string; number: number }> {\n const socket = this.socket;\n if (!socket) throw new Error(\"Not connected\");\n\n return new Promise((resolve, reject) => {\n socket.emit(\n \"agentRunner:createPR\",\n { taskId: this.config.taskId, ...params },\n (response: {\n success: boolean;\n data?: { url: string; number: number };\n error?: string;\n }): void => {\n if (response.success && response.data) {\n resolve(response.data);\n } else {\n reject(new Error(response.error ?? \"Failed to create pull request\"));\n }\n },\n );\n });\n }\n\n askUserQuestion(requestId: string, questions: AgentQuestion[]): Promise<Record<string, string>> {\n if (!this.socket) throw new Error(\"Not connected\");\n\n this.socket.emit(\"agentRunner:askUserQuestion\", {\n taskId: this.config.taskId,\n requestId,\n questions,\n });\n\n return new Promise((resolve) => {\n this.pendingQuestionResolvers.set(requestId, resolve);\n });\n }\n\n cancelPendingQuestions(): void {\n this.pendingQuestionResolvers.clear();\n }\n\n storeSessionId(sessionId: string): void {\n if (!this.socket) return;\n this.socket.emit(\"agentRunner:storeSessionId\", {\n taskId: this.config.taskId,\n sessionId,\n });\n }\n\n updateTaskFields(fields: { plan?: string; description?: string }): void {\n if (!this.socket) throw new Error(\"Not connected\");\n this.socket.emit(\"agentRunner:updateTaskFields\", {\n taskId: this.config.taskId,\n fields,\n });\n }\n\n onChatMessage(\n callback: (message: {\n content: string;\n userId: string;\n files?: {\n id: string;\n fileName: string;\n mimeType: string;\n downloadUrl: string;\n content?: string;\n contentEncoding?: \"base64\" | \"utf-8\";\n }[];\n }) => void,\n ): void {\n this.chatMessageCallback = callback;\n for (const msg of this.earlyMessages) {\n callback(msg);\n }\n this.earlyMessages = [];\n }\n\n onStopRequested(callback: () => void): void {\n this.stopCallback = callback;\n if (this.earlyStop) {\n callback();\n this.earlyStop = false;\n }\n }\n\n trackSpending(params: {\n agentId: string;\n inputTokens: number;\n outputTokens: number;\n totalTokens: number;\n totalCostUsd: number;\n onSubscription: boolean;\n }): void {\n if (!this.socket) throw new Error(\"Not connected\");\n\n this.socket.emit(\"agentRunner:trackSpending\", {\n taskId: this.config.taskId,\n ...params,\n });\n }\n\n emitStatus(status: string): void {\n if (!this.socket) return;\n this.socket.emit(\"agentRunner:statusUpdate\", {\n taskId: this.config.taskId,\n status,\n });\n }\n\n sendHeartbeat(): void {\n if (!this.socket) return;\n this.socket.emit(\"agentRunner:heartbeat\", {\n taskId: this.config.taskId,\n });\n }\n\n sendTypingStart(): void {\n this.sendEvent({ type: \"agent_typing_start\" });\n }\n\n sendTypingStop(): void {\n this.sendEvent({ type: \"agent_typing_stop\" });\n }\n\n createSubtask(data: {\n title: string;\n description?: string;\n plan?: string;\n ordinal?: number;\n storyPointValue?: number;\n }): Promise<{ id: string }> {\n const socket = this.socket;\n if (!socket) throw new Error(\"Not connected\");\n return new Promise((resolve, reject) => {\n socket.emit(\n \"agentRunner:createSubtask\",\n data,\n (response: { success: boolean; data?: { id: string }; error?: string }) => {\n if (response.success && response.data) resolve(response.data);\n else reject(new Error(response.error ?? \"Failed to create subtask\"));\n },\n );\n });\n }\n\n updateSubtask(\n subtaskId: string,\n fields: {\n title?: string;\n description?: string;\n plan?: string;\n ordinal?: number;\n storyPointValue?: number;\n },\n ): void {\n if (!this.socket) throw new Error(\"Not connected\");\n this.socket.emit(\"agentRunner:updateSubtask\", {\n subtaskId,\n fields,\n });\n }\n\n deleteSubtask(subtaskId: string): void {\n if (!this.socket) throw new Error(\"Not connected\");\n this.socket.emit(\"agentRunner:deleteSubtask\", { subtaskId });\n }\n\n listSubtasks(): Promise<\n {\n id: string;\n title: string;\n description: string | null;\n status: string;\n ordinal: number;\n storyPointId: string | null;\n plan: string | null;\n }[]\n > {\n const socket = this.socket;\n if (!socket) throw new Error(\"Not connected\");\n return new Promise((resolve, reject) => {\n socket.emit(\n \"agentRunner:listSubtasks\",\n {},\n (response: {\n success: boolean;\n data?: {\n id: string;\n title: string;\n description: string | null;\n status: string;\n ordinal: number;\n storyPointId: string | null;\n plan: string | null;\n }[];\n error?: string;\n }) => {\n if (response.success && response.data) resolve(response.data);\n else reject(new Error(response.error ?? \"Failed to list subtasks\"));\n },\n );\n });\n }\n\n disconnect(): void {\n this.flushEvents();\n this.socket?.disconnect();\n this.socket = null;\n }\n}\n","import { execSync } from \"node:child_process\";\nimport { spawn, type ChildProcess } from \"node:child_process\";\nimport { readFile } from \"node:fs/promises\";\nimport { join } from \"node:path\";\n\nexport interface ConveyorConfig {\n setupCommand?: string;\n startCommand?: string;\n previewPort?: number;\n}\n\nconst CONVEYOR_CONFIG_PATH = \".conveyor/config.json\";\nconst DEVCONTAINER_PATH = \".devcontainer/conveyor/devcontainer.json\";\n\nexport async function loadForwardPorts(workspaceDir: string): Promise<number[]> {\n try {\n const raw = await readFile(join(workspaceDir, DEVCONTAINER_PATH), \"utf-8\");\n const parsed = JSON.parse(raw) as { forwardPorts?: number[] };\n return parsed.forwardPorts ?? [];\n } catch {\n return [];\n }\n}\n\nexport async function loadConveyorConfig(workspaceDir: string): Promise<ConveyorConfig | null> {\n // Primary: .conveyor/config.json\n try {\n const raw = await readFile(join(workspaceDir, CONVEYOR_CONFIG_PATH), \"utf-8\");\n const parsed = JSON.parse(raw) as ConveyorConfig;\n if (parsed.setupCommand || parsed.startCommand) return parsed;\n } catch {\n // Not found or invalid — try fallback\n }\n\n // Fallback: devcontainer.json \"conveyor\" section\n try {\n const raw = await readFile(join(workspaceDir, DEVCONTAINER_PATH), \"utf-8\");\n const parsed = JSON.parse(raw) as { conveyor?: ConveyorConfig };\n if (parsed.conveyor && (parsed.conveyor.startCommand || parsed.conveyor.setupCommand)) {\n return parsed.conveyor;\n }\n } catch {\n // Not found or invalid\n }\n\n return null;\n}\n\n/**\n * Runs a command synchronously (waits for exit). Streams stdout/stderr\n * line-by-line via the onOutput callback.\n */\nexport function runSetupCommand(\n cmd: string,\n cwd: string,\n onOutput: (stream: \"stdout\" | \"stderr\", data: string) => void,\n): Promise<void> {\n return new Promise((resolve, reject) => {\n const child = spawn(\"sh\", [\"-c\", cmd], {\n cwd,\n stdio: [\"ignore\", \"pipe\", \"pipe\"],\n env: { ...process.env },\n });\n\n child.stdout.on(\"data\", (chunk: Buffer) => {\n onOutput(\"stdout\", chunk.toString());\n });\n\n child.stderr.on(\"data\", (chunk: Buffer) => {\n onOutput(\"stderr\", chunk.toString());\n });\n\n child.on(\"close\", (code) => {\n if (code === 0) {\n resolve();\n } else {\n reject(new Error(`Setup command exited with code ${code}`));\n }\n });\n\n child.on(\"error\", (err) => {\n reject(err);\n });\n });\n}\n\n/**\n * Runs a command in the background (does not wait for exit). Returns the\n * ChildProcess so it can be cleaned up on agent shutdown. Streams\n * stdout/stderr via the onOutput callback.\n */\nexport function runStartCommand(\n cmd: string,\n cwd: string,\n onOutput: (stream: \"stdout\" | \"stderr\", data: string) => void,\n): ChildProcess {\n const child = spawn(\"sh\", [\"-c\", cmd], {\n cwd,\n stdio: [\"ignore\", \"pipe\", \"pipe\"],\n detached: true,\n env: { ...process.env },\n });\n\n child.stdout.on(\"data\", (chunk: Buffer) => {\n onOutput(\"stdout\", chunk.toString());\n });\n\n child.stderr.on(\"data\", (chunk: Buffer) => {\n onOutput(\"stderr\", chunk.toString());\n });\n\n child.unref();\n return child;\n}\n\n/**\n * Reset `.devcontainer/conveyor/devcontainer.json` to match the base branch\n * and remove the cloud-build \"configure\" commit from git history. This runs\n * AFTER the codespace has started (env vars are already in process memory)\n * so the agent sees a branch identical to base — no spurious diffs, no\n * rebase conflicts on devcontainer.json.\n */\nexport function cleanDevcontainerFromGit(\n workspaceDir: string,\n taskBranch: string,\n baseBranch: string,\n): { cleaned: boolean; message: string } {\n const git = (cmd: string): string =>\n execSync(cmd, { cwd: workspaceDir, encoding: \"utf-8\", timeout: 30_000 }).trim();\n\n try {\n git(`git fetch origin ${baseBranch}`);\n } catch {\n return { cleaned: false, message: `Failed to fetch origin/${baseBranch}` };\n }\n\n // Check if devcontainer.json differs from base\n try {\n git(`git diff --quiet origin/${baseBranch} -- ${DEVCONTAINER_PATH}`);\n return { cleaned: false, message: \"devcontainer.json already matches base\" };\n } catch {\n // diff --quiet exits non-zero when there IS a diff — expected path\n }\n\n try {\n const ahead = parseInt(git(`git rev-list --count origin/${baseBranch}..HEAD`), 10);\n\n if (ahead <= 1) {\n // Fresh start: only the devcontainer commit exists — hard reset to base\n git(`git reset --hard origin/${baseBranch}`);\n } else {\n // Relaunch: agent has prior commits — restore file and add fixup commit\n git(`git checkout origin/${baseBranch} -- ${DEVCONTAINER_PATH}`);\n git(`git add ${DEVCONTAINER_PATH}`);\n\n try {\n git(`git diff --cached --quiet -- ${DEVCONTAINER_PATH}`);\n return { cleaned: false, message: \"devcontainer.json already clean in working tree\" };\n } catch {\n git(`git commit -m \"chore: reset devcontainer config\"`);\n }\n }\n\n git(`git push --force-with-lease origin ${taskBranch}`);\n return { cleaned: true, message: \"devcontainer.json cleaned from git history\" };\n } catch (err) {\n const msg = err instanceof Error ? err.message : \"Unknown error\";\n return { cleaned: false, message: `Git cleanup failed: ${msg}` };\n }\n}\n","import { execSync } from \"node:child_process\";\nimport { existsSync } from \"node:fs\";\nimport { join } from \"node:path\";\n\nconst WORKTREE_DIR = \".worktrees\";\n\n/**\n * Ensure a git worktree exists for the given task. Creates one if it doesn't\n * exist, reuses the existing one otherwise. Returns the absolute worktree path.\n *\n * Uses --detach to avoid \"branch already checked out\" errors when the branch\n * (e.g. dev) is already checked out in the main worktree or another worktree.\n */\nexport function ensureWorktree(projectDir: string, taskId: string, branch?: string): string {\n const worktreePath = join(projectDir, WORKTREE_DIR, taskId);\n\n if (existsSync(worktreePath)) {\n if (branch) {\n try {\n execSync(`git checkout --detach origin/${branch}`, {\n cwd: worktreePath,\n stdio: \"ignore\",\n });\n } catch {\n /* branch doesn't exist on remote yet */\n }\n }\n return worktreePath;\n }\n\n const ref = branch ? `origin/${branch}` : \"HEAD\";\n execSync(`git worktree add --detach \"${worktreePath}\" ${ref}`, {\n cwd: projectDir,\n stdio: \"ignore\",\n });\n\n return worktreePath;\n}\n\n/**\n * Remove a task's git worktree. Best-effort — silently ignores failures.\n */\nexport function removeWorktree(projectDir: string, taskId: string): void {\n const worktreePath = join(projectDir, WORKTREE_DIR, taskId);\n if (!existsSync(worktreePath)) return;\n try {\n execSync(`git worktree remove \"${worktreePath}\" --force`, {\n cwd: projectDir,\n stdio: \"ignore\",\n });\n } catch {\n /* best effort */\n }\n}\n","import { execSync } from \"node:child_process\";\nimport { readdirSync, statSync, readFileSync } from \"node:fs\";\nimport { homedir } from \"node:os\";\nimport { join } from \"node:path\";\nimport type { SDKUserMessage } from \"@anthropic-ai/claude-agent-sdk\";\nimport type {\n AgentRunnerConfig,\n AgentRunnerCallbacks,\n AgentRunnerStatus,\n AgentEvent,\n TaskContext,\n} from \"./types.js\";\nimport { ConveyorConnection } from \"./connection.js\";\nimport {\n cleanDevcontainerFromGit,\n loadConveyorConfig,\n loadForwardPorts,\n runSetupCommand,\n runStartCommand,\n type ConveyorConfig,\n} from \"./setup.js\";\nimport { runSdkQuery, type QueryHost } from \"./query-executor.js\";\nimport { ensureWorktree } from \"./worktree.js\";\n\nconst HEARTBEAT_INTERVAL_MS = 30_000;\n\nexport class AgentRunner {\n private config: AgentRunnerConfig;\n private connection: ConveyorConnection;\n private callbacks: AgentRunnerCallbacks;\n private _state: AgentRunnerStatus = \"connecting\";\n private stopped = false;\n private inputResolver: ((msg: SDKUserMessage) => void) | null = null;\n private pendingMessages: SDKUserMessage[] = [];\n private setupLog: string[] = [];\n private heartbeatTimer: ReturnType<typeof setInterval> | null = null;\n private taskContext: TaskContext | null = null;\n private planFileSnapshot = new Map<string, number>();\n private lockedPlanFile: string | null = null;\n private worktreeActive = false;\n private static readonly MAX_SETUP_LOG_LINES = 50;\n\n constructor(config: AgentRunnerConfig, callbacks: AgentRunnerCallbacks) {\n this.config = config;\n this.connection = new ConveyorConnection(config);\n this.callbacks = callbacks;\n }\n\n get state(): AgentRunnerStatus {\n return this._state;\n }\n\n private async setState(status: AgentRunnerStatus): Promise<void> {\n this._state = status;\n this.connection.emitStatus(status);\n await this.callbacks.onStatusChange(status);\n }\n\n private startHeartbeat(): void {\n this.heartbeatTimer = setInterval(() => {\n if (!this.stopped) {\n this.connection.sendHeartbeat();\n }\n }, HEARTBEAT_INTERVAL_MS);\n }\n\n private stopHeartbeat(): void {\n if (this.heartbeatTimer) {\n clearInterval(this.heartbeatTimer);\n this.heartbeatTimer = null;\n }\n }\n\n async start(): Promise<void> {\n await this.setState(\"connecting\");\n await this.connection.connect();\n\n this.connection.onStopRequested(() => this.stop());\n this.connection.onChatMessage((message) =>\n this.injectHumanMessage(message.content, message.files),\n );\n\n await this.setState(\"connected\");\n this.connection.sendEvent({ type: \"connected\", taskId: this.config.taskId });\n this.startHeartbeat();\n\n if (this.config.mode !== \"pm\" && process.env.CODESPACES === \"true\") {\n const setupOk = await this.runSetupSafe();\n if (!setupOk) {\n this.stopHeartbeat();\n await this.setState(\"error\");\n this.connection.disconnect();\n return;\n }\n }\n\n this.initRtk();\n\n // --- Phase 2.5: Worktree isolation (local agents) ---\n if (this.config.mode === \"pm\" || process.env.CONVEYOR_USE_WORKTREE === \"true\") {\n try {\n const worktreePath = ensureWorktree(this.config.workspaceDir, this.config.taskId);\n this.config = { ...this.config, workspaceDir: worktreePath };\n this.worktreeActive = true;\n this.setupLog.push(`[conveyor] Using worktree: ${worktreePath}`);\n } catch (error) {\n const msg = error instanceof Error ? error.message : \"Unknown error\";\n this.setupLog.push(`[conveyor] Worktree creation failed, using shared workspace: ${msg}`);\n }\n }\n\n // --- Phase 3: Fetch context ---\n await this.setState(\"fetching_context\");\n try {\n this.taskContext = await this.connection.fetchTaskContext();\n } catch (error) {\n const message = error instanceof Error ? error.message : \"Failed to fetch task context\";\n this.connection.sendEvent({ type: \"error\", message });\n await this.callbacks.onEvent({ type: \"error\", message });\n this.stopHeartbeat();\n await this.setState(\"error\");\n this.connection.disconnect();\n return;\n }\n\n // When resuming an existing session after a process restart, initialise\n // _lastReportedCostUsd from the spending already recorded in the DB so\n // the first SDK result delta is correct (fixes Bug 1 — over-counting).\n if (this.taskContext.claudeSessionId && this.taskContext._existingSpendingTotal !== null) {\n this.taskContext._lastReportedCostUsd = this.taskContext._existingSpendingTotal;\n }\n\n if (process.env.CODESPACES === \"true\" && this.taskContext.baseBranch) {\n const result = cleanDevcontainerFromGit(\n this.config.workspaceDir,\n this.taskContext.githubBranch,\n this.taskContext.baseBranch,\n );\n if (result.cleaned) {\n this.setupLog.push(`[conveyor] ${result.message}`);\n }\n }\n\n if (!this.worktreeActive && this.taskContext.useWorktree) {\n try {\n const worktreePath = ensureWorktree(this.config.workspaceDir, this.config.taskId);\n this.config = { ...this.config, workspaceDir: worktreePath };\n this.worktreeActive = true;\n this.setupLog.push(`[conveyor] Using worktree (from task config): ${worktreePath}`);\n } catch (error) {\n const msg = error instanceof Error ? error.message : \"Unknown error\";\n this.setupLog.push(`[conveyor] Worktree creation failed, using shared workspace: ${msg}`);\n }\n }\n\n if (this.worktreeActive && this.taskContext.githubBranch) {\n try {\n const branch = this.taskContext.githubBranch;\n execSync(`git fetch origin ${branch} && git checkout ${branch}`, {\n cwd: this.config.workspaceDir,\n stdio: \"ignore\",\n });\n } catch {\n /* branch may not exist remotely yet or already checked out */\n }\n }\n\n // --- Phase 4: Initial action ---\n const isPm = this.config.mode === \"pm\";\n if (isPm) {\n await this.setState(\"idle\");\n } else {\n await this.setState(\"running\");\n await runSdkQuery(this.asQueryHost(), this.taskContext);\n if (!this.stopped) await this.setState(\"idle\");\n }\n\n await this.runCoreLoop();\n\n this.stopHeartbeat();\n await this.setState(\"finished\");\n this.connection.disconnect();\n }\n\n private async runCoreLoop(): Promise<void> {\n if (!this.taskContext) return;\n while (!this.stopped) {\n if (this._state === \"idle\") {\n const msg = await this.waitForUserContent();\n if (!msg) break;\n await this.setState(\"running\");\n await runSdkQuery(this.asQueryHost(), this.taskContext, msg);\n if (!this.stopped) await this.setState(\"idle\");\n } else if (this._state === \"error\") {\n await this.setState(\"idle\");\n } else {\n break;\n }\n }\n }\n\n private async runSetupSafe(): Promise<boolean> {\n await this.setState(\"setup\");\n\n const ports = await loadForwardPorts(this.config.workspaceDir);\n if (ports.length > 0 && process.env.CODESPACE_NAME) {\n const visibility = ports.map((p) => `${p}:public`).join(\" \");\n runStartCommand(\n `gh codespace ports visibility ${visibility} -c \"${process.env.CODESPACE_NAME}\" 2>/dev/null`,\n this.config.workspaceDir,\n () => undefined,\n );\n }\n\n const config = await loadConveyorConfig(this.config.workspaceDir);\n if (!config) {\n this.connection.sendEvent({ type: \"setup_complete\" });\n await this.callbacks.onEvent({ type: \"setup_complete\" });\n return true;\n }\n\n try {\n await this.executeSetupConfig(config);\n const setupEvent: AgentEvent = {\n type: \"setup_complete\",\n previewPort: config.previewPort ?? undefined,\n };\n this.connection.sendEvent(setupEvent);\n await this.callbacks.onEvent(setupEvent);\n return true;\n } catch (error) {\n const message = error instanceof Error ? error.message : \"Setup failed\";\n this.connection.sendEvent({ type: \"setup_error\", message });\n await this.callbacks.onEvent({ type: \"setup_error\", message });\n this.connection.postChatMessage(\n `Environment setup failed: ${message}\\nThe agent cannot start until this is resolved.`,\n );\n return false;\n }\n }\n\n private pushSetupLog(line: string): void {\n this.setupLog.push(line);\n if (this.setupLog.length > AgentRunner.MAX_SETUP_LOG_LINES) {\n this.setupLog.splice(0, this.setupLog.length - AgentRunner.MAX_SETUP_LOG_LINES);\n }\n }\n\n private async executeSetupConfig(config: ConveyorConfig): Promise<void> {\n if (config.setupCommand) {\n this.pushSetupLog(`$ ${config.setupCommand}`);\n await runSetupCommand(config.setupCommand, this.config.workspaceDir, (stream, data) => {\n this.connection.sendEvent({ type: \"setup_output\", stream, data });\n for (const line of data.split(\"\\n\").filter(Boolean)) {\n this.pushSetupLog(`[${stream}] ${line}`);\n }\n });\n this.pushSetupLog(\"(exit 0)\");\n }\n\n if (config.startCommand) {\n this.pushSetupLog(`$ ${config.startCommand} & (background)`);\n runStartCommand(config.startCommand, this.config.workspaceDir, (stream, data) => {\n this.connection.sendEvent({ type: \"start_command_output\", stream, data });\n });\n }\n }\n\n private initRtk(): void {\n try {\n execSync(\"rtk --version\", { stdio: \"ignore\" });\n execSync(\"rtk init --global --auto-patch\", { stdio: \"ignore\" });\n } catch {\n // RTK not installed — skip silently\n }\n }\n\n private injectHumanMessage(\n content: string,\n files?: {\n id: string;\n fileName: string;\n mimeType: string;\n downloadUrl: string;\n content?: string;\n contentEncoding?: \"base64\" | \"utf-8\";\n }[],\n ): void {\n type ImageMediaType = \"image/gif\" | \"image/jpeg\" | \"image/png\" | \"image/webp\";\n type TextBlock = { type: \"text\"; text: string };\n type ImageBlock = {\n type: \"image\";\n source: { type: \"base64\"; media_type: ImageMediaType; data: string };\n };\n type ContentBlock = TextBlock | ImageBlock;\n\n let messageContent: string | ContentBlock[];\n if (files?.length) {\n const blocks: ContentBlock[] = [{ type: \"text\", text: content }];\n for (const f of files) {\n if (f.content && f.contentEncoding === \"base64\") {\n // Embed image directly as a visual content block\n blocks.push({\n type: \"image\",\n source: { type: \"base64\", media_type: f.mimeType as ImageMediaType, data: f.content },\n });\n blocks.push({\n type: \"text\",\n text: `[Attached image: ${f.fileName} (${f.mimeType})]`,\n });\n } else if (f.content && f.contentEncoding === \"utf-8\") {\n // Embed text content inline\n blocks.push({\n type: \"text\",\n text: `[Attached file: ${f.fileName} (${f.mimeType})]\\n\\`\\`\\`\\n${f.content}\\n\\`\\`\\``,\n });\n } else {\n // Fallback to download URL\n blocks.push({\n type: \"text\",\n text: `[Attached file: ${f.fileName} (${f.mimeType})] Download: ${f.downloadUrl}`,\n });\n }\n }\n messageContent = blocks;\n } else {\n messageContent = content;\n }\n\n const msg: SDKUserMessage = {\n type: \"user\" as const,\n session_id: \"\",\n message: { role: \"user\" as const, content: messageContent },\n parent_tool_use_id: null,\n };\n\n if (this.inputResolver) {\n const resolve = this.inputResolver;\n this.inputResolver = null;\n resolve(msg);\n } else {\n this.pendingMessages.push(msg);\n }\n }\n\n private waitForMessage(): Promise<SDKUserMessage | null> {\n return new Promise<SDKUserMessage | null>((resolve) => {\n const checkStopped = setInterval(() => {\n if (this.stopped) {\n clearInterval(checkStopped);\n this.inputResolver = null;\n resolve(null);\n }\n }, 1000);\n\n this.inputResolver = (msg: SDKUserMessage) => {\n clearInterval(checkStopped);\n resolve(msg);\n };\n });\n }\n\n private async waitForUserContent(): Promise<string | null> {\n if (this.pendingMessages.length > 0) {\n const next = this.pendingMessages.shift();\n return (next?.message as { content: string })?.content ?? null;\n }\n const msg = await this.waitForMessage();\n if (!msg) return null;\n return (msg.message as { content: string }).content;\n }\n\n async *createInputStream(initialPrompt: string): AsyncGenerator<SDKUserMessage, void, unknown> {\n const makeUserMessage = (content: string): SDKUserMessage => ({\n type: \"user\" as const,\n session_id: \"\",\n message: { role: \"user\" as const, content },\n parent_tool_use_id: null,\n });\n\n yield makeUserMessage(initialPrompt);\n\n while (!this.stopped) {\n if (this.pendingMessages.length > 0) {\n const next = this.pendingMessages.shift();\n if (next) yield next;\n continue;\n }\n\n this.connection.emitStatus(\"waiting_for_input\");\n await this.callbacks.onStatusChange(\"waiting_for_input\");\n const msg = await this.waitForMessage();\n\n if (!msg) break;\n this.connection.emitStatus(\"running\");\n await this.callbacks.onStatusChange(\"running\");\n yield msg;\n }\n }\n\n private getPlanDirs(): string[] {\n return [\n join(homedir(), \".claude\", \"plans\"),\n join(this.config.workspaceDir, \".claude\", \"plans\"),\n ];\n }\n\n /**\n * Snapshot current plan files so syncPlanFile can distinguish files created\n * by THIS session from ones created by a concurrent agent.\n */\n snapshotPlanFiles(): void {\n this.planFileSnapshot.clear();\n this.lockedPlanFile = null;\n for (const plansDir of this.getPlanDirs()) {\n try {\n for (const file of readdirSync(plansDir).filter((f) => f.endsWith(\".md\"))) {\n try {\n const fullPath = join(plansDir, file);\n const stat = statSync(fullPath);\n this.planFileSnapshot.set(fullPath, stat.mtimeMs);\n } catch {\n continue;\n }\n }\n } catch {\n /* plans dir doesn't exist yet */\n }\n }\n }\n\n syncPlanFile(): void {\n if (this.lockedPlanFile) {\n try {\n const content = readFileSync(this.lockedPlanFile, \"utf-8\").trim();\n if (content) {\n this.connection.updateTaskFields({ plan: content });\n const fileName = this.lockedPlanFile.split(\"/\").pop()!;\n this.connection.postChatMessage(`Synced local plan file (${fileName}) to the task plan.`);\n }\n } catch {\n /* locked file was deleted */\n }\n return;\n }\n\n let newest: { path: string; mtime: number } | null = null;\n for (const plansDir of this.getPlanDirs()) {\n let files: string[];\n try {\n files = readdirSync(plansDir).filter((f) => f.endsWith(\".md\"));\n } catch {\n continue;\n }\n\n for (const file of files) {\n const fullPath = join(plansDir, file);\n try {\n const stat = statSync(fullPath);\n const prevMtime = this.planFileSnapshot.get(fullPath);\n const isNew = prevMtime === undefined || stat.mtimeMs > prevMtime;\n if (isNew && (!newest || stat.mtimeMs > newest.mtime)) {\n newest = { path: fullPath, mtime: stat.mtimeMs };\n }\n } catch {\n continue;\n }\n }\n }\n\n if (newest) {\n this.lockedPlanFile = newest.path;\n const content = readFileSync(newest.path, \"utf-8\").trim();\n if (content) {\n this.connection.updateTaskFields({ plan: content });\n const fileName = newest.path.split(\"/\").pop()!;\n this.connection.postChatMessage(\n `Detected local plan file (${fileName}) and synced it to the task plan.`,\n );\n }\n }\n }\n\n private asQueryHost(): QueryHost {\n return {\n config: this.config,\n connection: this.connection,\n callbacks: this.callbacks,\n setupLog: this.setupLog,\n isStopped: () => this.stopped,\n createInputStream: (prompt: string) => this.createInputStream(prompt),\n snapshotPlanFiles: () => this.snapshotPlanFiles(),\n syncPlanFile: () => this.syncPlanFile(),\n };\n }\n\n stop(): void {\n this.stopped = true;\n if (this.inputResolver) {\n this.inputResolver(null as unknown as SDKUserMessage);\n this.inputResolver = null;\n }\n }\n}\n","import { randomUUID } from \"node:crypto\";\nimport { query, type SDKMessage, type SDKUserMessage } from \"@anthropic-ai/claude-agent-sdk\";\nimport type { ConveyorConnection } from \"./connection.js\";\nimport type {\n AgentRunnerConfig,\n AgentRunnerCallbacks,\n TaskContext,\n ActivityEventSummary,\n} from \"./types.js\";\nimport { buildInitialPrompt, buildSystemPrompt } from \"./prompt-builder.js\";\nimport { createConveyorMcpServer } from \"./mcp-tools.js\";\n\nconst API_ERROR_PATTERN = /API Error: [45]\\d\\d/;\nconst RETRY_DELAYS_MS = [60_000, 120_000, 180_000, 300_000];\nconst PM_PLAN_FILE_TOOLS = new Set([\"Write\", \"Edit\", \"MultiEdit\"]);\n\nexport interface QueryHost {\n config: AgentRunnerConfig;\n connection: ConveyorConnection;\n callbacks: AgentRunnerCallbacks;\n setupLog: string[];\n isStopped(): boolean;\n createInputStream(prompt: string): AsyncGenerator<SDKUserMessage, void, unknown>;\n snapshotPlanFiles(): void;\n syncPlanFile(): void;\n}\n\nasync function processAssistantEvent(\n event: SDKMessage,\n host: QueryHost,\n turnToolCalls: ActivityEventSummary[],\n): Promise<void> {\n const msg = (event as unknown as Record<string, unknown>).message as Record<string, unknown>;\n const content = msg.content as Record<string, unknown>[];\n const turnTextParts: string[] = [];\n\n for (const block of content) {\n const blockType = block.type as string;\n if (blockType === \"text\") {\n const text = block.text as string;\n turnTextParts.push(text);\n host.connection.sendEvent({ type: \"message\", content: text });\n await host.callbacks.onEvent({ type: \"message\", content: text });\n } else if (blockType === \"tool_use\") {\n const name = block.name as string;\n const inputStr = typeof block.input === \"string\" ? block.input : JSON.stringify(block.input);\n const isContentTool = [\"edit\", \"write\"].includes(name.toLowerCase());\n const inputLimit = isContentTool ? 10_000 : 500;\n const summary: ActivityEventSummary = {\n tool: name,\n input: inputStr.slice(0, inputLimit),\n timestamp: new Date().toISOString(),\n };\n turnToolCalls.push(summary);\n host.connection.sendEvent({ type: \"tool_use\", tool: name, input: inputStr });\n await host.callbacks.onEvent({ type: \"tool_use\", tool: name, input: inputStr });\n }\n }\n\n if (turnTextParts.length > 0) {\n host.connection.postChatMessage(turnTextParts.join(\"\\n\\n\"));\n }\n\n if (turnToolCalls.length > 0) {\n host.connection.sendEvent({ type: \"turn_end\", toolCalls: [...turnToolCalls] });\n turnToolCalls.length = 0;\n }\n}\n\nfunction handleResultEvent(\n event: SDKMessage,\n host: QueryHost,\n context: TaskContext,\n startTime: number,\n): { totalCostUsd: number; deltaCost: number; retriable: boolean } {\n const resultEvent = event as SDKMessage & { type: \"result\"; subtype: string };\n let totalCostUsd = 0;\n let deltaCost = 0;\n let retriable = false;\n\n if (resultEvent.subtype === \"success\") {\n totalCostUsd =\n \"total_cost_usd\" in resultEvent\n ? ((resultEvent as Record<string, unknown>).total_cost_usd as number)\n : 0;\n const durationMs = Date.now() - startTime;\n const summary =\n \"result\" in resultEvent\n ? String((resultEvent as Record<string, unknown>).result)\n : \"Task completed.\";\n\n if (API_ERROR_PATTERN.test(summary) && durationMs < 30_000) {\n retriable = true;\n }\n\n const lastCost = context._lastReportedCostUsd ?? 0;\n deltaCost = totalCostUsd - lastCost;\n context._lastReportedCostUsd = totalCostUsd;\n\n host.connection.sendEvent({ type: \"completed\", summary, costUsd: deltaCost, durationMs });\n\n if (deltaCost > 0 && context.agentId) {\n const estimatedDeltaTokens = Math.round(deltaCost * 100000);\n host.connection.trackSpending({\n agentId: context.agentId,\n inputTokens: Math.round(estimatedDeltaTokens * 0.7),\n outputTokens: Math.round(estimatedDeltaTokens * 0.3),\n totalTokens: estimatedDeltaTokens,\n totalCostUsd: deltaCost,\n onSubscription: host.config.mode === \"pm\" || !!process.env.CLAUDE_CODE_OAUTH_TOKEN,\n });\n }\n } else {\n const errors =\n \"errors\" in resultEvent ? ((resultEvent as Record<string, unknown>).errors as string[]) : [];\n const errorMsg =\n errors.length > 0 ? errors.join(\", \") : `Agent stopped: ${resultEvent.subtype}`;\n\n if (API_ERROR_PATTERN.test(errorMsg)) {\n retriable = true;\n }\n\n host.connection.sendEvent({ type: \"error\", message: errorMsg });\n }\n\n return { totalCostUsd, deltaCost, retriable };\n}\n\nasync function emitResultEvent(\n event: SDKMessage,\n host: QueryHost,\n context: TaskContext,\n startTime: number,\n): Promise<boolean> {\n const result = handleResultEvent(event, host, context, startTime);\n const durationMs = Date.now() - startTime;\n\n if (result.deltaCost > 0 && context.agentId) {\n await host.callbacks.onEvent({\n type: \"completed\",\n summary: \"Task completed.\",\n costUsd: result.deltaCost,\n durationMs,\n });\n } else {\n const resultEvent = event as SDKMessage & { subtype: string };\n if (resultEvent.subtype === \"success\") {\n const summary =\n \"result\" in resultEvent\n ? String((resultEvent as Record<string, unknown>).result)\n : \"Task completed.\";\n await host.callbacks.onEvent({\n type: \"completed\",\n summary,\n costUsd: 0,\n durationMs,\n });\n } else {\n const errors =\n \"errors\" in resultEvent\n ? ((resultEvent as Record<string, unknown>).errors as string[])\n : [];\n const errorMsg =\n errors.length > 0 ? errors.join(\", \") : `Agent stopped: ${resultEvent.subtype}`;\n await host.callbacks.onEvent({ type: \"error\", message: errorMsg });\n }\n }\n\n return result.retriable;\n}\n\nexport async function processEvents(\n events: AsyncGenerator<SDKMessage, void>,\n context: TaskContext,\n host: QueryHost,\n): Promise<{ retriable: boolean }> {\n const startTime = Date.now();\n let sessionIdStored = false;\n let isTyping = false;\n let retriable = false;\n const turnToolCalls: ActivityEventSummary[] = [];\n\n for await (const event of events) {\n if (host.isStopped()) break;\n\n switch (event.type) {\n case \"system\": {\n if (event.subtype === \"init\") {\n const sessionId = (event as unknown as Record<string, unknown>).session_id as\n | string\n | undefined;\n if (sessionId && !sessionIdStored) {\n sessionIdStored = true;\n host.connection.storeSessionId(sessionId);\n // Reset cost tracking when starting a new (different) session\n if (sessionId !== context.claudeSessionId) {\n context._lastReportedCostUsd = 0;\n }\n }\n await host.callbacks.onEvent({\n type: \"thinking\",\n message: `Agent initialized (model: ${event.model})`,\n });\n }\n break;\n }\n\n case \"assistant\": {\n if (!isTyping) {\n setTimeout(() => host.connection.sendTypingStart(), 200);\n isTyping = true;\n }\n await processAssistantEvent(event, host, turnToolCalls);\n break;\n }\n\n case \"result\": {\n if (isTyping) {\n host.connection.sendTypingStop();\n isTyping = false;\n }\n retriable = await emitResultEvent(event, host, context, startTime);\n break;\n }\n }\n }\n\n if (isTyping) {\n host.connection.sendTypingStop();\n }\n\n return { retriable };\n}\n\nfunction buildCanUseTool(\n host: QueryHost,\n): (\n toolName: string,\n input: Record<string, unknown>,\n) => Promise<\n | { behavior: \"allow\"; updatedInput?: Record<string, unknown> }\n | { behavior: \"deny\"; message: string }\n> {\n const QUESTION_TIMEOUT_MS = 5 * 60 * 1000;\n\n return async (toolName, input) => {\n if (host.config.mode === \"pm\" && PM_PLAN_FILE_TOOLS.has(toolName)) {\n const filePath = String(input.file_path ?? input.path ?? \"\");\n if (filePath.includes(\".claude/plans/\")) {\n return { behavior: \"allow\", updatedInput: input };\n }\n return {\n behavior: \"deny\",\n message: \"File write tools are only available for plan files in PM mode.\",\n };\n }\n\n if (toolName !== \"AskUserQuestion\") {\n return { behavior: \"allow\", updatedInput: input };\n }\n\n const questions = input.questions as {\n question: string;\n header: string;\n options: { label: string; description: string; preview?: string }[];\n multiSelect?: boolean;\n }[];\n\n const requestId = randomUUID();\n host.connection.emitStatus(\"waiting_for_input\");\n host.connection.sendEvent({\n type: \"tool_use\",\n tool: \"AskUserQuestion\",\n input: JSON.stringify(input),\n });\n\n const answerPromise = host.connection.askUserQuestion(requestId, questions);\n const timeoutPromise = new Promise<null>((resolve) => {\n setTimeout(() => resolve(null), QUESTION_TIMEOUT_MS);\n });\n\n const answers = await Promise.race([answerPromise, timeoutPromise]);\n host.connection.emitStatus(\"running\");\n\n if (!answers) {\n return {\n behavior: \"deny\",\n message:\n \"User did not respond to clarifying questions in time. Proceed with your best judgment.\",\n };\n }\n\n return { behavior: \"allow\", updatedInput: { questions: input.questions, answers } };\n };\n}\n\nfunction buildQueryOptions(host: QueryHost, context: TaskContext): Record<string, unknown> {\n const settings = context.agentSettings ?? host.config.agentSettings ?? {};\n const systemPromptText = buildSystemPrompt(host.config.mode, context, host.config, host.setupLog);\n const conveyorMcp = createConveyorMcpServer(host.connection, host.config);\n const isPm = host.config.mode === \"pm\";\n const pmDisallowedTools = isPm ? [\"TodoWrite\", \"TodoRead\", \"NotebookEdit\"] : [];\n const disallowedTools = [...(settings.disallowedTools ?? []), ...pmDisallowedTools];\n const settingSources = (settings.settingSources ?? [\"user\", \"project\"]) as (\n | \"user\"\n | \"project\"\n | \"local\"\n )[];\n\n return {\n model: context.model || host.config.model,\n systemPrompt: {\n type: \"preset\",\n preset: \"claude_code\",\n append: systemPromptText || undefined,\n },\n settingSources,\n cwd: host.config.workspaceDir,\n permissionMode: \"bypassPermissions\",\n allowDangerouslySkipPermissions: true,\n canUseTool: buildCanUseTool(host),\n tools: { type: \"preset\" as const, preset: \"claude_code\" as const },\n mcpServers: { conveyor: conveyorMcp },\n maxTurns: settings.maxTurns,\n effort: settings.effort,\n thinking: settings.thinking,\n betas: settings.betas,\n maxBudgetUsd: settings.maxBudgetUsd ?? 50,\n disallowedTools: disallowedTools.length > 0 ? disallowedTools : undefined,\n enableFileCheckpointing: settings.enableFileCheckpointing,\n };\n}\n\nexport async function runSdkQuery(\n host: QueryHost,\n context: TaskContext,\n followUpContent?: string,\n): Promise<void> {\n if (host.isStopped()) return;\n\n const isPm = host.config.mode === \"pm\";\n if (isPm) {\n host.snapshotPlanFiles();\n }\n\n const options = buildQueryOptions(host, context);\n const resume = context.claudeSessionId ?? undefined;\n\n if (followUpContent) {\n const prompt = isPm\n ? `${buildInitialPrompt(host.config.mode, context)}\\n\\n---\\n\\nThe team says:\\n${followUpContent}`\n : followUpContent;\n\n const agentQuery = query({ prompt, options: { ...options, resume } });\n await runWithRetry(agentQuery, context, host, options);\n } else if (isPm) {\n return;\n } else {\n const initialPrompt = buildInitialPrompt(host.config.mode, context);\n const agentQuery = query({\n prompt: host.createInputStream(initialPrompt),\n options: { ...options, resume },\n });\n await runWithRetry(agentQuery, context, host, options);\n }\n\n if (isPm) {\n host.syncPlanFile();\n }\n}\n\nasync function runWithRetry(\n initialQuery: AsyncGenerator<SDKMessage, void>,\n context: TaskContext,\n host: QueryHost,\n options: Record<string, unknown>,\n): Promise<void> {\n for (let attempt = 0; attempt <= RETRY_DELAYS_MS.length; attempt++) {\n if (host.isStopped()) return;\n\n const agentQuery =\n attempt === 0\n ? initialQuery\n : (() => {\n // New session starts cost from 0 — reset so deltas stay correct (Bug 2)\n context._lastReportedCostUsd = 0;\n return query({\n prompt: host.createInputStream(buildInitialPrompt(host.config.mode, context)),\n options: { ...options, resume: undefined },\n });\n })();\n\n try {\n const { retriable } = await processEvents(agentQuery, context, host);\n if (!retriable || host.isStopped()) return;\n } catch (error) {\n const isStaleSession =\n error instanceof Error && error.message.includes(\"No conversation found with session ID\");\n\n if (isStaleSession && context.claudeSessionId) {\n // Mutate the original context so state changes propagate back to runner.taskContext\n context.claudeSessionId = null;\n context._lastReportedCostUsd = 0;\n host.connection.storeSessionId(\"\");\n const freshQuery = query({\n prompt: host.createInputStream(buildInitialPrompt(host.config.mode, context)),\n options: { ...options, resume: undefined },\n });\n return runWithRetry(freshQuery, context, host, options);\n }\n\n const isApiError = error instanceof Error && API_ERROR_PATTERN.test(error.message);\n if (!isApiError) throw error;\n }\n\n if (attempt >= RETRY_DELAYS_MS.length) {\n host.connection.postChatMessage(\n `Agent shutting down after ${RETRY_DELAYS_MS.length} failed retry attempts due to API errors. ` +\n `The task will resume automatically when the codespace restarts.`,\n );\n return;\n }\n\n const delayMs = RETRY_DELAYS_MS[attempt];\n const delayMin = Math.round(delayMs / 60_000);\n host.connection.postChatMessage(\n `API error encountered. Retrying in ${delayMin} minute${delayMin > 1 ? \"s\" : \"\"}... (attempt ${attempt + 1}/${RETRY_DELAYS_MS.length})`,\n );\n host.connection.sendEvent({\n type: \"error\",\n message: `API error, retrying in ${delayMin}m (${attempt + 1}/${RETRY_DELAYS_MS.length})`,\n });\n host.connection.emitStatus(\"waiting_for_input\");\n await host.callbacks.onStatusChange(\"waiting_for_input\");\n\n await new Promise<void>((resolve) => {\n const timer = setTimeout(resolve, delayMs);\n const checkStopped = setInterval(() => {\n if (host.isStopped()) {\n clearTimeout(timer);\n clearInterval(checkStopped);\n resolve();\n }\n }, 1000);\n setTimeout(() => clearInterval(checkStopped), delayMs + 100);\n });\n\n host.connection.emitStatus(\"running\");\n await host.callbacks.onStatusChange(\"running\");\n }\n}\n","import type { RunnerMode, TaskContext, ChatMessage } from \"./types.js\";\n\nconst ACTIVE_STATUSES = new Set([\"InProgress\", \"ReviewPR\", \"ReviewDev\", \"ReviewLive\"]);\n\nfunction findLastAgentMessageIndex(history: ChatMessage[]): number {\n for (let i = history.length - 1; i >= 0; i--) {\n if (history[i].role === \"assistant\") return i;\n }\n return -1;\n}\n\nfunction detectRelaunchScenario(\n context: TaskContext,\n): \"fresh\" | \"idle_relaunch\" | \"feedback_relaunch\" {\n const lastAgentIdx = findLastAgentMessageIndex(context.chatHistory);\n if (lastAgentIdx === -1) return \"fresh\";\n\n const hasPriorWork =\n !!context.githubPRUrl || !!context.claudeSessionId || ACTIVE_STATUSES.has(context.status ?? \"\");\n if (!hasPriorWork) return \"fresh\";\n\n const messagesAfterAgent = context.chatHistory.slice(lastAgentIdx + 1);\n const hasNewUserMessages = messagesAfterAgent.some((m) => m.role === \"user\");\n return hasNewUserMessages ? \"feedback_relaunch\" : \"idle_relaunch\";\n}\n\nfunction buildRelaunchWithSession(\n mode: RunnerMode | undefined,\n context: TaskContext,\n): string | null {\n const scenario = detectRelaunchScenario(context);\n if (!context.claudeSessionId || scenario === \"fresh\") return null;\n\n const parts: string[] = [];\n const lastAgentIdx = findLastAgentMessageIndex(context.chatHistory);\n\n if (mode === \"pm\") {\n const newMessages = context.chatHistory\n .slice(lastAgentIdx + 1)\n .filter((m) => m.role === \"user\");\n if (newMessages.length > 0) {\n parts.push(\n `You have been relaunched. Here are new messages since your last session:`,\n ...newMessages.map((m) => `[${m.userName ?? \"user\"}]: ${m.content}`),\n );\n } else {\n parts.push(`You have been relaunched. No new messages since your last session.`);\n }\n parts.push(\n `\\nYou are the project manager for this task.`,\n `Review the context above and wait for the team to provide instructions before taking action.`,\n );\n } else if (scenario === \"feedback_relaunch\") {\n const newMessages = context.chatHistory\n .slice(lastAgentIdx + 1)\n .filter((m) => m.role === \"user\");\n parts.push(\n `You have been relaunched with new feedback.`,\n `Work on the git branch \"${context.githubBranch}\". Stay on this branch — do not checkout or create other branches.`,\n `\\nNew messages since your last run:`,\n ...newMessages.map((m) => `[${m.userName ?? \"user\"}]: ${m.content}`),\n `\\nAddress the requested changes. Do NOT re-investigate the codebase from scratch or write a new plan — review the feedback and implement the changes directly.`,\n `Commit and push your updates.`,\n );\n if (context.githubPRUrl) {\n parts.push(\n `An existing PR is open at ${context.githubPRUrl} — push to the same branch. Do NOT create a new PR.`,\n );\n } else {\n parts.push(\n `When finished, use the create_pull_request tool to open a PR. Do NOT use gh CLI.`,\n );\n }\n } else {\n parts.push(\n `You were relaunched but no new instructions have been given since your last run.`,\n `Work on the git branch \"${context.githubBranch}\". Stay on this branch — do not checkout or create other branches.`,\n `Run \\`git log --oneline -10\\` to review what you already committed.`,\n `Review the current state of the codebase and verify everything is working correctly.`,\n `Post a brief status update to the chat, then wait for further instructions.`,\n );\n if (context.githubPRUrl) {\n parts.push(`An existing PR is open at ${context.githubPRUrl}. Do not create a new PR.`);\n }\n }\n\n return parts.join(\"\\n\");\n}\n\nfunction buildTaskBody(context: TaskContext): string[] {\n const parts: string[] = [];\n parts.push(`# Task: ${context.title}`);\n if (context.description) {\n parts.push(`\\n## Description\\n${context.description}`);\n }\n if (context.plan) {\n parts.push(`\\n## Plan\\n${context.plan}`);\n }\n\n if (context.files && context.files.length > 0) {\n parts.push(`\\n## Attached Files`);\n for (const file of context.files) {\n if (file.content && file.contentEncoding === \"utf-8\") {\n // Inline text content directly\n parts.push(`\\n### ${file.fileName} (${file.mimeType})`);\n parts.push(\"```\");\n parts.push(file.content);\n parts.push(\"```\");\n } else if (!file.content) {\n // Fallback to download URL for large/non-embeddable files\n parts.push(`- **${file.fileName}** (${file.mimeType}): ${file.downloadUrl}`);\n }\n // Base64 images are handled via multimodal content blocks in the runner\n }\n }\n\n if (context.repoRefs && context.repoRefs.length > 0) {\n parts.push(`\\n## Repository References`);\n for (const ref of context.repoRefs) {\n const icon = ref.refType === \"folder\" ? \"folder\" : \"file\";\n parts.push(`- [${icon}] \\`${ref.path}\\``);\n }\n }\n\n if (context.chatHistory.length > 0) {\n const relevant = context.chatHistory.slice(-20);\n parts.push(`\\n## Recent Chat Context`);\n for (const msg of relevant) {\n const sender = msg.userName ?? msg.role;\n parts.push(`[${sender}]: ${msg.content}`);\n }\n }\n\n return parts;\n}\n\nfunction buildInstructions(\n mode: RunnerMode | undefined,\n context: TaskContext,\n scenario: \"fresh\" | \"idle_relaunch\" | \"feedback_relaunch\",\n): string[] {\n const parts: string[] = [`\\n## Instructions`];\n const isPm = mode === \"pm\";\n\n if (scenario === \"fresh\") {\n if (isPm) {\n parts.push(\n `You are the project manager for this task.`,\n `The task details are provided above. Wait for the team to ask questions or provide additional requirements before starting to plan.`,\n `When you finish planning, save the plan with update_task, post a summary to chat, and end your turn. A separate task agent will execute the plan after review.`,\n );\n } else {\n parts.push(\n `Begin executing the task plan above immediately.`,\n `Your FIRST action should be reading the relevant source files mentioned in the plan, then writing code. Do NOT run install, build, lint, test, or dev server commands first — the environment is already set up.`,\n `Work on the git branch \"${context.githubBranch}\". Stay on this branch for the entire task. Do not checkout or create other branches.`,\n `Post a brief message to chat when you begin meaningful implementation, and again when the PR is ready.`,\n `When finished, commit your changes, push the branch, and use the create_pull_request tool to open a PR. Do NOT use gh CLI or any other method to create PRs.`,\n );\n }\n } else if (scenario === \"idle_relaunch\") {\n if (isPm) {\n parts.push(\n `You were relaunched but no new instructions have been given since your last run.`,\n `You are the project manager for this task.`,\n `Wait for the team to provide instructions before taking action.`,\n );\n } else {\n parts.push(\n `You were relaunched but no new instructions have been given since your last run.`,\n `Work on the git branch \"${context.githubBranch}\". Stay on this branch — do not checkout or create other branches.`,\n `Run \\`git log --oneline -10\\` to review what you already committed, then verify the current state is correct.`,\n `Post a brief status update to the chat summarizing where things stand.`,\n `Then wait for further instructions — do NOT redo work that was already completed.`,\n );\n if (context.githubPRUrl) {\n parts.push(`An existing PR is open at ${context.githubPRUrl}. Do not create a new PR.`);\n }\n }\n } else {\n const lastAgentIdx = findLastAgentMessageIndex(context.chatHistory);\n const newMessages = context.chatHistory\n .slice(lastAgentIdx + 1)\n .filter((m) => m.role === \"user\");\n if (isPm) {\n parts.push(\n `You were relaunched with new feedback since your last run.`,\n `You are the project manager for this task.`,\n `\\nNew messages since your last run:`,\n ...newMessages.map((m) => `[${m.userName ?? \"user\"}]: ${m.content}`),\n `\\nReview these messages and wait for the team to provide instructions before taking action.`,\n );\n } else {\n parts.push(\n `You have been relaunched to address feedback on your previous work.`,\n `Work on the git branch \"${context.githubBranch}\". Stay on this branch — do not checkout or create other branches.`,\n `Start by running \\`git log --oneline -10\\` and \\`git diff HEAD~3 HEAD --stat\\` to review what you already committed.`,\n `\\nNew messages since your last run:`,\n ...newMessages.map((m) => `[${m.userName ?? \"user\"}]: ${m.content}`),\n `\\nAddress the requested changes directly. Do NOT re-investigate the codebase from scratch or write a new plan — go straight to implementing the feedback.`,\n `Commit and push your updates.`,\n );\n if (context.githubPRUrl) {\n parts.push(\n `An existing PR is open at ${context.githubPRUrl} — push to the same branch to update it. Do NOT create a new PR.`,\n );\n } else {\n parts.push(\n `When finished, use the create_pull_request tool to open a PR. Do NOT use gh CLI or any other method to create PRs.`,\n );\n }\n }\n }\n\n return parts;\n}\n\nexport function buildInitialPrompt(mode: RunnerMode | undefined, context: TaskContext): string {\n const sessionRelaunch = buildRelaunchWithSession(mode, context);\n if (sessionRelaunch) return sessionRelaunch;\n\n const scenario = detectRelaunchScenario(context);\n const body = buildTaskBody(context);\n const instructions = buildInstructions(mode, context, scenario);\n return [...body, ...instructions].join(\"\\n\");\n}\n\nexport function buildSystemPrompt(\n mode: RunnerMode | undefined,\n context: TaskContext,\n config: { instructions: string; workspaceDir: string },\n setupLog: string[],\n): string {\n const isPm = mode === \"pm\";\n const parts = isPm\n ? [\n `You are an AI project manager helping to plan tasks for the \"${context.title}\" project.`,\n `You are running locally with full access to the repository.`,\n `You can read files, search code, and run shell commands (e.g. git log, git diff) to understand the codebase. You cannot write or edit files.`,\n `\\nEnvironment (ready, no setup required):`,\n `- Repository is cloned at your current working directory.`,\n `- You can read files and run git commands to understand the codebase before writing task plans.`,\n `- Check the dev branch (e.g. run: git fetch && git checkout dev || git checkout main) to understand the current state of the codebase that agents will branch off of.`,\n `\\nWorkflow:`,\n `- You can draft and iterate on plans in .claude/plans/*.md — these files are automatically synced to the task.`,\n `- You can also use update_task directly to save the plan to the task.`,\n `- After saving the plan, post a summary to chat and end your turn. Do NOT attempt to execute the plan yourself.`,\n `- A separate task agent will handle execution after the team reviews and approves your plan.`,\n ]\n : [\n `You are an AI agent working on a task for the \"${context.title}\" project.`,\n `You are running inside a GitHub Codespace with full access to the repository.`,\n `\\nEnvironment (fully ready — do NOT verify or set up):`,\n `- Repository is cloned at your current working directory.`,\n `- Branch \\`${context.githubBranch}\\` is already checked out.`,\n `- All dependencies are installed, database is migrated, and the dev server is running.`,\n `- Git is configured. Commit and push directly to this branch.`,\n `\\nIMPORTANT — Skip all environment verification. Do NOT run any of the following:`,\n `- bun/npm install, pip install, or any dependency installation`,\n `- bun build, bun lint, bun test, bun typecheck, or any build/check commands as a \"first step\"`,\n `- bun db:generate, bun db:push, prisma migrate, or any database setup`,\n `- bun dev, npm start, or any dev server startup commands`,\n `- pwd, ls, echo, or exploratory shell commands to \"check\" the environment`,\n `Only run these if you encounter a specific error that requires it.`,\n `Start reading the task plan and writing code immediately.`,\n `\\nGit safety — STRICT rules:`,\n `- NEVER run \\`git checkout main\\`, \\`git checkout dev\\`, or switch to any branch other than \\`${context.githubBranch}\\`.`,\n `- NEVER create new branches (no \\`git checkout -b\\`, \\`git switch -c\\`, etc.).`,\n `- This branch was created from \\`${context.baseBranch}\\`. PRs will automatically target that branch.`,\n `- If \\`git push\\` fails with \"non-fast-forward\" or similar, run \\`git pull --rebase origin ${context.githubBranch}\\` and retry. If that also fails, use \\`git push --force-with-lease origin ${context.githubBranch}\\`.`,\n `- If you encounter merge conflicts during rebase, resolve them in place — do NOT abandon the branch.`,\n ];\n\n if (setupLog.length > 0) {\n parts.push(\n `\\nEnvironment setup log (already executed before you started — proof that setup succeeded):`,\n \"```\",\n ...setupLog,\n \"```\",\n );\n }\n\n if (context.agentInstructions) {\n parts.push(`\\nAgent Instructions:\\n${context.agentInstructions}`);\n }\n if (config.instructions) {\n parts.push(`\\nAdditional Instructions:\\n${config.instructions}`);\n }\n parts.push(\n `\\nYou have access to Conveyor MCP tools to interact with the task management system.`,\n `Use the post_to_chat tool to communicate progress or ask questions.`,\n `Use the read_task_chat tool to check for new messages from the team.`,\n );\n if (!isPm) {\n parts.push(\n `Use the create_pull_request tool to open PRs — do NOT use gh CLI or shell commands for PR creation.`,\n );\n }\n return parts.join(\"\\n\");\n}\n","import { tool, createSdkMcpServer } from \"@anthropic-ai/claude-agent-sdk\";\nimport { z } from \"zod\";\nimport type { ConveyorConnection } from \"./connection.js\";\nimport type { AgentRunnerConfig } from \"./types.js\";\n\nfunction buildCommonTools(connection: ConveyorConnection, config: AgentRunnerConfig) {\n return [\n tool(\n \"read_task_chat\",\n \"Read recent messages from the task chat to see team feedback or instructions\",\n {\n limit: z.number().optional().describe(\"Number of recent messages to fetch (default 20)\"),\n },\n async ({ limit }) => {\n try {\n const messages = await connection.fetchChatMessages(limit);\n return textResult(JSON.stringify(messages, null, 2));\n } catch {\n return textResult(\n JSON.stringify({\n note: \"Could not fetch live chat. Chat history was provided in the initial context.\",\n }),\n );\n }\n },\n { annotations: { readOnlyHint: true } },\n ),\n tool(\n \"post_to_chat\",\n \"Post a message to the task chat visible to all team members\",\n { message: z.string().describe(\"The message to post to the team\") },\n ({ message }) => {\n connection.postChatMessage(message);\n return Promise.resolve(textResult(\"Message posted to task chat.\"));\n },\n ),\n tool(\n \"update_task_status\",\n \"Update the task status on the Kanban board\",\n {\n status: z\n .enum([\"InProgress\", \"ReviewPR\", \"Complete\"])\n .describe(\"The new status for the task\"),\n },\n ({ status }) => {\n connection.updateStatus(status);\n return Promise.resolve(textResult(`Task status updated to ${status}.`));\n },\n ),\n tool(\n \"get_task_plan\",\n \"Re-read the latest task plan in case it was updated\",\n {},\n async () => {\n try {\n const ctx = await connection.fetchTaskContext();\n return textResult(ctx.plan ?? \"No plan available.\");\n } catch {\n return textResult(`Task ID: ${config.taskId} - could not fetch updated plan.`);\n }\n },\n { annotations: { readOnlyHint: true } },\n ),\n ];\n}\n\nfunction buildPmTools(connection: ConveyorConnection) {\n return [\n tool(\n \"update_task\",\n \"Save the finalized task plan and/or description\",\n {\n plan: z.string().optional().describe(\"The task plan in markdown\"),\n description: z.string().optional().describe(\"Updated task description\"),\n },\n async ({ plan, description }) => {\n try {\n await Promise.resolve(connection.updateTaskFields({ plan, description }));\n return textResult(\"Task updated successfully.\");\n } catch {\n return textResult(\"Failed to update task.\");\n }\n },\n ),\n tool(\n \"create_subtask\",\n \"Create a subtask under the current parent task. Use for breaking complex tasks into smaller pieces.\",\n {\n title: z.string().describe(\"Subtask title\"),\n description: z.string().optional().describe(\"Brief description\"),\n plan: z.string().optional().describe(\"Implementation plan in markdown\"),\n ordinal: z.number().optional().describe(\"Step/order number (0-based)\"),\n storyPointValue: z\n .number()\n .optional()\n .describe(\"Story point value (1=Common, 2=Magic, 3=Rare, 5=Unique)\"),\n },\n async (params) => {\n try {\n const result = await connection.createSubtask(params);\n return textResult(`Subtask created with ID: ${result.id}`);\n } catch (error) {\n return textResult(\n `Failed to create subtask: ${error instanceof Error ? error.message : \"Unknown error\"}`,\n );\n }\n },\n ),\n tool(\n \"update_subtask\",\n \"Update an existing subtask's fields\",\n {\n subtaskId: z.string().describe(\"The subtask ID to update\"),\n title: z.string().optional(),\n description: z.string().optional(),\n plan: z.string().optional(),\n ordinal: z.number().optional(),\n storyPointValue: z.number().optional(),\n },\n async ({ subtaskId, ...fields }) => {\n try {\n await Promise.resolve(connection.updateSubtask(subtaskId, fields));\n return textResult(\"Subtask updated.\");\n } catch (error) {\n return textResult(`Failed: ${error instanceof Error ? error.message : \"Unknown error\"}`);\n }\n },\n ),\n tool(\n \"delete_subtask\",\n \"Delete a subtask\",\n { subtaskId: z.string().describe(\"The subtask ID to delete\") },\n async ({ subtaskId }) => {\n try {\n await Promise.resolve(connection.deleteSubtask(subtaskId));\n return textResult(\"Subtask deleted.\");\n } catch (error) {\n return textResult(`Failed: ${error instanceof Error ? error.message : \"Unknown error\"}`);\n }\n },\n ),\n tool(\n \"list_subtasks\",\n \"List all subtasks under the current parent task\",\n {},\n async () => {\n try {\n const subtasks = await connection.listSubtasks();\n return textResult(JSON.stringify(subtasks, null, 2));\n } catch {\n return textResult(\"Failed to list subtasks.\");\n }\n },\n { annotations: { readOnlyHint: true } },\n ),\n ];\n}\n\nfunction buildTaskTools(connection: ConveyorConnection) {\n return [\n tool(\n \"create_pull_request\",\n \"Create a GitHub pull request for this task. Use this instead of gh CLI or git commands to create PRs.\",\n {\n title: z.string().describe(\"The PR title\"),\n body: z.string().describe(\"The PR description/body in markdown\"),\n },\n async ({ title, body }) => {\n try {\n const result = await connection.createPR({ title, body });\n connection.sendEvent({\n type: \"pr_created\",\n url: result.url,\n number: result.number,\n });\n return textResult(`Pull request #${result.number} created: ${result.url}`);\n } catch (error) {\n const msg = error instanceof Error ? error.message : \"Unknown error\";\n return textResult(`Failed to create pull request: ${msg}`);\n }\n },\n ),\n ];\n}\n\nfunction textResult(text: string): { content: { type: \"text\"; text: string }[] } {\n return { content: [{ type: \"text\" as const, text }] };\n}\n\n// oxlint-disable-next-line typescript/explicit-function-return-type\nexport function createConveyorMcpServer(connection: ConveyorConnection, config: AgentRunnerConfig) {\n const commonTools = buildCommonTools(connection, config);\n const modeTools = config.mode === \"pm\" ? buildPmTools(connection) : buildTaskTools(connection);\n\n return createSdkMcpServer({\n name: \"conveyor\",\n tools: [...commonTools, ...modeTools],\n });\n}\n","import { io, type Socket } from \"socket.io-client\";\n\nexport interface ProjectConnectionConfig {\n apiUrl: string;\n projectToken: string;\n projectId: string;\n}\n\nexport interface TaskAssignment {\n taskId: string;\n taskToken: string;\n apiUrl: string;\n mode: string;\n branch: string;\n devBranch: string;\n}\n\nexport class ProjectConnection {\n private socket: Socket | null = null;\n private config: ProjectConnectionConfig;\n private taskAssignmentCallback: ((assignment: TaskAssignment) => void) | null = null;\n private stopTaskCallback: ((data: { taskId: string }) => void) | null = null;\n private shutdownCallback: (() => void) | null = null;\n\n constructor(config: ProjectConnectionConfig) {\n this.config = config;\n }\n\n connect(): Promise<void> {\n return new Promise((resolve, reject) => {\n let settled = false;\n let attempts = 0;\n const maxInitialAttempts = 30;\n\n this.socket = io(this.config.apiUrl, {\n auth: { projectToken: this.config.projectToken },\n transports: [\"websocket\"],\n reconnection: true,\n reconnectionAttempts: Infinity,\n reconnectionDelay: 2000,\n reconnectionDelayMax: 30000,\n randomizationFactor: 0.3,\n extraHeaders: {\n \"ngrok-skip-browser-warning\": \"true\",\n },\n });\n\n this.socket.on(\"projectRunner:assignTask\", (data: TaskAssignment) => {\n if (this.taskAssignmentCallback) {\n this.taskAssignmentCallback(data);\n }\n });\n\n this.socket.on(\"projectRunner:stopTask\", (data: { taskId: string }) => {\n if (this.stopTaskCallback) {\n this.stopTaskCallback(data);\n }\n });\n\n this.socket.on(\"projectRunner:shutdown\", () => {\n if (this.shutdownCallback) {\n this.shutdownCallback();\n }\n });\n\n this.socket.on(\"connect\", () => {\n if (!settled) {\n settled = true;\n resolve();\n }\n });\n\n this.socket.io.on(\"reconnect_attempt\", () => {\n attempts++;\n if (!settled && attempts >= maxInitialAttempts) {\n settled = true;\n reject(new Error(`Failed to connect after ${maxInitialAttempts} attempts`));\n }\n });\n });\n }\n\n onTaskAssignment(callback: (assignment: TaskAssignment) => void): void {\n this.taskAssignmentCallback = callback;\n }\n\n onStopTask(callback: (data: { taskId: string }) => void): void {\n this.stopTaskCallback = callback;\n }\n\n onShutdown(callback: () => void): void {\n this.shutdownCallback = callback;\n }\n\n sendHeartbeat(): void {\n if (!this.socket) return;\n this.socket.emit(\"projectRunner:heartbeat\", {});\n }\n\n emitTaskStarted(taskId: string): void {\n if (!this.socket) return;\n this.socket.emit(\"projectRunner:taskStarted\", { taskId });\n }\n\n emitTaskStopped(taskId: string, reason: string): void {\n if (!this.socket) return;\n this.socket.emit(\"projectRunner:taskStopped\", { taskId, reason });\n }\n\n disconnect(): void {\n this.socket?.disconnect();\n this.socket = null;\n }\n}\n","/* oxlint-disable no-console */\n\nimport { fork, type ChildProcess } from \"node:child_process\";\nimport { execSync } from \"node:child_process\";\nimport * as path from \"node:path\";\nimport { fileURLToPath } from \"node:url\";\nimport { ProjectConnection, type TaskAssignment } from \"./project-connection.js\";\nimport { ensureWorktree, removeWorktree } from \"./worktree.js\";\n\nconst __filename = fileURLToPath(import.meta.url);\nconst __dirname = path.dirname(__filename);\n\nexport interface ProjectRunnerConfig {\n conveyorApiUrl: string;\n projectToken: string;\n projectId: string;\n projectDir: string;\n}\n\ninterface ActiveAgent {\n process: ChildProcess;\n worktreePath: string;\n mode: string;\n}\n\nconst HEARTBEAT_INTERVAL_MS = 30_000;\nconst MAX_CONCURRENT = 3;\nconst STOP_TIMEOUT_MS = 30_000;\n\nexport class ProjectRunner {\n private connection: ProjectConnection;\n private projectDir: string;\n private activeAgents = new Map<string, ActiveAgent>();\n private heartbeatTimer: ReturnType<typeof setInterval> | null = null;\n private stopping = false;\n private resolveLifecycle: (() => void) | null = null;\n\n constructor(config: ProjectRunnerConfig) {\n this.projectDir = config.projectDir;\n this.connection = new ProjectConnection({\n apiUrl: config.conveyorApiUrl,\n projectToken: config.projectToken,\n projectId: config.projectId,\n });\n }\n\n async start(): Promise<void> {\n await this.connection.connect();\n\n this.connection.onTaskAssignment((assignment) => {\n void this.handleAssignment(assignment);\n });\n\n this.connection.onStopTask((data) => {\n this.handleStopTask(data.taskId);\n });\n\n this.connection.onShutdown(() => {\n console.log(\"[project-runner] Received shutdown signal from server\");\n void this.stop();\n });\n\n this.heartbeatTimer = setInterval(() => {\n this.connection.sendHeartbeat();\n }, HEARTBEAT_INTERVAL_MS);\n\n console.log(\"[project-runner] Connected, waiting for task assignments...\");\n\n // Keep process alive until stop() is called\n await new Promise<void>((resolve) => {\n this.resolveLifecycle = resolve;\n process.on(\"SIGTERM\", () => void this.stop());\n process.on(\"SIGINT\", () => void this.stop());\n });\n }\n\n private async handleAssignment(assignment: TaskAssignment): Promise<void> {\n const { taskId, taskToken, apiUrl, mode, branch, devBranch } = assignment;\n const shortId = taskId.slice(0, 8);\n\n if (this.activeAgents.has(taskId)) {\n console.log(`[project-runner] Task ${shortId} already running, skipping`);\n return;\n }\n\n if (this.activeAgents.size >= MAX_CONCURRENT) {\n console.log(\n `[project-runner] Max concurrent agents (${MAX_CONCURRENT}) reached, rejecting task ${shortId}`,\n );\n this.connection.emitTaskStopped(taskId, \"max_concurrent_reached\");\n return;\n }\n\n try {\n // Fetch latest refs\n try {\n execSync(\"git fetch origin\", { cwd: this.projectDir, stdio: \"ignore\" });\n } catch {\n console.log(`[task:${shortId}] Warning: git fetch failed`);\n }\n\n // Create worktree with devBranch as base\n const worktreePath = ensureWorktree(this.projectDir, taskId, devBranch);\n\n // Checkout task branch if provided\n if (branch && branch !== devBranch) {\n try {\n execSync(`git checkout ${branch}`, { cwd: worktreePath, stdio: \"ignore\" });\n } catch {\n try {\n execSync(`git checkout -b ${branch}`, { cwd: worktreePath, stdio: \"ignore\" });\n } catch {\n console.log(`[task:${shortId}] Warning: could not checkout branch ${branch}`);\n }\n }\n }\n\n // Resolve CLI entry point\n const cliPath = path.resolve(__dirname, \"cli.js\");\n\n const child = fork(cliPath, [], {\n env: {\n ...process.env,\n CONVEYOR_API_URL: apiUrl,\n CONVEYOR_TASK_TOKEN: taskToken,\n CONVEYOR_TASK_ID: taskId,\n CONVEYOR_MODE: mode,\n CONVEYOR_WORKSPACE: worktreePath,\n CONVEYOR_USE_WORKTREE: \"false\",\n },\n cwd: worktreePath,\n stdio: [\"pipe\", \"pipe\", \"pipe\", \"ipc\"],\n });\n\n // Prefix child output\n child.stdout?.on(\"data\", (data: Buffer) => {\n const lines = data.toString().trimEnd().split(\"\\n\");\n for (const line of lines) {\n console.log(`[task:${shortId}] ${line}`);\n }\n });\n child.stderr?.on(\"data\", (data: Buffer) => {\n const lines = data.toString().trimEnd().split(\"\\n\");\n for (const line of lines) {\n console.error(`[task:${shortId}] ${line}`);\n }\n });\n\n this.activeAgents.set(taskId, { process: child, worktreePath, mode });\n this.connection.emitTaskStarted(taskId);\n\n console.log(`[project-runner] Started task ${shortId} in ${mode} mode at ${worktreePath}`);\n\n child.on(\"exit\", (code) => {\n this.activeAgents.delete(taskId);\n const reason = code === 0 ? \"completed\" : `exited with code ${code}`;\n this.connection.emitTaskStopped(taskId, reason);\n console.log(`[project-runner] Task ${shortId} ${reason}`);\n\n // Clean up worktree on success\n if (code === 0) {\n try {\n removeWorktree(this.projectDir, taskId);\n } catch {\n // best effort\n }\n }\n });\n } catch (error) {\n console.error(\n `[project-runner] Failed to start task ${shortId}:`,\n error instanceof Error ? error.message : error,\n );\n this.connection.emitTaskStopped(\n taskId,\n `start_failed: ${error instanceof Error ? error.message : \"Unknown\"}`,\n );\n }\n }\n\n private handleStopTask(taskId: string): void {\n const agent = this.activeAgents.get(taskId);\n if (!agent) return;\n\n const shortId = taskId.slice(0, 8);\n console.log(`[project-runner] Stopping task ${shortId}`);\n\n agent.process.kill(\"SIGTERM\");\n\n // Force kill after timeout\n const timer = setTimeout(() => {\n if (this.activeAgents.has(taskId)) {\n agent.process.kill(\"SIGKILL\");\n }\n }, STOP_TIMEOUT_MS);\n\n agent.process.on(\"exit\", () => {\n clearTimeout(timer);\n try {\n removeWorktree(this.projectDir, taskId);\n } catch {\n // best effort\n }\n });\n }\n\n async stop(): Promise<void> {\n if (this.stopping) return;\n this.stopping = true;\n\n console.log(\"[project-runner] Shutting down...\");\n\n if (this.heartbeatTimer) {\n clearInterval(this.heartbeatTimer);\n this.heartbeatTimer = null;\n }\n\n // Stop all active agents\n const stopPromises = [...this.activeAgents.keys()].map(\n (taskId) =>\n new Promise<void>((resolve) => {\n const agent = this.activeAgents.get(taskId);\n if (!agent) {\n resolve();\n return;\n }\n agent.process.on(\"exit\", () => {\n resolve();\n });\n this.handleStopTask(taskId);\n }),\n );\n\n // Wait for all agents with global timeout\n await Promise.race([\n Promise.all(stopPromises),\n new Promise<void>((resolve) => setTimeout(resolve, 60_000)),\n ]);\n\n this.connection.disconnect();\n console.log(\"[project-runner] Shutdown complete\");\n\n if (this.resolveLifecycle) {\n this.resolveLifecycle();\n this.resolveLifecycle = null;\n }\n }\n}\n"],"mappings":"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","names":["resolve","resolve","execSync","join","execSync","join","resolve","execSync","resolve","join","io","resolve","execSync","HEARTBEAT_INTERVAL_MS","resolve","execSync"]}
1
+ {"version":3,"sources":["../src/connection.ts","../src/setup.ts","../src/worktree.ts","../src/runner.ts","../src/query-executor.ts","../src/prompt-builder.ts","../src/mcp-tools.ts","../src/project-connection.ts","../src/project-runner.ts"],"sourcesContent":["import { io, type Socket } from \"socket.io-client\";\nimport type { AgentRunnerConfig, TaskContext, AgentEvent } from \"./types.js\";\n\ninterface AgentQuestionOption {\n label: string;\n description: string;\n preview?: string;\n}\n\ninterface AgentQuestion {\n question: string;\n header: string;\n options: AgentQuestionOption[];\n multiSelect?: boolean;\n}\n\nexport class ConveyorConnection {\n private socket: Socket | null = null;\n private config: AgentRunnerConfig;\n private eventBuffer: { taskId: string; event: AgentEvent }[] = [];\n private flushTimer: ReturnType<typeof setTimeout> | null = null;\n private static readonly EVENT_BATCH_MS = 500;\n\n private earlyMessages: {\n content: string;\n userId: string;\n files?: {\n id: string;\n fileName: string;\n mimeType: string;\n downloadUrl: string;\n content?: string;\n contentEncoding?: \"base64\" | \"utf-8\";\n }[];\n }[] = [];\n private earlyStop = false;\n private chatMessageCallback:\n | ((msg: {\n content: string;\n userId: string;\n files?: {\n id: string;\n fileName: string;\n mimeType: string;\n downloadUrl: string;\n content?: string;\n contentEncoding?: \"base64\" | \"utf-8\";\n }[];\n }) => void)\n | null = null;\n private stopCallback: (() => void) | null = null;\n private pendingQuestionResolvers = new Map<string, (answers: Record<string, string>) => void>();\n\n constructor(config: AgentRunnerConfig) {\n this.config = config;\n }\n\n connect(): Promise<void> {\n return new Promise((resolve, reject) => {\n let settled = false;\n let attempts = 0;\n const maxInitialAttempts = 30;\n\n this.socket = io(this.config.conveyorApiUrl, {\n auth: { taskToken: this.config.taskToken, runnerMode: this.config.mode ?? \"task\" },\n transports: [\"websocket\"],\n reconnection: true,\n reconnectionAttempts: Infinity,\n reconnectionDelay: 2000,\n reconnectionDelayMax: 30000,\n randomizationFactor: 0.3,\n extraHeaders: {\n \"ngrok-skip-browser-warning\": \"true\",\n },\n });\n\n // Register listeners immediately so we capture messages the server\n // flushes during registerHandlers (before connect() resolves).\n this.socket.on(\n \"agentRunner:incomingMessage\",\n (msg: {\n content: string;\n userId: string;\n files?: {\n id: string;\n fileName: string;\n mimeType: string;\n downloadUrl: string;\n content?: string;\n contentEncoding?: \"base64\" | \"utf-8\";\n }[];\n }) => {\n if (this.chatMessageCallback) {\n this.chatMessageCallback(msg);\n } else {\n this.earlyMessages.push(msg);\n }\n },\n );\n\n this.socket.on(\"agentRunner:stop\", () => {\n if (this.stopCallback) {\n this.stopCallback();\n } else {\n this.earlyStop = true;\n }\n });\n\n this.socket.on(\n \"agentRunner:questionAnswer\",\n (data: { requestId: string; answers: Record<string, string> }) => {\n const resolver = this.pendingQuestionResolvers.get(data.requestId);\n if (resolver) {\n this.pendingQuestionResolvers.delete(data.requestId);\n resolver(data.answers);\n }\n },\n );\n\n this.socket.on(\"connect\", () => {\n if (!settled) {\n settled = true;\n resolve();\n }\n });\n\n this.socket.io.on(\"reconnect_attempt\", () => {\n attempts++;\n if (!settled && attempts >= maxInitialAttempts) {\n settled = true;\n reject(new Error(`Failed to connect after ${maxInitialAttempts} attempts`));\n }\n });\n });\n }\n\n fetchChatMessages(\n limit?: number,\n ): Promise<\n { role: string; content: string; userId: string | null; userName?: string; createdAt: string }[]\n > {\n const socket = this.socket;\n if (!socket) throw new Error(\"Not connected\");\n\n return new Promise((resolve, reject) => {\n socket.emit(\n \"agentRunner:getChatMessages\",\n { taskId: this.config.taskId, limit },\n (response: {\n success: boolean;\n data?: {\n role: string;\n content: string;\n userId: string | null;\n userName?: string;\n createdAt: string;\n }[];\n error?: string;\n }): void => {\n if (response.success && response.data) {\n resolve(response.data);\n } else {\n reject(new Error(response.error ?? \"Failed to fetch chat messages\"));\n }\n },\n );\n });\n }\n\n fetchTaskContext(): Promise<TaskContext> {\n const socket = this.socket;\n if (!socket) throw new Error(\"Not connected\");\n\n return new Promise((resolve, reject) => {\n socket.emit(\n \"agentRunner:getTaskContext\",\n { taskId: this.config.taskId },\n (response: { success: boolean; data?: TaskContext; error?: string }): void => {\n if (response.success && response.data) {\n resolve(response.data);\n } else {\n reject(new Error(response.error ?? \"Failed to fetch task context\"));\n }\n },\n );\n });\n }\n\n sendEvent(event: AgentEvent): void {\n if (!this.socket) throw new Error(\"Not connected\");\n\n this.eventBuffer.push({ taskId: this.config.taskId, event });\n if (!this.flushTimer) {\n this.flushTimer = setTimeout(() => this.flushEvents(), ConveyorConnection.EVENT_BATCH_MS);\n }\n }\n\n flushEvents(): void {\n if (this.flushTimer) {\n clearTimeout(this.flushTimer);\n this.flushTimer = null;\n }\n if (!this.socket || this.eventBuffer.length === 0) return;\n for (const entry of this.eventBuffer) {\n this.socket.emit(\"agentRunner:event\", entry);\n }\n this.eventBuffer = [];\n }\n\n updateStatus(status: string): void {\n if (!this.socket) throw new Error(\"Not connected\");\n\n this.socket.emit(\"agentRunner:statusUpdate\", {\n taskId: this.config.taskId,\n status,\n });\n }\n\n postChatMessage(content: string): void {\n if (!this.socket) throw new Error(\"Not connected\");\n\n this.socket.emit(\"agentRunner:chatMessage\", {\n taskId: this.config.taskId,\n content,\n });\n }\n\n createPR(params: {\n title: string;\n body: string;\n baseBranch?: string;\n }): Promise<{ url: string; number: number }> {\n const socket = this.socket;\n if (!socket) throw new Error(\"Not connected\");\n\n return new Promise((resolve, reject) => {\n socket.emit(\n \"agentRunner:createPR\",\n { taskId: this.config.taskId, ...params },\n (response: {\n success: boolean;\n data?: { url: string; number: number };\n error?: string;\n }): void => {\n if (response.success && response.data) {\n resolve(response.data);\n } else {\n reject(new Error(response.error ?? \"Failed to create pull request\"));\n }\n },\n );\n });\n }\n\n askUserQuestion(requestId: string, questions: AgentQuestion[]): Promise<Record<string, string>> {\n if (!this.socket) throw new Error(\"Not connected\");\n\n this.socket.emit(\"agentRunner:askUserQuestion\", {\n taskId: this.config.taskId,\n requestId,\n questions,\n });\n\n return new Promise((resolve) => {\n this.pendingQuestionResolvers.set(requestId, resolve);\n });\n }\n\n cancelPendingQuestions(): void {\n this.pendingQuestionResolvers.clear();\n }\n\n storeSessionId(sessionId: string): void {\n if (!this.socket) return;\n this.socket.emit(\"agentRunner:storeSessionId\", {\n taskId: this.config.taskId,\n sessionId,\n });\n }\n\n updateTaskFields(fields: { plan?: string; description?: string }): void {\n if (!this.socket) throw new Error(\"Not connected\");\n this.socket.emit(\"agentRunner:updateTaskFields\", {\n taskId: this.config.taskId,\n fields,\n });\n }\n\n onChatMessage(\n callback: (message: {\n content: string;\n userId: string;\n files?: {\n id: string;\n fileName: string;\n mimeType: string;\n downloadUrl: string;\n content?: string;\n contentEncoding?: \"base64\" | \"utf-8\";\n }[];\n }) => void,\n ): void {\n this.chatMessageCallback = callback;\n for (const msg of this.earlyMessages) {\n callback(msg);\n }\n this.earlyMessages = [];\n }\n\n onStopRequested(callback: () => void): void {\n this.stopCallback = callback;\n if (this.earlyStop) {\n callback();\n this.earlyStop = false;\n }\n }\n\n trackSpending(params: {\n agentId: string;\n inputTokens: number;\n outputTokens: number;\n totalTokens: number;\n totalCostUsd: number;\n onSubscription: boolean;\n }): void {\n if (!this.socket) throw new Error(\"Not connected\");\n\n this.socket.emit(\"agentRunner:trackSpending\", {\n taskId: this.config.taskId,\n ...params,\n });\n }\n\n emitStatus(status: string): void {\n if (!this.socket) return;\n this.socket.emit(\"agentRunner:statusUpdate\", {\n taskId: this.config.taskId,\n status,\n });\n }\n\n sendHeartbeat(): void {\n if (!this.socket) return;\n this.socket.emit(\"agentRunner:heartbeat\", {\n taskId: this.config.taskId,\n });\n }\n\n sendTypingStart(): void {\n this.sendEvent({ type: \"agent_typing_start\" });\n }\n\n sendTypingStop(): void {\n this.sendEvent({ type: \"agent_typing_stop\" });\n }\n\n createSubtask(data: {\n title: string;\n description?: string;\n plan?: string;\n ordinal?: number;\n storyPointValue?: number;\n }): Promise<{ id: string }> {\n const socket = this.socket;\n if (!socket) throw new Error(\"Not connected\");\n return new Promise((resolve, reject) => {\n socket.emit(\n \"agentRunner:createSubtask\",\n data,\n (response: { success: boolean; data?: { id: string }; error?: string }) => {\n if (response.success && response.data) resolve(response.data);\n else reject(new Error(response.error ?? \"Failed to create subtask\"));\n },\n );\n });\n }\n\n updateSubtask(\n subtaskId: string,\n fields: {\n title?: string;\n description?: string;\n plan?: string;\n ordinal?: number;\n storyPointValue?: number;\n },\n ): void {\n if (!this.socket) throw new Error(\"Not connected\");\n this.socket.emit(\"agentRunner:updateSubtask\", {\n subtaskId,\n fields,\n });\n }\n\n deleteSubtask(subtaskId: string): void {\n if (!this.socket) throw new Error(\"Not connected\");\n this.socket.emit(\"agentRunner:deleteSubtask\", { subtaskId });\n }\n\n listSubtasks(): Promise<\n {\n id: string;\n title: string;\n description: string | null;\n status: string;\n ordinal: number;\n storyPointId: string | null;\n plan: string | null;\n }[]\n > {\n const socket = this.socket;\n if (!socket) throw new Error(\"Not connected\");\n return new Promise((resolve, reject) => {\n socket.emit(\n \"agentRunner:listSubtasks\",\n {},\n (response: {\n success: boolean;\n data?: {\n id: string;\n title: string;\n description: string | null;\n status: string;\n ordinal: number;\n storyPointId: string | null;\n plan: string | null;\n }[];\n error?: string;\n }) => {\n if (response.success && response.data) resolve(response.data);\n else reject(new Error(response.error ?? \"Failed to list subtasks\"));\n },\n );\n });\n }\n\n disconnect(): void {\n this.flushEvents();\n this.socket?.disconnect();\n this.socket = null;\n }\n}\n","import { execSync } from \"node:child_process\";\nimport { spawn, type ChildProcess } from \"node:child_process\";\nimport { readFile } from \"node:fs/promises\";\nimport { join } from \"node:path\";\n\nexport interface ConveyorConfig {\n setupCommand?: string;\n startCommand?: string;\n previewPort?: number;\n}\n\nconst CONVEYOR_CONFIG_PATH = \".conveyor/config.json\";\nconst DEVCONTAINER_PATH = \".devcontainer/conveyor/devcontainer.json\";\n\nexport async function loadForwardPorts(workspaceDir: string): Promise<number[]> {\n try {\n const raw = await readFile(join(workspaceDir, DEVCONTAINER_PATH), \"utf-8\");\n const parsed = JSON.parse(raw) as { forwardPorts?: number[] };\n return parsed.forwardPorts ?? [];\n } catch {\n return [];\n }\n}\n\nexport async function loadConveyorConfig(workspaceDir: string): Promise<ConveyorConfig | null> {\n // Primary: .conveyor/config.json\n try {\n const raw = await readFile(join(workspaceDir, CONVEYOR_CONFIG_PATH), \"utf-8\");\n const parsed = JSON.parse(raw) as ConveyorConfig;\n if (parsed.setupCommand || parsed.startCommand) return parsed;\n } catch {\n // Not found or invalid — try fallback\n }\n\n // Fallback: devcontainer.json \"conveyor\" section\n try {\n const raw = await readFile(join(workspaceDir, DEVCONTAINER_PATH), \"utf-8\");\n const parsed = JSON.parse(raw) as { conveyor?: ConveyorConfig };\n if (parsed.conveyor && (parsed.conveyor.startCommand || parsed.conveyor.setupCommand)) {\n return parsed.conveyor;\n }\n } catch {\n // Not found or invalid\n }\n\n return null;\n}\n\n/**\n * Runs a command synchronously (waits for exit). Streams stdout/stderr\n * line-by-line via the onOutput callback.\n */\nexport function runSetupCommand(\n cmd: string,\n cwd: string,\n onOutput: (stream: \"stdout\" | \"stderr\", data: string) => void,\n): Promise<void> {\n return new Promise((resolve, reject) => {\n const child = spawn(\"sh\", [\"-c\", cmd], {\n cwd,\n stdio: [\"ignore\", \"pipe\", \"pipe\"],\n env: { ...process.env },\n });\n\n child.stdout.on(\"data\", (chunk: Buffer) => {\n onOutput(\"stdout\", chunk.toString());\n });\n\n child.stderr.on(\"data\", (chunk: Buffer) => {\n onOutput(\"stderr\", chunk.toString());\n });\n\n child.on(\"close\", (code) => {\n if (code === 0) {\n resolve();\n } else {\n reject(new Error(`Setup command exited with code ${code}`));\n }\n });\n\n child.on(\"error\", (err) => {\n reject(err);\n });\n });\n}\n\n/**\n * Runs a command in the background (does not wait for exit). Returns the\n * ChildProcess so it can be cleaned up on agent shutdown. Streams\n * stdout/stderr via the onOutput callback.\n */\nexport function runStartCommand(\n cmd: string,\n cwd: string,\n onOutput: (stream: \"stdout\" | \"stderr\", data: string) => void,\n): ChildProcess {\n const child = spawn(\"sh\", [\"-c\", cmd], {\n cwd,\n stdio: [\"ignore\", \"pipe\", \"pipe\"],\n detached: true,\n env: { ...process.env },\n });\n\n child.stdout.on(\"data\", (chunk: Buffer) => {\n onOutput(\"stdout\", chunk.toString());\n });\n\n child.stderr.on(\"data\", (chunk: Buffer) => {\n onOutput(\"stderr\", chunk.toString());\n });\n\n child.unref();\n return child;\n}\n\n/**\n * Reset `.devcontainer/conveyor/devcontainer.json` to match the base branch\n * and remove the cloud-build \"configure\" commit from git history. This runs\n * AFTER the codespace has started (env vars are already in process memory)\n * so the agent sees a branch identical to base — no spurious diffs, no\n * rebase conflicts on devcontainer.json.\n */\nexport function cleanDevcontainerFromGit(\n workspaceDir: string,\n taskBranch: string,\n baseBranch: string,\n): { cleaned: boolean; message: string } {\n const git = (cmd: string): string =>\n execSync(cmd, { cwd: workspaceDir, encoding: \"utf-8\", timeout: 30_000 }).trim();\n\n try {\n git(`git fetch origin ${baseBranch}`);\n } catch {\n return { cleaned: false, message: `Failed to fetch origin/${baseBranch}` };\n }\n\n // Check if devcontainer.json differs from base\n try {\n git(`git diff --quiet origin/${baseBranch} -- ${DEVCONTAINER_PATH}`);\n return { cleaned: false, message: \"devcontainer.json already matches base\" };\n } catch {\n // diff --quiet exits non-zero when there IS a diff — expected path\n }\n\n try {\n const ahead = parseInt(git(`git rev-list --count origin/${baseBranch}..HEAD`), 10);\n\n if (ahead <= 1) {\n // Fresh start: only the devcontainer commit exists — hard reset to base\n git(`git reset --hard origin/${baseBranch}`);\n } else {\n // Relaunch: agent has prior commits — restore file and add fixup commit\n git(`git checkout origin/${baseBranch} -- ${DEVCONTAINER_PATH}`);\n git(`git add ${DEVCONTAINER_PATH}`);\n\n try {\n git(`git diff --cached --quiet -- ${DEVCONTAINER_PATH}`);\n return { cleaned: false, message: \"devcontainer.json already clean in working tree\" };\n } catch {\n git(`git commit -m \"chore: reset devcontainer config\"`);\n }\n }\n\n git(`git push --force-with-lease origin ${taskBranch}`);\n return { cleaned: true, message: \"devcontainer.json cleaned from git history\" };\n } catch (err) {\n const msg = err instanceof Error ? err.message : \"Unknown error\";\n return { cleaned: false, message: `Git cleanup failed: ${msg}` };\n }\n}\n","import { execSync } from \"node:child_process\";\nimport { existsSync } from \"node:fs\";\nimport { join } from \"node:path\";\n\nconst WORKTREE_DIR = \".worktrees\";\n\n/**\n * Ensure a git worktree exists for the given task. Creates one if it doesn't\n * exist, reuses the existing one otherwise. Returns the absolute worktree path.\n *\n * Uses --detach to avoid \"branch already checked out\" errors when the branch\n * (e.g. dev) is already checked out in the main worktree or another worktree.\n */\nexport function ensureWorktree(projectDir: string, taskId: string, branch?: string): string {\n const worktreePath = join(projectDir, WORKTREE_DIR, taskId);\n\n if (existsSync(worktreePath)) {\n if (branch) {\n try {\n execSync(`git checkout --detach origin/${branch}`, {\n cwd: worktreePath,\n stdio: \"ignore\",\n });\n } catch {\n /* branch doesn't exist on remote yet */\n }\n }\n return worktreePath;\n }\n\n const ref = branch ? `origin/${branch}` : \"HEAD\";\n execSync(`git worktree add --detach \"${worktreePath}\" ${ref}`, {\n cwd: projectDir,\n stdio: \"ignore\",\n });\n\n return worktreePath;\n}\n\n/**\n * Remove a task's git worktree. Best-effort — silently ignores failures.\n */\nexport function removeWorktree(projectDir: string, taskId: string): void {\n const worktreePath = join(projectDir, WORKTREE_DIR, taskId);\n if (!existsSync(worktreePath)) return;\n try {\n execSync(`git worktree remove \"${worktreePath}\" --force`, {\n cwd: projectDir,\n stdio: \"ignore\",\n });\n } catch {\n /* best effort */\n }\n}\n","import { execSync } from \"node:child_process\";\nimport { readdirSync, statSync, readFileSync } from \"node:fs\";\nimport { homedir } from \"node:os\";\nimport { join } from \"node:path\";\nimport type { SDKUserMessage } from \"@anthropic-ai/claude-agent-sdk\";\nimport type {\n AgentRunnerConfig,\n AgentRunnerCallbacks,\n AgentRunnerStatus,\n AgentEvent,\n TaskContext,\n} from \"./types.js\";\nimport { ConveyorConnection } from \"./connection.js\";\nimport {\n cleanDevcontainerFromGit,\n loadConveyorConfig,\n loadForwardPorts,\n runSetupCommand,\n runStartCommand,\n type ConveyorConfig,\n} from \"./setup.js\";\nimport { runSdkQuery, type QueryHost } from \"./query-executor.js\";\nimport { ensureWorktree } from \"./worktree.js\";\n\nconst HEARTBEAT_INTERVAL_MS = 30_000;\n\nexport class AgentRunner {\n private config: AgentRunnerConfig;\n private connection: ConveyorConnection;\n private callbacks: AgentRunnerCallbacks;\n private _state: AgentRunnerStatus = \"connecting\";\n private stopped = false;\n private inputResolver: ((msg: SDKUserMessage) => void) | null = null;\n private pendingMessages: SDKUserMessage[] = [];\n private setupLog: string[] = [];\n private heartbeatTimer: ReturnType<typeof setInterval> | null = null;\n private taskContext: TaskContext | null = null;\n private planFileSnapshot = new Map<string, number>();\n private lockedPlanFile: string | null = null;\n private worktreeActive = false;\n private static readonly MAX_SETUP_LOG_LINES = 50;\n\n constructor(config: AgentRunnerConfig, callbacks: AgentRunnerCallbacks) {\n this.config = config;\n this.connection = new ConveyorConnection(config);\n this.callbacks = callbacks;\n }\n\n get state(): AgentRunnerStatus {\n return this._state;\n }\n\n private async setState(status: AgentRunnerStatus): Promise<void> {\n this._state = status;\n this.connection.emitStatus(status);\n await this.callbacks.onStatusChange(status);\n }\n\n private startHeartbeat(): void {\n this.heartbeatTimer = setInterval(() => {\n if (!this.stopped) {\n this.connection.sendHeartbeat();\n }\n }, HEARTBEAT_INTERVAL_MS);\n }\n\n private stopHeartbeat(): void {\n if (this.heartbeatTimer) {\n clearInterval(this.heartbeatTimer);\n this.heartbeatTimer = null;\n }\n }\n\n async start(): Promise<void> {\n await this.setState(\"connecting\");\n await this.connection.connect();\n\n this.connection.onStopRequested(() => this.stop());\n this.connection.onChatMessage((message) =>\n this.injectHumanMessage(message.content, message.files),\n );\n\n await this.setState(\"connected\");\n this.connection.sendEvent({ type: \"connected\", taskId: this.config.taskId });\n this.startHeartbeat();\n\n if (this.config.mode !== \"pm\" && process.env.CODESPACES === \"true\") {\n const setupOk = await this.runSetupSafe();\n if (!setupOk) {\n this.stopHeartbeat();\n await this.setState(\"error\");\n this.connection.disconnect();\n return;\n }\n }\n\n this.initRtk();\n\n // --- Phase 2.5: Worktree isolation (local agents) ---\n if (this.config.mode === \"pm\" || process.env.CONVEYOR_USE_WORKTREE === \"true\") {\n try {\n const worktreePath = ensureWorktree(this.config.workspaceDir, this.config.taskId);\n this.config = { ...this.config, workspaceDir: worktreePath };\n this.worktreeActive = true;\n this.setupLog.push(`[conveyor] Using worktree: ${worktreePath}`);\n } catch (error) {\n const msg = error instanceof Error ? error.message : \"Unknown error\";\n this.setupLog.push(`[conveyor] Worktree creation failed, using shared workspace: ${msg}`);\n }\n }\n\n // --- Phase 3: Fetch context ---\n await this.setState(\"fetching_context\");\n try {\n this.taskContext = await this.connection.fetchTaskContext();\n } catch (error) {\n const message = error instanceof Error ? error.message : \"Failed to fetch task context\";\n this.connection.sendEvent({ type: \"error\", message });\n await this.callbacks.onEvent({ type: \"error\", message });\n this.stopHeartbeat();\n await this.setState(\"error\");\n this.connection.disconnect();\n return;\n }\n\n // When resuming an existing session after a process restart, initialise\n // _lastReportedCostUsd from the spending already recorded in the DB so\n // the first SDK result delta is correct (fixes Bug 1 — over-counting).\n if (this.taskContext.claudeSessionId && this.taskContext._existingSpendingTotal !== null) {\n this.taskContext._lastReportedCostUsd = this.taskContext._existingSpendingTotal;\n }\n\n if (process.env.CODESPACES === \"true\" && this.taskContext.baseBranch) {\n const result = cleanDevcontainerFromGit(\n this.config.workspaceDir,\n this.taskContext.githubBranch,\n this.taskContext.baseBranch,\n );\n if (result.cleaned) {\n this.setupLog.push(`[conveyor] ${result.message}`);\n }\n }\n\n if (!this.worktreeActive && this.taskContext.useWorktree) {\n try {\n const worktreePath = ensureWorktree(this.config.workspaceDir, this.config.taskId);\n this.config = { ...this.config, workspaceDir: worktreePath };\n this.worktreeActive = true;\n this.setupLog.push(`[conveyor] Using worktree (from task config): ${worktreePath}`);\n } catch (error) {\n const msg = error instanceof Error ? error.message : \"Unknown error\";\n this.setupLog.push(`[conveyor] Worktree creation failed, using shared workspace: ${msg}`);\n }\n }\n\n if (this.worktreeActive && this.taskContext.githubBranch) {\n try {\n const branch = this.taskContext.githubBranch;\n execSync(`git fetch origin ${branch} && git checkout ${branch}`, {\n cwd: this.config.workspaceDir,\n stdio: \"ignore\",\n });\n } catch {\n /* branch may not exist remotely yet or already checked out */\n }\n }\n\n // --- Phase 4: Initial action ---\n const isPm = this.config.mode === \"pm\";\n if (isPm) {\n await this.setState(\"idle\");\n } else {\n await this.setState(\"running\");\n await runSdkQuery(this.asQueryHost(), this.taskContext);\n if (!this.stopped) await this.setState(\"idle\");\n }\n\n await this.runCoreLoop();\n\n this.stopHeartbeat();\n await this.setState(\"finished\");\n this.connection.disconnect();\n }\n\n private async runCoreLoop(): Promise<void> {\n if (!this.taskContext) return;\n while (!this.stopped) {\n if (this._state === \"idle\") {\n const msg = await this.waitForUserContent();\n if (!msg) break;\n await this.setState(\"running\");\n await runSdkQuery(this.asQueryHost(), this.taskContext, msg);\n if (!this.stopped) await this.setState(\"idle\");\n } else if (this._state === \"error\") {\n await this.setState(\"idle\");\n } else {\n break;\n }\n }\n }\n\n private async runSetupSafe(): Promise<boolean> {\n await this.setState(\"setup\");\n\n const ports = await loadForwardPorts(this.config.workspaceDir);\n if (ports.length > 0 && process.env.CODESPACE_NAME) {\n const visibility = ports.map((p) => `${p}:public`).join(\" \");\n runStartCommand(\n `gh codespace ports visibility ${visibility} -c \"${process.env.CODESPACE_NAME}\" 2>/dev/null`,\n this.config.workspaceDir,\n () => undefined,\n );\n }\n\n const config = await loadConveyorConfig(this.config.workspaceDir);\n if (!config) {\n this.connection.sendEvent({ type: \"setup_complete\" });\n await this.callbacks.onEvent({ type: \"setup_complete\" });\n return true;\n }\n\n try {\n await this.executeSetupConfig(config);\n const setupEvent: AgentEvent = {\n type: \"setup_complete\",\n previewPort: config.previewPort ?? undefined,\n };\n this.connection.sendEvent(setupEvent);\n await this.callbacks.onEvent(setupEvent);\n return true;\n } catch (error) {\n const message = error instanceof Error ? error.message : \"Setup failed\";\n this.connection.sendEvent({ type: \"setup_error\", message });\n await this.callbacks.onEvent({ type: \"setup_error\", message });\n this.connection.postChatMessage(\n `Environment setup failed: ${message}\\nThe agent cannot start until this is resolved.`,\n );\n return false;\n }\n }\n\n private pushSetupLog(line: string): void {\n this.setupLog.push(line);\n if (this.setupLog.length > AgentRunner.MAX_SETUP_LOG_LINES) {\n this.setupLog.splice(0, this.setupLog.length - AgentRunner.MAX_SETUP_LOG_LINES);\n }\n }\n\n private async executeSetupConfig(config: ConveyorConfig): Promise<void> {\n if (config.setupCommand) {\n this.pushSetupLog(`$ ${config.setupCommand}`);\n await runSetupCommand(config.setupCommand, this.config.workspaceDir, (stream, data) => {\n this.connection.sendEvent({ type: \"setup_output\", stream, data });\n for (const line of data.split(\"\\n\").filter(Boolean)) {\n this.pushSetupLog(`[${stream}] ${line}`);\n }\n });\n this.pushSetupLog(\"(exit 0)\");\n }\n\n if (config.startCommand) {\n this.pushSetupLog(`$ ${config.startCommand} & (background)`);\n runStartCommand(config.startCommand, this.config.workspaceDir, (stream, data) => {\n this.connection.sendEvent({ type: \"start_command_output\", stream, data });\n });\n }\n }\n\n private initRtk(): void {\n try {\n execSync(\"rtk --version\", { stdio: \"ignore\" });\n execSync(\"rtk init --global --auto-patch\", { stdio: \"ignore\" });\n } catch {\n // RTK not installed — skip silently\n }\n }\n\n private injectHumanMessage(\n content: string,\n files?: {\n id: string;\n fileName: string;\n mimeType: string;\n downloadUrl: string;\n content?: string;\n contentEncoding?: \"base64\" | \"utf-8\";\n }[],\n ): void {\n type ImageMediaType = \"image/gif\" | \"image/jpeg\" | \"image/png\" | \"image/webp\";\n type TextBlock = { type: \"text\"; text: string };\n type ImageBlock = {\n type: \"image\";\n source: { type: \"base64\"; media_type: ImageMediaType; data: string };\n };\n type ContentBlock = TextBlock | ImageBlock;\n\n let messageContent: string | ContentBlock[];\n if (files?.length) {\n const blocks: ContentBlock[] = [{ type: \"text\", text: content }];\n for (const f of files) {\n if (f.content && f.contentEncoding === \"base64\") {\n // Embed image directly as a visual content block\n blocks.push({\n type: \"image\",\n source: { type: \"base64\", media_type: f.mimeType as ImageMediaType, data: f.content },\n });\n blocks.push({\n type: \"text\",\n text: `[Attached image: ${f.fileName} (${f.mimeType})]`,\n });\n } else if (f.content && f.contentEncoding === \"utf-8\") {\n // Embed text content inline\n blocks.push({\n type: \"text\",\n text: `[Attached file: ${f.fileName} (${f.mimeType})]\\n\\`\\`\\`\\n${f.content}\\n\\`\\`\\``,\n });\n } else {\n // Fallback to download URL\n blocks.push({\n type: \"text\",\n text: `[Attached file: ${f.fileName} (${f.mimeType})] Download: ${f.downloadUrl}`,\n });\n }\n }\n messageContent = blocks;\n } else {\n messageContent = content;\n }\n\n const msg: SDKUserMessage = {\n type: \"user\" as const,\n session_id: \"\",\n message: { role: \"user\" as const, content: messageContent },\n parent_tool_use_id: null,\n };\n\n if (this.inputResolver) {\n const resolve = this.inputResolver;\n this.inputResolver = null;\n resolve(msg);\n } else {\n this.pendingMessages.push(msg);\n }\n }\n\n private waitForMessage(): Promise<SDKUserMessage | null> {\n return new Promise<SDKUserMessage | null>((resolve) => {\n const checkStopped = setInterval(() => {\n if (this.stopped) {\n clearInterval(checkStopped);\n this.inputResolver = null;\n resolve(null);\n }\n }, 1000);\n\n this.inputResolver = (msg: SDKUserMessage) => {\n clearInterval(checkStopped);\n resolve(msg);\n };\n });\n }\n\n private async waitForUserContent(): Promise<string | null> {\n if (this.pendingMessages.length > 0) {\n const next = this.pendingMessages.shift();\n return (next?.message as { content: string })?.content ?? null;\n }\n const msg = await this.waitForMessage();\n if (!msg) return null;\n return (msg.message as { content: string }).content;\n }\n\n async *createInputStream(initialPrompt: string): AsyncGenerator<SDKUserMessage, void, unknown> {\n const makeUserMessage = (content: string): SDKUserMessage => ({\n type: \"user\" as const,\n session_id: \"\",\n message: { role: \"user\" as const, content },\n parent_tool_use_id: null,\n });\n\n yield makeUserMessage(initialPrompt);\n\n while (!this.stopped) {\n if (this.pendingMessages.length > 0) {\n const next = this.pendingMessages.shift();\n if (next) yield next;\n continue;\n }\n\n this.connection.emitStatus(\"waiting_for_input\");\n await this.callbacks.onStatusChange(\"waiting_for_input\");\n const msg = await this.waitForMessage();\n\n if (!msg) break;\n this.connection.emitStatus(\"running\");\n await this.callbacks.onStatusChange(\"running\");\n yield msg;\n }\n }\n\n private getPlanDirs(): string[] {\n return [\n join(homedir(), \".claude\", \"plans\"),\n join(this.config.workspaceDir, \".claude\", \"plans\"),\n ];\n }\n\n /**\n * Snapshot current plan files so syncPlanFile can distinguish files created\n * by THIS session from ones created by a concurrent agent.\n */\n snapshotPlanFiles(): void {\n this.planFileSnapshot.clear();\n this.lockedPlanFile = null;\n for (const plansDir of this.getPlanDirs()) {\n try {\n for (const file of readdirSync(plansDir).filter((f) => f.endsWith(\".md\"))) {\n try {\n const fullPath = join(plansDir, file);\n const stat = statSync(fullPath);\n this.planFileSnapshot.set(fullPath, stat.mtimeMs);\n } catch {\n continue;\n }\n }\n } catch {\n /* plans dir doesn't exist yet */\n }\n }\n }\n\n syncPlanFile(): void {\n if (this.lockedPlanFile) {\n try {\n const content = readFileSync(this.lockedPlanFile, \"utf-8\").trim();\n if (content) {\n this.connection.updateTaskFields({ plan: content });\n const fileName = this.lockedPlanFile.split(\"/\").pop()!;\n this.connection.postChatMessage(`Synced local plan file (${fileName}) to the task plan.`);\n }\n } catch {\n /* locked file was deleted */\n }\n return;\n }\n\n let newest: { path: string; mtime: number } | null = null;\n for (const plansDir of this.getPlanDirs()) {\n let files: string[];\n try {\n files = readdirSync(plansDir).filter((f) => f.endsWith(\".md\"));\n } catch {\n continue;\n }\n\n for (const file of files) {\n const fullPath = join(plansDir, file);\n try {\n const stat = statSync(fullPath);\n const prevMtime = this.planFileSnapshot.get(fullPath);\n const isNew = prevMtime === undefined || stat.mtimeMs > prevMtime;\n if (isNew && (!newest || stat.mtimeMs > newest.mtime)) {\n newest = { path: fullPath, mtime: stat.mtimeMs };\n }\n } catch {\n continue;\n }\n }\n }\n\n if (newest) {\n this.lockedPlanFile = newest.path;\n const content = readFileSync(newest.path, \"utf-8\").trim();\n if (content) {\n this.connection.updateTaskFields({ plan: content });\n const fileName = newest.path.split(\"/\").pop()!;\n this.connection.postChatMessage(\n `Detected local plan file (${fileName}) and synced it to the task plan.`,\n );\n }\n }\n }\n\n private asQueryHost(): QueryHost {\n return {\n config: this.config,\n connection: this.connection,\n callbacks: this.callbacks,\n setupLog: this.setupLog,\n isStopped: () => this.stopped,\n createInputStream: (prompt: string) => this.createInputStream(prompt),\n snapshotPlanFiles: () => this.snapshotPlanFiles(),\n syncPlanFile: () => this.syncPlanFile(),\n };\n }\n\n stop(): void {\n this.stopped = true;\n if (this.inputResolver) {\n this.inputResolver(null as unknown as SDKUserMessage);\n this.inputResolver = null;\n }\n }\n}\n","import { randomUUID } from \"node:crypto\";\nimport { query, type SDKMessage, type SDKUserMessage } from \"@anthropic-ai/claude-agent-sdk\";\nimport type { ConveyorConnection } from \"./connection.js\";\nimport type {\n AgentRunnerConfig,\n AgentRunnerCallbacks,\n TaskContext,\n ActivityEventSummary,\n} from \"./types.js\";\nimport { buildInitialPrompt, buildSystemPrompt } from \"./prompt-builder.js\";\nimport { createConveyorMcpServer } from \"./mcp-tools.js\";\n\nconst API_ERROR_PATTERN = /API Error: [45]\\d\\d/;\nconst RETRY_DELAYS_MS = [60_000, 120_000, 180_000, 300_000];\nconst PM_PLAN_FILE_TOOLS = new Set([\"Write\", \"Edit\", \"MultiEdit\"]);\n\nexport interface QueryHost {\n config: AgentRunnerConfig;\n connection: ConveyorConnection;\n callbacks: AgentRunnerCallbacks;\n setupLog: string[];\n isStopped(): boolean;\n createInputStream(prompt: string): AsyncGenerator<SDKUserMessage, void, unknown>;\n snapshotPlanFiles(): void;\n syncPlanFile(): void;\n}\n\nasync function processAssistantEvent(\n event: SDKMessage,\n host: QueryHost,\n turnToolCalls: ActivityEventSummary[],\n): Promise<void> {\n const msg = (event as unknown as Record<string, unknown>).message as Record<string, unknown>;\n const content = msg.content as Record<string, unknown>[];\n const turnTextParts: string[] = [];\n\n for (const block of content) {\n const blockType = block.type as string;\n if (blockType === \"text\") {\n const text = block.text as string;\n turnTextParts.push(text);\n host.connection.sendEvent({ type: \"message\", content: text });\n await host.callbacks.onEvent({ type: \"message\", content: text });\n } else if (blockType === \"tool_use\") {\n const name = block.name as string;\n const inputStr = typeof block.input === \"string\" ? block.input : JSON.stringify(block.input);\n const isContentTool = [\"edit\", \"write\"].includes(name.toLowerCase());\n const inputLimit = isContentTool ? 10_000 : 500;\n const summary: ActivityEventSummary = {\n tool: name,\n input: inputStr.slice(0, inputLimit),\n timestamp: new Date().toISOString(),\n };\n turnToolCalls.push(summary);\n host.connection.sendEvent({ type: \"tool_use\", tool: name, input: inputStr });\n await host.callbacks.onEvent({ type: \"tool_use\", tool: name, input: inputStr });\n }\n }\n\n if (turnTextParts.length > 0) {\n host.connection.postChatMessage(turnTextParts.join(\"\\n\\n\"));\n }\n\n if (turnToolCalls.length > 0) {\n host.connection.sendEvent({ type: \"turn_end\", toolCalls: [...turnToolCalls] });\n turnToolCalls.length = 0;\n }\n}\n\nfunction handleResultEvent(\n event: SDKMessage,\n host: QueryHost,\n context: TaskContext,\n startTime: number,\n): { totalCostUsd: number; deltaCost: number; retriable: boolean } {\n const resultEvent = event as SDKMessage & { type: \"result\"; subtype: string };\n let totalCostUsd = 0;\n let deltaCost = 0;\n let retriable = false;\n\n if (resultEvent.subtype === \"success\") {\n totalCostUsd =\n \"total_cost_usd\" in resultEvent\n ? ((resultEvent as Record<string, unknown>).total_cost_usd as number)\n : 0;\n const durationMs = Date.now() - startTime;\n const summary =\n \"result\" in resultEvent\n ? String((resultEvent as Record<string, unknown>).result)\n : \"Task completed.\";\n\n if (API_ERROR_PATTERN.test(summary) && durationMs < 30_000) {\n retriable = true;\n }\n\n const lastCost = context._lastReportedCostUsd ?? 0;\n deltaCost = totalCostUsd - lastCost;\n context._lastReportedCostUsd = totalCostUsd;\n\n host.connection.sendEvent({ type: \"completed\", summary, costUsd: deltaCost, durationMs });\n\n if (deltaCost > 0 && context.agentId) {\n const estimatedDeltaTokens = Math.round(deltaCost * 100000);\n host.connection.trackSpending({\n agentId: context.agentId,\n inputTokens: Math.round(estimatedDeltaTokens * 0.7),\n outputTokens: Math.round(estimatedDeltaTokens * 0.3),\n totalTokens: estimatedDeltaTokens,\n totalCostUsd: deltaCost,\n onSubscription: host.config.mode === \"pm\" || !!process.env.CLAUDE_CODE_OAUTH_TOKEN,\n });\n }\n } else {\n const errors =\n \"errors\" in resultEvent ? ((resultEvent as Record<string, unknown>).errors as string[]) : [];\n const errorMsg =\n errors.length > 0 ? errors.join(\", \") : `Agent stopped: ${resultEvent.subtype}`;\n\n if (API_ERROR_PATTERN.test(errorMsg)) {\n retriable = true;\n }\n\n host.connection.sendEvent({ type: \"error\", message: errorMsg });\n }\n\n return { totalCostUsd, deltaCost, retriable };\n}\n\nasync function emitResultEvent(\n event: SDKMessage,\n host: QueryHost,\n context: TaskContext,\n startTime: number,\n): Promise<boolean> {\n const result = handleResultEvent(event, host, context, startTime);\n const durationMs = Date.now() - startTime;\n\n if (result.deltaCost > 0 && context.agentId) {\n await host.callbacks.onEvent({\n type: \"completed\",\n summary: \"Task completed.\",\n costUsd: result.deltaCost,\n durationMs,\n });\n } else {\n const resultEvent = event as SDKMessage & { subtype: string };\n if (resultEvent.subtype === \"success\") {\n const summary =\n \"result\" in resultEvent\n ? String((resultEvent as Record<string, unknown>).result)\n : \"Task completed.\";\n await host.callbacks.onEvent({\n type: \"completed\",\n summary,\n costUsd: 0,\n durationMs,\n });\n } else {\n const errors =\n \"errors\" in resultEvent\n ? ((resultEvent as Record<string, unknown>).errors as string[])\n : [];\n const errorMsg =\n errors.length > 0 ? errors.join(\", \") : `Agent stopped: ${resultEvent.subtype}`;\n await host.callbacks.onEvent({ type: \"error\", message: errorMsg });\n }\n }\n\n return result.retriable;\n}\n\nexport async function processEvents(\n events: AsyncGenerator<SDKMessage, void>,\n context: TaskContext,\n host: QueryHost,\n): Promise<{ retriable: boolean }> {\n const startTime = Date.now();\n let sessionIdStored = false;\n let isTyping = false;\n let retriable = false;\n const turnToolCalls: ActivityEventSummary[] = [];\n\n for await (const event of events) {\n if (host.isStopped()) break;\n\n switch (event.type) {\n case \"system\": {\n if (event.subtype === \"init\") {\n const sessionId = (event as unknown as Record<string, unknown>).session_id as\n | string\n | undefined;\n if (sessionId && !sessionIdStored) {\n sessionIdStored = true;\n host.connection.storeSessionId(sessionId);\n // Reset cost tracking when starting a new (different) session\n if (sessionId !== context.claudeSessionId) {\n context._lastReportedCostUsd = 0;\n }\n }\n await host.callbacks.onEvent({\n type: \"thinking\",\n message: `Agent initialized (model: ${event.model})`,\n });\n }\n break;\n }\n\n case \"assistant\": {\n if (!isTyping) {\n setTimeout(() => host.connection.sendTypingStart(), 200);\n isTyping = true;\n }\n await processAssistantEvent(event, host, turnToolCalls);\n break;\n }\n\n case \"result\": {\n if (isTyping) {\n host.connection.sendTypingStop();\n isTyping = false;\n }\n retriable = await emitResultEvent(event, host, context, startTime);\n break;\n }\n }\n }\n\n if (isTyping) {\n host.connection.sendTypingStop();\n }\n\n return { retriable };\n}\n\nfunction buildCanUseTool(\n host: QueryHost,\n): (\n toolName: string,\n input: Record<string, unknown>,\n) => Promise<\n | { behavior: \"allow\"; updatedInput?: Record<string, unknown> }\n | { behavior: \"deny\"; message: string }\n> {\n const QUESTION_TIMEOUT_MS = 5 * 60 * 1000;\n\n return async (toolName, input) => {\n if (host.config.mode === \"pm\" && PM_PLAN_FILE_TOOLS.has(toolName)) {\n const filePath = String(input.file_path ?? input.path ?? \"\");\n if (filePath.includes(\".claude/plans/\")) {\n return { behavior: \"allow\", updatedInput: input };\n }\n return {\n behavior: \"deny\",\n message: \"File write tools are only available for plan files in PM mode.\",\n };\n }\n\n if (toolName !== \"AskUserQuestion\") {\n return { behavior: \"allow\", updatedInput: input };\n }\n\n const questions = input.questions as {\n question: string;\n header: string;\n options: { label: string; description: string; preview?: string }[];\n multiSelect?: boolean;\n }[];\n\n const requestId = randomUUID();\n host.connection.emitStatus(\"waiting_for_input\");\n host.connection.sendEvent({\n type: \"tool_use\",\n tool: \"AskUserQuestion\",\n input: JSON.stringify(input),\n });\n\n const answerPromise = host.connection.askUserQuestion(requestId, questions);\n const timeoutPromise = new Promise<null>((resolve) => {\n setTimeout(() => resolve(null), QUESTION_TIMEOUT_MS);\n });\n\n const answers = await Promise.race([answerPromise, timeoutPromise]);\n host.connection.emitStatus(\"running\");\n\n if (!answers) {\n return {\n behavior: \"deny\",\n message:\n \"User did not respond to clarifying questions in time. Proceed with your best judgment.\",\n };\n }\n\n return { behavior: \"allow\", updatedInput: { questions: input.questions, answers } };\n };\n}\n\nfunction buildQueryOptions(host: QueryHost, context: TaskContext): Record<string, unknown> {\n const settings = context.agentSettings ?? host.config.agentSettings ?? {};\n const systemPromptText = buildSystemPrompt(host.config.mode, context, host.config, host.setupLog);\n const conveyorMcp = createConveyorMcpServer(host.connection, host.config);\n const isPm = host.config.mode === \"pm\";\n const pmDisallowedTools = isPm ? [\"TodoWrite\", \"TodoRead\", \"NotebookEdit\"] : [];\n const disallowedTools = [...(settings.disallowedTools ?? []), ...pmDisallowedTools];\n const settingSources = (settings.settingSources ?? [\"user\", \"project\"]) as (\n | \"user\"\n | \"project\"\n | \"local\"\n )[];\n\n return {\n model: context.model || host.config.model,\n systemPrompt: {\n type: \"preset\",\n preset: \"claude_code\",\n append: systemPromptText || undefined,\n },\n settingSources,\n cwd: host.config.workspaceDir,\n permissionMode: \"bypassPermissions\",\n allowDangerouslySkipPermissions: true,\n canUseTool: buildCanUseTool(host),\n tools: { type: \"preset\" as const, preset: \"claude_code\" as const },\n mcpServers: { conveyor: conveyorMcp },\n maxTurns: settings.maxTurns,\n effort: settings.effort,\n thinking: settings.thinking,\n betas: settings.betas,\n maxBudgetUsd: settings.maxBudgetUsd ?? 50,\n disallowedTools: disallowedTools.length > 0 ? disallowedTools : undefined,\n enableFileCheckpointing: settings.enableFileCheckpointing,\n };\n}\n\nexport async function runSdkQuery(\n host: QueryHost,\n context: TaskContext,\n followUpContent?: string,\n): Promise<void> {\n if (host.isStopped()) return;\n\n const isPm = host.config.mode === \"pm\";\n if (isPm) {\n host.snapshotPlanFiles();\n }\n\n const options = buildQueryOptions(host, context);\n const resume = context.claudeSessionId ?? undefined;\n\n if (followUpContent) {\n const prompt = isPm\n ? `${buildInitialPrompt(host.config.mode, context)}\\n\\n---\\n\\nThe team says:\\n${followUpContent}`\n : followUpContent;\n\n const agentQuery = query({ prompt, options: { ...options, resume } });\n await runWithRetry(agentQuery, context, host, options);\n } else if (isPm) {\n return;\n } else {\n const initialPrompt = buildInitialPrompt(host.config.mode, context);\n const agentQuery = query({\n prompt: host.createInputStream(initialPrompt),\n options: { ...options, resume },\n });\n await runWithRetry(agentQuery, context, host, options);\n }\n\n if (isPm) {\n host.syncPlanFile();\n }\n}\n\nasync function runWithRetry(\n initialQuery: AsyncGenerator<SDKMessage, void>,\n context: TaskContext,\n host: QueryHost,\n options: Record<string, unknown>,\n): Promise<void> {\n for (let attempt = 0; attempt <= RETRY_DELAYS_MS.length; attempt++) {\n if (host.isStopped()) return;\n\n const agentQuery =\n attempt === 0\n ? initialQuery\n : (() => {\n // New session starts cost from 0 — reset so deltas stay correct (Bug 2)\n context._lastReportedCostUsd = 0;\n return query({\n prompt: host.createInputStream(buildInitialPrompt(host.config.mode, context)),\n options: { ...options, resume: undefined },\n });\n })();\n\n try {\n const { retriable } = await processEvents(agentQuery, context, host);\n if (!retriable || host.isStopped()) return;\n } catch (error) {\n const isStaleSession =\n error instanceof Error && error.message.includes(\"No conversation found with session ID\");\n\n if (isStaleSession && context.claudeSessionId) {\n // Mutate the original context so state changes propagate back to runner.taskContext\n context.claudeSessionId = null;\n context._lastReportedCostUsd = 0;\n host.connection.storeSessionId(\"\");\n const freshQuery = query({\n prompt: host.createInputStream(buildInitialPrompt(host.config.mode, context)),\n options: { ...options, resume: undefined },\n });\n return runWithRetry(freshQuery, context, host, options);\n }\n\n const isApiError = error instanceof Error && API_ERROR_PATTERN.test(error.message);\n if (!isApiError) throw error;\n }\n\n if (attempt >= RETRY_DELAYS_MS.length) {\n host.connection.postChatMessage(\n `Agent shutting down after ${RETRY_DELAYS_MS.length} failed retry attempts due to API errors. ` +\n `The task will resume automatically when the codespace restarts.`,\n );\n return;\n }\n\n const delayMs = RETRY_DELAYS_MS[attempt];\n const delayMin = Math.round(delayMs / 60_000);\n host.connection.postChatMessage(\n `API error encountered. Retrying in ${delayMin} minute${delayMin > 1 ? \"s\" : \"\"}... (attempt ${attempt + 1}/${RETRY_DELAYS_MS.length})`,\n );\n host.connection.sendEvent({\n type: \"error\",\n message: `API error, retrying in ${delayMin}m (${attempt + 1}/${RETRY_DELAYS_MS.length})`,\n });\n host.connection.emitStatus(\"waiting_for_input\");\n await host.callbacks.onStatusChange(\"waiting_for_input\");\n\n await new Promise<void>((resolve) => {\n const timer = setTimeout(resolve, delayMs);\n const checkStopped = setInterval(() => {\n if (host.isStopped()) {\n clearTimeout(timer);\n clearInterval(checkStopped);\n resolve();\n }\n }, 1000);\n setTimeout(() => clearInterval(checkStopped), delayMs + 100);\n });\n\n host.connection.emitStatus(\"running\");\n await host.callbacks.onStatusChange(\"running\");\n }\n}\n","import type { RunnerMode, TaskContext, ChatMessage } from \"./types.js\";\n\nconst ACTIVE_STATUSES = new Set([\"InProgress\", \"ReviewPR\", \"ReviewDev\", \"ReviewLive\"]);\n\nfunction findLastAgentMessageIndex(history: ChatMessage[]): number {\n for (let i = history.length - 1; i >= 0; i--) {\n if (history[i].role === \"assistant\") return i;\n }\n return -1;\n}\n\nfunction detectRelaunchScenario(\n context: TaskContext,\n): \"fresh\" | \"idle_relaunch\" | \"feedback_relaunch\" {\n const lastAgentIdx = findLastAgentMessageIndex(context.chatHistory);\n if (lastAgentIdx === -1) return \"fresh\";\n\n const hasPriorWork =\n !!context.githubPRUrl || !!context.claudeSessionId || ACTIVE_STATUSES.has(context.status ?? \"\");\n if (!hasPriorWork) return \"fresh\";\n\n const messagesAfterAgent = context.chatHistory.slice(lastAgentIdx + 1);\n const hasNewUserMessages = messagesAfterAgent.some((m) => m.role === \"user\");\n return hasNewUserMessages ? \"feedback_relaunch\" : \"idle_relaunch\";\n}\n\nfunction buildRelaunchWithSession(\n mode: RunnerMode | undefined,\n context: TaskContext,\n): string | null {\n const scenario = detectRelaunchScenario(context);\n if (!context.claudeSessionId || scenario === \"fresh\") return null;\n\n const parts: string[] = [];\n const lastAgentIdx = findLastAgentMessageIndex(context.chatHistory);\n\n if (mode === \"pm\") {\n const newMessages = context.chatHistory\n .slice(lastAgentIdx + 1)\n .filter((m) => m.role === \"user\");\n if (newMessages.length > 0) {\n parts.push(\n `You have been relaunched. Here are new messages since your last session:`,\n ...newMessages.map((m) => `[${m.userName ?? \"user\"}]: ${m.content}`),\n );\n } else {\n parts.push(`You have been relaunched. No new messages since your last session.`);\n }\n parts.push(\n `\\nYou are the project manager for this task.`,\n `Review the context above and wait for the team to provide instructions before taking action.`,\n );\n } else if (scenario === \"feedback_relaunch\") {\n const newMessages = context.chatHistory\n .slice(lastAgentIdx + 1)\n .filter((m) => m.role === \"user\");\n parts.push(\n `You have been relaunched with new feedback.`,\n `Work on the git branch \"${context.githubBranch}\". Stay on this branch — do not checkout or create other branches.`,\n `\\nNew messages since your last run:`,\n ...newMessages.map((m) => `[${m.userName ?? \"user\"}]: ${m.content}`),\n `\\nAddress the requested changes. Do NOT re-investigate the codebase from scratch or write a new plan — review the feedback and implement the changes directly.`,\n `Commit and push your updates.`,\n );\n if (context.githubPRUrl) {\n parts.push(\n `An existing PR is open at ${context.githubPRUrl} — push to the same branch. Do NOT create a new PR.`,\n );\n } else {\n parts.push(\n `When finished, use the create_pull_request tool to open a PR. Do NOT use gh CLI.`,\n );\n }\n } else {\n parts.push(\n `You were relaunched but no new instructions have been given since your last run.`,\n `Work on the git branch \"${context.githubBranch}\". Stay on this branch — do not checkout or create other branches.`,\n `Run \\`git log --oneline -10\\` to review what you already committed.`,\n `Review the current state of the codebase and verify everything is working correctly.`,\n `Post a brief status update to the chat, then wait for further instructions.`,\n );\n if (context.githubPRUrl) {\n parts.push(`An existing PR is open at ${context.githubPRUrl}. Do not create a new PR.`);\n }\n }\n\n return parts.join(\"\\n\");\n}\n\nfunction buildTaskBody(context: TaskContext): string[] {\n const parts: string[] = [];\n parts.push(`# Task: ${context.title}`);\n if (context.description) {\n parts.push(`\\n## Description\\n${context.description}`);\n }\n if (context.plan) {\n parts.push(`\\n## Plan\\n${context.plan}`);\n }\n\n if (context.files && context.files.length > 0) {\n parts.push(`\\n## Attached Files`);\n for (const file of context.files) {\n if (file.content && file.contentEncoding === \"utf-8\") {\n // Inline text content directly\n parts.push(`\\n### ${file.fileName} (${file.mimeType})`);\n parts.push(\"```\");\n parts.push(file.content);\n parts.push(\"```\");\n } else if (!file.content) {\n // Fallback to download URL for large/non-embeddable files\n parts.push(`- **${file.fileName}** (${file.mimeType}): ${file.downloadUrl}`);\n }\n // Base64 images are handled via multimodal content blocks in the runner\n }\n }\n\n if (context.repoRefs && context.repoRefs.length > 0) {\n parts.push(`\\n## Repository References`);\n for (const ref of context.repoRefs) {\n const icon = ref.refType === \"folder\" ? \"folder\" : \"file\";\n parts.push(`- [${icon}] \\`${ref.path}\\``);\n }\n }\n\n if (context.chatHistory.length > 0) {\n const relevant = context.chatHistory.slice(-20);\n parts.push(`\\n## Recent Chat Context`);\n for (const msg of relevant) {\n const sender = msg.userName ?? msg.role;\n parts.push(`[${sender}]: ${msg.content}`);\n }\n }\n\n return parts;\n}\n\nfunction buildInstructions(\n mode: RunnerMode | undefined,\n context: TaskContext,\n scenario: \"fresh\" | \"idle_relaunch\" | \"feedback_relaunch\",\n): string[] {\n const parts: string[] = [`\\n## Instructions`];\n const isPm = mode === \"pm\";\n\n if (scenario === \"fresh\") {\n if (isPm) {\n parts.push(\n `You are the project manager for this task.`,\n `The task details are provided above. Wait for the team to ask questions or provide additional requirements before starting to plan.`,\n `When you finish planning, save the plan with update_task, post a summary to chat, and end your turn. A separate task agent will execute the plan after review.`,\n );\n } else {\n parts.push(\n `Begin executing the task plan above immediately.`,\n `Your FIRST action should be reading the relevant source files mentioned in the plan, then writing code. Do NOT run install, build, lint, test, or dev server commands first — the environment is already set up.`,\n `Work on the git branch \"${context.githubBranch}\". Stay on this branch for the entire task. Do not checkout or create other branches.`,\n `Post a brief message to chat when you begin meaningful implementation, and again when the PR is ready.`,\n `When finished, commit your changes, push the branch, and use the create_pull_request tool to open a PR. Do NOT use gh CLI or any other method to create PRs.`,\n );\n }\n } else if (scenario === \"idle_relaunch\") {\n if (isPm) {\n parts.push(\n `You were relaunched but no new instructions have been given since your last run.`,\n `You are the project manager for this task.`,\n `Wait for the team to provide instructions before taking action.`,\n );\n } else {\n parts.push(\n `You were relaunched but no new instructions have been given since your last run.`,\n `Work on the git branch \"${context.githubBranch}\". Stay on this branch — do not checkout or create other branches.`,\n `Run \\`git log --oneline -10\\` to review what you already committed, then verify the current state is correct.`,\n `Post a brief status update to the chat summarizing where things stand.`,\n `Then wait for further instructions — do NOT redo work that was already completed.`,\n );\n if (context.githubPRUrl) {\n parts.push(`An existing PR is open at ${context.githubPRUrl}. Do not create a new PR.`);\n }\n }\n } else {\n const lastAgentIdx = findLastAgentMessageIndex(context.chatHistory);\n const newMessages = context.chatHistory\n .slice(lastAgentIdx + 1)\n .filter((m) => m.role === \"user\");\n if (isPm) {\n parts.push(\n `You were relaunched with new feedback since your last run.`,\n `You are the project manager for this task.`,\n `\\nNew messages since your last run:`,\n ...newMessages.map((m) => `[${m.userName ?? \"user\"}]: ${m.content}`),\n `\\nReview these messages and wait for the team to provide instructions before taking action.`,\n );\n } else {\n parts.push(\n `You have been relaunched to address feedback on your previous work.`,\n `Work on the git branch \"${context.githubBranch}\". Stay on this branch — do not checkout or create other branches.`,\n `Start by running \\`git log --oneline -10\\` and \\`git diff HEAD~3 HEAD --stat\\` to review what you already committed.`,\n `\\nNew messages since your last run:`,\n ...newMessages.map((m) => `[${m.userName ?? \"user\"}]: ${m.content}`),\n `\\nAddress the requested changes directly. Do NOT re-investigate the codebase from scratch or write a new plan — go straight to implementing the feedback.`,\n `Commit and push your updates.`,\n );\n if (context.githubPRUrl) {\n parts.push(\n `An existing PR is open at ${context.githubPRUrl} — push to the same branch to update it. Do NOT create a new PR.`,\n );\n } else {\n parts.push(\n `When finished, use the create_pull_request tool to open a PR. Do NOT use gh CLI or any other method to create PRs.`,\n );\n }\n }\n }\n\n return parts;\n}\n\nexport function buildInitialPrompt(mode: RunnerMode | undefined, context: TaskContext): string {\n const sessionRelaunch = buildRelaunchWithSession(mode, context);\n if (sessionRelaunch) return sessionRelaunch;\n\n const scenario = detectRelaunchScenario(context);\n const body = buildTaskBody(context);\n const instructions = buildInstructions(mode, context, scenario);\n return [...body, ...instructions].join(\"\\n\");\n}\n\nexport function buildSystemPrompt(\n mode: RunnerMode | undefined,\n context: TaskContext,\n config: { instructions: string; workspaceDir: string },\n setupLog: string[],\n): string {\n const isPm = mode === \"pm\";\n const parts = isPm\n ? [\n `You are an AI project manager helping to plan tasks for the \"${context.title}\" project.`,\n `You are running locally with full access to the repository.`,\n `You can read files, search code, and run shell commands (e.g. git log, git diff) to understand the codebase. You cannot write or edit files.`,\n `\\nEnvironment (ready, no setup required):`,\n `- Repository is cloned at your current working directory.`,\n `- You can read files and run git commands to understand the codebase before writing task plans.`,\n `- Check the dev branch (e.g. run: git fetch && git checkout dev || git checkout main) to understand the current state of the codebase that agents will branch off of.`,\n `\\nWorkflow:`,\n `- You can draft and iterate on plans in .claude/plans/*.md — these files are automatically synced to the task.`,\n `- You can also use update_task directly to save the plan to the task.`,\n `- After saving the plan, post a summary to chat and end your turn. Do NOT attempt to execute the plan yourself.`,\n `- A separate task agent will handle execution after the team reviews and approves your plan.`,\n ]\n : [\n `You are an AI agent working on a task for the \"${context.title}\" project.`,\n `You are running inside a GitHub Codespace with full access to the repository.`,\n `\\nEnvironment (fully ready — do NOT verify or set up):`,\n `- Repository is cloned at your current working directory.`,\n `- Branch \\`${context.githubBranch}\\` is already checked out.`,\n `- All dependencies are installed, database is migrated, and the dev server is running.`,\n `- Git is configured. Commit and push directly to this branch.`,\n `\\nIMPORTANT — Skip all environment verification. Do NOT run any of the following:`,\n `- bun/npm install, pip install, or any dependency installation`,\n `- bun build, bun lint, bun test, bun typecheck, or any build/check commands as a \"first step\"`,\n `- bun db:generate, bun db:push, prisma migrate, or any database setup`,\n `- bun dev, npm start, or any dev server startup commands`,\n `- pwd, ls, echo, or exploratory shell commands to \"check\" the environment`,\n `Only run these if you encounter a specific error that requires it.`,\n `Start reading the task plan and writing code immediately.`,\n `\\nGit safety — STRICT rules:`,\n `- NEVER run \\`git checkout main\\`, \\`git checkout dev\\`, or switch to any branch other than \\`${context.githubBranch}\\`.`,\n `- NEVER create new branches (no \\`git checkout -b\\`, \\`git switch -c\\`, etc.).`,\n `- This branch was created from \\`${context.baseBranch}\\`. PRs will automatically target that branch.`,\n `- If \\`git push\\` fails with \"non-fast-forward\" or similar, run \\`git pull --rebase origin ${context.githubBranch}\\` and retry. If that also fails, use \\`git push --force-with-lease origin ${context.githubBranch}\\`.`,\n `- If you encounter merge conflicts during rebase, resolve them in place — do NOT abandon the branch.`,\n ];\n\n if (setupLog.length > 0) {\n parts.push(\n `\\nEnvironment setup log (already executed before you started — proof that setup succeeded):`,\n \"```\",\n ...setupLog,\n \"```\",\n );\n }\n\n if (context.agentInstructions) {\n parts.push(`\\nAgent Instructions:\\n${context.agentInstructions}`);\n }\n if (config.instructions) {\n parts.push(`\\nAdditional Instructions:\\n${config.instructions}`);\n }\n parts.push(\n `\\nYou have access to Conveyor MCP tools to interact with the task management system.`,\n `Use the post_to_chat tool to communicate progress or ask questions.`,\n `Use the read_task_chat tool to check for new messages from the team.`,\n );\n if (!isPm) {\n parts.push(\n `Use the create_pull_request tool to open PRs — do NOT use gh CLI or shell commands for PR creation.`,\n );\n }\n return parts.join(\"\\n\");\n}\n","import { tool, createSdkMcpServer } from \"@anthropic-ai/claude-agent-sdk\";\nimport { z } from \"zod\";\nimport type { ConveyorConnection } from \"./connection.js\";\nimport type { AgentRunnerConfig } from \"./types.js\";\n\nfunction buildCommonTools(connection: ConveyorConnection, config: AgentRunnerConfig) {\n return [\n tool(\n \"read_task_chat\",\n \"Read recent messages from the task chat to see team feedback or instructions\",\n {\n limit: z.number().optional().describe(\"Number of recent messages to fetch (default 20)\"),\n },\n async ({ limit }) => {\n try {\n const messages = await connection.fetchChatMessages(limit);\n return textResult(JSON.stringify(messages, null, 2));\n } catch {\n return textResult(\n JSON.stringify({\n note: \"Could not fetch live chat. Chat history was provided in the initial context.\",\n }),\n );\n }\n },\n { annotations: { readOnlyHint: true } },\n ),\n tool(\n \"post_to_chat\",\n \"Post a message to the task chat visible to all team members\",\n { message: z.string().describe(\"The message to post to the team\") },\n ({ message }) => {\n connection.postChatMessage(message);\n return Promise.resolve(textResult(\"Message posted to task chat.\"));\n },\n ),\n tool(\n \"update_task_status\",\n \"Update the task status on the Kanban board\",\n {\n status: z\n .enum([\"InProgress\", \"ReviewPR\", \"Complete\"])\n .describe(\"The new status for the task\"),\n },\n ({ status }) => {\n connection.updateStatus(status);\n return Promise.resolve(textResult(`Task status updated to ${status}.`));\n },\n ),\n tool(\n \"get_task_plan\",\n \"Re-read the latest task plan in case it was updated\",\n {},\n async () => {\n try {\n const ctx = await connection.fetchTaskContext();\n return textResult(ctx.plan ?? \"No plan available.\");\n } catch {\n return textResult(`Task ID: ${config.taskId} - could not fetch updated plan.`);\n }\n },\n { annotations: { readOnlyHint: true } },\n ),\n ];\n}\n\nfunction buildPmTools(connection: ConveyorConnection) {\n return [\n tool(\n \"update_task\",\n \"Save the finalized task plan and/or description\",\n {\n plan: z.string().optional().describe(\"The task plan in markdown\"),\n description: z.string().optional().describe(\"Updated task description\"),\n },\n async ({ plan, description }) => {\n try {\n await Promise.resolve(connection.updateTaskFields({ plan, description }));\n return textResult(\"Task updated successfully.\");\n } catch {\n return textResult(\"Failed to update task.\");\n }\n },\n ),\n tool(\n \"create_subtask\",\n \"Create a subtask under the current parent task. Use for breaking complex tasks into smaller pieces.\",\n {\n title: z.string().describe(\"Subtask title\"),\n description: z.string().optional().describe(\"Brief description\"),\n plan: z.string().optional().describe(\"Implementation plan in markdown\"),\n ordinal: z.number().optional().describe(\"Step/order number (0-based)\"),\n storyPointValue: z\n .number()\n .optional()\n .describe(\"Story point value (1=Common, 2=Magic, 3=Rare, 5=Unique)\"),\n },\n async (params) => {\n try {\n const result = await connection.createSubtask(params);\n return textResult(`Subtask created with ID: ${result.id}`);\n } catch (error) {\n return textResult(\n `Failed to create subtask: ${error instanceof Error ? error.message : \"Unknown error\"}`,\n );\n }\n },\n ),\n tool(\n \"update_subtask\",\n \"Update an existing subtask's fields\",\n {\n subtaskId: z.string().describe(\"The subtask ID to update\"),\n title: z.string().optional(),\n description: z.string().optional(),\n plan: z.string().optional(),\n ordinal: z.number().optional(),\n storyPointValue: z.number().optional(),\n },\n async ({ subtaskId, ...fields }) => {\n try {\n await Promise.resolve(connection.updateSubtask(subtaskId, fields));\n return textResult(\"Subtask updated.\");\n } catch (error) {\n return textResult(`Failed: ${error instanceof Error ? error.message : \"Unknown error\"}`);\n }\n },\n ),\n tool(\n \"delete_subtask\",\n \"Delete a subtask\",\n { subtaskId: z.string().describe(\"The subtask ID to delete\") },\n async ({ subtaskId }) => {\n try {\n await Promise.resolve(connection.deleteSubtask(subtaskId));\n return textResult(\"Subtask deleted.\");\n } catch (error) {\n return textResult(`Failed: ${error instanceof Error ? error.message : \"Unknown error\"}`);\n }\n },\n ),\n tool(\n \"list_subtasks\",\n \"List all subtasks under the current parent task\",\n {},\n async () => {\n try {\n const subtasks = await connection.listSubtasks();\n return textResult(JSON.stringify(subtasks, null, 2));\n } catch {\n return textResult(\"Failed to list subtasks.\");\n }\n },\n { annotations: { readOnlyHint: true } },\n ),\n ];\n}\n\nfunction buildTaskTools(connection: ConveyorConnection) {\n return [\n tool(\n \"create_pull_request\",\n \"Create a GitHub pull request for this task. Use this instead of gh CLI or git commands to create PRs.\",\n {\n title: z.string().describe(\"The PR title\"),\n body: z.string().describe(\"The PR description/body in markdown\"),\n },\n async ({ title, body }) => {\n try {\n const result = await connection.createPR({ title, body });\n connection.sendEvent({\n type: \"pr_created\",\n url: result.url,\n number: result.number,\n });\n return textResult(`Pull request #${result.number} created: ${result.url}`);\n } catch (error) {\n const msg = error instanceof Error ? error.message : \"Unknown error\";\n return textResult(`Failed to create pull request: ${msg}`);\n }\n },\n ),\n ];\n}\n\nfunction textResult(text: string): { content: { type: \"text\"; text: string }[] } {\n return { content: [{ type: \"text\" as const, text }] };\n}\n\n// oxlint-disable-next-line typescript/explicit-function-return-type\nexport function createConveyorMcpServer(connection: ConveyorConnection, config: AgentRunnerConfig) {\n const commonTools = buildCommonTools(connection, config);\n const modeTools = config.mode === \"pm\" ? buildPmTools(connection) : buildTaskTools(connection);\n\n return createSdkMcpServer({\n name: \"conveyor\",\n tools: [...commonTools, ...modeTools],\n });\n}\n","import { io, type Socket } from \"socket.io-client\";\n\nexport interface ProjectConnectionConfig {\n apiUrl: string;\n projectToken: string;\n projectId: string;\n}\n\nexport interface TaskAssignment {\n taskId: string;\n taskToken: string;\n apiUrl: string;\n mode: string;\n branch: string;\n devBranch: string;\n}\n\nexport class ProjectConnection {\n private socket: Socket | null = null;\n private config: ProjectConnectionConfig;\n private taskAssignmentCallback: ((assignment: TaskAssignment) => void) | null = null;\n private stopTaskCallback: ((data: { taskId: string }) => void) | null = null;\n private shutdownCallback: (() => void) | null = null;\n\n constructor(config: ProjectConnectionConfig) {\n this.config = config;\n }\n\n connect(): Promise<void> {\n return new Promise((resolve, reject) => {\n let settled = false;\n let attempts = 0;\n const maxInitialAttempts = 30;\n\n this.socket = io(this.config.apiUrl, {\n auth: { projectToken: this.config.projectToken },\n transports: [\"websocket\"],\n reconnection: true,\n reconnectionAttempts: Infinity,\n reconnectionDelay: 2000,\n reconnectionDelayMax: 30000,\n randomizationFactor: 0.3,\n extraHeaders: {\n \"ngrok-skip-browser-warning\": \"true\",\n },\n });\n\n this.socket.on(\"projectRunner:assignTask\", (data: TaskAssignment) => {\n if (this.taskAssignmentCallback) {\n this.taskAssignmentCallback(data);\n }\n });\n\n this.socket.on(\"projectRunner:stopTask\", (data: { taskId: string }) => {\n if (this.stopTaskCallback) {\n this.stopTaskCallback(data);\n }\n });\n\n this.socket.on(\"projectRunner:shutdown\", () => {\n if (this.shutdownCallback) {\n this.shutdownCallback();\n }\n });\n\n this.socket.on(\"connect\", () => {\n if (!settled) {\n settled = true;\n resolve();\n }\n });\n\n this.socket.io.on(\"reconnect_attempt\", () => {\n attempts++;\n if (!settled && attempts >= maxInitialAttempts) {\n settled = true;\n reject(new Error(`Failed to connect after ${maxInitialAttempts} attempts`));\n }\n });\n });\n }\n\n onTaskAssignment(callback: (assignment: TaskAssignment) => void): void {\n this.taskAssignmentCallback = callback;\n }\n\n onStopTask(callback: (data: { taskId: string }) => void): void {\n this.stopTaskCallback = callback;\n }\n\n onShutdown(callback: () => void): void {\n this.shutdownCallback = callback;\n }\n\n sendHeartbeat(): void {\n if (!this.socket) return;\n this.socket.emit(\"projectRunner:heartbeat\", {});\n }\n\n emitTaskStarted(taskId: string): void {\n if (!this.socket) return;\n this.socket.emit(\"projectRunner:taskStarted\", { taskId });\n }\n\n emitTaskStopped(taskId: string, reason: string): void {\n if (!this.socket) return;\n this.socket.emit(\"projectRunner:taskStopped\", { taskId, reason });\n }\n\n disconnect(): void {\n this.socket?.disconnect();\n this.socket = null;\n }\n}\n","/* oxlint-disable no-console */\n\nimport { fork, type ChildProcess } from \"node:child_process\";\nimport { execSync } from \"node:child_process\";\nimport * as path from \"node:path\";\nimport { fileURLToPath } from \"node:url\";\nimport { ProjectConnection, type TaskAssignment } from \"./project-connection.js\";\nimport { ensureWorktree, removeWorktree } from \"./worktree.js\";\n\nconst __filename = fileURLToPath(import.meta.url);\nconst __dirname = path.dirname(__filename);\n\nexport interface ProjectRunnerConfig {\n conveyorApiUrl: string;\n projectToken: string;\n projectId: string;\n projectDir: string;\n}\n\ninterface ActiveAgent {\n process: ChildProcess;\n worktreePath: string;\n mode: string;\n}\n\nconst HEARTBEAT_INTERVAL_MS = 30_000;\nconst MAX_CONCURRENT = 3;\nconst STOP_TIMEOUT_MS = 30_000;\n\nexport class ProjectRunner {\n private connection: ProjectConnection;\n private projectDir: string;\n private activeAgents = new Map<string, ActiveAgent>();\n private heartbeatTimer: ReturnType<typeof setInterval> | null = null;\n private stopping = false;\n private resolveLifecycle: (() => void) | null = null;\n\n constructor(config: ProjectRunnerConfig) {\n this.projectDir = config.projectDir;\n this.connection = new ProjectConnection({\n apiUrl: config.conveyorApiUrl,\n projectToken: config.projectToken,\n projectId: config.projectId,\n });\n }\n\n async start(): Promise<void> {\n await this.connection.connect();\n\n this.connection.onTaskAssignment((assignment) => {\n void this.handleAssignment(assignment);\n });\n\n this.connection.onStopTask((data) => {\n this.handleStopTask(data.taskId);\n });\n\n this.connection.onShutdown(() => {\n console.log(\"[project-runner] Received shutdown signal from server\");\n void this.stop();\n });\n\n this.heartbeatTimer = setInterval(() => {\n this.connection.sendHeartbeat();\n }, HEARTBEAT_INTERVAL_MS);\n\n console.log(\"[project-runner] Connected, waiting for task assignments...\");\n\n // Keep process alive until stop() is called\n await new Promise<void>((resolve) => {\n this.resolveLifecycle = resolve;\n process.on(\"SIGTERM\", () => void this.stop());\n process.on(\"SIGINT\", () => void this.stop());\n });\n }\n\n private async handleAssignment(assignment: TaskAssignment): Promise<void> {\n const { taskId, taskToken, apiUrl, mode, branch, devBranch } = assignment;\n const shortId = taskId.slice(0, 8);\n\n if (this.activeAgents.has(taskId)) {\n console.log(`[project-runner] Task ${shortId} already running, skipping`);\n return;\n }\n\n if (this.activeAgents.size >= MAX_CONCURRENT) {\n console.log(\n `[project-runner] Max concurrent agents (${MAX_CONCURRENT}) reached, rejecting task ${shortId}`,\n );\n this.connection.emitTaskStopped(taskId, \"max_concurrent_reached\");\n return;\n }\n\n try {\n // Fetch latest refs\n try {\n execSync(\"git fetch origin\", { cwd: this.projectDir, stdio: \"ignore\" });\n } catch {\n console.log(`[task:${shortId}] Warning: git fetch failed`);\n }\n\n // Create worktree with devBranch as base\n const worktreePath = ensureWorktree(this.projectDir, taskId, devBranch);\n\n // Checkout task branch if provided\n if (branch && branch !== devBranch) {\n try {\n execSync(`git checkout ${branch}`, { cwd: worktreePath, stdio: \"ignore\" });\n } catch {\n try {\n execSync(`git checkout -b ${branch}`, { cwd: worktreePath, stdio: \"ignore\" });\n } catch {\n console.log(`[task:${shortId}] Warning: could not checkout branch ${branch}`);\n }\n }\n }\n\n // Resolve CLI entry point\n const cliPath = path.resolve(__dirname, \"cli.js\");\n\n // Strip project-runner env vars so the child enters per-task agent mode\n const childEnv = { ...process.env };\n delete childEnv.CONVEYOR_PROJECT_TOKEN;\n delete childEnv.CONVEYOR_PROJECT_ID;\n\n const child = fork(cliPath, [], {\n env: {\n ...childEnv,\n CONVEYOR_API_URL: apiUrl,\n CONVEYOR_TASK_TOKEN: taskToken,\n CONVEYOR_TASK_ID: taskId,\n CONVEYOR_MODE: mode,\n CONVEYOR_WORKSPACE: worktreePath,\n CONVEYOR_USE_WORKTREE: \"false\",\n },\n cwd: worktreePath,\n stdio: [\"pipe\", \"pipe\", \"pipe\", \"ipc\"],\n });\n\n // Prefix child output\n child.stdout?.on(\"data\", (data: Buffer) => {\n const lines = data.toString().trimEnd().split(\"\\n\");\n for (const line of lines) {\n console.log(`[task:${shortId}] ${line}`);\n }\n });\n child.stderr?.on(\"data\", (data: Buffer) => {\n const lines = data.toString().trimEnd().split(\"\\n\");\n for (const line of lines) {\n console.error(`[task:${shortId}] ${line}`);\n }\n });\n\n this.activeAgents.set(taskId, { process: child, worktreePath, mode });\n this.connection.emitTaskStarted(taskId);\n\n console.log(`[project-runner] Started task ${shortId} in ${mode} mode at ${worktreePath}`);\n\n child.on(\"exit\", (code) => {\n this.activeAgents.delete(taskId);\n const reason = code === 0 ? \"completed\" : `exited with code ${code}`;\n this.connection.emitTaskStopped(taskId, reason);\n console.log(`[project-runner] Task ${shortId} ${reason}`);\n\n // Clean up worktree on success\n if (code === 0) {\n try {\n removeWorktree(this.projectDir, taskId);\n } catch {\n // best effort\n }\n }\n });\n } catch (error) {\n console.error(\n `[project-runner] Failed to start task ${shortId}:`,\n error instanceof Error ? error.message : error,\n );\n this.connection.emitTaskStopped(\n taskId,\n `start_failed: ${error instanceof Error ? error.message : \"Unknown\"}`,\n );\n }\n }\n\n private handleStopTask(taskId: string): void {\n const agent = this.activeAgents.get(taskId);\n if (!agent) return;\n\n const shortId = taskId.slice(0, 8);\n console.log(`[project-runner] Stopping task ${shortId}`);\n\n agent.process.kill(\"SIGTERM\");\n\n // Force kill after timeout\n const timer = setTimeout(() => {\n if (this.activeAgents.has(taskId)) {\n agent.process.kill(\"SIGKILL\");\n }\n }, STOP_TIMEOUT_MS);\n\n agent.process.on(\"exit\", () => {\n clearTimeout(timer);\n try {\n removeWorktree(this.projectDir, taskId);\n } catch {\n // best effort\n }\n });\n }\n\n async stop(): Promise<void> {\n if (this.stopping) return;\n this.stopping = true;\n\n console.log(\"[project-runner] Shutting down...\");\n\n if (this.heartbeatTimer) {\n clearInterval(this.heartbeatTimer);\n this.heartbeatTimer = null;\n }\n\n // Stop all active agents\n const stopPromises = [...this.activeAgents.keys()].map(\n (taskId) =>\n new Promise<void>((resolve) => {\n const agent = this.activeAgents.get(taskId);\n if (!agent) {\n resolve();\n return;\n }\n agent.process.on(\"exit\", () => {\n resolve();\n });\n this.handleStopTask(taskId);\n }),\n );\n\n // Wait for all agents with global timeout\n await Promise.race([\n Promise.all(stopPromises),\n new Promise<void>((resolve) => setTimeout(resolve, 60_000)),\n ]);\n\n this.connection.disconnect();\n console.log(\"[project-runner] Shutdown complete\");\n\n if (this.resolveLifecycle) {\n this.resolveLifecycle();\n this.resolveLifecycle = null;\n }\n }\n}\n"],"mappings":"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","names":["resolve","resolve","execSync","join","execSync","join","resolve","execSync","resolve","join","io","resolve","execSync","HEARTBEAT_INTERVAL_MS","resolve","execSync"]}
package/dist/cli.js CHANGED
@@ -2,7 +2,7 @@
2
2
  import {
3
3
  AgentRunner,
4
4
  ProjectRunner
5
- } from "./chunk-N6QGELGE.js";
5
+ } from "./chunk-7XJAQPDE.js";
6
6
 
7
7
  // src/cli.ts
8
8
  var CONVEYOR_API_URL = process.env.CONVEYOR_API_URL;
package/dist/index.js CHANGED
@@ -8,7 +8,7 @@ import {
8
8
  removeWorktree,
9
9
  runSetupCommand,
10
10
  runStartCommand
11
- } from "./chunk-N6QGELGE.js";
11
+ } from "./chunk-7XJAQPDE.js";
12
12
 
13
13
  // src/file-cache.ts
14
14
  var DEFAULT_MAX_SIZE_BYTES = 50 * 1024 * 1024;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@rallycry/conveyor-agent",
3
- "version": "2.14.1",
3
+ "version": "2.14.2",
4
4
  "description": "Conveyor cloud build agent runner - executes task plans inside GitHub Codespaces",
5
5
  "keywords": [
6
6
  "agent",