@rallycry/conveyor-agent 4.5.0 → 4.7.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/{chunk-7Y3RP3ZA.js → chunk-F4RQRSK6.js} +102 -22
- package/dist/chunk-F4RQRSK6.js.map +1 -0
- package/dist/cli.js +4 -1
- 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-7Y3RP3ZA.js.map +0 -1
|
@@ -103,9 +103,11 @@ var ConveyorConnection = class _ConveyorConnection {
|
|
|
103
103
|
static EVENT_BATCH_MS = 500;
|
|
104
104
|
earlyMessages = [];
|
|
105
105
|
earlyStop = false;
|
|
106
|
+
earlySoftStop = false;
|
|
106
107
|
earlyModeChanges = [];
|
|
107
108
|
chatMessageCallback = null;
|
|
108
109
|
stopCallback = null;
|
|
110
|
+
softStopCallback = null;
|
|
109
111
|
modeChangeCallback = null;
|
|
110
112
|
runStartCommandCallback = null;
|
|
111
113
|
pendingQuestionResolvers = /* @__PURE__ */ new Map();
|
|
@@ -135,6 +137,10 @@ var ConveyorConnection = class _ConveyorConnection {
|
|
|
135
137
|
if (this.stopCallback) this.stopCallback();
|
|
136
138
|
else this.earlyStop = true;
|
|
137
139
|
});
|
|
140
|
+
this.socket.on("agentRunner:softStop", () => {
|
|
141
|
+
if (this.softStopCallback) this.softStopCallback();
|
|
142
|
+
else this.earlySoftStop = true;
|
|
143
|
+
});
|
|
138
144
|
this.socket.on("agentRunner:questionAnswer", (data) => {
|
|
139
145
|
const resolver = this.pendingQuestionResolvers.get(data.requestId);
|
|
140
146
|
if (resolver) {
|
|
@@ -233,6 +239,13 @@ var ConveyorConnection = class _ConveyorConnection {
|
|
|
233
239
|
this.earlyStop = false;
|
|
234
240
|
}
|
|
235
241
|
}
|
|
242
|
+
onSoftStopRequested(callback) {
|
|
243
|
+
this.softStopCallback = callback;
|
|
244
|
+
if (this.earlySoftStop) {
|
|
245
|
+
callback();
|
|
246
|
+
this.earlySoftStop = false;
|
|
247
|
+
}
|
|
248
|
+
}
|
|
236
249
|
onModeChange(callback) {
|
|
237
250
|
this.modeChangeCallback = callback;
|
|
238
251
|
for (const data of this.earlyModeChanges) callback(data);
|
|
@@ -485,6 +498,9 @@ import { existsSync } from "fs";
|
|
|
485
498
|
import { join } from "path";
|
|
486
499
|
var WORKTREE_DIR = ".worktrees";
|
|
487
500
|
function ensureWorktree(projectDir, taskId, branch) {
|
|
501
|
+
if (projectDir.includes(`/${WORKTREE_DIR}/`)) {
|
|
502
|
+
return projectDir;
|
|
503
|
+
}
|
|
488
504
|
const worktreePath = join(projectDir, WORKTREE_DIR, taskId);
|
|
489
505
|
if (existsSync(worktreePath)) {
|
|
490
506
|
if (branch) {
|
|
@@ -538,14 +554,6 @@ async function loadConveyorConfig(workspaceDir) {
|
|
|
538
554
|
if (parsed.setupCommand || parsed.startCommand) return parsed;
|
|
539
555
|
} catch {
|
|
540
556
|
}
|
|
541
|
-
try {
|
|
542
|
-
const raw = await readFile(join2(workspaceDir, DEVCONTAINER_PATH), "utf-8");
|
|
543
|
-
const parsed = JSON.parse(raw);
|
|
544
|
-
if (parsed.conveyor && (parsed.conveyor.startCommand || parsed.conveyor.setupCommand)) {
|
|
545
|
-
return parsed.conveyor;
|
|
546
|
-
}
|
|
547
|
-
} catch {
|
|
548
|
-
}
|
|
549
557
|
return null;
|
|
550
558
|
}
|
|
551
559
|
|
|
@@ -2070,11 +2078,11 @@ function getModeTools(agentMode, connection, config, context) {
|
|
|
2070
2078
|
return config.mode === "pm" ? buildPmTools(connection, context?.storyPoints, { includePackTools: false }) : buildTaskTools(connection);
|
|
2071
2079
|
}
|
|
2072
2080
|
}
|
|
2073
|
-
function createConveyorMcpServer(connection, config, context) {
|
|
2081
|
+
function createConveyorMcpServer(connection, config, context, agentMode) {
|
|
2074
2082
|
const commonTools = buildCommonTools(connection, config);
|
|
2075
|
-
const
|
|
2076
|
-
const modeTools = getModeTools(
|
|
2077
|
-
const discoveryTools =
|
|
2083
|
+
const effectiveMode = agentMode ?? context?.agentMode ?? void 0;
|
|
2084
|
+
const modeTools = getModeTools(effectiveMode, connection, config, context);
|
|
2085
|
+
const discoveryTools = effectiveMode === "discovery" || effectiveMode === "auto" ? buildDiscoveryTools(connection, context) : [];
|
|
2078
2086
|
return createSdkMcpServer({
|
|
2079
2087
|
name: "conveyor",
|
|
2080
2088
|
tools: [...commonTools, ...modeTools, ...discoveryTools]
|
|
@@ -2317,7 +2325,7 @@ function buildQueryOptions(host, context) {
|
|
|
2317
2325
|
allowDangerouslySkipPermissions: !needsCanUseTool,
|
|
2318
2326
|
canUseTool: buildCanUseTool(host),
|
|
2319
2327
|
tools: { type: "preset", preset: "claude_code" },
|
|
2320
|
-
mcpServers: { conveyor: createConveyorMcpServer(host.connection, host.config, context) },
|
|
2328
|
+
mcpServers: { conveyor: createConveyorMcpServer(host.connection, host.config, context, mode) },
|
|
2321
2329
|
hooks: buildHooks(host),
|
|
2322
2330
|
maxTurns: settings.maxTurns,
|
|
2323
2331
|
effort: settings.effort,
|
|
@@ -2406,7 +2414,12 @@ async function runSdkQuery(host, context, followUpContent) {
|
|
|
2406
2414
|
prompt: typeof prompt === "string" ? prompt : host.createInputStream(prompt),
|
|
2407
2415
|
options: { ...options, resume }
|
|
2408
2416
|
});
|
|
2409
|
-
|
|
2417
|
+
host.activeQuery = agentQuery;
|
|
2418
|
+
try {
|
|
2419
|
+
await runWithRetry(agentQuery, context, host, options);
|
|
2420
|
+
} finally {
|
|
2421
|
+
host.activeQuery = null;
|
|
2422
|
+
}
|
|
2410
2423
|
} else if (isDiscoveryLike) {
|
|
2411
2424
|
return;
|
|
2412
2425
|
} else {
|
|
@@ -2416,7 +2429,12 @@ async function runSdkQuery(host, context, followUpContent) {
|
|
|
2416
2429
|
prompt: host.createInputStream(prompt),
|
|
2417
2430
|
options: { ...options, resume }
|
|
2418
2431
|
});
|
|
2419
|
-
|
|
2432
|
+
host.activeQuery = agentQuery;
|
|
2433
|
+
try {
|
|
2434
|
+
await runWithRetry(agentQuery, context, host, options);
|
|
2435
|
+
} finally {
|
|
2436
|
+
host.activeQuery = null;
|
|
2437
|
+
}
|
|
2420
2438
|
}
|
|
2421
2439
|
if (isDiscoveryLike) {
|
|
2422
2440
|
host.syncPlanFile();
|
|
@@ -2702,6 +2720,39 @@ async function runSetupSafe(runnerConfig, connection, callbacks, setupLog, effec
|
|
|
2702
2720
|
() => void 0
|
|
2703
2721
|
);
|
|
2704
2722
|
}
|
|
2723
|
+
const pullBranch = process.env.CONVEYOR_PULL_BRANCH;
|
|
2724
|
+
if (pullBranch) {
|
|
2725
|
+
pushSetupLog(setupLog, `[conveyor] Merging latest from ${pullBranch}...`);
|
|
2726
|
+
connection.sendEvent({
|
|
2727
|
+
type: "setup_output",
|
|
2728
|
+
stream: "stdout",
|
|
2729
|
+
data: `Merging latest from ${pullBranch}...
|
|
2730
|
+
`
|
|
2731
|
+
});
|
|
2732
|
+
try {
|
|
2733
|
+
await runSetupCommand(
|
|
2734
|
+
`git fetch origin ${pullBranch} && git merge origin/${pullBranch} --no-edit`,
|
|
2735
|
+
runnerConfig.workspaceDir,
|
|
2736
|
+
(stream, data) => {
|
|
2737
|
+
connection.sendEvent({ type: "setup_output", stream, data });
|
|
2738
|
+
for (const line of data.split("\n").filter(Boolean)) {
|
|
2739
|
+
pushSetupLog(setupLog, `[${stream}] ${line}`);
|
|
2740
|
+
}
|
|
2741
|
+
}
|
|
2742
|
+
);
|
|
2743
|
+
pushSetupLog(setupLog, `[conveyor] Merge complete`);
|
|
2744
|
+
} catch (error) {
|
|
2745
|
+
const message = `Failed to merge ${pullBranch}: ${error instanceof Error ? error.message : "unknown error"}`;
|
|
2746
|
+
connection.sendEvent({ type: "setup_error", message });
|
|
2747
|
+
await callbacks.onEvent({ type: "setup_error", message });
|
|
2748
|
+
connection.postChatMessage(
|
|
2749
|
+
`Failed to merge latest code from \`${pullBranch}\`. There may be conflicts between the prebuild branch and dev.
|
|
2750
|
+
|
|
2751
|
+
${message}`
|
|
2752
|
+
);
|
|
2753
|
+
return { ok: false, deferredStartConfig: null };
|
|
2754
|
+
}
|
|
2755
|
+
}
|
|
2705
2756
|
const config = await loadConveyorConfig(runnerConfig.workspaceDir);
|
|
2706
2757
|
if (!config) {
|
|
2707
2758
|
connection.sendEvent({ type: "setup_complete" });
|
|
@@ -2850,6 +2901,7 @@ function buildQueryHost(deps) {
|
|
|
2850
2901
|
deps.setPendingModeRestart(val);
|
|
2851
2902
|
},
|
|
2852
2903
|
sessionIds: deps.sessionIds,
|
|
2904
|
+
activeQuery: null,
|
|
2853
2905
|
isStopped: deps.isStopped,
|
|
2854
2906
|
createInputStream: deps.createInputStream,
|
|
2855
2907
|
snapshotPlanFiles: () => deps.planSync.snapshotPlanFiles(),
|
|
@@ -2867,6 +2919,7 @@ var AgentRunner = class {
|
|
|
2867
2919
|
callbacks;
|
|
2868
2920
|
_state = "connecting";
|
|
2869
2921
|
stopped = false;
|
|
2922
|
+
interrupted = false;
|
|
2870
2923
|
inputResolver = null;
|
|
2871
2924
|
pendingMessages = [];
|
|
2872
2925
|
setupLog = [];
|
|
@@ -2884,6 +2937,7 @@ var AgentRunner = class {
|
|
|
2884
2937
|
idleTimer = null;
|
|
2885
2938
|
idleCheckInterval = null;
|
|
2886
2939
|
deferredStartConfig = null;
|
|
2940
|
+
_queryHost = null;
|
|
2887
2941
|
constructor(config, callbacks) {
|
|
2888
2942
|
this.config = config;
|
|
2889
2943
|
this.connection = new ConveyorConnection(config);
|
|
@@ -2930,6 +2984,7 @@ var AgentRunner = class {
|
|
|
2930
2984
|
await this.setState("connecting");
|
|
2931
2985
|
await this.connection.connect();
|
|
2932
2986
|
this.connection.onStopRequested(() => this.stop());
|
|
2987
|
+
this.connection.onSoftStopRequested(() => this.softStop());
|
|
2933
2988
|
this.connection.onChatMessage(
|
|
2934
2989
|
(message) => this.injectHumanMessage(message.content, message.files)
|
|
2935
2990
|
);
|
|
@@ -2991,7 +3046,7 @@ var AgentRunner = class {
|
|
|
2991
3046
|
return true;
|
|
2992
3047
|
}
|
|
2993
3048
|
tryPostContextWorktree() {
|
|
2994
|
-
if (process.env.CODESPACES !== "true" && !this.worktreeActive && this.taskContext?.useWorktree) {
|
|
3049
|
+
if (process.env.CODESPACES !== "true" && process.env.CONVEYOR_USE_WORKTREE !== "false" && !this.worktreeActive && this.taskContext?.useWorktree) {
|
|
2995
3050
|
this.activateWorktree("[conveyor] Using worktree (from task config):");
|
|
2996
3051
|
}
|
|
2997
3052
|
}
|
|
@@ -3072,9 +3127,17 @@ var AgentRunner = class {
|
|
|
3072
3127
|
}
|
|
3073
3128
|
if (this._state === "idle") {
|
|
3074
3129
|
const msg = await this.waitForUserContent();
|
|
3075
|
-
if (!msg)
|
|
3130
|
+
if (!msg) {
|
|
3131
|
+
if (this.interrupted && !this.stopped) {
|
|
3132
|
+
this.interrupted = false;
|
|
3133
|
+
continue;
|
|
3134
|
+
}
|
|
3135
|
+
break;
|
|
3136
|
+
}
|
|
3076
3137
|
await this.setState("running");
|
|
3138
|
+
this.interrupted = false;
|
|
3077
3139
|
await this.runQuerySafe(this.taskContext, msg);
|
|
3140
|
+
if (this.interrupted) this.interrupted = false;
|
|
3078
3141
|
if (!this.stopped && this._state !== "error") await this.setState("idle");
|
|
3079
3142
|
} else if (this._state === "error") {
|
|
3080
3143
|
await this.setState("idle");
|
|
@@ -3127,7 +3190,7 @@ var AgentRunner = class {
|
|
|
3127
3190
|
this.clearIdleTimers();
|
|
3128
3191
|
return new Promise((resolve2) => {
|
|
3129
3192
|
this.idleCheckInterval = setInterval(() => {
|
|
3130
|
-
if (this.stopped) {
|
|
3193
|
+
if (this.stopped || this.interrupted) {
|
|
3131
3194
|
this.clearIdleTimers();
|
|
3132
3195
|
this.inputResolver = null;
|
|
3133
3196
|
resolve2(null);
|
|
@@ -3167,7 +3230,7 @@ var AgentRunner = class {
|
|
|
3167
3230
|
});
|
|
3168
3231
|
yield makeUserMessage(initialPrompt);
|
|
3169
3232
|
try {
|
|
3170
|
-
while (!this.stopped) {
|
|
3233
|
+
while (!this.stopped && !this.interrupted) {
|
|
3171
3234
|
if (this.pendingMessages.length > 0) {
|
|
3172
3235
|
const next = this.pendingMessages.shift();
|
|
3173
3236
|
if (next) yield next;
|
|
@@ -3186,7 +3249,7 @@ var AgentRunner = class {
|
|
|
3186
3249
|
}
|
|
3187
3250
|
}
|
|
3188
3251
|
asQueryHost() {
|
|
3189
|
-
|
|
3252
|
+
const host = buildQueryHost({
|
|
3190
3253
|
config: this.config,
|
|
3191
3254
|
connection: this.connection,
|
|
3192
3255
|
callbacks: this.callbacks,
|
|
@@ -3204,12 +3267,14 @@ var AgentRunner = class {
|
|
|
3204
3267
|
setPendingModeRestart: (val) => {
|
|
3205
3268
|
this.pendingModeRestart = val;
|
|
3206
3269
|
},
|
|
3207
|
-
isStopped: () => this.stopped,
|
|
3270
|
+
isStopped: () => this.stopped || this.interrupted,
|
|
3208
3271
|
createInputStream: (prompt) => this.createInputStream(prompt),
|
|
3209
3272
|
onModeTransition: (newMode) => {
|
|
3210
3273
|
this.agentMode = newMode;
|
|
3211
3274
|
}
|
|
3212
3275
|
});
|
|
3276
|
+
this._queryHost = host;
|
|
3277
|
+
return host;
|
|
3213
3278
|
}
|
|
3214
3279
|
handleModeChange(newAgentMode) {
|
|
3215
3280
|
if (this.config.mode !== "pm") return;
|
|
@@ -3224,6 +3289,21 @@ var AgentRunner = class {
|
|
|
3224
3289
|
this.taskContext.status = "InProgress";
|
|
3225
3290
|
}
|
|
3226
3291
|
}
|
|
3292
|
+
softStop() {
|
|
3293
|
+
this.interrupted = true;
|
|
3294
|
+
const host = this._queryHost;
|
|
3295
|
+
if (host?.activeQuery) {
|
|
3296
|
+
const q = host.activeQuery;
|
|
3297
|
+
if (typeof q.interrupt === "function") {
|
|
3298
|
+
void q.interrupt();
|
|
3299
|
+
}
|
|
3300
|
+
host.activeQuery = null;
|
|
3301
|
+
}
|
|
3302
|
+
if (this.inputResolver) {
|
|
3303
|
+
this.inputResolver(null);
|
|
3304
|
+
this.inputResolver = null;
|
|
3305
|
+
}
|
|
3306
|
+
}
|
|
3227
3307
|
stop() {
|
|
3228
3308
|
this.stopped = true;
|
|
3229
3309
|
this.clearIdleTimers();
|
|
@@ -3696,4 +3776,4 @@ export {
|
|
|
3696
3776
|
ProjectRunner,
|
|
3697
3777
|
FileCache
|
|
3698
3778
|
};
|
|
3699
|
-
//# sourceMappingURL=chunk-
|
|
3779
|
+
//# sourceMappingURL=chunk-F4RQRSK6.js.map
|