@bastani/atomic 0.8.21 → 0.8.22-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 (235) hide show
  1. package/CHANGELOG.md +40 -9
  2. package/dist/builtin/intercom/broker/broker.ts +3 -3
  3. package/dist/builtin/intercom/config.ts +3 -3
  4. package/dist/builtin/intercom/index.ts +1 -1
  5. package/dist/builtin/intercom/package.json +1 -1
  6. package/dist/builtin/intercom/ui/compose.ts +2 -2
  7. package/dist/builtin/mcp/host-html-template.ts +0 -3
  8. package/dist/builtin/mcp/package.json +1 -1
  9. package/dist/builtin/subagents/CHANGELOG.md +13 -4
  10. package/dist/builtin/subagents/agents/codebase-online-researcher.md +9 -9
  11. package/dist/builtin/subagents/agents/debugger.md +6 -6
  12. package/dist/builtin/subagents/package.json +1 -1
  13. package/dist/builtin/subagents/prompts/parallel-handoff-plan.md +1 -1
  14. package/dist/builtin/subagents/skills/browser-use/SKILL.md +234 -0
  15. package/dist/builtin/subagents/skills/browser-use/references/cdp-python.md +76 -0
  16. package/dist/builtin/subagents/skills/browser-use/references/multi-session.md +92 -0
  17. package/dist/builtin/subagents/skills/subagent/SKILL.md +4 -4
  18. package/dist/builtin/subagents/src/agents/skills.ts +19 -1
  19. package/dist/builtin/subagents/src/extension/index.ts +24 -22
  20. package/dist/builtin/subagents/src/intercom/intercom-bridge.ts +7 -1
  21. package/dist/builtin/subagents/src/runs/background/async-execution.ts +23 -7
  22. package/dist/builtin/subagents/src/runs/background/async-job-tracker.ts +98 -3
  23. package/dist/builtin/subagents/src/runs/background/async-status.ts +3 -1
  24. package/dist/builtin/subagents/src/runs/background/run-status.ts +1 -1
  25. package/dist/builtin/subagents/src/runs/background/stale-run-reconciler.ts +3 -0
  26. package/dist/builtin/subagents/src/runs/background/subagent-runner.ts +37 -12
  27. package/dist/builtin/subagents/src/runs/foreground/chain-clarify.ts +15 -15
  28. package/dist/builtin/subagents/src/runs/foreground/execution.ts +26 -2
  29. package/dist/builtin/subagents/src/runs/shared/nested-render.ts +1 -1
  30. package/dist/builtin/subagents/src/runs/shared/parallel-utils.ts +7 -0
  31. package/dist/builtin/subagents/src/runs/shared/pi-args.ts +28 -1
  32. package/dist/builtin/subagents/src/shared/fast-mode.ts +80 -0
  33. package/dist/builtin/subagents/src/shared/formatters.ts +4 -2
  34. package/dist/builtin/subagents/src/shared/types.ts +4 -2
  35. package/dist/builtin/subagents/src/shared/utils.ts +3 -61
  36. package/dist/builtin/subagents/src/tui/render.ts +303 -157
  37. package/dist/builtin/web-access/package.json +1 -1
  38. package/dist/builtin/workflows/CHANGELOG.md +95 -35
  39. package/dist/builtin/workflows/README.md +228 -41
  40. package/dist/builtin/workflows/builtin/deep-research-codebase.ts +535 -541
  41. package/dist/builtin/workflows/builtin/goal.ts +39 -25
  42. package/dist/builtin/workflows/builtin/open-claude-design.ts +66 -69
  43. package/dist/builtin/workflows/builtin/ralph.ts +21 -21
  44. package/dist/builtin/workflows/package.json +6 -5
  45. package/dist/builtin/workflows/skills/research-codebase/SKILL.md +1 -1
  46. package/dist/builtin/workflows/src/extension/background-ui-adapter.ts +2 -2
  47. package/dist/builtin/workflows/src/extension/discovery.ts +25 -146
  48. package/dist/builtin/workflows/src/extension/dispatcher.ts +72 -24
  49. package/dist/builtin/workflows/src/extension/hil-answer-notifications.ts +363 -0
  50. package/dist/builtin/workflows/src/extension/index.ts +690 -352
  51. package/dist/builtin/workflows/src/extension/lifecycle-notifications.ts +99 -62
  52. package/dist/builtin/workflows/src/extension/render-call.ts +2 -1
  53. package/dist/builtin/workflows/src/extension/render-result.ts +9 -3
  54. package/dist/builtin/workflows/src/extension/renderers.ts +5 -3
  55. package/dist/builtin/workflows/src/extension/runtime.ts +68 -33
  56. package/dist/builtin/workflows/src/extension/status-writer.ts +1 -1
  57. package/dist/builtin/workflows/src/extension/wiring.ts +34 -13
  58. package/dist/builtin/workflows/src/extension/workflow-module-loader.ts +142 -0
  59. package/dist/builtin/workflows/src/extension/workflow-schema.ts +4 -4
  60. package/dist/builtin/workflows/src/index.ts +2 -0
  61. package/dist/builtin/workflows/src/intercom/result-intercom.ts +1 -1
  62. package/dist/builtin/workflows/src/runs/background/runner.ts +6 -4
  63. package/dist/builtin/workflows/src/runs/background/status.ts +45 -21
  64. package/dist/builtin/workflows/src/runs/foreground/executor.ts +624 -52
  65. package/dist/builtin/workflows/src/runs/foreground/stage-control-registry.ts +1 -1
  66. package/dist/builtin/workflows/src/runs/foreground/stage-runner.ts +80 -24
  67. package/dist/builtin/workflows/src/runs/shared/validate-inputs.ts +61 -24
  68. package/dist/builtin/workflows/src/runs/shared/workflow-runner.ts +32 -10
  69. package/dist/builtin/workflows/src/sdk-surface.ts +6 -0
  70. package/dist/builtin/workflows/src/shared/expanded-workflow-graph.ts +178 -0
  71. package/dist/builtin/workflows/src/shared/persistence-restore.ts +92 -12
  72. package/dist/builtin/workflows/src/shared/persistence-session-entries.ts +21 -3
  73. package/dist/builtin/workflows/src/shared/render-inputs-schema.ts +1 -2
  74. package/dist/builtin/workflows/src/shared/run-visibility.ts +9 -0
  75. package/dist/builtin/workflows/src/shared/schema-introspection.ts +121 -0
  76. package/dist/builtin/workflows/src/shared/serializable.ts +132 -0
  77. package/dist/builtin/workflows/src/shared/stage-ui-broker.ts +91 -9
  78. package/dist/builtin/workflows/src/shared/store-types.ts +31 -3
  79. package/dist/builtin/workflows/src/shared/store.ts +58 -14
  80. package/dist/builtin/workflows/src/shared/types.ts +105 -40
  81. package/dist/builtin/workflows/src/tui/chat-surface-message.ts +129 -13
  82. package/dist/builtin/workflows/src/tui/chat-surface.ts +6 -1
  83. package/dist/builtin/workflows/src/tui/dispatch-confirm.ts +3 -2
  84. package/dist/builtin/workflows/src/tui/graph-canvas.ts +1 -1
  85. package/dist/builtin/workflows/src/tui/graph-view.ts +91 -65
  86. package/dist/builtin/workflows/src/tui/inline-form-card.ts +1 -1
  87. package/dist/builtin/workflows/src/tui/inline-form-overlay.ts +3 -2
  88. package/dist/builtin/workflows/src/tui/inputs-overlay.ts +3 -2
  89. package/dist/builtin/workflows/src/tui/inputs-picker.ts +8 -7
  90. package/dist/builtin/workflows/src/tui/keybindings-adapter.ts +2 -0
  91. package/dist/builtin/workflows/src/tui/node-card.ts +34 -8
  92. package/dist/builtin/workflows/src/tui/overlay-adapter.ts +4 -11
  93. package/dist/builtin/workflows/src/tui/prompt-card.ts +98 -50
  94. package/dist/builtin/workflows/src/tui/session-list.ts +7 -2
  95. package/dist/builtin/workflows/src/tui/session-picker.ts +2 -0
  96. package/dist/builtin/workflows/src/tui/stage-chat-view.ts +226 -55
  97. package/dist/builtin/workflows/src/tui/status-helpers.ts +2 -0
  98. package/dist/builtin/workflows/src/tui/store-widget-installer.ts +37 -158
  99. package/dist/builtin/workflows/src/tui/toast.ts +2 -2
  100. package/dist/builtin/workflows/src/tui/widget.ts +53 -12
  101. package/dist/builtin/workflows/src/tui/workflow-attach-pane.ts +270 -19
  102. package/dist/builtin/workflows/src/tui/workflow-notice-card.ts +184 -0
  103. package/dist/builtin/workflows/src/workflows/define-workflow.ts +138 -43
  104. package/dist/config.d.ts +9 -0
  105. package/dist/config.d.ts.map +1 -1
  106. package/dist/config.js +45 -0
  107. package/dist/config.js.map +1 -1
  108. package/dist/core/agent-session.d.ts +27 -9
  109. package/dist/core/agent-session.d.ts.map +1 -1
  110. package/dist/core/agent-session.js +196 -17
  111. package/dist/core/agent-session.js.map +1 -1
  112. package/dist/core/atomic-guide-command.d.ts.map +1 -1
  113. package/dist/core/atomic-guide-command.js +2 -2
  114. package/dist/core/atomic-guide-command.js.map +1 -1
  115. package/dist/core/codex-fast-mode.d.ts +36 -0
  116. package/dist/core/codex-fast-mode.d.ts.map +1 -0
  117. package/dist/core/codex-fast-mode.js +117 -0
  118. package/dist/core/codex-fast-mode.js.map +1 -0
  119. package/dist/core/compaction/branch-summarization.d.ts.map +1 -1
  120. package/dist/core/compaction/branch-summarization.js +1 -1
  121. package/dist/core/compaction/branch-summarization.js.map +1 -1
  122. package/dist/core/compaction/compaction.d.ts.map +1 -1
  123. package/dist/core/compaction/compaction.js +1 -1
  124. package/dist/core/compaction/compaction.js.map +1 -1
  125. package/dist/core/extensions/index.d.ts +4 -1
  126. package/dist/core/extensions/index.d.ts.map +1 -1
  127. package/dist/core/extensions/index.js +1 -0
  128. package/dist/core/extensions/index.js.map +1 -1
  129. package/dist/core/extensions/loader.d.ts +7 -2
  130. package/dist/core/extensions/loader.d.ts.map +1 -1
  131. package/dist/core/extensions/loader.js +23 -8
  132. package/dist/core/extensions/loader.js.map +1 -1
  133. package/dist/core/extensions/reactive-widget.d.ts +58 -0
  134. package/dist/core/extensions/reactive-widget.d.ts.map +1 -0
  135. package/dist/core/extensions/reactive-widget.js +182 -0
  136. package/dist/core/extensions/reactive-widget.js.map +1 -0
  137. package/dist/core/extensions/runner.d.ts.map +1 -1
  138. package/dist/core/extensions/runner.js +1 -0
  139. package/dist/core/extensions/runner.js.map +1 -1
  140. package/dist/core/extensions/types.d.ts +26 -12
  141. package/dist/core/extensions/types.d.ts.map +1 -1
  142. package/dist/core/extensions/types.js.map +1 -1
  143. package/dist/core/messages.d.ts +1 -1
  144. package/dist/core/messages.d.ts.map +1 -1
  145. package/dist/core/messages.js +8 -2
  146. package/dist/core/messages.js.map +1 -1
  147. package/dist/core/model-registry.d.ts +4 -0
  148. package/dist/core/model-registry.d.ts.map +1 -1
  149. package/dist/core/model-registry.js +11 -0
  150. package/dist/core/model-registry.js.map +1 -1
  151. package/dist/core/resource-loader.d.ts +9 -1
  152. package/dist/core/resource-loader.d.ts.map +1 -1
  153. package/dist/core/resource-loader.js +49 -21
  154. package/dist/core/resource-loader.js.map +1 -1
  155. package/dist/core/sdk.d.ts.map +1 -1
  156. package/dist/core/sdk.js +22 -13
  157. package/dist/core/sdk.js.map +1 -1
  158. package/dist/core/session-manager.d.ts +7 -5
  159. package/dist/core/session-manager.d.ts.map +1 -1
  160. package/dist/core/session-manager.js +5 -3
  161. package/dist/core/session-manager.js.map +1 -1
  162. package/dist/core/settings-manager.d.ts +16 -0
  163. package/dist/core/settings-manager.d.ts.map +1 -1
  164. package/dist/core/settings-manager.js +64 -5
  165. package/dist/core/settings-manager.js.map +1 -1
  166. package/dist/core/slash-commands.d.ts.map +1 -1
  167. package/dist/core/slash-commands.js +1 -0
  168. package/dist/core/slash-commands.js.map +1 -1
  169. package/dist/core/system-prompt.d.ts.map +1 -1
  170. package/dist/core/system-prompt.js +7 -4
  171. package/dist/core/system-prompt.js.map +1 -1
  172. package/dist/core/tools/ask-user-question/ask-user-question.d.ts.map +1 -1
  173. package/dist/core/tools/ask-user-question/ask-user-question.js +2 -2
  174. package/dist/core/tools/ask-user-question/ask-user-question.js.map +1 -1
  175. package/dist/index.d.ts +4 -3
  176. package/dist/index.d.ts.map +1 -1
  177. package/dist/index.js +3 -2
  178. package/dist/index.js.map +1 -1
  179. package/dist/main.d.ts +3 -0
  180. package/dist/main.d.ts.map +1 -1
  181. package/dist/main.js +12 -0
  182. package/dist/main.js.map +1 -1
  183. package/dist/modes/interactive/chat-input-actions.d.ts.map +1 -1
  184. package/dist/modes/interactive/chat-input-actions.js.map +1 -1
  185. package/dist/modes/interactive/components/diff.d.ts.map +1 -1
  186. package/dist/modes/interactive/components/diff.js +0 -1
  187. package/dist/modes/interactive/components/diff.js.map +1 -1
  188. package/dist/modes/interactive/components/fast-mode-selector.d.ts +27 -0
  189. package/dist/modes/interactive/components/fast-mode-selector.d.ts.map +1 -0
  190. package/dist/modes/interactive/components/fast-mode-selector.js +105 -0
  191. package/dist/modes/interactive/components/fast-mode-selector.js.map +1 -0
  192. package/dist/modes/interactive/components/footer.d.ts.map +1 -1
  193. package/dist/modes/interactive/components/footer.js +7 -12
  194. package/dist/modes/interactive/components/footer.js.map +1 -1
  195. package/dist/modes/interactive/components/index.d.ts +1 -0
  196. package/dist/modes/interactive/components/index.d.ts.map +1 -1
  197. package/dist/modes/interactive/components/index.js +1 -0
  198. package/dist/modes/interactive/components/index.js.map +1 -1
  199. package/dist/modes/interactive/interactive-mode.d.ts +4 -0
  200. package/dist/modes/interactive/interactive-mode.d.ts.map +1 -1
  201. package/dist/modes/interactive/interactive-mode.js +132 -30
  202. package/dist/modes/interactive/interactive-mode.js.map +1 -1
  203. package/dist/modes/print-mode.d.ts.map +1 -1
  204. package/dist/modes/print-mode.js +53 -6
  205. package/dist/modes/print-mode.js.map +1 -1
  206. package/dist/modes/rpc/rpc-mode.d.ts.map +1 -1
  207. package/dist/modes/rpc/rpc-mode.js +3 -0
  208. package/dist/modes/rpc/rpc-mode.js.map +1 -1
  209. package/docs/compaction.md +1 -1
  210. package/docs/custom-provider.md +2 -2
  211. package/docs/development.md +2 -2
  212. package/docs/docs.json +2 -2
  213. package/docs/extensions.md +18 -13
  214. package/docs/providers.md +5 -1
  215. package/docs/quickstart.md +5 -3
  216. package/docs/rpc.md +5 -5
  217. package/docs/sdk.md +12 -12
  218. package/docs/settings.md +18 -0
  219. package/docs/themes.md +6 -6
  220. package/docs/tui.md +20 -18
  221. package/docs/usage.md +2 -0
  222. package/docs/workflows.md +403 -39
  223. package/examples/extensions/qna.ts +2 -2
  224. package/package.json +4 -4
  225. package/dist/builtin/subagents/skills/playwright-cli/SKILL.md +0 -392
  226. package/dist/builtin/subagents/skills/playwright-cli/references/element-attributes.md +0 -23
  227. package/dist/builtin/subagents/skills/playwright-cli/references/playwright-tests.md +0 -39
  228. package/dist/builtin/subagents/skills/playwright-cli/references/request-mocking.md +0 -87
  229. package/dist/builtin/subagents/skills/playwright-cli/references/running-code.md +0 -241
  230. package/dist/builtin/subagents/skills/playwright-cli/references/session-management.md +0 -225
  231. package/dist/builtin/subagents/skills/playwright-cli/references/spec-driven-testing.md +0 -305
  232. package/dist/builtin/subagents/skills/playwright-cli/references/storage-state.md +0 -275
  233. package/dist/builtin/subagents/skills/playwright-cli/references/test-generation.md +0 -134
  234. package/dist/builtin/subagents/skills/playwright-cli/references/tracing.md +0 -139
  235. package/dist/builtin/subagents/skills/playwright-cli/references/video-recording.md +0 -143
