@bastani/atomic 0.8.27-alpha.1 → 0.8.28-alpha.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +24 -0
- package/dist/builtin/intercom/CHANGELOG.md +6 -0
- package/dist/builtin/intercom/package.json +1 -1
- package/dist/builtin/mcp/CHANGELOG.md +6 -0
- package/dist/builtin/mcp/package.json +2 -2
- package/dist/builtin/subagents/CHANGELOG.md +6 -0
- package/dist/builtin/subagents/package.json +1 -1
- package/dist/builtin/web-access/CHANGELOG.md +6 -0
- package/dist/builtin/web-access/package.json +1 -1
- package/dist/builtin/workflows/CHANGELOG.md +20 -0
- package/dist/builtin/workflows/README.md +11 -9
- package/dist/builtin/workflows/package.json +1 -1
- package/dist/builtin/workflows/src/authoring.d.ts +5 -2
- package/dist/builtin/workflows/src/extension/background-ui-adapter.ts +3 -1
- package/dist/builtin/workflows/src/extension/hil-answer-notifications.ts +17 -25
- package/dist/builtin/workflows/src/extension/index.ts +133 -18
- package/dist/builtin/workflows/src/extension/render-result.ts +22 -2
- package/dist/builtin/workflows/src/extension/workflow-schema.ts +3 -3
- package/dist/builtin/workflows/src/runs/foreground/executor.ts +210 -16
- package/dist/builtin/workflows/src/sdk-surface.ts +1 -1
- package/dist/builtin/workflows/src/shared/authoring-contract.d.ts +42 -5
- package/dist/builtin/workflows/src/shared/store-types.ts +8 -2
- package/dist/builtin/workflows/src/shared/store.ts +51 -0
- package/dist/builtin/workflows/src/shared/types.ts +14 -4
- package/dist/builtin/workflows/src/tui/graph-view.ts +4 -1
- package/dist/builtin/workflows/src/tui/prompt-card.ts +6 -0
- package/dist/builtin/workflows/src/tui/stage-chat-view.ts +11 -1
- package/dist/core/agent-session.d.ts +4 -4
- package/dist/core/agent-session.d.ts.map +1 -1
- package/dist/core/agent-session.js +147 -31
- package/dist/core/agent-session.js.map +1 -1
- package/dist/core/auth-guidance.d.ts +10 -1
- package/dist/core/auth-guidance.d.ts.map +1 -1
- package/dist/core/auth-guidance.js +26 -1
- package/dist/core/auth-guidance.js.map +1 -1
- package/dist/core/compaction/branch-summarization.d.ts +2 -2
- package/dist/core/compaction/branch-summarization.d.ts.map +1 -1
- package/dist/core/compaction/branch-summarization.js +7 -7
- package/dist/core/compaction/branch-summarization.js.map +1 -1
- package/dist/core/compaction/compaction.d.ts +4 -84
- package/dist/core/compaction/compaction.d.ts.map +1 -1
- package/dist/core/compaction/compaction.js +3 -479
- package/dist/core/compaction/compaction.js.map +1 -1
- package/dist/core/compaction/context-compaction.d.ts.map +1 -1
- package/dist/core/compaction/context-compaction.js +39 -82
- package/dist/core/compaction/context-compaction.js.map +1 -1
- package/dist/core/compaction/index.d.ts +1 -1
- package/dist/core/compaction/index.d.ts.map +1 -1
- package/dist/core/compaction/index.js +1 -1
- package/dist/core/compaction/index.js.map +1 -1
- package/dist/core/extensions/types.d.ts +10 -8
- package/dist/core/extensions/types.d.ts.map +1 -1
- package/dist/core/extensions/types.js.map +1 -1
- package/dist/core/index.d.ts +1 -1
- package/dist/core/index.d.ts.map +1 -1
- package/dist/core/index.js.map +1 -1
- package/dist/core/messages.d.ts +1 -11
- package/dist/core/messages.d.ts.map +1 -1
- package/dist/core/messages.js +10 -25
- package/dist/core/messages.js.map +1 -1
- package/dist/core/session-manager.d.ts +5 -8
- package/dist/core/session-manager.d.ts.map +1 -1
- package/dist/core/session-manager.js +12 -76
- package/dist/core/session-manager.js.map +1 -1
- package/dist/core/settings-manager.d.ts +0 -3
- package/dist/core/settings-manager.d.ts.map +1 -1
- package/dist/core/settings-manager.js +0 -4
- package/dist/core/settings-manager.js.map +1 -1
- package/dist/index.d.ts +3 -3
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +3 -3
- package/dist/index.js.map +1 -1
- package/dist/modes/interactive/components/chat-message-renderer.d.ts +1 -5
- package/dist/modes/interactive/components/chat-message-renderer.d.ts.map +1 -1
- package/dist/modes/interactive/components/chat-message-renderer.js +5 -9
- package/dist/modes/interactive/components/chat-message-renderer.js.map +1 -1
- package/dist/modes/interactive/components/chat-session-host.d.ts.map +1 -1
- package/dist/modes/interactive/components/chat-session-host.js +0 -3
- package/dist/modes/interactive/components/chat-session-host.js.map +1 -1
- package/dist/modes/interactive/components/index.d.ts +0 -1
- package/dist/modes/interactive/components/index.d.ts.map +1 -1
- package/dist/modes/interactive/components/index.js +0 -1
- package/dist/modes/interactive/components/index.js.map +1 -1
- package/dist/modes/interactive/interactive-mode.d.ts.map +1 -1
- package/dist/modes/interactive/interactive-mode.js +4 -27
- package/dist/modes/interactive/interactive-mode.js.map +1 -1
- package/dist/modes/rpc/rpc-client.d.ts +1 -1
- package/dist/modes/rpc/rpc-client.d.ts.map +1 -1
- package/dist/modes/rpc/rpc-client.js +2 -2
- package/dist/modes/rpc/rpc-client.js.map +1 -1
- package/dist/modes/rpc/rpc-mode.d.ts.map +1 -1
- package/dist/modes/rpc/rpc-mode.js +1 -1
- package/dist/modes/rpc/rpc-mode.js.map +1 -1
- package/dist/modes/rpc/rpc-types.d.ts +0 -1
- package/dist/modes/rpc/rpc-types.d.ts.map +1 -1
- package/dist/modes/rpc/rpc-types.js.map +1 -1
- package/docs/compaction.md +210 -181
- package/docs/extensions.md +31 -20
- package/docs/json.md +3 -4
- package/docs/session-format.md +12 -21
- package/docs/sessions.md +3 -1
- package/docs/settings.md +2 -5
- package/docs/workflows.md +11 -9
- package/examples/extensions/README.md +1 -1
- package/examples/extensions/custom-compaction.ts +43 -106
- package/examples/extensions/handoff.ts +6 -44
- package/examples/extensions/trigger-compact.ts +5 -4
- package/package.json +5 -5
- package/dist/modes/interactive/components/compaction-summary-message.d.ts +0 -16
- package/dist/modes/interactive/components/compaction-summary-message.d.ts.map +0 -1
- package/dist/modes/interactive/components/compaction-summary-message.js +0 -43
- package/dist/modes/interactive/components/compaction-summary-message.js.map +0 -1
package/CHANGELOG.md
CHANGED
|
@@ -2,6 +2,30 @@
|
|
|
2
2
|
|
|
3
3
|
## [Unreleased]
|
|
4
4
|
|
|
5
|
+
## [0.8.28-alpha.1] - 2026-06-09
|
|
6
|
+
|
|
7
|
+
### Changed
|
|
8
|
+
|
|
9
|
+
- Changed Atomic compaction to be verbatim-only across manual `/compact`, automatic threshold/overflow compaction, SDK/RPC compaction, and extension-triggered compaction. All compaction now records validated `context_compaction` deletion targets and rebuilds active context with retained transcript content verbatim and unchanged. Retained file paths, exact commands, error strings, and line numbers are never paraphrased or rewritten.
|
|
10
|
+
- Changed compaction extension hooks (`session_before_compact`, `session_compact`) to receive verbatim context-compaction preparations/results and allow cancellation or locally validated deletion requests instead of custom generated summaries. The before-compact hook now yields `ContextCompactionPreparation` and accepts `{ cancel: true }` or `{ deletionRequest }` returns; the after-compact hook now receives `ContextCompactionResult` and `contextCompactionEntry`.
|
|
11
|
+
- Changed the verbatim compaction critical-overflow recovery prompt to evict in an explicit priority order when context still exceeds the token budget after compaction: removable reasoning traces are evicted first, then removable user/custom/summary context. Existing safety/retention rules (recent entries, unresolved errors, failed commands, and at least one task-bearing entry) are preserved ([#1308](https://github.com/bastani-inc/atomic/issues/1308)).
|
|
12
|
+
|
|
13
|
+
### Fixed
|
|
14
|
+
|
|
15
|
+
- Fixed `AgentSession.prompt` surfacing the confusing `No API key found for undefined` error when a model never resolved to a real provider (for example an unknown/unresolved model id reaching the prompt path as a bare string). The prompt path now fails fast with a clear `Unknown model: "<id>" did not resolve to an available provider` message, and `No API key found` guidance no longer renders a literal `undefined` provider.
|
|
16
|
+
|
|
17
|
+
### Removed
|
|
18
|
+
|
|
19
|
+
- Removed the legacy summary-compaction runtime path, summary prompts, `CompactionEntry` active-context injection, `CompactionSummaryMessage` active message type, custom compaction instructions (`CompactOptions.customInstructions`, RPC `compact.customInstructions`, `/compact [instructions]`), `compaction.keepRecentTokens` setting, summary-compaction public exports (`CompactionResult`, `CompactionPreparation`, `appendCompaction()`, `prepareCompaction()`, `generateSummary()`, summary `compact()`), and summary-compaction docs and examples. Historical `type:"compaction"` JSONL lines on disk are inert and are not injected into active LLM context.
|
|
20
|
+
|
|
21
|
+
## [0.8.27] - 2026-06-08
|
|
22
|
+
|
|
23
|
+
### Fixed
|
|
24
|
+
|
|
25
|
+
- Fixed `/compact` and auto-compaction regressions by removing the native `better-sqlite3` dependency from transcript-bound deletion tools and preserving the currently selected reasoning level for the compaction planner ([#1310](https://github.com/bastani-inc/atomic/issues/1310)).
|
|
26
|
+
|
|
27
|
+
## [0.8.27-alpha.1] - 2026-06-08
|
|
28
|
+
|
|
5
29
|
### Fixed
|
|
6
30
|
|
|
7
31
|
- Fixed `/compact` and auto-compaction regressions by removing the native `better-sqlite3` dependency from transcript-bound deletion tools and preserving the currently selected reasoning level for the compaction planner ([#1310](https://github.com/bastani-inc/atomic/issues/1310)).
|
|
@@ -4,6 +4,12 @@ All notable changes to the `pi-intercom` extension will be documented in this fi
|
|
|
4
4
|
|
|
5
5
|
## [Unreleased]
|
|
6
6
|
|
|
7
|
+
## [0.8.27] - 2026-06-08
|
|
8
|
+
|
|
9
|
+
### Changed
|
|
10
|
+
|
|
11
|
+
- Promoted the 0.8.27 prerelease package version to a stable release.
|
|
12
|
+
|
|
7
13
|
## [0.8.26] - 2026-06-08
|
|
8
14
|
|
|
9
15
|
### Changed
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@bastani/intercom",
|
|
3
|
-
"version": "0.8.
|
|
3
|
+
"version": "0.8.28-alpha.1",
|
|
4
4
|
"private": true,
|
|
5
5
|
"description": "Atomic extension providing a private coordination channel between parent and child agent sessions. Fork of: https://github.com/nicobailon/pi-intercom",
|
|
6
6
|
"contributors": [
|
|
@@ -7,6 +7,12 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
|
|
|
7
7
|
|
|
8
8
|
## [Unreleased]
|
|
9
9
|
|
|
10
|
+
## [0.8.27] - 2026-06-08
|
|
11
|
+
|
|
12
|
+
### Changed
|
|
13
|
+
|
|
14
|
+
- Promoted the 0.8.27 prerelease package version to a stable release.
|
|
15
|
+
|
|
10
16
|
## [0.8.26] - 2026-06-08
|
|
11
17
|
|
|
12
18
|
### Changed
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@bastani/mcp",
|
|
3
|
-
"version": "0.8.
|
|
3
|
+
"version": "0.8.28-alpha.1",
|
|
4
4
|
"private": true,
|
|
5
5
|
"description": "Atomic extension that adapts MCP (Model Context Protocol) servers into the coding agent. Fork of: https://github.com/nicobailon/pi-mcp-adapter",
|
|
6
6
|
"contributors": [
|
|
@@ -50,7 +50,7 @@
|
|
|
50
50
|
"dependencies": {
|
|
51
51
|
"@modelcontextprotocol/ext-apps": "^1.7.2",
|
|
52
52
|
"@modelcontextprotocol/sdk": "^1.25.1",
|
|
53
|
-
"open": "^
|
|
53
|
+
"open": "^11.0.0",
|
|
54
54
|
"typebox": "^1.1.24",
|
|
55
55
|
"zod": "^3.25.0 || ^4.0.0"
|
|
56
56
|
}
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@bastani/subagents",
|
|
3
|
-
"version": "0.8.
|
|
3
|
+
"version": "0.8.28-alpha.1",
|
|
4
4
|
"private": true,
|
|
5
5
|
"description": "Atomic extension for delegating tasks to subagents with chains, parallel execution, and TUI clarification. Fork of: https://github.com/nicobailon/pi-subagents",
|
|
6
6
|
"contributors": [
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@bastani/web-access",
|
|
3
|
-
"version": "0.8.
|
|
3
|
+
"version": "0.8.28-alpha.1",
|
|
4
4
|
"private": true,
|
|
5
5
|
"description": "Atomic extension for web search, URL fetching, GitHub repo cloning, PDF/video extraction. Fork of: https://github.com/nicobailon/pi-web-access",
|
|
6
6
|
"contributors": [
|
|
@@ -6,6 +6,26 @@ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.1.0/),
|
|
|
6
6
|
|
|
7
7
|
## [Unreleased]
|
|
8
8
|
|
|
9
|
+
## [0.8.28-alpha.1] - 2026-06-09
|
|
10
|
+
|
|
11
|
+
### Added
|
|
12
|
+
|
|
13
|
+
- Added workflow `ctx.ui.custom<T>(factory, options?)` for graph-visible custom TUI human-in-the-loop prompts. Custom prompts create `awaiting_input` prompt nodes, reuse the stage UI broker/attached stage chat component path, expose the same real TUI/theme/keybinding/component types as Atomic extension custom UI, participate in live-memory prompt replay through hashed custom identities, keep labels display-only/outside replay identity, honor prompt/run abort signals, and reject clearly in headless/unavailable UI modes. Iteration 1 supports inline graph rendering; `overlay: true` and non-TUI `workflow send` answers for arbitrary custom widget results return clear unsupported errors rather than silently degrading ([#1309](https://github.com/bastani-inc/atomic/issues/1309)).
|
|
14
|
+
|
|
15
|
+
### Changed
|
|
16
|
+
|
|
17
|
+
- Changed workflow transcript introspection to return `sessionFile`/`transcriptPath` metadata with a lazy-read prompt by default when a transcript path exists, while keeping bounded inline previews behind explicit `tail`/`limit` requests and falling back to a small preview when no path is available ([#1314](https://github.com/bastani-inc/atomic/issues/1314)).
|
|
18
|
+
|
|
19
|
+
### Fixed
|
|
20
|
+
|
|
21
|
+
- Fixed a workflow kill/abort race that could crash the entire CLI with a process-level uncaught exception (for example `No API key found for ...`). When a workflow was killed mid-prompt, the executor's `raceAbort` left the already-in-flight stage prompt promise unobserved; its later rejection escaped every workflow error boundary and became an unhandled rejection. `raceAbort` now always observes the in-flight promise in the already-aborted branch so a killed run can no longer orphan a rejecting prompt.
|
|
22
|
+
|
|
23
|
+
## [0.8.27] - 2026-06-08
|
|
24
|
+
|
|
25
|
+
### Changed
|
|
26
|
+
|
|
27
|
+
- Promoted the 0.8.27 prerelease package version to a stable release.
|
|
28
|
+
|
|
9
29
|
## [0.8.26] - 2026-06-08
|
|
10
30
|
|
|
11
31
|
### Changed
|
|
@@ -139,7 +139,9 @@ export default defineWorkflow("review-and-merge")
|
|
|
139
139
|
.compile();
|
|
140
140
|
```
|
|
141
141
|
|
|
142
|
-
Human input is runtime-only: call `ctx.ui.input`, `ctx.ui.confirm`, `ctx.ui.select`, or `ctx.ui.
|
|
142
|
+
Human input is runtime-only: call `ctx.ui.input`, `ctx.ui.confirm`, `ctx.ui.select`, `ctx.ui.editor`, or `ctx.ui.custom<T>` at the point where the workflow actually needs a decision. No builder-level declaration is required or supported.
|
|
143
|
+
|
|
144
|
+
`ctx.ui.custom<T>(factory, options?)` mounts an arbitrary focused TUI component in the attached workflow graph/stage UI and resolves with the value passed to `done(value)`. The factory uses the same real TUI/theme/keybinding/component types as Atomic extension `ctx.ui.custom`. Use `options.label` for a safe display-only graph/status label and `options.replayIdentity` (do not include secrets) when the widget's semantics can change without the callsite changing; label text is not part of replay identity. Custom widget prompts require an interactive workflow graph; they are not answerable through non-TUI `workflow send` in iteration 1. Inline graph rendering is supported; `overlay: true` is rejected clearly because nested workflow graph overlays are not safely supported yet.
|
|
143
145
|
|
|
144
146
|
### Example 4 — Compose workflows
|
|
145
147
|
|
|
@@ -458,11 +460,11 @@ Tradeoff: `Type.Unsafe<T>()` does not deeply validate at runtime — it trusts t
|
|
|
458
460
|
|
|
459
461
|
Input overrides are bare `key=value` tokens (no leading `--`). Values are JSON-parsed when possible, so numbers, booleans, and quoted strings work as expected (e.g. `count=3`, `flag=true`, `prompt="multi word value"`). A whole-object override can be passed as a single JSON token (e.g. `{"prompt":"...","count":3}`). Runtime validation is strict: unknown input keys, missing required values, type mismatches, and invalid `select` choices fail before a named workflow run starts.
|
|
460
462
|
|
|
461
|
-
Workflows always run as **background tasks** in interactive sessions — the chat editor stays free while a run executes. Press **F2** (or `/workflow connect <run-id>`) to attach to the live graph viewer; HIL prompts (`ctx.ui.input/confirm/select/editor`) appear as awaiting-input graph nodes. Press Enter on the node to answer locally, never as a modal dialog over the chat. Human input is detected when those runtime `ctx.ui.*` calls execute; workflows no longer have a declaration-time HIL flag.
|
|
463
|
+
Workflows always run as **background tasks** in interactive sessions — the chat editor stays free while a run executes. Press **F2** (or `/workflow connect <run-id>`) to attach to the live graph viewer; HIL prompts (`ctx.ui.input/confirm/select/editor/custom`) appear as awaiting-input graph nodes. Press Enter on the node to answer locally, never as a modal dialog over the chat. Human input is detected when those runtime `ctx.ui.*` calls execute; workflows no longer have a declaration-time HIL flag.
|
|
462
464
|
|
|
463
465
|
Nested `ctx.workflow(...)` calls are displayed as an expanded graph within the top-level run. `/workflow status` and run pickers list only top-level user-launched workflows, not implementation-owned child runs. The `workflow` tool's `stages`, `stage`, `transcript`, `send`, `pause`, `interrupt`, and `resume` actions can still target visible child stage ids, prefixes, or names from the expanded graph; Atomic routes the control action to the owning nested run internally. (`stages`, `stage`, `transcript`, and `send` are `workflow` tool actions, not `/workflow` slash subcommands; the slash command exposes `connect`, `attach`, `pause`, `list`, `status`, `interrupt`, `kill`, `resume`, `reload`, and `inputs`.)
|
|
464
466
|
|
|
465
|
-
Prompt answer replay is live-memory only. `StageSnapshot.promptAnswerState` reports whether continuation can replay a prompt answer (`available`), must ask again because the private ledger entry is gone (`unavailable`), or must ask again because multiple matching prompt nodes are ambiguous (`ambiguous`). Raw answers stay in a private `PromptAnswerRecord` ledger, are never serialized to snapshots or persistence, and remain resident in memory until the answer is cleared, the run is removed, or the store is cleared. Replay keys include prompt kind, message text, select choices, input/editor initial value, and hashed author callsite, so changing any of those inputs may intentionally re-ask on continuation. Empty `ctx.ui.select(..., [])` calls throw before creating a prompt node.
|
|
467
|
+
Prompt answer replay is live-memory only. `StageSnapshot.promptAnswerState` reports whether continuation can replay a prompt answer (`available`), must ask again because the private ledger entry is gone (`unavailable`), or must ask again because multiple matching prompt nodes are ambiguous (`ambiguous`). Raw answers stay in a private `PromptAnswerRecord` ledger, are never serialized to snapshots or persistence, and remain resident in memory until the answer is cleared, the run is removed, or the store is cleared. Replay keys include prompt kind, message text, select choices, input/editor initial value, custom prompt identity hash, and hashed author callsite, so changing any of those inputs may intentionally re-ask on continuation. Empty `ctx.ui.select(..., [])` calls throw before creating a prompt node. Arbitrary custom-widget answers cannot be supplied with `workflow send`; focus the `custom` awaiting-input node in the interactive graph instead.
|
|
466
468
|
|
|
467
469
|
### `workflow` tool (LLM-callable)
|
|
468
470
|
|
|
@@ -471,7 +473,7 @@ Prompt answer replay is live-memory only. `StageSnapshot.promptAnswerState` repo
|
|
|
471
473
|
```json
|
|
472
474
|
{
|
|
473
475
|
"name": "workflow",
|
|
474
|
-
"description": "Run named workflows or direct one-off task/tasks/chain workflows; discover with list/get/inputs, inspect status/stages/stage details, send prompt answers or steering, pause/resume/interrupt/kill runs, and reload workflow resources. For large stage handoffs, write context to files/artifacts, pass paths via reads, and prompt downstream agents to 'Read the file at <path>...' instead of injecting large previous text. For transcripts, prefer status/stages/stage to get sessionFile/transcriptPath, quote the exact path without rewriting separators (Windows backslashes are valid), search it with rg/grep
|
|
476
|
+
"description": "Run named workflows or direct one-off task/tasks/chain workflows; discover with list/get/inputs, inspect status/stages/stage details, send prompt answers or steering, pause/resume/interrupt/kill runs, and reload workflow resources. For large stage handoffs, write context to files/artifacts, pass paths via reads, and prompt downstream agents to 'Read the file at <path>...' instead of injecting large previous text. For transcripts, prefer status/stages/stage to get sessionFile/transcriptPath, quote the exact path without rewriting separators (Windows backslashes are valid), then search it with rg/grep and read small ranges; transcript is path-only by default when sessionFile/transcriptPath exists, explicit tail/limit returns bounded previews, and missing transcript paths fall back to a small preview.",
|
|
475
477
|
"parameters": {
|
|
476
478
|
"workflow": "string (optional) — workflow ID or normalized name",
|
|
477
479
|
"inputs": "object (optional) — key/value map of workflow inputs",
|
|
@@ -480,9 +482,9 @@ Prompt answer replay is live-memory only. `StageSnapshot.promptAnswerState` repo
|
|
|
480
482
|
"stageId": "optional stage id, prefix, or name for stage-scoped actions; cannot be combined with all:true",
|
|
481
483
|
"statusFilter": "optional stages filter: pending/running/awaiting_input/paused/blocked/completed/failed/skipped/all",
|
|
482
484
|
"format": "optional agent-facing output format: text or json",
|
|
483
|
-
"limit": "transcript-only explicit maximum number of recent entries; omitted with tail omitted uses the
|
|
485
|
+
"limit": "transcript-only explicit maximum number of recent entries; omitted with tail omitted uses the path-only default when sessionFile/transcriptPath exists",
|
|
484
486
|
"tail": "transcript-only explicit last-N entry count; overrides limit for quick recent-context checks",
|
|
485
|
-
"includeToolOutput": "transcript-only flag for
|
|
487
|
+
"includeToolOutput": "transcript-only flag for inlined snapshot preview/fallback tool-event output; does not bypass the path-only default; prefer rg/grep on the exact quoted sessionFile/transcriptPath for large outputs",
|
|
486
488
|
"text": "optional string payload for send/resume; explicit empty text answers pending prompts",
|
|
487
489
|
"response": "optional structured payload for answering pending prompts; explicit empty response is valid",
|
|
488
490
|
"message": "optional string payload for send/resume when text is not provided",
|
|
@@ -506,8 +508,8 @@ Prompt answer replay is live-memory only. `StageSnapshot.promptAnswerState` repo
|
|
|
506
508
|
|
|
507
509
|
- **`renderCall`** — renders a compact workflow call summary in the chat scroll.
|
|
508
510
|
- **`renderResult`** — renders the result or dispatch banner; live progress continues through the widget and graph viewer. Named workflow runs are background-oriented.
|
|
509
|
-
- **`transcript`** —
|
|
510
|
-
- **`send`** — answers pending stage prompts only when `text`, `response`, or `message` is present; an explicit empty string is a valid answer, while an omitted payload is a no-op. `delivery: "auto"` answers pending prompts first, then resumes paused stages, steers streaming stages, or queues a follow-up.
|
|
511
|
+
- **`transcript`** — path-only by default when a transcript file exists: use `status`, `stages`, or `stage` to identify the stage and its `sessionFile`/`transcriptPath`, quote the exact path without changing platform separators (for example, preserve Windows backslashes), then search that file with `rg`/`grep` for targeted terms and read only small surrounding ranges. Default text results include JSON-escaped `sessionFileJson`/`transcriptPathJson` lines for copy-safe path literals plus a `lazyReadPrompt`, with `entries: not inlined` so transcript bodies and tool outputs stay out of model context. Passing explicit `tail` or `limit` opts into a bounded inline preview for quick context checks. If no transcript path is available, the action falls back to a bounded preview of up to 5 recent entries with a `fallbackNote`. A registered live stage handle is used when one exists, even before live messages arrive; otherwise the action falls back to stored stage snapshots. Snapshot entries are ordered chronologically before `tail`/`limit` is applied, with terminal result/error entries kept after tool entries when timestamps are missing or tied. `includeToolOutput` applies only to inlined snapshot previews or no-path fallback previews; live session transcripts may not expose tool output.
|
|
512
|
+
- **`send`** — answers pending primitive/structured stage prompts only when `text`, `response`, or `message` is present; an explicit empty string is a valid answer, while an omitted payload is a no-op. Arbitrary `ctx.ui.custom<T>` widget prompts require the interactive workflow graph and return a clear unsupported message when targeted through `send`. `delivery: "auto"` answers pending prompts first, then resumes paused stages, steers streaming stages, or queues a follow-up.
|
|
511
513
|
- **`reload`** — refreshes workflow resources directly in-process instead of queuing a literal `/workflow reload` chat follow-up.
|
|
512
514
|
|
|
513
515
|
### F2 keyboard shortcut
|
|
@@ -520,7 +522,7 @@ Press **F2** while a workflow is running to open the DAG overlay for the active
|
|
|
520
522
|
|
|
521
523
|
For interactive use, run workflows through `/workflow <name> [key=value ...]` or let the LLM call the `workflow` tool. In non-interactive (`-p` / `--print` / `--mode json`) sessions, `/workflow <name> key=value` and LLM calls to the `workflow` tool remain available for deterministic workflows. The input picker and graph picker are disabled, top-level `ctx.ui.*` is unavailable, and stage child sessions exclude `ask_user_question`. Named workflow dispatch waits for the terminal run snapshot before returning.
|
|
522
524
|
|
|
523
|
-
Because human input is runtime-only and workflows no longer carry a declaration-time HIL marker, headless dispatch does not reject a workflow just because its source contains `ctx.ui.*`. If you copy the HIL example above into a non-interactive session, it can pass dispatch and then fail when execution reaches the prompt with an error such as `atomic-workflows: HIL ctx.ui.confirm is unavailable because Atomic runtime did not provide a UI adapter` (the primitive name varies). Run those workflows interactively, or guard/remove runtime `ctx.ui.*` calls before using headless mode.
|
|
525
|
+
Because human input is runtime-only and workflows no longer carry a declaration-time HIL marker, headless dispatch does not reject a workflow just because its source contains `ctx.ui.*`. If you copy the HIL example above into a non-interactive session, it can pass dispatch and then fail when execution reaches the prompt with an error such as `atomic-workflows: HIL ctx.ui.confirm is unavailable because Atomic runtime did not provide a UI adapter` (the primitive name varies, including `ctx.ui.custom`). Run those workflows interactively, or guard/remove runtime `ctx.ui.*` calls before using headless mode.
|
|
524
526
|
|
|
525
527
|
For library or package authoring, define reusable workflows with the builder and export the compiled definition. Hand-written objects with `__piWorkflow: true` are rejected by discovery and composition; `defineWorkflow(...).compile()` is the public authoring surface. Standalone TypeScript workflow packages can import `defineWorkflow` and `Type` from `@bastani/workflows` directly with no local `.d.ts` file or `declare module` shim. The former imperative `runWorkflow` object-form API is removed; use compiled workflow definitions with the exported `run()` / registry helpers for programmatic execution.
|
|
526
528
|
|
|
@@ -57,7 +57,7 @@ export declare const Type: Omit<typeof TypeboxType, "Any" | "Array" | "BigInt" |
|
|
|
57
57
|
Void(): TVoid;
|
|
58
58
|
};
|
|
59
59
|
export type { Static, TSchema } from "typebox";
|
|
60
|
-
export type { AgentSessionAdapter, CompleteAdapter, CompleteStageOpts, GitWorktreeSetupOptions, GitWorktreeSetupResult, PromptAdapter, PromptOptions, ResolvedInputs, RunResult, RunStatus, StageAdapters, StageStatus, StageOptions, StageContext, StageSnapshot, StageExecutionMeta, StageMcpOptions, StageOutputOptions, StagePromptOptions, StageSessionCreateOptions, StageSessionCreateResult, StageSessionRuntime, WorkflowAction, WorkflowArtifact, WorkflowChainOptions, WorkflowChainStep, WorkflowChildResult, WorkflowContextMode, WorkflowControlEvent, WorkflowCustomToolDefinition, WorkflowDetails, WorkflowDetailsMode, WorkflowDetailsStatus, WorkflowDirectOptions, WorkflowDirectTaskItem, WorkflowExecutionMode, WorkflowExecutionPolicy, WorkflowInputBindings, WorkflowInputSchema, WorkflowInputSchemaMap, WorkflowInputValues, WorkflowIntercomSummary, WorkflowMaxOutput, WorkflowMcpPort, WorkflowModelAttempt, WorkflowModelCatalogPort, WorkflowModelFallbackFields, WorkflowModelInfo, WorkflowModelUsage, WorkflowModelValue, WorkflowOutputMode, WorkflowOutputSchema, WorkflowOutputSchemaMap, WorkflowOutputValues, WorkflowParallelChainStep, WorkflowParallelOptions, WorkflowPersistencePort, WorkflowProgressSummary, WorkflowRunChildOptions, WorkflowRunOutput, WorkflowRuntimeConfig, WorkflowSerializableObject, WorkflowSerializablePrimitive, WorkflowSerializableValue, WorkflowSharedTaskDefaults, WorkflowTaskContext, WorkflowTaskContextInput, WorkflowTaskOptions, WorkflowTaskResult, WorkflowTaskSessionFields, WorkflowTaskSessionOptions, WorkflowTaskStep, WorkflowThinkingLevel, WorkflowUIAdapter, WorkflowUIContext, WorkflowWorktreeInputBinding, } from "./shared/authoring-contract.js";
|
|
60
|
+
export type { AgentSessionAdapter, CompleteAdapter, CompleteStageOpts, GitWorktreeSetupOptions, GitWorktreeSetupResult, PromptAdapter, PromptOptions, ResolvedInputs, RunResult, RunStatus, StageAdapters, StageStatus, StageOptions, StageContext, StageSnapshot, StageExecutionMeta, StageMcpOptions, StageOutputOptions, StagePromptOptions, StageSessionCreateOptions, StageSessionCreateResult, StageSessionRuntime, WorkflowAction, WorkflowArtifact, WorkflowChainOptions, WorkflowChainStep, WorkflowChildResult, WorkflowContextMode, WorkflowControlEvent, WorkflowCustomToolDefinition, WorkflowCustomUiComponent, WorkflowCustomUiFactory, WorkflowCustomUiKeybindings, WorkflowCustomUiOptions, WorkflowCustomUiOverlayHandle, WorkflowCustomUiOverlayOptions, WorkflowCustomUiTheme, WorkflowCustomUiTui, WorkflowDetails, WorkflowDetailsMode, WorkflowDetailsStatus, WorkflowDirectOptions, WorkflowDirectTaskItem, WorkflowExecutionMode, WorkflowExecutionPolicy, WorkflowInputBindings, WorkflowInputSchema, WorkflowInputSchemaMap, WorkflowInputValues, WorkflowIntercomSummary, WorkflowMaxOutput, WorkflowMcpPort, WorkflowModelAttempt, WorkflowModelCatalogPort, WorkflowModelFallbackFields, WorkflowModelInfo, WorkflowModelUsage, WorkflowModelValue, WorkflowOutputMode, WorkflowOutputSchema, WorkflowOutputSchemaMap, WorkflowOutputValues, WorkflowParallelChainStep, WorkflowParallelOptions, WorkflowPersistencePort, WorkflowProgressSummary, WorkflowRunChildOptions, WorkflowRunOutput, WorkflowRuntimeConfig, WorkflowSerializableObject, WorkflowSerializablePrimitive, WorkflowSerializableValue, WorkflowSharedTaskDefaults, WorkflowTaskContext, WorkflowTaskContextInput, WorkflowTaskOptions, WorkflowTaskResult, WorkflowTaskSessionFields, WorkflowTaskSessionOptions, WorkflowTaskStep, WorkflowThinkingLevel, WorkflowUIAdapter, WorkflowUIContext, WorkflowWorktreeInputBinding, } from "./shared/authoring-contract.js";
|
|
61
61
|
import type * as AuthoringContract from "./shared/authoring-contract.js";
|
|
62
62
|
import type { GitWorktreeSetupOptions, GitWorktreeSetupResult, ResolvedInputs, RunResult, RunStatus, StageSnapshot, WorkflowDefinition as WorkflowContractDefinition, WorkflowDetails, WorkflowDirectOptions, WorkflowDirectTaskItem, WorkflowExecutionPolicy, WorkflowInputValues, WorkflowOutputValues, WorkflowSerializableObject, WorkflowChainStep } from "./shared/authoring-contract.js";
|
|
63
63
|
declare const workflowDefinitionBrand: unique symbol;
|
|
@@ -118,13 +118,16 @@ export interface StageNode extends WorkflowSerializableObject {
|
|
|
118
118
|
readonly parentIds: readonly string[];
|
|
119
119
|
}
|
|
120
120
|
export type NoticeLevel = "info" | "warning" | "error";
|
|
121
|
-
export type PromptKind = "input" | "confirm" | "select" | "editor";
|
|
121
|
+
export type PromptKind = "input" | "confirm" | "select" | "editor" | "custom";
|
|
122
|
+
export type CustomPromptIdentitySource = "caller" | "factory" | "callsite";
|
|
122
123
|
export interface PendingPrompt extends WorkflowSerializableObject {
|
|
123
124
|
readonly id: string;
|
|
124
125
|
readonly kind: PromptKind;
|
|
125
126
|
readonly message: string;
|
|
126
127
|
readonly choices?: readonly string[];
|
|
127
128
|
readonly initial?: string;
|
|
129
|
+
readonly customIdentityHash?: string;
|
|
130
|
+
readonly customIdentitySource?: CustomPromptIdentitySource;
|
|
128
131
|
readonly createdAt: number;
|
|
129
132
|
}
|
|
130
133
|
export interface ToolEvent {
|
|
@@ -36,8 +36,10 @@ import type {
|
|
|
36
36
|
} from "../shared/store-types.js";
|
|
37
37
|
import type { WorkflowUIAdapter } from "../shared/types.js";
|
|
38
38
|
|
|
39
|
+
type BackgroundPromptKind = Exclude<PromptKind, "custom">;
|
|
40
|
+
|
|
39
41
|
interface PromptDescriptor {
|
|
40
|
-
readonly kind:
|
|
42
|
+
readonly kind: BackgroundPromptKind;
|
|
41
43
|
readonly message: string;
|
|
42
44
|
readonly choices?: readonly string[];
|
|
43
45
|
readonly initial?: string;
|
|
@@ -76,7 +76,6 @@ export function installWorkflowHilAnswerNotifications(
|
|
|
76
76
|
if (typeof send !== "function") return () => undefined;
|
|
77
77
|
|
|
78
78
|
const state = options.state ?? createWorkflowHilAnswerNotificationState();
|
|
79
|
-
let previousSnapshot = options.store.snapshot();
|
|
80
79
|
|
|
81
80
|
const emitOnce = (details: WorkflowHilAnswerNoticeDetails): void => {
|
|
82
81
|
const key = answerNoticeKey(details.runId, details.stageId, details.promptId, details.promptKind);
|
|
@@ -86,23 +85,21 @@ export function installWorkflowHilAnswerNotifications(
|
|
|
86
85
|
sendHilAnswerNotice(send, details);
|
|
87
86
|
};
|
|
88
87
|
|
|
89
|
-
const
|
|
90
|
-
for (const
|
|
91
|
-
const
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
if (
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
emitOnce(makeSimplePromptAnswerNotice(currentRun, answeredPrompt.stage, answeredPrompt.prompt, answerRecord?.value));
|
|
88
|
+
const inspectWorkflowPromptAnswers = (snapshot: StoreSnapshot): void => {
|
|
89
|
+
for (const currentRun of snapshot.runs) {
|
|
90
|
+
for (const currentStage of currentRun.stages) {
|
|
91
|
+
const prompt = workflowPromptAnswerCandidate(currentStage);
|
|
92
|
+
if (prompt === undefined) continue;
|
|
93
|
+
const answerRecord = options.store.getStagePromptAnswer(currentRun.id, currentStage.id);
|
|
94
|
+
if (answerRecord === undefined) continue;
|
|
95
|
+
if (answerRecord.promptId !== prompt.id) continue;
|
|
96
|
+
if (answerRecord.answerSource === "workflow_tool") continue;
|
|
97
|
+
emitOnce(makeSimplePromptAnswerNotice(currentRun, currentStage, prompt, answerRecord.value, answerRecord.answeredAt));
|
|
100
98
|
}
|
|
101
99
|
}
|
|
102
|
-
previousSnapshot = snapshot;
|
|
103
100
|
};
|
|
104
101
|
|
|
105
|
-
const unsubscribeStore = options.store.subscribe(
|
|
102
|
+
const unsubscribeStore = options.store.subscribe(inspectWorkflowPromptAnswers);
|
|
106
103
|
const unsubscribeBroker = options.stageUiBroker?.onStagePromptResolved((event) => {
|
|
107
104
|
if (event.answerSource === "workflow_tool") return;
|
|
108
105
|
const answeredStage = findStageSnapshot(options.store.snapshot(), event.runId, event.stageId);
|
|
@@ -180,17 +177,11 @@ function sendHilAnswerNotice(
|
|
|
180
177
|
}
|
|
181
178
|
}
|
|
182
179
|
|
|
183
|
-
function
|
|
184
|
-
|
|
185
|
-
currentRun: RunSnapshot,
|
|
186
|
-
): { stage: StageSnapshot; prompt: PendingPrompt } | undefined {
|
|
187
|
-
const prompt = previousStage.pendingPrompt;
|
|
180
|
+
function workflowPromptAnswerCandidate(stage: StageSnapshot): PendingPrompt | undefined {
|
|
181
|
+
const prompt = stage.promptFootprint;
|
|
188
182
|
if (prompt === undefined) return undefined;
|
|
189
|
-
|
|
190
|
-
|
|
191
|
-
if (currentStage.pendingPrompt !== undefined) return undefined;
|
|
192
|
-
if (currentStage.promptAnswerState !== "available") return undefined;
|
|
193
|
-
return { stage: currentStage, prompt };
|
|
183
|
+
if (stage.promptAnswerState !== "available") return undefined;
|
|
184
|
+
return prompt;
|
|
194
185
|
}
|
|
195
186
|
|
|
196
187
|
function findStageSnapshot(
|
|
@@ -215,6 +206,7 @@ function makeSimplePromptAnswerNotice(
|
|
|
215
206
|
stage: StageSnapshot,
|
|
216
207
|
prompt: PendingPrompt,
|
|
217
208
|
answer: unknown,
|
|
209
|
+
answeredAt: number,
|
|
218
210
|
): WorkflowHilAnswerNoticeDetails {
|
|
219
211
|
return {
|
|
220
212
|
kind: "hil_answered",
|
|
@@ -226,7 +218,7 @@ function makeSimplePromptAnswerNotice(
|
|
|
226
218
|
promptId: prompt.id,
|
|
227
219
|
promptKind: prompt.kind,
|
|
228
220
|
promptMessage: truncateAnswerSnippet(prompt.message),
|
|
229
|
-
answeredAt
|
|
221
|
+
answeredAt,
|
|
230
222
|
answerAvailable: true,
|
|
231
223
|
answerIncluded: true,
|
|
232
224
|
answerSummary: formatAnswerSummary(answer),
|
|
@@ -129,7 +129,7 @@ export const WORKFLOW_TOOL_DESCRIPTION =
|
|
|
129
129
|
"For large stage handoffs, write context to files/artifacts, pass paths via reads, and prompt downstream agents to 'Read the file at <path>...' instead of injecting large previous text. " +
|
|
130
130
|
"For transcripts, prefer status/stages/stage to get sessionFile/transcriptPath, " +
|
|
131
131
|
"quote the exact path without rewriting separators (Windows backslashes are valid), " +
|
|
132
|
-
"search it with rg/grep
|
|
132
|
+
"then search it with rg/grep and read small ranges; transcript is path-only by default when sessionFile/transcriptPath exists, explicit tail/limit returns bounded previews, and missing transcript paths fall back to a small preview.";
|
|
133
133
|
|
|
134
134
|
// ---------------------------------------------------------------------------
|
|
135
135
|
// Minimal ExtensionAPI structural types
|
|
@@ -644,8 +644,10 @@ function renderTranscriptToolContent(
|
|
|
644
644
|
if (result.transcriptPath) lines.push(`transcriptPathJson: ${JSON.stringify(result.transcriptPath)}`);
|
|
645
645
|
if (result.entryCount !== undefined) lines.push(`availableEntries: ${result.entryCount}`);
|
|
646
646
|
if (result.entryLimit !== undefined) lines.push(`entryLimit: ${result.entryLimit}`);
|
|
647
|
+
if (result.lazyReadPrompt) lines.push(`lazyReadPrompt: ${result.lazyReadPrompt}`);
|
|
648
|
+
if (result.fallbackNote) lines.push(`fallbackNote: ${result.fallbackNote}`);
|
|
647
649
|
if (result.entries.length === 0) {
|
|
648
|
-
lines.push("entries: none");
|
|
650
|
+
lines.push(result.inlineMode === "path_only" || result.lazyReadPrompt ? "entries: not inlined" : "entries: none");
|
|
649
651
|
return lines.join("\n");
|
|
650
652
|
}
|
|
651
653
|
lines.push("entries:");
|
|
@@ -702,6 +704,10 @@ function renderStagesToolContent(
|
|
|
702
704
|
lines.push("inputRequest:");
|
|
703
705
|
lines.push(JSON.stringify(stage.inputRequest, null, 2));
|
|
704
706
|
}
|
|
707
|
+
if (stage.promptFootprint !== undefined) {
|
|
708
|
+
lines.push("promptFootprint:");
|
|
709
|
+
lines.push(JSON.stringify(stage.promptFootprint, null, 2));
|
|
710
|
+
}
|
|
705
711
|
});
|
|
706
712
|
return lines.join("\n");
|
|
707
713
|
}
|
|
@@ -800,6 +806,7 @@ type WorkflowStageSummary = {
|
|
|
800
806
|
awaitingInputSince?: number;
|
|
801
807
|
pendingPrompt?: StageSnapshot["pendingPrompt"];
|
|
802
808
|
inputRequest?: StageSnapshot["inputRequest"];
|
|
809
|
+
promptFootprint?: StageSnapshot["promptFootprint"];
|
|
803
810
|
};
|
|
804
811
|
|
|
805
812
|
type WorkflowTranscriptEntry = {
|
|
@@ -842,6 +849,9 @@ function summarizeStage(stage: StageSnapshot): WorkflowStageSummary {
|
|
|
842
849
|
inputRequest: stage.inputRequest === undefined
|
|
843
850
|
? undefined
|
|
844
851
|
: structuredClone(stage.inputRequest),
|
|
852
|
+
promptFootprint: stage.promptFootprint === undefined
|
|
853
|
+
? undefined
|
|
854
|
+
: structuredClone(stage.promptFootprint),
|
|
845
855
|
};
|
|
846
856
|
}
|
|
847
857
|
|
|
@@ -854,6 +864,12 @@ type TranscriptEntrySelection = {
|
|
|
854
864
|
entryLimit?: number;
|
|
855
865
|
};
|
|
856
866
|
|
|
867
|
+
type WorkflowTranscriptResult = Extract<WorkflowToolResult, { action: "transcript" }>;
|
|
868
|
+
|
|
869
|
+
function isTranscriptPreviewExplicit(args: WorkflowToolArgs): boolean {
|
|
870
|
+
return args.tail !== undefined || args.limit !== undefined;
|
|
871
|
+
}
|
|
872
|
+
|
|
857
873
|
function requestedTranscriptEntryLimit(args: WorkflowToolArgs): number {
|
|
858
874
|
const raw = args.tail ?? args.limit;
|
|
859
875
|
if (raw === undefined) return DEFAULT_TRANSCRIPT_LIMIT;
|
|
@@ -891,6 +907,80 @@ function selectTranscriptEntries(
|
|
|
891
907
|
};
|
|
892
908
|
}
|
|
893
909
|
|
|
910
|
+
function transcriptLazyReadPrompt(path: string): string {
|
|
911
|
+
return `Transcript not inlined to protect context. Read it lazily from ${path} with your file read tools (read small ranges; rg/grep for targeted lookups).`;
|
|
912
|
+
}
|
|
913
|
+
|
|
914
|
+
function transcriptFallbackNote(limit: number): string {
|
|
915
|
+
return `No transcript file path is available for this stage; falling back to a bounded inline preview of up to ${limit} recent ${limit === 1 ? "entry" : "entries"}.`;
|
|
916
|
+
}
|
|
917
|
+
|
|
918
|
+
/**
|
|
919
|
+
* Shape a transcript tool result, keeping the context-safe path-only default
|
|
920
|
+
* the cheap hot path for the large runs #1314 protects against.
|
|
921
|
+
*
|
|
922
|
+
* `buildEntries` is a thunk so the default case (a transcript file path exists
|
|
923
|
+
* and no explicit `tail`/`limit` was requested) never materializes entry bodies
|
|
924
|
+
* just to discard them. Only the caller-provided `entryCount` is needed for the
|
|
925
|
+
* advisory count, which matches what `buildEntries()` would yield. The thunk is
|
|
926
|
+
* invoked solely for the explicit-preview and no-path fallback branches.
|
|
927
|
+
*/
|
|
928
|
+
function shapeTranscriptResult(input: {
|
|
929
|
+
runId: string;
|
|
930
|
+
stageId: string;
|
|
931
|
+
source: "live" | "snapshot";
|
|
932
|
+
entryCount: number;
|
|
933
|
+
buildEntries: () => readonly WorkflowTranscriptEntry[];
|
|
934
|
+
args: WorkflowToolArgs;
|
|
935
|
+
sessionId?: string | undefined;
|
|
936
|
+
sessionFile?: string | undefined;
|
|
937
|
+
transcriptPath?: string | undefined;
|
|
938
|
+
}): WorkflowTranscriptResult {
|
|
939
|
+
// `transcriptPath` already falls back to `sessionFile`, so it is the single
|
|
940
|
+
// resolved path the agent should lazily read.
|
|
941
|
+
const transcriptPath = input.transcriptPath ?? input.sessionFile;
|
|
942
|
+
if (transcriptPath !== undefined && !isTranscriptPreviewExplicit(input.args)) {
|
|
943
|
+
const result: WorkflowTranscriptResult = {
|
|
944
|
+
action: "transcript",
|
|
945
|
+
runId: input.runId,
|
|
946
|
+
stageId: input.stageId,
|
|
947
|
+
source: input.source,
|
|
948
|
+
entries: [],
|
|
949
|
+
// `truncated` here means "more transcript exists on disk than was inlined"
|
|
950
|
+
// (everything, since the default inlines nothing), not "an explicit limit
|
|
951
|
+
// clipped results". It only drives the cosmetic "(truncated)" notice
|
|
952
|
+
// suffix; no consumer re-fetches on it.
|
|
953
|
+
truncated: input.entryCount > 0,
|
|
954
|
+
entryCount: input.entryCount,
|
|
955
|
+
entryLimit: 0,
|
|
956
|
+
lazyReadPrompt: transcriptLazyReadPrompt(transcriptPath),
|
|
957
|
+
inlineMode: "path_only",
|
|
958
|
+
};
|
|
959
|
+
if (input.sessionId !== undefined) result.sessionId = input.sessionId;
|
|
960
|
+
if (input.sessionFile !== undefined) result.sessionFile = input.sessionFile;
|
|
961
|
+
result.transcriptPath = transcriptPath;
|
|
962
|
+
return result;
|
|
963
|
+
}
|
|
964
|
+
|
|
965
|
+
const limited = selectTranscriptEntries(input.buildEntries(), input.args);
|
|
966
|
+
const result: WorkflowTranscriptResult = {
|
|
967
|
+
action: "transcript",
|
|
968
|
+
runId: input.runId,
|
|
969
|
+
stageId: input.stageId,
|
|
970
|
+
source: input.source,
|
|
971
|
+
entries: limited.entries,
|
|
972
|
+
truncated: limited.truncated,
|
|
973
|
+
entryCount: limited.entryCount,
|
|
974
|
+
entryLimit: limited.entryLimit,
|
|
975
|
+
inlineMode: transcriptPath === undefined ? "fallback_preview" : "preview",
|
|
976
|
+
};
|
|
977
|
+
if (input.sessionId !== undefined) result.sessionId = input.sessionId;
|
|
978
|
+
if (input.sessionFile !== undefined) result.sessionFile = input.sessionFile;
|
|
979
|
+
if (transcriptPath !== undefined) result.transcriptPath = transcriptPath;
|
|
980
|
+
if (transcriptPath === undefined) result.fallbackNote = transcriptFallbackNote(limited.entryLimit ?? DEFAULT_TRANSCRIPT_LIMIT);
|
|
981
|
+
return result;
|
|
982
|
+
}
|
|
983
|
+
|
|
894
984
|
function messageText(content: MessageLike["content"]): string | undefined {
|
|
895
985
|
if (typeof content === "string") return content;
|
|
896
986
|
if (!Array.isArray(content)) return undefined;
|
|
@@ -1463,33 +1553,40 @@ export function makeExecuteWorkflowTool(
|
|
|
1463
1553
|
if (liveHandle !== undefined) {
|
|
1464
1554
|
const sessionFile = liveHandle.sessionFile ?? snapshot?.sessionFile;
|
|
1465
1555
|
const sessionId = liveHandle.sessionId ?? snapshot?.sessionId;
|
|
1466
|
-
|
|
1467
|
-
liveHandle.messages.map((m) => transcriptEntryFromMessage(m as MessageLike)),
|
|
1468
|
-
args,
|
|
1469
|
-
);
|
|
1470
|
-
return {
|
|
1471
|
-
action: "transcript",
|
|
1556
|
+
return shapeTranscriptResult({
|
|
1472
1557
|
runId: stageRunId,
|
|
1473
1558
|
stageId: stage.stageId,
|
|
1474
1559
|
source: "live",
|
|
1475
|
-
|
|
1560
|
+
entryCount: liveHandle.messages.length,
|
|
1561
|
+
buildEntries: () =>
|
|
1562
|
+
liveHandle.messages.map((m) => transcriptEntryFromMessage(m as MessageLike)),
|
|
1563
|
+
args,
|
|
1476
1564
|
sessionId,
|
|
1477
1565
|
sessionFile,
|
|
1478
1566
|
transcriptPath: sessionFile,
|
|
1479
|
-
};
|
|
1567
|
+
});
|
|
1480
1568
|
}
|
|
1481
|
-
const
|
|
1482
|
-
const
|
|
1483
|
-
|
|
1484
|
-
|
|
1569
|
+
const snapshotSessionFile = snapshot?.sessionFile;
|
|
1570
|
+
const includeSnapshotOutput = args.includeToolOutput === true && (
|
|
1571
|
+
isTranscriptPreviewExplicit(args) || snapshotSessionFile === undefined
|
|
1572
|
+
);
|
|
1573
|
+
// Cheap count matches `snapshotTranscriptEntries(...).length` (one entry
|
|
1574
|
+
// per tool event plus the optional terminal result/error entries)
|
|
1575
|
+
// without building bodies for the path-only default.
|
|
1576
|
+
const snapshotEntryCount = (snapshot?.toolEvents?.length ?? 0)
|
|
1577
|
+
+ (snapshot?.result !== undefined ? 1 : 0)
|
|
1578
|
+
+ (snapshot?.error !== undefined ? 1 : 0);
|
|
1579
|
+
return shapeTranscriptResult({
|
|
1485
1580
|
runId: stageRunId,
|
|
1486
1581
|
stageId: stage.stageId,
|
|
1487
1582
|
source: "snapshot",
|
|
1488
|
-
|
|
1583
|
+
entryCount: snapshotEntryCount,
|
|
1584
|
+
buildEntries: () => snapshotTranscriptEntries(snapshot, includeSnapshotOutput),
|
|
1585
|
+
args,
|
|
1489
1586
|
sessionId: snapshot?.sessionId,
|
|
1490
|
-
sessionFile:
|
|
1491
|
-
transcriptPath:
|
|
1492
|
-
};
|
|
1587
|
+
sessionFile: snapshotSessionFile,
|
|
1588
|
+
transcriptPath: snapshotSessionFile,
|
|
1589
|
+
});
|
|
1493
1590
|
}
|
|
1494
1591
|
|
|
1495
1592
|
case "send": {
|
|
@@ -1543,6 +1640,24 @@ export function makeExecuteWorkflowTool(
|
|
|
1543
1640
|
ok ? `Answered input request ${brokerPrompt.id}.` : `No matching pending input request ${brokerPrompt.id}.`,
|
|
1544
1641
|
);
|
|
1545
1642
|
}
|
|
1643
|
+
const customPrompt = snapshot?.status === "awaiting_input" && snapshot.promptFootprint?.kind === "custom"
|
|
1644
|
+
? snapshot.promptFootprint
|
|
1645
|
+
: undefined;
|
|
1646
|
+
const targetsCustomPrompt =
|
|
1647
|
+
customPrompt !== undefined &&
|
|
1648
|
+
(args.promptId === undefined || args.promptId === customPrompt.id) &&
|
|
1649
|
+
(requestedDelivery === "answer" ||
|
|
1650
|
+
args.promptId !== undefined ||
|
|
1651
|
+
requestedDelivery === "auto");
|
|
1652
|
+
if (targetsCustomPrompt && customPrompt !== undefined) {
|
|
1653
|
+
return workflowSendResult(
|
|
1654
|
+
stageRunId,
|
|
1655
|
+
stage.stageId,
|
|
1656
|
+
"answer",
|
|
1657
|
+
"noop",
|
|
1658
|
+
`Custom UI prompt ${customPrompt.id} requires the interactive workflow graph; arbitrary ctx.ui.custom<T> results cannot be answered through workflow send.`,
|
|
1659
|
+
);
|
|
1660
|
+
}
|
|
1546
1661
|
const targetsPrompt =
|
|
1547
1662
|
requestedDelivery === "answer" ||
|
|
1548
1663
|
args.promptId !== undefined ||
|