@rallycry/conveyor-agent 0.1.0 → 0.3.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -6,24 +6,39 @@ var ConveyorConnection = class {
6
6
  constructor(config) {
7
7
  this.config = config;
8
8
  }
9
- async connect() {
9
+ connect() {
10
10
  return new Promise((resolve, reject) => {
11
+ let settled = false;
12
+ let attempts = 0;
13
+ const maxInitialAttempts = 30;
11
14
  this.socket = io(this.config.conveyorApiUrl, {
12
15
  auth: { taskToken: this.config.taskToken },
13
16
  transports: ["websocket"],
14
17
  reconnection: true,
15
- reconnectionAttempts: 10,
16
- reconnectionDelay: 1e3
18
+ reconnectionAttempts: Infinity,
19
+ reconnectionDelay: 2e3,
20
+ reconnectionDelayMax: 3e4,
21
+ randomizationFactor: 0.3,
22
+ extraHeaders: {
23
+ "ngrok-skip-browser-warning": "true"
24
+ }
17
25
  });
18
26
  this.socket.on("connect", () => {
19
- resolve();
27
+ if (!settled) {
28
+ settled = true;
29
+ resolve();
30
+ }
20
31
  });
21
- this.socket.on("connect_error", (err) => {
22
- reject(err);
32
+ this.socket.io.on("reconnect_attempt", () => {
33
+ attempts++;
34
+ if (!settled && attempts >= maxInitialAttempts) {
35
+ settled = true;
36
+ reject(new Error(`Failed to connect after ${maxInitialAttempts} attempts`));
37
+ }
23
38
  });
24
39
  });
25
40
  }
26
- async fetchTaskContext() {
41
+ fetchTaskContext() {
27
42
  const socket = this.socket;
28
43
  if (!socket) throw new Error("Not connected");
29
44
  return new Promise((resolve, reject) => {
@@ -61,6 +76,23 @@ var ConveyorConnection = class {
61
76
  content
62
77
  });
63
78
  }
79
+ createPR(params) {
80
+ const socket = this.socket;
81
+ if (!socket) throw new Error("Not connected");
82
+ return new Promise((resolve, reject) => {
83
+ socket.emit(
84
+ "agentRunner:createPR",
85
+ { taskId: this.config.taskId, ...params },
86
+ (response) => {
87
+ if (response.success && response.data) {
88
+ resolve(response.data);
89
+ } else {
90
+ reject(new Error(response.error ?? "Failed to create pull request"));
91
+ }
92
+ }
93
+ );
94
+ });
95
+ }
64
96
  onChatMessage(callback) {
65
97
  this.socket?.on("agentRunner:incomingMessage", callback);
66
98
  }
@@ -74,7 +106,11 @@ var ConveyorConnection = class {
74
106
  };
75
107
 
76
108
  // src/runner.ts
77
- import { query, tool, createSdkMcpServer } from "@anthropic-ai/claude-agent-sdk";
109
+ import {
110
+ query,
111
+ tool,
112
+ createSdkMcpServer
113
+ } from "@anthropic-ai/claude-agent-sdk";
78
114
  import { z } from "zod";
79
115
  var AgentRunner = class {
80
116
  config;
@@ -163,8 +199,22 @@ var AgentRunner = class {
163
199
  yield msg;
164
200
  }
165
201
  }
202
+ findLastAgentMessageIndex(history) {
203
+ for (let i = history.length - 1; i >= 0; i--) {
204
+ if (history[i].role === "assistant") return i;
205
+ }
206
+ return -1;
207
+ }
208
+ detectRelaunchScenario(context) {
209
+ const lastAgentIdx = this.findLastAgentMessageIndex(context.chatHistory);
210
+ if (lastAgentIdx === -1) return "fresh";
211
+ const messagesAfterAgent = context.chatHistory.slice(lastAgentIdx + 1);
212
+ const hasNewUserMessages = messagesAfterAgent.some((m) => m.role === "user");
213
+ return hasNewUserMessages ? "feedback_relaunch" : "idle_relaunch";
214
+ }
166
215
  buildInitialPrompt(context) {
167
216
  const parts = [];
217
+ const scenario = this.detectRelaunchScenario(context);
168
218
  parts.push(`# Task: ${context.title}`);
169
219
  if (context.description) {
170
220
  parts.push(`
@@ -185,12 +235,46 @@ ${context.plan}`);
185
235
  parts.push(`[${sender}]: ${msg.content}`);
186
236
  }
187
237
  }
188
- parts.push(
189
- `
190
- ## Instructions`,
191
- `Execute the task plan above. Work on the git branch "${context.githubBranch}".`,
192
- `When finished, commit your changes, push the branch, and create a pull request.`
193
- );
238
+ parts.push(`
239
+ ## Instructions`);
240
+ if (scenario === "fresh") {
241
+ parts.push(
242
+ `Execute the task plan above. Work on the git branch "${context.githubBranch}".`,
243
+ `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.`
244
+ );
245
+ } else if (scenario === "idle_relaunch") {
246
+ parts.push(
247
+ `You were relaunched but no new instructions have been given since your last run.`,
248
+ `Work on the git branch "${context.githubBranch}".`,
249
+ `Review the current state of the codebase and verify everything is working correctly (e.g. tests pass, the web server starts on port 3000).`,
250
+ `Post a brief status update to the chat summarizing the current state.`,
251
+ `Then wait for further instructions \u2014 do NOT redo work that was already completed.`
252
+ );
253
+ if (context.githubPRUrl) {
254
+ parts.push(`An existing PR is open at ${context.githubPRUrl}. Do not create a new PR.`);
255
+ }
256
+ } else {
257
+ const lastAgentIdx = this.findLastAgentMessageIndex(context.chatHistory);
258
+ const newMessages = context.chatHistory.slice(lastAgentIdx + 1).filter((m) => m.role === "user");
259
+ parts.push(
260
+ `You were relaunched with new feedback since your last run.`,
261
+ `Work on the git branch "${context.githubBranch}".`,
262
+ `
263
+ New messages since your last run:`,
264
+ ...newMessages.map((m) => `[${m.userName ?? "user"}]: ${m.content}`),
265
+ `
266
+ Address the requested changes. Commit and push your updates.`
267
+ );
268
+ if (context.githubPRUrl) {
269
+ parts.push(
270
+ `An existing PR is open at ${context.githubPRUrl} \u2014 push to the same branch to update it. Do NOT create a new PR.`
271
+ );
272
+ } else {
273
+ parts.push(
274
+ `When finished, use the create_pull_request tool to open a PR. Do NOT use gh CLI or any other method to create PRs.`
275
+ );
276
+ }
277
+ }
194
278
  return parts.join("\n");
195
279
  }
196
280
  buildSystemPrompt(context) {
@@ -207,11 +291,12 @@ ${this.config.instructions}`);
207
291
  `
208
292
  You have access to Conveyor MCP tools to interact with the task management system.`,
209
293
  `Use the post_to_chat tool to communicate progress or ask questions.`,
210
- `Use the read_task_chat tool to check for new messages from the team.`
294
+ `Use the read_task_chat tool to check for new messages from the team.`,
295
+ `Use the create_pull_request tool to open PRs \u2014 do NOT use gh CLI or shell commands for PR creation.`
211
296
  );
212
297
  return parts.join("\n");
213
298
  }
214
- // eslint-disable-next-line @typescript-eslint/explicit-function-return-type
299
+ // oxlint-disable-next-line typescript/explicit-function-return-type, max-lines-per-function
215
300
  createConveyorMcpServer() {
216
301
  const connection = this.connection;
217
302
  const config = this.config;
@@ -224,11 +309,17 @@ You have access to Conveyor MCP tools to interact with the task management syste
224
309
  tool(
225
310
  "read_task_chat",
226
311
  "Read recent messages from the task chat to see team feedback or instructions",
227
- { limit: z.number().optional().describe("Number of recent messages to fetch (default 20)") },
312
+ {
313
+ limit: z.number().optional().describe("Number of recent messages to fetch (default 20)")
314
+ },
228
315
  (_args) => {
229
- return Promise.resolve(textResult(
230
- JSON.stringify({ note: "Chat history was provided in the initial context. Use post_to_chat to ask the team questions." })
231
- ));
316
+ return Promise.resolve(
317
+ textResult(
318
+ JSON.stringify({
319
+ note: "Chat history was provided in the initial context. Use post_to_chat to ask the team questions."
320
+ })
321
+ )
322
+ );
232
323
  },
233
324
  { annotations: { readOnly: true } }
234
325
  ),
@@ -253,15 +344,21 @@ You have access to Conveyor MCP tools to interact with the task management syste
253
344
  }
254
345
  ),
255
346
  tool(
256
- "report_pr_created",
257
- "Report that a pull request has been created for this task",
347
+ "create_pull_request",
348
+ "Create a GitHub pull request for this task. Use this instead of gh CLI or git commands to create PRs.",
258
349
  {
259
- url: z.string().describe("The URL of the pull request"),
260
- number: z.number().describe("The PR number")
350
+ title: z.string().describe("The PR title"),
351
+ body: z.string().describe("The PR description/body in markdown")
261
352
  },
262
- ({ url, number }) => {
263
- connection.sendEvent({ type: "pr_created", url, number });
264
- return Promise.resolve(textResult(`PR #${number} reported to Conveyor.`));
353
+ async ({ title, body }) => {
354
+ try {
355
+ const result = await connection.createPR({ title, body });
356
+ connection.sendEvent({ type: "pr_created", url: result.url, number: result.number });
357
+ return textResult(`Pull request #${result.number} created: ${result.url}`);
358
+ } catch (error) {
359
+ const msg = error instanceof Error ? error.message : "Unknown error";
360
+ return textResult(`Failed to create pull request: ${msg}`);
361
+ }
265
362
  }
266
363
  ),
267
364
  tool(
@@ -281,6 +378,7 @@ You have access to Conveyor MCP tools to interact with the task management syste
281
378
  ]
282
379
  });
283
380
  }
381
+ // oxlint-disable-next-line max-lines-per-function, complexity
284
382
  async processEvents(events) {
285
383
  const startTime = Date.now();
286
384
  let totalCostUsd = 0;
@@ -399,4 +497,4 @@ export {
399
497
  ConveyorConnection,
400
498
  AgentRunner
401
499
  };
402
- //# sourceMappingURL=chunk-LTQXNGLW.js.map
500
+ //# sourceMappingURL=chunk-XRNZVTJT.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../src/connection.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\n constructor(config: AgentRunnerConfig) {\n this.config = config;\n }\n\n connect(): Promise<void> {\n return new Promise((resolve, reject) => {\n let settled = false;\n let attempts = 0;\n const maxInitialAttempts = 30;\n\n this.socket = io(this.config.conveyorApiUrl, {\n auth: { taskToken: this.config.taskToken },\n transports: [\"websocket\"],\n reconnection: true,\n reconnectionAttempts: Infinity,\n reconnectionDelay: 2000,\n reconnectionDelayMax: 30000,\n randomizationFactor: 0.3,\n extraHeaders: {\n \"ngrok-skip-browser-warning\": \"true\",\n },\n });\n\n this.socket.on(\"connect\", () => {\n if (!settled) {\n settled = true;\n resolve();\n }\n });\n\n this.socket.io.on(\"reconnect_attempt\", () => {\n attempts++;\n if (!settled && attempts >= maxInitialAttempts) {\n settled = true;\n reject(new Error(`Failed to connect after ${maxInitialAttempts} attempts`));\n }\n });\n });\n }\n\n fetchTaskContext(): Promise<TaskContext> {\n const socket = this.socket;\n if (!socket) throw new Error(\"Not connected\");\n\n return new Promise((resolve, reject) => {\n socket.emit(\n \"agentRunner:getTaskContext\",\n { taskId: this.config.taskId },\n (response: { success: boolean; data?: TaskContext; error?: string }): void => {\n if (response.success && response.data) {\n resolve(response.data);\n } else {\n reject(new Error(response.error ?? \"Failed to fetch task context\"));\n }\n },\n );\n });\n }\n\n sendEvent(event: AgentEvent): void {\n if (!this.socket) throw new Error(\"Not connected\");\n\n this.socket.emit(\"agentRunner:event\", {\n taskId: this.config.taskId,\n event,\n });\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 onChatMessage(callback: (message: { content: string; userId: string }) => void): void {\n this.socket?.on(\"agentRunner:incomingMessage\", callback);\n }\n\n onStopRequested(callback: () => void): void {\n this.socket?.on(\"agentRunner:stop\", callback);\n }\n\n disconnect(): void {\n this.socket?.disconnect();\n this.socket = null;\n }\n}\n","// oxlint-disable max-lines\nimport {\n query,\n tool,\n createSdkMcpServer,\n type SDKMessage,\n type SDKUserMessage,\n} from \"@anthropic-ai/claude-agent-sdk\";\nimport { z } from \"zod\";\nimport type {\n AgentRunnerConfig,\n AgentRunnerCallbacks,\n TaskContext,\n ActivityEventSummary,\n} from \"./types.js\";\nimport { ConveyorConnection } from \"./connection.js\";\n\nexport class AgentRunner {\n private config: AgentRunnerConfig;\n private connection: ConveyorConnection;\n private callbacks: AgentRunnerCallbacks;\n private stopped = false;\n private inputResolver: ((msg: SDKUserMessage) => void) | null = null;\n private pendingMessages: SDKUserMessage[] = [];\n private currentTurnToolCalls: ActivityEventSummary[] = [];\n\n constructor(config: AgentRunnerConfig, callbacks: AgentRunnerCallbacks) {\n this.config = config;\n this.connection = new ConveyorConnection(config);\n this.callbacks = callbacks;\n }\n\n async start(): Promise<void> {\n await this.callbacks.onStatusChange(\"connecting\");\n await this.connection.connect();\n\n await this.callbacks.onStatusChange(\"fetching_context\");\n const context = await this.connection.fetchTaskContext();\n\n this.connection.onStopRequested(() => {\n this.stopped = true;\n });\n\n this.connection.onChatMessage((message) => {\n this.injectHumanMessage(message.content);\n });\n\n await this.callbacks.onStatusChange(\"running\");\n this.connection.sendEvent({\n type: \"connected\",\n taskId: this.config.taskId,\n });\n\n try {\n await this.executeTask(context);\n } catch (error) {\n const message = error instanceof Error ? error.message : \"Unknown error\";\n this.connection.sendEvent({ type: \"error\", message });\n await this.callbacks.onEvent({ type: \"error\", message });\n throw error;\n } finally {\n await this.callbacks.onStatusChange(\"finished\");\n this.connection.disconnect();\n }\n }\n\n private injectHumanMessage(content: string): void {\n const msg: SDKUserMessage = {\n type: \"user\" as const,\n session_id: \"\",\n message: { role: \"user\" as const, content },\n parent_tool_use_id: null,\n };\n\n if (this.inputResolver) {\n const resolve = this.inputResolver;\n this.inputResolver = null;\n resolve(msg);\n } else {\n this.pendingMessages.push(msg);\n }\n }\n\n private async *createInputStream(\n initialPrompt: string,\n ): AsyncGenerator<SDKUserMessage, void, unknown> {\n yield {\n type: \"user\" as const,\n session_id: \"\",\n message: { role: \"user\" as const, content: initialPrompt },\n parent_tool_use_id: null,\n };\n\n while (!this.stopped) {\n if (this.pendingMessages.length > 0) {\n const next = this.pendingMessages.shift();\n if (next) {\n yield next;\n }\n continue;\n }\n\n await this.callbacks.onStatusChange(\"waiting_for_input\");\n const msg = await new Promise<SDKUserMessage | null>((resolve) => {\n this.inputResolver = resolve as (msg: SDKUserMessage) => void;\n\n const checkStopped = setInterval(() => {\n if (this.stopped) {\n clearInterval(checkStopped);\n this.inputResolver = null;\n resolve(null);\n }\n }, 1000);\n });\n\n if (!msg) break;\n await this.callbacks.onStatusChange(\"running\");\n yield msg;\n }\n }\n\n private findLastAgentMessageIndex(history: TaskContext[\"chatHistory\"]): number {\n for (let i = history.length - 1; i >= 0; i--) {\n if (history[i].role === \"assistant\") return i;\n }\n return -1;\n }\n\n private detectRelaunchScenario(\n context: TaskContext,\n ): \"fresh\" | \"idle_relaunch\" | \"feedback_relaunch\" {\n const lastAgentIdx = this.findLastAgentMessageIndex(context.chatHistory);\n if (lastAgentIdx === -1) return \"fresh\";\n\n const messagesAfterAgent = context.chatHistory.slice(lastAgentIdx + 1);\n const hasNewUserMessages = messagesAfterAgent.some((m) => m.role === \"user\");\n return hasNewUserMessages ? \"feedback_relaunch\" : \"idle_relaunch\";\n }\n\n private buildInitialPrompt(context: TaskContext): string {\n const parts: string[] = [];\n const scenario = this.detectRelaunchScenario(context);\n\n parts.push(`# Task: ${context.title}`);\n if (context.description) {\n parts.push(`\\n## Description\\n${context.description}`);\n }\n if (context.plan) {\n parts.push(`\\n## Plan\\n${context.plan}`);\n }\n\n if (context.chatHistory.length > 0) {\n const relevant = context.chatHistory.slice(-20);\n parts.push(`\\n## Recent Chat Context`);\n for (const msg of relevant) {\n const sender = msg.userName ?? msg.role;\n parts.push(`[${sender}]: ${msg.content}`);\n }\n }\n\n parts.push(`\\n## Instructions`);\n\n if (scenario === \"fresh\") {\n parts.push(\n `Execute the task plan above. Work on the git branch \"${context.githubBranch}\".`,\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 } else if (scenario === \"idle_relaunch\") {\n parts.push(\n `You were relaunched but no new instructions have been given since your last run.`,\n `Work on the git branch \"${context.githubBranch}\".`,\n `Review the current state of the codebase and verify everything is working correctly (e.g. tests pass, the web server starts on port 3000).`,\n `Post a brief status update to the chat summarizing the current state.`,\n `Then wait for further instructions — do NOT redo work that was already completed.`,\n );\n if (context.githubPRUrl) {\n parts.push(`An existing PR is open at ${context.githubPRUrl}. Do not create a new PR.`);\n }\n } else {\n const lastAgentIdx = this.findLastAgentMessageIndex(context.chatHistory);\n const newMessages = context.chatHistory\n .slice(lastAgentIdx + 1)\n .filter((m) => m.role === \"user\");\n parts.push(\n `You were relaunched with new feedback since your last run.`,\n `Work on the git branch \"${context.githubBranch}\".`,\n `\\nNew messages since your last run:`,\n ...newMessages.map((m) => `[${m.userName ?? \"user\"}]: ${m.content}`),\n `\\nAddress the requested changes. Commit and push your updates.`,\n );\n if (context.githubPRUrl) {\n parts.push(\n `An existing PR is open at ${context.githubPRUrl} — push to the same branch to update it. Do NOT create a new PR.`,\n );\n } else {\n parts.push(\n `When finished, use the create_pull_request tool to open a PR. Do NOT use gh CLI or any other method to create PRs.`,\n );\n }\n }\n\n return parts.join(\"\\n\");\n }\n\n private buildSystemPrompt(context: TaskContext): string {\n const parts = [\n `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 ];\n if (this.config.instructions) {\n parts.push(`\\nAgent 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 `Use the create_pull_request tool to open PRs — do NOT use gh CLI or shell commands for PR creation.`,\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() {\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 return createSdkMcpServer({\n name: \"conveyor\",\n tools: [\n tool(\n \"read_task_chat\",\n \"Read recent messages from the task chat to see team feedback or instructions\",\n {\n limit: z\n .number()\n .optional()\n .describe(\"Number of recent messages to fetch (default 20)\"),\n },\n (_args) => {\n return Promise.resolve(\n textResult(\n JSON.stringify({\n note: \"Chat history was provided in the initial context. Use post_to_chat to ask the team questions.\",\n }),\n ),\n );\n },\n { annotations: { readOnly: true } },\n ),\n tool(\n \"post_to_chat\",\n \"Post a message to the task chat visible to all team members\",\n { message: z.string().describe(\"The message to post to the team\") },\n ({ message }) => {\n connection.postChatMessage(message);\n return Promise.resolve(textResult(\"Message posted to task chat.\"));\n },\n ),\n tool(\n \"update_task_status\",\n \"Update the task status on the Kanban board\",\n {\n status: z\n .enum([\"InProgress\", \"ReviewPR\", \"Complete\"])\n .describe(\"The new status for the task\"),\n },\n ({ status }) => {\n connection.updateStatus(status);\n return Promise.resolve(textResult(`Task status updated to ${status}.`));\n },\n ),\n tool(\n \"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({ type: \"pr_created\", url: result.url, number: result.number });\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 tool(\n \"get_task_plan\",\n \"Re-read the latest task plan in case it was updated\",\n {},\n async () => {\n try {\n const context = await connection.fetchTaskContext();\n return textResult(context.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 }\n\n // oxlint-disable-next-line max-lines-per-function, complexity\n private async processEvents(events: AsyncGenerator<SDKMessage, void>): Promise<void> {\n const startTime = Date.now();\n let totalCostUsd = 0;\n\n for await (const event of events) {\n if (this.stopped) break;\n\n switch (event.type) {\n case \"assistant\": {\n const msg = event.message as unknown as Record<string, unknown>;\n const content = msg.content as Record<string, unknown>[];\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 this.connection.sendEvent({ type: \"message\", content: text });\n this.connection.postChatMessage(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 summary: ActivityEventSummary = {\n tool: name,\n input: inputStr.slice(0, 500),\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 (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 const resultEvent = event as SDKMessage & { type: \"result\"; subtype: string };\n if (resultEvent.subtype === \"success\") {\n totalCostUsd =\n \"total_cost_usd\" in resultEvent\n ? ((resultEvent as Record<string, unknown>).total_cost_usd as number)\n : 0;\n const durationMs = Date.now() - startTime;\n const summary =\n \"result\" in resultEvent\n ? String((resultEvent as Record<string, unknown>).result)\n : \"Task completed.\";\n\n this.connection.sendEvent({\n type: \"completed\",\n summary,\n costUsd: totalCostUsd,\n durationMs,\n });\n\n await this.callbacks.onEvent({\n type: \"completed\",\n summary,\n costUsd: totalCostUsd,\n durationMs,\n });\n } else {\n const errors =\n \"errors\" in resultEvent\n ? ((resultEvent as Record<string, unknown>).errors as string[])\n : [];\n const errorMsg =\n errors.length > 0 ? errors.join(\", \") : `Agent stopped: ${resultEvent.subtype}`;\n this.connection.sendEvent({ type: \"error\", message: errorMsg });\n await this.callbacks.onEvent({ type: \"error\", message: errorMsg });\n }\n break;\n }\n\n case \"system\": {\n if (event.subtype === \"init\") {\n await this.callbacks.onEvent({\n type: \"thinking\",\n message: `Agent initialized (model: ${event.model})`,\n });\n }\n break;\n }\n }\n }\n }\n\n private async executeTask(context: TaskContext): Promise<void> {\n if (this.stopped) return;\n\n const initialPrompt = this.buildInitialPrompt(context);\n const systemPrompt = this.buildSystemPrompt(context);\n const conveyorMcp = this.createConveyorMcpServer();\n const inputStream = this.createInputStream(initialPrompt);\n\n const agentQuery = query({\n prompt: inputStream,\n options: {\n model: this.config.model,\n systemPrompt,\n cwd: this.config.workspaceDir,\n permissionMode: \"bypassPermissions\",\n allowDangerouslySkipPermissions: true,\n tools: { type: \"preset\", preset: \"claude_code\" },\n mcpServers: { conveyor: conveyorMcp },\n maxTurns: 100,\n },\n });\n\n await this.processEvents(agentQuery);\n }\n\n stop(): void {\n this.stopped = true;\n if (this.inputResolver) {\n this.inputResolver(null as unknown as SDKUserMessage);\n this.inputResolver = null;\n }\n }\n}\n"],"mappings":"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","names":[]}
package/dist/cli.js CHANGED
@@ -1,7 +1,7 @@
1
1
  #!/usr/bin/env node
2
2
  import {
3
3
  AgentRunner
4
- } from "./chunk-LTQXNGLW.js";
4
+ } from "./chunk-XRNZVTJT.js";
5
5
 
6
6
  // src/cli.ts
7
7
  var CONVEYOR_API_URL = process.env.CONVEYOR_API_URL;
package/dist/cli.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"sources":["../src/cli.ts"],"sourcesContent":["#!/usr/bin/env node\n/* eslint-disable no-console */\n\nimport { AgentRunner } from \"./runner.js\";\nimport type { AgentEvent, AgentRunnerStatus } from \"./types.js\";\n\nconst CONVEYOR_API_URL = process.env.CONVEYOR_API_URL;\nconst CONVEYOR_TASK_TOKEN = process.env.CONVEYOR_TASK_TOKEN;\nconst CONVEYOR_TASK_ID = process.env.CONVEYOR_TASK_ID;\nconst CONVEYOR_MODEL = process.env.CONVEYOR_MODEL ?? \"claude-sonnet-4-20250514\";\nconst CONVEYOR_INSTRUCTIONS = process.env.CONVEYOR_INSTRUCTIONS ?? \"\";\nconst CONVEYOR_WORKSPACE = process.env.CONVEYOR_WORKSPACE ?? process.cwd();\n\nif (!CONVEYOR_API_URL || !CONVEYOR_TASK_TOKEN || !CONVEYOR_TASK_ID) {\n console.error(\"Missing required environment variables:\");\n console.error(\" CONVEYOR_API_URL - URL of the Conveyor API server\");\n console.error(\" CONVEYOR_TASK_TOKEN - JWT token for task authentication\");\n console.error(\" CONVEYOR_TASK_ID - ID of the task to execute\");\n process.exit(1);\n}\n\nconst runner = new AgentRunner(\n {\n conveyorApiUrl: CONVEYOR_API_URL,\n taskToken: CONVEYOR_TASK_TOKEN,\n taskId: CONVEYOR_TASK_ID,\n model: CONVEYOR_MODEL,\n instructions: CONVEYOR_INSTRUCTIONS,\n workspaceDir: CONVEYOR_WORKSPACE,\n },\n {\n onEvent: (event: AgentEvent) => {\n const detail =\n \"message\" in event\n ? event.message\n : \"content\" in event\n ? event.content\n : \"summary\" in event\n ? event.summary\n : \"\";\n console.log(`[${event.type}] ${detail}`);\n },\n onStatusChange: (status: AgentRunnerStatus) => {\n console.log(`[status] ${status}`);\n },\n }\n);\n\nprocess.on(\"SIGTERM\", () => {\n console.log(\"Received SIGTERM, stopping agent...\");\n runner.stop();\n});\n\nprocess.on(\"SIGINT\", () => {\n console.log(\"Received SIGINT, stopping agent...\");\n runner.stop();\n});\n\nrunner.start().catch((error: unknown) => {\n console.error(\"Agent runner failed:\", error);\n process.exit(1);\n});\n"],"mappings":";;;;;;AAMA,IAAM,mBAAmB,QAAQ,IAAI;AACrC,IAAM,sBAAsB,QAAQ,IAAI;AACxC,IAAM,mBAAmB,QAAQ,IAAI;AACrC,IAAM,iBAAiB,QAAQ,IAAI,kBAAkB;AACrD,IAAM,wBAAwB,QAAQ,IAAI,yBAAyB;AACnE,IAAM,qBAAqB,QAAQ,IAAI,sBAAsB,QAAQ,IAAI;AAEzE,IAAI,CAAC,oBAAoB,CAAC,uBAAuB,CAAC,kBAAkB;AAClE,UAAQ,MAAM,yCAAyC;AACvD,UAAQ,MAAM,qDAAqD;AACnE,UAAQ,MAAM,2DAA2D;AACzE,UAAQ,MAAM,gDAAgD;AAC9D,UAAQ,KAAK,CAAC;AAChB;AAEA,IAAM,SAAS,IAAI;AAAA,EACjB;AAAA,IACE,gBAAgB;AAAA,IAChB,WAAW;AAAA,IACX,QAAQ;AAAA,IACR,OAAO;AAAA,IACP,cAAc;AAAA,IACd,cAAc;AAAA,EAChB;AAAA,EACA;AAAA,IACE,SAAS,CAAC,UAAsB;AAC9B,YAAM,SACJ,aAAa,QACT,MAAM,UACN,aAAa,QACX,MAAM,UACN,aAAa,QACX,MAAM,UACN;AACV,cAAQ,IAAI,IAAI,MAAM,IAAI,KAAK,MAAM,EAAE;AAAA,IACzC;AAAA,IACA,gBAAgB,CAAC,WAA8B;AAC7C,cAAQ,IAAI,YAAY,MAAM,EAAE;AAAA,IAClC;AAAA,EACF;AACF;AAEA,QAAQ,GAAG,WAAW,MAAM;AAC1B,UAAQ,IAAI,qCAAqC;AACjD,SAAO,KAAK;AACd,CAAC;AAED,QAAQ,GAAG,UAAU,MAAM;AACzB,UAAQ,IAAI,oCAAoC;AAChD,SAAO,KAAK;AACd,CAAC;AAED,OAAO,MAAM,EAAE,MAAM,CAAC,UAAmB;AACvC,UAAQ,MAAM,wBAAwB,KAAK;AAC3C,UAAQ,KAAK,CAAC;AAChB,CAAC;","names":[]}
1
+ {"version":3,"sources":["../src/cli.ts"],"sourcesContent":["#!/usr/bin/env node\n/* oxlint-disable no-console */\n\nimport { AgentRunner } from \"./runner.js\";\nimport type { AgentEvent, AgentRunnerStatus } from \"./types.js\";\n\nconst CONVEYOR_API_URL = process.env.CONVEYOR_API_URL;\nconst CONVEYOR_TASK_TOKEN = process.env.CONVEYOR_TASK_TOKEN;\nconst CONVEYOR_TASK_ID = process.env.CONVEYOR_TASK_ID;\nconst CONVEYOR_MODEL = process.env.CONVEYOR_MODEL ?? \"claude-sonnet-4-20250514\";\nconst CONVEYOR_INSTRUCTIONS = process.env.CONVEYOR_INSTRUCTIONS ?? \"\";\nconst CONVEYOR_WORKSPACE = process.env.CONVEYOR_WORKSPACE ?? process.cwd();\n\nif (!CONVEYOR_API_URL || !CONVEYOR_TASK_TOKEN || !CONVEYOR_TASK_ID) {\n console.error(\"Missing required environment variables:\");\n console.error(\" CONVEYOR_API_URL - URL of the Conveyor API server\");\n console.error(\" CONVEYOR_TASK_TOKEN - JWT token for task authentication\");\n console.error(\" CONVEYOR_TASK_ID - ID of the task to execute\");\n process.exit(1);\n}\n\nconst runner = new AgentRunner(\n {\n conveyorApiUrl: CONVEYOR_API_URL,\n taskToken: CONVEYOR_TASK_TOKEN,\n taskId: CONVEYOR_TASK_ID,\n model: CONVEYOR_MODEL,\n instructions: CONVEYOR_INSTRUCTIONS,\n workspaceDir: CONVEYOR_WORKSPACE,\n },\n {\n onEvent: (event: AgentEvent) => {\n const detail =\n \"message\" in event\n ? event.message\n : \"content\" in event\n ? event.content\n : \"summary\" in event\n ? event.summary\n : \"\";\n console.log(`[${event.type}] ${detail}`);\n },\n onStatusChange: (status: AgentRunnerStatus) => {\n console.log(`[status] ${status}`);\n },\n },\n);\n\nprocess.on(\"SIGTERM\", () => {\n console.log(\"Received SIGTERM, stopping agent...\");\n runner.stop();\n});\n\nprocess.on(\"SIGINT\", () => {\n console.log(\"Received SIGINT, stopping agent...\");\n runner.stop();\n});\n\nrunner.start().catch((error: unknown) => {\n console.error(\"Agent runner failed:\", error);\n process.exit(1);\n});\n"],"mappings":";;;;;;AAMA,IAAM,mBAAmB,QAAQ,IAAI;AACrC,IAAM,sBAAsB,QAAQ,IAAI;AACxC,IAAM,mBAAmB,QAAQ,IAAI;AACrC,IAAM,iBAAiB,QAAQ,IAAI,kBAAkB;AACrD,IAAM,wBAAwB,QAAQ,IAAI,yBAAyB;AACnE,IAAM,qBAAqB,QAAQ,IAAI,sBAAsB,QAAQ,IAAI;AAEzE,IAAI,CAAC,oBAAoB,CAAC,uBAAuB,CAAC,kBAAkB;AAClE,UAAQ,MAAM,yCAAyC;AACvD,UAAQ,MAAM,qDAAqD;AACnE,UAAQ,MAAM,2DAA2D;AACzE,UAAQ,MAAM,gDAAgD;AAC9D,UAAQ,KAAK,CAAC;AAChB;AAEA,IAAM,SAAS,IAAI;AAAA,EACjB;AAAA,IACE,gBAAgB;AAAA,IAChB,WAAW;AAAA,IACX,QAAQ;AAAA,IACR,OAAO;AAAA,IACP,cAAc;AAAA,IACd,cAAc;AAAA,EAChB;AAAA,EACA;AAAA,IACE,SAAS,CAAC,UAAsB;AAC9B,YAAM,SACJ,aAAa,QACT,MAAM,UACN,aAAa,QACX,MAAM,UACN,aAAa,QACX,MAAM,UACN;AACV,cAAQ,IAAI,IAAI,MAAM,IAAI,KAAK,MAAM,EAAE;AAAA,IACzC;AAAA,IACA,gBAAgB,CAAC,WAA8B;AAC7C,cAAQ,IAAI,YAAY,MAAM,EAAE;AAAA,IAClC;AAAA,EACF;AACF;AAEA,QAAQ,GAAG,WAAW,MAAM;AAC1B,UAAQ,IAAI,qCAAqC;AACjD,SAAO,KAAK;AACd,CAAC;AAED,QAAQ,GAAG,UAAU,MAAM;AACzB,UAAQ,IAAI,oCAAoC;AAChD,SAAO,KAAK;AACd,CAAC;AAED,OAAO,MAAM,EAAE,MAAM,CAAC,UAAmB;AACvC,UAAQ,MAAM,wBAAwB,KAAK;AAC3C,UAAQ,KAAK,CAAC;AAChB,CAAC;","names":[]}
package/dist/index.d.ts CHANGED
@@ -16,6 +16,7 @@ interface TaskContext {
16
16
  agentInstructions: string;
17
17
  model: string;
18
18
  githubBranch: string;
19
+ githubPRUrl?: string | null;
19
20
  }
20
21
  interface ChatMessage {
21
22
  role: "user" | "assistant" | "system";
@@ -84,6 +85,8 @@ declare class AgentRunner {
84
85
  start(): Promise<void>;
85
86
  private injectHumanMessage;
86
87
  private createInputStream;
88
+ private findLastAgentMessageIndex;
89
+ private detectRelaunchScenario;
87
90
  private buildInitialPrompt;
88
91
  private buildSystemPrompt;
89
92
  private createConveyorMcpServer;
@@ -101,6 +104,14 @@ declare class ConveyorConnection {
101
104
  sendEvent(event: AgentEvent): void;
102
105
  updateStatus(status: string): void;
103
106
  postChatMessage(content: string): void;
107
+ createPR(params: {
108
+ title: string;
109
+ body: string;
110
+ baseBranch?: string;
111
+ }): Promise<{
112
+ url: string;
113
+ number: number;
114
+ }>;
104
115
  onChatMessage(callback: (message: {
105
116
  content: string;
106
117
  userId: string;
package/dist/index.js CHANGED
@@ -1,7 +1,7 @@
1
1
  import {
2
2
  AgentRunner,
3
3
  ConveyorConnection
4
- } from "./chunk-LTQXNGLW.js";
4
+ } from "./chunk-XRNZVTJT.js";
5
5
  export {
6
6
  AgentRunner,
7
7
  ConveyorConnection
package/package.json CHANGED
@@ -1,29 +1,33 @@
1
1
  {
2
2
  "name": "@rallycry/conveyor-agent",
3
- "version": "0.1.0",
3
+ "version": "0.3.0",
4
4
  "description": "Conveyor cloud build agent runner - executes task plans inside GitHub Codespaces",
5
- "type": "module",
6
- "main": "./dist/index.js",
7
- "types": "./dist/index.d.ts",
5
+ "keywords": [
6
+ "agent",
7
+ "claude",
8
+ "codespace",
9
+ "conveyor"
10
+ ],
11
+ "license": "MIT",
8
12
  "bin": {
9
13
  "conveyor-agent": "./dist/cli.js"
10
14
  },
11
15
  "files": [
12
16
  "dist"
13
17
  ],
18
+ "type": "module",
19
+ "main": "./dist/index.js",
20
+ "types": "./dist/index.d.ts",
14
21
  "publishConfig": {
15
22
  "access": "public"
16
23
  },
17
24
  "scripts": {
18
25
  "build": "tsup",
19
26
  "dev": "tsup --watch",
20
- "lint": "eslint src",
21
- "lint:fix": "eslint src --fix",
22
- "typecheck": "tsc --noEmit",
23
- "prepublishOnly": "pnpm build"
27
+ "lint": "oxlint -c ../../.oxlintrc.json src",
28
+ "lint:fix": "oxlint -c ../../.oxlintrc.json --fix src",
29
+ "typecheck": "tsgo --noEmit"
24
30
  },
25
- "keywords": ["conveyor", "agent", "codespace", "claude"],
26
- "license": "MIT",
27
31
  "dependencies": {
28
32
  "@anthropic-ai/claude-agent-sdk": "^0.2.71",
29
33
  "socket.io-client": "^4.7.4",
@@ -31,8 +35,6 @@
31
35
  "zod": "^3.25.76"
32
36
  },
33
37
  "devDependencies": {
34
- "@project/eslint-config": "workspace:*",
35
- "eslint": "^9.0.0",
36
38
  "tsup": "^8.0.0",
37
39
  "typescript": "^5.3.0"
38
40
  }
@@ -1 +0,0 @@
1
- {"version":3,"sources":["../src/connection.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\n constructor(config: AgentRunnerConfig) {\n this.config = config;\n }\n\n async connect(): Promise<void> {\n return new Promise((resolve, reject) => {\n this.socket = io(this.config.conveyorApiUrl, {\n auth: { taskToken: this.config.taskToken },\n transports: [\"websocket\"],\n reconnection: true,\n reconnectionAttempts: 10,\n reconnectionDelay: 1000,\n });\n\n this.socket.on(\"connect\", () => {\n resolve();\n });\n this.socket.on(\"connect_error\", (err: Error) => {\n reject(err);\n });\n });\n }\n\n async 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.socket.emit(\"agentRunner:event\", {\n taskId: this.config.taskId,\n event,\n });\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 onChatMessage(callback: (message: { content: string; userId: string }) => void): void {\n this.socket?.on(\"agentRunner:incomingMessage\", callback);\n }\n\n onStopRequested(callback: () => void): void {\n this.socket?.on(\"agentRunner:stop\", callback);\n }\n\n disconnect(): void {\n this.socket?.disconnect();\n this.socket = null;\n }\n}\n","import { query, tool, createSdkMcpServer, type SDKMessage, type SDKUserMessage } from \"@anthropic-ai/claude-agent-sdk\";\nimport { z } from \"zod\";\nimport type {\n AgentRunnerConfig,\n AgentRunnerCallbacks,\n TaskContext,\n ActivityEventSummary,\n} from \"./types.js\";\nimport { ConveyorConnection } from \"./connection.js\";\n\nexport class AgentRunner {\n private config: AgentRunnerConfig;\n private connection: ConveyorConnection;\n private callbacks: AgentRunnerCallbacks;\n private stopped = false;\n private inputResolver: ((msg: SDKUserMessage) => void) | null = null;\n private pendingMessages: SDKUserMessage[] = [];\n private currentTurnToolCalls: ActivityEventSummary[] = [];\n\n constructor(config: AgentRunnerConfig, callbacks: AgentRunnerCallbacks) {\n this.config = config;\n this.connection = new ConveyorConnection(config);\n this.callbacks = callbacks;\n }\n\n async start(): Promise<void> {\n await this.callbacks.onStatusChange(\"connecting\");\n await this.connection.connect();\n\n await this.callbacks.onStatusChange(\"fetching_context\");\n const context = await this.connection.fetchTaskContext();\n\n this.connection.onStopRequested(() => {\n this.stopped = true;\n });\n\n this.connection.onChatMessage((message) => {\n this.injectHumanMessage(message.content);\n });\n\n await this.callbacks.onStatusChange(\"running\");\n this.connection.sendEvent({\n type: \"connected\",\n taskId: this.config.taskId,\n });\n\n try {\n await this.executeTask(context);\n } catch (error) {\n const message = error instanceof Error ? error.message : \"Unknown error\";\n this.connection.sendEvent({ type: \"error\", message });\n await this.callbacks.onEvent({ type: \"error\", message });\n throw error;\n } finally {\n await this.callbacks.onStatusChange(\"finished\");\n this.connection.disconnect();\n }\n }\n\n private injectHumanMessage(content: string): void {\n const msg: SDKUserMessage = {\n type: \"user\" as const,\n session_id: \"\",\n message: { role: \"user\" as const, content },\n parent_tool_use_id: null,\n };\n\n if (this.inputResolver) {\n const resolve = this.inputResolver;\n this.inputResolver = null;\n resolve(msg);\n } else {\n this.pendingMessages.push(msg);\n }\n }\n\n private async *createInputStream(\n initialPrompt: string\n ): AsyncGenerator<SDKUserMessage, void, unknown> {\n yield {\n type: \"user\" as const,\n session_id: \"\",\n message: { role: \"user\" as const, content: initialPrompt },\n parent_tool_use_id: null,\n };\n\n while (!this.stopped) {\n if (this.pendingMessages.length > 0) {\n const next = this.pendingMessages.shift();\n if (next) { yield next; }\n continue;\n }\n\n await this.callbacks.onStatusChange(\"waiting_for_input\");\n const msg = await new Promise<SDKUserMessage | null>((resolve) => {\n this.inputResolver = resolve as (msg: SDKUserMessage) => void;\n\n const checkStopped = setInterval(() => {\n if (this.stopped) {\n clearInterval(checkStopped);\n this.inputResolver = null;\n resolve(null);\n }\n }, 1000);\n });\n\n if (!msg) break;\n await this.callbacks.onStatusChange(\"running\");\n yield msg;\n }\n }\n\n private buildInitialPrompt(context: TaskContext): string {\n const parts: string[] = [];\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 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 parts.push(\n `\\n## Instructions`,\n `Execute the task plan above. Work on the git branch \"${context.githubBranch}\".`,\n `When finished, commit your changes, push the branch, and create a pull request.`\n );\n\n return parts.join(\"\\n\");\n }\n\n private buildSystemPrompt(context: TaskContext): string {\n const parts = [\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 ];\n if (this.config.instructions) {\n parts.push(`\\nAgent 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 return parts.join(\"\\n\");\n }\n\n // eslint-disable-next-line @typescript-eslint/explicit-function-return-type\n private createConveyorMcpServer() {\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 return createSdkMcpServer({\n name: \"conveyor\",\n tools: [\n tool(\n \"read_task_chat\",\n \"Read recent messages from the task chat to see team feedback or instructions\",\n { limit: z.number().optional().describe(\"Number of recent messages to fetch (default 20)\") },\n (_args) => {\n return Promise.resolve(textResult(\n JSON.stringify({ note: \"Chat history was provided in the initial context. Use post_to_chat to ask the team questions.\" })\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 \"report_pr_created\",\n \"Report that a pull request has been created for this task\",\n {\n url: z.string().describe(\"The URL of the pull request\"),\n number: z.number().describe(\"The PR number\"),\n },\n ({ url, number }) => {\n connection.sendEvent({ type: \"pr_created\", url, number });\n return Promise.resolve(textResult(`PR #${number} reported to Conveyor.`));\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 context = await connection.fetchTaskContext();\n return textResult(context.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 }\n\n private async processEvents(events: AsyncGenerator<SDKMessage, void>): Promise<void> {\n const startTime = Date.now();\n let totalCostUsd = 0;\n\n for await (const event of events) {\n if (this.stopped) break;\n\n switch (event.type) {\n case \"assistant\": {\n const msg = event.message as unknown as Record<string, unknown>;\n const content = msg.content as Record<string, unknown>[];\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 this.connection.sendEvent({ type: \"message\", content: text });\n this.connection.postChatMessage(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\"\n ? block.input\n : JSON.stringify(block.input);\n const summary: ActivityEventSummary = {\n tool: name,\n input: inputStr.slice(0, 500),\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 (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 const resultEvent = event as SDKMessage & { type: \"result\"; subtype: string };\n if (resultEvent.subtype === \"success\") {\n totalCostUsd = \"total_cost_usd\" in resultEvent ? (resultEvent as Record<string, unknown>).total_cost_usd as number : 0;\n const durationMs = Date.now() - startTime;\n const summary = \"result\" in resultEvent ? String((resultEvent as Record<string, unknown>).result) : \"Task completed.\";\n\n this.connection.sendEvent({\n type: \"completed\",\n summary,\n costUsd: totalCostUsd,\n durationMs,\n });\n\n await this.callbacks.onEvent({\n type: \"completed\",\n summary,\n costUsd: totalCostUsd,\n durationMs,\n });\n } else {\n const errors = \"errors\" in resultEvent ? (resultEvent as Record<string, unknown>).errors as string[] : [];\n const errorMsg = errors.length > 0 ? errors.join(\", \") : `Agent stopped: ${resultEvent.subtype}`;\n this.connection.sendEvent({ type: \"error\", message: errorMsg });\n await this.callbacks.onEvent({ type: \"error\", message: errorMsg });\n }\n break;\n }\n\n case \"system\": {\n if (event.subtype === \"init\") {\n await this.callbacks.onEvent({\n type: \"thinking\",\n message: `Agent initialized (model: ${event.model})`,\n });\n }\n break;\n }\n }\n }\n }\n\n private async executeTask(context: TaskContext): Promise<void> {\n if (this.stopped) return;\n\n const initialPrompt = this.buildInitialPrompt(context);\n const systemPrompt = this.buildSystemPrompt(context);\n const conveyorMcp = this.createConveyorMcpServer();\n const inputStream = this.createInputStream(initialPrompt);\n\n const agentQuery = query({\n prompt: inputStream,\n options: {\n model: this.config.model,\n systemPrompt,\n cwd: this.config.workspaceDir,\n permissionMode: \"bypassPermissions\",\n allowDangerouslySkipPermissions: true,\n tools: { type: \"preset\", preset: \"claude_code\" },\n mcpServers: { conveyor: conveyorMcp },\n maxTurns: 100,\n },\n });\n\n await this.processEvents(agentQuery);\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":[]}