@rallycry/conveyor-agent 8.4.1 → 8.5.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-B4QHEMMV.js → chunk-3T4SJEH6.js} +181 -24
- package/dist/chunk-3T4SJEH6.js.map +1 -0
- package/dist/{chunk-VDH55LTT.js → chunk-63FTZOL5.js} +227 -32
- package/dist/chunk-63FTZOL5.js.map +1 -0
- package/dist/cli.js +2 -2
- package/dist/index.d.ts +37 -0
- package/dist/index.js +2 -2
- package/dist/{tag-audit-handler-SWVMCAJH.js → tag-audit-handler-PKYLDJHH.js} +2 -2
- package/dist/{task-audit-handler-CZ2WWJFO.js → task-audit-handler-WINYLZMU.js} +2 -2
- package/package.json +1 -1
- package/dist/chunk-B4QHEMMV.js.map +0 -1
- package/dist/chunk-VDH55LTT.js.map +0 -1
- /package/dist/{tag-audit-handler-SWVMCAJH.js.map → tag-audit-handler-PKYLDJHH.js.map} +0 -0
- /package/dist/{task-audit-handler-CZ2WWJFO.js.map → task-audit-handler-WINYLZMU.js.map} +0 -0
|
@@ -5,13 +5,14 @@ import {
|
|
|
5
5
|
textResult
|
|
6
6
|
} from "./chunk-FDWECEDJ.js";
|
|
7
7
|
import {
|
|
8
|
+
configHomePlansDir,
|
|
8
9
|
createHarness,
|
|
9
10
|
createServiceLogger,
|
|
10
11
|
defineTool,
|
|
11
12
|
ensureClaudeCredentials,
|
|
12
13
|
removeConveyorCredentials,
|
|
13
14
|
sessionTranscriptPath
|
|
14
|
-
} from "./chunk-
|
|
15
|
+
} from "./chunk-63FTZOL5.js";
|
|
15
16
|
|
|
16
17
|
// src/setup/bootstrap.ts
|
|
17
18
|
var BOOTSTRAP_TIMEOUT_MS = 3e4;
|
|
@@ -227,7 +228,8 @@ var AgentConnection = class _AgentConnection {
|
|
|
227
228
|
content: msg.content,
|
|
228
229
|
userId: msg.userId,
|
|
229
230
|
...msg.source && { source: msg.source },
|
|
230
|
-
...msg.files && { files: msg.files }
|
|
231
|
+
...msg.files && { files: msg.files },
|
|
232
|
+
...msg.delivery === "prefill" && { delivery: msg.delivery }
|
|
231
233
|
};
|
|
232
234
|
if (this.messageCallback) this.messageCallback(incoming);
|
|
233
235
|
else this.earlyMessages.push(incoming);
|
|
@@ -1316,7 +1318,7 @@ var PlanSync = class {
|
|
|
1316
1318
|
this.workspaceDir = workspaceDir;
|
|
1317
1319
|
}
|
|
1318
1320
|
getPlanDirs() {
|
|
1319
|
-
return [join(this.workspaceDir, ".claude", "plans")];
|
|
1321
|
+
return [join(this.workspaceDir, ".claude", "plans"), configHomePlansDir()];
|
|
1320
1322
|
}
|
|
1321
1323
|
snapshotPlanFiles() {
|
|
1322
1324
|
this.planFileSnapshot.clear();
|
|
@@ -6259,7 +6261,11 @@ async function handleExitPlanMode(host, input) {
|
|
|
6259
6261
|
await host.connection.postChatMessageAwait(
|
|
6260
6262
|
"Planning complete \u2014 awaiting team approval. Icon and agent assignment will be set automatically."
|
|
6261
6263
|
);
|
|
6262
|
-
host.
|
|
6264
|
+
if (host.harnessKind === "pty") {
|
|
6265
|
+
setTimeout(() => host.requestStop(), 250);
|
|
6266
|
+
} else {
|
|
6267
|
+
host.requestStop();
|
|
6268
|
+
}
|
|
6263
6269
|
return { behavior: "allow", updatedInput: input };
|
|
6264
6270
|
}
|
|
6265
6271
|
try {
|
|
@@ -6533,9 +6539,10 @@ function repairTornSessionFile(path2) {
|
|
|
6533
6539
|
}
|
|
6534
6540
|
function resolvePromptDelivery(inputs) {
|
|
6535
6541
|
if (inputs.harnessKind !== "pty") return "submit";
|
|
6536
|
-
if (
|
|
6542
|
+
if (inputs.runnerMode === "code-review") return "submit";
|
|
6537
6543
|
if (inputs.isFollowUp || inputs.hasExistingSession) return "submit";
|
|
6538
6544
|
if (inputs.isAuto || inputs.agentMode === "auto") return "submit";
|
|
6545
|
+
if (inputs.agentMode !== "discovery" && inputs.agentMode !== "help") return "submit";
|
|
6539
6546
|
return "prefill";
|
|
6540
6547
|
}
|
|
6541
6548
|
function isReadOnlyMode(mode, hasExitedPlanMode) {
|
|
@@ -6572,6 +6579,14 @@ function buildQueryOptions(host, context) {
|
|
|
6572
6579
|
permissionMode: needsCanUseTool ? "plan" : "bypassPermissions",
|
|
6573
6580
|
allowDangerouslySkipPermissions: !needsCanUseTool,
|
|
6574
6581
|
canUseTool: buildCanUseTool(host),
|
|
6582
|
+
// The spawned CLI never sees `systemPrompt` (an SDK-only option) — deliver
|
|
6583
|
+
// the same text via `--append-system-prompt`. PTY-only: the SDK harness
|
|
6584
|
+
// already receives it through systemPrompt.append.
|
|
6585
|
+
...host.harnessKind === "pty" && systemPromptText ? { appendSystemPrompt: systemPromptText } : {},
|
|
6586
|
+
// Auto mode pre-exit: after the ExitPlanMode hook allows the call, the
|
|
6587
|
+
// CLI's plan dialog still renders — press Enter so the autonomous agent
|
|
6588
|
+
// continues building in the same session (Conveyor validated in the hook).
|
|
6589
|
+
planDialogAutoAccept: mode === "auto" && !host.hasExitedPlanMode,
|
|
6575
6590
|
tools: { type: "preset", preset: "claude_code" },
|
|
6576
6591
|
mcpServers: {
|
|
6577
6592
|
conveyor: createConveyorMcpServer(host.harness, host.connection, host.config, context, mode)
|
|
@@ -6712,13 +6727,7 @@ async function runSdkQuery(host, context, followUpContent, promptDeliveryOverrid
|
|
|
6712
6727
|
};
|
|
6713
6728
|
const resume = hasExistingSession ? sessionUuid : void 0;
|
|
6714
6729
|
if (followUpContent) {
|
|
6715
|
-
|
|
6716
|
-
const agentQuery = host.harness.executeQuery({
|
|
6717
|
-
prompt: typeof prompt === "string" ? prompt : host.createInputStream(prompt),
|
|
6718
|
-
options: { ...options },
|
|
6719
|
-
resume
|
|
6720
|
-
});
|
|
6721
|
-
await trackAndRun(host, context, options, agentQuery);
|
|
6730
|
+
await runFollowUpQuery(host, context, options, resume, followUpContent);
|
|
6722
6731
|
} else if (isDiscoveryLike && promptDelivery !== "prefill") {
|
|
6723
6732
|
return;
|
|
6724
6733
|
} else {
|
|
@@ -6728,6 +6737,42 @@ async function runSdkQuery(host, context, followUpContent, promptDeliveryOverrid
|
|
|
6728
6737
|
await host.syncPlanFile();
|
|
6729
6738
|
}
|
|
6730
6739
|
}
|
|
6740
|
+
async function runFollowUpQuery(host, context, options, resume, followUpContent) {
|
|
6741
|
+
if (options.promptDelivery === "prefill") {
|
|
6742
|
+
await runPrefilledFollowUp(host, context, options, resume, followUpContent);
|
|
6743
|
+
return;
|
|
6744
|
+
}
|
|
6745
|
+
const prompt = await buildFollowUpPrompt(host, context, followUpContent);
|
|
6746
|
+
const agentQuery = host.harness.executeQuery({
|
|
6747
|
+
prompt: typeof prompt === "string" ? prompt : host.createInputStream(prompt),
|
|
6748
|
+
options: { ...options },
|
|
6749
|
+
resume
|
|
6750
|
+
});
|
|
6751
|
+
await trackAndRun(host, context, options, agentQuery);
|
|
6752
|
+
}
|
|
6753
|
+
async function runPrefilledFollowUp(host, context, options, resume, followUpContent) {
|
|
6754
|
+
const followUpText = typeof followUpContent === "string" ? followUpContent : followUpContent.filter((b) => b.type === "text").map((b) => b.text).join("\n");
|
|
6755
|
+
const queryOptions = { ...options };
|
|
6756
|
+
if (host.config.mode === "pm" && !resume) {
|
|
6757
|
+
const initialPrompt = await buildInitialPrompt(
|
|
6758
|
+
host.config.mode,
|
|
6759
|
+
context,
|
|
6760
|
+
host.isAuto,
|
|
6761
|
+
host.agentMode
|
|
6762
|
+
);
|
|
6763
|
+
queryOptions.appendSystemPrompt = [queryOptions.appendSystemPrompt, initialPrompt].filter(Boolean).join("\n\n").slice(0, APPEND_SYSTEM_PROMPT_MAX_CHARS);
|
|
6764
|
+
}
|
|
6765
|
+
let agentQuery = host.harness.executeQuery({
|
|
6766
|
+
prompt: followUpText,
|
|
6767
|
+
options: queryOptions,
|
|
6768
|
+
resume
|
|
6769
|
+
});
|
|
6770
|
+
agentQuery = notifyOnFirstEvent(agentQuery, async () => {
|
|
6771
|
+
host.connection.emitStatus("running");
|
|
6772
|
+
await host.callbacks.onStatusChange("running");
|
|
6773
|
+
});
|
|
6774
|
+
await trackAndRun(host, context, queryOptions, agentQuery);
|
|
6775
|
+
}
|
|
6731
6776
|
async function trackAndRun(host, context, options, agentQuery) {
|
|
6732
6777
|
if (host.harnessKind === "pty" && options.promptDelivery !== "prefill") {
|
|
6733
6778
|
agentQuery = watchForParkedTui(agentQuery, host);
|
|
@@ -6739,6 +6784,14 @@ async function trackAndRun(host, context, options, agentQuery) {
|
|
|
6739
6784
|
host.activeQuery = null;
|
|
6740
6785
|
}
|
|
6741
6786
|
}
|
|
6787
|
+
var APPEND_SYSTEM_PROMPT_MAX_CHARS = 96e3;
|
|
6788
|
+
function latestUserMessageText(context) {
|
|
6789
|
+
for (let i = context.chatHistory.length - 1; i >= 0; i--) {
|
|
6790
|
+
const msg = context.chatHistory[i];
|
|
6791
|
+
if (msg.role === "user" && msg.content.trim()) return msg.content.trim();
|
|
6792
|
+
}
|
|
6793
|
+
return null;
|
|
6794
|
+
}
|
|
6742
6795
|
async function runInitialQuery(host, context, options, resume, promptDelivery) {
|
|
6743
6796
|
const initialPrompt = await buildInitialPrompt(
|
|
6744
6797
|
host.config.mode,
|
|
@@ -6746,10 +6799,18 @@ async function runInitialQuery(host, context, options, resume, promptDelivery) {
|
|
|
6746
6799
|
host.isAuto,
|
|
6747
6800
|
host.agentMode
|
|
6748
6801
|
);
|
|
6749
|
-
|
|
6802
|
+
let prompt;
|
|
6803
|
+
const queryOptions = { ...options };
|
|
6804
|
+
const prefillMessage = promptDelivery === "prefill" ? latestUserMessageText(context) : null;
|
|
6805
|
+
if (prefillMessage) {
|
|
6806
|
+
prompt = prefillMessage;
|
|
6807
|
+
queryOptions.appendSystemPrompt = [queryOptions.appendSystemPrompt, initialPrompt].filter(Boolean).join("\n\n").slice(0, APPEND_SYSTEM_PROMPT_MAX_CHARS);
|
|
6808
|
+
} else {
|
|
6809
|
+
prompt = buildMultimodalPrompt(initialPrompt, context);
|
|
6810
|
+
}
|
|
6750
6811
|
let agentQuery = host.harness.executeQuery({
|
|
6751
6812
|
prompt: host.createInputStream(prompt),
|
|
6752
|
-
options:
|
|
6813
|
+
options: queryOptions,
|
|
6753
6814
|
resume
|
|
6754
6815
|
});
|
|
6755
6816
|
if (promptDelivery === "prefill") {
|
|
@@ -6758,7 +6819,7 @@ async function runInitialQuery(host, context, options, resume, promptDelivery) {
|
|
|
6758
6819
|
await host.callbacks.onStatusChange("running");
|
|
6759
6820
|
});
|
|
6760
6821
|
}
|
|
6761
|
-
await trackAndRun(host, context,
|
|
6822
|
+
await trackAndRun(host, context, queryOptions, agentQuery);
|
|
6762
6823
|
}
|
|
6763
6824
|
async function buildRetryQuery(host, context, options, lastErrorWasImage) {
|
|
6764
6825
|
if (lastErrorWasImage) {
|
|
@@ -7111,6 +7172,7 @@ var QueryBridge = class {
|
|
|
7111
7172
|
runnerConfig;
|
|
7112
7173
|
callbacks;
|
|
7113
7174
|
harness;
|
|
7175
|
+
/** Which harness drives this bridge ("pty" task chat vs "sdk" rollback). */
|
|
7114
7176
|
harnessKind;
|
|
7115
7177
|
costTracker;
|
|
7116
7178
|
planSync;
|
|
@@ -7516,10 +7578,13 @@ var SessionRunner = class _SessionRunner {
|
|
|
7516
7578
|
this.queryBridge = this.createQueryBridge();
|
|
7517
7579
|
await this.seedCostTrackerFromServer();
|
|
7518
7580
|
this.logInitialization();
|
|
7519
|
-
const
|
|
7581
|
+
const staleBatch = [...this.pendingMessages];
|
|
7520
7582
|
const didExecuteInitialQuery = await this.executeInitialMode();
|
|
7521
|
-
if (
|
|
7522
|
-
|
|
7583
|
+
if (staleBatch.length > 0 && didExecuteInitialQuery) {
|
|
7584
|
+
for (const stale of staleBatch) {
|
|
7585
|
+
const idx = this.pendingMessages.indexOf(stale);
|
|
7586
|
+
if (idx !== -1) this.pendingMessages.splice(idx, 1);
|
|
7587
|
+
}
|
|
7523
7588
|
}
|
|
7524
7589
|
if (this.queryBridge?.isDiscoveryCompleted) {
|
|
7525
7590
|
process.stderr.write(
|
|
@@ -7567,14 +7632,18 @@ var SessionRunner = class _SessionRunner {
|
|
|
7567
7632
|
}
|
|
7568
7633
|
break;
|
|
7569
7634
|
}
|
|
7570
|
-
await this.setState("running");
|
|
7571
7635
|
this.interrupted = false;
|
|
7572
7636
|
await this.callbacks.onEvent({
|
|
7573
7637
|
type: "user_message",
|
|
7574
7638
|
content: msg.content,
|
|
7575
7639
|
userId: msg.userId
|
|
7576
7640
|
});
|
|
7577
|
-
|
|
7641
|
+
if (this.prefillEligible(msg)) {
|
|
7642
|
+
await this.runPrefilledMessage(msg, this.mode.effectiveMode);
|
|
7643
|
+
} else {
|
|
7644
|
+
await this.setState("running");
|
|
7645
|
+
await this.executeQuery(msg.content);
|
|
7646
|
+
}
|
|
7578
7647
|
if (this.queryBridge?.isDiscoveryCompleted) {
|
|
7579
7648
|
process.stderr.write(
|
|
7580
7649
|
"[conveyor-agent] Discovery completed \u2014 entering dormant idle (staying connected)\n"
|
|
@@ -7647,7 +7716,13 @@ var SessionRunner = class _SessionRunner {
|
|
|
7647
7716
|
async executeInitialMode() {
|
|
7648
7717
|
if (!this.taskContext || !this.fullContext) return false;
|
|
7649
7718
|
const effectiveMode = this.mode.effectiveMode;
|
|
7650
|
-
const
|
|
7719
|
+
const intrinsicDelivery = this.queryBridge?.initialPromptDelivery(this.fullContext) ?? "submit";
|
|
7720
|
+
const hinted = this.prepareInitialPendingMessages(intrinsicDelivery);
|
|
7721
|
+
if (hinted) {
|
|
7722
|
+
await this.runPrefilledMessage(hinted, effectiveMode);
|
|
7723
|
+
return true;
|
|
7724
|
+
}
|
|
7725
|
+
const delivery = this.pendingMessages.length > 0 ? "submit" : intrinsicDelivery;
|
|
7651
7726
|
const shouldRun = effectiveMode === "building" || effectiveMode === "auto" || effectiveMode === "review" || delivery === "prefill";
|
|
7652
7727
|
if (!shouldRun) {
|
|
7653
7728
|
await this.setState("idle");
|
|
@@ -7674,6 +7749,88 @@ var SessionRunner = class _SessionRunner {
|
|
|
7674
7749
|
if (!this.stopped) await this.setState("idle");
|
|
7675
7750
|
return true;
|
|
7676
7751
|
}
|
|
7752
|
+
// ── Prefill-delivery helpers ───────────────────────────────────────
|
|
7753
|
+
/**
|
|
7754
|
+
* Startup-queue preamble: the card's initial message reaches a fresh pod
|
|
7755
|
+
* twice — inside the task context (chat history) AND as a queued pending
|
|
7756
|
+
* message. When the intrinsic delivery is prefill (manual-mode fresh TUI)
|
|
7757
|
+
* or a hinted message is queued (Refine), drop those context-duplicates so
|
|
7758
|
+
* they don't force submit semantics — a genuinely-new live message still
|
|
7759
|
+
* does. Returns the lone hinted message to park, if any.
|
|
7760
|
+
*/
|
|
7761
|
+
prepareInitialPendingMessages(intrinsicDelivery) {
|
|
7762
|
+
const hasHintedPending = this.pendingMessages.some((m) => m.delivery === "prefill");
|
|
7763
|
+
if (this.pendingMessages.length > 0 && (intrinsicDelivery === "prefill" || hasHintedPending)) {
|
|
7764
|
+
this.foldContextDuplicatePendingMessages();
|
|
7765
|
+
}
|
|
7766
|
+
return this.takePrefillHintedMessage();
|
|
7767
|
+
}
|
|
7768
|
+
/**
|
|
7769
|
+
* Drop pending messages whose content is already present as a user message
|
|
7770
|
+
* in the task-context chat history (the card's initial message is delivered
|
|
7771
|
+
* both ways). Hinted (prefill) messages are kept — they are consumed by the
|
|
7772
|
+
* dedicated prefill path.
|
|
7773
|
+
*/
|
|
7774
|
+
foldContextDuplicatePendingMessages() {
|
|
7775
|
+
const userContents = new Set(
|
|
7776
|
+
(this.fullContext?.chatHistory ?? []).filter((m) => m.role === "user" && m.content.trim()).map((m) => m.content.trim())
|
|
7777
|
+
);
|
|
7778
|
+
const kept = this.pendingMessages.filter(
|
|
7779
|
+
(m) => m.delivery === "prefill" || !m.content.trim() || !userContents.has(m.content.trim())
|
|
7780
|
+
);
|
|
7781
|
+
const dropped = this.pendingMessages.length - kept.length;
|
|
7782
|
+
if (dropped > 0) {
|
|
7783
|
+
this.pendingMessages.length = 0;
|
|
7784
|
+
this.pendingMessages.push(...kept);
|
|
7785
|
+
process.stderr.write(
|
|
7786
|
+
`[conveyor-agent] Folded ${dropped} pending message(s) already present in chat context
|
|
7787
|
+
`
|
|
7788
|
+
);
|
|
7789
|
+
}
|
|
7790
|
+
}
|
|
7791
|
+
/**
|
|
7792
|
+
* Honor a prefill hint only when it is unambiguous: PTY harness, a manual
|
|
7793
|
+
* (human-facing) agent mode, no other message queued behind it, and not an
|
|
7794
|
+
* automated-critical source. Everything else keeps submit semantics.
|
|
7795
|
+
*/
|
|
7796
|
+
prefillEligible(msg) {
|
|
7797
|
+
if (msg.delivery !== "prefill") return false;
|
|
7798
|
+
if (this.pendingMessages.length > 0) return false;
|
|
7799
|
+
if (this.queryBridge?.harnessKind !== "pty") return false;
|
|
7800
|
+
if (msg.source && msg.source !== "mode_change" && msg.source !== "user") return false;
|
|
7801
|
+
const m = this.mode.effectiveMode;
|
|
7802
|
+
return m === "discovery" || m === "review" || m === "help";
|
|
7803
|
+
}
|
|
7804
|
+
/** Consume the sole pending message when it should park as a prefill. */
|
|
7805
|
+
takePrefillHintedMessage() {
|
|
7806
|
+
if (this.pendingMessages.length !== 1) return null;
|
|
7807
|
+
const [first] = this.pendingMessages;
|
|
7808
|
+
if (!first || first.delivery !== "prefill") return null;
|
|
7809
|
+
this.pendingMessages.length = 0;
|
|
7810
|
+
if (this.prefillEligible(first)) return first;
|
|
7811
|
+
this.pendingMessages.push(first);
|
|
7812
|
+
return null;
|
|
7813
|
+
}
|
|
7814
|
+
/**
|
|
7815
|
+
* Park a message in the Connected-TUI input (prefill) and wait for the human
|
|
7816
|
+
* to submit. Empty content prefills the mode's initial prompt instead (the
|
|
7817
|
+
* latest user chat message — e.g. a Refine wake on a dormant agent). The
|
|
7818
|
+
* caller restores the idle state afterwards.
|
|
7819
|
+
*/
|
|
7820
|
+
async runPrefilledMessage(msg, effectiveMode) {
|
|
7821
|
+
await this.setState("waiting_for_input");
|
|
7822
|
+
await this.callbacks.onEvent({
|
|
7823
|
+
type: "execute_mode",
|
|
7824
|
+
mode: effectiveMode,
|
|
7825
|
+
delivery: "prefill"
|
|
7826
|
+
});
|
|
7827
|
+
this.lifecycle.startIdleTimer();
|
|
7828
|
+
try {
|
|
7829
|
+
await this.executeQuery(msg.content.trim() ? msg.content : void 0, "prefill");
|
|
7830
|
+
} finally {
|
|
7831
|
+
this.lifecycle.cancelIdleTimer();
|
|
7832
|
+
}
|
|
7833
|
+
}
|
|
7677
7834
|
// ── Message waiting ────────────────────────────────────────────────
|
|
7678
7835
|
waitForMessage() {
|
|
7679
7836
|
if (this.pendingMessages.length > 0) {
|
|
@@ -10111,7 +10268,7 @@ var ProjectRunner = class {
|
|
|
10111
10268
|
async handleAuditTags(request) {
|
|
10112
10269
|
this.connection.emitStatus("busy");
|
|
10113
10270
|
try {
|
|
10114
|
-
const { handleTagAudit } = await import("./tag-audit-handler-
|
|
10271
|
+
const { handleTagAudit } = await import("./tag-audit-handler-PKYLDJHH.js");
|
|
10115
10272
|
await handleTagAudit(request, this.connection, this.projectDir);
|
|
10116
10273
|
} catch (error) {
|
|
10117
10274
|
const msg = parseErrorMessage(error);
|
|
@@ -10134,7 +10291,7 @@ var ProjectRunner = class {
|
|
|
10134
10291
|
async handleAuditTasks(request) {
|
|
10135
10292
|
this.connection.emitStatus("busy");
|
|
10136
10293
|
try {
|
|
10137
|
-
const { handleTaskAudit } = await import("./task-audit-handler-
|
|
10294
|
+
const { handleTaskAudit } = await import("./task-audit-handler-WINYLZMU.js");
|
|
10138
10295
|
await handleTaskAudit(request, this.connection, this.projectDir);
|
|
10139
10296
|
} catch (error) {
|
|
10140
10297
|
const msg = parseErrorMessage(error);
|
|
@@ -10275,4 +10432,4 @@ export {
|
|
|
10275
10432
|
loadConveyorConfig,
|
|
10276
10433
|
unshallowRepo
|
|
10277
10434
|
};
|
|
10278
|
-
//# sourceMappingURL=chunk-
|
|
10435
|
+
//# sourceMappingURL=chunk-3T4SJEH6.js.map
|