@rallycry/conveyor-agent 8.8.1 → 8.9.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-4ZZXIHJV.js → chunk-6462GDLZ.js} +66 -24
- package/dist/{chunk-4ZZXIHJV.js.map → chunk-6462GDLZ.js.map} +1 -1
- package/dist/{chunk-EOGZOS2H.js → chunk-TN2YYT2V.js} +1 -1
- package/dist/{chunk-EOGZOS2H.js.map → chunk-TN2YYT2V.js.map} +1 -1
- package/dist/cli.js +2 -2
- package/dist/index.d.ts +27 -3
- package/dist/index.js +2 -2
- package/dist/{tag-audit-handler-S4VT47XG.js → tag-audit-handler-X3LEX63H.js} +2 -2
- package/dist/{task-audit-handler-QK7S4LWO.js → task-audit-handler-BRCXB5V6.js} +2 -2
- package/package.json +1 -1
- /package/dist/{tag-audit-handler-S4VT47XG.js.map → tag-audit-handler-X3LEX63H.js.map} +0 -0
- /package/dist/{task-audit-handler-QK7S4LWO.js.map → task-audit-handler-BRCXB5V6.js.map} +0 -0
|
@@ -12,7 +12,7 @@ import {
|
|
|
12
12
|
ensureClaudeCredentials,
|
|
13
13
|
removeConveyorCredentials,
|
|
14
14
|
sessionTranscriptPath
|
|
15
|
-
} from "./chunk-
|
|
15
|
+
} from "./chunk-TN2YYT2V.js";
|
|
16
16
|
|
|
17
17
|
// src/setup/bootstrap.ts
|
|
18
18
|
var BOOTSTRAP_TIMEOUT_MS = 3e4;
|
|
@@ -7402,7 +7402,7 @@ var ExplorationTracker = class {
|
|
|
7402
7402
|
// src/runner/query-bridge.ts
|
|
7403
7403
|
var logger3 = createServiceLogger("QueryBridge");
|
|
7404
7404
|
function resolveHarnessKind() {
|
|
7405
|
-
return process.env.
|
|
7405
|
+
return process.env.CONVEYOR_FORCE_SDK_CARDS === "1" ? "sdk" : "pty";
|
|
7406
7406
|
}
|
|
7407
7407
|
function buildPtyBridge(connection) {
|
|
7408
7408
|
return {
|
|
@@ -7431,7 +7431,8 @@ var QueryBridge = class {
|
|
|
7431
7431
|
runnerConfig;
|
|
7432
7432
|
callbacks;
|
|
7433
7433
|
harness;
|
|
7434
|
-
/** Which harness drives this bridge ("pty" task chat
|
|
7434
|
+
/** Which harness drives this bridge ("pty" task chat; "sdk" only under the
|
|
7435
|
+
* CONVEYOR_FORCE_SDK_CARDS maintainer override). */
|
|
7435
7436
|
harnessKind;
|
|
7436
7437
|
costTracker;
|
|
7437
7438
|
planSync;
|
|
@@ -7687,6 +7688,9 @@ function handlePullBranch(workDir, branch) {
|
|
|
7687
7688
|
}
|
|
7688
7689
|
|
|
7689
7690
|
// src/runner/session-runner.ts
|
|
7691
|
+
function isPostToChatTool(name) {
|
|
7692
|
+
return typeof name === "string" && (name === "post_to_chat" || name.endsWith("__post_to_chat"));
|
|
7693
|
+
}
|
|
7690
7694
|
var SessionRunner = class _SessionRunner {
|
|
7691
7695
|
connection;
|
|
7692
7696
|
mode;
|
|
@@ -7712,6 +7716,12 @@ var SessionRunner = class _SessionRunner {
|
|
|
7712
7716
|
inputResolver = null;
|
|
7713
7717
|
pendingMessages = [];
|
|
7714
7718
|
prNudgeCount = 0;
|
|
7719
|
+
/** Set when the agent posts a substantive message to the task chat (the
|
|
7720
|
+
* `post_to_chat` tool) during the current turn; reset at the start of every
|
|
7721
|
+
* query. Read by the stuck-detection: an auto agent that finished without a
|
|
7722
|
+
* PR but DID explain itself / ask for help in chat is waiting on a human,
|
|
7723
|
+
* not silently stuck, so it is left attached rather than nudged. */
|
|
7724
|
+
agentSpokeThisTurn = false;
|
|
7715
7725
|
/** Guards overlapping runs of the periodic git flush. */
|
|
7716
7726
|
periodicFlushInFlight = false;
|
|
7717
7727
|
constructor(config, callbacks) {
|
|
@@ -7852,7 +7862,7 @@ var SessionRunner = class _SessionRunner {
|
|
|
7852
7862
|
this.queryBridge.isDiscoveryCompleted = false;
|
|
7853
7863
|
}
|
|
7854
7864
|
if (!this.stopped && this.pendingMessages.length === 0) {
|
|
7855
|
-
await this.
|
|
7865
|
+
await this.maybeHandleStuckAuto();
|
|
7856
7866
|
}
|
|
7857
7867
|
if (!this.stopped) {
|
|
7858
7868
|
process.stderr.write(
|
|
@@ -7925,7 +7935,7 @@ var SessionRunner = class _SessionRunner {
|
|
|
7925
7935
|
continue;
|
|
7926
7936
|
}
|
|
7927
7937
|
if (!this.stopped && this.pendingMessages.length === 0) {
|
|
7928
|
-
await this.
|
|
7938
|
+
await this.maybeHandleStuckAuto();
|
|
7929
7939
|
}
|
|
7930
7940
|
if (!this.stopped) await this.setState("idle");
|
|
7931
7941
|
} else if (this._state === "error") {
|
|
@@ -8116,6 +8126,7 @@ var SessionRunner = class _SessionRunner {
|
|
|
8116
8126
|
/** Run queryBridge.execute, swallowing abort errors from stop/softStop. */
|
|
8117
8127
|
async executeQuery(followUpContent, promptDelivery) {
|
|
8118
8128
|
if (!this.fullContext || !this.queryBridge) return;
|
|
8129
|
+
this.agentSpokeThisTurn = false;
|
|
8119
8130
|
try {
|
|
8120
8131
|
await this.queryBridge.execute(this.fullContext, followUpContent, promptDelivery);
|
|
8121
8132
|
} catch (err) {
|
|
@@ -8209,15 +8220,38 @@ var SessionRunner = class _SessionRunner {
|
|
|
8209
8220
|
resolver(null);
|
|
8210
8221
|
}
|
|
8211
8222
|
}
|
|
8212
|
-
// ── Auto-mode
|
|
8213
|
-
static
|
|
8214
|
-
|
|
8223
|
+
// ── Auto-mode stuck detection & nudge ───────────────────────────────
|
|
8224
|
+
static MAX_STUCK_NUDGES = 3;
|
|
8225
|
+
/** The prompt delivered into the live TUI when an auto agent looks stuck. It
|
|
8226
|
+
* must offer BOTH escape routes so the agent never just goes idle. */
|
|
8227
|
+
static STUCK_PROMPT = "You are in Auto mode, your task is still In Progress, and there is no open pull request. Do ONE of these right now: (1) open a pull request with the create_pull_request tool, OR (2) call post_to_chat to explain exactly where you are stuck and what you need from a human. Do not finish or go idle silently.";
|
|
8228
|
+
/**
|
|
8229
|
+
* An auto task is "stuck" when its last turn ended (the call sites run
|
|
8230
|
+
* post-turn, so the TUI is no longer actively working), it has no open PR,
|
|
8231
|
+
* AND the agent did not communicate in chat this turn. If the agent posted a
|
|
8232
|
+
* message (explained itself / asked for help) it is waiting on a human, not
|
|
8233
|
+
* silently stuck, so we leave it attached instead of nudging.
|
|
8234
|
+
*/
|
|
8235
|
+
isAutoStuck() {
|
|
8215
8236
|
if (!this.mode.isAuto || this.stopped) return false;
|
|
8216
8237
|
if (this.queryBridge?.wasRateLimited) return false;
|
|
8217
|
-
if (this.prNudgeCount > _SessionRunner.
|
|
8238
|
+
if (this.prNudgeCount > _SessionRunner.MAX_STUCK_NUDGES) return false;
|
|
8239
|
+
if (this.agentSpokeThisTurn) return false;
|
|
8218
8240
|
if (!this.taskContext) return false;
|
|
8219
8241
|
return this.taskContext.status === "InProgress" && !this.taskContext.githubPRUrl;
|
|
8220
8242
|
}
|
|
8243
|
+
/**
|
|
8244
|
+
* Stop driving the agent and route the core loop into dormant idle —
|
|
8245
|
+
* connected and attachable, but NOT running (so no tokens are spent while it
|
|
8246
|
+
* waits). A human reply (chat or TUI keystroke after the next wake) resumes
|
|
8247
|
+
* it. This replaces the old hard `stop()`: the auto agent must never kill its
|
|
8248
|
+
* own session, so a person can always take over.
|
|
8249
|
+
*/
|
|
8250
|
+
enterDormantForHumanTakeover(message) {
|
|
8251
|
+
this.connection.postChatMessage(message);
|
|
8252
|
+
this.completedThisTurn = true;
|
|
8253
|
+
void this.connection.sendHeartbeat();
|
|
8254
|
+
}
|
|
8221
8255
|
async refreshTaskContext() {
|
|
8222
8256
|
try {
|
|
8223
8257
|
const ctx = await this.connection.call("getTaskContext", {
|
|
@@ -8240,28 +8274,32 @@ var SessionRunner = class _SessionRunner {
|
|
|
8240
8274
|
} catch {
|
|
8241
8275
|
}
|
|
8242
8276
|
}
|
|
8243
|
-
async
|
|
8277
|
+
async maybeHandleStuckAuto() {
|
|
8244
8278
|
await this.refreshTaskContext();
|
|
8245
|
-
if (!this.
|
|
8246
|
-
while (!this.stopped && !this.interrupted && this.
|
|
8279
|
+
if (!this.isAutoStuck()) return;
|
|
8280
|
+
while (!this.stopped && !this.interrupted && this.isAutoStuck()) {
|
|
8247
8281
|
this.prNudgeCount++;
|
|
8248
|
-
if (this.prNudgeCount > _SessionRunner.
|
|
8249
|
-
this.
|
|
8250
|
-
`Auto-mode
|
|
8282
|
+
if (this.prNudgeCount > _SessionRunner.MAX_STUCK_NUDGES) {
|
|
8283
|
+
this.enterDormantForHumanTakeover(
|
|
8284
|
+
`Auto-mode: I couldn't open a PR or get unstuck after ${_SessionRunner.MAX_STUCK_NUDGES} attempts. Staying connected \u2014 reply here or in the terminal and I'll keep working.`
|
|
8251
8285
|
);
|
|
8252
|
-
this.stop();
|
|
8253
8286
|
return;
|
|
8254
8287
|
}
|
|
8255
|
-
const
|
|
8256
|
-
const chatMsg =
|
|
8257
|
-
const prompt = isFirst ? "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." : `This is reminder ${this.prNudgeCount} of ${_SessionRunner.MAX_PR_NUDGES}. You MUST open a pull request using create_pull_request NOW or explain what is blocking you. Do NOT go idle \u2014 either create the PR or describe the specific blocker.`;
|
|
8288
|
+
const attempt = this.prNudgeCount;
|
|
8289
|
+
const chatMsg = attempt === 1 ? "Auto-nudge: still In Progress with no PR \u2014 prompting the agent to finish or explain where it's stuck..." : `Auto-nudge (attempt ${attempt}/${_SessionRunner.MAX_STUCK_NUDGES}): still no PR \u2014 prompting the agent again...`;
|
|
8258
8290
|
this.connection.postChatMessage(chatMsg);
|
|
8259
8291
|
await this.setState("running");
|
|
8260
|
-
await this.callbacks.onEvent({ type: "pr_nudge", prompt });
|
|
8292
|
+
await this.callbacks.onEvent({ type: "pr_nudge", prompt: _SessionRunner.STUCK_PROMPT });
|
|
8261
8293
|
if (this.interrupted || this.stopped) return;
|
|
8262
|
-
await this.executeQuery(
|
|
8294
|
+
await this.executeQuery(_SessionRunner.STUCK_PROMPT);
|
|
8263
8295
|
if (this.interrupted || this.stopped) return;
|
|
8264
8296
|
await this.refreshTaskContext();
|
|
8297
|
+
if (this.agentSpokeThisTurn && !this.taskContext?.githubPRUrl) {
|
|
8298
|
+
this.enterDormantForHumanTakeover(
|
|
8299
|
+
"Auto-mode: the agent posted an update and is waiting for input. Staying connected \u2014 reply here or in the terminal to continue."
|
|
8300
|
+
);
|
|
8301
|
+
return;
|
|
8302
|
+
}
|
|
8265
8303
|
}
|
|
8266
8304
|
}
|
|
8267
8305
|
// ── Context & bridge construction ────────────────────────────────
|
|
@@ -8324,6 +8362,10 @@ var SessionRunner = class _SessionRunner {
|
|
|
8324
8362
|
return this.callbacks.onStatusChange(status);
|
|
8325
8363
|
},
|
|
8326
8364
|
onEvent: (event) => {
|
|
8365
|
+
const evt = event;
|
|
8366
|
+
if (evt.type === "tool_use" && isPostToChatTool(evt.tool)) {
|
|
8367
|
+
this.agentSpokeThisTurn = true;
|
|
8368
|
+
}
|
|
8327
8369
|
if (event.type === "completed") {
|
|
8328
8370
|
this.completedThisTurn = true;
|
|
8329
8371
|
void this.connection.sendHeartbeat();
|
|
@@ -10582,7 +10624,7 @@ var ProjectRunner = class {
|
|
|
10582
10624
|
async handleAuditTags(request) {
|
|
10583
10625
|
this.connection.emitStatus("busy");
|
|
10584
10626
|
try {
|
|
10585
|
-
const { handleTagAudit } = await import("./tag-audit-handler-
|
|
10627
|
+
const { handleTagAudit } = await import("./tag-audit-handler-X3LEX63H.js");
|
|
10586
10628
|
await handleTagAudit(request, this.connection, this.projectDir);
|
|
10587
10629
|
} catch (error) {
|
|
10588
10630
|
const msg = parseErrorMessage(error);
|
|
@@ -10605,7 +10647,7 @@ var ProjectRunner = class {
|
|
|
10605
10647
|
async handleAuditTasks(request) {
|
|
10606
10648
|
this.connection.emitStatus("busy");
|
|
10607
10649
|
try {
|
|
10608
|
-
const { handleTaskAudit } = await import("./task-audit-handler-
|
|
10650
|
+
const { handleTaskAudit } = await import("./task-audit-handler-BRCXB5V6.js");
|
|
10609
10651
|
await handleTaskAudit(request, this.connection, this.projectDir);
|
|
10610
10652
|
} catch (error) {
|
|
10611
10653
|
const msg = parseErrorMessage(error);
|
|
@@ -10746,4 +10788,4 @@ export {
|
|
|
10746
10788
|
loadConveyorConfig,
|
|
10747
10789
|
unshallowRepo
|
|
10748
10790
|
};
|
|
10749
|
-
//# sourceMappingURL=chunk-
|
|
10791
|
+
//# sourceMappingURL=chunk-6462GDLZ.js.map
|