@rallycry/conveyor-agent 7.0.6 → 7.0.8
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-3H2FXJFD.js → chunk-PMDVB2EU.js} +60 -9
- package/dist/chunk-PMDVB2EU.js.map +1 -0
- package/dist/cli.js +37 -19
- package/dist/cli.js.map +1 -1
- package/dist/index.d.ts +13 -0
- package/dist/index.js +1 -1
- package/package.json +1 -1
- package/dist/chunk-3H2FXJFD.js.map +0 -1
|
@@ -15,6 +15,8 @@ var AgentConnection = class _AgentConnection {
|
|
|
15
15
|
eventBuffer = [];
|
|
16
16
|
flushTimer = null;
|
|
17
17
|
lastEmittedStatus = null;
|
|
18
|
+
// Pending answer resolvers for askUserQuestion room-event fallback
|
|
19
|
+
pendingAnswerResolvers = /* @__PURE__ */ new Map();
|
|
18
20
|
// Dedup: suppress near-identical messages within a short window
|
|
19
21
|
recentMessages = [];
|
|
20
22
|
static DEDUP_WINDOW_MS = 3e4;
|
|
@@ -114,6 +116,13 @@ var AgentConnection = class _AgentConnection {
|
|
|
114
116
|
this.earlyMessages.push({ content: "", userId: "system" });
|
|
115
117
|
}
|
|
116
118
|
});
|
|
119
|
+
this.socket.on(
|
|
120
|
+
"session:answerQuestion",
|
|
121
|
+
(data) => {
|
|
122
|
+
const resolver = this.pendingAnswerResolvers.get(data.requestId);
|
|
123
|
+
if (resolver) resolver(data.answers);
|
|
124
|
+
}
|
|
125
|
+
);
|
|
117
126
|
this.socket.on("agentRunner:updateApiKey", (data) => {
|
|
118
127
|
if (this.apiKeyUpdateCallback) this.apiKeyUpdateCallback(data);
|
|
119
128
|
});
|
|
@@ -267,7 +276,7 @@ var AgentConnection = class _AgentConnection {
|
|
|
267
276
|
(m) => now - m.timestamp < _AgentConnection.DEDUP_WINDOW_MS
|
|
268
277
|
);
|
|
269
278
|
const words = new Set(
|
|
270
|
-
content.toLowerCase().split(/\s+/).filter((w) => w.length >= 3)
|
|
279
|
+
content.toLowerCase().replace(/[^\w\s]/g, "").split(/\s+/).filter((w) => w.length >= 3)
|
|
271
280
|
);
|
|
272
281
|
if (words.size === 0) return false;
|
|
273
282
|
for (const recent of this.recentMessages) {
|
|
@@ -364,13 +373,20 @@ var AgentConnection = class _AgentConnection {
|
|
|
364
373
|
${q.question}${q.options.length ? "\n" + q.options.map((o) => `- ${o.label}: ${o.description}`).join("\n") : ""}`
|
|
365
374
|
).join("\n\n");
|
|
366
375
|
const requestId = crypto.randomUUID();
|
|
367
|
-
const
|
|
376
|
+
const roomEventPromise = new Promise((resolve2) => {
|
|
377
|
+
this.pendingAnswerResolvers.set(requestId, resolve2);
|
|
378
|
+
});
|
|
379
|
+
const rpcPromise = this.call("askUserQuestion", {
|
|
368
380
|
sessionId: this.config.sessionId,
|
|
369
381
|
question: questionText,
|
|
370
382
|
requestId,
|
|
371
383
|
questions
|
|
372
|
-
});
|
|
373
|
-
|
|
384
|
+
}).then((res) => res.answers);
|
|
385
|
+
try {
|
|
386
|
+
return await Promise.race([rpcPromise, roomEventPromise]);
|
|
387
|
+
} finally {
|
|
388
|
+
this.pendingAnswerResolvers.delete(requestId);
|
|
389
|
+
}
|
|
374
390
|
}
|
|
375
391
|
// ── Typed service method wrappers ───────────────────────────────────
|
|
376
392
|
getTaskProperties() {
|
|
@@ -4957,7 +4973,7 @@ async function handleExitPlanMode(host, input) {
|
|
|
4957
4973
|
host.connection.postChatMessage(
|
|
4958
4974
|
"Plan complete. The task stays in Planning \u2014 identify it or switch to Build mode when ready."
|
|
4959
4975
|
);
|
|
4960
|
-
host.
|
|
4976
|
+
host.requestSoftStop();
|
|
4961
4977
|
return { behavior: "allow", updatedInput: input };
|
|
4962
4978
|
}
|
|
4963
4979
|
await host.connection.triggerIdentification();
|
|
@@ -5000,6 +5016,7 @@ async function handleAskUserQuestion(host, input) {
|
|
|
5000
5016
|
return { behavior: "allow", updatedInput: { questions: input.questions, answers } };
|
|
5001
5017
|
}
|
|
5002
5018
|
var DENIAL_WARNING_THRESHOLD = 3;
|
|
5019
|
+
var DENIAL_FORCE_STOP_THRESHOLD = 8;
|
|
5003
5020
|
function isResourceHeavyCommand(command) {
|
|
5004
5021
|
return RESOURCE_HEAVY_PATTERNS.some((p) => p.test(command));
|
|
5005
5022
|
}
|
|
@@ -5048,6 +5065,12 @@ function buildCanUseTool(host) {
|
|
|
5048
5065
|
`\u26A0\uFE0F Multiple tool denials detected. You are in ${host.agentMode} mode \u2014 file writes outside .claude/plans/ are not permitted. Focus on creating a plan instead of implementing code changes.`
|
|
5049
5066
|
);
|
|
5050
5067
|
}
|
|
5068
|
+
if (consecutiveDenials >= DENIAL_FORCE_STOP_THRESHOLD) {
|
|
5069
|
+
host.connection.postChatMessage(
|
|
5070
|
+
`Agent force-stopped after ${DENIAL_FORCE_STOP_THRESHOLD} consecutive tool denials. The agent appears stuck \u2014 send a message to resume.`
|
|
5071
|
+
);
|
|
5072
|
+
host.requestStop();
|
|
5073
|
+
}
|
|
5051
5074
|
} else {
|
|
5052
5075
|
consecutiveDenials = 0;
|
|
5053
5076
|
}
|
|
@@ -5485,6 +5508,8 @@ var QueryBridge = class {
|
|
|
5485
5508
|
_abortController = null;
|
|
5486
5509
|
/** Called by SessionRunner when ExitPlanMode triggers a mode transition. */
|
|
5487
5510
|
onModeTransition;
|
|
5511
|
+
/** Called by tool handlers to soft-stop (abort query, keep session alive). */
|
|
5512
|
+
onSoftStop;
|
|
5488
5513
|
get isStopped() {
|
|
5489
5514
|
return this._stopped;
|
|
5490
5515
|
}
|
|
@@ -5568,6 +5593,9 @@ var QueryBridge = class {
|
|
|
5568
5593
|
},
|
|
5569
5594
|
isStopped: () => bridge._stopped,
|
|
5570
5595
|
requestStop: () => bridge.stop(),
|
|
5596
|
+
requestSoftStop: () => {
|
|
5597
|
+
if (bridge.onSoftStop) bridge.onSoftStop();
|
|
5598
|
+
},
|
|
5571
5599
|
createInputStream: (prompt) => bridge.createInputStream(prompt),
|
|
5572
5600
|
snapshotPlanFiles: () => bridge.planSync.snapshotPlanFiles(),
|
|
5573
5601
|
syncPlanFile: () => bridge.planSync.syncPlanFile(),
|
|
@@ -5643,8 +5671,12 @@ var SessionRunner = class _SessionRunner {
|
|
|
5643
5671
|
return this.stopped;
|
|
5644
5672
|
}
|
|
5645
5673
|
// ── Main lifecycle ─────────────────────────────────────────────────
|
|
5646
|
-
|
|
5647
|
-
|
|
5674
|
+
/**
|
|
5675
|
+
* Establish the API connection, wire callbacks, and join the session room.
|
|
5676
|
+
* Call this before run() when you need to send events (e.g. setup/start
|
|
5677
|
+
* command output) before the main agent lifecycle begins.
|
|
5678
|
+
*/
|
|
5679
|
+
async connect() {
|
|
5648
5680
|
await this.setState("connecting");
|
|
5649
5681
|
await this.connection.connect();
|
|
5650
5682
|
await this.setState("connected");
|
|
@@ -5659,6 +5691,13 @@ var SessionRunner = class _SessionRunner {
|
|
|
5659
5691
|
this.pendingMessages.push({ content: msg.content, userId: msg.userId });
|
|
5660
5692
|
}
|
|
5661
5693
|
}
|
|
5694
|
+
}
|
|
5695
|
+
/**
|
|
5696
|
+
* Run the main agent lifecycle: fetch context, resolve mode, execute, loop.
|
|
5697
|
+
* Requires connect() to have been called first.
|
|
5698
|
+
*/
|
|
5699
|
+
// oxlint-disable-next-line max-lines-per-function, complexity -- lifecycle orchestration is inherently sequential
|
|
5700
|
+
async run() {
|
|
5662
5701
|
await this.setState("fetching_context");
|
|
5663
5702
|
try {
|
|
5664
5703
|
const ctx = await this.connection.call("getTaskContext", {
|
|
@@ -5706,6 +5745,11 @@ var SessionRunner = class _SessionRunner {
|
|
|
5706
5745
|
}
|
|
5707
5746
|
await this.shutdown("finished");
|
|
5708
5747
|
}
|
|
5748
|
+
/** Convenience wrapper: connect() then run(). */
|
|
5749
|
+
async start() {
|
|
5750
|
+
await this.connect();
|
|
5751
|
+
await this.run();
|
|
5752
|
+
}
|
|
5709
5753
|
// ── Core loop ──────────────────────────────────────────────────────
|
|
5710
5754
|
async coreLoop() {
|
|
5711
5755
|
while (!this.stopped) {
|
|
@@ -5863,7 +5907,7 @@ var SessionRunner = class _SessionRunner {
|
|
|
5863
5907
|
async maybeSendPRNudge() {
|
|
5864
5908
|
await this.refreshTaskContext();
|
|
5865
5909
|
if (!this.needsPRNudge()) return;
|
|
5866
|
-
while (!this.stopped && this.needsPRNudge()) {
|
|
5910
|
+
while (!this.stopped && !this.interrupted && this.needsPRNudge()) {
|
|
5867
5911
|
this.prNudgeCount++;
|
|
5868
5912
|
if (this.prNudgeCount > _SessionRunner.MAX_PR_NUDGES) {
|
|
5869
5913
|
this.connection.postChatMessage(
|
|
@@ -5878,6 +5922,7 @@ var SessionRunner = class _SessionRunner {
|
|
|
5878
5922
|
this.connection.postChatMessage(chatMsg);
|
|
5879
5923
|
await this.setState("running");
|
|
5880
5924
|
await this.callbacks.onEvent({ type: "pr_nudge", prompt });
|
|
5925
|
+
if (this.interrupted || this.stopped) return;
|
|
5881
5926
|
await this.executeQuery(prompt);
|
|
5882
5927
|
if (this.interrupted || this.stopped) return;
|
|
5883
5928
|
await this.refreshTaskContext();
|
|
@@ -5950,6 +5995,10 @@ var SessionRunner = class _SessionRunner {
|
|
|
5950
5995
|
this.config.workspaceDir
|
|
5951
5996
|
);
|
|
5952
5997
|
bridge.isParentTask = this.fullContext?.isParentTask ?? false;
|
|
5998
|
+
bridge.onSoftStop = () => {
|
|
5999
|
+
process.stderr.write("[conveyor-agent] Soft stop requested (discovery ExitPlanMode)\n");
|
|
6000
|
+
this.softStop();
|
|
6001
|
+
};
|
|
5953
6002
|
bridge.onModeTransition = (newMode) => {
|
|
5954
6003
|
const oldMode = this.mode.effectiveMode;
|
|
5955
6004
|
process.stderr.write(`[conveyor-agent] Mode transition: ${oldMode} \u2192 ${newMode}
|
|
@@ -6814,6 +6863,8 @@ function spawnChildAgent(assignment, workDir) {
|
|
|
6814
6863
|
const childEnv = { ...process.env };
|
|
6815
6864
|
delete childEnv.CONVEYOR_PROJECT_TOKEN;
|
|
6816
6865
|
delete childEnv.CONVEYOR_PROJECT_ID;
|
|
6866
|
+
delete childEnv.CONVEYOR_SETUP_COMMAND;
|
|
6867
|
+
delete childEnv.CONVEYOR_START_COMMAND;
|
|
6817
6868
|
const effectiveAgentMode = agentMode ?? (isAuto ? "auto" : "");
|
|
6818
6869
|
const effectiveApiUrl = apiUrl || process.env.CONVEYOR_API_URL || "";
|
|
6819
6870
|
if (!effectiveApiUrl) {
|
|
@@ -7427,4 +7478,4 @@ export {
|
|
|
7427
7478
|
loadForwardPorts,
|
|
7428
7479
|
loadConveyorConfig
|
|
7429
7480
|
};
|
|
7430
|
-
//# sourceMappingURL=chunk-
|
|
7481
|
+
//# sourceMappingURL=chunk-PMDVB2EU.js.map
|