@@ -11,12 +11,15 @@ import type {
11
11
  ModelCycleResult,
12
12
  PromptOptions,
13
13
  } from "@bastani/atomic";
14
+ import type { TSchema } from "typebox";
15
+
16
+ export type { TSchema };
14
17
 
15
18
  export type { AgentSessionEvent, CompactionResult, ModelCycleResult, PromptOptions };
16
19
 
17
20
  export type WorkflowModelValue = NonNullable<CreateAgentSessionOptions["model"]> | string;
18
21
 
19
- export interface WorkflowModelUsage {
22
+ export interface WorkflowModelUsage extends WorkflowSerializableObject {
20
23
  readonly input?: number;
21
24
  readonly output?: number;
22
25
  readonly cacheRead?: number;
@@ -25,7 +28,7 @@ export interface WorkflowModelUsage {
25
28
  readonly turns?: number;
26
29
  }
27
30
 
28
- export interface WorkflowModelAttempt {
31
+ export interface WorkflowModelAttempt extends WorkflowSerializableObject {
29
32
  readonly model: string;
30
33
  readonly success: boolean;
31
34
  readonly error?: string;
@@ -54,45 +57,93 @@ export interface WorkflowModelCatalogPort {
54
57
  }
55
58
 
56
59
  // ---------------------------------------------------------------------------
57
- // Workflow input schema
60
+ // Workflow serializable values
58
61
  // ---------------------------------------------------------------------------
59
62
 
60
- /** Discriminated union of supported input kinds. */
61
- export type WorkflowInputType = "text" | "string" | "number" | "boolean" | "select";
63
+ export type WorkflowSerializablePrimitive = string | number | boolean | null;
62
64
 
63
- interface BaseInputSchema {
64
- description?: string;
65
- required?: boolean;
65
+ export interface WorkflowSerializableObject {
66
+ /**
67
+ * Optional properties use `undefined` at the type level for ergonomic
68
+ * intellisense, but workflow runtime validation rejects actual `undefined`
69
+ * values in returned/input objects. Omit optional keys instead.
70
+ */
71
+ readonly [key: string]: WorkflowSerializableValue | undefined;
66
72
  }
67
73
 
68
- export interface TextInputSchema extends BaseInputSchema {
69
- type: "text" | "string";
70
- default?: string;
71
- }
74
+ export type WorkflowSerializableValue =
75
+ | WorkflowSerializablePrimitive
76
+ | readonly WorkflowSerializableValue[]
77
+ | WorkflowSerializableObject;
72
78
 
73
- export interface NumberInputSchema extends BaseInputSchema {
74
- type: "number";
75
- default?: number;
76
- }
79
+ export type WorkflowInputValues = WorkflowSerializableObject;
80
+ export type WorkflowOutputValues = WorkflowSerializableObject;
81
+ export type WorkflowRunOutput = WorkflowOutputValues;
82
+
83
+ // ---------------------------------------------------------------------------
84
+ // Workflow input / output schemas
85
+ // ---------------------------------------------------------------------------
86
+
87
+ /**
88
+ * Inputs and outputs are declared with TypeBox schemas. Authors use
89
+ * `.input(key, Type.String({ ... }))` / `.output(key, Type.Object({ ... }))`;
90
+ * the builder threads the precise `Static<>` types and the runtime validates
91
+ * via TypeBox `Value`.
92
+ */
93
+ export type WorkflowInputSchemaMap = Readonly<Record<string, TSchema>>;
94
+ export type WorkflowOutputSchemaMap = Readonly<Record<string, TSchema>>;
77
95
 
78
- export interface BooleanInputSchema extends BaseInputSchema {
79
- type: "boolean";
80
- default?: boolean;
96
+ /** A single declared input schema is just a TypeBox schema. */
97
+ export type WorkflowInputSchema = TSchema;
98
+ /** A single declared output schema is just a TypeBox schema. */
99
+ export type WorkflowOutputSchema = TSchema;
100
+
101
+ // ---------------------------------------------------------------------------
102
+ // Workflow execution policy
103
+ // ---------------------------------------------------------------------------
104
+
105
+ export type WorkflowExecutionMode = "interactive" | "non_interactive";
106
+
107
+ export interface WorkflowExecutionPolicy {
108
+ readonly mode: WorkflowExecutionMode;
109
+ readonly allowHumanInput: boolean;
110
+ readonly awaitTerminalRun: boolean;
111
+ readonly allowInputPicker: boolean;
81
112
  }
82
113
 
83
- export interface SelectInputSchema extends BaseInputSchema {
84
- type: "select";
85
- /** Non-empty array of valid string choices. */
86
- choices: readonly string[];
87
- default?: string;
114
+ export const INTERACTIVE_WORKFLOW_POLICY: WorkflowExecutionPolicy = Object.freeze({
115
+ mode: "interactive",
116
+ allowHumanInput: true,
117
+ awaitTerminalRun: false,
118
+ allowInputPicker: true,
119
+ });
120
+
121
+ export const NON_INTERACTIVE_WORKFLOW_POLICY: WorkflowExecutionPolicy = Object.freeze({
122
+ mode: "non_interactive",
123
+ allowHumanInput: false,
124
+ awaitTerminalRun: true,
125
+ allowInputPicker: false,
126
+ });
127
+
128
+ // ---------------------------------------------------------------------------
129
+ // Workflow child composition and outputs
130
+ // ---------------------------------------------------------------------------
131
+
132
+ export interface WorkflowRunChildOptions<TInputs extends WorkflowInputValues = WorkflowInputValues> {
133
+ /** Inputs forwarded to the child workflow, typed against its input contract. */
134
+ readonly inputs?: TInputs;
135
+ /** Parent boundary stage display name. Defaults to workflow:<workflow-name>. */
136
+ readonly stageName?: string;
88
137
  }
89
138
 
90
- /** Union of all concrete input schema shapes. */
91
- export type WorkflowInputSchema =
92
- | TextInputSchema
93
- | NumberInputSchema
94
- | BooleanInputSchema
95
- | SelectInputSchema;
139
+ export interface WorkflowChildResult<TOutputs extends WorkflowOutputValues = WorkflowOutputValues>
140
+ extends WorkflowSerializableObject {
141
+ readonly workflow: string;
142
+ readonly runId: string;
143
+ readonly status: "completed";
144
+ /** Child outputs, typed from the child workflow's declared `.output(...)` contract. */
145
+ readonly outputs: TOutputs;
146
+ }
96
147
 
97
148
  // ---------------------------------------------------------------------------
98
149
  // HIL (human-in-the-loop) primitives available inside run functions
@@ -186,6 +237,8 @@ export interface StageExecutionMeta {
186
237
  stageOptions?: StageOptions;
187
238
  /** AbortSignal propagated from the executor's own AbortController. */
188
239
  signal?: AbortSignal;
240
+ /** Runtime execution mode for policy-aware child sessions. */
241
+ executionMode?: WorkflowExecutionMode;
189
242
  }
190
243
 
191
244
  export interface CompleteStageOpts extends WorkflowModelFallbackFields {
@@ -227,7 +280,7 @@ export interface WorkflowPersistencePort {
227
280
  * `{previous}` handoffs as a typed SDK primitive instead of requiring authors
228
281
  * to manually concatenate prior output into every prompt.
229
282
  */
230
- export interface WorkflowTaskContext {
283
+ export interface WorkflowTaskContext extends WorkflowSerializableObject {
231
284
  /** Optional display label used when rendering the context block. */
232
285
  readonly name?: string;
233
286
  /** Textual context made available to the next task. */
@@ -243,6 +296,7 @@ export interface WorkflowTaskResult extends WorkflowTaskContext {
243
296
  readonly sessionFile?: string;
244
297
  readonly artifacts?: WorkflowArtifact[];
245
298
  readonly model?: string;
299
+ readonly fastMode?: boolean;
246
300
  readonly attemptedModels?: readonly string[];
247
301
  readonly modelAttempts?: readonly WorkflowModelAttempt[];
248
302
  readonly warnings?: readonly string[];
@@ -331,7 +385,7 @@ export interface StageOutputOptions {
331
385
 
332
386
  export type StagePromptOptions = PromptOptions & StageOutputOptions;
333
387
 
334
- export interface WorkflowArtifact {
388
+ export interface WorkflowArtifact extends WorkflowSerializableObject {
335
389
  readonly kind: "output" | "session" | "diff" | "patch";
336
390
  readonly path: string;
337
391
  readonly taskName?: string;
@@ -390,7 +444,7 @@ export interface WorkflowDetails {
390
444
  readonly status: WorkflowDetailsStatus;
391
445
  readonly context?: "fresh" | "fork";
392
446
  readonly results?: WorkflowTaskResult[];
393
- readonly output?: Record<string, unknown>;
447
+ readonly output?: WorkflowOutputValues;
394
448
  readonly progress?: WorkflowProgressSummary;
395
449
  readonly artifacts?: WorkflowArtifact[];
396
450
  readonly controlEvents?: WorkflowControlEvent[];
@@ -518,7 +572,7 @@ export interface StageContext {
518
572
  // Workflow run context (top-level ctx passed to the run function)
519
573
  // ---------------------------------------------------------------------------
520
574
 
521
- export interface WorkflowRunContext<TInputs extends Record<string, unknown> = Record<string, unknown>> {
575
+ export interface WorkflowRunContext<TInputs extends WorkflowInputValues = WorkflowInputValues> {
522
576
  /** Typed inputs provided by the caller, validated against the input schema. */
523
577
  readonly inputs: TInputs;
524
578
  /** Invocation working directory for workflow-owned artifacts. Defaults to the host process cwd when omitted. */
@@ -541,6 +595,11 @@ export interface WorkflowRunContext<TInputs extends Record<string, unknown> = Re
541
595
  chain(steps: readonly WorkflowTaskStep[], options?: WorkflowChainOptions): Promise<WorkflowTaskResult[]>;
542
596
  /** Run tasks in parallel. Missing step tasks use the first available task as a fallback. */
543
597
  parallel(steps: readonly WorkflowTaskStep[], options?: WorkflowParallelOptions): Promise<WorkflowTaskResult[]>;
598
+ /** Execute a reusable child workflow by compiled workflow definition. */
599
+ workflow<TChildInputs extends WorkflowInputValues, TChildOutputs extends WorkflowOutputValues>(
600
+ definition: WorkflowDefinition<TChildInputs, TChildOutputs>,
601
+ options?: WorkflowRunChildOptions<TChildInputs>,
602
+ ): Promise<WorkflowChildResult<TChildOutputs>>;
544
603
  /** HIL primitives for user interaction during a run. */
545
604
  readonly ui: WorkflowUIContext;
546
605
  }
@@ -581,9 +640,10 @@ export interface WorkflowRuntimeConfig {
581
640
  // Workflow run function
582
641
  // ---------------------------------------------------------------------------
583
642
 
584
- export type WorkflowRunFn<TInputs extends Record<string, unknown> = Record<string, unknown>> = (
585
- ctx: WorkflowRunContext<TInputs>,
586
- ) => Promise<Record<string, unknown>>;
643
+ export type WorkflowRunFn<
644
+ TInputs extends WorkflowInputValues = WorkflowInputValues,
645
+ TOutputs extends WorkflowOutputValues = WorkflowOutputValues,
646
+ > = (ctx: WorkflowRunContext<TInputs>) => Promise<TOutputs>;
587
647
 
588
648
  // ---------------------------------------------------------------------------
589
649
  // Compiled workflow definition
@@ -598,15 +658,20 @@ export interface WorkflowInputBindings {
598
658
  readonly worktree?: WorkflowWorktreeInputBinding;
599
659
  }
600
660
 
601
- export interface WorkflowDefinition<TInputs extends Record<string, unknown> = Record<string, unknown>> {
661
+ export interface WorkflowDefinition<
662
+ TInputs extends WorkflowInputValues = WorkflowInputValues,
663
+ TOutputs extends WorkflowOutputValues = WorkflowOutputValues,
664
+ > {
602
665
  /** Sentinel consumed by the registry loader to validate the export. */
603
666
  readonly __piWorkflow: true;
604
667
  readonly name: string;
605
668
  /** Normalised name (lowercase, hyphens) used as the registry key. */
606
669
  readonly normalizedName: string;
607
670
  readonly description: string;
608
- readonly inputs: Readonly<Record<string, WorkflowInputSchema>>;
671
+ readonly inputs: WorkflowInputSchemaMap;
672
+ /** Optional output contract used by parent workflows when selecting child outputs. */
673
+ readonly outputs?: WorkflowOutputSchemaMap;
609
674
  /** Optional input-to-runtime defaults declared by the workflow builder. */
610
675
  readonly inputBindings?: WorkflowInputBindings;
611
- readonly run: WorkflowRunFn<TInputs>;
676
+ readonly run: WorkflowRunFn<TInputs, TOutputs>;
612
677
  }
@@ -28,6 +28,7 @@
28
28
  import type { ExtensionAPI } from "../extension/index.js";
29
29
  import type { RunDetail } from "../runs/background/status.js";
30
30
  import type { RunSnapshot, RunStatus } from "../shared/store-types.js";
31
+ import type { WorkflowInputValues } from "../shared/types.js";
31
32
  import type { GraphTheme } from "./graph-theme.js";
32
33
  import type { WorkflowListEntry } from "./workflow-list.js";
33
34
  import { renderDispatchConfirm } from "./dispatch-confirm.js";
@@ -54,7 +55,7 @@ export interface DispatchPayload {
54
55
  kind: "dispatch";
55
56
  workflowName: string;
56
57
  runId: string;
57
- inputs: Readonly<Record<string, unknown>>;
58
+ inputs: Readonly<WorkflowInputValues>;
58
59
  }
59
60
 
60
61
  /**
@@ -147,16 +148,100 @@ export function registerChatSurfaceRenderer(
147
148
  * is invoked by pi on every chat re-render with the real chat content
148
149
  * width — there's no need for the caller to thread `process.stdout.columns`.
149
150
  */
151
+ export interface RenderChatSurfacePlainTextOptions {
152
+ readonly width?: number;
153
+ readonly now?: number;
154
+ readonly theme?: GraphTheme;
155
+ }
156
+
157
+ /**
158
+ * Render the full printable fallback stored in pi's custom-message `content`.
159
+ * The interactive TUI still uses `details` + the registered renderer; this
160
+ * string is for print mode, transcripts, and any host that cannot mount the
161
+ * custom component.
162
+ */
163
+ export function renderChatSurfacePlainText(
164
+ payload: ChatSurfacePayload,
165
+ options: RenderChatSurfacePlainTextOptions = {},
166
+ ): string {
167
+ const themed = options.theme === undefined ? {} : { theme: options.theme };
168
+ const width = options.width;
169
+ const now = options.now ?? Date.now();
170
+
171
+ switch (payload.kind) {
172
+ case "dispatch": {
173
+ const rendered = renderDispatchConfirm({
174
+ workflowName: payload.workflowName,
175
+ runId: payload.runId,
176
+ inputs: payload.inputs,
177
+ width,
178
+ ...themed,
179
+ });
180
+ return [
181
+ rendered,
182
+ `run id: ${payload.runId}`,
183
+ `inputs: ${formatPlainRecord(payload.inputs)}`,
184
+ ].join("\n");
185
+ }
186
+ case "status": {
187
+ const rendered = renderStatusList(payload.runs, { width, now, ...themed });
188
+ if (payload.runs.length === 0) return rendered;
189
+ return [
190
+ rendered,
191
+ "",
192
+ ...payload.runs.map(
193
+ (run) => `run id: ${run.id} · workflow: ${run.name} · status: ${run.status}`,
194
+ ),
195
+ ].join("\n");
196
+ }
197
+ case "list": {
198
+ const rendered = renderWorkflowList(payload.entries, { width, ...themed });
199
+ if (payload.entries.length === 0) return rendered;
200
+ return [
201
+ rendered,
202
+ "",
203
+ ...payload.entries.map(formatWorkflowEntryPlain),
204
+ ].join("\n");
205
+ }
206
+ case "detail": {
207
+ const rendered = renderRunDetail(payload.detail, { width, now, ...themed });
208
+ const lines = [
209
+ rendered,
210
+ `run id: ${payload.detail.runId}`,
211
+ `inputs: ${formatPlainRecord(payload.detail.inputs)}`,
212
+ ];
213
+ if (payload.detail.result !== undefined) {
214
+ lines.push(`result: ${formatPlainValue(payload.detail.result)}`);
215
+ }
216
+ if (payload.detail.error !== undefined) {
217
+ lines.push(`error: ${payload.detail.error}`);
218
+ }
219
+ return lines.join("\n");
220
+ }
221
+ case "killed":
222
+ if (options.theme !== undefined) {
223
+ return renderWorkflowKilledNotice({
224
+ width: width ?? 80,
225
+ theme: options.theme,
226
+ run: payload.run,
227
+ previousStatus: payload.previousStatus,
228
+ }).join("\n");
229
+ }
230
+ return renderKilledPlainText(payload);
231
+ }
232
+ }
233
+
150
234
  export function emitChatSurface(
151
235
  pi: ExtensionAPI,
152
236
  payload: ChatSurfacePayload,
237
+ options: { readonly content?: string } = {},
153
238
  ): void {
154
239
  const send = pi.sendMessage;
155
240
  if (typeof send !== "function") return;
156
- // `content` is unused by our renderer but pi's message store may surface
157
- // it in non-display contexts (e.g. transcript export); pick a short
158
- // descriptor per kind so it remains greppable.
159
- const content = describePayload(payload);
241
+ // The renderer consumes `details`, but print/json/transcript surfaces read
242
+ // the stored `content`. Default to a complete printable rendering so
243
+ // headless `/workflow list|status|status <id>` is useful without a TUI.
244
+ const content = options.content ?? renderChatSurfacePlainText(payload);
160
245
  (send as unknown as (msg: {
161
246
  customType: string;
162
247
  content: string;
@@ -174,14 +259,45 @@ export function emitChatSurface(
174
259
  // Internals
175
260
  // ---------------------------------------------------------------------------
176
261
 
177
- function describePayload(payload: ChatSurfacePayload): string {
178
- switch (payload.kind) {
179
- case "dispatch": return `dispatched ${payload.workflowName} · ${payload.runId.slice(0, 8)}`;
180
- case "status": return `status · ${payload.runs.length} run${payload.runs.length === 1 ? "" : "s"}`;
181
- case "list": return `workflows · ${payload.entries.length} registered`;
182
- case "detail": return `run detail · ${payload.detail.runId.slice(0, 8)}`;
183
- case "killed": return `workflow killed · ${payload.run.id.slice(0, 8)}`;
184
- }
262
+ function formatWorkflowEntryPlain(entry: WorkflowListEntry): string {
263
+ const required = entry.inputs
264
+ .filter((input) => input.required === true)
265
+ .map((input) => input.name);
266
+ const optional = entry.inputs
267
+ .filter((input) => input.required !== true)
268
+ .map((input) => input.name);
269
+ const inputs = [
270
+ required.length > 0 ? `required inputs: ${required.join(", ")}` : undefined,
271
+ optional.length > 0 ? `optional inputs: ${optional.join(", ")}` : undefined,
272
+ ].filter((part): part is string => part !== undefined);
273
+ const inputSummary = inputs.length > 0 ? inputs.join(" · ") : "inputs: (none)";
274
+ return `workflow: ${entry.name} · description: ${entry.description} · ${inputSummary}`;
275
+ }
276
+
277
+ function renderKilledPlainText(payload: KilledPayload): string {
278
+ const run = payload.run;
279
+ const stageCount = run.stages.length;
280
+ const runningStages = run.stages.filter((stage) => stage.status === "running").length;
281
+ return [
282
+ "Workflow killed",
283
+ `workflow: ${run.name}`,
284
+ `run id: ${run.id}`,
285
+ `status: ${payload.previousStatus} → killed`,
286
+ `active stages: ${runningStages}/${stageCount}`,
287
+ `inspect: /workflow status ${run.id}`,
288
+ ].join("\n");
289
+ }
290
+
291
+ function formatPlainRecord(record: Readonly<WorkflowInputValues>): string {
292
+ const entries = Object.entries(record);
293
+ if (entries.length === 0) return "(none)";
294
+ return entries.map(([key, value]) => `${key}=${formatPlainValue(value)}`).join(", ");
295
+ }
296
+
297
+ function formatPlainValue(value: unknown): string {
298
+ if (typeof value === "string") return JSON.stringify(value);
299
+ const json = JSON.stringify(value);
300
+ return json === undefined ? String(value) : json;
185
301
  }
186
302
 
187
303
  function makeComponent(
@@ -118,7 +118,10 @@ export function renderRoundedBoxLines(opts: RenderRoundedBoxOpts & { width: numb
118
118
  ? ` ${truncateToWidth(opts.title, titleBudget, ELLIPSIS)} `
119
119
  : "";
120
120
  const topFill = Math.max(0, inner - visibleWidth(titleText));
121
- const top = `${border}╭${titleText}${"─".repeat(topFill)}╮${reset}`;
121
+ // `titleText` may contain its own ANSI runs (for status-coloured badges).
122
+ // Re-prime the border colour after it so RESETs inside the title do not
123
+ // leave the trailing rule/corner on the terminal default colour.
124
+ const top = `${border}╭${titleText}${border}${"─".repeat(topFill)}╮${reset}`;
122
125
 
123
126
  const body = opts.bodyLines.length > 0 ? opts.bodyLines : [""];
124
127
  const rows = body.map((line) => {
@@ -504,6 +507,7 @@ function stageGlyph(status: StageStatus): string {
504
507
  case "completed": return "✓";
505
508
  case "running": return "●";
506
509
  case "failed": return "✗";
510
+ case "awaiting_input": return "?";
507
511
  case "skipped": return "⊘";
508
512
  case "pending":
509
513
  default: return "○";
@@ -515,6 +519,7 @@ function stageColor(status: StageStatus, theme: GraphTheme): string {
515
519
  case "completed": return hexToAnsi(theme.success);
516
520
  case "running": return hexToAnsi(theme.warning);
517
521
  case "failed": return hexToAnsi(theme.error);
522
+ case "awaiting_input": return hexToAnsi(theme.info);
518
523
  case "skipped": return hexToAnsi(theme.dim);
519
524
  case "pending":
520
525
  default: return hexToAnsi(theme.dim);
@@ -33,6 +33,7 @@
33
33
  */
34
34
 
35
35
  import type { GraphTheme } from "./graph-theme.js";
36
+ import type { WorkflowInputValues } from "../shared/types.js";
36
37
  import {
37
38
  renderHintRows,
38
39
  renderRoundedBox,
@@ -59,7 +60,7 @@ export interface RenderDispatchConfirmOpts {
59
60
  /** Real run UUID; the renderer surfaces the first 8 chars in the tag. */
60
61
  runId: string;
61
62
  /** Inputs merged from CLI tokens + picker output. */
62
- inputs: Readonly<Record<string, unknown>>;
63
+ inputs: Readonly<WorkflowInputValues>;
63
64
  /** Provide for themed chrome; omit for plain ASCII. */
64
65
  theme?: GraphTheme;
65
66
  /** Render width (cells). Defaults to `process.stdout.columns`. */
@@ -195,7 +196,7 @@ interface InputsSegment {
195
196
  * label.
196
197
  */
197
198
  function renderInputsSegment(
198
- inputs: Readonly<Record<string, unknown>>,
199
+ inputs: Readonly<WorkflowInputValues>,
199
200
  budget: number,
200
201
  theme?: GraphTheme,
201
202
  ): InputsSegment | null {
@@ -9,7 +9,7 @@
9
9
  * keeps the buffer cheap for wide-but-mostly-empty graph canvases.
10
10
  *
11
11
  * cross-ref:
12
- * - github.com/flora131/atomic packages/atomic-sdk/src/components/connectors.ts
12
+ * - github.com/bastani-inc/atomic packages/atomic-sdk/src/components/connectors.ts
13
13
  * - src/tui/graph-view.ts _renderGraph
14
14
  */
15
15