@rallycry/conveyor-agent 4.10.1 → 5.0.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-XRB3VPXH.js → chunk-DODEEME6.js} +219 -64
- package/dist/chunk-DODEEME6.js.map +1 -0
- package/dist/cli.js +42 -32
- package/dist/cli.js.map +1 -1
- package/dist/index.d.ts +6 -0
- package/dist/index.js +1 -1
- package/package.json +1 -1
- package/dist/chunk-XRB3VPXH.js.map +0 -1
|
@@ -272,6 +272,10 @@ var ConveyorConnection = class _ConveyorConnection {
|
|
|
272
272
|
if (!this.socket) return;
|
|
273
273
|
this.socket.emit("agentRunner:statusUpdate", { status });
|
|
274
274
|
}
|
|
275
|
+
emitAuthToken(token) {
|
|
276
|
+
if (!this.socket) return;
|
|
277
|
+
this.socket.emit("agentRunner:authToken", { token });
|
|
278
|
+
}
|
|
275
279
|
emitRateLimitPause(resetsAt) {
|
|
276
280
|
if (!this.socket) return;
|
|
277
281
|
this.socket.emit("agentRunner:rateLimitPause", { resetsAt });
|
|
@@ -560,6 +564,18 @@ async function loadForwardPorts(workspaceDir) {
|
|
|
560
564
|
}
|
|
561
565
|
}
|
|
562
566
|
async function loadConveyorConfig(workspaceDir) {
|
|
567
|
+
const envSetup = process.env.CONVEYOR_SETUP_COMMAND;
|
|
568
|
+
const envStart = process.env.CONVEYOR_START_COMMAND;
|
|
569
|
+
const envPort = process.env.CONVEYOR_PREVIEW_PORT;
|
|
570
|
+
const envAuth = process.env.CONVEYOR_AUTH_TOKEN_COMMAND;
|
|
571
|
+
if (envSetup || envStart || envAuth) {
|
|
572
|
+
return {
|
|
573
|
+
setupCommand: envSetup,
|
|
574
|
+
startCommand: envStart,
|
|
575
|
+
previewPort: envPort ? Number(envPort) : void 0,
|
|
576
|
+
authTokenCommand: envAuth
|
|
577
|
+
};
|
|
578
|
+
}
|
|
563
579
|
try {
|
|
564
580
|
const raw = await readFile(join2(workspaceDir, CONVEYOR_CONFIG_PATH), "utf-8");
|
|
565
581
|
const parsed = JSON.parse(raw);
|
|
@@ -570,7 +586,7 @@ async function loadConveyorConfig(workspaceDir) {
|
|
|
570
586
|
}
|
|
571
587
|
|
|
572
588
|
// src/setup/commands.ts
|
|
573
|
-
import { spawn } from "child_process";
|
|
589
|
+
import { spawn, execSync as execSync2 } from "child_process";
|
|
574
590
|
function runSetupCommand(cmd, cwd, onOutput) {
|
|
575
591
|
return new Promise((resolve2, reject) => {
|
|
576
592
|
const child = spawn("sh", ["-c", cmd], {
|
|
@@ -596,6 +612,21 @@ function runSetupCommand(cmd, cwd, onOutput) {
|
|
|
596
612
|
});
|
|
597
613
|
});
|
|
598
614
|
}
|
|
615
|
+
var AUTH_TOKEN_TIMEOUT_MS = 3e4;
|
|
616
|
+
function runAuthTokenCommand(cmd, userEmail, cwd) {
|
|
617
|
+
try {
|
|
618
|
+
const output = execSync2(`${cmd} ${JSON.stringify(userEmail)}`, {
|
|
619
|
+
cwd,
|
|
620
|
+
timeout: AUTH_TOKEN_TIMEOUT_MS,
|
|
621
|
+
stdio: ["ignore", "pipe", "ignore"],
|
|
622
|
+
env: { ...process.env }
|
|
623
|
+
});
|
|
624
|
+
const token = output.toString().trim();
|
|
625
|
+
return token || null;
|
|
626
|
+
} catch {
|
|
627
|
+
return null;
|
|
628
|
+
}
|
|
629
|
+
}
|
|
599
630
|
function runStartCommand(cmd, cwd, onOutput) {
|
|
600
631
|
const child = spawn("sh", ["-c", cmd], {
|
|
601
632
|
cwd,
|
|
@@ -614,17 +645,17 @@ function runStartCommand(cmd, cwd, onOutput) {
|
|
|
614
645
|
}
|
|
615
646
|
|
|
616
647
|
// src/setup/codespace.ts
|
|
617
|
-
import { execSync as
|
|
648
|
+
import { execSync as execSync3 } from "child_process";
|
|
618
649
|
function initRtk() {
|
|
619
650
|
try {
|
|
620
|
-
|
|
621
|
-
|
|
651
|
+
execSync3("rtk --version", { stdio: "ignore" });
|
|
652
|
+
execSync3("rtk init --global --auto-patch", { stdio: "ignore" });
|
|
622
653
|
} catch {
|
|
623
654
|
}
|
|
624
655
|
}
|
|
625
656
|
function unshallowRepo(workspaceDir) {
|
|
626
657
|
try {
|
|
627
|
-
|
|
658
|
+
execSync3("git fetch --unshallow", {
|
|
628
659
|
cwd: workspaceDir,
|
|
629
660
|
stdio: "ignore",
|
|
630
661
|
timeout: 6e4
|
|
@@ -633,9 +664,36 @@ function unshallowRepo(workspaceDir) {
|
|
|
633
664
|
}
|
|
634
665
|
}
|
|
635
666
|
|
|
667
|
+
// src/utils/logger.ts
|
|
668
|
+
import winston from "winston";
|
|
669
|
+
var { combine, timestamp, printf, colorize } = winston.format;
|
|
670
|
+
var customFormat = printf(({ level, message, timestamp: ts, service, ...meta }) => {
|
|
671
|
+
const svc = service ? `[${service}] ` : "";
|
|
672
|
+
const metaStr = Object.keys(meta).length ? ` ${JSON.stringify(meta)}` : "";
|
|
673
|
+
return `${ts} [${level}]: ${svc}${message}${metaStr}`;
|
|
674
|
+
});
|
|
675
|
+
var logger = winston.createLogger({
|
|
676
|
+
level: process.env.LOG_LEVEL ?? "info",
|
|
677
|
+
format: combine(timestamp({ format: "YYYY-MM-DD HH:mm:ss" }), combine(colorize(), customFormat)),
|
|
678
|
+
transports: [new winston.transports.Console()]
|
|
679
|
+
});
|
|
680
|
+
function createServiceLogger(serviceName) {
|
|
681
|
+
return logger.child({ service: serviceName });
|
|
682
|
+
}
|
|
683
|
+
function errorMeta(error) {
|
|
684
|
+
if (error instanceof Error) {
|
|
685
|
+
return {
|
|
686
|
+
message: error.message,
|
|
687
|
+
stack: error.stack,
|
|
688
|
+
..."code" in error && typeof error.code === "string" ? { code: error.code } : {}
|
|
689
|
+
};
|
|
690
|
+
}
|
|
691
|
+
return { message: String(error) };
|
|
692
|
+
}
|
|
693
|
+
|
|
636
694
|
// src/runner/agent-runner.ts
|
|
637
695
|
import { randomUUID as randomUUID2 } from "crypto";
|
|
638
|
-
import { execSync as
|
|
696
|
+
import { execSync as execSync4 } from "child_process";
|
|
639
697
|
|
|
640
698
|
// src/execution/event-processor.ts
|
|
641
699
|
function epochSecondsToISO(value) {
|
|
@@ -2820,6 +2878,74 @@ async function executeSetupConfig(config, runnerConfig, connection, setupLog, ef
|
|
|
2820
2878
|
}
|
|
2821
2879
|
return deferredStartConfig;
|
|
2822
2880
|
}
|
|
2881
|
+
async function checkoutTaskBranch(runnerConfig, connection, callbacks, setupLog) {
|
|
2882
|
+
const taskBranch = process.env.CONVEYOR_TASK_BRANCH;
|
|
2883
|
+
if (!taskBranch) return true;
|
|
2884
|
+
pushSetupLog(setupLog, `[conveyor] Switching to task branch ${taskBranch}...`);
|
|
2885
|
+
connection.sendEvent({
|
|
2886
|
+
type: "setup_output",
|
|
2887
|
+
stream: "stdout",
|
|
2888
|
+
data: `Switching to task branch ${taskBranch}...
|
|
2889
|
+
`
|
|
2890
|
+
});
|
|
2891
|
+
try {
|
|
2892
|
+
await runSetupCommand(
|
|
2893
|
+
`git fetch origin ${taskBranch} && git checkout ${taskBranch}`,
|
|
2894
|
+
runnerConfig.workspaceDir,
|
|
2895
|
+
(stream, data) => {
|
|
2896
|
+
connection.sendEvent({ type: "setup_output", stream, data });
|
|
2897
|
+
for (const line of data.split("\n").filter(Boolean)) {
|
|
2898
|
+
pushSetupLog(setupLog, `[${stream}] ${line}`);
|
|
2899
|
+
}
|
|
2900
|
+
}
|
|
2901
|
+
);
|
|
2902
|
+
pushSetupLog(setupLog, `[conveyor] Switched to ${taskBranch}`);
|
|
2903
|
+
return true;
|
|
2904
|
+
} catch (error) {
|
|
2905
|
+
const message = `Failed to checkout ${taskBranch}: ${error instanceof Error ? error.message : "unknown error"}`;
|
|
2906
|
+
connection.sendEvent({ type: "setup_error", message });
|
|
2907
|
+
await callbacks.onEvent({ type: "setup_error", message });
|
|
2908
|
+
connection.postChatMessage(`Failed to switch to task branch \`${taskBranch}\`.
|
|
2909
|
+
|
|
2910
|
+
${message}`);
|
|
2911
|
+
return false;
|
|
2912
|
+
}
|
|
2913
|
+
}
|
|
2914
|
+
async function rebasePullBranch(runnerConfig, connection, callbacks, setupLog) {
|
|
2915
|
+
const pullBranch = process.env.CONVEYOR_PULL_BRANCH;
|
|
2916
|
+
if (!pullBranch) return true;
|
|
2917
|
+
pushSetupLog(setupLog, `[conveyor] Rebasing onto latest ${pullBranch}...`);
|
|
2918
|
+
connection.sendEvent({
|
|
2919
|
+
type: "setup_output",
|
|
2920
|
+
stream: "stdout",
|
|
2921
|
+
data: `Rebasing onto latest ${pullBranch}...
|
|
2922
|
+
`
|
|
2923
|
+
});
|
|
2924
|
+
try {
|
|
2925
|
+
await runSetupCommand(
|
|
2926
|
+
`git fetch origin ${pullBranch} && git rebase origin/${pullBranch}`,
|
|
2927
|
+
runnerConfig.workspaceDir,
|
|
2928
|
+
(stream, data) => {
|
|
2929
|
+
connection.sendEvent({ type: "setup_output", stream, data });
|
|
2930
|
+
for (const line of data.split("\n").filter(Boolean)) {
|
|
2931
|
+
pushSetupLog(setupLog, `[${stream}] ${line}`);
|
|
2932
|
+
}
|
|
2933
|
+
}
|
|
2934
|
+
);
|
|
2935
|
+
pushSetupLog(setupLog, `[conveyor] Rebase complete`);
|
|
2936
|
+
return true;
|
|
2937
|
+
} catch (error) {
|
|
2938
|
+
const message = `Failed to rebase onto ${pullBranch}: ${error instanceof Error ? error.message : "unknown error"}`;
|
|
2939
|
+
connection.sendEvent({ type: "setup_error", message });
|
|
2940
|
+
await callbacks.onEvent({ type: "setup_error", message });
|
|
2941
|
+
connection.postChatMessage(
|
|
2942
|
+
`Failed to rebase onto latest \`${pullBranch}\`. There may be conflicts between the task branch and dev.
|
|
2943
|
+
|
|
2944
|
+
${message}`
|
|
2945
|
+
);
|
|
2946
|
+
return false;
|
|
2947
|
+
}
|
|
2948
|
+
}
|
|
2823
2949
|
async function runSetupSafe(runnerConfig, connection, callbacks, setupLog, effectiveAgentMode, setState) {
|
|
2824
2950
|
await setState("setup");
|
|
2825
2951
|
const ports = await loadForwardPorts(runnerConfig.workspaceDir);
|
|
@@ -2831,18 +2957,24 @@ async function runSetupSafe(runnerConfig, connection, callbacks, setupLog, effec
|
|
|
2831
2957
|
() => void 0
|
|
2832
2958
|
);
|
|
2833
2959
|
}
|
|
2834
|
-
|
|
2835
|
-
|
|
2836
|
-
|
|
2960
|
+
if (!await checkoutTaskBranch(runnerConfig, connection, callbacks, setupLog)) {
|
|
2961
|
+
return { ok: false, deferredStartConfig: null };
|
|
2962
|
+
}
|
|
2963
|
+
if (!await rebasePullBranch(runnerConfig, connection, callbacks, setupLog)) {
|
|
2964
|
+
return { ok: false, deferredStartConfig: null };
|
|
2965
|
+
}
|
|
2966
|
+
const taskBranch = process.env.CONVEYOR_TASK_BRANCH;
|
|
2967
|
+
if (taskBranch) {
|
|
2968
|
+
pushSetupLog(setupLog, `[conveyor] Switching to task branch ${taskBranch}...`);
|
|
2837
2969
|
connection.sendEvent({
|
|
2838
2970
|
type: "setup_output",
|
|
2839
2971
|
stream: "stdout",
|
|
2840
|
-
data: `
|
|
2972
|
+
data: `Switching to task branch ${taskBranch}...
|
|
2841
2973
|
`
|
|
2842
2974
|
});
|
|
2843
2975
|
try {
|
|
2844
2976
|
await runSetupCommand(
|
|
2845
|
-
`git fetch origin ${
|
|
2977
|
+
`git fetch origin ${taskBranch} && git checkout ${taskBranch}`,
|
|
2846
2978
|
runnerConfig.workspaceDir,
|
|
2847
2979
|
(stream, data) => {
|
|
2848
2980
|
connection.sendEvent({ type: "setup_output", stream, data });
|
|
@@ -2851,13 +2983,13 @@ async function runSetupSafe(runnerConfig, connection, callbacks, setupLog, effec
|
|
|
2851
2983
|
}
|
|
2852
2984
|
}
|
|
2853
2985
|
);
|
|
2854
|
-
pushSetupLog(setupLog, `[conveyor]
|
|
2986
|
+
pushSetupLog(setupLog, `[conveyor] Switched to ${taskBranch}`);
|
|
2855
2987
|
} catch (error) {
|
|
2856
|
-
const message = `Failed to
|
|
2988
|
+
const message = `Failed to checkout ${taskBranch}: ${error instanceof Error ? error.message : "unknown error"}`;
|
|
2857
2989
|
connection.sendEvent({ type: "setup_error", message });
|
|
2858
2990
|
await callbacks.onEvent({ type: "setup_error", message });
|
|
2859
2991
|
connection.postChatMessage(
|
|
2860
|
-
`Failed to
|
|
2992
|
+
`Failed to switch to task branch \`${taskBranch}\`.
|
|
2861
2993
|
|
|
2862
2994
|
${message}`
|
|
2863
2995
|
);
|
|
@@ -2897,6 +3029,17 @@ The agent cannot start until this is resolved.`
|
|
|
2897
3029
|
return { ok: false, deferredStartConfig: null };
|
|
2898
3030
|
}
|
|
2899
3031
|
}
|
|
3032
|
+
function runAuthTokenSafe(config, connection, taskContext) {
|
|
3033
|
+
const authCmd = process.env.CONVEYOR_AUTH_TOKEN_COMMAND;
|
|
3034
|
+
if (!authCmd || !taskContext.userEmail) return;
|
|
3035
|
+
try {
|
|
3036
|
+
const token = runAuthTokenCommand(authCmd, taskContext.userEmail, config.workspaceDir);
|
|
3037
|
+
if (token) {
|
|
3038
|
+
connection.emitAuthToken(token);
|
|
3039
|
+
}
|
|
3040
|
+
} catch {
|
|
3041
|
+
}
|
|
3042
|
+
}
|
|
2900
3043
|
function runDeferredStartCommand(deferredStartConfig, runnerConfig, connection, setupLog) {
|
|
2901
3044
|
if (!deferredStartConfig?.startCommand) return;
|
|
2902
3045
|
pushSetupLog(setupLog, `$ ${deferredStartConfig.startCommand} & (background, deferred)`);
|
|
@@ -3022,6 +3165,7 @@ function buildQueryHost(deps) {
|
|
|
3022
3165
|
}
|
|
3023
3166
|
|
|
3024
3167
|
// src/runner/agent-runner.ts
|
|
3168
|
+
var logger2 = createServiceLogger("AgentRunner");
|
|
3025
3169
|
var HEARTBEAT_INTERVAL_MS = 3e4;
|
|
3026
3170
|
var IDLE_TIMEOUT_MS = 30 * 60 * 1e3;
|
|
3027
3171
|
var AgentRunner = class {
|
|
@@ -3125,6 +3269,9 @@ var AgentRunner = class {
|
|
|
3125
3269
|
initRtk();
|
|
3126
3270
|
this.tryInitWorktree();
|
|
3127
3271
|
if (!await this.fetchAndInitContext()) return;
|
|
3272
|
+
if (process.env.CODESPACES === "true" && this.taskContext) {
|
|
3273
|
+
runAuthTokenSafe(this.config, this.connection, this.taskContext);
|
|
3274
|
+
}
|
|
3128
3275
|
this.tryPostContextWorktree();
|
|
3129
3276
|
this.checkoutWorktreeBranch();
|
|
3130
3277
|
await this.executeInitialMode();
|
|
@@ -3181,7 +3328,7 @@ var AgentRunner = class {
|
|
|
3181
3328
|
if (!this.worktreeActive || !this.taskContext?.githubBranch) return;
|
|
3182
3329
|
try {
|
|
3183
3330
|
const branch = this.taskContext.githubBranch;
|
|
3184
|
-
|
|
3331
|
+
execSync4(`git fetch origin ${branch} && git checkout ${branch}`, {
|
|
3185
3332
|
cwd: this.config.workspaceDir,
|
|
3186
3333
|
stdio: "ignore"
|
|
3187
3334
|
});
|
|
@@ -3200,8 +3347,10 @@ var AgentRunner = class {
|
|
|
3200
3347
|
"Auto-nudge: Task is still In Progress with no PR. Prompting agent to continue..."
|
|
3201
3348
|
);
|
|
3202
3349
|
await this.setState("running");
|
|
3350
|
+
const ctx = this.taskContext ?? fresh;
|
|
3351
|
+
if (!ctx) return false;
|
|
3203
3352
|
await this.runQuerySafe(
|
|
3204
|
-
|
|
3353
|
+
ctx,
|
|
3205
3354
|
"You are in Auto mode and your task is still In Progress with no pull request. You MUST create a pull request before finishing. Use the create_pull_request tool now to open a PR for your changes. If you are blocked, explain what is preventing you from creating a PR."
|
|
3206
3355
|
);
|
|
3207
3356
|
return true;
|
|
@@ -3291,7 +3440,12 @@ var AgentRunner = class {
|
|
|
3291
3440
|
handleRunStartCommand() {
|
|
3292
3441
|
if (!this.deferredStartConfig?.startCommand || this.startCommandStarted) return;
|
|
3293
3442
|
this.startCommandStarted = true;
|
|
3294
|
-
runDeferredStartCommand(
|
|
3443
|
+
runDeferredStartCommand(
|
|
3444
|
+
this.deferredStartConfig,
|
|
3445
|
+
this.config,
|
|
3446
|
+
this.connection,
|
|
3447
|
+
this.setupLog
|
|
3448
|
+
);
|
|
3295
3449
|
this.deferredStartConfig = null;
|
|
3296
3450
|
}
|
|
3297
3451
|
logEffectiveSettings() {
|
|
@@ -3299,18 +3453,17 @@ var AgentRunner = class {
|
|
|
3299
3453
|
const s = this.taskContext.agentSettings ?? this.config.agentSettings ?? {};
|
|
3300
3454
|
const model = this.taskContext.model || this.config.model;
|
|
3301
3455
|
const thinking = formatThinkingSetting(s.thinking);
|
|
3302
|
-
|
|
3303
|
-
|
|
3304
|
-
|
|
3305
|
-
|
|
3306
|
-
|
|
3307
|
-
|
|
3308
|
-
|
|
3309
|
-
|
|
3310
|
-
|
|
3311
|
-
|
|
3312
|
-
|
|
3313
|
-
console.log(`[conveyor-agent] ${parts.join(", ")}`);
|
|
3456
|
+
logger2.info("Effective agent settings", {
|
|
3457
|
+
model,
|
|
3458
|
+
mode: this.config.mode ?? "task",
|
|
3459
|
+
effort: s.effort ?? "default",
|
|
3460
|
+
thinking,
|
|
3461
|
+
maxBudget: s.maxBudgetUsd ?? 50,
|
|
3462
|
+
maxTurns: s.maxTurns ?? "unlimited",
|
|
3463
|
+
...s.betas?.length ? { betas: s.betas } : {},
|
|
3464
|
+
...s.disallowedTools?.length ? { disallowedTools: s.disallowedTools } : {},
|
|
3465
|
+
...s.enableFileCheckpointing ? { checkpointing: "on" } : {}
|
|
3466
|
+
});
|
|
3314
3467
|
}
|
|
3315
3468
|
injectHumanMessage(content, files) {
|
|
3316
3469
|
const messageContent = buildMessageContent(content, files);
|
|
@@ -3341,9 +3494,9 @@ var AgentRunner = class {
|
|
|
3341
3494
|
this.idleTimer = setTimeout(() => {
|
|
3342
3495
|
this.clearIdleTimers();
|
|
3343
3496
|
this.inputResolver = null;
|
|
3344
|
-
|
|
3345
|
-
|
|
3346
|
-
);
|
|
3497
|
+
logger2.info("Idle timeout reached, shutting down", {
|
|
3498
|
+
idleMinutes: IDLE_TIMEOUT_MS / 6e4
|
|
3499
|
+
});
|
|
3347
3500
|
this.connection.postChatMessage(
|
|
3348
3501
|
`Agent idle for ${IDLE_TIMEOUT_MS / 6e4} minutes with no new messages \u2014 shutting down.`
|
|
3349
3502
|
);
|
|
@@ -3458,12 +3611,13 @@ var AgentRunner = class {
|
|
|
3458
3611
|
|
|
3459
3612
|
// src/runner/project-runner.ts
|
|
3460
3613
|
import { fork } from "child_process";
|
|
3461
|
-
import { execSync as
|
|
3614
|
+
import { execSync as execSync5 } from "child_process";
|
|
3462
3615
|
import * as path from "path";
|
|
3463
3616
|
import { fileURLToPath } from "url";
|
|
3464
3617
|
|
|
3465
3618
|
// src/runner/project-chat-handler.ts
|
|
3466
3619
|
import { query as query2 } from "@anthropic-ai/claude-agent-sdk";
|
|
3620
|
+
var logger3 = createServiceLogger("ProjectChat");
|
|
3467
3621
|
var FALLBACK_MODEL = "claude-sonnet-4-20250514";
|
|
3468
3622
|
function buildSystemPrompt2(projectDir, agentCtx) {
|
|
3469
3623
|
const parts = [];
|
|
@@ -3516,7 +3670,7 @@ function processContentBlock(block, responseParts, turnToolCalls) {
|
|
|
3516
3670
|
input: inputStr.slice(0, 1e4),
|
|
3517
3671
|
timestamp: (/* @__PURE__ */ new Date()).toISOString()
|
|
3518
3672
|
});
|
|
3519
|
-
|
|
3673
|
+
logger3.debug("Tool use", { tool: block.name });
|
|
3520
3674
|
}
|
|
3521
3675
|
}
|
|
3522
3676
|
async function fetchContext(connection) {
|
|
@@ -3524,13 +3678,13 @@ async function fetchContext(connection) {
|
|
|
3524
3678
|
try {
|
|
3525
3679
|
agentCtx = await connection.fetchAgentContext();
|
|
3526
3680
|
} catch {
|
|
3527
|
-
|
|
3681
|
+
logger3.warn("Could not fetch agent context, using defaults");
|
|
3528
3682
|
}
|
|
3529
3683
|
let chatHistory = [];
|
|
3530
3684
|
try {
|
|
3531
3685
|
chatHistory = await connection.fetchChatHistory(30);
|
|
3532
3686
|
} catch {
|
|
3533
|
-
|
|
3687
|
+
logger3.warn("Could not fetch chat history, proceeding without it");
|
|
3534
3688
|
}
|
|
3535
3689
|
return { agentCtx, chatHistory };
|
|
3536
3690
|
}
|
|
@@ -3604,10 +3758,7 @@ async function handleProjectChatMessage(message, connection, projectDir) {
|
|
|
3604
3758
|
try {
|
|
3605
3759
|
await runChatQuery(message, connection, projectDir);
|
|
3606
3760
|
} catch (error) {
|
|
3607
|
-
|
|
3608
|
-
"[project-chat] Failed to handle message:",
|
|
3609
|
-
error instanceof Error ? error.message : error
|
|
3610
|
-
);
|
|
3761
|
+
logger3.error("Failed to handle message", errorMeta(error));
|
|
3611
3762
|
try {
|
|
3612
3763
|
await connection.emitChatMessage(
|
|
3613
3764
|
"I encountered an error processing your message. Please try again."
|
|
@@ -3620,6 +3771,7 @@ async function handleProjectChatMessage(message, connection, projectDir) {
|
|
|
3620
3771
|
}
|
|
3621
3772
|
|
|
3622
3773
|
// src/runner/project-runner.ts
|
|
3774
|
+
var logger4 = createServiceLogger("ProjectRunner");
|
|
3623
3775
|
var __filename = fileURLToPath(import.meta.url);
|
|
3624
3776
|
var __dirname = path.dirname(__filename);
|
|
3625
3777
|
var HEARTBEAT_INTERVAL_MS2 = 3e4;
|
|
@@ -3637,12 +3789,12 @@ function setupWorkDir(projectDir, assignment) {
|
|
|
3637
3789
|
}
|
|
3638
3790
|
if (branch && branch !== devBranch) {
|
|
3639
3791
|
try {
|
|
3640
|
-
|
|
3792
|
+
execSync5(`git checkout ${branch}`, { cwd: workDir, stdio: "ignore" });
|
|
3641
3793
|
} catch {
|
|
3642
3794
|
try {
|
|
3643
|
-
|
|
3795
|
+
execSync5(`git checkout -b ${branch}`, { cwd: workDir, stdio: "ignore" });
|
|
3644
3796
|
} catch {
|
|
3645
|
-
|
|
3797
|
+
logger4.warn("Could not checkout branch", { taskId: shortId, branch });
|
|
3646
3798
|
}
|
|
3647
3799
|
}
|
|
3648
3800
|
}
|
|
@@ -3680,13 +3832,13 @@ function spawnChildAgent(assignment, workDir) {
|
|
|
3680
3832
|
child.stdout?.on("data", (data) => {
|
|
3681
3833
|
const lines = data.toString().trimEnd().split("\n");
|
|
3682
3834
|
for (const line of lines) {
|
|
3683
|
-
|
|
3835
|
+
logger4.info(line, { taskId: shortId });
|
|
3684
3836
|
}
|
|
3685
3837
|
});
|
|
3686
3838
|
child.stderr?.on("data", (data) => {
|
|
3687
3839
|
const lines = data.toString().trimEnd().split("\n");
|
|
3688
3840
|
for (const line of lines) {
|
|
3689
|
-
|
|
3841
|
+
logger4.error(line, { taskId: shortId });
|
|
3690
3842
|
}
|
|
3691
3843
|
});
|
|
3692
3844
|
return child;
|
|
@@ -3715,17 +3867,17 @@ var ProjectRunner = class {
|
|
|
3715
3867
|
this.handleStopTask(data.taskId);
|
|
3716
3868
|
});
|
|
3717
3869
|
this.connection.onShutdown(() => {
|
|
3718
|
-
|
|
3870
|
+
logger4.info("Received shutdown signal from server");
|
|
3719
3871
|
void this.stop();
|
|
3720
3872
|
});
|
|
3721
3873
|
this.connection.onChatMessage((msg) => {
|
|
3722
|
-
|
|
3874
|
+
logger4.debug("Received project chat message");
|
|
3723
3875
|
void handleProjectChatMessage(msg, this.connection, this.projectDir);
|
|
3724
3876
|
});
|
|
3725
3877
|
this.heartbeatTimer = setInterval(() => {
|
|
3726
3878
|
this.connection.sendHeartbeat();
|
|
3727
3879
|
}, HEARTBEAT_INTERVAL_MS2);
|
|
3728
|
-
|
|
3880
|
+
logger4.info("Connected, waiting for task assignments");
|
|
3729
3881
|
await new Promise((resolve2) => {
|
|
3730
3882
|
this.resolveLifecycle = resolve2;
|
|
3731
3883
|
process.on("SIGTERM", () => void this.stop());
|
|
@@ -3736,21 +3888,22 @@ var ProjectRunner = class {
|
|
|
3736
3888
|
const { taskId, mode } = assignment;
|
|
3737
3889
|
const shortId = taskId.slice(0, 8);
|
|
3738
3890
|
if (this.activeAgents.has(taskId)) {
|
|
3739
|
-
|
|
3891
|
+
logger4.info("Task already running, skipping", { taskId: shortId });
|
|
3740
3892
|
return;
|
|
3741
3893
|
}
|
|
3742
3894
|
if (this.activeAgents.size >= MAX_CONCURRENT) {
|
|
3743
|
-
|
|
3744
|
-
|
|
3745
|
-
|
|
3895
|
+
logger4.warn("Max concurrent agents reached, rejecting task", {
|
|
3896
|
+
maxConcurrent: MAX_CONCURRENT,
|
|
3897
|
+
taskId: shortId
|
|
3898
|
+
});
|
|
3746
3899
|
this.connection.emitTaskStopped(taskId, "max_concurrent_reached");
|
|
3747
3900
|
return;
|
|
3748
3901
|
}
|
|
3749
3902
|
try {
|
|
3750
3903
|
try {
|
|
3751
|
-
|
|
3904
|
+
execSync5("git fetch origin", { cwd: this.projectDir, stdio: "ignore" });
|
|
3752
3905
|
} catch {
|
|
3753
|
-
|
|
3906
|
+
logger4.warn("Git fetch failed", { taskId: shortId });
|
|
3754
3907
|
}
|
|
3755
3908
|
const { workDir, usesWorktree } = setupWorkDir(this.projectDir, assignment);
|
|
3756
3909
|
const child = spawnChildAgent(assignment, workDir);
|
|
@@ -3761,12 +3914,12 @@ var ProjectRunner = class {
|
|
|
3761
3914
|
usesWorktree
|
|
3762
3915
|
});
|
|
3763
3916
|
this.connection.emitTaskStarted(taskId);
|
|
3764
|
-
|
|
3917
|
+
logger4.info("Started task", { taskId: shortId, mode, workDir });
|
|
3765
3918
|
child.on("exit", (code) => {
|
|
3766
3919
|
this.activeAgents.delete(taskId);
|
|
3767
3920
|
const reason = code === 0 ? "completed" : `exited with code ${code}`;
|
|
3768
3921
|
this.connection.emitTaskStopped(taskId, reason);
|
|
3769
|
-
|
|
3922
|
+
logger4.info("Task exited", { taskId: shortId, reason });
|
|
3770
3923
|
if (code === 0 && usesWorktree) {
|
|
3771
3924
|
try {
|
|
3772
3925
|
removeWorktree(this.projectDir, taskId);
|
|
@@ -3775,10 +3928,10 @@ var ProjectRunner = class {
|
|
|
3775
3928
|
}
|
|
3776
3929
|
});
|
|
3777
3930
|
} catch (error) {
|
|
3778
|
-
|
|
3779
|
-
|
|
3780
|
-
error
|
|
3781
|
-
);
|
|
3931
|
+
logger4.error("Failed to start task", {
|
|
3932
|
+
taskId: shortId,
|
|
3933
|
+
...errorMeta(error)
|
|
3934
|
+
});
|
|
3782
3935
|
this.connection.emitTaskStopped(
|
|
3783
3936
|
taskId,
|
|
3784
3937
|
`start_failed: ${error instanceof Error ? error.message : "Unknown"}`
|
|
@@ -3789,7 +3942,7 @@ var ProjectRunner = class {
|
|
|
3789
3942
|
const agent = this.activeAgents.get(taskId);
|
|
3790
3943
|
if (!agent) return;
|
|
3791
3944
|
const shortId = taskId.slice(0, 8);
|
|
3792
|
-
|
|
3945
|
+
logger4.info("Stopping task", { taskId: shortId });
|
|
3793
3946
|
agent.process.kill("SIGTERM");
|
|
3794
3947
|
const timer = setTimeout(() => {
|
|
3795
3948
|
if (this.activeAgents.has(taskId)) {
|
|
@@ -3809,7 +3962,7 @@ var ProjectRunner = class {
|
|
|
3809
3962
|
async stop() {
|
|
3810
3963
|
if (this.stopping) return;
|
|
3811
3964
|
this.stopping = true;
|
|
3812
|
-
|
|
3965
|
+
logger4.info("Shutting down");
|
|
3813
3966
|
if (this.heartbeatTimer) {
|
|
3814
3967
|
clearInterval(this.heartbeatTimer);
|
|
3815
3968
|
this.heartbeatTimer = null;
|
|
@@ -3834,7 +3987,7 @@ var ProjectRunner = class {
|
|
|
3834
3987
|
})
|
|
3835
3988
|
]);
|
|
3836
3989
|
this.connection.disconnect();
|
|
3837
|
-
|
|
3990
|
+
logger4.info("Shutdown complete");
|
|
3838
3991
|
if (this.resolveLifecycle) {
|
|
3839
3992
|
this.resolveLifecycle();
|
|
3840
3993
|
this.resolveLifecycle = null;
|
|
@@ -3914,8 +4067,10 @@ export {
|
|
|
3914
4067
|
loadConveyorConfig,
|
|
3915
4068
|
runSetupCommand,
|
|
3916
4069
|
runStartCommand,
|
|
4070
|
+
createServiceLogger,
|
|
4071
|
+
errorMeta,
|
|
3917
4072
|
AgentRunner,
|
|
3918
4073
|
ProjectRunner,
|
|
3919
4074
|
FileCache
|
|
3920
4075
|
};
|
|
3921
|
-
//# sourceMappingURL=chunk-
|
|
4076
|
+
//# sourceMappingURL=chunk-DODEEME6.js.map
|