@rallycry/conveyor-agent 0.3.1 → 0.4.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.
- package/dist/{chunk-A3Q3QSHK.js → chunk-QOPHJHQV.js} +312 -96
- package/dist/chunk-QOPHJHQV.js.map +1 -0
- package/dist/cli.js +14 -2
- package/dist/cli.js.map +1 -1
- package/dist/index.d.ts +66 -2
- package/dist/index.js +9 -3
- package/package.json +6 -3
- package/dist/chunk-A3Q3QSHK.js.map +0 -1
|
@@ -93,6 +93,20 @@ var ConveyorConnection = class {
|
|
|
93
93
|
);
|
|
94
94
|
});
|
|
95
95
|
}
|
|
96
|
+
storeSessionId(sessionId) {
|
|
97
|
+
if (!this.socket) return;
|
|
98
|
+
this.socket.emit("agentRunner:storeSessionId", {
|
|
99
|
+
taskId: this.config.taskId,
|
|
100
|
+
sessionId
|
|
101
|
+
});
|
|
102
|
+
}
|
|
103
|
+
updateTaskFields(fields) {
|
|
104
|
+
if (!this.socket) throw new Error("Not connected");
|
|
105
|
+
this.socket.emit("agentRunner:updateTaskFields", {
|
|
106
|
+
taskId: this.config.taskId,
|
|
107
|
+
fields
|
|
108
|
+
});
|
|
109
|
+
}
|
|
96
110
|
onChatMessage(callback) {
|
|
97
111
|
this.socket?.on("agentRunner:incomingMessage", callback);
|
|
98
112
|
}
|
|
@@ -105,6 +119,71 @@ var ConveyorConnection = class {
|
|
|
105
119
|
}
|
|
106
120
|
};
|
|
107
121
|
|
|
122
|
+
// src/setup.ts
|
|
123
|
+
import { spawn } from "child_process";
|
|
124
|
+
import { readFile } from "fs/promises";
|
|
125
|
+
import { join } from "path";
|
|
126
|
+
var CONVEYOR_CONFIG_PATH = ".conveyor/config.json";
|
|
127
|
+
var DEVCONTAINER_PATH = ".devcontainer/conveyor/devcontainer.json";
|
|
128
|
+
async function loadConveyorConfig(workspaceDir) {
|
|
129
|
+
try {
|
|
130
|
+
const raw = await readFile(join(workspaceDir, CONVEYOR_CONFIG_PATH), "utf-8");
|
|
131
|
+
const parsed = JSON.parse(raw);
|
|
132
|
+
if (parsed.setupCommand || parsed.startCommand) return parsed;
|
|
133
|
+
} catch {
|
|
134
|
+
}
|
|
135
|
+
try {
|
|
136
|
+
const raw = await readFile(join(workspaceDir, DEVCONTAINER_PATH), "utf-8");
|
|
137
|
+
const parsed = JSON.parse(raw);
|
|
138
|
+
if (parsed.conveyor && (parsed.conveyor.startCommand || parsed.conveyor.setupCommand)) {
|
|
139
|
+
return parsed.conveyor;
|
|
140
|
+
}
|
|
141
|
+
} catch {
|
|
142
|
+
}
|
|
143
|
+
return null;
|
|
144
|
+
}
|
|
145
|
+
function runSetupCommand(cmd, cwd, onOutput) {
|
|
146
|
+
return new Promise((resolve, reject) => {
|
|
147
|
+
const child = spawn("sh", ["-c", cmd], {
|
|
148
|
+
cwd,
|
|
149
|
+
stdio: ["ignore", "pipe", "pipe"],
|
|
150
|
+
env: { ...process.env }
|
|
151
|
+
});
|
|
152
|
+
child.stdout.on("data", (chunk) => {
|
|
153
|
+
onOutput("stdout", chunk.toString());
|
|
154
|
+
});
|
|
155
|
+
child.stderr.on("data", (chunk) => {
|
|
156
|
+
onOutput("stderr", chunk.toString());
|
|
157
|
+
});
|
|
158
|
+
child.on("close", (code) => {
|
|
159
|
+
if (code === 0) {
|
|
160
|
+
resolve();
|
|
161
|
+
} else {
|
|
162
|
+
reject(new Error(`Setup command exited with code ${code}`));
|
|
163
|
+
}
|
|
164
|
+
});
|
|
165
|
+
child.on("error", (err) => {
|
|
166
|
+
reject(err);
|
|
167
|
+
});
|
|
168
|
+
});
|
|
169
|
+
}
|
|
170
|
+
function runStartCommand(cmd, cwd, onOutput) {
|
|
171
|
+
const child = spawn("sh", ["-c", cmd], {
|
|
172
|
+
cwd,
|
|
173
|
+
stdio: ["ignore", "pipe", "pipe"],
|
|
174
|
+
detached: true,
|
|
175
|
+
env: { ...process.env }
|
|
176
|
+
});
|
|
177
|
+
child.stdout.on("data", (chunk) => {
|
|
178
|
+
onOutput("stdout", chunk.toString());
|
|
179
|
+
});
|
|
180
|
+
child.stderr.on("data", (chunk) => {
|
|
181
|
+
onOutput("stderr", chunk.toString());
|
|
182
|
+
});
|
|
183
|
+
child.unref();
|
|
184
|
+
return child;
|
|
185
|
+
}
|
|
186
|
+
|
|
108
187
|
// src/runner.ts
|
|
109
188
|
import {
|
|
110
189
|
query,
|
|
@@ -128,19 +207,22 @@ var AgentRunner = class {
|
|
|
128
207
|
async start() {
|
|
129
208
|
await this.callbacks.onStatusChange("connecting");
|
|
130
209
|
await this.connection.connect();
|
|
131
|
-
await this.callbacks.onStatusChange("fetching_context");
|
|
132
|
-
const context = await this.connection.fetchTaskContext();
|
|
133
210
|
this.connection.onStopRequested(() => {
|
|
134
211
|
this.stopped = true;
|
|
135
212
|
});
|
|
136
213
|
this.connection.onChatMessage((message) => {
|
|
137
214
|
this.injectHumanMessage(message.content);
|
|
138
215
|
});
|
|
139
|
-
await this.callbacks.onStatusChange("running");
|
|
140
216
|
this.connection.sendEvent({
|
|
141
217
|
type: "connected",
|
|
142
218
|
taskId: this.config.taskId
|
|
143
219
|
});
|
|
220
|
+
if (process.env.CODESPACE === "true") {
|
|
221
|
+
await this.runProjectSetup();
|
|
222
|
+
}
|
|
223
|
+
await this.callbacks.onStatusChange("fetching_context");
|
|
224
|
+
const context = await this.connection.fetchTaskContext();
|
|
225
|
+
await this.callbacks.onStatusChange("running");
|
|
144
226
|
try {
|
|
145
227
|
await this.executeTask(context);
|
|
146
228
|
} catch (error) {
|
|
@@ -153,6 +235,37 @@ var AgentRunner = class {
|
|
|
153
235
|
this.connection.disconnect();
|
|
154
236
|
}
|
|
155
237
|
}
|
|
238
|
+
async runProjectSetup() {
|
|
239
|
+
await this.callbacks.onStatusChange("setup");
|
|
240
|
+
const config = await loadConveyorConfig(this.config.workspaceDir);
|
|
241
|
+
if (!config) {
|
|
242
|
+
this.connection.sendEvent({ type: "setup_complete" });
|
|
243
|
+
await this.callbacks.onEvent({ type: "setup_complete" });
|
|
244
|
+
return;
|
|
245
|
+
}
|
|
246
|
+
try {
|
|
247
|
+
await this.executeSetupConfig(config);
|
|
248
|
+
this.connection.sendEvent({ type: "setup_complete" });
|
|
249
|
+
await this.callbacks.onEvent({ type: "setup_complete" });
|
|
250
|
+
} catch (error) {
|
|
251
|
+
const message = error instanceof Error ? error.message : "Setup failed";
|
|
252
|
+
this.connection.sendEvent({ type: "setup_error", message });
|
|
253
|
+
await this.callbacks.onEvent({ type: "setup_error", message });
|
|
254
|
+
throw error;
|
|
255
|
+
}
|
|
256
|
+
}
|
|
257
|
+
async executeSetupConfig(config) {
|
|
258
|
+
if (config.setupCommand) {
|
|
259
|
+
await runSetupCommand(config.setupCommand, this.config.workspaceDir, (stream, data) => {
|
|
260
|
+
this.connection.sendEvent({ type: "setup_output", stream, data });
|
|
261
|
+
});
|
|
262
|
+
}
|
|
263
|
+
if (config.startCommand) {
|
|
264
|
+
runStartCommand(config.startCommand, this.config.workspaceDir, (stream, data) => {
|
|
265
|
+
this.connection.sendEvent({ type: "start_command_output", stream, data });
|
|
266
|
+
});
|
|
267
|
+
}
|
|
268
|
+
}
|
|
156
269
|
injectHumanMessage(content) {
|
|
157
270
|
const msg = {
|
|
158
271
|
type: "user",
|
|
@@ -215,6 +328,41 @@ var AgentRunner = class {
|
|
|
215
328
|
buildInitialPrompt(context) {
|
|
216
329
|
const parts = [];
|
|
217
330
|
const scenario = this.detectRelaunchScenario(context);
|
|
331
|
+
if (context.claudeSessionId && scenario !== "fresh") {
|
|
332
|
+
if (scenario === "feedback_relaunch") {
|
|
333
|
+
const lastAgentIdx = this.findLastAgentMessageIndex(context.chatHistory);
|
|
334
|
+
const newMessages = context.chatHistory.slice(lastAgentIdx + 1).filter((m) => m.role === "user");
|
|
335
|
+
parts.push(
|
|
336
|
+
`You have been relaunched with new feedback.`,
|
|
337
|
+
`Work on the git branch "${context.githubBranch}".`,
|
|
338
|
+
`
|
|
339
|
+
New messages since your last run:`,
|
|
340
|
+
...newMessages.map((m) => `[${m.userName ?? "user"}]: ${m.content}`),
|
|
341
|
+
`
|
|
342
|
+
Address the requested changes. Commit and push your updates.`
|
|
343
|
+
);
|
|
344
|
+
if (context.githubPRUrl) {
|
|
345
|
+
parts.push(
|
|
346
|
+
`An existing PR is open at ${context.githubPRUrl} \u2014 push to the same branch. Do NOT create a new PR.`
|
|
347
|
+
);
|
|
348
|
+
} else {
|
|
349
|
+
parts.push(
|
|
350
|
+
`When finished, use the create_pull_request tool to open a PR. Do NOT use gh CLI.`
|
|
351
|
+
);
|
|
352
|
+
}
|
|
353
|
+
} else {
|
|
354
|
+
parts.push(
|
|
355
|
+
`You were relaunched but no new instructions have been given since your last run.`,
|
|
356
|
+
`Work on the git branch "${context.githubBranch}".`,
|
|
357
|
+
`Review the current state of the codebase and verify everything is working correctly.`,
|
|
358
|
+
`Post a brief status update to the chat, then wait for further instructions.`
|
|
359
|
+
);
|
|
360
|
+
if (context.githubPRUrl) {
|
|
361
|
+
parts.push(`An existing PR is open at ${context.githubPRUrl}. Do not create a new PR.`);
|
|
362
|
+
}
|
|
363
|
+
}
|
|
364
|
+
return parts.join("\n");
|
|
365
|
+
}
|
|
218
366
|
parts.push(`# Task: ${context.title}`);
|
|
219
367
|
if (context.description) {
|
|
220
368
|
parts.push(`
|
|
@@ -238,12 +386,20 @@ ${context.plan}`);
|
|
|
238
386
|
parts.push(`
|
|
239
387
|
## Instructions`);
|
|
240
388
|
if (scenario === "fresh") {
|
|
241
|
-
|
|
242
|
-
|
|
243
|
-
|
|
244
|
-
|
|
245
|
-
|
|
246
|
-
|
|
389
|
+
if (this.config.mode === "pm") {
|
|
390
|
+
parts.push(
|
|
391
|
+
`You are the project manager for this task. Help the team plan and refine it.`,
|
|
392
|
+
`You have access to the repository \u2014 read files to understand the codebase before writing the plan.`,
|
|
393
|
+
`When the plan is complete and ready, use the update_task tool to save it and update_task_status to move the task to "Open".`
|
|
394
|
+
);
|
|
395
|
+
} else {
|
|
396
|
+
parts.push(
|
|
397
|
+
`Begin executing the task plan above immediately. Do not perform a preliminary assessment or wait for confirmation before writing code.`,
|
|
398
|
+
`Work on the git branch "${context.githubBranch}".`,
|
|
399
|
+
`Post a brief message to chat when you begin meaningful implementation, and again when the PR is ready.`,
|
|
400
|
+
`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.`
|
|
401
|
+
);
|
|
402
|
+
}
|
|
247
403
|
} else if (scenario === "idle_relaunch") {
|
|
248
404
|
parts.push(
|
|
249
405
|
`You were relaunched but no new instructions have been given since your last run.`,
|
|
@@ -280,7 +436,14 @@ Address the requested changes. Commit and push your updates.`
|
|
|
280
436
|
return parts.join("\n");
|
|
281
437
|
}
|
|
282
438
|
buildSystemPrompt(context) {
|
|
283
|
-
const parts = [
|
|
439
|
+
const parts = this.config.mode === "pm" ? [
|
|
440
|
+
`You are an AI project manager helping to plan tasks for the "${context.title}" project.`,
|
|
441
|
+
`You are running locally with full access to the repository.`,
|
|
442
|
+
`
|
|
443
|
+
Environment (ready, no setup required):`,
|
|
444
|
+
`- Repository is cloned at your current working directory.`,
|
|
445
|
+
`- You can read files to understand the codebase before writing task plans.`
|
|
446
|
+
] : [
|
|
284
447
|
`You are an AI agent working on a task for the "${context.title}" project.`,
|
|
285
448
|
`You are running inside a GitHub Codespace with full access to the repository.`,
|
|
286
449
|
`
|
|
@@ -299,100 +462,144 @@ ${this.config.instructions}`);
|
|
|
299
462
|
`
|
|
300
463
|
You have access to Conveyor MCP tools to interact with the task management system.`,
|
|
301
464
|
`Use the post_to_chat tool to communicate progress or ask questions.`,
|
|
302
|
-
`Use the read_task_chat tool to check for new messages from the team
|
|
303
|
-
`Use the create_pull_request tool to open PRs \u2014 do NOT use gh CLI or shell commands for PR creation.`
|
|
465
|
+
`Use the read_task_chat tool to check for new messages from the team.`
|
|
304
466
|
);
|
|
467
|
+
if (this.config.mode !== "pm") {
|
|
468
|
+
parts.push(
|
|
469
|
+
`Use the create_pull_request tool to open PRs \u2014 do NOT use gh CLI or shell commands for PR creation.`
|
|
470
|
+
);
|
|
471
|
+
}
|
|
305
472
|
return parts.join("\n");
|
|
306
473
|
}
|
|
307
474
|
// oxlint-disable-next-line typescript/explicit-function-return-type, max-lines-per-function
|
|
308
|
-
createConveyorMcpServer() {
|
|
475
|
+
createConveyorMcpServer(context) {
|
|
309
476
|
const connection = this.connection;
|
|
310
477
|
const config = this.config;
|
|
311
478
|
const textResult = (text) => ({
|
|
312
479
|
content: [{ type: "text", text }]
|
|
313
480
|
});
|
|
314
|
-
|
|
315
|
-
|
|
316
|
-
|
|
317
|
-
|
|
318
|
-
|
|
319
|
-
"
|
|
320
|
-
|
|
321
|
-
|
|
322
|
-
|
|
323
|
-
|
|
324
|
-
|
|
325
|
-
|
|
326
|
-
|
|
327
|
-
|
|
328
|
-
|
|
329
|
-
|
|
330
|
-
|
|
331
|
-
|
|
332
|
-
|
|
333
|
-
|
|
334
|
-
|
|
335
|
-
|
|
336
|
-
|
|
337
|
-
|
|
338
|
-
(
|
|
339
|
-
|
|
340
|
-
|
|
481
|
+
const commonTools = [
|
|
482
|
+
tool(
|
|
483
|
+
"read_task_chat",
|
|
484
|
+
"Read recent messages from the task chat to see team feedback or instructions",
|
|
485
|
+
{
|
|
486
|
+
limit: z.number().optional().describe("Number of recent messages to fetch (default 20)")
|
|
487
|
+
},
|
|
488
|
+
(_args) => {
|
|
489
|
+
return Promise.resolve(
|
|
490
|
+
textResult(
|
|
491
|
+
JSON.stringify({
|
|
492
|
+
note: "Chat history was provided in the initial context. Use post_to_chat to ask the team questions."
|
|
493
|
+
})
|
|
494
|
+
)
|
|
495
|
+
);
|
|
496
|
+
},
|
|
497
|
+
{ annotations: { readOnly: true } }
|
|
498
|
+
),
|
|
499
|
+
tool(
|
|
500
|
+
"post_to_chat",
|
|
501
|
+
"Post a message to the task chat visible to all team members",
|
|
502
|
+
{ message: z.string().describe("The message to post to the team") },
|
|
503
|
+
({ message }) => {
|
|
504
|
+
connection.postChatMessage(message);
|
|
505
|
+
return Promise.resolve(textResult("Message posted to task chat."));
|
|
506
|
+
}
|
|
507
|
+
),
|
|
508
|
+
tool(
|
|
509
|
+
"update_task_status",
|
|
510
|
+
"Update the task status on the Kanban board",
|
|
511
|
+
{
|
|
512
|
+
status: z.enum(["InProgress", "ReviewPR", "Complete"]).describe("The new status for the task")
|
|
513
|
+
},
|
|
514
|
+
({ status }) => {
|
|
515
|
+
connection.updateStatus(status);
|
|
516
|
+
return Promise.resolve(textResult(`Task status updated to ${status}.`));
|
|
517
|
+
}
|
|
518
|
+
),
|
|
519
|
+
tool(
|
|
520
|
+
"get_task_plan",
|
|
521
|
+
"Re-read the latest task plan in case it was updated",
|
|
522
|
+
{},
|
|
523
|
+
async () => {
|
|
524
|
+
try {
|
|
525
|
+
const ctx = await connection.fetchTaskContext();
|
|
526
|
+
return textResult(ctx.plan ?? "No plan available.");
|
|
527
|
+
} catch {
|
|
528
|
+
return textResult(`Task ID: ${config.taskId} - could not fetch updated plan.`);
|
|
341
529
|
}
|
|
342
|
-
|
|
343
|
-
|
|
344
|
-
|
|
345
|
-
|
|
346
|
-
|
|
347
|
-
|
|
348
|
-
|
|
349
|
-
|
|
350
|
-
|
|
351
|
-
|
|
530
|
+
},
|
|
531
|
+
{ annotations: { readOnly: true } }
|
|
532
|
+
)
|
|
533
|
+
];
|
|
534
|
+
const modeTools = config.mode === "pm" ? [
|
|
535
|
+
tool(
|
|
536
|
+
"update_task",
|
|
537
|
+
"Save the finalized task plan and/or description",
|
|
538
|
+
{
|
|
539
|
+
plan: z.string().optional().describe("The task plan in markdown"),
|
|
540
|
+
description: z.string().optional().describe("Updated task description")
|
|
541
|
+
},
|
|
542
|
+
async ({ plan, description }) => {
|
|
543
|
+
try {
|
|
544
|
+
connection.updateTaskFields({ plan, description });
|
|
545
|
+
return textResult("Task updated successfully.");
|
|
546
|
+
} catch {
|
|
547
|
+
return textResult("Failed to update task.");
|
|
352
548
|
}
|
|
353
|
-
|
|
354
|
-
|
|
355
|
-
|
|
356
|
-
|
|
357
|
-
|
|
358
|
-
|
|
359
|
-
|
|
360
|
-
|
|
361
|
-
|
|
362
|
-
|
|
363
|
-
|
|
364
|
-
|
|
365
|
-
|
|
366
|
-
|
|
367
|
-
|
|
368
|
-
|
|
369
|
-
|
|
549
|
+
}
|
|
550
|
+
)
|
|
551
|
+
] : [
|
|
552
|
+
tool(
|
|
553
|
+
"create_pull_request",
|
|
554
|
+
"Create a GitHub pull request for this task. Use this instead of gh CLI or git commands to create PRs.",
|
|
555
|
+
{
|
|
556
|
+
title: z.string().describe("The PR title"),
|
|
557
|
+
body: z.string().describe("The PR description/body in markdown")
|
|
558
|
+
},
|
|
559
|
+
async ({ title, body }) => {
|
|
560
|
+
try {
|
|
561
|
+
const result = await connection.createPR({ title, body });
|
|
562
|
+
connection.sendEvent({
|
|
563
|
+
type: "pr_created",
|
|
564
|
+
url: result.url,
|
|
565
|
+
number: result.number
|
|
566
|
+
});
|
|
567
|
+
return textResult(`Pull request #${result.number} created: ${result.url}`);
|
|
568
|
+
} catch (error) {
|
|
569
|
+
const msg = error instanceof Error ? error.message : "Unknown error";
|
|
570
|
+
return textResult(`Failed to create pull request: ${msg}`);
|
|
370
571
|
}
|
|
371
|
-
|
|
372
|
-
|
|
373
|
-
|
|
374
|
-
|
|
375
|
-
|
|
376
|
-
|
|
377
|
-
try {
|
|
378
|
-
const context = await connection.fetchTaskContext();
|
|
379
|
-
return textResult(context.plan ?? "No plan available.");
|
|
380
|
-
} catch {
|
|
381
|
-
return textResult(`Task ID: ${config.taskId} - could not fetch updated plan.`);
|
|
382
|
-
}
|
|
383
|
-
},
|
|
384
|
-
{ annotations: { readOnly: true } }
|
|
385
|
-
)
|
|
386
|
-
]
|
|
572
|
+
}
|
|
573
|
+
)
|
|
574
|
+
];
|
|
575
|
+
return createSdkMcpServer({
|
|
576
|
+
name: "conveyor",
|
|
577
|
+
tools: [...commonTools, ...modeTools]
|
|
387
578
|
});
|
|
579
|
+
void context;
|
|
388
580
|
}
|
|
389
581
|
// oxlint-disable-next-line max-lines-per-function, complexity
|
|
390
582
|
async processEvents(events) {
|
|
391
583
|
const startTime = Date.now();
|
|
392
584
|
let totalCostUsd = 0;
|
|
585
|
+
let sessionIdStored = false;
|
|
393
586
|
for await (const event of events) {
|
|
394
587
|
if (this.stopped) break;
|
|
395
588
|
switch (event.type) {
|
|
589
|
+
case "system": {
|
|
590
|
+
if (event.subtype === "init") {
|
|
591
|
+
const sessionId = event.session_id;
|
|
592
|
+
if (sessionId && !sessionIdStored) {
|
|
593
|
+
sessionIdStored = true;
|
|
594
|
+
this.connection.storeSessionId(sessionId);
|
|
595
|
+
}
|
|
596
|
+
await this.callbacks.onEvent({
|
|
597
|
+
type: "thinking",
|
|
598
|
+
message: `Agent initialized (model: ${event.model})`
|
|
599
|
+
});
|
|
600
|
+
}
|
|
601
|
+
break;
|
|
602
|
+
}
|
|
396
603
|
case "assistant": {
|
|
397
604
|
const msg = event.message;
|
|
398
605
|
const content = msg.content;
|
|
@@ -459,35 +666,41 @@ You have access to Conveyor MCP tools to interact with the task management syste
|
|
|
459
666
|
}
|
|
460
667
|
break;
|
|
461
668
|
}
|
|
462
|
-
case "system": {
|
|
463
|
-
if (event.subtype === "init") {
|
|
464
|
-
await this.callbacks.onEvent({
|
|
465
|
-
type: "thinking",
|
|
466
|
-
message: `Agent initialized (model: ${event.model})`
|
|
467
|
-
});
|
|
468
|
-
}
|
|
469
|
-
break;
|
|
470
|
-
}
|
|
471
669
|
}
|
|
472
670
|
}
|
|
473
671
|
}
|
|
474
672
|
async executeTask(context) {
|
|
475
673
|
if (this.stopped) return;
|
|
674
|
+
const settings = context.agentSettings ?? this.config.agentSettings ?? {};
|
|
476
675
|
const initialPrompt = this.buildInitialPrompt(context);
|
|
477
|
-
const
|
|
478
|
-
const conveyorMcp = this.createConveyorMcpServer();
|
|
676
|
+
const systemPromptText = this.buildSystemPrompt(context);
|
|
677
|
+
const conveyorMcp = this.createConveyorMcpServer(context);
|
|
479
678
|
const inputStream = this.createInputStream(initialPrompt);
|
|
679
|
+
const systemPrompt = {
|
|
680
|
+
type: "preset",
|
|
681
|
+
preset: "claude_code",
|
|
682
|
+
append: systemPromptText || void 0
|
|
683
|
+
};
|
|
684
|
+
const settingSources = settings.settingSources ?? ["project"];
|
|
480
685
|
const agentQuery = query({
|
|
481
686
|
prompt: inputStream,
|
|
482
687
|
options: {
|
|
483
688
|
model: this.config.model,
|
|
484
689
|
systemPrompt,
|
|
690
|
+
settingSources,
|
|
485
691
|
cwd: this.config.workspaceDir,
|
|
486
692
|
permissionMode: "bypassPermissions",
|
|
487
693
|
allowDangerouslySkipPermissions: true,
|
|
488
694
|
tools: { type: "preset", preset: "claude_code" },
|
|
489
695
|
mcpServers: { conveyor: conveyorMcp },
|
|
490
|
-
maxTurns: 100
|
|
696
|
+
maxTurns: settings.maxTurns ?? 100,
|
|
697
|
+
resume: context.claudeSessionId ?? void 0,
|
|
698
|
+
effort: settings.effort,
|
|
699
|
+
thinking: settings.thinking,
|
|
700
|
+
betas: settings.betas,
|
|
701
|
+
maxBudgetUsd: settings.maxBudgetUsd,
|
|
702
|
+
disallowedTools: settings.disallowedTools,
|
|
703
|
+
enableFileCheckpointing: settings.enableFileCheckpointing
|
|
491
704
|
}
|
|
492
705
|
});
|
|
493
706
|
await this.processEvents(agentQuery);
|
|
@@ -503,6 +716,9 @@ You have access to Conveyor MCP tools to interact with the task management syste
|
|
|
503
716
|
|
|
504
717
|
export {
|
|
505
718
|
ConveyorConnection,
|
|
719
|
+
loadConveyorConfig,
|
|
720
|
+
runSetupCommand,
|
|
721
|
+
runStartCommand,
|
|
506
722
|
AgentRunner
|
|
507
723
|
};
|
|
508
|
-
//# sourceMappingURL=chunk-
|
|
724
|
+
//# sourceMappingURL=chunk-QOPHJHQV.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../src/connection.ts","../src/setup.ts","../src/runner.ts"],"sourcesContent":["import { io, type Socket } from \"socket.io-client\";\nimport type { AgentRunnerConfig, TaskContext, AgentEvent } from \"./types.js\";\n\nexport class ConveyorConnection {\n private socket: Socket | null = null;\n private config: AgentRunnerConfig;\n\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 storeSessionId(sessionId: string): void {\n if (!this.socket) return;\n this.socket.emit(\"agentRunner:storeSessionId\", {\n taskId: this.config.taskId,\n sessionId,\n });\n }\n\n updateTaskFields(fields: { plan?: string; description?: string }): void {\n if (!this.socket) throw new Error(\"Not connected\");\n this.socket.emit(\"agentRunner:updateTaskFields\", {\n taskId: this.config.taskId,\n fields,\n });\n }\n\n onChatMessage(callback: (message: { content: string; userId: string }) => void): void {\n this.socket?.on(\"agentRunner:incomingMessage\", callback);\n }\n\n onStopRequested(callback: () => void): void {\n this.socket?.on(\"agentRunner:stop\", callback);\n }\n\n disconnect(): void {\n this.socket?.disconnect();\n this.socket = null;\n }\n}\n","import { spawn, type ChildProcess } from \"node:child_process\";\nimport { readFile } from \"node:fs/promises\";\nimport { join } from \"node:path\";\n\nexport interface ConveyorConfig {\n setupCommand?: string;\n startCommand?: string;\n previewPort?: number;\n}\n\nconst CONVEYOR_CONFIG_PATH = \".conveyor/config.json\";\nconst DEVCONTAINER_PATH = \".devcontainer/conveyor/devcontainer.json\";\n\nexport async function loadConveyorConfig(workspaceDir: string): Promise<ConveyorConfig | null> {\n // Primary: .conveyor/config.json\n try {\n const raw = await readFile(join(workspaceDir, CONVEYOR_CONFIG_PATH), \"utf-8\");\n const parsed = JSON.parse(raw) as ConveyorConfig;\n if (parsed.setupCommand || parsed.startCommand) return parsed;\n } catch {\n // Not found or invalid — try fallback\n }\n\n // Fallback: devcontainer.json \"conveyor\" section\n try {\n const raw = await readFile(join(workspaceDir, DEVCONTAINER_PATH), \"utf-8\");\n const parsed = JSON.parse(raw) as { conveyor?: ConveyorConfig };\n if (parsed.conveyor && (parsed.conveyor.startCommand || parsed.conveyor.setupCommand)) {\n return parsed.conveyor;\n }\n } catch {\n // Not found or invalid\n }\n\n return null;\n}\n\n/**\n * Runs a command synchronously (waits for exit). Streams stdout/stderr\n * line-by-line via the onOutput callback.\n */\nexport function runSetupCommand(\n cmd: string,\n cwd: string,\n onOutput: (stream: \"stdout\" | \"stderr\", data: string) => void,\n): Promise<void> {\n return new Promise((resolve, reject) => {\n const child = spawn(\"sh\", [\"-c\", cmd], {\n cwd,\n stdio: [\"ignore\", \"pipe\", \"pipe\"],\n env: { ...process.env },\n });\n\n child.stdout.on(\"data\", (chunk: Buffer) => {\n onOutput(\"stdout\", chunk.toString());\n });\n\n child.stderr.on(\"data\", (chunk: Buffer) => {\n onOutput(\"stderr\", chunk.toString());\n });\n\n child.on(\"close\", (code) => {\n if (code === 0) {\n resolve();\n } else {\n reject(new Error(`Setup command exited with code ${code}`));\n }\n });\n\n child.on(\"error\", (err) => {\n reject(err);\n });\n });\n}\n\n/**\n * Runs a command in the background (does not wait for exit). Returns the\n * ChildProcess so it can be cleaned up on agent shutdown. Streams\n * stdout/stderr via the onOutput callback.\n */\nexport function runStartCommand(\n cmd: string,\n cwd: string,\n onOutput: (stream: \"stdout\" | \"stderr\", data: string) => void,\n): ChildProcess {\n const child = spawn(\"sh\", [\"-c\", cmd], {\n cwd,\n stdio: [\"ignore\", \"pipe\", \"pipe\"],\n detached: true,\n env: { ...process.env },\n });\n\n child.stdout.on(\"data\", (chunk: Buffer) => {\n onOutput(\"stdout\", chunk.toString());\n });\n\n child.stderr.on(\"data\", (chunk: Buffer) => {\n onOutput(\"stderr\", chunk.toString());\n });\n\n child.unref();\n return child;\n}\n","// oxlint-disable max-lines\nimport {\n query,\n tool,\n createSdkMcpServer,\n type SDKMessage,\n type SDKUserMessage,\n} from \"@anthropic-ai/claude-agent-sdk\";\nimport { z } from \"zod\";\nimport type {\n AgentRunnerConfig,\n AgentRunnerCallbacks,\n TaskContext,\n ActivityEventSummary,\n} from \"./types.js\";\nimport { ConveyorConnection } from \"./connection.js\";\nimport { loadConveyorConfig, runSetupCommand, runStartCommand, type ConveyorConfig } from \"./setup.js\";\n\nexport class AgentRunner {\n private config: AgentRunnerConfig;\n private connection: ConveyorConnection;\n private callbacks: AgentRunnerCallbacks;\n private stopped = false;\n private inputResolver: ((msg: SDKUserMessage) => void) | null = null;\n private pendingMessages: SDKUserMessage[] = [];\n private currentTurnToolCalls: ActivityEventSummary[] = [];\n\n constructor(config: AgentRunnerConfig, callbacks: AgentRunnerCallbacks) {\n this.config = config;\n this.connection = new ConveyorConnection(config);\n this.callbacks = callbacks;\n }\n\n async start(): Promise<void> {\n await this.callbacks.onStatusChange(\"connecting\");\n await this.connection.connect();\n\n this.connection.onStopRequested(() => {\n this.stopped = true;\n });\n\n this.connection.onChatMessage((message) => {\n this.injectHumanMessage(message.content);\n });\n\n this.connection.sendEvent({\n type: \"connected\",\n taskId: this.config.taskId,\n });\n\n if (process.env.CODESPACE === \"true\") {\n await this.runProjectSetup();\n }\n\n await this.callbacks.onStatusChange(\"fetching_context\");\n const context = await this.connection.fetchTaskContext();\n\n await this.callbacks.onStatusChange(\"running\");\n\n try {\n await this.executeTask(context);\n } catch (error) {\n const message = error instanceof Error ? error.message : \"Unknown error\";\n this.connection.sendEvent({ type: \"error\", message });\n await this.callbacks.onEvent({ type: \"error\", message });\n throw error;\n } finally {\n await this.callbacks.onStatusChange(\"finished\");\n this.connection.disconnect();\n }\n }\n\n private async runProjectSetup(): Promise<void> {\n await this.callbacks.onStatusChange(\"setup\");\n\n const config = await loadConveyorConfig(this.config.workspaceDir);\n if (!config) {\n this.connection.sendEvent({ type: \"setup_complete\" });\n await this.callbacks.onEvent({ type: \"setup_complete\" });\n return;\n }\n\n try {\n await this.executeSetupConfig(config);\n this.connection.sendEvent({ type: \"setup_complete\" });\n await this.callbacks.onEvent({ type: \"setup_complete\" });\n } catch (error) {\n const message = error instanceof Error ? error.message : \"Setup failed\";\n this.connection.sendEvent({ type: \"setup_error\", message });\n await this.callbacks.onEvent({ type: \"setup_error\", message });\n throw error;\n }\n }\n\n private async executeSetupConfig(config: ConveyorConfig): Promise<void> {\n if (config.setupCommand) {\n await runSetupCommand(config.setupCommand, this.config.workspaceDir, (stream, data) => {\n this.connection.sendEvent({ type: \"setup_output\", stream, data });\n });\n }\n\n if (config.startCommand) {\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 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 // When resuming a session, the context is already in the session history —\n // just inject a brief orientation message.\n if (context.claudeSessionId && scenario !== \"fresh\") {\n if (scenario === \"feedback_relaunch\") {\n const lastAgentIdx = this.findLastAgentMessageIndex(context.chatHistory);\n const newMessages = context.chatHistory\n .slice(lastAgentIdx + 1)\n .filter((m) => m.role === \"user\");\n parts.push(\n `You have been relaunched with new feedback.`,\n `Work on the git branch \"${context.githubBranch}\".`,\n `\\nNew messages since your last run:`,\n ...newMessages.map((m) => `[${m.userName ?? \"user\"}]: ${m.content}`),\n `\\nAddress the requested changes. Commit and push your updates.`,\n );\n if (context.githubPRUrl) {\n parts.push(\n `An existing PR is open at ${context.githubPRUrl} — push to the same branch. Do NOT create a new PR.`,\n );\n } else {\n parts.push(\n `When finished, use the create_pull_request tool to open a PR. Do NOT use gh CLI.`,\n );\n }\n } else {\n parts.push(\n `You were relaunched but no new instructions have been given since your last run.`,\n `Work on the git branch \"${context.githubBranch}\".`,\n `Review the current state of the codebase and verify everything is working correctly.`,\n `Post a brief status update to the chat, then wait for further instructions.`,\n );\n if (context.githubPRUrl) {\n parts.push(`An existing PR is open at ${context.githubPRUrl}. Do not create a new PR.`);\n }\n }\n return parts.join(\"\\n\");\n }\n\n parts.push(`# Task: ${context.title}`);\n if (context.description) {\n parts.push(`\\n## Description\\n${context.description}`);\n }\n if (context.plan) {\n parts.push(`\\n## Plan\\n${context.plan}`);\n }\n\n if (context.chatHistory.length > 0) {\n const relevant = context.chatHistory.slice(-20);\n parts.push(`\\n## Recent Chat Context`);\n for (const msg of relevant) {\n const sender = msg.userName ?? msg.role;\n parts.push(`[${sender}]: ${msg.content}`);\n }\n }\n\n parts.push(`\\n## Instructions`);\n\n if (scenario === \"fresh\") {\n if (this.config.mode === \"pm\") {\n parts.push(\n `You are the project manager for this task. Help the team plan and refine it.`,\n `You have access to the repository — read files to understand the codebase before writing the plan.`,\n `When the plan is complete and ready, use the update_task tool to save it and update_task_status to move the task to \"Open\".`,\n );\n } else {\n parts.push(\n `Begin executing the task plan above immediately. Do not perform a preliminary assessment or wait for confirmation before writing code.`,\n `Work on the git branch \"${context.githubBranch}\".`,\n `Post a brief message to chat when you begin meaningful implementation, and again when the PR is ready.`,\n `When finished, commit your changes, push the branch, and use the create_pull_request tool to open a PR. Do NOT use gh CLI or any other method to create PRs.`,\n );\n }\n } else if (scenario === \"idle_relaunch\") {\n parts.push(\n `You were relaunched but no new instructions have been given since your last run.`,\n `Work on the git branch \"${context.githubBranch}\".`,\n `Review the current state of the codebase and verify everything is working correctly (e.g. tests pass, the web server starts on port 3000).`,\n `Post a brief status update to the chat summarizing the current state.`,\n `Then wait for further instructions — do NOT redo work that was already completed.`,\n );\n if (context.githubPRUrl) {\n parts.push(`An existing PR is open at ${context.githubPRUrl}. Do not create a new PR.`);\n }\n } else {\n const lastAgentIdx = this.findLastAgentMessageIndex(context.chatHistory);\n const newMessages = context.chatHistory\n .slice(lastAgentIdx + 1)\n .filter((m) => m.role === \"user\");\n parts.push(\n `You were relaunched with new feedback since your last run.`,\n `Work on the git branch \"${context.githubBranch}\".`,\n `\\nNew messages since your last run:`,\n ...newMessages.map((m) => `[${m.userName ?? \"user\"}]: ${m.content}`),\n `\\nAddress the requested changes. Commit and push your updates.`,\n );\n if (context.githubPRUrl) {\n parts.push(\n `An existing PR is open at ${context.githubPRUrl} — push to the same branch to update it. Do NOT create a new PR.`,\n );\n } else {\n parts.push(\n `When finished, use the create_pull_request tool to open a PR. Do NOT use gh CLI or any other method to create PRs.`,\n );\n }\n }\n\n return parts.join(\"\\n\");\n }\n\n private buildSystemPrompt(context: TaskContext): string {\n const parts =\n this.config.mode === \"pm\"\n ? [\n `You are an AI project manager helping to plan tasks for the \"${context.title}\" project.`,\n `You are running locally with full access to the repository.`,\n `\\nEnvironment (ready, no setup required):`,\n `- Repository is cloned at your current working directory.`,\n `- You can read files to understand the codebase before writing task plans.`,\n ]\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 (ready, no setup required):`,\n `- Repository is cloned at your current working directory.`,\n `- Branch \\`${context.githubBranch}\\` is already checked out.`,\n `- All project dependencies are installed (devcontainer build is complete).`,\n `- Git is configured. Commit and push directly to this branch.`,\n ];\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 if (this.config.mode !== \"pm\") {\n parts.push(\n `Use the create_pull_request tool to open PRs — do NOT use gh CLI or shell commands for PR creation.`,\n );\n }\n return parts.join(\"\\n\");\n }\n\n // oxlint-disable-next-line typescript/explicit-function-return-type, max-lines-per-function\n private createConveyorMcpServer(context: TaskContext) {\n const connection = this.connection;\n const config = this.config;\n\n const textResult = (text: string): { content: { type: \"text\"; text: string }[] } => ({\n content: [{ type: \"text\" as const, text }],\n });\n\n const commonTools = [\n tool(\n \"read_task_chat\",\n \"Read recent messages from the task chat to see team feedback or instructions\",\n {\n limit: z.number().optional().describe(\"Number of recent messages to fetch (default 20)\"),\n },\n (_args) => {\n return Promise.resolve(\n textResult(\n JSON.stringify({\n note: \"Chat history was provided in the initial context. Use post_to_chat to ask the team questions.\",\n }),\n ),\n );\n },\n { annotations: { readOnly: true } },\n ),\n tool(\n \"post_to_chat\",\n \"Post a message to the task chat visible to all team members\",\n { message: z.string().describe(\"The message to post to the team\") },\n ({ message }) => {\n connection.postChatMessage(message);\n return Promise.resolve(textResult(\"Message posted to task chat.\"));\n },\n ),\n tool(\n \"update_task_status\",\n \"Update the task status on the Kanban board\",\n {\n status: z\n .enum([\"InProgress\", \"ReviewPR\", \"Complete\"])\n .describe(\"The new status for the task\"),\n },\n ({ status }) => {\n connection.updateStatus(status);\n return Promise.resolve(textResult(`Task status updated to ${status}.`));\n },\n ),\n tool(\n \"get_task_plan\",\n \"Re-read the latest task plan in case it was updated\",\n {},\n async () => {\n try {\n const ctx = await connection.fetchTaskContext();\n return textResult(ctx.plan ?? \"No plan available.\");\n } catch {\n return textResult(`Task ID: ${config.taskId} - could not fetch updated plan.`);\n }\n },\n { annotations: { readOnly: true } },\n ),\n ];\n\n // PM mode gets update_task tool; task mode gets create_pull_request\n const modeTools =\n config.mode === \"pm\"\n ? [\n tool(\n \"update_task\",\n \"Save the finalized task plan and/or description\",\n {\n plan: z.string().optional().describe(\"The task plan in markdown\"),\n description: z.string().optional().describe(\"Updated task description\"),\n },\n async ({ plan, description }) => {\n try {\n connection.updateTaskFields({ plan, description });\n return textResult(\"Task updated successfully.\");\n } catch {\n return textResult(\"Failed to update task.\");\n }\n },\n ),\n ]\n : [\n tool(\n \"create_pull_request\",\n \"Create a GitHub pull request for this task. Use this instead of gh CLI or git commands to create PRs.\",\n {\n title: z.string().describe(\"The PR title\"),\n body: z.string().describe(\"The PR description/body in markdown\"),\n },\n async ({ title, body }) => {\n try {\n const result = await connection.createPR({ title, body });\n connection.sendEvent({\n type: \"pr_created\",\n url: result.url,\n number: result.number,\n });\n return textResult(`Pull request #${result.number} created: ${result.url}`);\n } catch (error) {\n const msg = error instanceof Error ? error.message : \"Unknown error\";\n return textResult(`Failed to create pull request: ${msg}`);\n }\n },\n ),\n ];\n\n return createSdkMcpServer({\n name: \"conveyor\",\n tools: [...commonTools, ...modeTools],\n });\n\n // Suppress unused warning — context used by callers for session ID\n void context;\n }\n\n // oxlint-disable-next-line max-lines-per-function, complexity\n private async processEvents(events: AsyncGenerator<SDKMessage, void>): Promise<void> {\n const startTime = Date.now();\n let totalCostUsd = 0;\n let sessionIdStored = 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 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 }\n }\n\n private async executeTask(context: TaskContext): Promise<void> {\n if (this.stopped) return;\n\n const settings = context.agentSettings ?? this.config.agentSettings ?? {};\n const initialPrompt = this.buildInitialPrompt(context);\n const systemPromptText = this.buildSystemPrompt(context);\n const conveyorMcp = this.createConveyorMcpServer(context);\n const inputStream = this.createInputStream(initialPrompt);\n\n // Use claude_code preset so CLAUDE.md is loaded; append agent instructions after the preset.\n // Resolve settingSources — default to project so CLAUDE.md is always loaded.\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 ?? [\"project\"]) as (\n | \"user\"\n | \"project\"\n | \"local\"\n )[];\n\n const agentQuery = query({\n prompt: inputStream,\n options: {\n model: this.config.model,\n systemPrompt,\n settingSources,\n cwd: this.config.workspaceDir,\n permissionMode: \"bypassPermissions\",\n allowDangerouslySkipPermissions: true,\n tools: { type: \"preset\", preset: \"claude_code\" },\n mcpServers: { conveyor: conveyorMcp },\n maxTurns: settings.maxTurns ?? 100,\n resume: context.claudeSessionId ?? undefined,\n effort: settings.effort,\n thinking: settings.thinking,\n betas: settings.betas,\n maxBudgetUsd: settings.maxBudgetUsd,\n disallowedTools: settings.disallowedTools,\n enableFileCheckpointing: settings.enableFileCheckpointing,\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-
|
|
4
|
+
} from "./chunk-QOPHJHQV.js";
|
|
5
5
|
|
|
6
6
|
// src/cli.ts
|
|
7
7
|
var CONVEYOR_API_URL = process.env.CONVEYOR_API_URL;
|
|
@@ -10,13 +10,24 @@ var CONVEYOR_TASK_ID = process.env.CONVEYOR_TASK_ID;
|
|
|
10
10
|
var CONVEYOR_MODEL = process.env.CONVEYOR_MODEL ?? "claude-sonnet-4-20250514";
|
|
11
11
|
var CONVEYOR_INSTRUCTIONS = process.env.CONVEYOR_INSTRUCTIONS ?? "";
|
|
12
12
|
var CONVEYOR_WORKSPACE = process.env.CONVEYOR_WORKSPACE ?? process.cwd();
|
|
13
|
+
var CONVEYOR_MODE = process.env.CONVEYOR_MODE ?? "task";
|
|
13
14
|
if (!CONVEYOR_API_URL || !CONVEYOR_TASK_TOKEN || !CONVEYOR_TASK_ID) {
|
|
14
15
|
console.error("Missing required environment variables:");
|
|
15
16
|
console.error(" CONVEYOR_API_URL - URL of the Conveyor API server");
|
|
16
17
|
console.error(" CONVEYOR_TASK_TOKEN - JWT token for task authentication");
|
|
17
18
|
console.error(" CONVEYOR_TASK_ID - ID of the task to execute");
|
|
19
|
+
console.error("");
|
|
20
|
+
console.error("Optional:");
|
|
21
|
+
console.error(" CONVEYOR_MODE - Runner mode: 'task' (default) or 'pm'");
|
|
22
|
+
console.error(" CONVEYOR_MODEL - Claude model to use");
|
|
23
|
+
console.error(" CONVEYOR_WORKSPACE - Working directory (defaults to cwd)");
|
|
18
24
|
process.exit(1);
|
|
19
25
|
}
|
|
26
|
+
if (CONVEYOR_MODE !== "task" && CONVEYOR_MODE !== "pm") {
|
|
27
|
+
console.error(`Invalid CONVEYOR_MODE: "${CONVEYOR_MODE}". Must be "task" or "pm".`);
|
|
28
|
+
process.exit(1);
|
|
29
|
+
}
|
|
30
|
+
console.log(`[conveyor-agent] Starting in ${CONVEYOR_MODE} mode`);
|
|
20
31
|
var runner = new AgentRunner(
|
|
21
32
|
{
|
|
22
33
|
conveyorApiUrl: CONVEYOR_API_URL,
|
|
@@ -24,7 +35,8 @@ var runner = new AgentRunner(
|
|
|
24
35
|
taskId: CONVEYOR_TASK_ID,
|
|
25
36
|
model: CONVEYOR_MODEL,
|
|
26
37
|
instructions: CONVEYOR_INSTRUCTIONS,
|
|
27
|
-
workspaceDir: CONVEYOR_WORKSPACE
|
|
38
|
+
workspaceDir: CONVEYOR_WORKSPACE,
|
|
39
|
+
mode: CONVEYOR_MODE
|
|
28
40
|
},
|
|
29
41
|
{
|
|
30
42
|
onEvent: (event) => {
|
package/dist/cli.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
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;
|
|
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, RunnerMode } 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();\nconst CONVEYOR_MODE = (process.env.CONVEYOR_MODE ?? \"task\") as RunnerMode;\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 console.error(\"\");\n console.error(\"Optional:\");\n console.error(\" CONVEYOR_MODE - Runner mode: 'task' (default) or 'pm'\");\n console.error(\" CONVEYOR_MODEL - Claude model to use\");\n console.error(\" CONVEYOR_WORKSPACE - Working directory (defaults to cwd)\");\n process.exit(1);\n}\n\nif (CONVEYOR_MODE !== \"task\" && CONVEYOR_MODE !== \"pm\") {\n console.error(`Invalid CONVEYOR_MODE: \"${CONVEYOR_MODE}\". Must be \"task\" or \"pm\".`);\n process.exit(1);\n}\n\nconsole.log(`[conveyor-agent] Starting in ${CONVEYOR_MODE} mode`);\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 mode: CONVEYOR_MODE,\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;AACzE,IAAM,gBAAiB,QAAQ,IAAI,iBAAiB;AAEpD,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,MAAM,EAAE;AAChB,UAAQ,MAAM,WAAW;AACzB,UAAQ,MAAM,yDAAyD;AACvE,UAAQ,MAAM,wCAAwC;AACtD,UAAQ,MAAM,4DAA4D;AAC1E,UAAQ,KAAK,CAAC;AAChB;AAEA,IAAI,kBAAkB,UAAU,kBAAkB,MAAM;AACtD,UAAQ,MAAM,2BAA2B,aAAa,4BAA4B;AAClF,UAAQ,KAAK,CAAC;AAChB;AAEA,QAAQ,IAAI,gCAAgC,aAAa,OAAO;AAEhE,IAAM,SAAS,IAAI;AAAA,EACjB;AAAA,IACE,gBAAgB;AAAA,IAChB,WAAW;AAAA,IACX,QAAQ;AAAA,IACR,OAAO;AAAA,IACP,cAAc;AAAA,IACd,cAAc;AAAA,IACd,MAAM;AAAA,EACR;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
|
@@ -1,3 +1,25 @@
|
|
|
1
|
+
import { ChildProcess } from 'node:child_process';
|
|
2
|
+
|
|
3
|
+
type AgentSettingsThinking = {
|
|
4
|
+
type: "adaptive";
|
|
5
|
+
} | {
|
|
6
|
+
type: "enabled";
|
|
7
|
+
budgetTokens: number;
|
|
8
|
+
} | {
|
|
9
|
+
type: "disabled";
|
|
10
|
+
};
|
|
11
|
+
type SdkBeta = "context-1m-2025-08-07";
|
|
12
|
+
interface AgentSettings {
|
|
13
|
+
effort?: "low" | "medium" | "high" | "max";
|
|
14
|
+
thinking?: AgentSettingsThinking;
|
|
15
|
+
betas?: SdkBeta[];
|
|
16
|
+
maxBudgetUsd?: number;
|
|
17
|
+
maxTurns?: number;
|
|
18
|
+
disallowedTools?: string[];
|
|
19
|
+
enableFileCheckpointing?: boolean;
|
|
20
|
+
settingSources?: ("user" | "project" | "local")[];
|
|
21
|
+
}
|
|
22
|
+
type RunnerMode = "task" | "pm";
|
|
1
23
|
interface AgentRunnerConfig {
|
|
2
24
|
conveyorApiUrl: string;
|
|
3
25
|
taskToken: string;
|
|
@@ -5,6 +27,8 @@ interface AgentRunnerConfig {
|
|
|
5
27
|
model: string;
|
|
6
28
|
instructions: string;
|
|
7
29
|
workspaceDir: string;
|
|
30
|
+
mode?: RunnerMode;
|
|
31
|
+
agentSettings?: AgentSettings;
|
|
8
32
|
}
|
|
9
33
|
interface TaskContext {
|
|
10
34
|
taskId: string;
|
|
@@ -17,6 +41,8 @@ interface TaskContext {
|
|
|
17
41
|
model: string;
|
|
18
42
|
githubBranch: string;
|
|
19
43
|
githubPRUrl?: string | null;
|
|
44
|
+
claudeSessionId?: string | null;
|
|
45
|
+
agentSettings?: AgentSettings | null;
|
|
20
46
|
}
|
|
21
47
|
interface ChatMessage {
|
|
22
48
|
role: "user" | "assistant" | "system";
|
|
@@ -60,6 +86,19 @@ type AgentEvent = {
|
|
|
60
86
|
} | {
|
|
61
87
|
type: "turn_end";
|
|
62
88
|
toolCalls: ActivityEventSummary[];
|
|
89
|
+
} | {
|
|
90
|
+
type: "setup_output";
|
|
91
|
+
stream: "stdout" | "stderr";
|
|
92
|
+
data: string;
|
|
93
|
+
} | {
|
|
94
|
+
type: "setup_complete";
|
|
95
|
+
} | {
|
|
96
|
+
type: "setup_error";
|
|
97
|
+
message: string;
|
|
98
|
+
} | {
|
|
99
|
+
type: "start_command_output";
|
|
100
|
+
stream: "stdout" | "stderr";
|
|
101
|
+
data: string;
|
|
63
102
|
};
|
|
64
103
|
interface ActivityEventSummary {
|
|
65
104
|
tool: string;
|
|
@@ -67,7 +106,7 @@ interface ActivityEventSummary {
|
|
|
67
106
|
output?: string;
|
|
68
107
|
timestamp: string;
|
|
69
108
|
}
|
|
70
|
-
type AgentRunnerStatus = "connecting" | "fetching_context" | "running" | "waiting_for_input" | "stopping" | "finished" | "error";
|
|
109
|
+
type AgentRunnerStatus = "connecting" | "setup" | "fetching_context" | "running" | "waiting_for_input" | "stopping" | "finished" | "error";
|
|
71
110
|
interface AgentRunnerCallbacks {
|
|
72
111
|
onEvent: (event: AgentEvent) => void | Promise<void>;
|
|
73
112
|
onStatusChange: (status: AgentRunnerStatus) => void | Promise<void>;
|
|
@@ -83,6 +122,8 @@ declare class AgentRunner {
|
|
|
83
122
|
private currentTurnToolCalls;
|
|
84
123
|
constructor(config: AgentRunnerConfig, callbacks: AgentRunnerCallbacks);
|
|
85
124
|
start(): Promise<void>;
|
|
125
|
+
private runProjectSetup;
|
|
126
|
+
private executeSetupConfig;
|
|
86
127
|
private injectHumanMessage;
|
|
87
128
|
private createInputStream;
|
|
88
129
|
private findLastAgentMessageIndex;
|
|
@@ -112,6 +153,11 @@ declare class ConveyorConnection {
|
|
|
112
153
|
url: string;
|
|
113
154
|
number: number;
|
|
114
155
|
}>;
|
|
156
|
+
storeSessionId(sessionId: string): void;
|
|
157
|
+
updateTaskFields(fields: {
|
|
158
|
+
plan?: string;
|
|
159
|
+
description?: string;
|
|
160
|
+
}): void;
|
|
115
161
|
onChatMessage(callback: (message: {
|
|
116
162
|
content: string;
|
|
117
163
|
userId: string;
|
|
@@ -120,4 +166,22 @@ declare class ConveyorConnection {
|
|
|
120
166
|
disconnect(): void;
|
|
121
167
|
}
|
|
122
168
|
|
|
123
|
-
|
|
169
|
+
interface ConveyorConfig {
|
|
170
|
+
setupCommand?: string;
|
|
171
|
+
startCommand?: string;
|
|
172
|
+
previewPort?: number;
|
|
173
|
+
}
|
|
174
|
+
declare function loadConveyorConfig(workspaceDir: string): Promise<ConveyorConfig | null>;
|
|
175
|
+
/**
|
|
176
|
+
* Runs a command synchronously (waits for exit). Streams stdout/stderr
|
|
177
|
+
* line-by-line via the onOutput callback.
|
|
178
|
+
*/
|
|
179
|
+
declare function runSetupCommand(cmd: string, cwd: string, onOutput: (stream: "stdout" | "stderr", data: string) => void): Promise<void>;
|
|
180
|
+
/**
|
|
181
|
+
* Runs a command in the background (does not wait for exit). Returns the
|
|
182
|
+
* ChildProcess so it can be cleaned up on agent shutdown. Streams
|
|
183
|
+
* stdout/stderr via the onOutput callback.
|
|
184
|
+
*/
|
|
185
|
+
declare function runStartCommand(cmd: string, cwd: string, onOutput: (stream: "stdout" | "stderr", data: string) => void): ChildProcess;
|
|
186
|
+
|
|
187
|
+
export { type AgentEvent, AgentRunner, type AgentRunnerCallbacks, type AgentRunnerConfig, type ChatMessage, type ConveyorConfig, ConveyorConnection, type TaskContext, loadConveyorConfig, runSetupCommand, runStartCommand };
|
package/dist/index.js
CHANGED
|
@@ -1,9 +1,15 @@
|
|
|
1
1
|
import {
|
|
2
2
|
AgentRunner,
|
|
3
|
-
ConveyorConnection
|
|
4
|
-
|
|
3
|
+
ConveyorConnection,
|
|
4
|
+
loadConveyorConfig,
|
|
5
|
+
runSetupCommand,
|
|
6
|
+
runStartCommand
|
|
7
|
+
} from "./chunk-QOPHJHQV.js";
|
|
5
8
|
export {
|
|
6
9
|
AgentRunner,
|
|
7
|
-
ConveyorConnection
|
|
10
|
+
ConveyorConnection,
|
|
11
|
+
loadConveyorConfig,
|
|
12
|
+
runSetupCommand,
|
|
13
|
+
runStartCommand
|
|
8
14
|
};
|
|
9
15
|
//# sourceMappingURL=index.js.map
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@rallycry/conveyor-agent",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.4.0",
|
|
4
4
|
"description": "Conveyor cloud build agent runner - executes task plans inside GitHub Codespaces",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"agent",
|
|
@@ -10,7 +10,7 @@
|
|
|
10
10
|
],
|
|
11
11
|
"license": "MIT",
|
|
12
12
|
"bin": {
|
|
13
|
-
"conveyor-agent": "
|
|
13
|
+
"conveyor-agent": "dist/cli.js"
|
|
14
14
|
},
|
|
15
15
|
"files": [
|
|
16
16
|
"dist"
|
|
@@ -24,6 +24,8 @@
|
|
|
24
24
|
"scripts": {
|
|
25
25
|
"build": "tsup",
|
|
26
26
|
"dev": "tsup --watch",
|
|
27
|
+
"test": "vitest run",
|
|
28
|
+
"test:watch": "vitest",
|
|
27
29
|
"lint": "oxlint -c ../../.oxlintrc.json src",
|
|
28
30
|
"lint:fix": "oxlint -c ../../.oxlintrc.json --fix src",
|
|
29
31
|
"typecheck": "tsgo --noEmit"
|
|
@@ -36,6 +38,7 @@
|
|
|
36
38
|
},
|
|
37
39
|
"devDependencies": {
|
|
38
40
|
"tsup": "^8.0.0",
|
|
39
|
-
"typescript": "^5.3.0"
|
|
41
|
+
"typescript": "^5.3.0",
|
|
42
|
+
"vitest": "^4.0.17"
|
|
40
43
|
}
|
|
41
44
|
}
|
|
@@ -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 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 `Begin executing the task plan above immediately. Do not perform a preliminary assessment or wait for confirmation before writing code.`,\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 } 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 `\\nEnvironment (ready, no setup required):`,\n `- Repository is cloned at your current working directory.`,\n `- Branch \\`${context.githubBranch}\\` is already checked out.`,\n `- All project dependencies are installed (devcontainer build is complete).`,\n `- Git is configured. Commit and push directly to this branch.`,\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":[]}
|