@rallycry/conveyor-agent 2.5.0 → 2.7.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.
@@ -10,6 +10,7 @@ var ConveyorConnection = class _ConveyorConnection {
10
10
  earlyStop = false;
11
11
  chatMessageCallback = null;
12
12
  stopCallback = null;
13
+ pendingQuestionResolvers = /* @__PURE__ */ new Map();
13
14
  constructor(config) {
14
15
  this.config = config;
15
16
  }
@@ -44,6 +45,16 @@ var ConveyorConnection = class _ConveyorConnection {
44
45
  this.earlyStop = true;
45
46
  }
46
47
  });
48
+ this.socket.on(
49
+ "agentRunner:questionAnswer",
50
+ (data) => {
51
+ const resolver = this.pendingQuestionResolvers.get(data.requestId);
52
+ if (resolver) {
53
+ this.pendingQuestionResolvers.delete(data.requestId);
54
+ resolver(data.answers);
55
+ }
56
+ }
57
+ );
47
58
  this.socket.on("connect", () => {
48
59
  if (!settled) {
49
60
  settled = true;
@@ -142,6 +153,20 @@ var ConveyorConnection = class _ConveyorConnection {
142
153
  );
143
154
  });
144
155
  }
156
+ askUserQuestion(requestId, questions) {
157
+ if (!this.socket) throw new Error("Not connected");
158
+ this.socket.emit("agentRunner:askUserQuestion", {
159
+ taskId: this.config.taskId,
160
+ requestId,
161
+ questions
162
+ });
163
+ return new Promise((resolve) => {
164
+ this.pendingQuestionResolvers.set(requestId, resolve);
165
+ });
166
+ }
167
+ cancelPendingQuestions() {
168
+ this.pendingQuestionResolvers.clear();
169
+ }
145
170
  storeSessionId(sessionId) {
146
171
  if (!this.socket) return;
147
172
  this.socket.emit("agentRunner:storeSessionId", {
@@ -311,8 +336,47 @@ function cleanDevcontainerFromGit(workspaceDir, taskBranch, baseBranch) {
311
336
  }
312
337
  }
313
338
 
314
- // src/runner.ts
339
+ // src/worktree.ts
315
340
  import { execSync as execSync2 } from "child_process";
341
+ import { existsSync } from "fs";
342
+ import { join as join2 } from "path";
343
+ var WORKTREE_DIR = ".worktrees";
344
+ function ensureWorktree(projectDir, taskId, branch) {
345
+ const worktreePath = join2(projectDir, WORKTREE_DIR, taskId);
346
+ if (existsSync(worktreePath)) {
347
+ if (branch) {
348
+ try {
349
+ execSync2(`git checkout ${branch}`, { cwd: worktreePath, stdio: "ignore" });
350
+ } catch {
351
+ }
352
+ }
353
+ return worktreePath;
354
+ }
355
+ const target = branch ?? "HEAD";
356
+ execSync2(`git worktree add "${worktreePath}" ${target}`, {
357
+ cwd: projectDir,
358
+ stdio: "ignore"
359
+ });
360
+ return worktreePath;
361
+ }
362
+ function removeWorktree(projectDir, taskId) {
363
+ const worktreePath = join2(projectDir, WORKTREE_DIR, taskId);
364
+ if (!existsSync(worktreePath)) return;
365
+ try {
366
+ execSync2(`git worktree remove "${worktreePath}" --force`, {
367
+ cwd: projectDir,
368
+ stdio: "ignore"
369
+ });
370
+ } catch {
371
+ }
372
+ }
373
+
374
+ // src/runner.ts
375
+ import { randomUUID } from "crypto";
376
+ import { execSync as execSync3 } from "child_process";
377
+ import { readdirSync, statSync, readFileSync } from "fs";
378
+ import { homedir } from "os";
379
+ import { join as join3 } from "path";
316
380
  import {
317
381
  query,
318
382
  tool,
@@ -322,6 +386,7 @@ import { z } from "zod";
322
386
  var API_ERROR_PATTERN = /API Error: [45]\d\d/;
323
387
  var RETRY_DELAYS_MS = [6e4, 12e4, 18e4, 3e5];
324
388
  var HEARTBEAT_INTERVAL_MS = 3e4;
389
+ var PM_DENIED_TOOLS = /* @__PURE__ */ new Set(["Write", "Edit", "MultiEdit", "NotebookEdit", "Bash"]);
325
390
  var AgentRunner = class _AgentRunner {
326
391
  config;
327
392
  connection;
@@ -334,6 +399,8 @@ var AgentRunner = class _AgentRunner {
334
399
  setupLog = [];
335
400
  heartbeatTimer = null;
336
401
  taskContext = null;
402
+ planFileSnapshot = /* @__PURE__ */ new Map();
403
+ worktreeActive = false;
337
404
  static MAX_SETUP_LOG_LINES = 50;
338
405
  constructor(config, callbacks) {
339
406
  this.config = config;
@@ -387,6 +454,17 @@ var AgentRunner = class _AgentRunner {
387
454
  }
388
455
  }
389
456
  this.initRtk();
457
+ if (this.config.mode === "pm" || process.env.CONVEYOR_USE_WORKTREE === "true") {
458
+ try {
459
+ const worktreePath = ensureWorktree(this.config.workspaceDir, this.config.taskId);
460
+ this.config = { ...this.config, workspaceDir: worktreePath };
461
+ this.worktreeActive = true;
462
+ this.setupLog.push(`[conveyor] Using worktree: ${worktreePath}`);
463
+ } catch (error) {
464
+ const msg = error instanceof Error ? error.message : "Unknown error";
465
+ this.setupLog.push(`[conveyor] Worktree creation failed, using shared workspace: ${msg}`);
466
+ }
467
+ }
390
468
  await this.setState("fetching_context");
391
469
  try {
392
470
  this.taskContext = await this.connection.fetchTaskContext();
@@ -409,6 +487,27 @@ var AgentRunner = class _AgentRunner {
409
487
  this.setupLog.push(`[conveyor] ${result.message}`);
410
488
  }
411
489
  }
490
+ if (!this.worktreeActive && this.taskContext.useWorktree) {
491
+ try {
492
+ const worktreePath = ensureWorktree(this.config.workspaceDir, this.config.taskId);
493
+ this.config = { ...this.config, workspaceDir: worktreePath };
494
+ this.worktreeActive = true;
495
+ this.setupLog.push(`[conveyor] Using worktree (from task config): ${worktreePath}`);
496
+ } catch (error) {
497
+ const msg = error instanceof Error ? error.message : "Unknown error";
498
+ this.setupLog.push(`[conveyor] Worktree creation failed, using shared workspace: ${msg}`);
499
+ }
500
+ }
501
+ if (this.worktreeActive && this.taskContext.githubBranch) {
502
+ try {
503
+ const branch = this.taskContext.githubBranch;
504
+ execSync3(`git fetch origin ${branch} && git checkout ${branch}`, {
505
+ cwd: this.config.workspaceDir,
506
+ stdio: "ignore"
507
+ });
508
+ } catch {
509
+ }
510
+ }
412
511
  const isPm = this.config.mode === "pm";
413
512
  if (isPm) {
414
513
  await this.setState("idle");
@@ -505,8 +604,8 @@ The agent cannot start until this is resolved.`
505
604
  }
506
605
  initRtk() {
507
606
  try {
508
- execSync2("rtk --version", { stdio: "ignore" });
509
- execSync2("rtk init --global --auto-patch", { stdio: "ignore" });
607
+ execSync3("rtk --version", { stdio: "ignore" });
608
+ execSync3("rtk init --global --auto-patch", { stdio: "ignore" });
510
609
  } catch {
511
610
  }
512
611
  }
@@ -999,6 +1098,9 @@ You have access to Conveyor MCP tools to interact with the task management syste
999
1098
  });
1000
1099
  this.currentTurnToolCalls = [];
1001
1100
  }
1101
+ if (this.config.mode === "pm") {
1102
+ this.syncPlanFile();
1103
+ }
1002
1104
  break;
1003
1105
  }
1004
1106
  case "result": {
@@ -1057,6 +1159,59 @@ You have access to Conveyor MCP tools to interact with the task management syste
1057
1159
  }
1058
1160
  return { retriable };
1059
1161
  }
1162
+ /**
1163
+ * Snapshot current plan files so syncPlanFile can distinguish files created
1164
+ * by THIS session from ones created by a concurrent agent.
1165
+ */
1166
+ snapshotPlanFiles() {
1167
+ const plansDir = join3(homedir(), ".claude", "plans");
1168
+ this.planFileSnapshot.clear();
1169
+ try {
1170
+ for (const file of readdirSync(plansDir).filter((f) => f.endsWith(".md"))) {
1171
+ try {
1172
+ const stat = statSync(join3(plansDir, file));
1173
+ this.planFileSnapshot.set(file, stat.mtimeMs);
1174
+ } catch {
1175
+ continue;
1176
+ }
1177
+ }
1178
+ } catch {
1179
+ }
1180
+ }
1181
+ /**
1182
+ * After a PM-mode query, scan ~/.claude/plans/ for plan files that were
1183
+ * created or modified by THIS session (not present in the pre-query snapshot)
1184
+ * and push the newest one to the task.
1185
+ */
1186
+ syncPlanFile() {
1187
+ const plansDir = join3(homedir(), ".claude", "plans");
1188
+ let files;
1189
+ try {
1190
+ files = readdirSync(plansDir).filter((f) => f.endsWith(".md"));
1191
+ } catch {
1192
+ return;
1193
+ }
1194
+ let newest = null;
1195
+ for (const file of files) {
1196
+ const fullPath = join3(plansDir, file);
1197
+ try {
1198
+ const stat = statSync(fullPath);
1199
+ const prevMtime = this.planFileSnapshot.get(file);
1200
+ const isNew = prevMtime === void 0 || stat.mtimeMs > prevMtime;
1201
+ if (isNew && (!newest || stat.mtimeMs > newest.mtime)) {
1202
+ newest = { path: fullPath, mtime: stat.mtimeMs };
1203
+ }
1204
+ } catch {
1205
+ continue;
1206
+ }
1207
+ }
1208
+ if (newest) {
1209
+ const content = readFileSync(newest.path, "utf-8").trim();
1210
+ if (content) {
1211
+ this.connection.updateTaskFields({ plan: content });
1212
+ }
1213
+ }
1214
+ }
1060
1215
  /**
1061
1216
  * Runs one SDK query cycle. For PM mode this is a single-turn query per
1062
1217
  * user message. For task mode this uses the long-running input stream
@@ -1078,6 +1233,45 @@ You have access to Conveyor MCP tools to interact with the task management syste
1078
1233
  const pmDisallowedTools = this.config.mode === "pm" ? ["TodoWrite", "TodoRead"] : [];
1079
1234
  const disallowedTools = [...settings.disallowedTools ?? [], ...pmDisallowedTools];
1080
1235
  const isPm = this.config.mode === "pm";
1236
+ if (isPm) {
1237
+ this.snapshotPlanFiles();
1238
+ }
1239
+ const QUESTION_TIMEOUT_MS = 5 * 60 * 1e3;
1240
+ const canUseTool = async (toolName, input) => {
1241
+ if (toolName === "AskUserQuestion") {
1242
+ const questions = input.questions;
1243
+ const requestId = randomUUID();
1244
+ this.connection.emitStatus("waiting_for_input");
1245
+ this.connection.sendEvent({
1246
+ type: "tool_use",
1247
+ tool: "AskUserQuestion",
1248
+ input: JSON.stringify(input)
1249
+ });
1250
+ const answerPromise = this.connection.askUserQuestion(requestId, questions);
1251
+ const timeoutPromise = new Promise(
1252
+ (resolve) => setTimeout(() => resolve(null), QUESTION_TIMEOUT_MS)
1253
+ );
1254
+ const answers = await Promise.race([answerPromise, timeoutPromise]);
1255
+ this.connection.emitStatus("running");
1256
+ if (!answers) {
1257
+ return {
1258
+ behavior: "deny",
1259
+ message: "User did not respond to clarifying questions in time. Proceed with your best judgment."
1260
+ };
1261
+ }
1262
+ return {
1263
+ behavior: "allow",
1264
+ updatedInput: { questions: input.questions, answers }
1265
+ };
1266
+ }
1267
+ if (isPm && PM_DENIED_TOOLS.has(toolName)) {
1268
+ return {
1269
+ behavior: "deny",
1270
+ message: "PM mode is plan-only. Use the update_task tool to save your plan."
1271
+ };
1272
+ }
1273
+ return { behavior: "allow", updatedInput: input };
1274
+ };
1081
1275
  const commonOptions = {
1082
1276
  model,
1083
1277
  systemPrompt,
@@ -1085,6 +1279,7 @@ You have access to Conveyor MCP tools to interact with the task management syste
1085
1279
  cwd: this.config.workspaceDir,
1086
1280
  permissionMode: isPm ? "plan" : "bypassPermissions",
1087
1281
  allowDangerouslySkipPermissions: !isPm,
1282
+ canUseTool,
1088
1283
  tools: { type: "preset", preset: "claude_code" },
1089
1284
  mcpServers: { conveyor: conveyorMcp },
1090
1285
  maxTurns: settings.maxTurns,
@@ -1118,6 +1313,9 @@ ${followUpContent}` : followUpContent;
1118
1313
  });
1119
1314
  await this.runWithRetry(agentQuery, context, commonOptions);
1120
1315
  }
1316
+ if (isPm) {
1317
+ this.syncPlanFile();
1318
+ }
1121
1319
  }
1122
1320
  /**
1123
1321
  * Run a query with retry logic for transient API errors.
@@ -1192,6 +1390,8 @@ export {
1192
1390
  loadConveyorConfig,
1193
1391
  runSetupCommand,
1194
1392
  runStartCommand,
1393
+ ensureWorktree,
1394
+ removeWorktree,
1195
1395
  AgentRunner
1196
1396
  };
1197
- //# sourceMappingURL=chunk-US4HLRJA.js.map
1397
+ //# sourceMappingURL=chunk-JWIGEYRD.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../src/connection.ts","../src/setup.ts","../src/worktree.ts","../src/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: { 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 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(\"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(\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(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 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 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 */\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 ${branch}`, { cwd: worktreePath, stdio: \"ignore\" });\n } catch {\n /* already on branch or branch doesn't exist locally yet */\n }\n }\n return worktreePath;\n }\n\n const target = branch ?? \"HEAD\";\n execSync(`git worktree add \"${worktreePath}\" ${target}`, {\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","// oxlint-disable max-lines\nimport { randomUUID } from \"node:crypto\";\nimport { execSync } from \"node:child_process\";\nimport { readdirSync, statSync, readFileSync } from \"node:fs\";\nimport { homedir } from \"node:os\";\nimport { join } from \"node:path\";\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 AgentRunnerStatus,\n AgentEvent,\n TaskContext,\n ActivityEventSummary,\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 { ensureWorktree } from \"./worktree.js\";\n\nconst API_ERROR_PATTERN = /API Error: [45]\\d\\d/;\nconst RETRY_DELAYS_MS = [60_000, 120_000, 180_000, 300_000]; // 1, 2, 3, 5 minutes\nconst HEARTBEAT_INTERVAL_MS = 30_000;\n\nconst PM_DENIED_TOOLS = new Set([\"Write\", \"Edit\", \"MultiEdit\", \"NotebookEdit\", \"Bash\"]);\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 currentTurnToolCalls: ActivityEventSummary[] = [];\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 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 // oxlint-disable-next-line max-lines-per-function\n async start(): Promise<void> {\n // --- Phase 1: Connect ---\n await this.setState(\"connecting\");\n await this.connection.connect();\n\n this.connection.onStopRequested(() => {\n this.stop();\n });\n\n this.connection.onChatMessage((message) => {\n this.injectHumanMessage(message.content);\n });\n\n await this.setState(\"connected\");\n this.connection.sendEvent({\n type: \"connected\",\n taskId: this.config.taskId,\n });\n this.startHeartbeat();\n\n // --- Phase 2: Setup (task mode + codespace only) ---\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 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 this.runSdkQuery(this.taskContext);\n if (!this.stopped) {\n await this.setState(\"idle\");\n }\n }\n\n // --- Phase 5: Core loop — stay alive for follow-up messages ---\n while (!this.stopped) {\n if (this._state === \"idle\") {\n const msg = await this.waitForUserContent();\n if (!msg) break;\n\n await this.setState(\"running\");\n await this.runSdkQuery(this.taskContext, msg);\n\n if (!this.stopped) {\n await this.setState(\"idle\");\n }\n } else if (this._state === \"error\") {\n await this.setState(\"idle\");\n } else {\n break;\n }\n }\n\n // --- Cleanup ---\n this.stopHeartbeat();\n await this.setState(\"finished\");\n this.connection.disconnect();\n }\n\n /**\n * Wraps project setup in try/catch. On failure, posts error to chat\n * directly (no SDK needed) and streams to CLI. Returns false if setup failed.\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(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 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 /**\n * Wait for the next user message content string. Drains pendingMessages first.\n * Returns null if stopped.\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;\n }\n\n const msg = await this.waitForMessage();\n if (!msg) return null;\n return (msg.message as { content: string }).content;\n }\n\n private async *createInputStream(\n initialPrompt: string,\n ): 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) {\n yield next;\n }\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 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 if (context.claudeSessionId && scenario !== \"fresh\") {\n if (this.config.mode === \"pm\") {\n const lastAgentIdx = this.findLastAgentMessageIndex(context.chatHistory);\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 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 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 if (this.config.mode === \"pm\") {\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}\".`,\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 }\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 if (this.config.mode === \"pm\") {\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 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\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 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 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<{ retriable: boolean }> {\n const startTime = Date.now();\n let totalCostUsd = 0;\n let sessionIdStored = false;\n let isTyping = false;\n let retriable = 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 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\n if (this.config.mode === \"pm\") {\n this.syncPlanFile();\n }\n break;\n }\n\n case \"result\": {\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 if (API_ERROR_PATTERN.test(summary) && durationMs < 30_000) {\n retriable = true;\n }\n\n this.connection.sendEvent({\n type: \"completed\",\n summary,\n costUsd: totalCostUsd,\n durationMs,\n });\n\n if (totalCostUsd > 0 && context.agentId) {\n const estimatedTotalTokens = Math.round(totalCostUsd * 100000);\n const estimatedInputTokens = Math.round(estimatedTotalTokens * 0.7);\n const estimatedOutputTokens = Math.round(estimatedTotalTokens * 0.3);\n\n this.connection.trackSpending({\n agentId: context.agentId,\n inputTokens: estimatedInputTokens,\n outputTokens: estimatedOutputTokens,\n totalTokens: estimatedTotalTokens,\n totalCostUsd,\n onSubscription: this.config.mode === \"pm\" || !!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\n if (API_ERROR_PATTERN.test(errorMsg)) {\n retriable = true;\n }\n\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 if (isTyping) {\n this.connection.sendTypingStop();\n }\n\n return { retriable };\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 private snapshotPlanFiles(): void {\n const plansDir = join(homedir(), \".claude\", \"plans\");\n this.planFileSnapshot.clear();\n try {\n for (const file of readdirSync(plansDir).filter((f) => f.endsWith(\".md\"))) {\n try {\n const stat = statSync(join(plansDir, file));\n this.planFileSnapshot.set(file, stat.mtimeMs);\n } catch {\n continue;\n }\n }\n } catch {\n /* plans dir doesn't exist yet */\n }\n }\n\n /**\n * After a PM-mode query, scan ~/.claude/plans/ for plan files that were\n * created or modified by THIS session (not present in the pre-query snapshot)\n * and push the newest one to the task.\n */\n private syncPlanFile(): void {\n const plansDir = join(homedir(), \".claude\", \"plans\");\n\n let files: string[];\n try {\n files = readdirSync(plansDir).filter((f) => f.endsWith(\".md\"));\n } catch {\n return;\n }\n\n let newest: { path: string; mtime: number } | null = null;\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(file);\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 if (newest) {\n const content = readFileSync(newest.path, \"utf-8\").trim();\n if (content) {\n this.connection.updateTaskFields({ plan: content });\n }\n }\n }\n\n /**\n * Runs one SDK query cycle. For PM mode this is a single-turn query per\n * user message. For task mode this uses the long-running input stream\n * (initial execution) or a single follow-up prompt.\n */\n // oxlint-disable-next-line max-lines-per-function\n private async runSdkQuery(context: TaskContext, followUpContent?: string): 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 isPm = this.config.mode === \"pm\";\n if (isPm) {\n this.snapshotPlanFiles();\n }\n\n const QUESTION_TIMEOUT_MS = 5 * 60 * 1000;\n\n const canUseTool = async (\n toolName: string,\n input: Record<string, unknown>,\n ): Promise<\n | { behavior: \"allow\"; updatedInput?: Record<string, unknown> }\n | { behavior: \"deny\"; message: string }\n > => {\n if (toolName === \"AskUserQuestion\") {\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\n this.connection.emitStatus(\"waiting_for_input\");\n this.connection.sendEvent({\n type: \"tool_use\",\n tool: \"AskUserQuestion\",\n input: JSON.stringify(input),\n });\n\n const answerPromise = this.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\n this.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 {\n behavior: \"allow\",\n updatedInput: { questions: input.questions, answers },\n };\n }\n\n if (isPm && PM_DENIED_TOOLS.has(toolName)) {\n return {\n behavior: \"deny\",\n message: \"PM mode is plan-only. Use the update_task tool to save your plan.\",\n };\n }\n\n return { behavior: \"allow\", updatedInput: input };\n };\n\n const commonOptions = {\n model,\n systemPrompt,\n settingSources,\n cwd: this.config.workspaceDir,\n permissionMode: (isPm ? \"plan\" : \"bypassPermissions\") as \"plan\" | \"bypassPermissions\",\n allowDangerouslySkipPermissions: !isPm,\n canUseTool,\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 resume = context.claudeSessionId ?? undefined;\n\n if (followUpContent) {\n // Follow-up message: single prompt, resume session\n const prompt = isPm\n ? `${this.buildInitialPrompt(context)}\\n\\n---\\n\\nThe team says:\\n${followUpContent}`\n : followUpContent;\n\n const agentQuery = query({\n prompt,\n options: { ...commonOptions, resume },\n });\n await this.runWithRetry(agentQuery, context, commonOptions);\n } else if (isPm) {\n // PM initial: no-op, we go straight to idle and wait for messages\n return;\n } else {\n // Task initial: long-running query with input stream\n const initialPrompt = this.buildInitialPrompt(context);\n const agentQuery = query({\n prompt: this.createInputStream(initialPrompt),\n options: { ...commonOptions, resume },\n });\n await this.runWithRetry(agentQuery, context, commonOptions);\n }\n\n if (isPm) {\n this.syncPlanFile();\n }\n }\n\n /**\n * Run a query with retry logic for transient API errors.\n */\n private async runWithRetry(\n initialQuery: AsyncGenerator<SDKMessage, void>,\n context: TaskContext,\n // oxlint-disable-next-line typescript/no-explicit-any\n options: Record<string, any>,\n ): Promise<void> {\n for (let attempt = 0; attempt <= RETRY_DELAYS_MS.length; attempt++) {\n if (this.stopped) return;\n\n const agentQuery =\n attempt === 0\n ? initialQuery\n : query({\n prompt: this.createInputStream(this.buildInitialPrompt(context)),\n options: { ...options, resume: undefined },\n });\n\n try {\n const { retriable } = await this.processEvents(agentQuery, context);\n if (!retriable || this.stopped) 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 this.connection.storeSessionId(\"\");\n const freshCtx = { ...context, claudeSessionId: null };\n const freshQuery = query({\n prompt: this.createInputStream(this.buildInitialPrompt(freshCtx)),\n options: { ...options, resume: undefined },\n });\n return this.runWithRetry(freshQuery, freshCtx, 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 this.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 this.connection.postChatMessage(\n `API error encountered. Retrying in ${delayMin} minute${delayMin > 1 ? \"s\" : \"\"}... (attempt ${attempt + 1}/${RETRY_DELAYS_MS.length})`,\n );\n this.connection.sendEvent({\n type: \"error\",\n message: `API error, retrying in ${delayMin}m (${attempt + 1}/${RETRY_DELAYS_MS.length})`,\n });\n this.connection.emitStatus(\"waiting_for_input\");\n await this.callbacks.onStatusChange(\"waiting_for_input\");\n\n await new Promise<void>((resolve) => {\n const timer = setTimeout(resolve, delayMs);\n const checkStopped = setInterval(() => {\n if (this.stopped) {\n clearTimeout(timer);\n clearInterval(checkStopped);\n resolve();\n }\n }, 1000);\n setTimeout(() => clearInterval(checkStopped), delayMs + 100);\n });\n\n this.connection.emitStatus(\"running\");\n await this.callbacks.onStatusChange(\"running\");\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":["execSync","join","execSync","join","execSync","join"]}
package/dist/cli.js CHANGED
@@ -1,7 +1,7 @@
1
1
  #!/usr/bin/env node
2
2
  import {
3
3
  AgentRunner
4
- } from "./chunk-US4HLRJA.js";
4
+ } from "./chunk-JWIGEYRD.js";
5
5
 
