@rallycry/conveyor-agent 2.0.0 → 2.1.0
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.
|
@@ -6,6 +6,10 @@ var ConveyorConnection = class _ConveyorConnection {
|
|
|
6
6
|
eventBuffer = [];
|
|
7
7
|
flushTimer = null;
|
|
8
8
|
static EVENT_BATCH_MS = 500;
|
|
9
|
+
earlyMessages = [];
|
|
10
|
+
earlyStop = false;
|
|
11
|
+
chatMessageCallback = null;
|
|
12
|
+
stopCallback = null;
|
|
9
13
|
constructor(config) {
|
|
10
14
|
this.config = config;
|
|
11
15
|
}
|
|
@@ -26,6 +30,20 @@ var ConveyorConnection = class _ConveyorConnection {
|
|
|
26
30
|
"ngrok-skip-browser-warning": "true"
|
|
27
31
|
}
|
|
28
32
|
});
|
|
33
|
+
this.socket.on("agentRunner:incomingMessage", (msg) => {
|
|
34
|
+
if (this.chatMessageCallback) {
|
|
35
|
+
this.chatMessageCallback(msg);
|
|
36
|
+
} else {
|
|
37
|
+
this.earlyMessages.push(msg);
|
|
38
|
+
}
|
|
39
|
+
});
|
|
40
|
+
this.socket.on("agentRunner:stop", () => {
|
|
41
|
+
if (this.stopCallback) {
|
|
42
|
+
this.stopCallback();
|
|
43
|
+
} else {
|
|
44
|
+
this.earlyStop = true;
|
|
45
|
+
}
|
|
46
|
+
});
|
|
29
47
|
this.socket.on("connect", () => {
|
|
30
48
|
if (!settled) {
|
|
31
49
|
settled = true;
|
|
@@ -41,6 +59,23 @@ var ConveyorConnection = class _ConveyorConnection {
|
|
|
41
59
|
});
|
|
42
60
|
});
|
|
43
61
|
}
|
|
62
|
+
fetchChatMessages(limit) {
|
|
63
|
+
const socket = this.socket;
|
|
64
|
+
if (!socket) throw new Error("Not connected");
|
|
65
|
+
return new Promise((resolve, reject) => {
|
|
66
|
+
socket.emit(
|
|
67
|
+
"agentRunner:getChatMessages",
|
|
68
|
+
{ taskId: this.config.taskId, limit },
|
|
69
|
+
(response) => {
|
|
70
|
+
if (response.success && response.data) {
|
|
71
|
+
resolve(response.data);
|
|
72
|
+
} else {
|
|
73
|
+
reject(new Error(response.error ?? "Failed to fetch chat messages"));
|
|
74
|
+
}
|
|
75
|
+
}
|
|
76
|
+
);
|
|
77
|
+
});
|
|
78
|
+
}
|
|
44
79
|
fetchTaskContext() {
|
|
45
80
|
const socket = this.socket;
|
|
46
81
|
if (!socket) throw new Error("Not connected");
|
|
@@ -122,10 +157,18 @@ var ConveyorConnection = class _ConveyorConnection {
|
|
|
122
157
|
});
|
|
123
158
|
}
|
|
124
159
|
onChatMessage(callback) {
|
|
125
|
-
this.
|
|
160
|
+
this.chatMessageCallback = callback;
|
|
161
|
+
for (const msg of this.earlyMessages) {
|
|
162
|
+
callback(msg);
|
|
163
|
+
}
|
|
164
|
+
this.earlyMessages = [];
|
|
126
165
|
}
|
|
127
166
|
onStopRequested(callback) {
|
|
128
|
-
this.
|
|
167
|
+
this.stopCallback = callback;
|
|
168
|
+
if (this.earlyStop) {
|
|
169
|
+
callback();
|
|
170
|
+
this.earlyStop = false;
|
|
171
|
+
}
|
|
129
172
|
}
|
|
130
173
|
trackSpending(params) {
|
|
131
174
|
if (!this.socket) throw new Error("Not connected");
|
|
@@ -396,6 +439,7 @@ var AgentRunner = class _AgentRunner {
|
|
|
396
439
|
const hasNewUserMessages = messagesAfterAgent.some((m) => m.role === "user");
|
|
397
440
|
return hasNewUserMessages ? "feedback_relaunch" : "idle_relaunch";
|
|
398
441
|
}
|
|
442
|
+
// eslint-disable-next-line max-lines-per-function
|
|
399
443
|
buildInitialPrompt(context) {
|
|
400
444
|
const parts = [];
|
|
401
445
|
const scenario = this.detectRelaunchScenario(context);
|
|
@@ -445,6 +489,21 @@ ${context.description}`);
|
|
|
445
489
|
## Plan
|
|
446
490
|
${context.plan}`);
|
|
447
491
|
}
|
|
492
|
+
if (context.files && context.files.length > 0) {
|
|
493
|
+
parts.push(`
|
|
494
|
+
## Attached Files`);
|
|
495
|
+
for (const file of context.files) {
|
|
496
|
+
parts.push(`- **${file.fileName}** (${file.mimeType}): ${file.downloadUrl}`);
|
|
497
|
+
}
|
|
498
|
+
}
|
|
499
|
+
if (context.repoRefs && context.repoRefs.length > 0) {
|
|
500
|
+
parts.push(`
|
|
501
|
+
## Repository References`);
|
|
502
|
+
for (const ref of context.repoRefs) {
|
|
503
|
+
const icon = ref.refType === "folder" ? "folder" : "file";
|
|
504
|
+
parts.push(`- [${icon}] \`${ref.path}\``);
|
|
505
|
+
}
|
|
506
|
+
}
|
|
448
507
|
if (context.chatHistory.length > 0) {
|
|
449
508
|
const relevant = context.chatHistory.slice(-20);
|
|
450
509
|
parts.push(`
|
|
@@ -580,14 +639,17 @@ You have access to Conveyor MCP tools to interact with the task management syste
|
|
|
580
639
|
{
|
|
581
640
|
limit: z.number().optional().describe("Number of recent messages to fetch (default 20)")
|
|
582
641
|
},
|
|
583
|
-
(
|
|
584
|
-
|
|
585
|
-
|
|
642
|
+
async ({ limit }) => {
|
|
643
|
+
try {
|
|
644
|
+
const messages = await connection.fetchChatMessages(limit);
|
|
645
|
+
return textResult(JSON.stringify(messages, null, 2));
|
|
646
|
+
} catch {
|
|
647
|
+
return textResult(
|
|
586
648
|
JSON.stringify({
|
|
587
|
-
note: "Chat history was provided in the initial context.
|
|
649
|
+
note: "Could not fetch live chat. Chat history was provided in the initial context."
|
|
588
650
|
})
|
|
589
|
-
)
|
|
590
|
-
|
|
651
|
+
);
|
|
652
|
+
}
|
|
591
653
|
},
|
|
592
654
|
{ annotations: { readOnly: true } }
|
|
593
655
|
),
|
|
@@ -870,4 +932,4 @@ export {
|
|
|
870
932
|
runStartCommand,
|
|
871
933
|
AgentRunner
|
|
872
934
|
};
|
|
873
|
-
//# sourceMappingURL=chunk-
|
|
935
|
+
//# sourceMappingURL=chunk-COCSEUDC.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../src/connection.ts","../src/setup.ts","../src/runner.ts"],"sourcesContent":["import { io, type Socket } from \"socket.io-client\";\nimport type { AgentRunnerConfig, TaskContext, AgentEvent } from \"./types.js\";\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: { content: string; userId: string }[] = [];\n private earlyStop = false;\n private chatMessageCallback: ((msg: { content: string; userId: string }) => void) | null = null;\n private stopCallback: (() => void) | null = null;\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 },\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(\"agentRunner:incomingMessage\", (msg: { content: string; userId: string }) => {\n if (this.chatMessageCallback) {\n this.chatMessageCallback(msg);\n } else {\n this.earlyMessages.push(msg);\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(\"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 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(callback: (message: { content: string; userId: string }) => void): 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 sendTypingStart(): void {\n this.sendEvent({ type: \"agent_typing_start\" });\n }\n\n sendTypingStop(): void {\n this.sendEvent({ type: \"agent_typing_stop\" });\n }\n\n disconnect(): void {\n this.flushEvents();\n this.socket?.disconnect();\n this.socket = null;\n }\n}\n","import { 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","// oxlint-disable max-lines\nimport { execSync } from \"node:child_process\";\nimport {\n query,\n tool,\n createSdkMcpServer,\n type SDKMessage,\n type SDKUserMessage,\n} from \"@anthropic-ai/claude-agent-sdk\";\nimport { z } from \"zod\";\nimport type {\n AgentRunnerConfig,\n AgentRunnerCallbacks,\n TaskContext,\n ActivityEventSummary,\n} from \"./types.js\";\nimport { ConveyorConnection } from \"./connection.js\";\nimport {\n loadConveyorConfig,\n loadForwardPorts,\n runSetupCommand,\n runStartCommand,\n type ConveyorConfig,\n} from \"./setup.js\";\n\nexport class AgentRunner {\n private config: AgentRunnerConfig;\n private connection: ConveyorConnection;\n private callbacks: AgentRunnerCallbacks;\n private stopped = false;\n private inputResolver: ((msg: SDKUserMessage) => void) | null = null;\n private pendingMessages: SDKUserMessage[] = [];\n private currentTurnToolCalls: ActivityEventSummary[] = [];\n private setupLog: string[] = [];\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 async start(): Promise<void> {\n await this.callbacks.onStatusChange(\"connecting\");\n await this.connection.connect();\n\n this.connection.onStopRequested(() => {\n this.stopped = true;\n });\n\n this.connection.onChatMessage((message) => {\n this.injectHumanMessage(message.content);\n });\n\n this.connection.sendEvent({\n type: \"connected\",\n taskId: this.config.taskId,\n });\n\n if (process.env.CODESPACES === \"true\") {\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 await this.runProjectSetup();\n }\n\n this.initRtk();\n\n await this.callbacks.onStatusChange(\"fetching_context\");\n const context = await this.connection.fetchTaskContext();\n\n await this.callbacks.onStatusChange(\"running\");\n\n try {\n await this.executeTask(context);\n } catch (error) {\n const message = error instanceof Error ? error.message : \"Unknown error\";\n this.connection.sendEvent({ type: \"error\", message });\n await this.callbacks.onEvent({ type: \"error\", message });\n throw error;\n } finally {\n await this.callbacks.onStatusChange(\"finished\");\n this.connection.disconnect();\n }\n }\n\n private async runProjectSetup(): Promise<void> {\n await this.callbacks.onStatusChange(\"setup\");\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;\n }\n\n try {\n await this.executeSetupConfig(config);\n this.connection.sendEvent({ type: \"setup_complete\" });\n await this.callbacks.onEvent({ type: \"setup_complete\" });\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 throw error;\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(content: string): void {\n const msg: 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 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 async *createInputStream(\n initialPrompt: string,\n ): AsyncGenerator<SDKUserMessage, void, unknown> {\n yield {\n type: \"user\" as const,\n session_id: \"\",\n message: { role: \"user\" as const, content: initialPrompt },\n parent_tool_use_id: null,\n };\n\n while (!this.stopped) {\n if (this.pendingMessages.length > 0) {\n const next = this.pendingMessages.shift();\n if (next) {\n yield next;\n }\n continue;\n }\n\n await this.callbacks.onStatusChange(\"waiting_for_input\");\n const msg = await new Promise<SDKUserMessage | null>((resolve) => {\n this.inputResolver = resolve as (msg: SDKUserMessage) => void;\n\n const checkStopped = setInterval(() => {\n if (this.stopped) {\n clearInterval(checkStopped);\n this.inputResolver = null;\n resolve(null);\n }\n }, 1000);\n });\n\n if (!msg) break;\n await this.callbacks.onStatusChange(\"running\");\n yield msg;\n }\n }\n\n private findLastAgentMessageIndex(history: TaskContext[\"chatHistory\"]): 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\n private detectRelaunchScenario(\n context: TaskContext,\n ): \"fresh\" | \"idle_relaunch\" | \"feedback_relaunch\" {\n const lastAgentIdx = this.findLastAgentMessageIndex(context.chatHistory);\n if (lastAgentIdx === -1) return \"fresh\";\n\n const hasPriorWork = !!context.githubPRUrl || !!context.claudeSessionId;\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\n // eslint-disable-next-line max-lines-per-function\n private buildInitialPrompt(context: TaskContext): string {\n const parts: string[] = [];\n const scenario = this.detectRelaunchScenario(context);\n\n // When resuming a session, the context is already in the session history —\n // just inject a brief orientation message.\n if (context.claudeSessionId && scenario !== \"fresh\") {\n if (scenario === \"feedback_relaunch\") {\n const lastAgentIdx = this.findLastAgentMessageIndex(context.chatHistory);\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}\".`,\n `\\nNew messages since your last run:`,\n ...newMessages.map((m) => `[${m.userName ?? \"user\"}]: ${m.content}`),\n `\\nAddress the requested changes. 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}\".`,\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 return parts.join(\"\\n\");\n }\n\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 parts.push(`- **${file.fileName}** (${file.mimeType}): ${file.downloadUrl}`);\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 parts.push(`\\n## Instructions`);\n\n if (scenario === \"fresh\") {\n if (this.config.mode === \"pm\") {\n // For fresh PM scenarios, provide minimal context and explicitly wait for user input\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 );\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}\".`,\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 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}\".`,\n `Review the current state of the codebase and verify everything is working correctly (e.g. tests pass, the web server starts on port 3000).`,\n `Post a brief status update to the chat summarizing the current state.`,\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 } else {\n const lastAgentIdx = this.findLastAgentMessageIndex(context.chatHistory);\n const newMessages = context.chatHistory\n .slice(lastAgentIdx + 1)\n .filter((m) => m.role === \"user\");\n parts.push(\n `You were relaunched with new feedback since your last run.`,\n `Work on the git branch \"${context.githubBranch}\".`,\n `\\nNew messages since your last run:`,\n ...newMessages.map((m) => `[${m.userName ?? \"user\"}]: ${m.content}`),\n `\\nAddress the requested changes. 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 return parts.join(\"\\n\");\n }\n\n private buildSystemPrompt(context: TaskContext): string {\n const parts =\n this.config.mode === \"pm\"\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 `\\nEnvironment (ready, no setup required):`,\n `- Repository is cloned at your current working directory.`,\n `- You can read files 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 ]\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 ];\n\n if (this.setupLog.length > 0) {\n parts.push(\n `\\nEnvironment setup log (already executed before you started — proof that setup succeeded):`,\n \"```\",\n ...this.setupLog,\n \"```\",\n );\n }\n\n if (context.agentInstructions) {\n parts.push(`\\nAgent Instructions:\\n${context.agentInstructions}`);\n }\n if (this.config.instructions) {\n parts.push(`\\nAdditional Instructions:\\n${this.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 (this.config.mode !== \"pm\") {\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\n // oxlint-disable-next-line typescript/explicit-function-return-type, max-lines-per-function\n private createConveyorMcpServer(context: TaskContext) {\n const connection = this.connection;\n const config = this.config;\n\n const textResult = (text: string): { content: { type: \"text\"; text: string }[] } => ({\n content: [{ type: \"text\" as const, text }],\n });\n\n const commonTools = [\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: { readOnly: 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: { readOnly: true } },\n ),\n ];\n\n // PM mode gets update_task tool; task mode gets create_pull_request\n const modeTools =\n config.mode === \"pm\"\n ? [\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 connection.updateTaskFields({ plan, description });\n return textResult(\"Task updated successfully.\");\n } catch {\n return textResult(\"Failed to update task.\");\n }\n },\n ),\n ]\n : [\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 return createSdkMcpServer({\n name: \"conveyor\",\n tools: [...commonTools, ...modeTools],\n });\n\n // Suppress unused warning — context used by callers for session ID\n void context;\n }\n\n // oxlint-disable-next-line max-lines-per-function, complexity\n private async processEvents(\n events: AsyncGenerator<SDKMessage, void>,\n context: TaskContext,\n ): Promise<void> {\n const startTime = Date.now();\n let totalCostUsd = 0;\n let sessionIdStored = false;\n let isTyping = false;\n\n for await (const event of events) {\n if (this.stopped) 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 this.connection.storeSessionId(sessionId);\n }\n await this.callbacks.onEvent({\n type: \"thinking\",\n message: `Agent initialized (model: ${event.model})`,\n });\n }\n break;\n }\n\n case \"assistant\": {\n // Send typing start event with 200ms delay (like Cloud PM Agent)\n if (!isTyping) {\n setTimeout(() => {\n this.connection.sendTypingStart();\n }, 200);\n isTyping = true;\n }\n\n const msg = event.message as unknown as Record<string, unknown>;\n const content = msg.content as Record<string, unknown>[];\n const turnTextParts: string[] = [];\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 this.connection.sendEvent({ type: \"message\", content: text });\n await this.callbacks.onEvent({ type: \"message\", content: text });\n } else if (blockType === \"tool_use\") {\n const name = block.name as string;\n const inputStr =\n 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 this.currentTurnToolCalls.push(summary);\n this.connection.sendEvent({\n type: \"tool_use\",\n tool: name,\n input: inputStr,\n });\n await this.callbacks.onEvent({\n type: \"tool_use\",\n tool: name,\n input: inputStr,\n });\n }\n }\n\n if (turnTextParts.length > 0) {\n this.connection.postChatMessage(turnTextParts.join(\"\\n\\n\"));\n }\n\n if (this.currentTurnToolCalls.length > 0) {\n this.connection.sendEvent({\n type: \"turn_end\",\n toolCalls: [...this.currentTurnToolCalls],\n });\n this.currentTurnToolCalls = [];\n }\n break;\n }\n\n case \"result\": {\n // Send typing stop event when processing completes\n if (isTyping) {\n this.connection.sendTypingStop();\n isTyping = false;\n }\n\n const resultEvent = event as SDKMessage & { type: \"result\"; subtype: string };\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 this.connection.sendEvent({\n type: \"completed\",\n summary,\n costUsd: totalCostUsd,\n durationMs,\n });\n\n // Track spending if cost information is available and we have an agent ID\n if (totalCostUsd > 0 && context.agentId) {\n // For now, estimate token usage from cost since SDK doesn't provide detailed breakdown\n // We'll use the agent's default model to reverse-calculate approximate tokens\n // Rough estimation: assume average token cost and split evenly between input/output\n // This is a temporary solution until we can get actual token counts from SDK\n const estimatedTotalTokens = Math.round(totalCostUsd * 100000); // Very rough estimate\n const estimatedInputTokens = Math.round(estimatedTotalTokens * 0.7); // 70% input\n const estimatedOutputTokens = Math.round(estimatedTotalTokens * 0.3); // 30% output\n\n this.connection.trackSpending({\n agentId: context.agentId,\n inputTokens: estimatedInputTokens,\n outputTokens: estimatedOutputTokens,\n totalTokens: estimatedTotalTokens,\n totalCostUsd,\n onSubscription: !!process.env.CLAUDE_CODE_OAUTH_TOKEN,\n });\n }\n\n await this.callbacks.onEvent({\n type: \"completed\",\n summary,\n costUsd: totalCostUsd,\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 this.connection.sendEvent({ type: \"error\", message: errorMsg });\n await this.callbacks.onEvent({ type: \"error\", message: errorMsg });\n }\n break;\n }\n }\n }\n\n // Ensure typing stops when processing ends\n if (isTyping) {\n this.connection.sendTypingStop();\n }\n }\n\n // oxlint-disable-next-line max-lines-per-function\n private async executeTask(context: TaskContext): Promise<void> {\n if (this.stopped) return;\n\n const settings = context.agentSettings ?? this.config.agentSettings ?? {};\n const systemPromptText = this.buildSystemPrompt(context);\n const conveyorMcp = this.createConveyorMcpServer(context);\n\n const systemPrompt: { type: \"preset\"; preset: \"claude_code\"; append?: string } = {\n type: \"preset\",\n preset: \"claude_code\",\n append: systemPromptText || undefined,\n };\n const settingSources = (settings.settingSources ?? [\"user\", \"project\"]) as (\n | \"user\"\n | \"project\"\n | \"local\"\n )[];\n\n const model = context.model || this.config.model;\n const pmDisallowedTools = this.config.mode === \"pm\" ? [\"TodoWrite\", \"TodoRead\"] : [];\n const disallowedTools = [...(settings.disallowedTools ?? []), ...pmDisallowedTools];\n\n const commonOptions = {\n model,\n systemPrompt,\n settingSources,\n cwd: this.config.workspaceDir,\n permissionMode: \"bypassPermissions\" as const,\n allowDangerouslySkipPermissions: true,\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 const initialPrompt = this.buildInitialPrompt(context);\n const agentQuery = query({\n prompt: this.createInputStream(initialPrompt),\n options: {\n ...commonOptions,\n resume: context.claudeSessionId ?? undefined,\n },\n });\n\n try {\n await this.processEvents(agentQuery, context);\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 this.connection.storeSessionId(\"\");\n const freshPrompt = this.buildInitialPrompt({ ...context, claudeSessionId: null });\n const freshQuery = query({\n prompt: this.createInputStream(freshPrompt),\n options: { ...commonOptions, resume: undefined },\n });\n await this.processEvents(freshQuery, context);\n } else {\n throw error;\n }\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"],"mappings":"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","names":[]}
|
package/dist/cli.js
CHANGED
package/dist/index.d.ts
CHANGED
|
@@ -30,6 +30,16 @@ interface AgentRunnerConfig {
|
|
|
30
30
|
mode?: RunnerMode;
|
|
31
31
|
agentSettings?: AgentSettings;
|
|
32
32
|
}
|
|
33
|
+
interface TaskFileContext {
|
|
34
|
+
fileId: string;
|
|
35
|
+
fileName: string;
|
|
36
|
+
mimeType: string;
|
|
37
|
+
downloadUrl: string;
|
|
38
|
+
}
|
|
39
|
+
interface TaskRepoRefContext {
|
|
40
|
+
path: string;
|
|
41
|
+
refType: "file" | "folder";
|
|
42
|
+
}
|
|
33
43
|
interface TaskContext {
|
|
34
44
|
taskId: string;
|
|
35
45
|
projectId: string;
|
|
@@ -44,6 +54,8 @@ interface TaskContext {
|
|
|
44
54
|
githubPRUrl?: string | null;
|
|
45
55
|
claudeSessionId?: string | null;
|
|
46
56
|
agentSettings?: AgentSettings | null;
|
|
57
|
+
files?: TaskFileContext[];
|
|
58
|
+
repoRefs?: TaskRepoRefContext[];
|
|
47
59
|
}
|
|
48
60
|
interface ChatMessage {
|
|
49
61
|
role: "user" | "assistant" | "system";
|
|
@@ -151,8 +163,19 @@ declare class ConveyorConnection {
|
|
|
151
163
|
private eventBuffer;
|
|
152
164
|
private flushTimer;
|
|
153
165
|
private static readonly EVENT_BATCH_MS;
|
|
166
|
+
private earlyMessages;
|
|
167
|
+
private earlyStop;
|
|
168
|
+
private chatMessageCallback;
|
|
169
|
+
private stopCallback;
|
|
154
170
|
constructor(config: AgentRunnerConfig);
|
|
155
171
|
connect(): Promise<void>;
|
|
172
|
+
fetchChatMessages(limit?: number): Promise<{
|
|
173
|
+
role: string;
|
|
174
|
+
content: string;
|
|
175
|
+
userId: string | null;
|
|
176
|
+
userName?: string;
|
|
177
|
+
createdAt: string;
|
|
178
|
+
}[]>;
|
|
156
179
|
fetchTaskContext(): Promise<TaskContext>;
|
|
157
180
|
sendEvent(event: AgentEvent): void;
|
|
158
181
|
flushEvents(): void;
|
package/dist/index.js
CHANGED
package/package.json
CHANGED
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/connection.ts","../src/setup.ts","../src/runner.ts"],"sourcesContent":["import { io, type Socket } from \"socket.io-client\";\nimport type { AgentRunnerConfig, TaskContext, AgentEvent } from \"./types.js\";\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 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 },\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(\"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 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 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(callback: (message: { content: string; userId: string }) => void): void {\n this.socket?.on(\"agentRunner:incomingMessage\", callback);\n }\n\n onStopRequested(callback: () => void): void {\n this.socket?.on(\"agentRunner:stop\", callback);\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 sendTypingStart(): void {\n this.sendEvent({ type: \"agent_typing_start\" });\n }\n\n sendTypingStop(): void {\n this.sendEvent({ type: \"agent_typing_stop\" });\n }\n\n disconnect(): void {\n this.flushEvents();\n this.socket?.disconnect();\n this.socket = null;\n }\n}\n","import { 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","// oxlint-disable max-lines\nimport { execSync } from \"node:child_process\";\nimport {\n query,\n tool,\n createSdkMcpServer,\n type SDKMessage,\n type SDKUserMessage,\n} from \"@anthropic-ai/claude-agent-sdk\";\nimport { z } from \"zod\";\nimport type {\n AgentRunnerConfig,\n AgentRunnerCallbacks,\n TaskContext,\n ActivityEventSummary,\n} from \"./types.js\";\nimport { ConveyorConnection } from \"./connection.js\";\nimport {\n loadConveyorConfig,\n loadForwardPorts,\n runSetupCommand,\n runStartCommand,\n type ConveyorConfig,\n} from \"./setup.js\";\n\nexport class AgentRunner {\n private config: AgentRunnerConfig;\n private connection: ConveyorConnection;\n private callbacks: AgentRunnerCallbacks;\n private stopped = false;\n private inputResolver: ((msg: SDKUserMessage) => void) | null = null;\n private pendingMessages: SDKUserMessage[] = [];\n private currentTurnToolCalls: ActivityEventSummary[] = [];\n private setupLog: string[] = [];\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 async start(): Promise<void> {\n await this.callbacks.onStatusChange(\"connecting\");\n await this.connection.connect();\n\n this.connection.onStopRequested(() => {\n this.stopped = true;\n });\n\n this.connection.onChatMessage((message) => {\n this.injectHumanMessage(message.content);\n });\n\n this.connection.sendEvent({\n type: \"connected\",\n taskId: this.config.taskId,\n });\n\n if (process.env.CODESPACES === \"true\") {\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 await this.runProjectSetup();\n }\n\n this.initRtk();\n\n await this.callbacks.onStatusChange(\"fetching_context\");\n const context = await this.connection.fetchTaskContext();\n\n await this.callbacks.onStatusChange(\"running\");\n\n try {\n await this.executeTask(context);\n } catch (error) {\n const message = error instanceof Error ? error.message : \"Unknown error\";\n this.connection.sendEvent({ type: \"error\", message });\n await this.callbacks.onEvent({ type: \"error\", message });\n throw error;\n } finally {\n await this.callbacks.onStatusChange(\"finished\");\n this.connection.disconnect();\n }\n }\n\n private async runProjectSetup(): Promise<void> {\n await this.callbacks.onStatusChange(\"setup\");\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;\n }\n\n try {\n await this.executeSetupConfig(config);\n this.connection.sendEvent({ type: \"setup_complete\" });\n await this.callbacks.onEvent({ type: \"setup_complete\" });\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 throw error;\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(content: string): void {\n const msg: 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 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 async *createInputStream(\n initialPrompt: string,\n ): AsyncGenerator<SDKUserMessage, void, unknown> {\n yield {\n type: \"user\" as const,\n session_id: \"\",\n message: { role: \"user\" as const, content: initialPrompt },\n parent_tool_use_id: null,\n };\n\n while (!this.stopped) {\n if (this.pendingMessages.length > 0) {\n const next = this.pendingMessages.shift();\n if (next) {\n yield next;\n }\n continue;\n }\n\n await this.callbacks.onStatusChange(\"waiting_for_input\");\n const msg = await new Promise<SDKUserMessage | null>((resolve) => {\n this.inputResolver = resolve as (msg: SDKUserMessage) => void;\n\n const checkStopped = setInterval(() => {\n if (this.stopped) {\n clearInterval(checkStopped);\n this.inputResolver = null;\n resolve(null);\n }\n }, 1000);\n });\n\n if (!msg) break;\n await this.callbacks.onStatusChange(\"running\");\n yield msg;\n }\n }\n\n private findLastAgentMessageIndex(history: TaskContext[\"chatHistory\"]): 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\n private detectRelaunchScenario(\n context: TaskContext,\n ): \"fresh\" | \"idle_relaunch\" | \"feedback_relaunch\" {\n const lastAgentIdx = this.findLastAgentMessageIndex(context.chatHistory);\n if (lastAgentIdx === -1) return \"fresh\";\n\n const hasPriorWork = !!context.githubPRUrl || !!context.claudeSessionId;\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\n private buildInitialPrompt(context: TaskContext): string {\n const parts: string[] = [];\n const scenario = this.detectRelaunchScenario(context);\n\n // When resuming a session, the context is already in the session history —\n // just inject a brief orientation message.\n if (context.claudeSessionId && scenario !== \"fresh\") {\n if (scenario === \"feedback_relaunch\") {\n const lastAgentIdx = this.findLastAgentMessageIndex(context.chatHistory);\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}\".`,\n `\\nNew messages since your last run:`,\n ...newMessages.map((m) => `[${m.userName ?? \"user\"}]: ${m.content}`),\n `\\nAddress the requested changes. 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}\".`,\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 return parts.join(\"\\n\");\n }\n\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.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 parts.push(`\\n## Instructions`);\n\n if (scenario === \"fresh\") {\n if (this.config.mode === \"pm\") {\n // For fresh PM scenarios, provide minimal context and explicitly wait for user input\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 );\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}\".`,\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 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}\".`,\n `Review the current state of the codebase and verify everything is working correctly (e.g. tests pass, the web server starts on port 3000).`,\n `Post a brief status update to the chat summarizing the current state.`,\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 } else {\n const lastAgentIdx = this.findLastAgentMessageIndex(context.chatHistory);\n const newMessages = context.chatHistory\n .slice(lastAgentIdx + 1)\n .filter((m) => m.role === \"user\");\n parts.push(\n `You were relaunched with new feedback since your last run.`,\n `Work on the git branch \"${context.githubBranch}\".`,\n `\\nNew messages since your last run:`,\n ...newMessages.map((m) => `[${m.userName ?? \"user\"}]: ${m.content}`),\n `\\nAddress the requested changes. 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 return parts.join(\"\\n\");\n }\n\n private buildSystemPrompt(context: TaskContext): string {\n const parts =\n this.config.mode === \"pm\"\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 `\\nEnvironment (ready, no setup required):`,\n `- Repository is cloned at your current working directory.`,\n `- You can read files 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 ]\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 ];\n\n if (this.setupLog.length > 0) {\n parts.push(\n `\\nEnvironment setup log (already executed before you started — proof that setup succeeded):`,\n \"```\",\n ...this.setupLog,\n \"```\",\n );\n }\n\n if (context.agentInstructions) {\n parts.push(`\\nAgent Instructions:\\n${context.agentInstructions}`);\n }\n if (this.config.instructions) {\n parts.push(`\\nAdditional Instructions:\\n${this.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 (this.config.mode !== \"pm\") {\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\n // oxlint-disable-next-line typescript/explicit-function-return-type, max-lines-per-function\n private createConveyorMcpServer(context: TaskContext) {\n const connection = this.connection;\n const config = this.config;\n\n const textResult = (text: string): { content: { type: \"text\"; text: string }[] } => ({\n content: [{ type: \"text\" as const, text }],\n });\n\n const commonTools = [\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 (_args) => {\n return Promise.resolve(\n textResult(\n JSON.stringify({\n note: \"Chat history was provided in the initial context. Use post_to_chat to ask the team questions.\",\n }),\n ),\n );\n },\n { annotations: { readOnly: 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: { readOnly: true } },\n ),\n ];\n\n // PM mode gets update_task tool; task mode gets create_pull_request\n const modeTools =\n config.mode === \"pm\"\n ? [\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 connection.updateTaskFields({ plan, description });\n return textResult(\"Task updated successfully.\");\n } catch {\n return textResult(\"Failed to update task.\");\n }\n },\n ),\n ]\n : [\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 return createSdkMcpServer({\n name: \"conveyor\",\n tools: [...commonTools, ...modeTools],\n });\n\n // Suppress unused warning — context used by callers for session ID\n void context;\n }\n\n // oxlint-disable-next-line max-lines-per-function, complexity\n private async processEvents(\n events: AsyncGenerator<SDKMessage, void>,\n context: TaskContext,\n ): Promise<void> {\n const startTime = Date.now();\n let totalCostUsd = 0;\n let sessionIdStored = false;\n let isTyping = false;\n\n for await (const event of events) {\n if (this.stopped) 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 this.connection.storeSessionId(sessionId);\n }\n await this.callbacks.onEvent({\n type: \"thinking\",\n message: `Agent initialized (model: ${event.model})`,\n });\n }\n break;\n }\n\n case \"assistant\": {\n // Send typing start event with 200ms delay (like Cloud PM Agent)\n if (!isTyping) {\n setTimeout(() => {\n this.connection.sendTypingStart();\n }, 200);\n isTyping = true;\n }\n\n const msg = event.message as unknown as Record<string, unknown>;\n const content = msg.content as Record<string, unknown>[];\n const turnTextParts: string[] = [];\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 this.connection.sendEvent({ type: \"message\", content: text });\n await this.callbacks.onEvent({ type: \"message\", content: text });\n } else if (blockType === \"tool_use\") {\n const name = block.name as string;\n const inputStr =\n 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 this.currentTurnToolCalls.push(summary);\n this.connection.sendEvent({\n type: \"tool_use\",\n tool: name,\n input: inputStr,\n });\n await this.callbacks.onEvent({\n type: \"tool_use\",\n tool: name,\n input: inputStr,\n });\n }\n }\n\n if (turnTextParts.length > 0) {\n this.connection.postChatMessage(turnTextParts.join(\"\\n\\n\"));\n }\n\n if (this.currentTurnToolCalls.length > 0) {\n this.connection.sendEvent({\n type: \"turn_end\",\n toolCalls: [...this.currentTurnToolCalls],\n });\n this.currentTurnToolCalls = [];\n }\n break;\n }\n\n case \"result\": {\n // Send typing stop event when processing completes\n if (isTyping) {\n this.connection.sendTypingStop();\n isTyping = false;\n }\n\n const resultEvent = event as SDKMessage & { type: \"result\"; subtype: string };\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 this.connection.sendEvent({\n type: \"completed\",\n summary,\n costUsd: totalCostUsd,\n durationMs,\n });\n\n // Track spending if cost information is available and we have an agent ID\n if (totalCostUsd > 0 && context.agentId) {\n // For now, estimate token usage from cost since SDK doesn't provide detailed breakdown\n // We'll use the agent's default model to reverse-calculate approximate tokens\n // Rough estimation: assume average token cost and split evenly between input/output\n // This is a temporary solution until we can get actual token counts from SDK\n const estimatedTotalTokens = Math.round(totalCostUsd * 100000); // Very rough estimate\n const estimatedInputTokens = Math.round(estimatedTotalTokens * 0.7); // 70% input\n const estimatedOutputTokens = Math.round(estimatedTotalTokens * 0.3); // 30% output\n\n this.connection.trackSpending({\n agentId: context.agentId,\n inputTokens: estimatedInputTokens,\n outputTokens: estimatedOutputTokens,\n totalTokens: estimatedTotalTokens,\n totalCostUsd,\n onSubscription: !!process.env.CLAUDE_CODE_OAUTH_TOKEN,\n });\n }\n\n await this.callbacks.onEvent({\n type: \"completed\",\n summary,\n costUsd: totalCostUsd,\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 this.connection.sendEvent({ type: \"error\", message: errorMsg });\n await this.callbacks.onEvent({ type: \"error\", message: errorMsg });\n }\n break;\n }\n }\n }\n\n // Ensure typing stops when processing ends\n if (isTyping) {\n this.connection.sendTypingStop();\n }\n }\n\n // oxlint-disable-next-line max-lines-per-function\n private async executeTask(context: TaskContext): Promise<void> {\n if (this.stopped) return;\n\n const settings = context.agentSettings ?? this.config.agentSettings ?? {};\n const systemPromptText = this.buildSystemPrompt(context);\n const conveyorMcp = this.createConveyorMcpServer(context);\n\n const systemPrompt: { type: \"preset\"; preset: \"claude_code\"; append?: string } = {\n type: \"preset\",\n preset: \"claude_code\",\n append: systemPromptText || undefined,\n };\n const settingSources = (settings.settingSources ?? [\"user\", \"project\"]) as (\n | \"user\"\n | \"project\"\n | \"local\"\n )[];\n\n const model = context.model || this.config.model;\n const pmDisallowedTools = this.config.mode === \"pm\" ? [\"TodoWrite\", \"TodoRead\"] : [];\n const disallowedTools = [...(settings.disallowedTools ?? []), ...pmDisallowedTools];\n\n const commonOptions = {\n model,\n systemPrompt,\n settingSources,\n cwd: this.config.workspaceDir,\n permissionMode: \"bypassPermissions\" as const,\n allowDangerouslySkipPermissions: true,\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 const initialPrompt = this.buildInitialPrompt(context);\n const agentQuery = query({\n prompt: this.createInputStream(initialPrompt),\n options: {\n ...commonOptions,\n resume: context.claudeSessionId ?? undefined,\n },\n });\n\n try {\n await this.processEvents(agentQuery, context);\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 this.connection.storeSessionId(\"\");\n const freshPrompt = this.buildInitialPrompt({ ...context, claudeSessionId: null });\n const freshQuery = query({\n prompt: this.createInputStream(freshPrompt),\n options: { ...commonOptions, resume: undefined },\n });\n await this.processEvents(freshQuery, context);\n } else {\n throw error;\n }\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"],"mappings":"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","names":[]}
|