@bastani/atomic 0.5.16-0 → 0.5.17-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.
Files changed (38) hide show
  1. package/.agents/skills/workflow-creator/references/agent-sessions.md +3 -1
  2. package/.agents/skills/workflow-creator/references/failure-modes.md +140 -0
  3. package/.claude/settings.json +1 -0
  4. package/dist/sdk/components/header.d.ts.map +1 -1
  5. package/dist/sdk/components/layout.d.ts.map +1 -1
  6. package/dist/sdk/components/node-card.d.ts.map +1 -1
  7. package/dist/sdk/components/orchestrator-panel-store.d.ts +2 -0
  8. package/dist/sdk/components/orchestrator-panel-store.d.ts.map +1 -1
  9. package/dist/sdk/components/orchestrator-panel-types.d.ts +1 -1
  10. package/dist/sdk/components/orchestrator-panel-types.d.ts.map +1 -1
  11. package/dist/sdk/components/orchestrator-panel.d.ts +2 -0
  12. package/dist/sdk/components/orchestrator-panel.d.ts.map +1 -1
  13. package/dist/sdk/components/status-helpers.d.ts.map +1 -1
  14. package/dist/sdk/providers/claude.d.ts +33 -1
  15. package/dist/sdk/providers/claude.d.ts.map +1 -1
  16. package/dist/sdk/runtime/executor.d.ts +88 -0
  17. package/dist/sdk/runtime/executor.d.ts.map +1 -1
  18. package/dist/sdk/workflows/builtin/deep-research-codebase/claude/index.d.ts.map +1 -1
  19. package/dist/sdk/workflows/builtin/ralph/claude/index.d.ts +7 -3
  20. package/dist/sdk/workflows/builtin/ralph/claude/index.d.ts.map +1 -1
  21. package/dist/services/config/definitions.d.ts.map +1 -1
  22. package/package.json +5 -5
  23. package/src/commands/cli/init/onboarding.ts +19 -2
  24. package/src/sdk/components/header.tsx +2 -1
  25. package/src/sdk/components/layout.ts +2 -1
  26. package/src/sdk/components/node-card.tsx +16 -0
  27. package/src/sdk/components/orchestrator-panel-store.test.ts +88 -0
  28. package/src/sdk/components/orchestrator-panel-store.ts +16 -0
  29. package/src/sdk/components/orchestrator-panel-types.ts +1 -1
  30. package/src/sdk/components/orchestrator-panel.tsx +8 -0
  31. package/src/sdk/components/session-graph-panel.tsx +1 -1
  32. package/src/sdk/components/status-helpers.ts +3 -2
  33. package/src/sdk/providers/claude.ts +160 -2
  34. package/src/sdk/runtime/executor.test.ts +144 -0
  35. package/src/sdk/runtime/executor.ts +219 -31
  36. package/src/sdk/workflows/builtin/deep-research-codebase/claude/index.ts +3 -18
  37. package/src/sdk/workflows/builtin/ralph/claude/index.ts +41 -51
  38. package/src/services/config/definitions.ts +5 -0
@@ -99,7 +99,9 @@ Claude maintains conversation context across calls within the same pane. Call `s
99
99
 
100
100
  ### Advanced: Claude Agent SDK `query()` API
101
101
 
102
- For programmatic control beyond tmux automation, the Claude Agent SDK provides `query()`:
102
+ For programmatic control beyond tmux automation, the Claude Agent SDK provides `query()`. **Do not call it from inside a non-headless `ctx.stage()`** — that spawns a TUI in a tmux pane that goes unused while the SDK runs in-process (see `failure-modes.md` §F17). Either set `headless: true` on the stage and pass SDK options through `s.session.query(prompt, options)` (the headless wrapper forwards them to `query()`), or use the interactive TUI route below with `chatFlags: ["--agent", "<name>", ...]` plus `s.session.query(prompt)`.
103
+
104
+ The example below is reference for the SDK option surface — in real workflow code, prefer `s.session.query()` so the runtime, not your callback, decides which transport to use:
103
105
 
104
106
  ```ts
105
107
  import { query } from "@anthropic-ai/claude-agent-sdk";
