@rallycry/conveyor-agent 8.8.0 → 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-KEBJAORX.js → chunk-6462GDLZ.js} +73 -30
- package/dist/chunk-6462GDLZ.js.map +1 -0
- package/dist/{chunk-6B545CHM.js → chunk-TN2YYT2V.js} +12 -1
- package/dist/{chunk-6B545CHM.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-3IFB7YDV.js → tag-audit-handler-X3LEX63H.js} +2 -2
- package/dist/{task-audit-handler-U5Q52YT2.js → task-audit-handler-BRCXB5V6.js} +2 -2
- package/package.json +1 -1
- package/dist/chunk-KEBJAORX.js.map +0 -1
- /package/dist/{tag-audit-handler-3IFB7YDV.js.map → tag-audit-handler-X3LEX63H.js.map} +0 -0
- /package/dist/{task-audit-handler-U5Q52YT2.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;
|
|
@@ -1424,14 +1424,11 @@ var PlanSync = class {
|
|
|
1424
1424
|
}
|
|
1425
1425
|
};
|
|
1426
1426
|
|
|
1427
|
-
// src/execution/query-executor.ts
|
|
1428
|
-
import { createHash } from "crypto";
|
|
1429
|
-
import { existsSync, readFileSync as readFileSync2, truncateSync } from "fs";
|
|
1430
|
-
|
|
1431
1427
|
// ../shared/dist/index.js
|
|
1432
1428
|
import { z } from "zod";
|
|
1433
1429
|
import { z as z2 } from "zod";
|
|
1434
1430
|
import { z as z3 } from "zod";
|
|
1431
|
+
var DEFAULT_SONNET_MODEL = "claude-sonnet-4-6";
|
|
1435
1432
|
var MAX_FILE_SIZE_BYTES = 25 * 1024 * 1024;
|
|
1436
1433
|
var EMBED_THRESHOLD_IMAGES = 5 * 1024 * 1024;
|
|
1437
1434
|
var EMBED_THRESHOLD_TEXT = 2 * 1024 * 1024;
|
|
@@ -2220,6 +2217,10 @@ var TASK_CHAT_HISTORY_LIMIT = 20;
|
|
|
2220
2217
|
var PM_CHAT_HISTORY_LIMIT = 40;
|
|
2221
2218
|
var AGENT_CHAT_HISTORY_FETCH_LIMIT = Math.max(TASK_CHAT_HISTORY_LIMIT, PM_CHAT_HISTORY_LIMIT) + 10;
|
|
2222
2219
|
|
|
2220
|
+
// src/execution/query-executor.ts
|
|
2221
|
+
import { createHash } from "crypto";
|
|
2222
|
+
import { existsSync, readFileSync as readFileSync2, truncateSync } from "fs";
|
|
2223
|
+
|
|
2223
2224
|
// src/execution/pack-runner-prompt.ts
|
|
2224
2225
|
function findLastAgentMessageIndex(history) {
|
|
2225
2226
|
for (let i = history.length - 1; i >= 0; i--) {
|
|
@@ -7401,7 +7402,7 @@ var ExplorationTracker = class {
|
|
|
7401
7402
|
// src/runner/query-bridge.ts
|
|
7402
7403
|
var logger3 = createServiceLogger("QueryBridge");
|
|
7403
7404
|
function resolveHarnessKind() {
|
|
7404
|
-
return process.env.
|
|
7405
|
+
return process.env.CONVEYOR_FORCE_SDK_CARDS === "1" ? "sdk" : "pty";
|
|
7405
7406
|
}
|
|
7406
7407
|
function buildPtyBridge(connection) {
|
|
7407
7408
|
return {
|
|
@@ -7430,7 +7431,8 @@ var QueryBridge = class {
|
|
|
7430
7431
|
runnerConfig;
|
|
7431
7432
|
callbacks;
|
|
7432
7433
|
harness;
|
|
7433
|
-
/** 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). */
|
|
7434
7436
|
harnessKind;
|
|
7435
7437
|
costTracker;
|
|
7436
7438
|
planSync;
|
|
@@ -7686,6 +7688,9 @@ function handlePullBranch(workDir, branch) {
|
|
|
7686
7688
|
}
|
|
7687
7689
|
|
|
7688
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
|
+
}
|
|
7689
7694
|
var SessionRunner = class _SessionRunner {
|
|
7690
7695
|
connection;
|
|
7691
7696
|
mode;
|
|
@@ -7711,6 +7716,12 @@ var SessionRunner = class _SessionRunner {
|
|
|
7711
7716
|
inputResolver = null;
|
|
7712
7717
|
pendingMessages = [];
|
|
7713
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;
|
|
7714
7725
|
/** Guards overlapping runs of the periodic git flush. */
|
|
7715
7726
|
periodicFlushInFlight = false;
|
|
7716
7727
|
constructor(config, callbacks) {
|
|
@@ -7851,7 +7862,7 @@ var SessionRunner = class _SessionRunner {
|
|
|
7851
7862
|
this.queryBridge.isDiscoveryCompleted = false;
|
|
7852
7863
|
}
|
|
7853
7864
|
if (!this.stopped && this.pendingMessages.length === 0) {
|
|
7854
|
-
await this.
|
|
7865
|
+
await this.maybeHandleStuckAuto();
|
|
7855
7866
|
}
|
|
7856
7867
|
if (!this.stopped) {
|
|
7857
7868
|
process.stderr.write(
|
|
@@ -7924,7 +7935,7 @@ var SessionRunner = class _SessionRunner {
|
|
|
7924
7935
|
continue;
|
|
7925
7936
|
}
|
|
7926
7937
|
if (!this.stopped && this.pendingMessages.length === 0) {
|
|
7927
|
-
await this.
|
|
7938
|
+
await this.maybeHandleStuckAuto();
|
|
7928
7939
|
}
|
|
7929
7940
|
if (!this.stopped) await this.setState("idle");
|
|
7930
7941
|
} else if (this._state === "error") {
|
|
@@ -8115,6 +8126,7 @@ var SessionRunner = class _SessionRunner {
|
|
|
8115
8126
|
/** Run queryBridge.execute, swallowing abort errors from stop/softStop. */
|
|
8116
8127
|
async executeQuery(followUpContent, promptDelivery) {
|
|
8117
8128
|
if (!this.fullContext || !this.queryBridge) return;
|
|
8129
|
+
this.agentSpokeThisTurn = false;
|
|
8118
8130
|
try {
|
|
8119
8131
|
await this.queryBridge.execute(this.fullContext, followUpContent, promptDelivery);
|
|
8120
8132
|
} catch (err) {
|
|
@@ -8208,15 +8220,38 @@ var SessionRunner = class _SessionRunner {
|
|
|
8208
8220
|
resolver(null);
|
|
8209
8221
|
}
|
|
8210
8222
|
}
|
|
8211
|
-
// ── Auto-mode
|
|
8212
|
-
static
|
|
8213
|
-
|
|
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() {
|
|
8214
8236
|
if (!this.mode.isAuto || this.stopped) return false;
|
|
8215
8237
|
if (this.queryBridge?.wasRateLimited) return false;
|
|
8216
|
-
if (this.prNudgeCount > _SessionRunner.
|
|
8238
|
+
if (this.prNudgeCount > _SessionRunner.MAX_STUCK_NUDGES) return false;
|
|
8239
|
+
if (this.agentSpokeThisTurn) return false;
|
|
8217
8240
|
if (!this.taskContext) return false;
|
|
8218
8241
|
return this.taskContext.status === "InProgress" && !this.taskContext.githubPRUrl;
|
|
8219
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
|
+
}
|
|
8220
8255
|
async refreshTaskContext() {
|
|
8221
8256
|
try {
|
|
8222
8257
|
const ctx = await this.connection.call("getTaskContext", {
|
|
@@ -8239,28 +8274,32 @@ var SessionRunner = class _SessionRunner {
|
|
|
8239
8274
|
} catch {
|
|
8240
8275
|
}
|
|
8241
8276
|
}
|
|
8242
|
-
async
|
|
8277
|
+
async maybeHandleStuckAuto() {
|
|
8243
8278
|
await this.refreshTaskContext();
|
|
8244
|
-
if (!this.
|
|
8245
|
-
while (!this.stopped && !this.interrupted && this.
|
|
8279
|
+
if (!this.isAutoStuck()) return;
|
|
8280
|
+
while (!this.stopped && !this.interrupted && this.isAutoStuck()) {
|
|
8246
8281
|
this.prNudgeCount++;
|
|
8247
|
-
if (this.prNudgeCount > _SessionRunner.
|
|
8248
|
-
this.
|
|
8249
|
-
`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.`
|
|
8250
8285
|
);
|
|
8251
|
-
this.stop();
|
|
8252
8286
|
return;
|
|
8253
8287
|
}
|
|
8254
|
-
const
|
|
8255
|
-
const chatMsg =
|
|
8256
|
-
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...`;
|
|
8257
8290
|
this.connection.postChatMessage(chatMsg);
|
|
8258
8291
|
await this.setState("running");
|
|
8259
|
-
await this.callbacks.onEvent({ type: "pr_nudge", prompt });
|
|
8292
|
+
await this.callbacks.onEvent({ type: "pr_nudge", prompt: _SessionRunner.STUCK_PROMPT });
|
|
8260
8293
|
if (this.interrupted || this.stopped) return;
|
|
8261
|
-
await this.executeQuery(
|
|
8294
|
+
await this.executeQuery(_SessionRunner.STUCK_PROMPT);
|
|
8262
8295
|
if (this.interrupted || this.stopped) return;
|
|
8263
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
|
+
}
|
|
8264
8303
|
}
|
|
8265
8304
|
}
|
|
8266
8305
|
// ── Context & bridge construction ────────────────────────────────
|
|
@@ -8304,7 +8343,7 @@ var SessionRunner = class _SessionRunner {
|
|
|
8304
8343
|
conveyorApiUrl: this.config.connection.apiUrl,
|
|
8305
8344
|
taskToken: this.config.connection.taskToken,
|
|
8306
8345
|
taskId: this.fullContext?.taskId ?? "",
|
|
8307
|
-
model: this.fullContext?.model ??
|
|
8346
|
+
model: this.fullContext?.model ?? DEFAULT_SONNET_MODEL,
|
|
8308
8347
|
instructions: this.fullContext?.agentInstructions ?? "",
|
|
8309
8348
|
workspaceDir: this.config.workspaceDir,
|
|
8310
8349
|
mode: this.config.runnerMode,
|
|
@@ -8323,6 +8362,10 @@ var SessionRunner = class _SessionRunner {
|
|
|
8323
8362
|
return this.callbacks.onStatusChange(status);
|
|
8324
8363
|
},
|
|
8325
8364
|
onEvent: (event) => {
|
|
8365
|
+
const evt = event;
|
|
8366
|
+
if (evt.type === "tool_use" && isPostToChatTool(evt.tool)) {
|
|
8367
|
+
this.agentSpokeThisTurn = true;
|
|
8368
|
+
}
|
|
8326
8369
|
if (event.type === "completed") {
|
|
8327
8370
|
this.completedThisTurn = true;
|
|
8328
8371
|
void this.connection.sendHeartbeat();
|
|
@@ -9661,7 +9704,7 @@ function buildProjectTools(connection, getRequestingUserId = () => void 0) {
|
|
|
9661
9704
|
|
|
9662
9705
|
// src/runner/project-chat-handler.ts
|
|
9663
9706
|
var logger6 = createServiceLogger("ProjectChat");
|
|
9664
|
-
var FALLBACK_MODEL =
|
|
9707
|
+
var FALLBACK_MODEL = DEFAULT_SONNET_MODEL;
|
|
9665
9708
|
function buildSystemPrompt2(projectDir, agentCtx) {
|
|
9666
9709
|
const parts = [];
|
|
9667
9710
|
if (agentCtx?.agentInstructions) {
|
|
@@ -10581,7 +10624,7 @@ var ProjectRunner = class {
|
|
|
10581
10624
|
async handleAuditTags(request) {
|
|
10582
10625
|
this.connection.emitStatus("busy");
|
|
10583
10626
|
try {
|
|
10584
|
-
const { handleTagAudit } = await import("./tag-audit-handler-
|
|
10627
|
+
const { handleTagAudit } = await import("./tag-audit-handler-X3LEX63H.js");
|
|
10585
10628
|
await handleTagAudit(request, this.connection, this.projectDir);
|
|
10586
10629
|
} catch (error) {
|
|
10587
10630
|
const msg = parseErrorMessage(error);
|
|
@@ -10604,7 +10647,7 @@ var ProjectRunner = class {
|
|
|
10604
10647
|
async handleAuditTasks(request) {
|
|
10605
10648
|
this.connection.emitStatus("busy");
|
|
10606
10649
|
try {
|
|
10607
|
-
const { handleTaskAudit } = await import("./task-audit-handler-
|
|
10650
|
+
const { handleTaskAudit } = await import("./task-audit-handler-BRCXB5V6.js");
|
|
10608
10651
|
await handleTaskAudit(request, this.connection, this.projectDir);
|
|
10609
10652
|
} catch (error) {
|
|
10610
10653
|
const msg = parseErrorMessage(error);
|
|
@@ -10745,4 +10788,4 @@ export {
|
|
|
10745
10788
|
loadConveyorConfig,
|
|
10746
10789
|
unshallowRepo
|
|
10747
10790
|
};
|
|
10748
|
-
//# sourceMappingURL=chunk-
|
|
10791
|
+
//# sourceMappingURL=chunk-6462GDLZ.js.map
|