@bastani/atomic 0.8.14-0 → 0.8.15-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 (50) hide show
  1. package/CHANGELOG.md +35 -0
  2. package/README.md +0 -8
  3. package/dist/builtin/intercom/package.json +1 -1
  4. package/dist/builtin/mcp/CHANGELOG.md +3 -0
  5. package/dist/builtin/mcp/index.ts +4 -8
  6. package/dist/builtin/mcp/package.json +1 -1
  7. package/dist/builtin/subagents/package.json +1 -1
  8. package/dist/builtin/subagents/skills/tmux/SKILL.md +220 -0
  9. package/dist/builtin/subagents/skills/tmux/scripts/find-sessions.sh +112 -0
  10. package/dist/builtin/subagents/skills/tmux/scripts/wait-for-text.sh +83 -0
  11. package/dist/builtin/web-access/package.json +1 -1
  12. package/dist/builtin/workflows/CHANGELOG.md +10 -1
  13. package/dist/builtin/workflows/README.md +3 -1
  14. package/dist/builtin/workflows/builtin/ralph.ts +222 -295
  15. package/dist/builtin/workflows/package.json +1 -1
  16. package/dist/builtin/workflows/src/extension/background-ui-adapter.ts +20 -11
  17. package/dist/builtin/workflows/src/extension/index.ts +1 -0
  18. package/dist/builtin/workflows/src/extension/status-writer.ts +18 -3
  19. package/dist/builtin/workflows/src/runs/background/runner.ts +8 -10
  20. package/dist/builtin/workflows/src/runs/foreground/executor.ts +484 -91
  21. package/dist/builtin/workflows/src/runs/foreground/stage-control-registry.ts +13 -2
  22. package/dist/builtin/workflows/src/runs/foreground/stage-runner.ts +41 -15
  23. package/dist/builtin/workflows/src/runs/shared/graph-inference.ts +31 -0
  24. package/dist/builtin/workflows/src/runs/shared/prompt-callsite.ts +98 -0
  25. package/dist/builtin/workflows/src/shared/persistence-restore.ts +3 -1
  26. package/dist/builtin/workflows/src/shared/persistence-session-entries.ts +4 -0
  27. package/dist/builtin/workflows/src/shared/store-types.ts +12 -1
  28. package/dist/builtin/workflows/src/shared/store.ts +77 -3
  29. package/dist/builtin/workflows/src/tui/graph-view.ts +17 -1
  30. package/dist/builtin/workflows/src/tui/prompt-card.ts +185 -30
  31. package/dist/builtin/workflows/src/tui/stage-chat-view.ts +386 -21
  32. package/docs/changelog.mdx +41 -14
  33. package/docs/docs.json +1 -0
  34. package/docs/extensions.md +19 -19
  35. package/docs/images/workflow-input-picker.png +0 -0
  36. package/docs/images/workflow-list.png +0 -0
  37. package/docs/index.md +33 -27
  38. package/docs/providers.md +2 -2
  39. package/docs/quickstart.md +15 -15
  40. package/docs/sdk.md +8 -8
  41. package/docs/sessions.md +5 -5
  42. package/docs/settings.md +27 -1
  43. package/docs/skills.md +2 -2
  44. package/docs/subagents.md +157 -0
  45. package/docs/usage.md +7 -7
  46. package/docs/windows.md +8 -0
  47. package/docs/workflows.md +62 -9
  48. package/package.json +2 -1
  49. package/docs/images/doom-extension.png +0 -0
  50. package/docs/images/exy.png +0 -3
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@bastani/workflows",
3
- "version": "0.8.14-0",
3
+ "version": "0.8.15-0",
4
4
  "private": true,
5
5
  "description": "Atomic extension for multi-stage workflow authoring and execution.",