@@ -46,6 +46,7 @@ Silent failures are catalogued first below. Loud failures are grouped at the end
46
46
  | [F14](#f14-forgetting-to-await-ctxstage) | Forgetting to `await` `ctx.stage()` | all | silent |
47
47
  | [F15](#f15-using-a-pending-sessionhandle-before-completion) | Using a pending `SessionHandle` before completion | all | silent |
48
48
  | [F16](#f16-headless-stage-errors-are-invisible-in-the-graph) | Headless stage errors are invisible in the graph | all | silent |
49
+ | [F17](#f17-claude-importing-sdk-query-inside-a-non-headless-stage) | Claude: importing the SDK `query()` inside a non-headless stage (anti-pattern) | Claude | silent |
49
50
 
50
51
  ---
51
52
 
@@ -713,6 +714,144 @@ full error for each failed headless stage.
713
714
 
714
715
  ---
715
716
 
717
+ ## F17. Claude: importing the SDK `query()` inside a non-headless stage
718
+
719
+ **Symptom.** A reviewer / extractor / structured-output stage shows up in
720
+ the workflow graph as a tmux pane, but the pane sits idle on the Claude
721
+ welcome screen for the entire stage duration. The stage still produces a
722
+ result — but the visible session never moved. CPU and token cost double:
723
+ two Claude processes ran, one in the pane (idle) and one in-process (the
724
+ SDK call that actually did the work).
725
+
726
+ **Root cause.** The stage was registered without `headless: true`, so the
727
+ runtime spawned an interactive Claude TUI in a tmux pane and bound
728
+ `s.session` to it. The callback ignored that and called
729
+ `query()` from `@anthropic-ai/claude-agent-sdk` directly:
730
+
731
+ ```ts
732
+ import { query } from "@anthropic-ai/claude-agent-sdk";
733
+ // ...
734
+ ctx.stage({ name: "review" }, {}, {}, async (s) => {
735
+ for await (const msg of query({ prompt, options: { outputFormat: ... } })) { /* ... */ }
736
+ });
737
+ ```
738
+
739
+ That import bypasses `s.session` entirely. The runtime cannot route the
740
+ SDK call through the TUI it just started, so:
741
+
742
+ 1. The visible pane never receives a prompt — the user sees a blank Claude
743
+ session in the graph.
744
+ 2. A second Claude process spins up in the orchestrator process to service
745
+ the SDK call. Both processes count against rate limits and token spend.
746
+ 3. Idle detection on the pane never fires because no prompt was ever sent;
747
+ the runtime relies on session-state events that won't arrive, and stage
748
+ completion happens only because the callback returned (not because the
749
+ pane finished work).
750
+
751
+ The runtime exposes exactly two routes for an SDK feature:
752
+
753
+ | You want to use… | Stage shape | Code in callback |
754
+ |---|---|---|
755
+ | `outputFormat`, custom `agents`, `maxBudgetUsd`, etc. **without** a visible pane | `{ headless: true }` | `s.session.query(prompt, sdkOptions)` — wraps `HeadlessClaudeSessionWrapper.query()` which forwards `options` to the SDK |
756
+ | The visible TUI with a sub-agent | omit `headless` and pass `chatFlags: ["--agent", "<name>", ...]` | `s.session.query(prompt)` — sends through tmux send-keys |
757
+
758
+ The one option that does **not** exist is "visible pane + in-process SDK call".
759
+ That combination is always wrong — pick one route or the other.
760
+
761
+ **Affected SDKs.** Claude only. Copilot and OpenCode don't expose a
762
+ parallel "import the bare SDK" foot-gun in this codebase.
763
+
764
+ ### ❌ Wrong — visible pane + bypassed-SDK call
765
+
766
+ ```ts
767
+ import { query as claudeSdkQuery } from "@anthropic-ai/claude-agent-sdk";
768
+
769
+ await ctx.stage({ name: "review" }, {}, {}, async (s) => {
770
+ // Visible TUI was started, but we're ignoring it.
771
+ for await (const msg of claudeSdkQuery({
772
+ prompt: reviewPrompt,
773
+ options: {
774
+ outputFormat: { type: "json_schema", schema: REVIEW_SCHEMA },
775
+ },
776
+ })) {
777
+ if (msg.type === "result") { /* ... */ }
778
+ }
779
+ s.save(s.sessionId);
780
+ });
781
+ ```
782
+
783
+ ### ✅ Right (a) — visible TUI with sub-agent + chatFlags
784
+
785
+ When you want the user to watch the review happen, run the sub-agent in
786
+ the pane via `--agent` and parse JSON out of the assistant text. The
787
+ prompt should enumerate the schema fields so the model emits matching
788
+ JSON; a tolerant parser (last-fenced-block + last-balanced-object
789
+ fallback, F8) handles any prose the model adds:
790
+
791
+ ```ts
792
+ await ctx.stage(
793
+ { name: "review" },
794
+ { chatFlags: ["--agent", "reviewer", "--allow-dangerously-skip-permissions", "--dangerously-skip-permissions"] },
795
+ {},
796
+ async (s) => {
797
+ const messages = await s.session.query(reviewPrompt);
798
+ s.save(s.sessionId);
799
+ return parseReviewResult(extractAssistantText(messages, 0));
800
+ },
801
+ );
802
+ ```
803
+
804
+ This is the pattern used by `src/sdk/workflows/builtin/ralph/claude/index.ts`
805
+ for its planner, orchestrator, reviewer, and debugger stages.
806
+
807
+ ### ✅ Right (b) — headless stage with SDK options via `s.session.query()`
808
+
809
+ When you don't need the pane (e.g. background data gathering), set
810
+ `headless: true` and pass SDK options as the second argument to
811
+ `s.session.query()`. The runtime uses `HeadlessClaudeSessionWrapper`,
812
+ which calls the SDK's `query()` in-process and exposes the full options
813
+ surface (`agent`, `outputFormat`, `permissionMode`, `maxBudgetUsd`, etc.):
814
+
815
+ ```ts
816
+ await ctx.stage(
817
+ { name: "review", headless: true },
818
+ {}, {},
819
+ async (s) => {
820
+ const messages = await s.session.query(reviewPrompt, {
821
+ agent: "reviewer",
822
+ permissionMode: "bypassPermissions",
823
+ allowDangerouslySkipPermissions: true,
824
+ });
825
+ s.save(s.sessionId);
826
+ return extractAssistantText(messages, 0);
827
+ },
828
+ );
829
+ ```
830
+
831
+ > **Note on `--json-schema`.** The CLI's `--json-schema` flag requires
832
+ > `-p` (print mode) and therefore can't be passed via `chatFlags` to the
833
+ > interactive TUI. If you need SDK-validated structured output, use route
834
+ > (b) — set `headless: true` and pass `outputFormat: { type: "json_schema", schema }`
835
+ > in the `s.session.query()` options. Pair (a)'s visible TUI with a
836
+ > tolerant JSON parser instead. (Note: `s.session.query()`'s headless
837
+ > wrapper currently returns `SessionMessage[]` and discards the SDK
838
+ > result event's `structured_output` field — for now, parse JSON out of
839
+ > the assistant text either way.)
840
+
841
+ **Detection.**
842
+ 1. Grep your workflow for `from "@anthropic-ai/claude-agent-sdk"` —
843
+ `query`, `tool`, `createSdkMcpServer` and similar imports inside a
844
+ `.run()` callback are the smell. Workflow code should import from
845
+ `@bastani/atomic/workflows` and access the SDK exclusively through
846
+ `s.client` and `s.session`.
847
+ 2. Watch the workflow run. If a visible pane shows the Claude welcome
848
+ screen for the entire duration of a stage and never receives a prompt,
849
+ you have F17.
850
+ 3. Cost monitoring. F17 roughly doubles the Claude process count — if
851
+ stage spend looks 2× a single run, audit imports.
852
+
853
+ ---
854
+
716
855
  ## Design checklist
717
856
 
718
857
  Before shipping a multi-session workflow, walk the list:
@@ -729,3 +868,4 @@ Before shipping a multi-session workflow, walk the list:
729
868
  - [ ] `SessionHandle` values are only used after the promise resolves (F15)
730
869
  - [ ] If provider-level resume/fork is used at all, it stays within the same agent role (F12)
731
870
  - [ ] Headless stage callbacks include descriptive error context so failures can be diagnosed without a graph node (F16)
871
+ - [ ] Claude stages never import `query` (or other entry points) from `@anthropic-ai/claude-agent-sdk` directly — go through `s.session.query()` so the runtime routes to the TUI (interactive) or the SDK (headless) consistently (F17)
@@ -5,6 +5,7 @@
5
5
  "CLAUDE_CODE_NO_FLICKER": "1"
6
6
  },
7
7
  "includeCoAuthoredBy": false,
8
+ "skipDangerousModePermissionPrompt": true,
8
9
  "permissions": {
9
10
  "defaultMode": "bypassPermissions"
10
11
  },
@@ -1 +1 @@
1
- {"version":3,"file":"header.d.ts","sourceRoot":"","sources":["../../../src/sdk/components/header.tsx"],"names":[],"mappings":"AAAA,sCAAsC;AAetC,wBAAgB,MAAM,8BA0CrB"}
1
+ {"version":3,"file":"header.d.ts","sourceRoot":"","sources":["../../../src/sdk/components/header.tsx"],"names":[],"mappings":"AAAA,sCAAsC;AAetC,wBAAgB,MAAM,8BA2CrB"}
@@ -1 +1 @@
1
- {"version":3,"file":"layout.d.ts","sourceRoot":"","sources":["../../../src/sdk/components/layout.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,WAAW,EAAE,aAAa,EAAE,MAAM,+BAA+B,CAAC;AAIhF,eAAO,MAAM,MAAM,KAAK,CAAC;AACzB,eAAO,MAAM,MAAM,IAAI,CAAC;AACxB,eAAO,MAAM,KAAK,IAAI,CAAC;AACvB,eAAO,MAAM,KAAK,IAAI,CAAC;AACvB,eAAO,MAAM,GAAG,IAAI,CAAC;AAIrB,MAAM,WAAW,UAAU;IACzB,IAAI,EAAE,MAAM,CAAC;IACb,MAAM,EAAE,aAAa,CAAC;IACtB,OAAO,EAAE,MAAM,EAAE,CAAC;IAClB,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,SAAS,EAAE,MAAM,GAAG,IAAI,CAAC;IACzB,OAAO,EAAE,MAAM,GAAG,IAAI,CAAC;IACvB,QAAQ,EAAE,UAAU,EAAE,CAAC;IACvB,KAAK,EAAE,MAAM,CAAC;IACd,CAAC,EAAE,MAAM,CAAC;IACV,CAAC,EAAE,MAAM,CAAC;CACX;AAED,MAAM,WAAW,YAAY;IAC3B,KAAK,EAAE,UAAU,EAAE,CAAC;IACpB,GAAG,EAAE,MAAM,CAAC,MAAM,EAAE,UAAU,CAAC,CAAC;IAChC,IAAI,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;IAC7B,KAAK,EAAE,MAAM,CAAC;IACd,MAAM,EAAE,MAAM,CAAC;CAChB;AAmED,wBAAgB,aAAa,CAAC,QAAQ,EAAE,WAAW,EAAE,GAAG,YAAY,CAyHnE"}
1
+ {"version":3,"file":"layout.d.ts","sourceRoot":"","sources":["../../../src/sdk/components/layout.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,WAAW,EAAE,aAAa,EAAE,MAAM,+BAA+B,CAAC;AAIhF,eAAO,MAAM,MAAM,KAAK,CAAC;AACzB,eAAO,MAAM,MAAM,IAAI,CAAC;AACxB,eAAO,MAAM,KAAK,IAAI,CAAC;AACvB,eAAO,MAAM,KAAK,IAAI,CAAC;AACvB,eAAO,MAAM,GAAG,IAAI,CAAC;AAIrB,MAAM,WAAW,UAAU;IACzB,IAAI,EAAE,MAAM,CAAC;IACb,MAAM,EAAE,aAAa,CAAC;IACtB,OAAO,EAAE,MAAM,EAAE,CAAC;IAClB,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,SAAS,EAAE,MAAM,GAAG,IAAI,CAAC;IACzB,OAAO,EAAE,MAAM,GAAG,IAAI,CAAC;IACvB,QAAQ,EAAE,UAAU,EAAE,CAAC;IACvB,KAAK,EAAE,MAAM,CAAC;IACd,CAAC,EAAE,MAAM,CAAC;IACV,CAAC,EAAE,MAAM,CAAC;CACX;AAED,MAAM,WAAW,YAAY;IAC3B,KAAK,EAAE,UAAU,EAAE,CAAC;IACpB,GAAG,EAAE,MAAM,CAAC,MAAM,EAAE,UAAU,CAAC,CAAC;IAChC,IAAI,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;IAC7B,KAAK,EAAE,MAAM,CAAC;IACd,MAAM,EAAE,MAAM,CAAC;CAChB;AAmED,wBAAgB,aAAa,CAAC,QAAQ,EAAE,WAAW,EAAE,GAAG,YAAY,CA0HnE"}
@@ -1 +1 @@
1
- {"version":3,"file":"node-card.d.ts","sourceRoot":"","sources":["../../../src/sdk/components/node-card.tsx"],"names":[],"mappings":"AAAA,sCAAsC;AAEtC,OAAO,KAAK,MAAM,OAAO,CAAC;AAI1B,OAAO,EAAU,KAAK,UAAU,EAAE,MAAM,aAAa,CAAC;AAEtD,eAAO,MAAM,QAAQ,uEAKlB;IACD,IAAI,EAAE,UAAU,CAAC;IACjB,OAAO,EAAE,OAAO,CAAC;IACjB,UAAU,EAAE,MAAM,CAAC;IACnB,QAAQ,EAAE,MAAM,CAAC;CAClB,qBAkDC,CAAC"}
1
+ {"version":3,"file":"node-card.d.ts","sourceRoot":"","sources":["../../../src/sdk/components/node-card.tsx"],"names":[],"mappings":"AAAA,sCAAsC;AAEtC,OAAO,KAAK,MAAM,OAAO,CAAC;AAI1B,OAAO,EAAU,KAAK,UAAU,EAAE,MAAM,aAAa,CAAC;AAEtD,eAAO,MAAM,QAAQ,uEAKlB;IACD,IAAI,EAAE,UAAU,CAAC;IACjB,OAAO,EAAE,OAAO,CAAC;IACjB,UAAU,EAAE,MAAM,CAAC;IACnB,QAAQ,EAAE,MAAM,CAAC;CAClB,qBAkEC,CAAC"}
@@ -27,6 +27,8 @@ export declare class PanelStore {
27
27
  startSession(name: string): void;
28
28
  completeSession(name: string): void;
29
29
  failSession(name: string, error: string): void;
30
+ awaitingInput(name: string): void;
31
+ resumeSession(name: string): void;
30
32
  addSession(session: SessionData): void;
31
33
  setCompletion(workflowName: string, transcriptsPath: string): void;
32
34
  setFatalError(message: string): void;
@@ -1 +1 @@
1
- {"version":3,"file":"orchestrator-panel-store.d.ts","sourceRoot":"","sources":["../../../src/sdk/components/orchestrator-panel-store.ts"],"names":[],"mappings":"AAGA,OAAO,KAAK,EAAE,WAAW,EAAiB,YAAY,EAAE,QAAQ,EAAE,MAAM,+BAA+B,CAAC;AAExG,KAAK,QAAQ,GAAG,MAAM,IAAI,CAAC;AAE3B,qBAAa,UAAU;IACrB,OAAO,SAAK;IACZ,YAAY,SAAM;IAClB,KAAK,SAAM;IACX,MAAM,SAAM;IACZ,QAAQ,EAAE,WAAW,EAAE,CAAM;IAC7B,cAAc,EAAE;QAAE,YAAY,EAAE,MAAM,CAAC;QAAC,eAAe,EAAE,MAAM,CAAA;KAAE,GAAG,IAAI,CAAQ;IAChF,UAAU,EAAE,MAAM,GAAG,IAAI,CAAQ;IACjC,iBAAiB,UAAS;IAC1B,WAAW,EAAE,CAAC,MAAM,IAAI,CAAC,GAAG,IAAI,CAAQ;IACxC,YAAY,EAAE,CAAC,MAAM,IAAI,CAAC,GAAG,IAAI,CAAQ;IAEzC,oEAAoE;IACpE,mBAAmB,SAAK;IAExB,0EAA0E;IAC1E,QAAQ,EAAE,QAAQ,CAAW;IAC7B,4FAA4F;IAC5F,aAAa,SAAM;IAEnB,OAAO,CAAC,SAAS,CAAuB;IAExC,SAAS,GAAI,IAAI,QAAQ,KAAG,CAAC,MAAM,IAAI,CAAC,CAGtC;IAEF,OAAO,CAAC,IAAI;IAKZ,eAAe,CACb,IAAI,EAAE,MAAM,EACZ,KAAK,EAAE,MAAM,EACb,QAAQ,EAAE,YAAY,EAAE,EACxB,MAAM,EAAE,MAAM,GACb,IAAI;IAuBP,YAAY,CAAC,IAAI,EAAE,MAAM,GAAG,IAAI;IAQhC,eAAe,CAAC,IAAI,EAAE,MAAM,GAAG,IAAI;IAQnC,WAAW,CAAC,IAAI,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,GAAG,IAAI;IAS9C,UAAU,CAAC,OAAO,EAAE,WAAW,GAAG,IAAI;IAKtC,aAAa,CAAC,YAAY,EAAE,MAAM,EAAE,eAAe,EAAE,MAAM,GAAG,IAAI;IAUlE,aAAa,CAAC,OAAO,EAAE,MAAM,GAAG,IAAI;IAWpC,wBAAwB,IAAI,IAAI;IAKhC,wBAAwB,IAAI,IAAI;IAKhC;;;;OAIG;IACH,WAAW,CAAC,IAAI,EAAE,QAAQ,EAAE,OAAO,CAAC,EAAE,MAAM,GAAG,IAAI;IAMnD,qFAAqF;IACrF,WAAW,IAAI,IAAI;IAQnB,4EAA4E;IAC5E,YAAY,IAAI,IAAI;IAQpB,gFAAgF;IAChF,WAAW,IAAI,IAAI;IAQnB,qBAAqB,IAAI,IAAI;CAI9B"}
1
+ {"version":3,"file":"orchestrator-panel-store.d.ts","sourceRoot":"","sources":["../../../src/sdk/components/orchestrator-panel-store.ts"],"names":[],"mappings":"AAGA,OAAO,KAAK,EAAE,WAAW,EAAiB,YAAY,EAAE,QAAQ,EAAE,MAAM,+BAA+B,CAAC;AAExG,KAAK,QAAQ,GAAG,MAAM,IAAI,CAAC;AAE3B,qBAAa,UAAU;IACrB,OAAO,SAAK;IACZ,YAAY,SAAM;IAClB,KAAK,SAAM;IACX,MAAM,SAAM;IACZ,QAAQ,EAAE,WAAW,EAAE,CAAM;IAC7B,cAAc,EAAE;QAAE,YAAY,EAAE,MAAM,CAAC;QAAC,eAAe,EAAE,MAAM,CAAA;KAAE,GAAG,IAAI,CAAQ;IAChF,UAAU,EAAE,MAAM,GAAG,IAAI,CAAQ;IACjC,iBAAiB,UAAS;IAC1B,WAAW,EAAE,CAAC,MAAM,IAAI,CAAC,GAAG,IAAI,CAAQ;IACxC,YAAY,EAAE,CAAC,MAAM,IAAI,CAAC,GAAG,IAAI,CAAQ;IAEzC,oEAAoE;IACpE,mBAAmB,SAAK;IAExB,0EAA0E;IAC1E,QAAQ,EAAE,QAAQ,CAAW;IAC7B,4FAA4F;IAC5F,aAAa,SAAM;IAEnB,OAAO,CAAC,SAAS,CAAuB;IAExC,SAAS,GAAI,IAAI,QAAQ,KAAG,CAAC,MAAM,IAAI,CAAC,CAGtC;IAEF,OAAO,CAAC,IAAI;IAKZ,eAAe,CACb,IAAI,EAAE,MAAM,EACZ,KAAK,EAAE,MAAM,EACb,QAAQ,EAAE,YAAY,EAAE,EACxB,MAAM,EAAE,MAAM,GACb,IAAI;IAuBP,YAAY,CAAC,IAAI,EAAE,MAAM,GAAG,IAAI;IAQhC,eAAe,CAAC,IAAI,EAAE,MAAM,GAAG,IAAI;IAQnC,WAAW,CAAC,IAAI,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,GAAG,IAAI;IAS9C,aAAa,CAAC,IAAI,EAAE,MAAM,GAAG,IAAI;IAQjC,aAAa,CAAC,IAAI,EAAE,MAAM,GAAG,IAAI;IAQjC,UAAU,CAAC,OAAO,EAAE,WAAW,GAAG,IAAI;IAKtC,aAAa,CAAC,YAAY,EAAE,MAAM,EAAE,eAAe,EAAE,MAAM,GAAG,IAAI;IAUlE,aAAa,CAAC,OAAO,EAAE,MAAM,GAAG,IAAI;IAWpC,wBAAwB,IAAI,IAAI;IAKhC,wBAAwB,IAAI,IAAI;IAKhC;;;;OAIG;IACH,WAAW,CAAC,IAAI,EAAE,QAAQ,EAAE,OAAO,CAAC,EAAE,MAAM,GAAG,IAAI;IAMnD,qFAAqF;IACrF,WAAW,IAAI,IAAI;IAQnB,4EAA4E;IAC5E,YAAY,IAAI,IAAI;IAQpB,gFAAgF;IAChF,WAAW,IAAI,IAAI;IAQnB,qBAAqB,IAAI,IAAI;CAI9B"}
@@ -1,4 +1,4 @@
1
- export type SessionStatus = "pending" | "running" | "complete" | "error";
1
+ export type SessionStatus = "pending" | "running" | "complete" | "error" | "awaiting_input";
2
2
  export type ViewMode = "graph" | "attached";
3
3
  export interface PanelSession {
4
4
  name: string;
@@ -1 +1 @@
1
- {"version":3,"file":"orchestrator-panel-types.d.ts","sourceRoot":"","sources":["../../../src/sdk/components/orchestrator-panel-types.ts"],"names":[],"mappings":"AAEA,MAAM,MAAM,aAAa,GAAG,SAAS,GAAG,SAAS,GAAG,UAAU,GAAG,OAAO,CAAC;AAEzE,MAAM,MAAM,QAAQ,GAAG,OAAO,GAAG,UAAU,CAAC;AAE5C,MAAM,WAAW,YAAY;IAC3B,IAAI,EAAE,MAAM,CAAC;IACb,OAAO,EAAE,MAAM,EAAE,CAAC;CACnB;AAED,MAAM,WAAW,YAAY;IAC3B,WAAW,EAAE,MAAM,CAAC;CACrB;AAED,MAAM,WAAW,WAAW;IAC1B,IAAI,EAAE,MAAM,CAAC;IACb,MAAM,EAAE,aAAa,CAAC;IACtB,OAAO,EAAE,MAAM,EAAE,CAAC;IAClB,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,SAAS,EAAE,MAAM,GAAG,IAAI,CAAC;IACzB,OAAO,EAAE,MAAM,GAAG,IAAI,CAAC;CACxB"}
1
+ {"version":3,"file":"orchestrator-panel-types.d.ts","sourceRoot":"","sources":["../../../src/sdk/components/orchestrator-panel-types.ts"],"names":[],"mappings":"AAEA,MAAM,MAAM,aAAa,GAAG,SAAS,GAAG,SAAS,GAAG,UAAU,GAAG,OAAO,GAAG,gBAAgB,CAAC;AAE5F,MAAM,MAAM,QAAQ,GAAG,OAAO,GAAG,UAAU,CAAC;AAE5C,MAAM,WAAW,YAAY;IAC3B,IAAI,EAAE,MAAM,CAAC;IACb,OAAO,EAAE,MAAM,EAAE,CAAC;CACnB;AAED,MAAM,WAAW,YAAY;IAC3B,WAAW,EAAE,MAAM,CAAC;CACrB;AAED,MAAM,WAAW,WAAW;IAC1B,IAAI,EAAE,MAAM,CAAC;IACb,MAAM,EAAE,aAAa,CAAC;IACtB,OAAO,EAAE,MAAM,EAAE,CAAC;IAClB,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,SAAS,EAAE,MAAM,GAAG,IAAI,CAAC;IACzB,OAAO,EAAE,MAAM,GAAG,IAAI,CAAC;CACxB"}
@@ -30,6 +30,8 @@ export declare class OrchestratorPanel {
30
30
  sessionSuccess(name: string): void;
31
31
  /** Mark a session as failed in the graph UI and display the error message. */
32
32
  sessionError(name: string, message: string): void;
33
+ sessionAwaitingInput(name: string): void;
34
+ sessionResumed(name: string): void;
33
35
  /** Dynamically add a new session node to the graph UI. */
34
36
  addSession(name: string, parents: string[]): void;
35
37
  /** Increment the background task counter (shown in the statusline footer). */
@@ -1 +1 @@
1
- {"version":3,"file":"orchestrator-panel.d.ts","sourceRoot":"","sources":["../../../src/sdk/components/orchestrator-panel.tsx"],"names":[],"mappings":"AAAA,sCAAsC;AACtC;;;GAGG;AAEH,OAAO,EAAqB,KAAK,WAAW,EAAE,MAAM,eAAe,CAAC;AAOpE,OAAO,KAAK,EAAE,YAAY,EAAE,YAAY,EAAE,MAAM,+BAA+B,CAAC;AAIhF,qBAAa,iBAAiB;IAC5B,OAAO,CAAC,KAAK,CAAa;IAC1B,OAAO,CAAC,QAAQ,CAAc;IAC9B,OAAO,CAAC,SAAS,CAAS;IAE1B,OAAO;IAsCP;;;;;OAKG;WACU,MAAM,CAAC,OAAO,EAAE,YAAY,GAAG,OAAO,CAAC,iBAAiB,CAAC;IAQtE,0EAA0E;IAC1E,MAAM,CAAC,kBAAkB,CACvB,QAAQ,EAAE,WAAW,EACrB,OAAO,EAAE,YAAY,GACpB,iBAAiB;IAOpB;;;OAGG;IACH,gBAAgB,CACd,IAAI,EAAE,MAAM,EACZ,KAAK,EAAE,MAAM,EACb,QAAQ,EAAE,YAAY,EAAE,EACxB,MAAM,EAAE,MAAM,GACb,IAAI;IAIP,iDAAiD;IACjD,YAAY,CAAC,IAAI,EAAE,MAAM,GAAG,IAAI;IAIhC,gEAAgE;IAChE,cAAc,CAAC,IAAI,EAAE,MAAM,GAAG,IAAI;IAIlC,8EAA8E;IAC9E,YAAY,CAAC,IAAI,EAAE,MAAM,EAAE,OAAO,EAAE,MAAM,GAAG,IAAI;IAIjD,0DAA0D;IAC1D,UAAU,CAAC,IAAI,EAAE,MAAM,EAAE,OAAO,EAAE,MAAM,EAAE,GAAG,IAAI;IAUjD,8EAA8E;IAC9E,qBAAqB,IAAI,IAAI;IAI7B,8EAA8E;IAC9E,sBAAsB,IAAI,IAAI;IAI9B,0EAA0E;IAC1E,cAAc,CAAC,YAAY,EAAE,MAAM,EAAE,eAAe,EAAE,MAAM,GAAG,IAAI;IAInE,+CAA+C;IAC/C,cAAc,CAAC,OAAO,EAAE,MAAM,GAAG,IAAI;IAIrC;;;OAGG;IACH,WAAW,IAAI,OAAO,CAAC,IAAI,CAAC;IAO5B;;;OAGG;IACH,YAAY,IAAI,OAAO,CAAC,IAAI,CAAC;IAM7B,yEAAyE;IACzE,OAAO,IAAI,IAAI;CAOhB"}
1
+ {"version":3,"file":"orchestrator-panel.d.ts","sourceRoot":"","sources":["../../../src/sdk/components/orchestrator-panel.tsx"],"names":[],"mappings":"AAAA,sCAAsC;AACtC;;;GAGG;AAEH,OAAO,EAAqB,KAAK,WAAW,EAAE,MAAM,eAAe,CAAC;AAOpE,OAAO,KAAK,EAAE,YAAY,EAAE,YAAY,EAAE,MAAM,+BAA+B,CAAC;AAIhF,qBAAa,iBAAiB;IAC5B,OAAO,CAAC,KAAK,CAAa;IAC1B,OAAO,CAAC,QAAQ,CAAc;IAC9B,OAAO,CAAC,SAAS,CAAS;IAE1B,OAAO;IAsCP;;;;;OAKG;WACU,MAAM,CAAC,OAAO,EAAE,YAAY,GAAG,OAAO,CAAC,iBAAiB,CAAC;IAQtE,0EAA0E;IAC1E,MAAM,CAAC,kBAAkB,CACvB,QAAQ,EAAE,WAAW,EACrB,OAAO,EAAE,YAAY,GACpB,iBAAiB;IAOpB;;;OAGG;IACH,gBAAgB,CACd,IAAI,EAAE,MAAM,EACZ,KAAK,EAAE,MAAM,EACb,QAAQ,EAAE,YAAY,EAAE,EACxB,MAAM,EAAE,MAAM,GACb,IAAI;IAIP,iDAAiD;IACjD,YAAY,CAAC,IAAI,EAAE,MAAM,GAAG,IAAI;IAIhC,gEAAgE;IAChE,cAAc,CAAC,IAAI,EAAE,MAAM,GAAG,IAAI;IAIlC,8EAA8E;IAC9E,YAAY,CAAC,IAAI,EAAE,MAAM,EAAE,OAAO,EAAE,MAAM,GAAG,IAAI;IAIjD,oBAAoB,CAAC,IAAI,EAAE,MAAM,GAAG,IAAI;IAIxC,cAAc,CAAC,IAAI,EAAE,MAAM,GAAG,IAAI;IAIlC,0DAA0D;IAC1D,UAAU,CAAC,IAAI,EAAE,MAAM,EAAE,OAAO,EAAE,MAAM,EAAE,GAAG,IAAI;IAUjD,8EAA8E;IAC9E,qBAAqB,IAAI,IAAI;IAI7B,8EAA8E;IAC9E,sBAAsB,IAAI,IAAI;IAI9B,0EAA0E;IAC1E,cAAc,CAAC,YAAY,EAAE,MAAM,EAAE,eAAe,EAAE,MAAM,GAAG,IAAI;IAInE,+CAA+C;IAC/C,cAAc,CAAC,OAAO,EAAE,MAAM,GAAG,IAAI;IAIrC;;;OAGG;IACH,WAAW,IAAI,OAAO,CAAC,IAAI,CAAC;IAO5B;;;OAGG;IACH,YAAY,IAAI,OAAO,CAAC,IAAI,CAAC;IAM7B,yEAAyE;IACzE,OAAO,IAAI,IAAI;CAOhB"}
@@ -1 +1 @@
1
- {"version":3,"file":"status-helpers.d.ts","sourceRoot":"","sources":["../../../src/sdk/components/status-helpers.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,kBAAkB,CAAC;AAEnD,wBAAgB,WAAW,CAAC,MAAM,EAAE,MAAM,EAAE,KAAK,EAAE,UAAU,GAAG,MAAM,CASrE;AAED,wBAAgB,WAAW,CAAC,MAAM,EAAE,MAAM,GAAG,MAAM,CAKlD;AAED,wBAAgB,UAAU,CAAC,MAAM,EAAE,MAAM,GAAG,MAAM,CAEjD;AAID,wBAAgB,WAAW,CAAC,EAAE,EAAE,MAAM,GAAG,MAAM,CAG9C"}
1
+ {"version":3,"file":"status-helpers.d.ts","sourceRoot":"","sources":["../../../src/sdk/components/status-helpers.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,kBAAkB,CAAC;AAEnD,wBAAgB,WAAW,CAAC,MAAM,EAAE,MAAM,EAAE,KAAK,EAAE,UAAU,GAAG,MAAM,CAUrE;AAED,wBAAgB,WAAW,CAAC,MAAM,EAAE,MAAM,GAAG,MAAM,CAKlD;AAED,wBAAgB,UAAU,CAAC,MAAM,EAAE,MAAM,GAAG,MAAM,CAEjD;AAID,wBAAgB,WAAW,CAAC,EAAE,EAAE,MAAM,GAAG,MAAM,CAG9C"}
@@ -55,6 +55,31 @@ export interface ClaudeSessionOptions {
55
55
  * ```
56
56
  */
57
57
  export declare function createClaudeSession(options: ClaudeSessionOptions): Promise<void>;
58
+ /**
59
+ * Returns true if the most recent assistant message contains an
60
+ * `AskUserQuestion` tool_use block that has not yet been resolved
61
+ * by a corresponding `tool_result` in a subsequent user message.
62
+ *
63
+ * Pure function — no side effects, safe to call from a watch loop.
64
+ *
65
+ * Exported as `_hasUnresolvedHILTool` for unit testing.
66
+ */
67
+ export declare function _hasUnresolvedHILTool(messages: SessionMessage[]): boolean;
68
+ /**
69
+ * Core HIL watcher loop — pure logic, dependency-injected for testability.
70
+ *
71
+ * Iterates an async iterable of "file change" events (each event triggers a
72
+ * transcript read via `readMessages`). Calls `onHIL(true)` when
73
+ * `_hasUnresolvedHILTool` first returns true, `onHIL(false)` when it returns
74
+ * false after having been true. The `wasHIL` guard prevents redundant
75
+ * callbacks on repeated events with the same HIL state. Read errors from
76
+ * `readMessages` are swallowed so a single corrupt JSONL write doesn't kill
77
+ * the watcher.
78
+ *
79
+ * Exported as `_runHILWatcher` for unit testing (event source and message
80
+ * reader are injected rather than hard-coded to `fs.watch` / `getSessionMessages`).
81
+ */
82
+ export declare function _runHILWatcher(events: AsyncIterable<unknown>, readMessages: () => Promise<SessionMessage[]>, onHIL: (waiting: boolean) => void): Promise<void>;
58
83
  export interface ClaudeQueryOptions {
59
84
  /** tmux pane ID where Claude is running */
60
85
  paneId: string;
@@ -68,6 +93,12 @@ export interface ClaudeQueryOptions {
68
93
  maxSubmitRounds?: number;
69
94
  /** Timeout in ms waiting for pane to be ready before sending (default: 30s) */
70
95
  readyTimeoutMs?: number;
96
+ /**
97
+ * Called when the agent's human-in-the-loop state changes.
98
+ * `waiting=true` → AskUserQuestion is pending (agent blocked on user input).
99
+ * `waiting=false` → AskUserQuestion was resolved (agent resumed processing).
100
+ */
101
+ onHIL?: (waiting: boolean) => void;
71
102
  }
72
103
  /**
73
104
  * Extract text content from assistant messages in a transcript slice.
@@ -145,7 +176,8 @@ export declare class ClaudeSessionWrapper {
145
176
  readonly paneId: string;
146
177
  readonly sessionId: string;
147
178
  private readonly defaults;
148
- constructor(paneId: string, sessionId: string, defaults?: ClaudeQueryDefaults);
179
+ private readonly onHIL;
180
+ constructor(paneId: string, sessionId: string, defaults?: ClaudeQueryDefaults, onHIL?: (waiting: boolean) => void);
149
181
  /** Send a prompt to Claude and wait for the response. */
150
182
  query(prompt: string, opts?: Partial<ClaudeQueryDefaults & SDKOptions>): Promise<SessionMessage[]>;
151
183
  /** Noop — for API symmetry with CopilotSession.disconnect(). */
@@ -1 +1 @@
1
- {"version":3,"file":"claude.d.ts","sourceRoot":"","sources":["../../../src/sdk/providers/claude.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"claude.d.ts","sourceRoot":"","sources":["../../../src/sdk/providers/claude.ts"],"names":[],"mappings":"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"}
@@ -68,5 +68,93 @@ export declare function hasContent(value: unknown): value is {
68
68
  content: string;
69
69
  };
70
70
  export declare function renderMessagesToText(messages: SavedMessage[]): string;
71
+ /**
72
+ * Minimal Copilot session surface required by `wrapCopilotSend()`.
73
+ * Uses a generic `on` signature to remain compatible with both the real
74
+ * CopilotSession and lightweight test mocks.
75
+ */
76
+ export interface CopilotSendSessionSurface {
77
+ on(eventType: string, handler: (event: {
78
+ data?: unknown;
79
+ }) => void): () => void;
80
+ }
81
+ /**
82
+ * Wraps a Copilot session's `send()` to block until `session.idle` fires.
83
+ *
84
+ * Copilot's `send()` is fire-and-forget — it returns immediately after
85
+ * queuing the message. This wrapper blocks the returned promise until the
86
+ * session emits `session.idle` (turn complete) or `session.error`.
87
+ *
88
+ * HIL detection for Copilot is handled separately by
89
+ * `watchCopilotSessionForHIL()`, which subscribes to the session's
90
+ * `tool.execution_start` / `tool.execution_complete` events for the
91
+ * `ask_user` built-in tool. Those events fire regardless of whether
92
+ * an `onUserInputRequest` handler is registered, so we can detect HIL
93
+ * via native SDK events while the CLI continues to handle user input
94
+ * locally in the tmux pane.
95
+ *
96
+ * Exported for unit testing.
97
+ */
98
+ export declare function wrapCopilotSend<O, R>(session: CopilotSendSessionSurface, nativeSend: (options: O) => Promise<R>): (options: O) => Promise<R>;
99
+ /**
100
+ * Minimal shape of an event as produced by the OpenCode v2 SDK event stream.
101
+ * Using a structural interface rather than the SDK's generated union type keeps
102
+ * this helper independently unit-testable with plain objects.
103
+ *
104
+ * `sessionID` is optional because many OpenCode event types (e.g.
105
+ * `file.edited`, `session.compacted`) carry properties without that field.
106
+ * The `watchOpencodeStreamForHIL` implementation guards with a runtime check.
107
+ */
108
+ export interface OpenCodeHILEvent {
109
+ type: string;
110
+ properties: {
111
+ sessionID?: string;
112
+ [key: string]: unknown;
113
+ };
114
+ }
115
+ /**
116
+ * Consume an OpenCode SSE event stream and call `onHIL` whenever the session
117
+ * with `sessionId` enters or exits a human-in-the-loop (HIL) state:
118
+ *
119
+ * - `question.asked` → `onHIL(true)` (agent awaiting user input)
120
+ * - `question.replied` → `onHIL(false)` (user answered, agent resumes)
121
+ * - `question.rejected` → `onHIL(false)` (user dismissed, agent resumes)
122
+ *
123
+ * Events for other sessions are silently ignored. The function returns when
124
+ * the stream is exhausted (i.e. the server closes the connection).
125
+ *
126
+ * Exported for unit testing.
127
+ */
128
+ export declare function watchOpencodeStreamForHIL(stream: AsyncIterable<OpenCodeHILEvent>, sessionId: string, onHIL: (waiting: boolean) => void): Promise<void>;
129
+ /**
130
+ * Minimal Copilot session surface required by `watchCopilotSessionForHIL()`.
131
+ * A structural `on()` signature keeps this helper independently unit-testable
132
+ * with plain objects and compatible with both the real CopilotSession and
133
+ * test mocks.
134
+ */
135
+ export interface CopilotHILSessionSurface {
136
+ on(eventType: string, handler: (event: {
137
+ data?: unknown;
138
+ }) => void): () => void;
139
+ }
140
+ /**
141
+ * Subscribe to a Copilot session's tool-execution events to track HIL state
142
+ * for the `ask_user` built-in tool:
143
+ *
144
+ * - `tool.execution_start` with `toolName === "ask_user"` → `onHIL(true)`
145
+ * - `tool.execution_complete` with matching `toolCallId` → `onHIL(false)`
146
+ *
147
+ * These events fire regardless of whether an `onUserInputRequest` handler is
148
+ * registered, so we can detect HIL without providing one — letting the CLI
149
+ * keep its native tmux-pane dialog.
150
+ *
151
+ * Overlapping `ask_user` invocations are tracked by `toolCallId` so
152
+ * `onHIL(false)` only fires after the last active request resolves.
153
+ *
154
+ * Returns an unsubscribe function that removes both listeners.
155
+ *
156
+ * Exported for unit testing.
157
+ */
158
+ export declare function watchCopilotSessionForHIL(session: CopilotHILSessionSurface, onHIL: (waiting: boolean) => void): () => void;
71
159
  export declare function runOrchestrator(): Promise<void>;
72
160
  //# sourceMappingURL=executor.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"executor.d.ts","sourceRoot":"","sources":["../../../src/sdk/runtime/executor.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;GAcG;AAKH,OAAO,KAAK,EACV,kBAAkB,EAMlB,SAAS,EAET,YAAY,EAMb,MAAM,aAAa,CAAC;AAqErB,OAAO,EAAE,YAAY,EAAE,MAAM,cAAc,CAAC;AAa5C,MAAM,WAAW,kBAAkB;IACjC,uCAAuC;IACvC,UAAU,EAAE,kBAAkB,CAAC;IAC/B,iBAAiB;IACjB,KAAK,EAAE,SAAS,CAAC;IACjB;;;;;OAKG;IACH,MAAM,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;IAChC,qEAAqE;IACrE,YAAY,EAAE,MAAM,CAAC;IACrB,qCAAqC;IACrC,WAAW,CAAC,EAAE,MAAM,CAAC;CACtB;AAuID;;;;;;GAMG;AACH,wBAAgB,OAAO,CAAC,CAAC,EAAE,MAAM,GAAG,MAAM,CAKzC;AAED;;;;;GAKG;AACH,wBAAgB,OAAO,CAAC,CAAC,EAAE,MAAM,GAAG,MAAM,CAMzC;AAED;;;;;;GAMG;AACH,wBAAgB,cAAc,CAC5B,GAAG,EAAE,MAAM,GAAG,SAAS,GACtB,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAgBxB;AAMD;;;;;;GAMG;AACH,wBAAsB,eAAe,CACnC,OAAO,EAAE,kBAAkB,GAC1B,OAAO,CAAC,IAAI,CAAC,CAyEf;AAcD,gGAAgG;AAChG,wBAAgB,UAAU,CAAC,KAAK,EAAE,OAAO,GAAG,KAAK,IAAI;IAAE,OAAO,EAAE,MAAM,CAAA;CAAE,CAOvE;AAED,wBAAgB,oBAAoB,CAAC,QAAQ,EAAE,YAAY,EAAE,GAAG,MAAM,CAkDrE;AAulBD,wBAAsB,eAAe,IAAI,OAAO,CAAC,IAAI,CAAC,CA8JrD"}
1
+ {"version":3,"file":"executor.d.ts","sourceRoot":"","sources":["../../../src/sdk/runtime/executor.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;GAcG;AAKH,OAAO,KAAK,EACV,kBAAkB,EAMlB,SAAS,EAET,YAAY,EAMb,MAAM,aAAa,CAAC;AAqErB,OAAO,EAAE,YAAY,EAAE,MAAM,cAAc,CAAC;AAa5C,MAAM,WAAW,kBAAkB;IACjC,uCAAuC;IACvC,UAAU,EAAE,kBAAkB,CAAC;IAC/B,iBAAiB;IACjB,KAAK,EAAE,SAAS,CAAC;IACjB;;;;;OAKG;IACH,MAAM,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;IAChC,qEAAqE;IACrE,YAAY,EAAE,MAAM,CAAC;IACrB,qCAAqC;IACrC,WAAW,CAAC,EAAE,MAAM,CAAC;CACtB;AAuID;;;;;;GAMG;AACH,wBAAgB,OAAO,CAAC,CAAC,EAAE,MAAM,GAAG,MAAM,CAKzC;AAED;;;;;GAKG;AACH,wBAAgB,OAAO,CAAC,CAAC,EAAE,MAAM,GAAG,MAAM,CAMzC;AAED;;;;;;GAMG;AACH,wBAAgB,cAAc,CAC5B,GAAG,EAAE,MAAM,GAAG,SAAS,GACtB,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAgBxB;AAMD;;;;;;GAMG;AACH,wBAAsB,eAAe,CACnC,OAAO,EAAE,kBAAkB,GAC1B,OAAO,CAAC,IAAI,CAAC,CAyEf;AAcD,gGAAgG;AAChG,wBAAgB,UAAU,CAAC,KAAK,EAAE,OAAO,GAAG,KAAK,IAAI;IAAE,OAAO,EAAE,MAAM,CAAA;CAAE,CAOvE;AAED,wBAAgB,oBAAoB,CAAC,QAAQ,EAAE,YAAY,EAAE,GAAG,MAAM,CAkDrE;AAOD;;;;GAIG;AACH,MAAM,WAAW,yBAAyB;IACxC,EAAE,CAAC,SAAS,EAAE,MAAM,EAAE,OAAO,EAAE,CAAC,KAAK,EAAE;QAAE,IAAI,CAAC,EAAE,OAAO,CAAA;KAAE,KAAK,IAAI,GAAG,MAAM,IAAI,CAAC;CACjF;AAED;;;;;;;;;;;;;;;;GAgBG;AACH,wBAAgB,eAAe,CAAC,CAAC,EAAE,CAAC,EAClC,OAAO,EAAE,yBAAyB,EAClC,UAAU,EAAE,CAAC,OAAO,EAAE,CAAC,KAAK,OAAO,CAAC,CAAC,CAAC,GACrC,CAAC,OAAO,EAAE,CAAC,KAAK,OAAO,CAAC,CAAC,CAAC,CAuB5B;AAED;;;;;;;;GAQG;AACH,MAAM,WAAW,gBAAgB;IAC/B,IAAI,EAAE,MAAM,CAAC;IACb,UAAU,EAAE;QAAE,SAAS,CAAC,EAAE,MAAM,CAAC;QAAC,CAAC,GAAG,EAAE,MAAM,GAAG,OAAO,CAAA;KAAE,CAAC;CAC5D;AAED;;;;;;;;;;;;GAYG;AACH,wBAAsB,yBAAyB,CAC7C,MAAM,EAAE,aAAa,CAAC,gBAAgB,CAAC,EACvC,SAAS,EAAE,MAAM,EACjB,KAAK,EAAE,CAAC,OAAO,EAAE,OAAO,KAAK,IAAI,GAChC,OAAO,CAAC,IAAI,CAAC,CAef;AAED;;;;;GAKG;AACH,MAAM,WAAW,wBAAwB;IACvC,EAAE,CACA,SAAS,EAAE,MAAM,EACjB,OAAO,EAAE,CAAC,KAAK,EAAE;QAAE,IAAI,CAAC,EAAE,OAAO,CAAA;KAAE,KAAK,IAAI,GAC3C,MAAM,IAAI,CAAC;CACf;AAED;;;;;;;;;;;;;;;;;GAiBG;AACH,wBAAgB,yBAAyB,CACvC,OAAO,EAAE,wBAAwB,EACjC,KAAK,EAAE,CAAC,OAAO,EAAE,OAAO,KAAK,IAAI,GAChC,MAAM,IAAI,CA0BZ;AA0mBD,wBAAsB,eAAe,IAAI,OAAO,CAAC,IAAI,CAAC,CA8JrD"}
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../../../../src/sdk/workflows/builtin/deep-research-codebase/claude/index.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA6DG;;AA4BH,wBA2Oa"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../../../../src/sdk/workflows/builtin/deep-research-codebase/claude/index.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA6DG;;AA4BH,wBA4Na"}
@@ -7,9 +7,13 @@
7
7
  * - {@link MAX_LOOPS} iterations have completed, OR
8
8
  * - Two parallel reviewer passes both return zero findings.
9
9
  *
10
- * The reviewer stages use the Claude Agent SDK's structured output
11
- * (`outputFormat`) to guarantee the review result matches the
12
- * {@link ReviewResultSchema} no manual JSON parsing required.
10
+ * The reviewer stages run the `reviewer` sub-agent in a visible TUI via the
11
+ * `--agent reviewer` chatFlag, then parse the JSON review out of the
12
+ * assistant text with {@link parseReviewResult}. The prompt enumerates the
13
+ * {@link ReviewResultSchema} fields so the model emits matching JSON. We
14
+ * deliberately avoid invoking the Claude Agent SDK's `query()` from inside a
15
+ * non-headless stage — that would spawn a TUI pane that goes unused while
16
+ * the SDK runs in-process (see workflow-creator skill, failure-modes F17).
13
17
  *
14
18
  * Run: atomic workflow -n ralph -a claude "<your spec>"
15
19
  */
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../../../../src/sdk/workflows/builtin/ralph/claude/index.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;GAcG;;AAkEH,wBAiLa"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../../../../src/sdk/workflows/builtin/ralph/claude/index.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;GAkBG;;AAmCH,wBAkMa"}
@@ -1 +1 @@
1
- {"version":3,"file":"definitions.d.ts","sourceRoot":"","sources":["../../../src/services/config/definitions.ts"],"names":[],"mappings":"AAAA;;GAEG;AAKH,MAAM,WAAW,WAAW;IAC1B,iCAAiC;IACjC,IAAI,EAAE,MAAM,CAAC;IACb,mCAAmC;IACnC,GAAG,EAAE,MAAM,CAAC;IACZ,kEAAkE;IAClE,UAAU,EAAE,MAAM,EAAE,CAAC;IACrB,qFAAqF;IACrF,QAAQ,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;IACjC,0CAA0C;IAC1C,MAAM,EAAE,MAAM,CAAC;IACf,wCAAwC;IACxC,WAAW,EAAE,MAAM,CAAC;IACpB,yDAAyD;IACzD,OAAO,EAAE,MAAM,EAAE,CAAC;IAClB,qEAAqE;IACrE,gBAAgB,EAAE,KAAK,CAAC;QACtB,MAAM,EAAE,MAAM,CAAC;QACf,WAAW,EAAE,MAAM,CAAC;QACpB,KAAK,EAAE,OAAO,CAAC;KAChB,CAAC,CAAC;CACJ;AAED,QAAA,MAAM,UAAU,4CAA6C,CAAC;AAC9D,MAAM,MAAM,QAAQ,GAAG,CAAC,OAAO,UAAU,CAAC,CAAC,MAAM,CAAC,CAAC;AAEnD,eAAO,MAAM,YAAY,EAAE,MAAM,CAAC,QAAQ,EAAE,WAAW,CA4DtD,CAAC;AAEF;;;;;;;GAOG;AACH,MAAM,WAAW,iBAAiB;IAChC,SAAS,CAAC,EAAE,MAAM,EAAE,CAAC;IACrB,OAAO,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;CAClC;AAED,wBAAgB,YAAY,CAAC,GAAG,EAAE,MAAM,GAAG,GAAG,IAAI,QAAQ,CAEzD;AAED,wBAAgB,cAAc,CAAC,GAAG,EAAE,QAAQ,GAAG,WAAW,CAEzD;AAED,wBAAgB,YAAY,IAAI,QAAQ,EAAE,CAEzC;AAED;;GAEG;AAEH,6BAA6B;AAC7B,QAAA,MAAM,QAAQ,gCAAiC,CAAC;AAEhD,oEAAoE;AACpE,MAAM,MAAM,iBAAiB,GAAG,CAAC,OAAO,QAAQ,CAAC,CAAC,MAAM,CAAC,CAAC;AAE1D,MAAM,WAAW,SAAS;IACxB,+BAA+B;IAC/B,WAAW,EAAE,MAAM,CAAC;IACpB,mCAAmC;IACnC,OAAO,EAAE,MAAM,CAAC;IAChB,+CAA+C;IAC/C,YAAY,EAAE,MAAM,CAAC;IACrB,8EAA8E;IAC9E,SAAS,EAAE,MAAM,CAAC;CACnB;AAED,eAAO,MAAM,UAAU,EAAE,MAAM,CAAC,iBAAiB,EAAE,SAAS,CAa3D,CAAC;AAEF;;;;;;;;GAQG;AACH,eAAO,MAAM,kBAAkB,EAAE,MAAM,CAAC,iBAAiB,EAAE,SAAS,MAAM,EAAE,CAIzE,CAAC;AAEJ,4EAA4E;AAC5E,eAAO,MAAM,cAAc,EAAE,SAAS,MAAM,EAG3C,CAAC;AAEF;;GAEG;AACH,wBAAgB,UAAU,IAAI,iBAAiB,EAAE,CAEhD;AAED;;GAEG;AACH,wBAAgB,UAAU,CAAC,GAAG,EAAE,MAAM,GAAG,GAAG,IAAI,iBAAiB,CAEhE;AAED;;;;;GAKG;AACH,wBAAsB,aAAa,CACjC,WAAW,EAAE,MAAM,GAClB,OAAO,CAAC,iBAAiB,GAAG,IAAI,CAAC,CAWnC"}
1
+ {"version":3,"file":"definitions.d.ts","sourceRoot":"","sources":["../../../src/services/config/definitions.ts"],"names":[],"mappings":"AAAA;;GAEG;AAKH,MAAM,WAAW,WAAW;IAC1B,iCAAiC;IACjC,IAAI,EAAE,MAAM,CAAC;IACb,mCAAmC;IACnC,GAAG,EAAE,MAAM,CAAC;IACZ,kEAAkE;IAClE,UAAU,EAAE,MAAM,EAAE,CAAC;IACrB,qFAAqF;IACrF,QAAQ,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;IACjC,0CAA0C;IAC1C,MAAM,EAAE,MAAM,CAAC;IACf,wCAAwC;IACxC,WAAW,EAAE,MAAM,CAAC;IACpB,yDAAyD;IACzD,OAAO,EAAE,MAAM,EAAE,CAAC;IAClB,qEAAqE;IACrE,gBAAgB,EAAE,KAAK,CAAC;QACtB,MAAM,EAAE,MAAM,CAAC;QACf,WAAW,EAAE,MAAM,CAAC;QACpB,KAAK,EAAE,OAAO,CAAC;KAChB,CAAC,CAAC;CACJ;AAED,QAAA,MAAM,UAAU,4CAA6C,CAAC;AAC9D,MAAM,MAAM,QAAQ,GAAG,CAAC,OAAO,UAAU,CAAC,CAAC,MAAM,CAAC,CAAC;AAEnD,eAAO,MAAM,YAAY,EAAE,MAAM,CAAC,QAAQ,EAAE,WAAW,CAiEtD,CAAC;AAEF;;;;;;;GAOG;AACH,MAAM,WAAW,iBAAiB;IAChC,SAAS,CAAC,EAAE,MAAM,EAAE,CAAC;IACrB,OAAO,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;CAClC;AAED,wBAAgB,YAAY,CAAC,GAAG,EAAE,MAAM,GAAG,GAAG,IAAI,QAAQ,CAEzD;AAED,wBAAgB,cAAc,CAAC,GAAG,EAAE,QAAQ,GAAG,WAAW,CAEzD;AAED,wBAAgB,YAAY,IAAI,QAAQ,EAAE,CAEzC;AAED;;GAEG;AAEH,6BAA6B;AAC7B,QAAA,MAAM,QAAQ,gCAAiC,CAAC;AAEhD,oEAAoE;AACpE,MAAM,MAAM,iBAAiB,GAAG,CAAC,OAAO,QAAQ,CAAC,CAAC,MAAM,CAAC,CAAC;AAE1D,MAAM,WAAW,SAAS;IACxB,+BAA+B;IAC/B,WAAW,EAAE,MAAM,CAAC;IACpB,mCAAmC;IACnC,OAAO,EAAE,MAAM,CAAC;IAChB,+CAA+C;IAC/C,YAAY,EAAE,MAAM,CAAC;IACrB,8EAA8E;IAC9E,SAAS,EAAE,MAAM,CAAC;CACnB;AAED,eAAO,MAAM,UAAU,EAAE,MAAM,CAAC,iBAAiB,EAAE,SAAS,CAa3D,CAAC;AAEF;;;;;;;;GAQG;AACH,eAAO,MAAM,kBAAkB,EAAE,MAAM,CAAC,iBAAiB,EAAE,SAAS,MAAM,EAAE,CAIzE,CAAC;AAEJ,4EAA4E;AAC5E,eAAO,MAAM,cAAc,EAAE,SAAS,MAAM,EAG3C,CAAC;AAEF;;GAEG;AACH,wBAAgB,UAAU,IAAI,iBAAiB,EAAE,CAEhD;AAED;;GAEG;AACH,wBAAgB,UAAU,CAAC,GAAG,EAAE,MAAM,GAAG,GAAG,IAAI,iBAAiB,CAEhE;AAED;;;;;GAKG;AACH,wBAAsB,aAAa,CACjC,WAAW,EAAE,MAAM,GAClB,OAAO,CAAC,iBAAiB,GAAG,IAAI,CAAC,CAWnC"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@bastani/atomic",
3
- "version": "0.5.16-0",
3
+ "version": "0.5.17-0",
4
4
  "description": "Configuration management CLI and SDK for coding agents",
5
5
  "type": "module",
6
6
  "license": "MIT",
@@ -68,17 +68,17 @@
68
68
  "devDependencies": {
69
69
  "@types/bun": "^1.3.12",
70
70
  "@types/react": "^19.2.14",
71
- "lefthook": "^2.1.5",
71
+ "lefthook": "^2.1.6",
72
72
  "oxlint": "^1.60.0",
73
73
  "typescript": "^6.0.2",
74
74
  "typescript-language-server": "^5.1.3"
75
75
  },
76
76
  "dependencies": {
77
- "@anthropic-ai/claude-agent-sdk": "^0.2.108",
77
+ "@anthropic-ai/claude-agent-sdk": "^0.2.111",
78
78
  "@clack/prompts": "^1.2.0",
79
79
  "@commander-js/extra-typings": "^14.0.0",
80
80
  "@github/copilot-sdk": "^0.2.2",
81
- "@opencode-ai/sdk": "^1.4.3",
81
+ "@opencode-ai/sdk": "^1.4.6",
82
82
  "@opentui/core": "^0.1.99",
83
83
  "@opentui/react": "^0.1.99",
84
84
  "commander": "^14.0.3",
@@ -87,6 +87,6 @@
87
87
  "zod": "^4.3.6"
88
88
  },
89
89
  "peerDependencies": {
90
- "react": ">=19.0.0"
90
+ "react": "^19.2.5"
91
91
  }
92
92
  }
@@ -1,8 +1,22 @@
1
1
  import { join } from "node:path";
2
+ import { homedir } from "node:os";
2
3
  import { AGENT_CONFIG, type AgentKey } from "../../../services/config/index.ts";
3
4
  import { pathExists } from "../../../services/system/copy.ts";
4
5
  import { syncJsonFile } from "../../../lib/merge.ts";
5
6
 
7
+ /**
8
+ * Resolve an onboarding destination path. A leading `~/` is expanded to
9
+ * the user's home directory so providers can target global config roots
10
+ * (e.g. `~/.claude/settings.json`); anything else resolves against the
11
+ * project root.
12
+ */
13
+ function resolveDestination(destination: string, projectRoot: string): string {
14
+ if (destination === "~" || destination.startsWith("~/")) {
15
+ return join(homedir(), destination.slice(1));
16
+ }
17
+ return join(projectRoot, destination);
18
+ }
19
+
6
20
  export async function applyManagedOnboardingFiles(
7
21
  agentKey: AgentKey,
8
22
  projectRoot: string,
@@ -16,7 +30,10 @@ export async function applyManagedOnboardingFiles(
16
30
  continue;
17
31
  }
18
32
 
19
- const destinationPath = join(projectRoot, managedFile.destination);
33
+ const destinationPath = resolveDestination(
34
+ managedFile.destination,
35
+ projectRoot,
36
+ );
20
37
  await syncJsonFile(sourcePath, destinationPath, managedFile.merge);
21
38
  }
22
39
  }
@@ -32,7 +49,7 @@ export async function hasProjectOnboardingFiles(
32
49
 
33
50
  const checks = await Promise.all(
34
51
  onboardingFiles.map((managedFile) =>
35
- pathExists(join(projectRoot, managedFile.destination))
52
+ pathExists(resolveDestination(managedFile.destination, projectRoot))
36
53
  ),
37
54
  );
38
55
  return checks.every(Boolean);
@@ -19,7 +19,7 @@ export function Header() {
19
19
  const storeVersion = useStoreVersion(store);
20
20
 
21
21
  const counts = useMemo(() => {
22
- const c: Record<SessionStatus, number> = { complete: 0, running: 0, pending: 0, error: 0 };
22
+ const c: Record<SessionStatus, number> = { complete: 0, running: 0, pending: 0, error: 0, awaiting_input: 0 };
23
23
  for (const s of store.sessions) c[s.status]++;
24
24
  return c;
25
25
  }, [storeVersion]);
@@ -50,6 +50,7 @@ export function Header() {
50
50
  <box flexGrow={1} justifyContent="flex-end" flexDirection="row" gap={2}>
51
51
  <CountBadge color={theme.success} icon={"\u2713"} count={counts.complete} />
52
52
  <CountBadge color={theme.warning} icon={"\u25CF"} count={counts.running} />
53
+ <CountBadge color={theme.info} icon={"?"} count={counts.awaiting_input} />
53
54
  <CountBadge color={theme.textDim} icon={"\u25CB"} count={counts.pending} />
54
55
  <CountBadge color={theme.error} icon={"\u2717"} count={counts.error} />
55
56
  </box>
@@ -152,7 +152,8 @@ export function computeLayout(sessions: SessionData[]): LayoutResult {
152
152
 
153
153
  const rowH: Record<number, number> = {};
154
154
  for (const n of Object.values(map)) {
155
- rowH[n.depth] = Math.max(rowH[n.depth] ?? 0, NODE_H);
155
+ const nodeHeight = n.status === "awaiting_input" ? 6 : NODE_H;
156
+ rowH[n.depth] = Math.max(rowH[n.depth] ?? 0, nodeHeight);
156
157
  }
157
158
 
158
159
  function yAt(d: number): number {
@@ -21,6 +21,7 @@ export const NodeCard = React.memo(function NodeCard({
21
21
  const sc = statusColor(node.status, theme);
22
22
  const isPending = node.status === "pending";
23
23
  const isRunning = node.status === "running";
24
+ const isAwaitingInput = node.status === "awaiting_input";
24
25
 
25
26
  // Border: running nodes smoothly pulse, others show status color
26
27
  let borderCol: string;
@@ -29,6 +30,11 @@ export const NodeCard = React.memo(function NodeCard({
29
30
  borderCol = focused
30
31
  ? lerpColor(theme.warning, "#ffffff", 0.2)
31
32
  : lerpColor(theme.border, theme.warning, t);
33
+ } else if (isAwaitingInput) {
34
+ const t = (Math.sin((pulsePhase / 32) * Math.PI * 2 - Math.PI / 2) + 1) / 2;
35
+ borderCol = focused
36
+ ? lerpColor(theme.info, "#ffffff", 0.2)
37
+ : lerpColor(theme.border, theme.info, t);
32
38
  } else if (isPending) {
33
39
  borderCol = focused ? sc : theme.borderActive;
34
40
  } else {
@@ -64,6 +70,16 @@ export const NodeCard = React.memo(function NodeCard({
64
70
  <box alignItems="center">
65
71
  <text fg={durCol}>{duration}</text>
66
72
  </box>
73
+ {isAwaitingInput && (
74
+ <>
75
+ <box alignItems="center">
76
+ <text fg={theme.info}>waiting for response</text>
77
+ </box>
78
+ <box alignItems="center">
79
+ <text fg={theme.textDim}>↵ enter to respond</text>
80
+ </box>
81
+ </>
82
+ )}
67
83
  </box>
68
84
  );
69
85
  });