6
6
  // src/cli.ts
7
7
  var CONVEYOR_API_URL = process.env.CONVEYOR_API_URL;
package/dist/index.d.ts CHANGED
@@ -54,6 +54,7 @@ interface TaskContext {
54
54
  baseBranch: string;
55
55
  githubPRUrl?: string | null;
56
56
  claudeSessionId?: string | null;
57
+ useWorktree?: boolean;
57
58
  agentSettings?: AgentSettings | null;
58
59
  files?: TaskFileContext[];
59
60
  repoRefs?: TaskRepoRefContext[];
@@ -146,6 +147,8 @@ declare class AgentRunner {
146
147
  private setupLog;
147
148
  private heartbeatTimer;
148
149
  private taskContext;
150
+ private planFileSnapshot;
151
+ private worktreeActive;
149
152
  private static readonly MAX_SETUP_LOG_LINES;
150
153
  constructor(config: AgentRunnerConfig, callbacks: AgentRunnerCallbacks);
151
154
  get state(): AgentRunnerStatus;
@@ -175,6 +178,17 @@ declare class AgentRunner {
175
178
  private buildSystemPrompt;
176
179
  private createConveyorMcpServer;
177
180
  private processEvents;
181
+ /**
182
+ * Snapshot current plan files so syncPlanFile can distinguish files created
183
+ * by THIS session from ones created by a concurrent agent.
184
+ */
185
+ private snapshotPlanFiles;
186
+ /**
187
+ * After a PM-mode query, scan ~/.claude/plans/ for plan files that were
188
+ * created or modified by THIS session (not present in the pre-query snapshot)
189
+ * and push the newest one to the task.
190
+ */
191
+ private syncPlanFile;
178
192
  /**
179
193
  * Runs one SDK query cycle. For PM mode this is a single-turn query per
180
194
  * user message. For task mode this uses the long-running input stream
@@ -188,6 +202,17 @@ declare class AgentRunner {
188
202
  stop(): void;
189
203
  }
190
204
 
205
+ interface AgentQuestionOption {
206
+ label: string;
207
+ description: string;
208
+ preview?: string;
209
+ }
210
+ interface AgentQuestion {
211
+ question: string;
212
+ header: string;
213
+ options: AgentQuestionOption[];
214
+ multiSelect?: boolean;
215
+ }
191
216
  declare class ConveyorConnection {
192
217
  private socket;
193
218
  private config;
@@ -198,6 +223,7 @@ declare class ConveyorConnection {
198
223
  private earlyStop;
199
224
  private chatMessageCallback;
200
225
  private stopCallback;
226
+ private pendingQuestionResolvers;
201
227
  constructor(config: AgentRunnerConfig);
202
228
  connect(): Promise<void>;
203
229
  fetchChatMessages(limit?: number): Promise<{
@@ -220,6 +246,8 @@ declare class ConveyorConnection {
220
246
  url: string;
221
247
  number: number;
222
248
  }>;
249
+ askUserQuestion(requestId: string, questions: AgentQuestion[]): Promise<Record<string, string>>;
250
+ cancelPendingQuestions(): void;
223
251
  storeSessionId(sessionId: string): void;
224
252
  updateTaskFields(fields: {
225
253
  plan?: string;
@@ -263,4 +291,14 @@ declare function runSetupCommand(cmd: string, cwd: string, onOutput: (stream: "s
263
291
  */
264
292
  declare function runStartCommand(cmd: string, cwd: string, onOutput: (stream: "stdout" | "stderr", data: string) => void): ChildProcess;
265
293
 
266
- export { type AgentEvent, AgentRunner, type AgentRunnerCallbacks, type AgentRunnerConfig, type ChatMessage, type ConveyorConfig, ConveyorConnection, type TaskContext, loadConveyorConfig, runSetupCommand, runStartCommand };
294
+ /**
295
+ * Ensure a git worktree exists for the given task. Creates one if it doesn't
296
+ * exist, reuses the existing one otherwise. Returns the absolute worktree path.
297
+ */
298
+ declare function ensureWorktree(projectDir: string, taskId: string, branch?: string): string;
299
+ /**
300
+ * Remove a task's git worktree. Best-effort — silently ignores failures.
301
+ */
302
+ declare function removeWorktree(projectDir: string, taskId: string): void;
303
+
304
+ export { type AgentEvent, AgentRunner, type AgentRunnerCallbacks, type AgentRunnerConfig, type ChatMessage, type ConveyorConfig, ConveyorConnection, type TaskContext, ensureWorktree, loadConveyorConfig, removeWorktree, runSetupCommand, runStartCommand };
package/dist/index.js CHANGED
@@ -1,14 +1,18 @@
1
1
  import {
2
2
  AgentRunner,
3
3
  ConveyorConnection,
4
+ ensureWorktree,
4
5
  loadConveyorConfig,
6
+ removeWorktree,
5
7
  runSetupCommand,
6
8
  runStartCommand
7
- } from "./chunk-US4HLRJA.js";
9
+ } from "./chunk-JWIGEYRD.js";
8
10
  export {
9
11
  AgentRunner,
10
12
  ConveyorConnection,
13
+ ensureWorktree,
11
14
  loadConveyorConfig,
15
+ removeWorktree,
12
16
  runSetupCommand,
13
17
  runStartCommand
14
18
  };
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@rallycry/conveyor-agent",
3
- "version": "2.5.0",
3
+ "version": "2.7.0",
4
4
  "description": "Conveyor cloud build agent runner - executes task plans inside GitHub Codespaces",
5
5
  "keywords": [
6
6
  "agent",
@@ -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 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, 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(\"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 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 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","// 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 AgentRunnerStatus,\n AgentEvent,\n TaskContext,\n ActivityEventSummary,\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\";\n\nconst API_ERROR_PATTERN = /API Error: [45]\\d\\d/;\nconst RETRY_DELAYS_MS = [60_000, 120_000, 180_000, 300_000]; // 1, 2, 3, 5 minutes\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 currentTurnToolCalls: ActivityEventSummary[] = [];\n private setupLog: string[] = [];\n private heartbeatTimer: ReturnType<typeof setInterval> | null = null;\n private taskContext: TaskContext | null = null;\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 // oxlint-disable-next-line max-lines-per-function\n async start(): Promise<void> {\n // --- Phase 1: Connect ---\n await this.setState(\"connecting\");\n await this.connection.connect();\n\n this.connection.onStopRequested(() => {\n this.stop();\n });\n\n this.connection.onChatMessage((message) => {\n this.injectHumanMessage(message.content);\n });\n\n await this.setState(\"connected\");\n this.connection.sendEvent({\n type: \"connected\",\n taskId: this.config.taskId,\n });\n this.startHeartbeat();\n\n // --- Phase 2: Setup (task mode + codespace only) ---\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 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 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 // --- 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 this.runSdkQuery(this.taskContext);\n if (!this.stopped) {\n await this.setState(\"idle\");\n }\n }\n\n // --- Phase 5: Core loop — stay alive for follow-up messages ---\n while (!this.stopped) {\n if (this._state === \"idle\") {\n const msg = await this.waitForUserContent();\n if (!msg) break;\n\n await this.setState(\"running\");\n await this.runSdkQuery(this.taskContext, msg);\n\n if (!this.stopped) {\n await this.setState(\"idle\");\n }\n } else if (this._state === \"error\") {\n await this.setState(\"idle\");\n } else {\n break;\n }\n }\n\n // --- Cleanup ---\n this.stopHeartbeat();\n await this.setState(\"finished\");\n this.connection.disconnect();\n }\n\n /**\n * Wraps project setup in try/catch. On failure, posts error to chat\n * directly (no SDK needed) and streams to CLI. Returns false if setup failed.\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(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 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 /**\n * Wait for the next user message content string. Drains pendingMessages first.\n * Returns null if stopped.\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;\n }\n\n const msg = await this.waitForMessage();\n if (!msg) return null;\n return (msg.message as { content: string }).content;\n }\n\n private async *createInputStream(\n initialPrompt: string,\n ): 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) {\n yield next;\n }\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 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 if (context.claudeSessionId && scenario !== \"fresh\") {\n if (this.config.mode === \"pm\") {\n const lastAgentIdx = this.findLastAgentMessageIndex(context.chatHistory);\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 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 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 if (this.config.mode === \"pm\") {\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}\".`,\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 }\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 if (this.config.mode === \"pm\") {\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 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\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 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 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<{ retriable: boolean }> {\n const startTime = Date.now();\n let totalCostUsd = 0;\n let sessionIdStored = false;\n let isTyping = false;\n let retriable = 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 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 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 if (API_ERROR_PATTERN.test(summary) && durationMs < 30_000) {\n retriable = true;\n }\n\n this.connection.sendEvent({\n type: \"completed\",\n summary,\n costUsd: totalCostUsd,\n durationMs,\n });\n\n if (totalCostUsd > 0 && context.agentId) {\n const estimatedTotalTokens = Math.round(totalCostUsd * 100000);\n const estimatedInputTokens = Math.round(estimatedTotalTokens * 0.7);\n const estimatedOutputTokens = Math.round(estimatedTotalTokens * 0.3);\n\n this.connection.trackSpending({\n agentId: context.agentId,\n inputTokens: estimatedInputTokens,\n outputTokens: estimatedOutputTokens,\n totalTokens: estimatedTotalTokens,\n totalCostUsd,\n onSubscription: this.config.mode === \"pm\" || !!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\n if (API_ERROR_PATTERN.test(errorMsg)) {\n retriable = true;\n }\n\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 if (isTyping) {\n this.connection.sendTypingStop();\n }\n\n return { retriable };\n }\n\n /**\n * Runs one SDK query cycle. For PM mode this is a single-turn query per\n * user message. For task mode this uses the long-running input stream\n * (initial execution) or a single follow-up prompt.\n */\n // oxlint-disable-next-line max-lines-per-function\n private async runSdkQuery(context: TaskContext, followUpContent?: string): 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 isPm = this.config.mode === \"pm\";\n const commonOptions = {\n model,\n systemPrompt,\n settingSources,\n cwd: this.config.workspaceDir,\n permissionMode: (isPm ? \"plan\" : \"bypassPermissions\") as \"plan\" | \"bypassPermissions\",\n allowDangerouslySkipPermissions: !isPm,\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 resume = context.claudeSessionId ?? undefined;\n\n if (followUpContent) {\n // Follow-up message: single prompt, resume session\n const prompt = isPm\n ? `${this.buildInitialPrompt(context)}\\n\\n---\\n\\nThe team says:\\n${followUpContent}`\n : followUpContent;\n\n const agentQuery = query({\n prompt,\n options: { ...commonOptions, resume },\n });\n await this.runWithRetry(agentQuery, context, commonOptions);\n } else if (isPm) {\n // PM initial: no-op, we go straight to idle and wait for messages\n return;\n } else {\n // Task initial: long-running query with input stream\n const initialPrompt = this.buildInitialPrompt(context);\n const agentQuery = query({\n prompt: this.createInputStream(initialPrompt),\n options: { ...commonOptions, resume },\n });\n await this.runWithRetry(agentQuery, context, commonOptions);\n }\n }\n\n /**\n * Run a query with retry logic for transient API errors.\n */\n private async runWithRetry(\n initialQuery: AsyncGenerator<SDKMessage, void>,\n context: TaskContext,\n // oxlint-disable-next-line typescript/no-explicit-any\n options: Record<string, any>,\n ): Promise<void> {\n for (let attempt = 0; attempt <= RETRY_DELAYS_MS.length; attempt++) {\n if (this.stopped) return;\n\n const agentQuery =\n attempt === 0\n ? initialQuery\n : query({\n prompt: this.createInputStream(this.buildInitialPrompt(context)),\n options: { ...options, resume: undefined },\n });\n\n try {\n const { retriable } = await this.processEvents(agentQuery, context);\n if (!retriable || this.stopped) 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 this.connection.storeSessionId(\"\");\n const freshCtx = { ...context, claudeSessionId: null };\n const freshQuery = query({\n prompt: this.createInputStream(this.buildInitialPrompt(freshCtx)),\n options: { ...options, resume: undefined },\n });\n return this.runWithRetry(freshQuery, freshCtx, 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 this.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 this.connection.postChatMessage(\n `API error encountered. Retrying in ${delayMin} minute${delayMin > 1 ? \"s\" : \"\"}... (attempt ${attempt + 1}/${RETRY_DELAYS_MS.length})`,\n );\n this.connection.sendEvent({\n type: \"error\",\n message: `API error, retrying in ${delayMin}m (${attempt + 1}/${RETRY_DELAYS_MS.length})`,\n });\n this.connection.emitStatus(\"waiting_for_input\");\n await this.callbacks.onStatusChange(\"waiting_for_input\");\n\n await new Promise<void>((resolve) => {\n const timer = setTimeout(resolve, delayMs);\n const checkStopped = setInterval(() => {\n if (this.stopped) {\n clearTimeout(timer);\n clearInterval(checkStopped);\n resolve();\n }\n }, 1000);\n setTimeout(() => clearInterval(checkStopped), delayMs + 100);\n });\n\n this.connection.emitStatus(\"running\");\n await this.callbacks.onStatusChange(\"running\");\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":["execSync","execSync"]}