6
6
  "contributors": [
@@ -1,9 +1,11 @@
1
1
  /**
2
- * Background workflow HIL adapter — bridges `ctx.ui.input/confirm/select/editor`
3
- * to store-backed pending prompts instead of pi.ui modal dialogs.
2
+ * Legacy background workflow HIL adapter — bridges
3
+ * `ctx.ui.input/confirm/select/editor` to run-level store-backed pending
4
+ * prompts instead of pi.ui modal dialogs.
4
5
  *
5
- * Detached runs use this adapter so the main chat editor stays usable while
6
- * a workflow is in flight. HIL surfaces through the graph viewer overlay:
6
+ * Normal detached workflow runs now use executor-owned synthetic prompt nodes
7
+ * backed by `StageSnapshot.pendingPrompt`; this adapter remains for tests and
8
+ * non-executor fallback callers that still need the run-level graph overlay:
7
9
  *
8
10
  * 1. Stage calls `ctx.ui.editor(prefill)`
9
11
  * 2. Adapter records a `PendingPrompt` on the run via the store
@@ -17,6 +19,10 @@
17
19
  * rejects via `recordRunEnd` so the executor can finalise cleanly — no leaked
18
20
  * pending promises.
19
21
  *
22
+ * @internal Legacy fallback retained for tests and non-executor callers.
23
+ * TODO(workflows): delete after all tests and fallback entrypoints migrate to
24
+ * executor-owned synthetic prompt nodes.
25
+ *
20
26
  * cross-ref:
21
27
  * src/shared/store-types.ts PendingPrompt
22
28
  * src/shared/store.ts recordPendingPrompt / resolvePendingPrompt / awaitPendingPrompt
@@ -111,13 +117,13 @@ function fallbackForKind(descriptor: PromptDescriptor): unknown {
111
117
  }
112
118
 
113
119
  /**
114
- * Build a `WorkflowUIAdapter` whose methods record prompts on `runId` via
115
- * the store and await user response through the graph viewer.
120
+ * Build a legacy `WorkflowUIAdapter` whose methods record prompts on `runId`
121
+ * via the store and await user response through the graph viewer overlay.
116
122
  *
117
- * This is the only HIL surface a workflow body sees — `pi.ui.editor`,
118
- * `pi.ui.confirm`, etc. are intentionally never invoked from inside a run.
119
- * The chat editor stays free; the user attends to prompts via F2 / the
120
- * `/workflow connect` overlay.
123
+ * Detached workflow execution normally uses node-local prompt stages instead.
124
+ * `pi.ui.editor`, `pi.ui.confirm`, etc. are still intentionally never invoked
125
+ * from inside a background run. The chat editor stays free; fallback callers
126
+ * attend to run-level prompts via F2 / the `/workflow connect` overlay.
121
127
  *
122
128
  * `signal` is the run's `AbortController.signal`; when fired (e.g. via
123
129
  * `/workflow interrupt <id>`), any HIL waiter rejects so the workflow body
@@ -144,6 +150,9 @@ export function buildBackgroundUIAdapter(
144
150
  message: string,
145
151
  options: readonly T[],
146
152
  ): Promise<T> {
153
+ if (options.length === 0) {
154
+ throw new Error("pi-workflows: ctx.ui.select requires at least one option");
155
+ }
147
156
  const response = await ask(store, runId, {
148
157
  kind: "select",
149
158
  message,
@@ -152,7 +161,7 @@ export function buildBackgroundUIAdapter(
152
161
  if (typeof response === "string" && (options as readonly string[]).includes(response)) {
153
162
  return response as T;
154
163
  }
155
- return options[0];
164
+ return options[0]!;
156
165
  },
157
166
 
158
167
  async editor(initial?: string): Promise<string> {
@@ -3266,6 +3266,7 @@ function factory(pi: ExtensionAPI): void {
3266
3266
  persistence: persistenceRef.current,
3267
3267
  });
3268
3268
  store.clear();
3269
+ stageControlRegistry.clear();
3269
3270
 
3270
3271
  // pi-intercom session naming lives here so we don't trip the
3271
3272
  // loader's "Action methods cannot be called during extension
@@ -42,6 +42,8 @@ export interface StatusWriterOpts {
42
42
  }
43
43
 
44
44
  export interface StatusWriter {
45
+ /** Wait until all currently queued status writes have reached disk. */
46
+ flush(): Promise<void>;
45
47
  /** Stop receiving store updates and cancel any pending flush. */
46
48
  unsubscribe(): void;
47
49
  }
