@rallycry/conveyor-agent 10.13.12 → 10.13.13
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-4KIPA6LF.js → chunk-TB5SQIGX.js} +178 -34
- package/dist/chunk-TB5SQIGX.js.map +1 -0
- package/dist/cli.js +1 -1
- package/dist/index.d.ts +9 -0
- package/dist/index.js +1 -1
- package/package.json +1 -1
- package/dist/chunk-4KIPA6LF.js.map +0 -1
|
@@ -2662,6 +2662,13 @@ var StartAdhocSessionRequestSchema = z4.object({
|
|
|
2662
2662
|
mode: z4.enum(["adhoc", "pm"]).optional(),
|
|
2663
2663
|
/** Base branch to check out (defaults to the project's dev branch). */
|
|
2664
2664
|
branch: z4.string().max(300).optional(),
|
|
2665
|
+
/**
|
|
2666
|
+
* Server-assembled instructions the pod's TUI auto-submits once on first boot
|
|
2667
|
+
* (headless kickoff). Used by the onboarding "Set it up for me" flow to seed a
|
|
2668
|
+
* setup-driver prompt; the session stays watchable/interactive in the Sessions
|
|
2669
|
+
* view. `ensureAdhocWorkspace` persists it and clears it after first submit.
|
|
2670
|
+
*/
|
|
2671
|
+
initialPrompt: z4.string().max(2e4).optional(),
|
|
2665
2672
|
requestingUserId: z4.string().optional()
|
|
2666
2673
|
});
|
|
2667
2674
|
var StopAdhocSessionRequestSchema = z4.object({
|
|
@@ -4465,6 +4472,22 @@ async function readRaw(path3) {
|
|
|
4465
4472
|
return null;
|
|
4466
4473
|
}
|
|
4467
4474
|
}
|
|
4475
|
+
function classifyTuiAuth(input) {
|
|
4476
|
+
if (!input.isCloud) return "ready";
|
|
4477
|
+
if (input.hasOauthToken || input.hasApiKey || input.credsHasAccessToken) return "ready";
|
|
4478
|
+
return "no-credential";
|
|
4479
|
+
}
|
|
4480
|
+
async function resolveTuiAuthReadiness(env = process.env, readIdentity = readCredentialsIdentity) {
|
|
4481
|
+
const isCloud = isConveyorCloudEnv(env);
|
|
4482
|
+
const credsHasAccessToken = isCloud ? Boolean((await readIdentity())?.accessToken) : false;
|
|
4483
|
+
const status = classifyTuiAuth({
|
|
4484
|
+
isCloud,
|
|
4485
|
+
hasOauthToken: Boolean(env.CLAUDE_CODE_OAUTH_TOKEN),
|
|
4486
|
+
hasApiKey: Boolean(env.ANTHROPIC_API_KEY),
|
|
4487
|
+
credsHasAccessToken
|
|
4488
|
+
});
|
|
4489
|
+
return { ready: status === "ready", status };
|
|
4490
|
+
}
|
|
4468
4491
|
async function readCredentialsIdentity() {
|
|
4469
4492
|
const parsed = parseClaudeAiOauth(await readRaw(claudeCredentialsPath()));
|
|
4470
4493
|
if (!parsed) return null;
|
|
@@ -5149,6 +5172,39 @@ var PtySession = class {
|
|
|
5149
5172
|
writeStdin(text) {
|
|
5150
5173
|
this.pty?.write(text);
|
|
5151
5174
|
}
|
|
5175
|
+
/**
|
|
5176
|
+
* Inject a follow-up message into the CURRENTLY-RUNNING turn by pasting it into
|
|
5177
|
+
* the live TUI input, exactly as a human typing mid-turn would — the CLI queues
|
|
5178
|
+
* it and picks it up at the next turn boundary. Unlike beginTurn this does NOT
|
|
5179
|
+
* reset per-turn state, allocate a new queue, or re-arm the abort listener: the
|
|
5180
|
+
* in-flight turn (and its transcript stream) keeps flowing, so the injected
|
|
5181
|
+
* message and its response ride the SAME event pipeline. Returns false when
|
|
5182
|
+
* there is no live, actively-draining turn to inject into — parked/idle
|
|
5183
|
+
* (activeQueue === null), torn down, exited, or a raw-terminal TUI that gives
|
|
5184
|
+
* us no trusted signal that a turn is running — so the caller falls back to the
|
|
5185
|
+
* abort+respawn supersede path.
|
|
5186
|
+
*/
|
|
5187
|
+
injectIntoRunningTurn(text) {
|
|
5188
|
+
if (!this.pty || this._toreDown || this.exited) return false;
|
|
5189
|
+
if (this.activeQueue === null) return false;
|
|
5190
|
+
if (!this.adapter.capabilities.structuredEvents) return false;
|
|
5191
|
+
if (!text.trim()) return false;
|
|
5192
|
+
void this.submitLivePrompt(text);
|
|
5193
|
+
return true;
|
|
5194
|
+
}
|
|
5195
|
+
/**
|
|
5196
|
+
* Paste + submit a prompt into the live pty WITHOUT any turn bookkeeping.
|
|
5197
|
+
* Mirrors deliverPrompt's submit path (bracketed paste, then a separate Enter
|
|
5198
|
+
* after a settle window) but never arms the submit nudge — the running turn is
|
|
5199
|
+
* already producing transcript records, so re-pressing Enter would risk
|
|
5200
|
+
* accepting an unrelated mid-turn dialog. Fire-and-forget.
|
|
5201
|
+
*/
|
|
5202
|
+
async submitLivePrompt(text) {
|
|
5203
|
+
this.writeStdin(this.adapter.encodePromptBytes(text));
|
|
5204
|
+
await sleep(resolveSubmitSettleMs());
|
|
5205
|
+
if (this._toreDown || this.exited) return;
|
|
5206
|
+
this.writeStdin("\r");
|
|
5207
|
+
}
|
|
5152
5208
|
/** Apply a relayed resize to the live pty (reconciled dims from the server). */
|
|
5153
5209
|
resizePty(cols, rows) {
|
|
5154
5210
|
if (cols <= 0 || rows <= 0) return;
|
|
@@ -5560,6 +5616,9 @@ var PtyHarness = class _PtyHarness {
|
|
|
5560
5616
|
endedTimer = null;
|
|
5561
5617
|
/** Passive-activity subscriber, re-attached to whichever session is parked. */
|
|
5562
5618
|
passiveHandler = null;
|
|
5619
|
+
/** Once-per-session guard so the "no Claude credential" notice isn't re-posted
|
|
5620
|
+
* on every respawn (a fresh spawn happens on each fingerprint/lineage flip). */
|
|
5621
|
+
authNoticeSent = false;
|
|
5563
5622
|
/**
|
|
5564
5623
|
* Wiggle the live pty's size so the CLI repaints its whole screen. No-op on
|
|
5565
5624
|
* the SDK harness. Falls back to the parked session so an API reconnect while
|
|
@@ -5568,6 +5627,30 @@ var PtyHarness = class _PtyHarness {
|
|
|
5568
5627
|
forceRepaint() {
|
|
5569
5628
|
(this.activeSession ?? this.parked)?.forceRepaint();
|
|
5570
5629
|
}
|
|
5630
|
+
/** Actionable message posted to the card when a spawn will park at the Claude
|
|
5631
|
+
* sign-in screen. Kept as a constant so the harness stays free of i18n deps. */
|
|
5632
|
+
static AUTH_NOT_READY_MESSAGE = "\u26A0\uFE0F This pod started the Claude Code TUI with no Claude credential, so it is parked on the sign-in screen and can't make progress. This usually means there is no usable Claude subscription token or API key configured for this project/assignee. Add or repair the Claude credential in project settings, then restart the session.";
|
|
5633
|
+
/**
|
|
5634
|
+
* Best-effort: if the TUI is about to spawn with no usable credential, post a
|
|
5635
|
+
* one-time diagnostic through the relay bridge. Never throws — a readiness
|
|
5636
|
+
* probe must not block or fail a spawn.
|
|
5637
|
+
*/
|
|
5638
|
+
async warnIfAuthNotReady() {
|
|
5639
|
+
if (this.authNoticeSent || !this.bridge?.notifyAuthNotReady) return;
|
|
5640
|
+
try {
|
|
5641
|
+
const readiness = await resolveTuiAuthReadiness();
|
|
5642
|
+
if (readiness.ready) return;
|
|
5643
|
+
this.authNoticeSent = true;
|
|
5644
|
+
this.bridge.notifyAuthNotReady(_PtyHarness.AUTH_NOT_READY_MESSAGE);
|
|
5645
|
+
_PtyHarness.log.warn(
|
|
5646
|
+
"Claude TUI spawning with no usable credential \u2014 parked at sign-in screen"
|
|
5647
|
+
);
|
|
5648
|
+
} catch (err) {
|
|
5649
|
+
_PtyHarness.log.warn("auth-readiness probe failed", {
|
|
5650
|
+
error: err instanceof Error ? err.message : String(err)
|
|
5651
|
+
});
|
|
5652
|
+
}
|
|
5653
|
+
}
|
|
5571
5654
|
async *executeQuery(opts) {
|
|
5572
5655
|
const want = opts.resume ?? opts.options.resume;
|
|
5573
5656
|
const fingerprint = this.fingerprintOf(opts.options);
|
|
@@ -5589,6 +5672,9 @@ var PtyHarness = class _PtyHarness {
|
|
|
5589
5672
|
await ensureUsableClaudeConfigHome(opts.options.cwd, _PtyHarness.log);
|
|
5590
5673
|
}
|
|
5591
5674
|
await this.adapter.prepareEnvironment({ cwd: opts.options.cwd });
|
|
5675
|
+
if (this.adapter.capabilities.structuredEvents) {
|
|
5676
|
+
await this.warnIfAuthNotReady();
|
|
5677
|
+
}
|
|
5592
5678
|
session.onExit(() => this.handleSessionExit(session));
|
|
5593
5679
|
await session.start();
|
|
5594
5680
|
}
|
|
@@ -5599,6 +5685,15 @@ var PtyHarness = class _PtyHarness {
|
|
|
5599
5685
|
* query running" (a human typed into the idle Connected-TUI). Attaches to the
|
|
5600
5686
|
* currently-parked session and to any session parked later.
|
|
5601
5687
|
*/
|
|
5688
|
+
/**
|
|
5689
|
+
* PTY-only: inject a follow-up message into the turn currently streaming
|
|
5690
|
+
* events (the active session), so the runner can add to a running turn without
|
|
5691
|
+
* aborting + respawning. Returns false when no turn is active (idle/parked) or
|
|
5692
|
+
* the paste couldn't be delivered — the caller supersedes instead.
|
|
5693
|
+
*/
|
|
5694
|
+
injectIntoRunningTurn(text) {
|
|
5695
|
+
return this.activeSession?.injectIntoRunningTurn(text) ?? false;
|
|
5696
|
+
}
|
|
5602
5697
|
onPassiveActivity(handler) {
|
|
5603
5698
|
this.passiveHandler = handler;
|
|
5604
5699
|
const unsubParked = this.parked?.onPassiveActivity(handler);
|
|
@@ -6378,6 +6473,18 @@ function buildPlanDocumentationSection(context) {
|
|
|
6378
6473
|
`- Identification auto-fills title, story points, and icon with quick AI guesses. After exploring, refine the title and story points with update_task_properties if they look like placeholders. Icons are automatic \u2014 never set them.`
|
|
6379
6474
|
];
|
|
6380
6475
|
}
|
|
6476
|
+
function buildNoPrWhenNoCodeSection(baseBranch) {
|
|
6477
|
+
const base = baseBranch ?? "dev";
|
|
6478
|
+
return [
|
|
6479
|
+
``,
|
|
6480
|
+
`### A PR is NOT required \u2014 only open one for actual code changes`,
|
|
6481
|
+
`\`create_pull_request\` is for tasks that change code in the repo. Many tasks don't: support requests, config/credential help, answering a question, investigations, or research whose deliverable is an answer or a file rather than a diff.`,
|
|
6482
|
+
`- If you finish the work with NO code changes (an empty \`git diff ${base}..HEAD\`), do NOT open a PR. An empty or throwaway PR just to "complete" the workflow is wrong \u2014 a human then has to close it.`,
|
|
6483
|
+
`- Deliver the result where it belongs: post the answer/config/findings with \`post_to_chat\`, and attach any files the user should keep with \`upload_attachment\`.`,
|
|
6484
|
+
`- Then complete the card directly with \`force_update_task_status("Complete")\` \u2014 there is no PR or review step for a no-code task.`,
|
|
6485
|
+
`- When in doubt, check \`git diff ${base}..HEAD\`: a real diff means open a PR; no diff means finish in chat and mark Complete.`
|
|
6486
|
+
];
|
|
6487
|
+
}
|
|
6381
6488
|
function buildExplorationMethodology() {
|
|
6382
6489
|
return [
|
|
6383
6490
|
``,
|
|
@@ -6500,7 +6607,7 @@ function buildAutoPrompt(context, runnerMode) {
|
|
|
6500
6607
|
`If no children exist yet, break the work down now: save a parent-level plan with update_task_plan, then create child tasks with create_subtask (each with a detailed plan).`,
|
|
6501
6608
|
`Child task status lifecycle: Open \u2192 InProgress \u2192 ReviewPR \u2192 ReviewDev \u2192 Complete.`,
|
|
6502
6609
|
`Set child ordering with \`dependsOn\` (sibling ids/slugs) on \`create_subtask\` \u2014 explicit metadata the pack runner schedules off, not order described in plan text. Independent children get none and run in parallel.`
|
|
6503
|
-
] :
|
|
6610
|
+
] : buildNoPrWhenNoCodeSection(context?.baseBranch),
|
|
6504
6611
|
``,
|
|
6505
6612
|
`### Autonomous Guidelines:`,
|
|
6506
6613
|
`- Make decisions independently \u2014 do not ask the team for approval at each step`,
|
|
@@ -6510,37 +6617,40 @@ function buildAutoPrompt(context, runnerMode) {
|
|
|
6510
6617
|
if (context) parts.push(...buildPropertyInstructions(context, runnerMode));
|
|
6511
6618
|
return parts.join("\n");
|
|
6512
6619
|
}
|
|
6620
|
+
function buildBuildingPrompt(context) {
|
|
6621
|
+
const parts = [
|
|
6622
|
+
`
|
|
6623
|
+
## Mode: Building`,
|
|
6624
|
+
`You are in Building mode \u2014 executing the plan.`,
|
|
6625
|
+
`- You have full coding access (read, write, edit, bash, git)`,
|
|
6626
|
+
`- Safety rules: no destructive operations, use --force-with-lease instead of --force`,
|
|
6627
|
+
...context?.isParentTask ? [
|
|
6628
|
+
`- You are a parent task. Use \`list_subtasks\`, \`start_child_cloud_build\`, and subtask management tools to coordinate children.`,
|
|
6629
|
+
`- Do NOT implement code directly \u2014 fire child builds and review their work.`,
|
|
6630
|
+
`- Goal: coordinate child task execution and ensure all children complete successfully`
|
|
6631
|
+
] : [
|
|
6632
|
+
`- If this is a leaf task (no children): execute the plan directly`,
|
|
6633
|
+
`- Goal: implement the plan, run scoped verification, open a PR when done`,
|
|
6634
|
+
``,
|
|
6635
|
+
`### Pre-PR Verification Checklist`,
|
|
6636
|
+
`CI runs the FULL suite (lint, typecheck, all test shards) on every PR \u2014 do not duplicate it locally. Before calling \`mcp__conveyor__create_pull_request\`, scope verification to your diff:`,
|
|
6637
|
+
`1. \`bun run check\` \u2014 lint + typecheck (fast; run whenever you changed code)`,
|
|
6638
|
+
`2. \`bun run test:affected\` \u2014 runs only the tests your diff can affect (docs-only diffs run nothing; apps/api diffs run unit tests only since CI covers the int shards; shared/db diffs escalate to the full suite automatically)`,
|
|
6639
|
+
`Docs/markdown/.claude-only changes need NO local gates \u2014 open the PR and let CI validate.`,
|
|
6640
|
+
`If a gate fails, fix it before opening the PR. Do NOT open PRs with known failing gates. Never run the full \`bun run test\` for a diff confined to one package.`,
|
|
6641
|
+
`For refactors: also run \`git diff ${context?.baseBranch ?? "dev"}..HEAD\` and confirm the public API surface (exports, function signatures) has no unintended breaking changes.`,
|
|
6642
|
+
...buildNoPrWhenNoCodeSection(context?.baseBranch),
|
|
6643
|
+
...context?.isAuto || !context?.plan?.trim() ? buildPlanDocumentationSection(context) : []
|
|
6644
|
+
]
|
|
6645
|
+
];
|
|
6646
|
+
return parts.join("\n");
|
|
6647
|
+
}
|
|
6513
6648
|
function buildModePrompt(agentMode, context, runnerMode) {
|
|
6514
6649
|
switch (agentMode) {
|
|
6515
6650
|
case "discovery":
|
|
6516
6651
|
return buildDiscoveryPrompt(context, runnerMode);
|
|
6517
|
-
case "building":
|
|
6518
|
-
|
|
6519
|
-
`
|
|
6520
|
-
## Mode: Building`,
|
|
6521
|
-
`You are in Building mode \u2014 executing the plan.`,
|
|
6522
|
-
`- You have full coding access (read, write, edit, bash, git)`,
|
|
6523
|
-
`- Safety rules: no destructive operations, use --force-with-lease instead of --force`,
|
|
6524
|
-
...context?.isParentTask ? [
|
|
6525
|
-
`- You are a parent task. Use \`list_subtasks\`, \`start_child_cloud_build\`, and subtask management tools to coordinate children.`,
|
|
6526
|
-
`- Do NOT implement code directly \u2014 fire child builds and review their work.`,
|
|
6527
|
-
`- Goal: coordinate child task execution and ensure all children complete successfully`
|
|
6528
|
-
] : [
|
|
6529
|
-
`- If this is a leaf task (no children): execute the plan directly`,
|
|
6530
|
-
`- Goal: implement the plan, run scoped verification, open a PR when done`,
|
|
6531
|
-
``,
|
|
6532
|
-
`### Pre-PR Verification Checklist`,
|
|
6533
|
-
`CI runs the FULL suite (lint, typecheck, all test shards) on every PR \u2014 do not duplicate it locally. Before calling \`mcp__conveyor__create_pull_request\`, scope verification to your diff:`,
|
|
6534
|
-
`1. \`bun run check\` \u2014 lint + typecheck (fast; run whenever you changed code)`,
|
|
6535
|
-
`2. \`bun run test:affected\` \u2014 runs only the tests your diff can affect (docs-only diffs run nothing; apps/api diffs run unit tests only since CI covers the int shards; shared/db diffs escalate to the full suite automatically)`,
|
|
6536
|
-
`Docs/markdown/.claude-only changes need NO local gates \u2014 open the PR and let CI validate.`,
|
|
6537
|
-
`If a gate fails, fix it before opening the PR. Do NOT open PRs with known failing gates. Never run the full \`bun run test\` for a diff confined to one package.`,
|
|
6538
|
-
`For refactors: also run \`git diff ${context?.baseBranch ?? "dev"}..HEAD\` and confirm the public API surface (exports, function signatures) has no unintended breaking changes.`,
|
|
6539
|
-
...context?.isAuto || !context?.plan?.trim() ? buildPlanDocumentationSection(context) : []
|
|
6540
|
-
]
|
|
6541
|
-
];
|
|
6542
|
-
return parts.join("\n");
|
|
6543
|
-
}
|
|
6652
|
+
case "building":
|
|
6653
|
+
return buildBuildingPrompt(context);
|
|
6544
6654
|
case "review":
|
|
6545
6655
|
return buildReviewPrompt(context);
|
|
6546
6656
|
case "auto":
|
|
@@ -10002,6 +10112,7 @@ function buildPtyBridge(connection) {
|
|
|
10002
10112
|
sendOutput: (data, dims) => connection.sendPtyOutput(data, dims),
|
|
10003
10113
|
sendChatEvent: (event) => connection.sendPtyChatEvent(event),
|
|
10004
10114
|
sendEnded: () => connection.sendPtyEnded(),
|
|
10115
|
+
notifyAuthNotReady: (detail) => connection.postChatMessage(detail),
|
|
10005
10116
|
onInput: (handler) => connection.onPtyInput(handler),
|
|
10006
10117
|
onResize: (handler) => connection.onPtyResize(handler)
|
|
10007
10118
|
};
|
|
@@ -10072,6 +10183,16 @@ var QueryBridge = class {
|
|
|
10072
10183
|
resume() {
|
|
10073
10184
|
this._stopped = false;
|
|
10074
10185
|
}
|
|
10186
|
+
/**
|
|
10187
|
+
* Inject a follow-up message into the turn currently running under the harness
|
|
10188
|
+
* (PTY keep-alive) instead of aborting it. Returns true when the harness fed
|
|
10189
|
+
* the message into the live TUI; false when there is no running turn to inject
|
|
10190
|
+
* into or the harness has no live terminal (SDK) — the caller then supersedes
|
|
10191
|
+
* via stop() + respawn.
|
|
10192
|
+
*/
|
|
10193
|
+
injectIntoRunningTurn(content) {
|
|
10194
|
+
return this.harness.injectIntoRunningTurn?.(content) ?? false;
|
|
10195
|
+
}
|
|
10075
10196
|
/**
|
|
10076
10197
|
* Tear down any parked/active CLI process the harness is keeping alive between
|
|
10077
10198
|
* turns (PTY keep-alive). Called by SessionRunner on stop/shutdown so the
|
|
@@ -11427,12 +11548,35 @@ var SessionRunner = class _SessionRunner {
|
|
|
11427
11548
|
const resolve = this.inputResolver;
|
|
11428
11549
|
this.inputResolver = null;
|
|
11429
11550
|
resolve(msg);
|
|
11430
|
-
|
|
11431
|
-
this.pendingMessages.push(msg);
|
|
11432
|
-
if (this._state === "running" || this._state === "waiting_for_input") {
|
|
11433
|
-
this.queryBridge?.stop();
|
|
11434
|
-
}
|
|
11551
|
+
return;
|
|
11435
11552
|
}
|
|
11553
|
+
if (this._state === "running" && this.canInjectIntoRunningTurn(msg) && this.queryBridge?.injectIntoRunningTurn(msg.content)) {
|
|
11554
|
+
void this.callbacks.onEvent({
|
|
11555
|
+
type: "user_message",
|
|
11556
|
+
content: msg.content,
|
|
11557
|
+
userId: msg.userId
|
|
11558
|
+
});
|
|
11559
|
+
return;
|
|
11560
|
+
}
|
|
11561
|
+
this.pendingMessages.push(msg);
|
|
11562
|
+
if (this._state === "running" || this._state === "waiting_for_input") {
|
|
11563
|
+
this.queryBridge?.stop();
|
|
11564
|
+
}
|
|
11565
|
+
}
|
|
11566
|
+
/**
|
|
11567
|
+
* Whether a mid-turn message may be pasted into the live running TUI rather
|
|
11568
|
+
* than superseding the turn. Restricted to genuine same-mode user follow-ups:
|
|
11569
|
+
* a pending mode restart, an empty body, a prefill hint, or any non-"user"
|
|
11570
|
+
* source (mode_change / pty_passive / system / ci_failure / review_trigger)
|
|
11571
|
+
* must take the abort+respawn path — a mode/fingerprint change needs a fresh
|
|
11572
|
+
* spawn, and a prefill must park unsubmitted for the human.
|
|
11573
|
+
*/
|
|
11574
|
+
canInjectIntoRunningTurn(msg) {
|
|
11575
|
+
if (this.mode.pendingModeRestart) return false;
|
|
11576
|
+
if (!msg.content.trim()) return false;
|
|
11577
|
+
if (msg.delivery === "prefill") return false;
|
|
11578
|
+
if (msg.source && msg.source !== "user") return false;
|
|
11579
|
+
return true;
|
|
11436
11580
|
}
|
|
11437
11581
|
// ── Query execution with abort handling ────────────────────────────
|
|
11438
11582
|
/** Run queryBridge.execute, swallowing abort errors from stop/softStop. */
|
|
@@ -11950,4 +12094,4 @@ export {
|
|
|
11950
12094
|
loadConveyorConfig,
|
|
11951
12095
|
unshallowRepo
|
|
11952
12096
|
};
|
|
11953
|
-
//# sourceMappingURL=chunk-
|
|
12097
|
+
//# sourceMappingURL=chunk-TB5SQIGX.js.map
|