@bastani/atomic 0.9.5-alpha.9 → 0.9.5
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 +106 -0
- package/README.md +2 -2
- package/dist/builtin/cursor/CHANGELOG.md +12 -0
- package/dist/builtin/cursor/package.json +3 -3
- package/dist/builtin/cursor/src/model-mapper.ts +6 -3
- package/dist/builtin/intercom/CHANGELOG.md +37 -0
- package/dist/builtin/intercom/README.md +4 -2
- package/dist/builtin/intercom/broker/broker.ts +6 -114
- package/dist/builtin/intercom/broker/client.ts +29 -54
- package/dist/builtin/intercom/broker/delivered-message-cache.ts +44 -0
- package/dist/builtin/intercom/broker/pending-send-registry.ts +142 -0
- package/dist/builtin/intercom/broker/send-handler.ts +106 -0
- package/dist/builtin/intercom/broker/send-signature.ts +37 -0
- package/dist/builtin/intercom/foreground-detach-handoff.ts +136 -0
- package/dist/builtin/intercom/index-heavy.ts +49 -53
- package/dist/builtin/intercom/index.ts +278 -262
- package/dist/builtin/intercom/lazy-heavy-proxy.ts +114 -0
- package/dist/builtin/intercom/lazy-subagent-ack.ts +20 -0
- package/dist/builtin/intercom/lazy-tool-execution.ts +39 -0
- package/dist/builtin/intercom/lifecycle-lease.ts +51 -0
- package/dist/builtin/intercom/lifecycle.ts +37 -20
- package/dist/builtin/intercom/package.json +3 -6
- package/dist/builtin/intercom/reply-routing.ts +17 -0
- package/dist/builtin/intercom/subagent-relay.ts +58 -12
- package/dist/builtin/intercom/types.ts +3 -3
- package/dist/builtin/mcp/CHANGELOG.md +27 -0
- package/dist/builtin/mcp/OAUTH.md +1 -0
- package/dist/builtin/mcp/README.md +4 -0
- package/dist/builtin/mcp/apps-cancellation.ts +32 -0
- package/dist/builtin/mcp/call-tool-result.ts +9 -0
- package/dist/builtin/mcp/caller-wait.ts +50 -0
- package/dist/builtin/mcp/command-registration.ts +82 -0
- package/dist/builtin/mcp/direct-tool-executor.ts +279 -0
- package/dist/builtin/mcp/direct-tools.ts +6 -239
- package/dist/builtin/mcp/host-html-template.ts +4 -2
- package/dist/builtin/mcp/index.ts +258 -250
- package/dist/builtin/mcp/init.ts +96 -87
- package/dist/builtin/mcp/mcp-auth-flow.ts +247 -237
- package/dist/builtin/mcp/mcp-callback-server.ts +89 -68
- package/dist/builtin/mcp/mcp-oauth-provider.ts +23 -1
- package/dist/builtin/mcp/metadata-hydration.ts +21 -6
- package/dist/builtin/mcp/package.json +3 -3
- package/dist/builtin/mcp/proxy-auth.ts +4 -4
- package/dist/builtin/mcp/proxy-call.ts +111 -40
- package/dist/builtin/mcp/proxy-connect.ts +35 -15
- package/dist/builtin/mcp/proxy-info-modes.ts +49 -19
- package/dist/builtin/mcp/proxy-modes.ts +3 -3
- package/dist/builtin/mcp/session-cleanup-barrier.ts +43 -0
- package/dist/builtin/mcp/state-lease.ts +12 -0
- package/dist/builtin/mcp/ui-server.ts +8 -8
- package/dist/builtin/mcp/ui-session.ts +9 -18
- package/dist/builtin/subagents/CHANGELOG.md +66 -0
- package/dist/builtin/subagents/README.md +30 -29
- package/dist/builtin/subagents/agents/code-simplifier.md +2 -2
- package/dist/builtin/subagents/agents/codebase-analyzer.md +2 -2
- package/dist/builtin/subagents/agents/codebase-locator.md +2 -2
- package/dist/builtin/subagents/agents/codebase-online-researcher.md +2 -2
- package/dist/builtin/subagents/agents/codebase-pattern-finder.md +2 -2
- package/dist/builtin/subagents/agents/codebase-research-analyzer.md +2 -2
- package/dist/builtin/subagents/agents/codebase-research-locator.md +2 -2
- package/dist/builtin/subagents/agents/debugger.md +2 -2
- package/dist/builtin/subagents/agents/worker.md +2 -2
- package/dist/builtin/subagents/package.json +5 -5
- package/dist/builtin/subagents/prompts/review-loop.md +1 -1
- package/dist/builtin/subagents/skills/subagent/SKILL.md +37 -36
- package/dist/builtin/subagents/src/extension/api-lifecycle.ts +64 -0
- package/dist/builtin/subagents/src/extension/fanout-child.ts +44 -51
- package/dist/builtin/subagents/src/extension/index.ts +287 -307
- package/dist/builtin/subagents/src/extension/prompt-guidance.ts +7 -10
- package/dist/builtin/subagents/src/extension/schemas.ts +22 -5
- package/dist/builtin/subagents/src/extension/tool-description.ts +29 -0
- package/dist/builtin/subagents/src/intercom/intercom-bridge.ts +13 -2
- package/dist/builtin/subagents/src/intercom/result-intercom.ts +4 -4
- package/dist/builtin/subagents/src/runs/background/async-event-journal.ts +106 -0
- package/dist/builtin/subagents/src/runs/background/async-execution-common.ts +3 -2
- package/dist/builtin/subagents/src/runs/background/async-execution-single.ts +13 -2
- package/dist/builtin/subagents/src/runs/background/async-execution-types.ts +3 -0
- package/dist/builtin/subagents/src/runs/background/async-job-tracker.ts +1 -1
- package/dist/builtin/subagents/src/runs/background/completion-claims.ts +189 -0
- package/dist/builtin/subagents/src/runs/background/completion-dedupe.ts +44 -7
- package/dist/builtin/subagents/src/runs/background/completion-notification.ts +34 -0
- package/dist/builtin/subagents/src/runs/background/notify.ts +72 -22
- package/dist/builtin/subagents/src/runs/background/result-delivery-processor.ts +232 -0
- package/dist/builtin/subagents/src/runs/background/result-file-claims.ts +151 -0
- package/dist/builtin/subagents/src/runs/background/result-quarantine.ts +72 -0
- package/dist/builtin/subagents/src/runs/background/result-retry-scheduler.ts +48 -0
- package/dist/builtin/subagents/src/runs/background/result-status.ts +81 -0
- package/dist/builtin/subagents/src/runs/background/result-watcher-data.ts +59 -0
- package/dist/builtin/subagents/src/runs/background/result-watcher.ts +172 -238
- package/dist/builtin/subagents/src/runs/background/run-id-resolver.ts +3 -2
- package/dist/builtin/subagents/src/runs/background/stale-run-reconciler.ts +73 -14
- package/dist/builtin/subagents/src/runs/background/subagent-runner-streaming.ts +17 -13
- package/dist/builtin/subagents/src/runs/background/top-level-async.ts +1 -2
- package/dist/builtin/subagents/src/runs/foreground/chain-execution-dynamic-step.ts +1 -0
- package/dist/builtin/subagents/src/runs/foreground/chain-execution-parallel-runner.ts +1 -0
- package/dist/builtin/subagents/src/runs/foreground/chain-execution-parallel-step.ts +1 -0
- package/dist/builtin/subagents/src/runs/foreground/chain-execution-sequential-step.ts +7 -9
- package/dist/builtin/subagents/src/runs/foreground/chain-execution-types.ts +3 -13
- package/dist/builtin/subagents/src/runs/foreground/chain-execution.ts +2 -15
- package/dist/builtin/subagents/src/runs/foreground/execution-attempt-finalize.ts +2 -2
- package/dist/builtin/subagents/src/runs/foreground/execution-attempt.ts +53 -44
- package/dist/builtin/subagents/src/runs/foreground/execution-detach-reservations.ts +48 -0
- package/dist/builtin/subagents/src/runs/foreground/execution-detach-route.ts +17 -0
- package/dist/builtin/subagents/src/runs/foreground/execution-run-sync.ts +39 -26
- package/dist/builtin/subagents/src/runs/foreground/subagent-executor-async.ts +3 -1
- package/dist/builtin/subagents/src/runs/foreground/subagent-executor-chain.ts +3 -51
- package/dist/builtin/subagents/src/runs/foreground/subagent-executor-context.ts +6 -11
- package/dist/builtin/subagents/src/runs/foreground/subagent-executor-input.ts +11 -2
- package/dist/builtin/subagents/src/runs/foreground/subagent-executor-parallel-task.ts +2 -0
- package/dist/builtin/subagents/src/runs/foreground/subagent-executor-parallel.ts +5 -112
- package/dist/builtin/subagents/src/runs/foreground/subagent-executor-resume.ts +2 -0
- package/dist/builtin/subagents/src/runs/foreground/subagent-executor-single.ts +68 -118
- package/dist/builtin/subagents/src/runs/foreground/subagent-executor-status.ts +79 -7
- package/dist/builtin/subagents/src/runs/foreground/subagent-executor-types.ts +2 -2
- package/dist/builtin/subagents/src/runs/foreground/subagent-executor.ts +3 -0
- package/dist/builtin/subagents/src/runs/shared/pi-args.ts +2 -2
- package/dist/builtin/subagents/src/runs/shared/pi-spawn.ts +27 -11
- package/dist/builtin/subagents/src/shared/artifacts.ts +22 -11
- package/dist/builtin/subagents/src/shared/event-jsonl-writer.ts +294 -0
- package/dist/builtin/subagents/src/shared/exclusive-file-publication.ts +44 -0
- package/dist/builtin/subagents/src/shared/jsonl-writer.ts +1 -0
- package/dist/builtin/subagents/src/shared/model-info.ts +2 -2
- package/dist/builtin/subagents/src/shared/settings.ts +20 -10
- package/dist/builtin/subagents/src/shared/types-async.ts +3 -1
- package/dist/builtin/subagents/src/shared/types-config.ts +2 -0
- package/dist/builtin/subagents/src/shared/types-runtime.ts +3 -2
- package/dist/builtin/subagents/src/slash/slash-commands.ts +9 -12
- package/dist/builtin/subagents/src/slash/slash-live-state.ts +63 -32
- package/dist/builtin/subagents/src/tui/render-result.ts +7 -0
- package/dist/builtin/subagents/src/tui/render-stable-output.ts +1 -0
- package/dist/builtin/subagents/src/tui/render-widget.ts +128 -89
- package/dist/builtin/web-access/CHANGELOG.md +28 -0
- package/dist/builtin/web-access/README.md +4 -0
- package/dist/builtin/web-access/content-tools.ts +8 -3
- package/dist/builtin/web-access/index-heavy.ts +1 -1
- package/dist/builtin/web-access/index.ts +190 -46
- package/dist/builtin/web-access/lifecycle-lease.ts +38 -0
- package/dist/builtin/web-access/package.json +2 -2
- package/dist/builtin/web-access/result-renderers.ts +1 -1
- package/dist/builtin/web-access/summary-review.ts +1 -1
- package/dist/builtin/web-access/web-search-activity.ts +1 -1
- package/dist/builtin/web-access/web-search-return.ts +7 -0
- package/dist/builtin/web-access/web-search-summary.ts +1 -1
- package/dist/builtin/web-access/web-search-tool.ts +4 -2
- package/dist/builtin/workflows/CHANGELOG.md +68 -0
- package/dist/builtin/workflows/README.md +4 -4
- package/dist/builtin/workflows/builtin/deep-research-codebase-utils.ts +27 -4
- package/dist/builtin/workflows/builtin/goal-runner.ts +47 -26
- package/dist/builtin/workflows/builtin/open-claude-design-runner.ts +10 -0
- package/dist/builtin/workflows/builtin/ralph-core.ts +9 -9
- package/dist/builtin/workflows/builtin/ralph-models.ts +71 -36
- package/dist/builtin/workflows/builtin/ralph-runner.ts +20 -31
- package/dist/builtin/workflows/package.json +2 -2
- package/dist/builtin/workflows/src/durable/stage-primitive.ts +2 -1
- package/dist/builtin/workflows/src/engine/primitives/task.ts +2 -1
- package/dist/builtin/workflows/src/extension/workflow-prompts.ts +17 -22
- package/dist/builtin/workflows/src/extension/workflow-schema.ts +15 -2
- package/dist/builtin/workflows/src/runs/foreground/executor-hil.ts +1 -2
- package/dist/builtin/workflows/src/runs/shared/model-fallback-candidates.ts +1 -1
- package/dist/builtin/workflows/src/shared/authoring-contract-stage.d.ts +2 -2
- package/dist/builtin/workflows/src/shared/authoring-contract-stage.ts +2 -2
- package/dist/builtin/workflows/src/shared/resume-continuation.ts +2 -0
- package/dist/builtin/workflows/src/tui/stage-chat-view-archive-history.ts +1 -23
- package/dist/builtin/workflows/src/tui/stage-chat-view-footer-status.ts +54 -9
- package/dist/builtin/workflows/src/tui/stage-chat-view.ts +5 -2
- package/dist/cli/args.d.ts.map +1 -1
- package/dist/cli/args.js +2 -2
- package/dist/cli/args.js.map +1 -1
- package/dist/core/agent-session-events.d.ts.map +1 -1
- package/dist/core/agent-session-events.js +2 -1
- package/dist/core/agent-session-events.js.map +1 -1
- package/dist/core/agent-session-message-queue.d.ts.map +1 -1
- package/dist/core/agent-session-message-queue.js +1 -1
- package/dist/core/agent-session-message-queue.js.map +1 -1
- package/dist/core/agent-session-prompt.d.ts.map +1 -1
- package/dist/core/agent-session-prompt.js +1 -1
- package/dist/core/agent-session-prompt.js.map +1 -1
- package/dist/core/agent-session-retry.d.ts.map +1 -1
- package/dist/core/agent-session-retry.js +1 -1
- package/dist/core/agent-session-retry.js.map +1 -1
- package/dist/core/agent-session-services.d.ts.map +1 -1
- package/dist/core/agent-session-services.js +3 -2
- package/dist/core/agent-session-services.js.map +1 -1
- package/dist/core/agent-session-types.d.ts.map +1 -1
- package/dist/core/agent-session-types.js +1 -1
- package/dist/core/agent-session-types.js.map +1 -1
- package/dist/core/anthropic-thinking-guard.d.ts +5 -5
- package/dist/core/anthropic-thinking-guard.d.ts.map +1 -1
- package/dist/core/anthropic-thinking-guard.js +42 -32
- package/dist/core/anthropic-thinking-guard.js.map +1 -1
- package/dist/core/atomic-guide-command.d.ts.map +1 -1
- package/dist/core/atomic-guide-command.js +15 -15
- package/dist/core/atomic-guide-command.js.map +1 -1
- package/dist/core/auth-storage.d.ts.map +1 -1
- package/dist/core/auth-storage.js +14 -9
- package/dist/core/auth-storage.js.map +1 -1
- package/dist/core/compaction/compaction.d.ts +2 -0
- package/dist/core/compaction/compaction.d.ts.map +1 -1
- package/dist/core/compaction/compaction.js +79 -46
- package/dist/core/compaction/compaction.js.map +1 -1
- package/dist/core/compaction/context-assistant-turns.d.ts +42 -0
- package/dist/core/compaction/context-assistant-turns.d.ts.map +1 -0
- package/dist/core/compaction/context-assistant-turns.js +87 -0
- package/dist/core/compaction/context-assistant-turns.js.map +1 -0
- package/dist/core/compaction/context-compaction-critical.d.ts +1 -1
- package/dist/core/compaction/context-compaction-critical.d.ts.map +1 -1
- package/dist/core/compaction/context-compaction-critical.js +2 -2
- package/dist/core/compaction/context-compaction-critical.js.map +1 -1
- package/dist/core/compaction/context-compaction-eviction-alternates.d.ts +18 -0
- package/dist/core/compaction/context-compaction-eviction-alternates.d.ts.map +1 -0
- package/dist/core/compaction/context-compaction-eviction-alternates.js +186 -0
- package/dist/core/compaction/context-compaction-eviction-alternates.js.map +1 -0
- package/dist/core/compaction/context-compaction-eviction.d.ts +10 -2
- package/dist/core/compaction/context-compaction-eviction.d.ts.map +1 -1
- package/dist/core/compaction/context-compaction-eviction.js +196 -146
- package/dist/core/compaction/context-compaction-eviction.js.map +1 -1
- package/dist/core/compaction/context-compaction-prompt.d.ts.map +1 -1
- package/dist/core/compaction/context-compaction-prompt.js +1 -1
- package/dist/core/compaction/context-compaction-prompt.js.map +1 -1
- package/dist/core/compaction/context-compaction-types.d.ts +2 -0
- package/dist/core/compaction/context-compaction-types.d.ts.map +1 -1
- package/dist/core/compaction/context-compaction-types.js.map +1 -1
- package/dist/core/compaction/context-deletion-application.d.ts +5 -4
- package/dist/core/compaction/context-deletion-application.d.ts.map +1 -1
- package/dist/core/compaction/context-deletion-application.js +17 -15
- package/dist/core/compaction/context-deletion-application.js.map +1 -1
- package/dist/core/compaction/context-deletion-store.d.ts.map +1 -1
- package/dist/core/compaction/context-deletion-store.js +1 -1
- package/dist/core/compaction/context-deletion-store.js.map +1 -1
- package/dist/core/compaction/context-deletion-targets.d.ts +2 -1
- package/dist/core/compaction/context-deletion-targets.d.ts.map +1 -1
- package/dist/core/compaction/context-deletion-targets.js +36 -31
- package/dist/core/compaction/context-deletion-targets.js.map +1 -1
- package/dist/core/compaction/context-deletion-tool-helpers.d.ts.map +1 -1
- package/dist/core/compaction/context-deletion-tool-helpers.js +116 -43
- package/dist/core/compaction/context-deletion-tool-helpers.js.map +1 -1
- package/dist/core/compaction/context-transcript-analysis.d.ts +1 -2
- package/dist/core/compaction/context-transcript-analysis.d.ts.map +1 -1
- package/dist/core/compaction/context-transcript-analysis.js +33 -37
- package/dist/core/compaction/context-transcript-analysis.js.map +1 -1
- package/dist/core/copilot-model-synthesis.d.ts.map +1 -1
- package/dist/core/copilot-model-synthesis.js +3 -1
- package/dist/core/copilot-model-synthesis.js.map +1 -1
- package/dist/core/extensions/provider-types.d.ts +2 -7
- package/dist/core/extensions/provider-types.d.ts.map +1 -1
- package/dist/core/extensions/provider-types.js.map +1 -1
- package/dist/core/messages.d.ts +9 -0
- package/dist/core/messages.d.ts.map +1 -1
- package/dist/core/messages.js +100 -18
- package/dist/core/messages.js.map +1 -1
- package/dist/core/model-registry-builtins.d.ts.map +1 -1
- package/dist/core/model-registry-builtins.js +5 -0
- package/dist/core/model-registry-builtins.js.map +1 -1
- package/dist/core/model-registry-custom-loader.d.ts.map +1 -1
- package/dist/core/model-registry-custom-loader.js +49 -8
- package/dist/core/model-registry-custom-loader.js.map +1 -1
- package/dist/core/model-registry-dynamic.d.ts.map +1 -1
- package/dist/core/model-registry-dynamic.js +11 -5
- package/dist/core/model-registry-dynamic.js.map +1 -1
- package/dist/core/model-registry-loader.d.ts.map +1 -1
- package/dist/core/model-registry-loader.js +8 -0
- package/dist/core/model-registry-loader.js.map +1 -1
- package/dist/core/model-registry-schemas.d.ts +93 -8
- package/dist/core/model-registry-schemas.d.ts.map +1 -1
- package/dist/core/model-registry-schemas.js +24 -12
- package/dist/core/model-registry-schemas.js.map +1 -1
- package/dist/core/model-registry-types.d.ts +7 -6
- package/dist/core/model-registry-types.d.ts.map +1 -1
- package/dist/core/model-registry-types.js.map +1 -1
- package/dist/core/model-registry.d.ts +5 -0
- package/dist/core/model-registry.d.ts.map +1 -1
- package/dist/core/model-registry.js +23 -0
- package/dist/core/model-registry.js.map +1 -1
- package/dist/core/model-resolver-cli.d.ts.map +1 -1
- package/dist/core/model-resolver-cli.js +33 -5
- package/dist/core/model-resolver-cli.js.map +1 -1
- package/dist/core/model-resolver-initial.d.ts +6 -1
- package/dist/core/model-resolver-initial.d.ts.map +1 -1
- package/dist/core/model-resolver-initial.js +12 -7
- package/dist/core/model-resolver-initial.js.map +1 -1
- package/dist/core/model-resolver.d.ts +1 -1
- package/dist/core/model-resolver.d.ts.map +1 -1
- package/dist/core/model-resolver.js +1 -1
- package/dist/core/model-resolver.js.map +1 -1
- package/dist/core/resource-loader-context-files.d.ts +1 -0
- package/dist/core/resource-loader-context-files.d.ts.map +1 -1
- package/dist/core/resource-loader-context-files.js +13 -10
- package/dist/core/resource-loader-context-files.js.map +1 -1
- package/dist/core/sdk.d.ts.map +1 -1
- package/dist/core/sdk.js +2 -2
- package/dist/core/sdk.js.map +1 -1
- package/dist/core/session-entry-normalization.d.ts +7 -0
- package/dist/core/session-entry-normalization.d.ts.map +1 -0
- package/dist/core/session-entry-normalization.js +14 -0
- package/dist/core/session-entry-normalization.js.map +1 -0
- package/dist/core/session-manager-core.d.ts.map +1 -1
- package/dist/core/session-manager-core.js +1 -0
- package/dist/core/session-manager-core.js.map +1 -1
- package/dist/core/session-manager-history.d.ts +2 -2
- package/dist/core/session-manager-history.d.ts.map +1 -1
- package/dist/core/session-manager-history.js +127 -108
- package/dist/core/session-manager-history.js.map +1 -1
- package/dist/core/settings-manager-basic-accessors.d.ts +2 -2
- package/dist/core/settings-manager-basic-accessors.d.ts.map +1 -1
- package/dist/core/settings-manager-basic-accessors.js.map +1 -1
- package/dist/core/settings-types.d.ts +1 -1
- package/dist/core/settings-types.d.ts.map +1 -1
- package/dist/core/settings-types.js.map +1 -1
- package/dist/core/tools/bash.d.ts.map +1 -1
- package/dist/core/tools/bash.js +11 -8
- package/dist/core/tools/bash.js.map +1 -1
- package/dist/main-session.d.ts.map +1 -1
- package/dist/main-session.js +1 -0
- package/dist/main-session.js.map +1 -1
- package/dist/modes/interactive/components/settings-selector-options.d.ts.map +1 -1
- package/dist/modes/interactive/components/settings-selector-options.js +3 -1
- package/dist/modes/interactive/components/settings-selector-options.js.map +1 -1
- package/dist/modes/interactive/components/thinking-selector.d.ts.map +1 -1
- package/dist/modes/interactive/components/thinking-selector.js +2 -1
- package/dist/modes/interactive/components/thinking-selector.js.map +1 -1
- package/dist/modes/interactive/interactive-agent-events.d.ts.map +1 -1
- package/dist/modes/interactive/interactive-agent-events.js +2 -1
- package/dist/modes/interactive/interactive-agent-events.js.map +1 -1
- package/dist/modes/interactive/interactive-child-ordering.d.ts +7 -0
- package/dist/modes/interactive/interactive-child-ordering.d.ts.map +1 -0
- package/dist/modes/interactive/interactive-child-ordering.js +26 -0
- package/dist/modes/interactive/interactive-child-ordering.js.map +1 -0
- package/dist/modes/interactive/interactive-deferred-startup.d.ts.map +1 -1
- package/dist/modes/interactive/interactive-deferred-startup.js +2 -2
- package/dist/modes/interactive/interactive-deferred-startup.js.map +1 -1
- package/dist/modes/interactive/interactive-mode-deps.d.ts +1 -1
- package/dist/modes/interactive/interactive-mode-deps.d.ts.map +1 -1
- package/dist/modes/interactive/interactive-mode-deps.js +1 -1
- package/dist/modes/interactive/interactive-mode-deps.js.map +1 -1
- package/dist/modes/interactive/interactive-model-routing.d.ts.map +1 -1
- package/dist/modes/interactive/interactive-model-routing.js +8 -3
- package/dist/modes/interactive/interactive-model-routing.js.map +1 -1
- package/dist/modes/interactive/theme/theme-class.d.ts +1 -1
- package/dist/modes/interactive/theme/theme-class.d.ts.map +1 -1
- package/dist/modes/interactive/theme/theme-class.js +2 -0
- package/dist/modes/interactive/theme/theme-class.js.map +1 -1
- package/dist/utils/clipboard-image.d.ts.map +1 -1
- package/dist/utils/clipboard-image.js +3 -0
- package/dist/utils/clipboard-image.js.map +1 -1
- package/docs/changelog.mdx +19 -0
- package/docs/compaction.md +55 -48
- package/docs/custom-provider.md +18 -5
- package/docs/extensions.md +7 -3
- package/docs/models.md +69 -10
- package/docs/providers.md +1 -1
- package/docs/quickstart.md +11 -7
- package/docs/rpc.md +2 -2
- package/docs/sdk.md +1 -1
- package/docs/settings.md +3 -3
- package/docs/subagents.md +36 -5
- package/docs/tools.md +1 -1
- package/docs/usage.md +4 -2
- package/docs/workflows.md +26 -43
- package/examples/extensions/preset.ts +2 -2
- package/examples/extensions/subagent/README.md +2 -2
- package/examples/extensions/subagent/index.ts +1 -2
- package/examples/extensions/subagent/schemas.ts +4 -1
- package/examples/sdk/12-full-control.ts +1 -1
- package/npm-shrinkwrap.json +48 -51
- package/package.json +7 -7
- package/dist/builtin/subagents/src/runs/foreground/chain-clarify-behavior.ts +0 -75
- package/dist/builtin/subagents/src/runs/foreground/chain-clarify-component.ts +0 -202
- package/dist/builtin/subagents/src/runs/foreground/chain-clarify-edit.ts +0 -97
- package/dist/builtin/subagents/src/runs/foreground/chain-clarify-editor.ts +0 -160
- package/dist/builtin/subagents/src/runs/foreground/chain-clarify-frame.ts +0 -72
- package/dist/builtin/subagents/src/runs/foreground/chain-clarify-render-modes.ts +0 -161
- package/dist/builtin/subagents/src/runs/foreground/chain-clarify-render-selectors.ts +0 -203
- package/dist/builtin/subagents/src/runs/foreground/chain-clarify-selectors.ts +0 -234
- package/dist/builtin/subagents/src/runs/foreground/chain-clarify-state.ts +0 -103
- package/dist/builtin/subagents/src/runs/foreground/chain-clarify-types.ts +0 -29
- package/dist/builtin/subagents/src/runs/foreground/chain-clarify.ts +0 -9
- package/dist/builtin/subagents/src/runs/foreground/chain-execution-clarify.ts +0 -117
|
@@ -1,13 +1,10 @@
|
|
|
1
1
|
export const DEFAULT_PROMPT_GUIDANCE: string[] = [
|
|
2
|
-
`**Subagent
|
|
3
|
-
-
|
|
4
|
-
-
|
|
5
|
-
-
|
|
6
|
-
-
|
|
7
|
-
-
|
|
8
|
-
|
|
9
|
-
- Explain the debugger's insights to the user clearly and concisely.
|
|
10
|
-
- Once the user confirms, implement the necessary code changes based on those insights.
|
|
11
|
-
- If the user has follow-up questions, spawn additional debugger and research subagents as needed.`,
|
|
2
|
+
`**Subagent orchestration**: Use subagents selectively for bounded specialist delegation while the parent remains in control.
|
|
3
|
+
- Keep interactive, exploratory, conceptual, and conversation-led work inline when direct discussion and user steering are more useful than delegation.
|
|
4
|
+
- Use a single subagent for a focused specialty, a chain for a bounded sequential handoff, or parallel tasks for independent work. Multiple steps, files, tests, validation, or parallelism alone do not require a workflow.
|
|
5
|
+
- Delegate noisy or context-heavy command investigation when isolation helps, but run concise commands inline when that is simpler. Do not split work with substantial overlap across independent subagents.
|
|
6
|
+
- Use async/background execution selectively for genuinely long-running or independently useful delegated work. Foreground execution is appropriate when the parent needs the result before proceeding; do not duplicate a delegated job while waiting.
|
|
7
|
+
- For clearly delegated, well-defined autonomous jobs that are likely long-running/background-oriented or materially need durable stages, checkpoints, resumability, human input, gates, retries, or bounded loops, prefer an appropriate workflow rather than stretching subagent orchestration into an ad hoc workflow.
|
|
8
|
+
- Debug conceptual questions or exploratory analysis inline when appropriate. Use the debugger subagent for actual failures that need reproduction, root-cause diagnosis, and a validated fix; additional debugger or research delegates are optional when they add a distinct useful angle.`,
|
|
12
9
|
];
|
|
13
10
|
|
|
@@ -3,7 +3,7 @@
|
|
|
3
3
|
*/
|
|
4
4
|
|
|
5
5
|
import { Type } from "typebox";
|
|
6
|
-
import { MAX_SUBAGENT_NESTING_DEPTH, SUBAGENT_ACTIONS } from "../shared/types.ts";
|
|
6
|
+
import { MAX_PARALLEL_TASKS, MAX_SUBAGENT_NESTING_DEPTH, SUBAGENT_ACTIONS } from "../shared/types.ts";
|
|
7
7
|
|
|
8
8
|
const SkillOverride = Type.Unsafe({
|
|
9
9
|
anyOf: [
|
|
@@ -35,12 +35,25 @@ const ReadsOverride = Type.Unsafe({
|
|
|
35
35
|
description: "Files to read before running (array of filenames), or false to disable",
|
|
36
36
|
});
|
|
37
37
|
|
|
38
|
+
const RootReadsOverride = Type.Unsafe({
|
|
39
|
+
anyOf: [
|
|
40
|
+
{ type: "array", items: { type: "string" } },
|
|
41
|
+
{ type: "boolean", enum: [false] },
|
|
42
|
+
],
|
|
43
|
+
description: "Files for a single agent to read before running, or false to disable. Relative paths resolve against the effective child cwd.",
|
|
44
|
+
});
|
|
45
|
+
|
|
38
46
|
const JsonSchemaObject = Type.Unsafe({
|
|
39
47
|
type: "object",
|
|
40
48
|
additionalProperties: true,
|
|
41
49
|
description: "Plain JSON Schema object for structured output.",
|
|
42
50
|
});
|
|
43
51
|
|
|
52
|
+
const MaxOutputSchema = Type.Object({
|
|
53
|
+
bytes: Type.Optional(Type.Number()),
|
|
54
|
+
lines: Type.Optional(Type.Number()),
|
|
55
|
+
}, { additionalProperties: false });
|
|
56
|
+
|
|
44
57
|
const TaskItem = Type.Object({
|
|
45
58
|
agent: Type.String(),
|
|
46
59
|
task: Type.String(),
|
|
@@ -185,7 +198,10 @@ export const SubagentParams = Type.Object({
|
|
|
185
198
|
],
|
|
186
199
|
description: `Agent or chain config for create/update. Agent: name, package (optional namespace; runtime name becomes package.name), description, scope ('user'|'project', default 'user'), systemPrompt, systemPromptMode, inheritProjectContext, inheritSkills, defaultContext ('fresh'|'fork'), model, tools (comma-separated), extensions (comma-separated), skills (comma-separated), thinking, output, reads, progress, maxSubagentDepth (integer >= 0, clamped to ${MAX_SUBAGENT_NESTING_DEPTH}). Chain: name, package, description, scope, steps (array of {agent, task?, output?, outputMode?, reads?, model?, skill?, progress?}). Presence of 'steps' creates a chain instead of an agent. String values must be valid JSON.`
|
|
187
200
|
})),
|
|
188
|
-
tasks: Type.Optional(Type.Array(TaskItem, {
|
|
201
|
+
tasks: Type.Optional(Type.Array(TaskItem, {
|
|
202
|
+
maxItems: MAX_PARALLEL_TASKS,
|
|
203
|
+
description: `PARALLEL mode: [{agent, task, count?, output?, outputMode?, reads?, progress?}, ...]. Maximum ${MAX_PARALLEL_TASKS} tasks after count expansion.`,
|
|
204
|
+
})),
|
|
189
205
|
concurrency: Type.Optional(Type.Integer({ minimum: 1, description: "Top-level PARALLEL mode only: max concurrent tasks. Defaults to config.parallel.concurrency or 4." })),
|
|
190
206
|
worktree: Type.Optional(Type.Boolean({
|
|
191
207
|
description: "Create isolated git worktrees for each parallel task. " +
|
|
@@ -201,14 +217,13 @@ export const SubagentParams = Type.Object({
|
|
|
201
217
|
async: Type.Optional(Type.Boolean({ description: "Run in background (default: false, or per config)" })),
|
|
202
218
|
agentScope: Type.Optional(Type.String({ description: "Agent discovery scope: 'user', 'project', or 'both' (default: 'both'; project wins on name collisions)" })),
|
|
203
219
|
cwd: Type.Optional(Type.String()),
|
|
220
|
+
maxOutput: Type.Optional(MaxOutputSchema),
|
|
204
221
|
artifacts: Type.Optional(Type.Boolean({ description: "Write debug artifacts (default: true)" })),
|
|
205
222
|
includeProgress: Type.Optional(Type.Boolean({ description: "Include full progress in result (default: false)" })),
|
|
206
223
|
share: Type.Optional(Type.Boolean({ description: "Upload session to GitHub Gist for sharing (default: false)" })),
|
|
207
224
|
sessionDir: Type.Optional(
|
|
208
225
|
Type.String({ description: "Directory to store session logs (default: temp; enables sessions even if share=false)" }),
|
|
209
226
|
),
|
|
210
|
-
// Clarification TUI
|
|
211
|
-
clarify: Type.Optional(Type.Boolean({ description: "Show TUI to preview/edit before execution. Explicit clarify: true keeps the run foreground for the clarify UI; omitted clarify can still run in the background when async: true is set." })),
|
|
212
227
|
control: Type.Optional(ControlOverrides),
|
|
213
228
|
// Solo agent overrides
|
|
214
229
|
output: Type.Optional(Type.Unsafe({
|
|
@@ -219,6 +234,8 @@ export const SubagentParams = Type.Object({
|
|
|
219
234
|
description: "Output file for single agent (string), or false to disable. Relative paths resolve against cwd.",
|
|
220
235
|
})),
|
|
221
236
|
outputMode: Type.Optional(OutputModeOverride),
|
|
237
|
+
reads: Type.Optional(RootReadsOverride),
|
|
238
|
+
progress: Type.Optional(Type.Boolean({ description: "Enable run-scoped progress.md tracking for a single agent under isolated artifact storage, without writing progress.md into the child cwd. This controls the child-maintained file; includeProgress separately controls whether detailed runtime telemetry is returned." })),
|
|
222
239
|
skill: Type.Optional(SkillOverride),
|
|
223
240
|
model: Type.Optional(Type.String({ description: "Override model for single agent (e.g. 'anthropic/claude-sonnet-4')" })),
|
|
224
|
-
});
|
|
241
|
+
}, { additionalProperties: false });
|
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
import { APP_NAME } from "@bastani/atomic";
|
|
2
|
+
|
|
3
|
+
export const SUBAGENT_TOOL_DESCRIPTION = `Delegate bounded specialist work to subagents or manage agent definitions while the parent remains in control.
|
|
4
|
+
EXECUTION (use exactly ONE mode):
|
|
5
|
+
• Execution calls always start non-interactively.
|
|
6
|
+
• Before executing, use { action: "list" } to inspect configured agents/chains. Only execute agents listed as executable/non-disabled.
|
|
7
|
+
• SINGLE: { agent, task?, progress? } - one focused task; progress:true maintains a run-scoped progress.md under isolated artifact storage without writing it into the child cwd (separate from includeProgress, which only returns runtime telemetry); omit task for self-contained agents
|
|
8
|
+
• CHAIN: { chain: [{agent:"agent-a"}, {parallel:[{agent:"agent-b",count:3}]}] } - bounded sequential pipeline with optional parallel fan-out
|
|
9
|
+
• PARALLEL: { tasks: [{agent,task,count?,output?,reads?,progress?}, ...], concurrency?: number, worktree?: true } - independent concurrent tasks (worktree: isolate each task in a git worktree)
|
|
10
|
+
• Optional context: { context: "fresh" | "fork" } (default: if any requested agent has defaultContext: "fork", the whole invocation uses fork; otherwise "fresh"; inspect agent defaults via { action: "list" })
|
|
11
|
+
• async:true is selective for genuinely long-running/background work; foreground is appropriate when the parent needs the result before proceeding
|
|
12
|
+
CHAIN TEMPLATE VARIABLES (use in task strings):
|
|
13
|
+
• {task} - The original task/request from the user
|
|
14
|
+
• {previous} - Text response from the previous step (empty for first step)
|
|
15
|
+
• {chain_dir} - Shared directory for chain files (e.g., <tmpdir>/${APP_NAME}-subagents-<scope>/chain-runs/abc123/)
|
|
16
|
+
Example: { chain: [{agent:"agent-a", task:"Analyze {task}"}, {agent:"agent-b", task:"Plan based on {previous}"}] }
|
|
17
|
+
MANAGEMENT (use action field, omit agent/task/chain/tasks):
|
|
18
|
+
• { action: "list" } - discover executable agents/chains
|
|
19
|
+
• { action: "get", agent: "name" } - full detail; packaged agents use dotted runtime names like "package.agent"
|
|
20
|
+
• { action: "create", config: { name: "custom-agent", package: "code-analysis", systemPrompt, systemPromptMode, inheritProjectContext, inheritSkills, defaultContext, ... } }
|
|
21
|
+
• { action: "update", agent: "code-analysis.custom-agent", config: { package: "analysis", ... } } - merge
|
|
22
|
+
• { action: "delete", agent: "code-analysis.custom-agent" }
|
|
23
|
+
• Use chainName for chain operations; packaged chains also use dotted runtime names
|
|
24
|
+
CONTROL:
|
|
25
|
+
• { action: "status", id: "..." } - inspect an async/background run by id or prefix
|
|
26
|
+
• { action: "interrupt", id?: "..." } - soft-interrupt the current child turn and leave the run paused
|
|
27
|
+
• { action: "resume", id: "...", message: "...", index?: 0 } - follow up with a live async child or revive a completed async/foreground child from its session
|
|
28
|
+
DIAGNOSTICS:
|
|
29
|
+
• { action: "doctor" } - read-only report for runtime paths, discovery, sessions, and intercom`;
|
|
@@ -2,7 +2,8 @@ import { execSync } from "node:child_process";
|
|
|
2
2
|
import * as fs from "node:fs";
|
|
3
3
|
import * as os from "node:os";
|
|
4
4
|
import * as path from "node:path";
|
|
5
|
-
import {
|
|
5
|
+
import { fileURLToPath } from "node:url";
|
|
6
|
+
import { APP_NAME, getProjectConfigDirs, getEnvValue } from "@bastani/atomic";
|
|
6
7
|
import type { AgentConfig } from "../agents/agents.ts";
|
|
7
8
|
import type { ExtensionConfig, IntercomBridgeConfig, IntercomBridgeMode } from "../shared/types.ts";
|
|
8
9
|
import { getAgentDir } from "../shared/utils.ts";
|
|
@@ -12,11 +13,16 @@ const PI_INTERCOM_PACKAGE_NAME = "pi-intercom";
|
|
|
12
13
|
function defaultAgentDir(): string {
|
|
13
14
|
return getAgentDir();
|
|
14
15
|
}
|
|
16
|
+
const INTERCOM_SESSION_ID_ENV = `${APP_NAME.toUpperCase()}_INTERCOM_SESSION_ID`;
|
|
15
17
|
|
|
16
18
|
function defaultIntercomExtensionDir(agentDir = defaultAgentDir()): string {
|
|
17
19
|
return path.join(agentDir, "extensions", PI_INTERCOM_PACKAGE_NAME);
|
|
18
20
|
}
|
|
19
21
|
|
|
22
|
+
function bundledIntercomExtensionDir(): string {
|
|
23
|
+
return path.resolve(path.dirname(fileURLToPath(import.meta.url)), "..", "..", "..", "intercom");
|
|
24
|
+
}
|
|
25
|
+
|
|
20
26
|
function defaultIntercomConfigPath(agentDir = defaultAgentDir()): string {
|
|
21
27
|
return path.join(agentDir, "intercom", "config.json");
|
|
22
28
|
}
|
|
@@ -72,6 +78,8 @@ interface ResolveIntercomBridgeInput {
|
|
|
72
78
|
}
|
|
73
79
|
|
|
74
80
|
export function resolveIntercomSessionTarget(sessionName: string | undefined, sessionId: string): string {
|
|
81
|
+
const connectedIntercomSessionId = getEnvValue(INTERCOM_SESSION_ID_ENV)?.trim();
|
|
82
|
+
if (connectedIntercomSessionId) return connectedIntercomSessionId;
|
|
75
83
|
const trimmedName = sessionName?.trim();
|
|
76
84
|
if (trimmedName) return trimmedName;
|
|
77
85
|
const normalizedSessionId = sessionId.startsWith("session-") ? sessionId.slice("session-".length) : sessionId;
|
|
@@ -231,7 +239,10 @@ function configuredPiIntercomPackageDir(input: ResolveIntercomBridgeInput, agent
|
|
|
231
239
|
}
|
|
232
240
|
|
|
233
241
|
function resolveIntercomExtensionDir(input: ResolveIntercomBridgeInput, agentDir: string): string {
|
|
234
|
-
|
|
242
|
+
if (input.extensionDir) return path.resolve(input.extensionDir);
|
|
243
|
+
const bundledDir = bundledIntercomExtensionDir();
|
|
244
|
+
if (packageHasPiExtension(bundledDir)) return bundledDir;
|
|
245
|
+
const legacyDir = path.resolve(defaultIntercomExtensionDir(agentDir));
|
|
235
246
|
if (fs.existsSync(legacyDir)) return legacyDir;
|
|
236
247
|
return configuredPiIntercomPackageDir(input, agentDir) ?? legacyDir;
|
|
237
248
|
}
|
|
@@ -167,7 +167,7 @@ function formatNestedResultLines(children: PublicNestedRunSummary[] | undefined)
|
|
|
167
167
|
return lines;
|
|
168
168
|
}
|
|
169
169
|
|
|
170
|
-
interface GroupedResultIntercomMessageInput {
|
|
170
|
+
export interface GroupedResultIntercomMessageInput {
|
|
171
171
|
to: string;
|
|
172
172
|
runId: string;
|
|
173
173
|
mode: SubagentRunMode;
|
|
@@ -276,7 +276,7 @@ export function buildSubagentResultIntercomPayload(input: GroupedResultIntercomM
|
|
|
276
276
|
export async function deliverSubagentResultIntercomEvent(
|
|
277
277
|
events: IntercomEventBus,
|
|
278
278
|
payload: SubagentResultIntercomPayload,
|
|
279
|
-
timeoutMs = 500,
|
|
279
|
+
timeoutMs: number | false = 500,
|
|
280
280
|
): Promise<boolean> {
|
|
281
281
|
return deliverSubagentIntercomMessageEvent(events, payload.to, payload.message, timeoutMs, payload as unknown as Record<string, unknown>);
|
|
282
282
|
}
|
|
@@ -285,7 +285,7 @@ export async function deliverSubagentIntercomMessageEvent(
|
|
|
285
285
|
events: IntercomEventBus,
|
|
286
286
|
to: string,
|
|
287
287
|
message: string,
|
|
288
|
-
timeoutMs = 500,
|
|
288
|
+
timeoutMs: number | false = 500,
|
|
289
289
|
extra: Record<string, unknown> = {},
|
|
290
290
|
): Promise<boolean> {
|
|
291
291
|
if (typeof events.on !== "function" || typeof events.emit !== "function") return false;
|
|
@@ -307,7 +307,7 @@ export async function deliverSubagentIntercomMessageEvent(
|
|
|
307
307
|
if (delivery.requestId !== requestId) return;
|
|
308
308
|
finish(delivery.delivered === true);
|
|
309
309
|
});
|
|
310
|
-
timer = setTimeout(() => finish(false), timeoutMs);
|
|
310
|
+
if (timeoutMs !== false) timer = setTimeout(() => finish(false), timeoutMs);
|
|
311
311
|
try {
|
|
312
312
|
events.emit(SUBAGENT_RESULT_INTERCOM_EVENT, { ...extra, to, message, requestId });
|
|
313
313
|
} catch {
|
|
@@ -0,0 +1,106 @@
|
|
|
1
|
+
import * as fs from "node:fs";
|
|
2
|
+
import type { DrainableSource, JsonlWriteStream } from "../../shared/jsonl-writer.ts";
|
|
3
|
+
import { acquireEventWriter } from "../../shared/event-jsonl-writer.ts";
|
|
4
|
+
|
|
5
|
+
const DEFAULT_TELEMETRY_BYTES = 512 * 1024;
|
|
6
|
+
const CAPPED_CHILD_EVENT_TYPES = new Set([
|
|
7
|
+
"message_update", "tool_execution_update", "subagent.child.stdout", "subagent.child.stderr",
|
|
8
|
+
]);
|
|
9
|
+
|
|
10
|
+
interface ChildEventJournalContext {
|
|
11
|
+
runId: string;
|
|
12
|
+
stepIndex?: number;
|
|
13
|
+
agent: string;
|
|
14
|
+
}
|
|
15
|
+
|
|
16
|
+
interface ChildEventJournalDeps {
|
|
17
|
+
maxTelemetryBytes?: number;
|
|
18
|
+
createWriteStream?: (filePath: string) => JsonlWriteStream;
|
|
19
|
+
now?: () => number;
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
export interface ChildEventJournal {
|
|
23
|
+
append(event: Record<string, unknown>): void;
|
|
24
|
+
close(): Promise<void>;
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
function withoutKey(record: Record<string, unknown>, key: string): Record<string, unknown> {
|
|
28
|
+
const { [key]: _removed, ...rest } = record;
|
|
29
|
+
return rest;
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
/** Remove cumulative streaming snapshots while retaining compact delta metadata. */
|
|
33
|
+
export function sanitizeChildEvent(event: Record<string, unknown>): Record<string, unknown> {
|
|
34
|
+
let sanitized = event;
|
|
35
|
+
if (event.type === "message_update") {
|
|
36
|
+
sanitized = withoutKey(event, "message");
|
|
37
|
+
const assistantEvent = sanitized.assistantMessageEvent;
|
|
38
|
+
if (assistantEvent && typeof assistantEvent === "object" && !Array.isArray(assistantEvent)) {
|
|
39
|
+
let compactEvent = withoutKey(withoutKey(assistantEvent as Record<string, unknown>, "partial"), "message");
|
|
40
|
+
if (!("delta" in compactEvent)) {
|
|
41
|
+
compactEvent = withoutKey(withoutKey(compactEvent, "content"), "toolCall");
|
|
42
|
+
}
|
|
43
|
+
sanitized = { ...sanitized, assistantMessageEvent: compactEvent };
|
|
44
|
+
}
|
|
45
|
+
}
|
|
46
|
+
if (event.type === "message_start") sanitized = withoutKey(sanitized, "message");
|
|
47
|
+
if (event.type === "tool_execution_update") sanitized = withoutKey(sanitized, "partialResult");
|
|
48
|
+
if (event.type === "turn_end") sanitized = withoutKey(sanitized, "message");
|
|
49
|
+
if (event.type === "agent_end") sanitized = withoutKey(sanitized, "messages");
|
|
50
|
+
return sanitized;
|
|
51
|
+
}
|
|
52
|
+
|
|
53
|
+
export function createChildEventJournal(
|
|
54
|
+
filePath: string | undefined,
|
|
55
|
+
source: DrainableSource,
|
|
56
|
+
context: ChildEventJournalContext,
|
|
57
|
+
deps: ChildEventJournalDeps = {},
|
|
58
|
+
): ChildEventJournal {
|
|
59
|
+
if (!filePath) return { append() {}, async close() {} };
|
|
60
|
+
const createStream = deps.createWriteStream ?? ((target: string) => fs.createWriteStream(target, { flags: "a" }));
|
|
61
|
+
const writer = acquireEventWriter(filePath, source, createStream);
|
|
62
|
+
if (!writer) return { append() {}, async close() {} };
|
|
63
|
+
const maxTelemetryBytes = deps.maxTelemetryBytes ?? DEFAULT_TELEMETRY_BYTES;
|
|
64
|
+
const now = deps.now ?? Date.now;
|
|
65
|
+
let closed = false;
|
|
66
|
+
let closePromise: Promise<void> | undefined;
|
|
67
|
+
const write = (record: Record<string, unknown>): void => writer.writeLine(JSON.stringify(record));
|
|
68
|
+
|
|
69
|
+
const enrich = (event: Record<string, unknown>): Record<string, unknown> => ({
|
|
70
|
+
...event,
|
|
71
|
+
subagentSource: "child",
|
|
72
|
+
subagentRunId: context.runId,
|
|
73
|
+
subagentStepIndex: context.stepIndex,
|
|
74
|
+
subagentAgent: context.agent,
|
|
75
|
+
observedAt: now(),
|
|
76
|
+
});
|
|
77
|
+
|
|
78
|
+
return {
|
|
79
|
+
append(event) {
|
|
80
|
+
if (closed) return;
|
|
81
|
+
const sanitized = sanitizeChildEvent(event);
|
|
82
|
+
const record = enrich(sanitized);
|
|
83
|
+
const lineBytes = Buffer.byteLength(`${JSON.stringify(record)}\n`, "utf-8");
|
|
84
|
+
const assistantEvent = event.type === "message_update" && event.assistantMessageEvent
|
|
85
|
+
&& typeof event.assistantMessageEvent === "object" && !Array.isArray(event.assistantMessageEvent)
|
|
86
|
+
? event.assistantMessageEvent as Record<string, unknown>
|
|
87
|
+
: undefined;
|
|
88
|
+
const nestedTerminal = assistantEvent?.type === "done" || assistantEvent?.type === "error";
|
|
89
|
+
const capped = !nestedTerminal && typeof event.type === "string" && CAPPED_CHILD_EVENT_TYPES.has(event.type);
|
|
90
|
+
if (capped && !writer.reserveTelemetry(lineBytes, maxTelemetryBytes)) {
|
|
91
|
+
if (writer.claimTruncationMarker()) {
|
|
92
|
+
write(enrich({ type: "subagent.child.telemetry_truncated", maxTelemetryBytes }));
|
|
93
|
+
}
|
|
94
|
+
return;
|
|
95
|
+
}
|
|
96
|
+
write(record);
|
|
97
|
+
},
|
|
98
|
+
close() {
|
|
99
|
+
if (!closePromise) {
|
|
100
|
+
closed = true;
|
|
101
|
+
closePromise = writer.close();
|
|
102
|
+
}
|
|
103
|
+
return closePromise;
|
|
104
|
+
},
|
|
105
|
+
};
|
|
106
|
+
}
|
|
@@ -59,10 +59,11 @@ const jitiCliPath = resolveJitiCliPath();
|
|
|
59
59
|
|
|
60
60
|
export function formatAsyncStartedMessage(headline: string): string {
|
|
61
61
|
return [
|
|
62
|
-
headline
|
|
62
|
+
`Launched: ${headline}`,
|
|
63
|
+
"Completion pending; Pi will deliver the result when the detached run finishes.",
|
|
63
64
|
"",
|
|
64
65
|
"The async run is detached. Do not run sleep timers or polling loops just to wait for it.",
|
|
65
|
-
"If you have independent work, continue that work. If you have nothing else to do until the async result arrives, end your turn now
|
|
66
|
+
"If you have independent work, continue that work. If you have nothing else to do until the async result arrives, end your turn now.",
|
|
66
67
|
"Use subagent({ action: \"status\", id: \"...\" }) when you need the current status/result, or to inspect a blocked/stale run. Do not poll just to wait.",
|
|
67
68
|
].join("\n");
|
|
68
69
|
}
|
|
@@ -4,6 +4,7 @@ import { getEnvValue } from "@bastani/atomic";
|
|
|
4
4
|
import { buildSkillInjection, resolveSkillsWithFallback } from "../../agents/skills.ts";
|
|
5
5
|
import { getSubagentCodexFastModeSettings, resolveSubagentCodexFastModeScope, resolveSubagentModelFastModeMetadata } from "../../shared/fast-mode.ts";
|
|
6
6
|
import { resolveEffectiveThinking } from "../../shared/model-info.ts";
|
|
7
|
+
import { injectSingleProgressInstruction, writeInitialProgressFile } from "../../shared/settings.ts";
|
|
7
8
|
import { ASYNC_DIR, RESULTS_DIR, SUBAGENT_ASYNC_STARTED_EVENT, resolveChildMaxSubagentDepth } from "../../shared/types.ts";
|
|
8
9
|
import { resolveChildCwd } from "../../shared/utils.ts";
|
|
9
10
|
import { applyThinkingSuffix, SUBAGENT_INTERCOM_SESSION_NAME_ENV } from "../shared/pi-args.ts";
|
|
@@ -16,7 +17,7 @@ import {
|
|
|
16
17
|
formatAsyncStartedMessage,
|
|
17
18
|
formatAsyncStartError,
|
|
18
19
|
piPackageRoot,
|
|
19
|
-
spawnRunner,
|
|
20
|
+
spawnRunner as defaultSpawnRunner,
|
|
20
21
|
} from "./async-execution-common.ts";
|
|
21
22
|
import type { AsyncExecutionResult, AsyncSingleParams, AsyncSpawnResult } from "./async-execution-types.ts";
|
|
22
23
|
|
|
@@ -46,6 +47,7 @@ export function executeAsyncSingle(
|
|
|
46
47
|
controlIntercomTarget,
|
|
47
48
|
childIntercomTarget,
|
|
48
49
|
nestedRoute,
|
|
50
|
+
spawnRunner = defaultSpawnRunner,
|
|
49
51
|
} = params;
|
|
50
52
|
const task = params.task ?? "";
|
|
51
53
|
const runnerCwd = resolveChildCwd(ctx.cwd, cwd);
|
|
@@ -81,7 +83,16 @@ export function executeAsyncSingle(
|
|
|
81
83
|
const outputMode = params.outputMode ?? "inline";
|
|
82
84
|
const validationError = validateFileOnlyOutputMode(outputMode, outputPath, `Async single run (${agent})`);
|
|
83
85
|
if (validationError) return formatAsyncStartError("single", validationError);
|
|
84
|
-
|
|
86
|
+
let taskWithOutputInstruction = injectSingleOutputInstruction(task, outputPath);
|
|
87
|
+
// Keep each child's progress contract outside its cwd and isolated by run;
|
|
88
|
+
// artifacts-disabled async runs use their already run-owned async directory.
|
|
89
|
+
if (params.progress) {
|
|
90
|
+
const progressDir = artifactConfig.enabled && artifactsDir
|
|
91
|
+
? path.join(artifactsDir, "progress", id)
|
|
92
|
+
: path.join(asyncDir, "progress");
|
|
93
|
+
writeInitialProgressFile(progressDir);
|
|
94
|
+
taskWithOutputInstruction = injectSingleProgressInstruction(taskWithOutputInstruction, progressDir);
|
|
95
|
+
}
|
|
85
96
|
const model = applyThinkingSuffix(
|
|
86
97
|
resolveModelCandidate(params.modelOverride ?? agentConfig.model, availableModels, ctx.currentModelProvider),
|
|
87
98
|
agentConfig.thinking,
|
|
@@ -61,6 +61,7 @@ export interface AsyncSingleParams {
|
|
|
61
61
|
skills?: string[];
|
|
62
62
|
output?: string | boolean;
|
|
63
63
|
outputMode?: "inline" | "file-only";
|
|
64
|
+
progress?: boolean;
|
|
64
65
|
modelOverride?: string;
|
|
65
66
|
availableModels?: AvailableModelInfo[];
|
|
66
67
|
knownModelProviders?: string[];
|
|
@@ -72,6 +73,8 @@ export interface AsyncSingleParams {
|
|
|
72
73
|
controlIntercomTarget?: string;
|
|
73
74
|
childIntercomTarget?: (agent: string, index: number) => string | undefined;
|
|
74
75
|
nestedRoute?: NestedRouteInfo;
|
|
76
|
+
/** Internal launch seam used by focused runtime tests. */
|
|
77
|
+
spawnRunner?: (config: object, suffix: string, cwd: string) => AsyncSpawnResult;
|
|
75
78
|
}
|
|
76
79
|
|
|
77
80
|
export interface AsyncExecutionResult {
|
|
@@ -97,7 +97,7 @@ export function createAsyncJobTracker(pi: Pick<ExtensionAPI, "events">, state: S
|
|
|
97
97
|
const pollIntervalMs = options.pollIntervalMs ?? POLL_INTERVAL_MS;
|
|
98
98
|
const resultsDir = options.resultsDir ?? RESULTS_DIR;
|
|
99
99
|
const rerenderWidget = (ctx: ExtensionContext, jobs = Array.from(state.asyncJobs.values())) => {
|
|
100
|
-
renderWidget(ctx, jobs);
|
|
100
|
+
renderWidget(ctx, jobs, pi);
|
|
101
101
|
};
|
|
102
102
|
const cancelCleanup = (asyncId: string) => {
|
|
103
103
|
const existingTimer = state.cleanupTimers.get(asyncId);
|
|
@@ -0,0 +1,189 @@
|
|
|
1
|
+
import type { FrozenCompletionEnvelope } from "./result-file-claims.js";
|
|
2
|
+
|
|
3
|
+
type CompletionClaimStatus = "delivered" | "retry" | "exhausted" | "conflict" | "released";
|
|
4
|
+
type TerminalStatus = Extract<CompletionClaimStatus, "delivered" | "exhausted">;
|
|
5
|
+
|
|
6
|
+
interface CompletionAttempt {
|
|
7
|
+
status: CompletionClaimStatus;
|
|
8
|
+
noProgressFailures: number;
|
|
9
|
+
}
|
|
10
|
+
|
|
11
|
+
interface CompletionFlight {
|
|
12
|
+
promise: Promise<CompletionAttempt>;
|
|
13
|
+
}
|
|
14
|
+
|
|
15
|
+
export interface CompletionClaimSnapshot {
|
|
16
|
+
intercomDelivered: boolean;
|
|
17
|
+
localDelivered: boolean;
|
|
18
|
+
noProgressFailures: number;
|
|
19
|
+
terminalStatus?: TerminalStatus;
|
|
20
|
+
envelope: FrozenCompletionEnvelope;
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
interface CompletionClaim extends CompletionClaimSnapshot {
|
|
24
|
+
signature: string;
|
|
25
|
+
inFlight?: CompletionFlight;
|
|
26
|
+
completedAt?: number;
|
|
27
|
+
lastTouchedAt: number;
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
export interface CompletionClaimResult extends CompletionAttempt {
|
|
31
|
+
owner: boolean;
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
export interface CompletionDeliveryPhases {
|
|
35
|
+
intercom?: (envelope: FrozenCompletionEnvelope) => Promise<boolean> | boolean;
|
|
36
|
+
local?: (envelope: FrozenCompletionEnvelope) => Promise<boolean> | boolean;
|
|
37
|
+
isOwned?: () => boolean;
|
|
38
|
+
onState?: (snapshot: CompletionClaimSnapshot) => void;
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
export interface CompletionClaimInitial {
|
|
42
|
+
intercomDelivered?: boolean;
|
|
43
|
+
localDelivered?: boolean;
|
|
44
|
+
noProgressFailures?: number;
|
|
45
|
+
terminalStatus?: TerminalStatus;
|
|
46
|
+
envelope?: FrozenCompletionEnvelope;
|
|
47
|
+
}
|
|
48
|
+
|
|
49
|
+
const STORE_KEY = "__atomicSubagentCompletionClaims";
|
|
50
|
+
const DEFAULT_MAX_NO_PROGRESS_FAILURES = 8;
|
|
51
|
+
const MAX_CLAIMS = 2048;
|
|
52
|
+
|
|
53
|
+
function cloneEnvelope(envelope: FrozenCompletionEnvelope): FrozenCompletionEnvelope {
|
|
54
|
+
return JSON.parse(JSON.stringify(envelope)) as FrozenCompletionEnvelope;
|
|
55
|
+
}
|
|
56
|
+
|
|
57
|
+
function claims(): Map<string, CompletionClaim> {
|
|
58
|
+
const globalStore = globalThis as Record<string, unknown>;
|
|
59
|
+
const existing = globalStore[STORE_KEY];
|
|
60
|
+
if (existing instanceof Map) return existing as Map<string, CompletionClaim>;
|
|
61
|
+
const created = new Map<string, CompletionClaim>();
|
|
62
|
+
globalStore[STORE_KEY] = created;
|
|
63
|
+
return created;
|
|
64
|
+
}
|
|
65
|
+
|
|
66
|
+
function prune(store: Map<string, CompletionClaim>, now: number, ttlMs: number): void {
|
|
67
|
+
for (const [key, claim] of store) {
|
|
68
|
+
if (claim.completedAt !== undefined && now - claim.completedAt > ttlMs) store.delete(key);
|
|
69
|
+
}
|
|
70
|
+
if (store.size <= MAX_CLAIMS) return;
|
|
71
|
+
const disposable = [...store.entries()]
|
|
72
|
+
.filter(([, claim]) => !claim.inFlight && !claim.intercomDelivered && !claim.localDelivered)
|
|
73
|
+
.sort((a, b) => a[1].lastTouchedAt - b[1].lastTouchedAt);
|
|
74
|
+
for (const [key] of disposable) {
|
|
75
|
+
if (store.size <= MAX_CLAIMS) break;
|
|
76
|
+
store.delete(key);
|
|
77
|
+
}
|
|
78
|
+
}
|
|
79
|
+
|
|
80
|
+
function snapshot(claim: CompletionClaim): CompletionClaimSnapshot {
|
|
81
|
+
return {
|
|
82
|
+
intercomDelivered: claim.intercomDelivered,
|
|
83
|
+
localDelivered: claim.localDelivered,
|
|
84
|
+
noProgressFailures: claim.noProgressFailures,
|
|
85
|
+
terminalStatus: claim.terminalStatus,
|
|
86
|
+
envelope: cloneEnvelope(claim.envelope),
|
|
87
|
+
};
|
|
88
|
+
}
|
|
89
|
+
|
|
90
|
+
function persist(claim: CompletionClaim, callback: CompletionDeliveryPhases["onState"]): void {
|
|
91
|
+
claim.lastTouchedAt = Date.now();
|
|
92
|
+
callback?.(snapshot(claim));
|
|
93
|
+
}
|
|
94
|
+
|
|
95
|
+
/** Atomically owns and advances one completion across aliases and watcher replacements. */
|
|
96
|
+
export async function deliverClaimedCompletion(
|
|
97
|
+
key: string,
|
|
98
|
+
signature: string,
|
|
99
|
+
ttlMs: number,
|
|
100
|
+
phases: CompletionDeliveryPhases,
|
|
101
|
+
maxNoProgressFailures = DEFAULT_MAX_NO_PROGRESS_FAILURES,
|
|
102
|
+
initial: CompletionClaimInitial = {},
|
|
103
|
+
envelope: FrozenCompletionEnvelope = { local: {} },
|
|
104
|
+
): Promise<CompletionClaimResult> {
|
|
105
|
+
const store = claims();
|
|
106
|
+
const now = Date.now();
|
|
107
|
+
prune(store, now, ttlMs);
|
|
108
|
+
let claim = store.get(key);
|
|
109
|
+
if (!claim) {
|
|
110
|
+
claim = {
|
|
111
|
+
signature,
|
|
112
|
+
envelope: cloneEnvelope(initial.envelope ?? envelope),
|
|
113
|
+
intercomDelivered: initial.intercomDelivered === true,
|
|
114
|
+
localDelivered: initial.localDelivered === true,
|
|
115
|
+
noProgressFailures: initial.noProgressFailures ?? 0,
|
|
116
|
+
terminalStatus: initial.terminalStatus,
|
|
117
|
+
completedAt: initial.terminalStatus ? now : undefined,
|
|
118
|
+
lastTouchedAt: now,
|
|
119
|
+
};
|
|
120
|
+
store.set(key, claim);
|
|
121
|
+
persist(claim, phases.onState);
|
|
122
|
+
} else if (claim.signature !== signature) {
|
|
123
|
+
return { owner: false, status: "conflict", noProgressFailures: claim.noProgressFailures };
|
|
124
|
+
}
|
|
125
|
+
claim.lastTouchedAt = now;
|
|
126
|
+
if (claim.terminalStatus) return { owner: false, status: claim.terminalStatus, noProgressFailures: claim.noProgressFailures };
|
|
127
|
+
if (claim.inFlight) return { owner: false, ...await claim.inFlight.promise };
|
|
128
|
+
|
|
129
|
+
const ownedClaim = claim;
|
|
130
|
+
const hasVisibleProgress = () => ownedClaim.intercomDelivered || ownedClaim.localDelivered;
|
|
131
|
+
const retireForOwnershipLoss = (): CompletionAttempt => {
|
|
132
|
+
if (!hasVisibleProgress()) {
|
|
133
|
+
store.delete(key);
|
|
134
|
+
return { status: "released", noProgressFailures: ownedClaim.noProgressFailures };
|
|
135
|
+
}
|
|
136
|
+
persist(ownedClaim, phases.onState);
|
|
137
|
+
return { status: "released", noProgressFailures: ownedClaim.noProgressFailures };
|
|
138
|
+
};
|
|
139
|
+
const attempt = (async (): Promise<CompletionAttempt> => {
|
|
140
|
+
let progressed = false;
|
|
141
|
+
const failed = (): CompletionAttempt => {
|
|
142
|
+
if (phases.isOwned && !phases.isOwned()) return retireForOwnershipLoss();
|
|
143
|
+
ownedClaim.noProgressFailures = progressed ? 0 : ownedClaim.noProgressFailures + 1;
|
|
144
|
+
if (ownedClaim.noProgressFailures >= Math.max(1, maxNoProgressFailures)) {
|
|
145
|
+
ownedClaim.terminalStatus = "exhausted";
|
|
146
|
+
ownedClaim.completedAt = Date.now();
|
|
147
|
+
persist(ownedClaim, phases.onState);
|
|
148
|
+
return { status: "exhausted", noProgressFailures: ownedClaim.noProgressFailures };
|
|
149
|
+
}
|
|
150
|
+
persist(ownedClaim, phases.onState);
|
|
151
|
+
return { status: "retry", noProgressFailures: ownedClaim.noProgressFailures };
|
|
152
|
+
};
|
|
153
|
+
const runPhase = async (phase: ((value: FrozenCompletionEnvelope) => Promise<boolean> | boolean) | undefined): Promise<boolean | undefined> => {
|
|
154
|
+
if (!phase) return undefined;
|
|
155
|
+
if (phases.isOwned && !phases.isOwned()) return false;
|
|
156
|
+
try { return await phase(cloneEnvelope(ownedClaim.envelope)); } catch { return false; }
|
|
157
|
+
};
|
|
158
|
+
if (!ownedClaim.intercomDelivered && phases.intercom) {
|
|
159
|
+
const delivered = await runPhase(phases.intercom);
|
|
160
|
+
if (!delivered) return failed();
|
|
161
|
+
ownedClaim.intercomDelivered = true;
|
|
162
|
+
progressed = true;
|
|
163
|
+
persist(ownedClaim, phases.onState);
|
|
164
|
+
if (phases.isOwned && !phases.isOwned()) return retireForOwnershipLoss();
|
|
165
|
+
}
|
|
166
|
+
if (!ownedClaim.localDelivered && phases.local) {
|
|
167
|
+
const delivered = await runPhase(phases.local);
|
|
168
|
+
if (!delivered) return failed();
|
|
169
|
+
ownedClaim.localDelivered = true;
|
|
170
|
+
progressed = true;
|
|
171
|
+
persist(ownedClaim, phases.onState);
|
|
172
|
+
if (phases.isOwned && !phases.isOwned()) return retireForOwnershipLoss();
|
|
173
|
+
}
|
|
174
|
+
ownedClaim.noProgressFailures = 0;
|
|
175
|
+
ownedClaim.terminalStatus = "delivered";
|
|
176
|
+
ownedClaim.completedAt = Date.now();
|
|
177
|
+
persist(ownedClaim, phases.onState);
|
|
178
|
+
return { status: "delivered", noProgressFailures: 0 };
|
|
179
|
+
})();
|
|
180
|
+
const flight: CompletionFlight = { promise: attempt };
|
|
181
|
+
ownedClaim.inFlight = flight;
|
|
182
|
+
try {
|
|
183
|
+
return { owner: true, ...await flight.promise };
|
|
184
|
+
} finally {
|
|
185
|
+
// The explicit flight handle is the ownership token; comparing resolved
|
|
186
|
+
// values would let an older attempt clear a newer in-flight claim.
|
|
187
|
+
if (ownedClaim.inFlight === flight) ownedClaim.inFlight = undefined;
|
|
188
|
+
}
|
|
189
|
+
}
|