@@ -105,7 +107,7 @@ export function createStatusWriter(
105
107
  opts: StatusWriterOpts = {},
106
108
  ): StatusWriter {
107
109
  if (!config.statusFile) {
108
- return { unsubscribe() {} };
110
+ return { async flush() {}, unsubscribe() {} };
109
111
  }
110
112
 
111
113
  const filePath = resolveStatusFilePath(config, opts);
@@ -117,6 +119,7 @@ export function createStatusWriter(
117
119
  let active = true;
118
120
  let writing = false;
119
121
  let pendingContent: string | null = null;
122
+ let drainPromise: Promise<void> | null = null;
120
123
 
121
124
  function recordWriteError(err: unknown): void {
122
125
  const msg = err instanceof Error ? err.message : String(err);
@@ -148,16 +151,28 @@ export function createStatusWriter(
148
151
  }
149
152
  } finally {
150
153
  writing = false;
151
- if (active && pendingContent !== null) void drainWrites();
152
154
  }
153
155
  }
154
156
 
157
+ function ensureDrain(): Promise<void> {
158
+ drainPromise ??= drainWrites().finally(() => {
159
+ drainPromise = null;
160
+ if (active && pendingContent !== null) void ensureDrain();
161
+ });
162
+ return drainPromise;
163
+ }
164
+
155
165
  const unsubscribeStore = store.subscribe((snap: StoreSnapshot) => {
156
166
  pendingContent = JSON.stringify(snap, null, 2);
157
- void drainWrites();
167
+ void ensureDrain();
158
168
  });
159
169
 
160
170
  return {
171
+ async flush() {
172
+ while (active && (pendingContent !== null || drainPromise !== null)) {
173
+ await ensureDrain();
174
+ }
175
+ },
161
176
  unsubscribe() {
162
177
  active = false;
163
178
  pendingContent = null;
@@ -23,7 +23,6 @@ import { run as syncRun } from "../foreground/executor.js";
23
23
  import { cancellationRegistry as defaultCancellationRegistry } from "./cancellation-registry.js";
24
24
  import { jobTracker as defaultJobTracker } from "./job-tracker.js";
25
25
  import { store as defaultStore } from "../../shared/store.js";
26
- import { buildBackgroundUIAdapter } from "../../extension/background-ui-adapter.js";
27
26
 
28
27
  // ---------------------------------------------------------------------------
29
28
  // Types
@@ -103,20 +102,19 @@ export function runDetached<TInputs extends Record<string, unknown>>(
103
102
  // are not lost.
104
103
  registry.register(runId, controller);
105
104
 
106
- // 4. Build executor opts — inject runId seam, signal, and a store-backed
107
- // HIL adapter. Background runs must NOT route ctx.ui.* through pi.ui
108
- // dialogs (those steal focus from the main chat editor); the adapter
109
- // records prompts on the run and the graph viewer overlay drives the
110
- // response. Destructure `jobs`/`cancellation`/`ui` out so they're not
111
- // forwarded to RunOpts twice.
105
+ // 4. Build executor opts — inject runId seam, signal, and node-local
106
+ // store-backed HIL. Background runs must NOT route ctx.ui.* through pi.ui
107
+ // dialogs (those steal focus from the main chat editor); the executor
108
+ // records prompts on synthetic workflow nodes and the attached stage chat
109
+ // drives the response. Destructure `jobs`/`cancellation`/`ui` out so
110
+ // they're not forwarded to RunOpts twice.
112
111
  const {
113
112
  jobs: _jobs,
114
113
  cancellation: _cancellation,
115
- ui: _ignoredFgUi,
114
+ ui: _ui,
116
115
  store: storeOverride,
117
116
  ...restOpts
118
117
  } = opts;
119
- void _ignoredFgUi;
120
118
  const store: Store = storeOverride ?? defaultStore;
121
119
  const execOpts: RunOpts = {
122
120
  ...restOpts,
@@ -124,7 +122,7 @@ export function runDetached<TInputs extends Record<string, unknown>>(
124
122
  signal: controller.signal,
125
123
  cancellation: registry,
126
124
  store,
127
- ui: buildBackgroundUIAdapter(store, runId, controller.signal),
125
+ usePromptNodesForUi: true,
128
126
  deferWorkflowStart: true,
129
127
  };
130
128