@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.
@@ -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
- const parts = [
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
- } else {
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-4KIPA6LF.js.map
12097
+ //# sourceMappingURL=chunk-TB5SQIGX.js.map