@bastani/atomic 0.8.19 → 0.8.20-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.
- package/CHANGELOG.md +13 -0
- package/dist/builtin/intercom/package.json +1 -1
- package/dist/builtin/mcp/CHANGELOG.md +5 -0
- package/dist/builtin/mcp/package.json +2 -2
- package/dist/builtin/subagents/CHANGELOG.md +12 -2
- package/dist/builtin/subagents/agents/code-simplifier.md +1 -1
- package/dist/builtin/subagents/agents/codebase-analyzer.md +1 -1
- package/dist/builtin/subagents/agents/codebase-online-researcher.md +1 -1
- package/dist/builtin/subagents/agents/codebase-research-analyzer.md +1 -1
- package/dist/builtin/subagents/agents/debugger.md +1 -1
- package/dist/builtin/subagents/package.json +1 -1
- package/dist/builtin/subagents/skills/subagent/SKILL.md +12 -12
- package/dist/builtin/subagents/src/agents/agent-management.ts +16 -11
- package/dist/builtin/subagents/src/agents/skills.ts +13 -1
- package/dist/builtin/subagents/src/extension/index.ts +14 -3
- package/dist/builtin/subagents/src/runs/background/async-execution.ts +8 -0
- package/dist/builtin/subagents/src/runs/background/run-status.ts +2 -3
- package/dist/builtin/subagents/src/runs/background/subagent-runner.ts +11 -1
- package/dist/builtin/subagents/src/runs/foreground/chain-clarify.ts +2 -2
- package/dist/builtin/subagents/src/runs/foreground/chain-execution.ts +31 -23
- package/dist/builtin/subagents/src/runs/foreground/execution.ts +13 -7
- package/dist/builtin/subagents/src/runs/foreground/subagent-executor.ts +160 -93
- package/dist/builtin/subagents/src/runs/shared/parallel-utils.ts +1 -0
- package/dist/builtin/subagents/src/runs/shared/run-history.ts +1 -1
- package/dist/builtin/subagents/src/shared/settings.ts +1 -0
- package/dist/builtin/subagents/src/shared/types.ts +78 -4
- package/dist/builtin/subagents/src/tui/render.ts +203 -19
- package/dist/builtin/web-access/CHANGELOG.md +5 -0
- package/dist/builtin/web-access/package.json +2 -2
- package/dist/builtin/workflows/CHANGELOG.md +19 -0
- package/dist/builtin/workflows/README.md +22 -3
- package/dist/builtin/workflows/builtin/deep-research-codebase.ts +1 -1
- package/dist/builtin/workflows/builtin/open-claude-design.ts +12 -4
- package/dist/builtin/workflows/builtin/ralph.ts +2 -2
- package/dist/builtin/workflows/package.json +1 -1
- package/dist/builtin/workflows/src/extension/config-loader.ts +68 -0
- package/dist/builtin/workflows/src/extension/index.ts +246 -55
- package/dist/builtin/workflows/src/extension/lifecycle-notifications.ts +372 -0
- package/dist/builtin/workflows/src/extension/render-call.ts +1 -1
- package/dist/builtin/workflows/src/extension/wiring.ts +32 -3
- package/dist/builtin/workflows/src/runs/background/status.ts +14 -74
- package/dist/builtin/workflows/src/shared/persistence-restore.ts +5 -3
- package/dist/builtin/workflows/src/tui/chat-surface-message.ts +3 -13
- package/dist/builtin/workflows/src/tui/inline-form-overlay.ts +2 -10
- package/dist/builtin/workflows/src/tui/overlay-adapter.ts +5 -5
- package/dist/builtin/workflows/src/tui/session-confirm.ts +6 -7
- package/dist/builtin/workflows/src/tui/session-picker.ts +18 -14
- package/dist/builtin/workflows/src/tui/status-list.ts +2 -2
- package/dist/builtin/workflows/src/tui/store-widget-installer.ts +125 -30
- package/dist/config.d.ts +1 -0
- package/dist/config.d.ts.map +1 -1
- package/dist/config.js +1 -0
- package/dist/config.js.map +1 -1
- package/dist/core/agent-session.d.ts +4 -1
- package/dist/core/agent-session.d.ts.map +1 -1
- package/dist/core/agent-session.js +2 -1
- package/dist/core/agent-session.js.map +1 -1
- package/dist/core/atomic-guide-command.d.ts.map +1 -1
- package/dist/core/atomic-guide-command.js +3 -2
- package/dist/core/atomic-guide-command.js.map +1 -1
- package/dist/core/extensions/index.d.ts +1 -1
- package/dist/core/extensions/index.d.ts.map +1 -1
- package/dist/core/extensions/index.js.map +1 -1
- package/dist/core/extensions/runner.d.ts +3 -2
- package/dist/core/extensions/runner.d.ts.map +1 -1
- package/dist/core/extensions/runner.js +6 -1
- package/dist/core/extensions/runner.js.map +1 -1
- package/dist/core/extensions/types.d.ts +13 -0
- package/dist/core/extensions/types.d.ts.map +1 -1
- package/dist/core/extensions/types.js.map +1 -1
- package/dist/core/model-resolver.d.ts.map +1 -1
- package/dist/core/model-resolver.js +63 -17
- package/dist/core/model-resolver.js.map +1 -1
- package/dist/core/output-guard.d.ts.map +1 -1
- package/dist/core/output-guard.js +29 -0
- package/dist/core/output-guard.js.map +1 -1
- package/dist/core/sdk.d.ts +3 -1
- package/dist/core/sdk.d.ts.map +1 -1
- package/dist/core/sdk.js +1 -0
- package/dist/core/sdk.js.map +1 -1
- package/dist/core/system-prompt.d.ts.map +1 -1
- package/dist/core/system-prompt.js +1 -1
- package/dist/core/system-prompt.js.map +1 -1
- package/dist/index.d.ts +2 -2
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +1 -1
- package/dist/index.js.map +1 -1
- package/dist/modes/interactive/interactive-mode.d.ts.map +1 -1
- package/dist/modes/interactive/interactive-mode.js +46 -13
- package/dist/modes/interactive/interactive-mode.js.map +1 -1
- package/dist/utils/pi-user-agent.d.ts.map +1 -1
- package/dist/utils/pi-user-agent.js +2 -1
- package/dist/utils/pi-user-agent.js.map +1 -1
- package/dist/utils/syntax-highlight.d.ts.map +1 -1
- package/dist/utils/syntax-highlight.js +1 -1
- package/dist/utils/syntax-highlight.js.map +1 -1
- package/dist/utils/tools-manager.d.ts.map +1 -1
- package/dist/utils/tools-manager.js +3 -5
- package/dist/utils/tools-manager.js.map +1 -1
- package/docs/models.md +52 -52
- package/docs/quickstart.md +2 -2
- package/docs/workflows.md +22 -5
- package/package.json +9 -9
package/CHANGELOG.md
CHANGED
|
@@ -2,6 +2,19 @@
|
|
|
2
2
|
|
|
3
3
|
## [Unreleased]
|
|
4
4
|
|
|
5
|
+
## [0.8.20-0] - 2026-05-29
|
|
6
|
+
|
|
7
|
+
### Added
|
|
8
|
+
|
|
9
|
+
- Added session-scoped `orchestrationContext` support to SDK agent sessions and extension contexts for workflow-stage policy enforcement.
|
|
10
|
+
- Added support for the Claude Opus 4.8 model across model configuration, selection, and validation via the `@earendil-works/pi-ai` 0.77.0 upgrade ([#1097](https://github.com/flora131/atomic/issues/1097)).
|
|
11
|
+
|
|
12
|
+
### Changed
|
|
13
|
+
|
|
14
|
+
- Upgraded the pi runtime packages (`@earendil-works/pi-agent-core`, `@earendil-works/pi-ai`, `@earendil-works/pi-tui`) from 0.75.5 to 0.77.0 and bumped `@modelcontextprotocol/ext-apps` to 1.7.2, `highlight.js` to 11.x, `linkedom` to 0.18.x, `undici` to 8.x, and `vitest` (dev) to 4.x.
|
|
15
|
+
- Switched the `highlight.js` import to the package-root default export and replaced the Node stream pipeline in the tools downloader with `Bun.write()` to align with the upgraded dependencies.
|
|
16
|
+
- Pinned the footer (model + cwd identity) directly under the editor and moved below-editor widgets beneath it (separated by a blank line), so transient run status such as the workflow companion counter renders at the very bottom instead of separating the footer from the input. Stacked below-editor widgets (e.g. the async-subagent widget and the workflow run counter) are also separated from each other by a blank line. Rendering below-editor widgets last keeps a live widget at the bottom of the buffer (within the viewport), preserving the widget resize-flicker fix. Extension-provided custom footers are now swapped in place (rather than appended), so installing a custom footer keeps the below-editor widget container as the last UI child and does not regress this ordering ([#1109](https://github.com/flora131/atomic/issues/1109)).
|
|
17
|
+
|
|
5
18
|
## [0.8.19] - 2026-05-27
|
|
6
19
|
|
|
7
20
|
### Changed
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@bastani/intercom",
|
|
3
|
-
"version": "0.8.
|
|
3
|
+
"version": "0.8.20-0",
|
|
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,11 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
|
|
|
7
7
|
|
|
8
8
|
## [Unreleased]
|
|
9
9
|
|
|
10
|
+
## [0.8.20-0] - 2026-05-29
|
|
11
|
+
|
|
12
|
+
### Changed
|
|
13
|
+
- Bumped `@modelcontextprotocol/ext-apps` to 1.7.2 to align with the pi 0.77.0 upgrade.
|
|
14
|
+
|
|
10
15
|
## [0.8.18] - 2026-05-27
|
|
11
16
|
|
|
12
17
|
### Changed
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@bastani/mcp",
|
|
3
|
-
"version": "0.8.
|
|
3
|
+
"version": "0.8.20-0",
|
|
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": [
|
|
@@ -48,7 +48,7 @@
|
|
|
48
48
|
}
|
|
49
49
|
},
|
|
50
50
|
"dependencies": {
|
|
51
|
-
"@modelcontextprotocol/ext-apps": "^1.
|
|
51
|
+
"@modelcontextprotocol/ext-apps": "^1.7.2",
|
|
52
52
|
"@modelcontextprotocol/sdk": "^1.25.1",
|
|
53
53
|
"open": "^10.2.0",
|
|
54
54
|
"typebox": "^1.1.24",
|
|
@@ -1,5 +1,17 @@
|
|
|
1
1
|
# Changelog
|
|
2
2
|
|
|
3
|
+
## [Unreleased]
|
|
4
|
+
|
|
5
|
+
## [0.8.20-0] - 2026-05-29
|
|
6
|
+
|
|
7
|
+
### Fixed
|
|
8
|
+
|
|
9
|
+
- Fixed the subagent running spinner freezing/stuttering and the surrounding TUI flickering while subagents run: the running glyph is now driven by wall-clock time with a steady re-render ticker (result cards, slash result cards, and the async-agents widget), so it animates smoothly and continuously instead of only advancing when progress data changes. Per-frame diffs stay limited to the spinner glyph cell, so the differential renderer keeps doing partial redraws (no full-screen clear / flicker), and the ticker is torn down on completion, reload, and session shutdown ([#1084](https://github.com/flora131/atomic/issues/1084)).
|
|
10
|
+
- Moved the async-agents (background subagent) widget from above the editor to below it (`belowEditor`). The widget animates a running glyph and elapsed labels every tick; pi-tui full-clears the screen+scrollback whenever a changed line sits above the viewport fold, so an above-editor widget flickered once the bottom region grew tall and pushed it above the fold. Rendering below the editor keeps the live line within the bottom viewport (flicker-free) and matches the workflow companion widget's placement ([#1109](https://github.com/flora131/atomic/issues/1109)).
|
|
11
|
+
- Hardened workflow-stage subagent guard propagation tests with an internal executor runtime DI seam ([#1088](https://github.com/flora131/atomic/issues/1088)).
|
|
12
|
+
- Capped subagent fanout spawned from workflow stages to a single child level with a workflow-specific nested-subagent error.
|
|
13
|
+
- Fixed builtin subagent skill resolution from project cwd ([#1087](https://github.com/flora131/atomic/issues/1087)).
|
|
14
|
+
|
|
3
15
|
## [0.24.3] - 2026-05-14
|
|
4
16
|
|
|
5
17
|
### Added
|
|
@@ -9,8 +21,6 @@
|
|
|
9
21
|
### Fixed
|
|
10
22
|
- Let `async: true` chain tool calls run in the background when `clarify` is omitted, and avoid showing the async badge for explicit foreground clarify runs.
|
|
11
23
|
|
|
12
|
-
## [Unreleased]
|
|
13
|
-
|
|
14
24
|
## [0.8.18] - 2026-05-27
|
|
15
25
|
|
|
16
26
|
### Changed
|
|
@@ -9,7 +9,7 @@ description: |
|
|
|
9
9
|
- Code that has gotten messy after several iterations.
|
|
10
10
|
tools: read, edit, write, grep, find, ls, bash
|
|
11
11
|
model: openai/gpt-5.5
|
|
12
|
-
fallbackModels: openai-codex/gpt-5.5, github-copilot/gpt-5.5, anthropic/claude-opus-4-
|
|
12
|
+
fallbackModels: openai-codex/gpt-5.5, github-copilot/gpt-5.5, anthropic/claude-opus-4-8, github-copilot/claude-opus-4.7
|
|
13
13
|
thinking: low
|
|
14
14
|
---
|
|
15
15
|
|
|
@@ -3,7 +3,7 @@ name: codebase-analyzer
|
|
|
3
3
|
description: Analyzes codebase implementation details. Call the codebase-analyzer agent when you need to find detailed information about specific components.
|
|
4
4
|
tools: read, grep, find, ls, bash
|
|
5
5
|
model: openai/gpt-5.5
|
|
6
|
-
fallbackModels: openai-codex/gpt-5.5, github-copilot/gpt-5.5, anthropic/claude-opus-4-
|
|
6
|
+
fallbackModels: openai-codex/gpt-5.5, github-copilot/gpt-5.5, anthropic/claude-opus-4-8, github-copilot/claude-opus-4.7
|
|
7
7
|
thinking: low
|
|
8
8
|
---
|
|
9
9
|
|
|
@@ -3,7 +3,7 @@ name: codebase-online-researcher
|
|
|
3
3
|
description: Online research for up-to-date documentation and library-source knowledge. Use when you need authoritative external information — official docs, ecosystem context, version-specific behavior, GitHub permalinks into open-source libraries, or video tutorials.
|
|
4
4
|
tools: read, grep, find, ls, bash, write, web_search, fetch_content, get_search_content
|
|
5
5
|
model: openai/gpt-5.5
|
|
6
|
-
fallbackModels: openai-codex/gpt-5.5, github-copilot/gpt-5.5, anthropic/claude-opus-4-
|
|
6
|
+
fallbackModels: openai-codex/gpt-5.5, github-copilot/gpt-5.5, anthropic/claude-opus-4-8, github-copilot/claude-opus-4.7
|
|
7
7
|
thinking: low
|
|
8
8
|
skills: playwright-cli
|
|
9
9
|
---
|
|
@@ -3,7 +3,7 @@ name: codebase-research-analyzer
|
|
|
3
3
|
description: Analyzes local research documents to extract high-value insights, decisions, and technical details while filtering out noise. Use this when you want to deep dive on a research topic or understand the rationale behind decisions.
|
|
4
4
|
tools: read, grep, find, ls, bash
|
|
5
5
|
model: openai/gpt-5.5
|
|
6
|
-
fallbackModels: openai-codex/gpt-5.5, github-copilot/gpt-5.5, anthropic/claude-opus-4-
|
|
6
|
+
fallbackModels: openai-codex/gpt-5.5, github-copilot/gpt-5.5, anthropic/claude-opus-4-8, github-copilot/claude-opus-4.7
|
|
7
7
|
thinking: low
|
|
8
8
|
---
|
|
9
9
|
|
|
@@ -3,7 +3,7 @@ name: debugger
|
|
|
3
3
|
description: Debug errors, test failures, and unexpected behavior. Use PROACTIVELY when encountering issues, analyzing stack traces, or investigating system problems.
|
|
4
4
|
tools: read, edit, write, grep, find, ls, bash, web_search, fetch_content, get_search_content
|
|
5
5
|
model: openai/gpt-5.5
|
|
6
|
-
fallbackModels: openai-codex/gpt-5.5, github-copilot/gpt-5.5, anthropic/claude-opus-4-
|
|
6
|
+
fallbackModels: openai-codex/gpt-5.5, github-copilot/gpt-5.5, anthropic/claude-opus-4-8, github-copilot/claude-opus-4.7
|
|
7
7
|
thinking: high
|
|
8
8
|
skills: tdd, playwright-cli
|
|
9
9
|
---
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@bastani/subagents",
|
|
3
|
-
"version": "0.8.
|
|
3
|
+
"version": "0.8.20-0",
|
|
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": [
|
|
@@ -118,18 +118,18 @@ Use this after implementation when the user wants cleanup review or when a final
|
|
|
118
118
|
|
|
119
119
|
Builtin agents load at the lowest priority. Project agents override user agents, and user/project agents override builtins with the same name.
|
|
120
120
|
|
|
121
|
-
| Agent
|
|
122
|
-
|
|
123
|
-
| `codebase-locator`
|
|
124
|
-
| `codebase-analyzer`
|
|
125
|
-
| `codebase-pattern-finder`
|
|
126
|
-
| `codebase-research-locator`
|
|
127
|
-
| `codebase-research-analyzer` | Extract decisions and constraints from prior docs
|
|
128
|
-
| `codebase-online-researcher` | Web research with authoritative sources
|
|
129
|
-
| `code-simplifier`
|
|
130
|
-
| `debugger`
|
|
131
|
-
|
|
132
|
-
Each builtin declares an explicit `model` and `fallbackModels` chain (typically `github-copilot/<same>`, then `anthropic/claude-opus-4-
|
|
121
|
+
| Agent | Purpose | Default model | Thinking | Tools | Notes |
|
|
122
|
+
| ---------------------------- | ----------------------------------------------------------------- | --------------------- | -------- | -------------------------------------------------------------------------------------- | ---------------------------------------------------------------------------------------------------------- |
|
|
123
|
+
| `codebase-locator` | Locate files, directories, tests, and configs relevant to a topic | `openai/gpt-5.4-mini` | low | read, grep, find, ls, bash | Read-only finder. Returns a categorized file map; no analysis. |
|
|
124
|
+
| `codebase-analyzer` | Explain how specific code currently works | `openai/gpt-5.5` | low | read, grep, find, ls, bash | Read-only. Traces flow with `file:line` references; does not critique. |
|
|
125
|
+
| `codebase-pattern-finder` | Find similar implementations or conventions | `openai/gpt-5.4-mini` | low | read, grep, find, ls, bash | Read-only. Returns code snippets with `file:line` references. |
|
|
126
|
+
| `codebase-research-locator` | Discover prior `research/` and `specs/` docs | `openai/gpt-5.4-mini` | low | read, grep, find, ls, bash | Read-only. Sorts by date, tiers by recency, flags supersession. |
|
|
127
|
+
| `codebase-research-analyzer` | Extract decisions and constraints from prior docs | `openai/gpt-5.5` | low | read, grep, find, ls, bash | Read-only. Filters aggressively for what still applies today. |
|
|
128
|
+
| `codebase-online-researcher` | Web research with authoritative sources | `openai/gpt-5.5` | low | read, grep, find, ls, bash, write, web_search, fetch_content, get_search_content | Has the `playwright-cli` skill. Persists keepers to `research/web/`. |
|
|
129
|
+
| `code-simplifier` | Clean up recently changed code without changing behavior | `openai/gpt-5.5` | low | read, edit, write, grep, find, ls, bash | **Writer.** Scopes to recently modified code by default; preserves all observable behavior. |
|
|
130
|
+
| `debugger` | Reproduce, diagnose, and fix failing behavior | `openai/gpt-5.5` | high | read, edit, write, grep, find, ls, bash, web_search, fetch_content, get_search_content | **Writer.** Has the `tdd` and `playwright-cli` skills. Inspect-only mode requires an explicit instruction. |
|
|
131
|
+
|
|
132
|
+
Each builtin declares an explicit `model` and `fallbackModels` chain (typically `github-copilot/<same>`, then `anthropic/claude-opus-4-8`, then `github-copilot/claude-opus-4.7`). The current user-selected model is automatically appended as the last fallback and de-duplicated. Override per run with inline config:
|
|
133
133
|
|
|
134
134
|
```text
|
|
135
135
|
/run codebase-analyzer[model=anthropic/claude-sonnet-4] "Trace the auth flow"
|
|
@@ -1,6 +1,5 @@
|
|
|
1
1
|
import * as fs from "node:fs";
|
|
2
2
|
import * as path from "node:path";
|
|
3
|
-
import type { AgentToolResult } from "@earendil-works/pi-agent-core";
|
|
4
3
|
import { CONFIG_DIR_NAME } from "@bastani/atomic";
|
|
5
4
|
import type { ExtensionContext } from "@bastani/atomic";
|
|
6
5
|
import {
|
|
@@ -20,7 +19,7 @@ import {
|
|
|
20
19
|
import { serializeAgent } from "./agent-serializer.ts";
|
|
21
20
|
import { serializeChain } from "./chain-serializer.ts";
|
|
22
21
|
import { discoverAvailableSkills } from "./skills.ts";
|
|
23
|
-
import type {
|
|
22
|
+
import type { SubagentToolResult } from "../shared/types.ts";
|
|
24
23
|
|
|
25
24
|
type ManagementAction = "list" | "get" | "create" | "update" | "delete";
|
|
26
25
|
type ManagementScope = "user" | "project";
|
|
@@ -34,7 +33,7 @@ interface ManagementParams {
|
|
|
34
33
|
config?: unknown;
|
|
35
34
|
}
|
|
36
35
|
|
|
37
|
-
function result(text: string, isError = false):
|
|
36
|
+
function result(text: string, isError = false): SubagentToolResult {
|
|
38
37
|
return { content: [{ type: "text", text }], isError, details: { mode: "management", results: [] } };
|
|
39
38
|
}
|
|
40
39
|
|
|
@@ -305,14 +304,20 @@ function applyAgentConfig(target: AgentConfig, cfg: Record<string, unknown>): st
|
|
|
305
304
|
return undefined;
|
|
306
305
|
}
|
|
307
306
|
|
|
307
|
+
type MutableDefinition<T extends { source: AgentSource }> = T & { source: ManagementScope };
|
|
308
|
+
|
|
309
|
+
function isMutableDefinition<T extends { source: AgentSource }>(value: T): value is MutableDefinition<T> {
|
|
310
|
+
return value.source === "user" || value.source === "project";
|
|
311
|
+
}
|
|
312
|
+
|
|
308
313
|
function resolveTarget<T extends { source: AgentSource; filePath: string }>(
|
|
309
314
|
kind: "agent" | "chain",
|
|
310
315
|
name: string,
|
|
311
316
|
matches: T[],
|
|
312
317
|
cwd: string,
|
|
313
318
|
scopeHint?: string,
|
|
314
|
-
): T |
|
|
315
|
-
const mutable = matches.filter(
|
|
319
|
+
): MutableDefinition<T> | SubagentToolResult {
|
|
320
|
+
const mutable = matches.filter(isMutableDefinition);
|
|
316
321
|
if (mutable.length === 0) {
|
|
317
322
|
if (matches.length > 0) {
|
|
318
323
|
return result(`${kind === "agent" ? "Agent" : "Chain"} '${name}' is builtin and cannot be modified. Create a same-named ${kind} in user or project scope to override it.`, true);
|
|
@@ -400,7 +405,7 @@ function formatChainDetail(chain: ChainConfig): string {
|
|
|
400
405
|
return lines.join("\n");
|
|
401
406
|
}
|
|
402
407
|
|
|
403
|
-
export function handleList(params: ManagementParams, ctx: ManagementContext):
|
|
408
|
+
export function handleList(params: ManagementParams, ctx: ManagementContext): SubagentToolResult {
|
|
404
409
|
const scope = normalizeListScope(params.agentScope) ?? "both";
|
|
405
410
|
const d = discoverAgentsAll(ctx.cwd);
|
|
406
411
|
const scopedAgents = allAgents(d).filter((a) => scope === "both" || a.source === "builtin" || a.source === scope).sort((a, b) => a.name.localeCompare(b.name));
|
|
@@ -418,7 +423,7 @@ export function handleList(params: ManagementParams, ctx: ManagementContext): Ag
|
|
|
418
423
|
return result(lines.join("\n"));
|
|
419
424
|
}
|
|
420
425
|
|
|
421
|
-
function handleGet(params: ManagementParams, ctx: ManagementContext):
|
|
426
|
+
function handleGet(params: ManagementParams, ctx: ManagementContext): SubagentToolResult {
|
|
422
427
|
if (!params.agent && !params.chainName) return result("Specify 'agent' or 'chainName' for get.", true);
|
|
423
428
|
const hasBoth = Boolean(params.agent && params.chainName);
|
|
424
429
|
const blocks: string[] = [];
|
|
@@ -448,7 +453,7 @@ function handleGet(params: ManagementParams, ctx: ManagementContext): AgentToolR
|
|
|
448
453
|
return result(blocks.join("\n\n"), !anyFound);
|
|
449
454
|
}
|
|
450
455
|
|
|
451
|
-
export function handleCreate(params: ManagementParams, ctx: ManagementContext):
|
|
456
|
+
export function handleCreate(params: ManagementParams, ctx: ManagementContext): SubagentToolResult {
|
|
452
457
|
const parsedConfig = configObject(params.config);
|
|
453
458
|
if (parsedConfig.error) return result(parsedConfig.error, true);
|
|
454
459
|
const cfg = parsedConfig.value;
|
|
@@ -508,7 +513,7 @@ export function handleCreate(params: ManagementParams, ctx: ManagementContext):
|
|
|
508
513
|
return result([`Created agent '${runtimeName}' at ${targetPath}.`, ...warnings].join("\n"));
|
|
509
514
|
}
|
|
510
515
|
|
|
511
|
-
export function handleUpdate(params: ManagementParams, ctx: ManagementContext):
|
|
516
|
+
export function handleUpdate(params: ManagementParams, ctx: ManagementContext): SubagentToolResult {
|
|
512
517
|
if (!params.agent && !params.chainName) return result("Specify 'agent' or 'chainName' for update.", true);
|
|
513
518
|
if (params.agent && params.chainName) return result("Specify either 'agent' or 'chainName', not both.", true);
|
|
514
519
|
const parsedConfig = configObject(params.config);
|
|
@@ -616,7 +621,7 @@ export function handleUpdate(params: ManagementParams, ctx: ManagementContext):
|
|
|
616
621
|
return result([headline, ...warnings].join("\n"));
|
|
617
622
|
}
|
|
618
623
|
|
|
619
|
-
function handleDelete(params: ManagementParams, ctx: ManagementContext):
|
|
624
|
+
function handleDelete(params: ManagementParams, ctx: ManagementContext): SubagentToolResult {
|
|
620
625
|
if (!params.agent && !params.chainName) return result("Specify 'agent' or 'chainName' for delete.", true);
|
|
621
626
|
if (params.agent && params.chainName) return result("Specify either 'agent' or 'chainName', not both.", true);
|
|
622
627
|
const scopeHint = asDisambiguationScope(params.agentScope);
|
|
@@ -637,7 +642,7 @@ function handleDelete(params: ManagementParams, ctx: ManagementContext): AgentTo
|
|
|
637
642
|
return result(`Deleted chain '${target.name}' at ${target.filePath}.`);
|
|
638
643
|
}
|
|
639
644
|
|
|
640
|
-
export function handleManagementAction(action: string, params: ManagementParams, ctx: ManagementContext):
|
|
645
|
+
export function handleManagementAction(action: string, params: ManagementParams, ctx: ManagementContext): SubagentToolResult {
|
|
641
646
|
switch (action as ManagementAction) {
|
|
642
647
|
case "list": return handleList(params, ctx);
|
|
643
648
|
case "get": return handleGet(params, ctx);
|
|
@@ -6,7 +6,7 @@ import { execSync } from "node:child_process";
|
|
|
6
6
|
import * as fs from "node:fs";
|
|
7
7
|
import * as os from "node:os";
|
|
8
8
|
import * as path from "node:path";
|
|
9
|
-
import { getAgentConfigPaths, getAgentDirs, getProjectConfigDirs } from "@bastani/atomic";
|
|
9
|
+
import { getAgentConfigPaths, getAgentDirs, getBuiltinPackagePaths, getProjectConfigDirs } from "@bastani/atomic";
|
|
10
10
|
|
|
11
11
|
export type SkillSource =
|
|
12
12
|
| "project"
|
|
@@ -314,6 +314,17 @@ function collectSettingsPackageSkillPaths(cwd: string): SkillSearchPath[] {
|
|
|
314
314
|
return results;
|
|
315
315
|
}
|
|
316
316
|
|
|
317
|
+
function collectBuiltinPackageSkillPaths(): SkillSearchPath[] {
|
|
318
|
+
try {
|
|
319
|
+
return getBuiltinPackagePaths().flatMap((packageRoot) =>
|
|
320
|
+
extractSkillPathsFromPackageRoot(packageRoot, "builtin", true)
|
|
321
|
+
);
|
|
322
|
+
} catch {
|
|
323
|
+
// Builtin package discovery is additive; keep project/user/settings skill resolution working if unavailable.
|
|
324
|
+
return [];
|
|
325
|
+
}
|
|
326
|
+
}
|
|
327
|
+
|
|
317
328
|
function buildSkillPaths(cwd: string): SkillSearchPath[] {
|
|
318
329
|
const skillPaths: SkillSearchPath[] = [
|
|
319
330
|
...getProjectConfigDirs(cwd).map((configDir) => ({ path: path.join(configDir, "skills"), source: "project" as const })),
|
|
@@ -324,6 +335,7 @@ function buildSkillPaths(cwd: string): SkillSearchPath[] {
|
|
|
324
335
|
...collectSettingsPackageSkillPaths(cwd),
|
|
325
336
|
...extractSkillPathsFromPackageRoot(cwd, "project-package"),
|
|
326
337
|
...collectSettingsSkillPaths(cwd),
|
|
338
|
+
...collectBuiltinPackageSkillPaths(),
|
|
327
339
|
];
|
|
328
340
|
|
|
329
341
|
const deduped = new Map<string, SkillSearchPath>();
|
|
@@ -23,7 +23,7 @@ import { discoverAgents } from "../agents/agents.ts";
|
|
|
23
23
|
import { cleanupAllArtifactDirs, cleanupOldArtifacts, getArtifactsDir } from "../shared/artifacts.ts";
|
|
24
24
|
import { resolveCurrentSessionId } from "../shared/session-identity.ts";
|
|
25
25
|
import { cleanupOldChainDirs } from "../shared/settings.ts";
|
|
26
|
-
import {
|
|
26
|
+
import { renderWidget, renderSubagentResult, stopResultAnimations, stopWidgetAnimation, syncResultAnimation } from "../tui/render.ts";
|
|
27
27
|
import { SubagentParams } from "./schemas.ts";
|
|
28
28
|
import { createSubagentExecutor, type SubagentParamsLike } from "../runs/foreground/subagent-executor.ts";
|
|
29
29
|
import { createAsyncJobTracker } from "../runs/background/async-job-tracker.ts";
|
|
@@ -135,8 +135,10 @@ function createSlashResultComponent(
|
|
|
135
135
|
details: SlashMessageDetails,
|
|
136
136
|
options: { expanded: boolean },
|
|
137
137
|
theme: ExtensionContext["ui"]["theme"],
|
|
138
|
+
requestRender: () => void,
|
|
138
139
|
): Container {
|
|
139
140
|
const container = new Container();
|
|
141
|
+
const animationState: { subagentResultAnimationTimer?: ReturnType<typeof setInterval> } = {};
|
|
140
142
|
let lastVersion = -1;
|
|
141
143
|
container.render = (width: number): string[] => {
|
|
142
144
|
const snapshot = getSlashRenderableSnapshot(details);
|
|
@@ -144,6 +146,9 @@ function createSlashResultComponent(
|
|
|
144
146
|
lastVersion = snapshot.version;
|
|
145
147
|
rebuildSlashResultContainer(container, snapshot.result, options, theme);
|
|
146
148
|
}
|
|
149
|
+
// Keep the live slash card's spinner animating by scheduling steady
|
|
150
|
+
// re-renders while it runs (and tearing the timer down once it settles).
|
|
151
|
+
syncResultAnimation(snapshot.result, { state: animationState, invalidate: requestRender });
|
|
147
152
|
return Container.prototype.render.call(container, width);
|
|
148
153
|
};
|
|
149
154
|
return container;
|
|
@@ -266,6 +271,8 @@ export default function registerSubagentExtension(pi: ExtensionAPI): void {
|
|
|
266
271
|
|
|
267
272
|
const runtimeCleanup = () => {
|
|
268
273
|
stopResultWatcher();
|
|
274
|
+
stopWidgetAnimation();
|
|
275
|
+
stopResultAnimations();
|
|
269
276
|
clearPendingForegroundControlNotices(state);
|
|
270
277
|
if (state.poller) {
|
|
271
278
|
clearInterval(state.poller);
|
|
@@ -289,7 +296,7 @@ export default function registerSubagentExtension(pi: ExtensionAPI): void {
|
|
|
289
296
|
pi.registerMessageRenderer<SlashMessageDetails>(SLASH_RESULT_TYPE, (message, options, theme) => {
|
|
290
297
|
const details = resolveSlashMessageDetails(message.details);
|
|
291
298
|
if (!details) return undefined;
|
|
292
|
-
return createSlashResultComponent(details, options, theme);
|
|
299
|
+
return createSlashResultComponent(details, options, theme, () => state.lastUiContext?.ui.requestRender?.());
|
|
293
300
|
});
|
|
294
301
|
|
|
295
302
|
pi.registerMessageRenderer<SubagentNotifyDetails>("subagent-notify", (message, options, theme) => {
|
|
@@ -458,7 +465,9 @@ DIAGNOSTICS:
|
|
|
458
465
|
},
|
|
459
466
|
|
|
460
467
|
renderResult(result, options, theme, context) {
|
|
461
|
-
|
|
468
|
+
// Animate the live subagent spinner by scheduling steady re-renders
|
|
469
|
+
// while the result is running; the timer stops once it settles.
|
|
470
|
+
syncResultAnimation(result, context);
|
|
462
471
|
return renderSubagentResult(result, options, theme);
|
|
463
472
|
},
|
|
464
473
|
|
|
@@ -549,6 +558,8 @@ DIAGNOSTICS:
|
|
|
549
558
|
delete globalStore[eventUnsubscribeStoreKey];
|
|
550
559
|
}
|
|
551
560
|
stopResultWatcher();
|
|
561
|
+
stopWidgetAnimation();
|
|
562
|
+
stopResultAnimations();
|
|
552
563
|
if (state.poller) clearInterval(state.poller);
|
|
553
564
|
state.poller = null;
|
|
554
565
|
clearPendingForegroundControlNotices(state);
|
|
@@ -109,6 +109,7 @@ interface AsyncChainParams {
|
|
|
109
109
|
chainSkills?: string[];
|
|
110
110
|
sessionFilesByFlatIndex?: (string | undefined)[];
|
|
111
111
|
maxSubagentDepth: number;
|
|
112
|
+
workflowStageSubagentGuard?: boolean;
|
|
112
113
|
worktreeSetupHook?: string;
|
|
113
114
|
worktreeSetupHookTimeoutMs?: number;
|
|
114
115
|
controlConfig?: ResolvedControlConfig;
|
|
@@ -135,6 +136,7 @@ interface AsyncSingleParams {
|
|
|
135
136
|
modelOverride?: string;
|
|
136
137
|
availableModels?: AvailableModelInfo[];
|
|
137
138
|
maxSubagentDepth: number;
|
|
139
|
+
workflowStageSubagentGuard?: boolean;
|
|
138
140
|
worktreeSetupHook?: string;
|
|
139
141
|
worktreeSetupHookTimeoutMs?: number;
|
|
140
142
|
controlConfig?: ResolvedControlConfig;
|
|
@@ -241,6 +243,7 @@ export function executeAsyncChain(
|
|
|
241
243
|
sessionRoot,
|
|
242
244
|
sessionFilesByFlatIndex,
|
|
243
245
|
maxSubagentDepth,
|
|
246
|
+
workflowStageSubagentGuard,
|
|
244
247
|
worktreeSetupHook,
|
|
245
248
|
worktreeSetupHookTimeoutMs,
|
|
246
249
|
controlConfig,
|
|
@@ -348,6 +351,7 @@ export function executeAsyncChain(
|
|
|
348
351
|
outputMode: behavior.outputMode,
|
|
349
352
|
sessionFile,
|
|
350
353
|
maxSubagentDepth: resolveChildMaxSubagentDepth(maxSubagentDepth, a.maxSubagentDepth),
|
|
354
|
+
workflowStageSubagentGuard,
|
|
351
355
|
};
|
|
352
356
|
};
|
|
353
357
|
|
|
@@ -427,6 +431,7 @@ export function executeAsyncChain(
|
|
|
427
431
|
childIntercomTargets,
|
|
428
432
|
resultMode,
|
|
429
433
|
nestedRoute: nestedRoute ?? inheritedNestedRoute,
|
|
434
|
+
workflowStageSubagentGuard,
|
|
430
435
|
nestedSelf: inheritedNestedRoute && nestedAddress ? {
|
|
431
436
|
parentRunId: nestedAddress.parentRunId,
|
|
432
437
|
parentStepIndex: nestedAddress.parentStepIndex,
|
|
@@ -551,6 +556,7 @@ export function executeAsyncSingle(
|
|
|
551
556
|
sessionRoot,
|
|
552
557
|
sessionFile,
|
|
553
558
|
maxSubagentDepth,
|
|
559
|
+
workflowStageSubagentGuard,
|
|
554
560
|
worktreeSetupHook,
|
|
555
561
|
worktreeSetupHookTimeoutMs,
|
|
556
562
|
controlConfig,
|
|
@@ -624,6 +630,7 @@ export function executeAsyncSingle(
|
|
|
624
630
|
outputMode,
|
|
625
631
|
sessionFile,
|
|
626
632
|
maxSubagentDepth: resolveChildMaxSubagentDepth(maxSubagentDepth, agentConfig.maxSubagentDepth),
|
|
633
|
+
workflowStageSubagentGuard,
|
|
627
634
|
},
|
|
628
635
|
],
|
|
629
636
|
resultPath: inheritedNestedRoute ? nestedResultsPath(inheritedNestedRoute.rootRunId, id) : path.join(RESULTS_DIR, `${id}.json`),
|
|
@@ -645,6 +652,7 @@ export function executeAsyncSingle(
|
|
|
645
652
|
childIntercomTargets: childIntercomTarget ? [childIntercomTarget(agent, 0)] : undefined,
|
|
646
653
|
resultMode: "single",
|
|
647
654
|
nestedRoute: nestedRoute ?? inheritedNestedRoute,
|
|
655
|
+
workflowStageSubagentGuard,
|
|
648
656
|
nestedSelf: inheritedNestedRoute && nestedAddress ? {
|
|
649
657
|
parentRunId: nestedAddress.parentRunId,
|
|
650
658
|
parentStepIndex: nestedAddress.parentStepIndex,
|
|
@@ -1,11 +1,10 @@
|
|
|
1
1
|
import * as fs from "node:fs";
|
|
2
2
|
import * as path from "node:path";
|
|
3
|
-
import type { AgentToolResult } from "@earendil-works/pi-agent-core";
|
|
4
3
|
import { formatAsyncRunList, formatAsyncRunOutputPath, formatAsyncRunProgressLabel, listAsyncRuns } from "./async-status.ts";
|
|
5
4
|
import { formatNestedRunStatusLines } from "../shared/nested-render.ts";
|
|
6
5
|
import { formatModelThinking } from "../../shared/formatters.ts";
|
|
7
6
|
import { formatActivityLabel } from "../../shared/status-format.ts";
|
|
8
|
-
import { ASYNC_DIR, RESULTS_DIR, type AsyncStatus, type
|
|
7
|
+
import { ASYNC_DIR, RESULTS_DIR, type AsyncStatus, type NestedRunSummary, type SubagentState, type SubagentToolResult } from "../../shared/types.ts";
|
|
9
8
|
import { resolveSubagentIntercomTarget } from "../../intercom/intercom-bridge.ts";
|
|
10
9
|
import { resolveAsyncRunLocation } from "./async-resume.ts";
|
|
11
10
|
import { resolveSubagentRunId } from "./run-id-resolver.ts";
|
|
@@ -98,7 +97,7 @@ function formatNestedExactStatus(rootRunId: string, run: NestedRunSummary): stri
|
|
|
98
97
|
return lines.join("\n");
|
|
99
98
|
}
|
|
100
99
|
|
|
101
|
-
export function inspectSubagentStatus(params: RunStatusParams, deps: RunStatusDeps = {}):
|
|
100
|
+
export function inspectSubagentStatus(params: RunStatusParams, deps: RunStatusDeps = {}): SubagentToolResult {
|
|
102
101
|
const asyncDirRoot = deps.asyncDirRoot ?? ASYNC_DIR;
|
|
103
102
|
const resultsDir = deps.resultsDir ?? RESULTS_DIR;
|
|
104
103
|
if (!params.id && !params.runId && !params.dir) {
|
|
@@ -95,6 +95,7 @@ interface SubagentRunConfig {
|
|
|
95
95
|
childIntercomTargets?: Array<string | undefined>;
|
|
96
96
|
resultMode?: SubagentRunMode;
|
|
97
97
|
nestedRoute?: NestedRouteInfo;
|
|
98
|
+
workflowStageSubagentGuard?: boolean;
|
|
98
99
|
nestedSelf?: { parentRunId: string; parentStepIndex?: number; depth: number; path?: Array<{ runId: string; stepIndex?: number; agent?: string }> };
|
|
99
100
|
}
|
|
100
101
|
|
|
@@ -215,13 +216,18 @@ function runPiStreaming(
|
|
|
215
216
|
piPackageRoot?: string,
|
|
216
217
|
piArgv1?: string,
|
|
217
218
|
maxSubagentDepth?: number,
|
|
219
|
+
workflowStageSubagentGuard?: boolean,
|
|
218
220
|
childEventContext?: ChildEventContext,
|
|
219
221
|
registerInterrupt?: (interrupt: (() => void) | undefined) => void,
|
|
220
222
|
onChildEvent?: (event: ChildEvent) => void,
|
|
221
223
|
): Promise<RunPiStreamingResult> {
|
|
222
224
|
return new Promise((resolve) => {
|
|
223
225
|
const outputStream = fs.createWriteStream(outputFile, { flags: "w" });
|
|
224
|
-
const spawnEnv = {
|
|
226
|
+
const spawnEnv = {
|
|
227
|
+
...process.env,
|
|
228
|
+
...(env ?? {}),
|
|
229
|
+
...getSubagentDepthEnv(maxSubagentDepth, { workflowStageSubagentGuard }),
|
|
230
|
+
};
|
|
225
231
|
const spawnSpec = getPiSpawnCommand(args, {
|
|
226
232
|
...(piPackageRoot ? { piPackageRoot } : {}),
|
|
227
233
|
...(piArgv1 ? { argv1: piArgv1 } : {}),
|
|
@@ -561,6 +567,7 @@ interface SingleStepContext {
|
|
|
561
567
|
nestedRoute?: NestedRouteInfo;
|
|
562
568
|
onAttemptStart?: (attempt: { model?: string; thinking?: string }) => void;
|
|
563
569
|
onChildEvent?: (event: ChildEvent) => void;
|
|
570
|
+
workflowStageSubagentGuard?: boolean;
|
|
564
571
|
}
|
|
565
572
|
|
|
566
573
|
/** Run a single pi agent step, returning output and metadata */
|
|
@@ -647,6 +654,7 @@ async function runSingleStep(
|
|
|
647
654
|
ctx.piPackageRoot,
|
|
648
655
|
ctx.piArgv1,
|
|
649
656
|
step.maxSubagentDepth,
|
|
657
|
+
step.workflowStageSubagentGuard ?? ctx.workflowStageSubagentGuard,
|
|
650
658
|
{ eventsPath, runId: ctx.id, stepIndex: ctx.flatIndex, agent: step.agent },
|
|
651
659
|
ctx.registerInterrupt,
|
|
652
660
|
ctx.onChildEvent,
|
|
@@ -1393,6 +1401,7 @@ async function runSubagent(config: SubagentRunConfig): Promise<void> {
|
|
|
1393
1401
|
},
|
|
1394
1402
|
onAttemptStart: (attempt) => updateStepModel(fi, attempt.model, attempt.thinking),
|
|
1395
1403
|
onChildEvent: (event) => updateStepFromChildEvent(fi, event),
|
|
1404
|
+
workflowStageSubagentGuard: config.workflowStageSubagentGuard,
|
|
1396
1405
|
});
|
|
1397
1406
|
if (task.sessionFile) {
|
|
1398
1407
|
latestSessionFile = task.sessionFile;
|
|
@@ -1539,6 +1548,7 @@ async function runSubagent(config: SubagentRunConfig): Promise<void> {
|
|
|
1539
1548
|
},
|
|
1540
1549
|
onAttemptStart: (attempt) => updateStepModel(flatIndex, attempt.model, attempt.thinking),
|
|
1541
1550
|
onChildEvent: (event) => updateStepFromChildEvent(flatIndex, event),
|
|
1551
|
+
workflowStageSubagentGuard: config.workflowStageSubagentGuard,
|
|
1542
1552
|
});
|
|
1543
1553
|
if (seqStep.sessionFile) {
|
|
1544
1554
|
latestSessionFile = seqStep.sessionFile;
|
|
@@ -775,7 +775,7 @@ export class ChainClarifyComponent implements Component {
|
|
|
775
775
|
|
|
776
776
|
private handleEditInput(data: string): void {
|
|
777
777
|
const textWidth = this.width - 4; // Must match render: innerW - 2 = (width - 2) - 2
|
|
778
|
-
if (matchesKey(data, "shift+up") || matchesKey(data, "
|
|
778
|
+
if (matchesKey(data, "shift+up") || matchesKey(data, "pageUp")) {
|
|
779
779
|
const { lines: wrapped, starts } = wrapText(this.editState.buffer, textWidth);
|
|
780
780
|
const cursorPos = getCursorDisplayPos(this.editState.cursor, starts);
|
|
781
781
|
const targetLine = Math.max(0, cursorPos.line - this.EDIT_VIEWPORT_HEIGHT);
|
|
@@ -785,7 +785,7 @@ export class ChainClarifyComponent implements Component {
|
|
|
785
785
|
return;
|
|
786
786
|
}
|
|
787
787
|
|
|
788
|
-
if (matchesKey(data, "shift+down") || matchesKey(data, "
|
|
788
|
+
if (matchesKey(data, "shift+down") || matchesKey(data, "pageDown")) {
|
|
789
789
|
const { lines: wrapped, starts } = wrapText(this.editState.buffer, textWidth);
|
|
790
790
|
const cursorPos = getCursorDisplayPos(this.editState.cursor, starts);
|
|
791
791
|
const targetLine = Math.min(wrapped.length - 1, cursorPos.line + this.EDIT_VIEWPORT_HEIGHT);
|