@bastani/atomic 0.9.5-alpha.8 → 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 +122 -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 +38 -0
- package/dist/builtin/mcp/OAUTH.md +1 -0
- package/dist/builtin/mcp/README.md +10 -6
- 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 +40 -255
- package/dist/builtin/mcp/host-html-template.ts +4 -2
- package/dist/builtin/mcp/index.ts +274 -239
- package/dist/builtin/mcp/init.ts +96 -126
- 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 +52 -0
- 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 +106 -23
- package/dist/builtin/mcp/proxy-modes.ts +3 -3
- package/dist/builtin/mcp/session-cleanup-barrier.ts +43 -0
- package/dist/builtin/mcp/startup-warmup.ts +98 -0
- package/dist/builtin/mcp/state-lease.ts +12 -0
- package/dist/builtin/mcp/tool-result-renderer.ts +3 -3
- package/dist/builtin/mcp/ui-server.ts +8 -8
- package/dist/builtin/mcp/ui-session.ts +9 -18
- package/dist/builtin/subagents/CHANGELOG.md +78 -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 +289 -320
- 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/startup-maintenance.ts +89 -0
- 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 +26 -20
- 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 +177 -233
- 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 +29 -15
- 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 +63 -46
- 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 +55 -12
- 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 +157 -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 +86 -0
- package/dist/builtin/workflows/README.md +5 -5
- package/dist/builtin/workflows/builtin/deep-research-codebase-utils.ts +27 -4
- package/dist/builtin/workflows/builtin/goal-runner.ts +86 -27
- 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/skills/impeccable/SKILL.md +16 -13
- package/dist/builtin/workflows/skills/impeccable/reference/adapt.md +1 -0
- package/dist/builtin/workflows/skills/impeccable/reference/adapt.native.md +58 -0
- package/dist/builtin/workflows/skills/impeccable/reference/android.md +40 -0
- package/dist/builtin/workflows/skills/impeccable/reference/animate.md +2 -0
- package/dist/builtin/workflows/skills/impeccable/reference/audit.md +2 -0
- package/dist/builtin/workflows/skills/impeccable/reference/audit.native.md +139 -0
- package/dist/builtin/workflows/skills/impeccable/reference/bolder.md +69 -62
- package/dist/builtin/workflows/skills/impeccable/reference/critique.md +21 -7
- package/dist/builtin/workflows/skills/impeccable/reference/document.md +1 -1
- package/dist/builtin/workflows/skills/impeccable/reference/hooks.md +92 -0
- package/dist/builtin/workflows/skills/impeccable/reference/init.md +29 -7
- package/dist/builtin/workflows/skills/impeccable/reference/ios.md +45 -0
- package/dist/builtin/workflows/skills/impeccable/reference/layout.md +25 -1
- package/dist/builtin/workflows/skills/impeccable/reference/typeset.md +23 -1
- package/dist/builtin/workflows/skills/impeccable/scripts/context-signals.mjs +2 -1
- package/dist/builtin/workflows/skills/impeccable/scripts/context.mjs +75 -14
- package/dist/builtin/workflows/skills/impeccable/scripts/detector/browser/injected/index.mjs +1 -1
- package/dist/builtin/workflows/skills/impeccable/scripts/detector/cli/main.mjs +31 -0
- package/dist/builtin/workflows/skills/impeccable/scripts/detector/design-system.mjs +64 -0
- package/dist/builtin/workflows/skills/impeccable/scripts/detector/detect-antipatterns-browser.js +118 -11
- package/dist/builtin/workflows/skills/impeccable/scripts/detector/engines/regex/detect-text.mjs +16 -11
- package/dist/builtin/workflows/skills/impeccable/scripts/detector/registry/antipatterns.mjs +66 -0
- package/dist/builtin/workflows/skills/impeccable/scripts/detector/rules/checks.mjs +42 -10
- package/dist/builtin/workflows/skills/impeccable/scripts/detector/shared/fonts.mjs +30 -0
- package/dist/builtin/workflows/skills/impeccable/scripts/detector/shared/page.mjs +4 -6
- package/dist/builtin/workflows/skills/impeccable/scripts/hook-admin.mjs +660 -0
- package/dist/builtin/workflows/skills/impeccable/scripts/hook-before-edit.mjs +516 -0
- package/dist/builtin/workflows/skills/impeccable/scripts/hook-lib.mjs +1764 -0
- package/dist/builtin/workflows/skills/impeccable/scripts/hook.mjs +61 -0
- package/dist/builtin/workflows/skills/impeccable/scripts/lib/impeccable-config.mjs +4 -2
- package/dist/builtin/workflows/skills/impeccable/scripts/lib/is-generated.mjs +2 -2
- package/dist/builtin/workflows/skills/impeccable/scripts/live/svelte-component.mjs +13 -16
- package/dist/builtin/workflows/skills/impeccable/scripts/live-accept.mjs +17 -11
- package/dist/builtin/workflows/skills/impeccable/scripts/live-browser.js +104 -37
- package/dist/builtin/workflows/skills/impeccable/scripts/live-wrap.mjs +9 -0
- package/dist/builtin/workflows/src/durable/backend.ts +12 -0
- package/dist/builtin/workflows/src/durable/dbos-backend.ts +17 -1
- package/dist/builtin/workflows/src/durable/resume-catalog.ts +12 -0
- package/dist/builtin/workflows/src/durable/resume-runtime.ts +5 -2
- package/dist/builtin/workflows/src/durable/stage-primitive.ts +2 -1
- package/dist/builtin/workflows/src/durable/types.ts +16 -0
- package/dist/builtin/workflows/src/engine/primitives/task.ts +3 -1
- package/dist/builtin/workflows/src/engine/run-durable-finalize.ts +1 -2
- package/dist/builtin/workflows/src/engine/run-returned-status.ts +50 -16
- package/dist/builtin/workflows/src/engine/run.ts +20 -19
- package/dist/builtin/workflows/src/engine/runtime.ts +5 -0
- package/dist/builtin/workflows/src/extension/extension-factory.ts +3 -0
- package/dist/builtin/workflows/src/extension/extension-lifecycle.ts +9 -2
- package/dist/builtin/workflows/src/extension/extension-runtime-state.ts +137 -27
- package/dist/builtin/workflows/src/extension/lifecycle-notifications.ts +22 -6
- package/dist/builtin/workflows/src/extension/public-types.ts +1 -1
- package/dist/builtin/workflows/src/extension/workflow-command-completions.ts +13 -1
- package/dist/builtin/workflows/src/extension/workflow-command-registration.ts +19 -4
- package/dist/builtin/workflows/src/extension/workflow-command-surfaces.ts +9 -0
- package/dist/builtin/workflows/src/extension/workflow-prompts.ts +17 -22
- package/dist/builtin/workflows/src/extension/workflow-run-control-command.ts +48 -23
- package/dist/builtin/workflows/src/extension/workflow-schema.ts +15 -2
- package/dist/builtin/workflows/src/extension/workflow-tool-control.ts +20 -8
- package/dist/builtin/workflows/src/extension/workflow-tool.ts +24 -8
- package/dist/builtin/workflows/src/runs/background/status.ts +4 -3
- package/dist/builtin/workflows/src/runs/foreground/executor-direct-helpers.ts +29 -8
- package/dist/builtin/workflows/src/runs/foreground/executor-hil.ts +1 -1
- package/dist/builtin/workflows/src/runs/foreground/executor-stage-factory.ts +3 -2
- package/dist/builtin/workflows/src/runs/shared/model-fallback-candidates.ts +1 -1
- package/dist/builtin/workflows/src/runs/shared/worktree-git.ts +155 -20
- package/dist/builtin/workflows/src/runs/shared/worktree-types.ts +6 -0
- package/dist/builtin/workflows/src/runs/shared/worktree.ts +2 -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/shared/returned-run-status.ts +116 -0
- package/dist/builtin/workflows/src/shared/workflow-failures-decisions.ts +2 -0
- package/dist/builtin/workflows/src/tui/graph-view-render-helpers.ts +21 -3
- package/dist/builtin/workflows/src/tui/graph-view-state.ts +3 -0
- package/dist/builtin/workflows/src/tui/graph-view-types.ts +3 -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/builtin/workflows/src/tui/status-list.ts +22 -15
- package/dist/builtin/workflows/src/tui/workflow-attach-pane.ts +4 -4
- 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-auto-compaction.d.ts +23 -3
- package/dist/core/agent-session-auto-compaction.d.ts.map +1 -1
- package/dist/core/agent-session-auto-compaction.js +129 -17
- package/dist/core/agent-session-auto-compaction.js.map +1 -1
- package/dist/core/agent-session-events.d.ts.map +1 -1
- package/dist/core/agent-session-events.js +9 -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-methods.d.ts +6 -3
- package/dist/core/agent-session-methods.d.ts.map +1 -1
- package/dist/core/agent-session-methods.js.map +1 -1
- package/dist/core/agent-session-prompt.d.ts.map +1 -1
- package/dist/core/agent-session-prompt.js +2 -2
- 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/agent-session.d.ts +4 -2
- package/dist/core/agent-session.d.ts.map +1 -1
- package/dist/core/agent-session.js +4 -2
- package/dist/core/agent-session.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/loader-virtual-modules.d.ts +8 -1
- package/dist/core/extensions/loader-virtual-modules.d.ts.map +1 -1
- package/dist/core/extensions/loader-virtual-modules.js +2 -1
- package/dist/core/extensions/loader-virtual-modules.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/footer-data-provider.d.ts +6 -0
- package/dist/core/footer-data-provider.d.ts.map +1 -1
- package/dist/core/footer-data-provider.js +72 -29
- package/dist/core/footer-data-provider.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/openai-responses-payload-sanitizer.d.ts +1 -0
- package/dist/core/openai-responses-payload-sanitizer.d.ts.map +1 -1
- package/dist/core/openai-responses-payload-sanitizer.js +24 -9
- package/dist/core/openai-responses-payload-sanitizer.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/slash-commands.d.ts +2 -0
- package/dist/core/slash-commands.d.ts.map +1 -1
- package/dist/core/slash-commands.js +141 -0
- package/dist/core/slash-commands.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/index.d.ts +1 -0
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +1 -0
- package/dist/index.js.map +1 -1
- package/dist/main-deferred-startup.d.ts.map +1 -1
- package/dist/main-deferred-startup.js +2 -2
- package/dist/main-deferred-startup.js.map +1 -1
- package/dist/main-early-input.d.ts.map +1 -1
- package/dist/main-early-input.js +7 -0
- package/dist/main-early-input.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/main.d.ts.map +1 -1
- package/dist/main.js +1 -1
- package/dist/main.js.map +1 -1
- package/dist/modes/interactive/components/chat-session-host-actions.d.ts.map +1 -1
- package/dist/modes/interactive/components/chat-session-host-actions.js +0 -1
- package/dist/modes/interactive/components/chat-session-host-actions.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 +3 -1
- package/dist/modes/interactive/interactive-agent-events.js.map +1 -1
- package/dist/modes/interactive/interactive-autocomplete.d.ts.map +1 -1
- package/dist/modes/interactive/interactive-autocomplete.js +21 -9
- package/dist/modes/interactive/interactive-autocomplete.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 +43 -30
- package/dist/modes/interactive/interactive-deferred-startup.js.map +1 -1
- package/dist/modes/interactive/interactive-hotkeys-debug.d.ts.map +1 -1
- package/dist/modes/interactive/interactive-hotkeys-debug.js +1 -0
- package/dist/modes/interactive/interactive-hotkeys-debug.js.map +1 -1
- package/dist/modes/interactive/interactive-input-handling.d.ts.map +1 -1
- package/dist/modes/interactive/interactive-input-handling.js +41 -6
- package/dist/modes/interactive/interactive-input-handling.js.map +1 -1
- package/dist/modes/interactive/interactive-mode-base.d.ts +3 -0
- package/dist/modes/interactive/interactive-mode-base.d.ts.map +1 -1
- package/dist/modes/interactive/interactive-mode-base.js +3 -0
- package/dist/modes/interactive/interactive-mode-base.js.map +1 -1
- package/dist/modes/interactive/interactive-mode-deps.d.ts +2 -2
- package/dist/modes/interactive/interactive-mode-deps.d.ts.map +1 -1
- package/dist/modes/interactive/interactive-mode-deps.js +2 -2
- package/dist/modes/interactive/interactive-mode-deps.js.map +1 -1
- package/dist/modes/interactive/interactive-mode-surface.d.ts +2 -2
- package/dist/modes/interactive/interactive-mode-surface.d.ts.map +1 -1
- package/dist/modes/interactive/interactive-mode-surface.js.map +1 -1
- package/dist/modes/interactive/interactive-model-routing.d.ts.map +1 -1
- package/dist/modes/interactive/interactive-model-routing.js +11 -4
- package/dist/modes/interactive/interactive-model-routing.js.map +1 -1
- package/dist/modes/interactive/interactive-process-lifecycle.d.ts.map +1 -1
- package/dist/modes/interactive/interactive-process-lifecycle.js +0 -3
- package/dist/modes/interactive/interactive-process-lifecycle.js.map +1 -1
- package/dist/modes/interactive/interactive-render-chat.d.ts.map +1 -1
- package/dist/modes/interactive/interactive-render-chat.js +15 -1
- package/dist/modes/interactive/interactive-render-chat.js.map +1 -1
- package/dist/modes/interactive/interactive-session-routing.d.ts.map +1 -1
- package/dist/modes/interactive/interactive-session-routing.js +5 -1
- package/dist/modes/interactive/interactive-session-routing.js.map +1 -1
- package/dist/modes/interactive/interactive-startup.d.ts.map +1 -1
- package/dist/modes/interactive/interactive-startup.js +20 -21
- package/dist/modes/interactive/interactive-startup.js.map +1 -1
- package/dist/modes/interactive/theme/global-theme.d.ts.map +1 -1
- package/dist/modes/interactive/theme/global-theme.js +26 -2
- package/dist/modes/interactive/theme/global-theme.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/dist/utils/fs-watch.d.ts +24 -1
- package/dist/utils/fs-watch.d.ts.map +1 -1
- package/dist/utils/fs-watch.js +60 -5
- package/dist/utils/fs-watch.js.map +1 -1
- package/docs/changelog.mdx +19 -0
- package/docs/compaction.md +60 -49
- package/docs/custom-provider.md +18 -5
- package/docs/development.md +4 -0
- package/docs/extensions.md +11 -2
- package/docs/json.md +1 -1
- package/docs/models.md +69 -10
- package/docs/providers.md +1 -1
- package/docs/quickstart.md +12 -8
- package/docs/rpc.md +2 -2
- package/docs/sdk.md +1 -1
- package/docs/settings.md +4 -4
- package/docs/subagents.md +40 -5
- package/docs/tools.md +1 -1
- package/docs/usage.md +4 -2
- package/docs/windows.md +4 -0
- package/docs/workflows.md +33 -48
- 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
|
@@ -5,11 +5,11 @@ import type { Api, Message, Model } from "@earendil-works/pi-ai/compat";
|
|
|
5
5
|
*
|
|
6
6
|
* Anthropic requires thinking/redacted_thinking blocks from replayed assistant
|
|
7
7
|
* messages to remain byte-for-byte identical to the original response. The
|
|
8
|
-
* upstream pi-ai Anthropic converter
|
|
9
|
-
*
|
|
10
|
-
*
|
|
11
|
-
*
|
|
12
|
-
* unchanged.
|
|
8
|
+
* upstream pi-ai Anthropic converter can sanitize thinking text and drop signed
|
|
9
|
+
* empty thinking. convertToLlm normalizes raw redacted_thinking blocks in its
|
|
10
|
+
* transient, non-mutating LLM-compatible messages before this hook, then this guard
|
|
11
|
+
* restores exact same-model payloads while leaving non-Anthropic and cross-model
|
|
12
|
+
* payloads unchanged.
|
|
13
13
|
*/
|
|
14
14
|
export declare function restoreAnthropicReplayThinkingBlocks(payload: unknown, sourceMessages: readonly Message[], model: Model<Api>): unknown;
|
|
15
15
|
//# sourceMappingURL=anthropic-thinking-guard.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"anthropic-thinking-guard.d.ts","sourceRoot":"","sources":["../../src/core/anthropic-thinking-guard.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,GAAG,EAAoB,OAAO,EAAE,KAAK,EAAE,MAAM,8BAA8B,CAAC;AAuL1F;;;;;;;;;;;GAWG;AACH,wBAAgB,oCAAoC,CAAC,OAAO,EAAE,OAAO,EAAE,cAAc,EAAE,SAAS,OAAO,EAAE,EAAE,KAAK,EAAE,KAAK,CAAC,GAAG,CAAC,GAAG,OAAO,CAyCrI","sourcesContent":["import type { Api, AssistantMessage, Message, Model } from \"@earendil-works/pi-ai/compat\";\n\ntype JsonObject = Record<string, unknown>;\n\ntype AnthropicContentBlock = JsonObject & { type: string };\n\ntype ReplayThinkingBlock =\n\t| { type: \"thinking\"; thinking: string; signature: string }\n\t| { type: \"redacted_thinking\"; data: string };\n\nfunction isObject(value: unknown): value is JsonObject {\n\treturn value !== null && typeof value === \"object\" && !Array.isArray(value);\n}\n\nfunction isAnthropicContentBlock(value: unknown): value is AnthropicContentBlock {\n\treturn isObject(value) && typeof value.type === \"string\";\n}\n\nfunction isThinkingLikeAnthropicBlock(value: unknown): boolean {\n\tif (!isAnthropicContentBlock(value)) return false;\n\treturn value.type === \"thinking\" || value.type === \"redacted_thinking\";\n}\n\nfunction isSameModelAssistant(message: AssistantMessage, model: Model<Api>): boolean {\n\treturn message.provider === model.provider && message.api === model.api && message.model === model.id;\n}\n\nfunction readReplayThinkingBlock(block: unknown): ReplayThinkingBlock | undefined {\n\tif (!isObject(block) || typeof block.type !== \"string\") return undefined;\n\n\tif (block.type === \"redacted_thinking\") {\n\t\treturn typeof block.data === \"string\" ? { type: \"redacted_thinking\", data: block.data } : undefined;\n\t}\n\n\tif (block.type !== \"thinking\") return undefined;\n\n\tif (block.redacted === true) {\n\t\treturn typeof block.thinkingSignature === \"string\"\n\t\t\t? { type: \"redacted_thinking\", data: block.thinkingSignature }\n\t\t\t: undefined;\n\t}\n\n\treturn typeof block.thinking === \"string\" && typeof block.thinkingSignature === \"string\"\n\t\t? { type: \"thinking\", thinking: block.thinking, signature: block.thinkingSignature }\n\t\t: undefined;\n}\n\nfunction hasReplayThinkingBlock(message: AssistantMessage): boolean {\n\treturn message.content.some((block) => readReplayThinkingBlock(block) !== undefined);\n}\n\nfunction legacyProviderWouldEmitAssistantBlock(block: unknown, allowEmptySignature: boolean): boolean {\n\tif (!isObject(block) || typeof block.type !== \"string\") return false;\n\n\tif (block.type === \"text\") {\n\t\treturn typeof block.text === \"string\" && block.text.trim().length > 0;\n\t}\n\n\tif (block.type === \"toolCall\") {\n\t\treturn true;\n\t}\n\n\tif (block.type !== \"thinking\") {\n\t\treturn false;\n\t}\n\n\tif (block.redacted === true) {\n\t\treturn true;\n\t}\n\n\tif (typeof block.thinking !== \"string\") return false;\n\tif (block.thinking.trim().length === 0) return false;\n\n\tconst signature = typeof block.thinkingSignature === \"string\" ? block.thinkingSignature : undefined;\n\tif (signature !== undefined && signature.trim().length > 0) return true;\n\treturn allowEmptySignature;\n}\n\nfunction legacyProviderWouldEmitAssistant(message: AssistantMessage, model: Model<Api>, allowEmptySignature: boolean): boolean {\n\tif (message.stopReason === \"error\" || message.stopReason === \"aborted\") return false;\n\n\t// This mirrors the relevant same-model branch in @earendil-works/pi-ai's\n\t// transformMessages() + Anthropic convertMessages() pipeline closely enough\n\t// to keep assistant ordinal mapping aligned with the provider payload.\n\tif (isSameModelAssistant(message, model)) {\n\t\treturn message.content.some((block) => legacyProviderWouldEmitAssistantBlock(block, allowEmptySignature));\n\t}\n\n\treturn message.content.some((block) => {\n\t\tif (!isObject(block) || typeof block.type !== \"string\") return false;\n\t\tif (block.type === \"text\") return typeof block.text === \"string\" && block.text.trim().length > 0;\n\t\tif (block.type === \"toolCall\") return true;\n\t\tif (block.type !== \"thinking\") return false;\n\t\tif (block.redacted === true) return false;\n\t\treturn typeof block.thinking === \"string\" && block.thinking.trim().length > 0;\n\t});\n}\n\nfunction fallbackTextBlock(block: JsonObject): AnthropicContentBlock | undefined {\n\treturn typeof block.text === \"string\" && block.text.trim().length > 0\n\t\t? { type: \"text\", text: block.text }\n\t\t: undefined;\n}\n\nfunction fallbackToolUseBlock(block: JsonObject): AnthropicContentBlock | undefined {\n\tif (typeof block.id !== \"string\" || typeof block.name !== \"string\") return undefined;\n\treturn { type: \"tool_use\", id: block.id, name: block.name, input: block.arguments ?? {} };\n}\n\nfunction takeProviderBlock(\n\tproviderBlocks: readonly AnthropicContentBlock[],\n\tproviderIndex: number,\n\texpectedType: string,\n): { block: AnthropicContentBlock | undefined; nextProviderIndex: number } {\n\tconst providerBlock = providerBlocks[providerIndex];\n\tif (providerBlock?.type === expectedType) {\n\t\treturn { block: providerBlock, nextProviderIndex: providerIndex + 1 };\n\t}\n\treturn { block: undefined, nextProviderIndex: providerIndex };\n}\n\nfunction repairAssistantContent(\n\toriginalMessage: AssistantMessage,\n\tproviderBlocks: readonly AnthropicContentBlock[],\n): AnthropicContentBlock[] {\n\tconst repaired: AnthropicContentBlock[] = [];\n\tlet providerIndex = 0;\n\n\tfor (const originalBlock of originalMessage.content) {\n\t\tconst replayBlock = readReplayThinkingBlock(originalBlock);\n\t\tif (replayBlock) {\n\t\t\tif (isThinkingLikeAnthropicBlock(providerBlocks[providerIndex])) {\n\t\t\t\tproviderIndex += 1;\n\t\t\t}\n\t\t\trepaired.push({ ...replayBlock });\n\t\t\tcontinue;\n\t\t}\n\n\t\tif (!isObject(originalBlock) || typeof originalBlock.type !== \"string\") continue;\n\n\t\tif (originalBlock.type === \"text\") {\n\t\t\tconst providerText = takeProviderBlock(providerBlocks, providerIndex, \"text\");\n\t\t\tif (providerText.block) {\n\t\t\t\trepaired.push(providerText.block);\n\t\t\t\tproviderIndex = providerText.nextProviderIndex;\n\t\t\t\tcontinue;\n\t\t\t}\n\t\t\tconst fallback = fallbackTextBlock(originalBlock);\n\t\t\tif (fallback) repaired.push(fallback);\n\t\t\tcontinue;\n\t\t}\n\n\t\tif (originalBlock.type === \"toolCall\") {\n\t\t\tconst providerToolUse = takeProviderBlock(providerBlocks, providerIndex, \"tool_use\");\n\t\t\tif (providerToolUse.block) {\n\t\t\t\trepaired.push(providerToolUse.block);\n\t\t\t\tproviderIndex = providerToolUse.nextProviderIndex;\n\t\t\t\tcontinue;\n\t\t\t}\n\t\t\tconst fallback = fallbackToolUseBlock(originalBlock);\n\t\t\tif (fallback) repaired.push(fallback);\n\t\t}\n\t}\n\n\tfor (; providerIndex < providerBlocks.length; providerIndex += 1) {\n\t\trepaired.push(providerBlocks[providerIndex]);\n\t}\n\n\treturn repaired;\n}\n\nfunction getAnthropicMessages(payload: unknown): unknown[] | undefined {\n\tif (!isObject(payload)) return undefined;\n\treturn Array.isArray(payload.messages) ? payload.messages : undefined;\n}\n\nfunction getAnthropicAssistantContent(message: unknown): AnthropicContentBlock[] | undefined {\n\tif (!isObject(message) || message.role !== \"assistant\") return undefined;\n\tif (!Array.isArray(message.content)) return undefined;\n\tconst content = message.content.filter(isAnthropicContentBlock);\n\treturn content.length === message.content.length ? content : undefined;\n}\n\n/**\n * Restore same-model Anthropic replay thinking blocks after provider payload\n * construction and extension payload hooks.\n *\n * Anthropic requires thinking/redacted_thinking blocks from replayed assistant\n * messages to remain byte-for-byte identical to the original response. The\n * upstream pi-ai Anthropic converter currently still sanitizes thinking text,\n * drops signed empty thinking, and does not understand raw redacted_thinking\n * blocks. This guard repairs the already-built Anthropic payload from the\n * pre-provider LLM messages while leaving non-Anthropic and cross-model payloads\n * unchanged.\n */\nexport function restoreAnthropicReplayThinkingBlocks(payload: unknown, sourceMessages: readonly Message[], model: Model<Api>): unknown {\n\tif (model.api !== \"anthropic-messages\") return payload;\n\n\tconst payloadMessages = getAnthropicMessages(payload);\n\tif (!payloadMessages) return payload;\n\n\tconst assistantPayloads = payloadMessages\n\t\t.map((message, index) => ({ message, index, content: getAnthropicAssistantContent(message) }))\n\t\t.filter(\n\t\t\t(entry): entry is { message: JsonObject; index: number; content: AnthropicContentBlock[] } =>\n\t\t\t\tentry.content !== undefined && isObject(entry.message),\n\t\t);\n\n\tif (assistantPayloads.length === 0) return payload;\n\n\tconst allowEmptySignature = isObject(model.compat) && model.compat.allowEmptySignature === true;\n\tlet assistantPayloadOrdinal = 0;\n\tlet nextPayloadMessages: unknown[] | undefined;\n\n\tfor (const sourceMessage of sourceMessages) {\n\t\tif (sourceMessage.role !== \"assistant\") continue;\n\t\tif (!legacyProviderWouldEmitAssistant(sourceMessage, model, allowEmptySignature)) continue;\n\n\t\tconst payloadAssistant = assistantPayloads[assistantPayloadOrdinal];\n\t\tassistantPayloadOrdinal += 1;\n\t\tif (!payloadAssistant) break;\n\n\t\tif (!isSameModelAssistant(sourceMessage, model) || !hasReplayThinkingBlock(sourceMessage)) continue;\n\n\t\tconst repairedContent = repairAssistantContent(sourceMessage, payloadAssistant.content);\n\t\tif (JSON.stringify(repairedContent) === JSON.stringify(payloadAssistant.content)) continue;\n\n\t\tnextPayloadMessages ??= [...payloadMessages];\n\t\tnextPayloadMessages[payloadAssistant.index] = {\n\t\t\t...payloadAssistant.message,\n\t\t\tcontent: repairedContent,\n\t\t};\n\t}\n\n\tif (!nextPayloadMessages || !isObject(payload)) return payload;\n\treturn { ...payload, messages: nextPayloadMessages };\n}\n"]}
|
|
1
|
+
{"version":3,"file":"anthropic-thinking-guard.d.ts","sourceRoot":"","sources":["../../src/core/anthropic-thinking-guard.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,GAAG,EAAoB,OAAO,EAAE,KAAK,EAAE,MAAM,8BAA8B,CAAC;AA+L1F;;;;;;;;;;;GAWG;AACH,wBAAgB,oCAAoC,CAAC,OAAO,EAAE,OAAO,EAAE,cAAc,EAAE,SAAS,OAAO,EAAE,EAAE,KAAK,EAAE,KAAK,CAAC,GAAG,CAAC,GAAG,OAAO,CA6CrI","sourcesContent":["import type { Api, AssistantMessage, Message, Model } from \"@earendil-works/pi-ai/compat\";\n\ntype JsonObject = Record<string, unknown>;\n\ntype AnthropicContentBlock = JsonObject & { type: string };\n\ntype ReplayThinkingBlock =\n\t| { type: \"thinking\"; thinking: string; signature: string }\n\t| { type: \"redacted_thinking\"; data: string };\n\nfunction isObject(value: unknown): value is JsonObject {\n\treturn value !== null && typeof value === \"object\" && !Array.isArray(value);\n}\n\nfunction isAnthropicContentBlock(value: unknown): value is AnthropicContentBlock {\n\treturn isObject(value) && typeof value.type === \"string\";\n}\n\nfunction isThinkingLikeAnthropicBlock(value: unknown): boolean {\n\tif (!isAnthropicContentBlock(value)) return false;\n\treturn value.type === \"thinking\" || value.type === \"redacted_thinking\";\n}\n\nfunction isSameModelAssistant(message: AssistantMessage, model: Model<Api>): boolean {\n\treturn message.provider === model.provider && message.api === model.api && message.model === model.id;\n}\n\nfunction readReplayThinkingBlock(block: unknown, allowEmptySignature = false): ReplayThinkingBlock | undefined {\n\tif (!isObject(block) || typeof block.type !== \"string\") return undefined;\n\n\tif (block.type === \"redacted_thinking\") {\n\t\treturn typeof block.data === \"string\" ? { type: \"redacted_thinking\", data: block.data } : undefined;\n\t}\n\n\tif (block.type !== \"thinking\") return undefined;\n\n\tif (block.redacted === true) {\n\t\treturn typeof block.thinkingSignature === \"string\"\n\t\t\t? { type: \"redacted_thinking\", data: block.thinkingSignature }\n\t\t\t: undefined;\n\t}\n\n\tif (typeof block.thinking !== \"string\" || typeof block.thinkingSignature !== \"string\") return undefined;\n\tif (!allowEmptySignature && block.thinkingSignature.trim().length === 0) return undefined;\n\treturn { type: \"thinking\", thinking: block.thinking, signature: block.thinkingSignature };\n}\n\nfunction hasReplayThinkingBlock(message: AssistantMessage, allowEmptySignature: boolean): boolean {\n\treturn message.content.some((block) => readReplayThinkingBlock(block, allowEmptySignature) !== undefined);\n}\n\nfunction legacyProviderWouldEmitAssistantBlock(block: unknown): boolean {\n\tif (!isObject(block) || typeof block.type !== \"string\") return false;\n\n\tif (block.type === \"text\") {\n\t\treturn typeof block.text === \"string\" && block.text.trim().length > 0;\n\t}\n\n\tif (block.type === \"toolCall\") {\n\t\treturn true;\n\t}\n\n\tif (block.type !== \"thinking\") {\n\t\treturn false;\n\t}\n\n\tif (block.redacted === true) {\n\t\treturn true;\n\t}\n\n\tif (typeof block.thinking !== \"string\") return false;\n\tconst signature = typeof block.thinkingSignature === \"string\" ? block.thinkingSignature : undefined;\n\treturn block.thinking.trim().length > 0 || (signature !== undefined && signature.trim().length > 0);\n}\n\nfunction legacyProviderWouldEmitAssistant(message: AssistantMessage, model: Model<Api>): boolean {\n\tif (message.stopReason === \"error\" || message.stopReason === \"aborted\") return false;\n\n\t// This mirrors the relevant same-model branch in @earendil-works/pi-ai's\n\t// transformMessages() + Anthropic convertMessages() pipeline closely enough\n\t// to keep assistant ordinal mapping aligned with the provider payload.\n\tif (isSameModelAssistant(message, model)) {\n\t\treturn message.content.some((block) => legacyProviderWouldEmitAssistantBlock(block));\n\t}\n\n\treturn message.content.some((block) => {\n\t\tif (!isObject(block) || typeof block.type !== \"string\") return false;\n\t\tif (block.type === \"text\") return typeof block.text === \"string\" && block.text.trim().length > 0;\n\t\tif (block.type === \"toolCall\") return true;\n\t\tif (block.type !== \"thinking\") return false;\n\t\tif (block.redacted === true) return false;\n\t\treturn typeof block.thinking === \"string\" && block.thinking.trim().length > 0;\n\t});\n}\n\nfunction fallbackTextBlock(block: JsonObject): AnthropicContentBlock | undefined {\n\treturn typeof block.text === \"string\" && block.text.trim().length > 0\n\t\t? { type: \"text\", text: block.text }\n\t\t: undefined;\n}\n\nfunction fallbackToolUseBlock(block: JsonObject): AnthropicContentBlock | undefined {\n\tif (typeof block.id !== \"string\" || typeof block.name !== \"string\") return undefined;\n\treturn { type: \"tool_use\", id: block.id, name: block.name, input: block.arguments ?? {} };\n}\n\nfunction takeProviderBlock(\n\tproviderBlocks: readonly AnthropicContentBlock[],\n\tproviderIndex: number,\n\texpectedType: string,\n): { block: AnthropicContentBlock | undefined; nextProviderIndex: number } {\n\tconst providerBlock = providerBlocks[providerIndex];\n\tif (providerBlock?.type === expectedType) {\n\t\treturn { block: providerBlock, nextProviderIndex: providerIndex + 1 };\n\t}\n\treturn { block: undefined, nextProviderIndex: providerIndex };\n}\n\nfunction nonThinkingBlocksAlign(message: AssistantMessage, providerBlocks: readonly AnthropicContentBlock[]): boolean {\n\tconst sourceTypes = message.content.flatMap((block) => {\n\t\tif (!isObject(block) || typeof block.type !== \"string\") return [];\n\t\tif (block.type === \"text\") return typeof block.text === \"string\" && block.text.trim().length > 0 ? [\"text\"] : [];\n\t\treturn block.type === \"toolCall\" ? [\"tool_use\"] : [];\n\t});\n\tconst providerTypes = providerBlocks.filter((block) => !isThinkingLikeAnthropicBlock(block)).map((block) => block.type);\n\treturn sourceTypes.length === providerTypes.length && sourceTypes.every((type, index) => type === providerTypes[index]);\n}\n\nfunction repairAssistantContent(\n\toriginalMessage: AssistantMessage,\n\tproviderBlocks: readonly AnthropicContentBlock[],\n\tallowEmptySignature: boolean,\n): AnthropicContentBlock[] {\n\tconst repaired: AnthropicContentBlock[] = [];\n\tlet providerIndex = 0;\n\n\tfor (const originalBlock of originalMessage.content) {\n\t\tconst replayBlock = readReplayThinkingBlock(originalBlock, allowEmptySignature);\n\t\tif (replayBlock) {\n\t\t\tif (isThinkingLikeAnthropicBlock(providerBlocks[providerIndex])) {\n\t\t\t\tproviderIndex += 1;\n\t\t\t}\n\t\t\trepaired.push({ ...replayBlock });\n\t\t\tcontinue;\n\t\t}\n\n\t\tif (!isObject(originalBlock) || typeof originalBlock.type !== \"string\") continue;\n\n\t\tif (originalBlock.type === \"text\") {\n\t\t\tconst providerText = takeProviderBlock(providerBlocks, providerIndex, \"text\");\n\t\t\tif (providerText.block) {\n\t\t\t\trepaired.push(providerText.block);\n\t\t\t\tproviderIndex = providerText.nextProviderIndex;\n\t\t\t\tcontinue;\n\t\t\t}\n\t\t\tconst fallback = fallbackTextBlock(originalBlock);\n\t\t\tif (fallback) repaired.push(fallback);\n\t\t\tcontinue;\n\t\t}\n\n\t\tif (originalBlock.type === \"toolCall\") {\n\t\t\tconst providerToolUse = takeProviderBlock(providerBlocks, providerIndex, \"tool_use\");\n\t\t\tif (providerToolUse.block) {\n\t\t\t\trepaired.push(providerToolUse.block);\n\t\t\t\tproviderIndex = providerToolUse.nextProviderIndex;\n\t\t\t\tcontinue;\n\t\t\t}\n\t\t\tconst fallback = fallbackToolUseBlock(originalBlock);\n\t\t\tif (fallback) repaired.push(fallback);\n\t\t}\n\t}\n\n\tfor (; providerIndex < providerBlocks.length; providerIndex += 1) {\n\t\trepaired.push(providerBlocks[providerIndex]);\n\t}\n\n\treturn repaired;\n}\n\nfunction getAnthropicMessages(payload: unknown): unknown[] | undefined {\n\tif (!isObject(payload)) return undefined;\n\treturn Array.isArray(payload.messages) ? payload.messages : undefined;\n}\n\nfunction getAnthropicAssistantContent(message: unknown): AnthropicContentBlock[] | undefined {\n\tif (!isObject(message) || message.role !== \"assistant\") return undefined;\n\tif (!Array.isArray(message.content)) return undefined;\n\tconst content = message.content.filter(isAnthropicContentBlock);\n\treturn content.length === message.content.length ? content : undefined;\n}\n\n/**\n * Restore same-model Anthropic replay thinking blocks after provider payload\n * construction and extension payload hooks.\n *\n * Anthropic requires thinking/redacted_thinking blocks from replayed assistant\n * messages to remain byte-for-byte identical to the original response. The\n * upstream pi-ai Anthropic converter can sanitize thinking text and drop signed\n * empty thinking. convertToLlm normalizes raw redacted_thinking blocks in its\n * transient, non-mutating LLM-compatible messages before this hook, then this guard\n * restores exact same-model payloads while leaving non-Anthropic and cross-model\n * payloads unchanged.\n */\nexport function restoreAnthropicReplayThinkingBlocks(payload: unknown, sourceMessages: readonly Message[], model: Model<Api>): unknown {\n\tif (model.api !== \"anthropic-messages\") return payload;\n\n\tconst payloadMessages = getAnthropicMessages(payload);\n\tif (!payloadMessages) return payload;\n\n\tconst assistantPayloads = payloadMessages\n\t\t.map((message, index) => ({ message, index, content: getAnthropicAssistantContent(message) }))\n\t\t.filter(\n\t\t\t(entry): entry is { message: JsonObject; index: number; content: AnthropicContentBlock[] } =>\n\t\t\t\tentry.content !== undefined && isObject(entry.message),\n\t\t);\n\n\tif (assistantPayloads.length === 0) return payload;\n\n\tconst emittingSourceAssistants = sourceMessages.filter(\n\t\t(message): message is AssistantMessage => message.role === \"assistant\" && legacyProviderWouldEmitAssistant(message, model),\n\t);\n\t// Fail closed if pi-ai's converter emission behavior drifts from the model above;\n\t// ordinal restoration must never splice thinking into a different assistant.\n\tif (emittingSourceAssistants.length !== assistantPayloads.length) return payload;\n\n\tconst allowEmptySignature = isObject(model.compat) && model.compat.allowEmptySignature === true;\n\tlet nextPayloadMessages: unknown[] | undefined;\n\n\tfor (const [assistantPayloadOrdinal, sourceMessage] of emittingSourceAssistants.entries()) {\n\t\tconst payloadAssistant = assistantPayloads[assistantPayloadOrdinal];\n\n\t\tif (!isSameModelAssistant(sourceMessage, model) || !hasReplayThinkingBlock(sourceMessage, allowEmptySignature)) continue;\n\t\t// A second fail-closed guard verifies the non-thinking shape before replacing\n\t\t// signed blocks, protecting against equal-count ordinal misalignment.\n\t\tif (!nonThinkingBlocksAlign(sourceMessage, payloadAssistant.content)) continue;\n\n\t\tconst repairedContent = repairAssistantContent(sourceMessage, payloadAssistant.content, allowEmptySignature);\n\t\tif (JSON.stringify(repairedContent) === JSON.stringify(payloadAssistant.content)) continue;\n\n\t\tnextPayloadMessages ??= [...payloadMessages];\n\t\tnextPayloadMessages[payloadAssistant.index] = {\n\t\t\t...payloadAssistant.message,\n\t\t\tcontent: repairedContent,\n\t\t};\n\t}\n\n\tif (!nextPayloadMessages || !isObject(payload)) return payload;\n\treturn { ...payload, messages: nextPayloadMessages };\n}\n"]}
|
|
@@ -12,7 +12,7 @@ function isThinkingLikeAnthropicBlock(value) {
|
|
|
12
12
|
function isSameModelAssistant(message, model) {
|
|
13
13
|
return message.provider === model.provider && message.api === model.api && message.model === model.id;
|
|
14
14
|
}
|
|
15
|
-
function readReplayThinkingBlock(block) {
|
|
15
|
+
function readReplayThinkingBlock(block, allowEmptySignature = false) {
|
|
16
16
|
if (!isObject(block) || typeof block.type !== "string")
|
|
17
17
|
return undefined;
|
|
18
18
|
if (block.type === "redacted_thinking") {
|
|
@@ -25,14 +25,16 @@ function readReplayThinkingBlock(block) {
|
|
|
25
25
|
? { type: "redacted_thinking", data: block.thinkingSignature }
|
|
26
26
|
: undefined;
|
|
27
27
|
}
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
28
|
+
if (typeof block.thinking !== "string" || typeof block.thinkingSignature !== "string")
|
|
29
|
+
return undefined;
|
|
30
|
+
if (!allowEmptySignature && block.thinkingSignature.trim().length === 0)
|
|
31
|
+
return undefined;
|
|
32
|
+
return { type: "thinking", thinking: block.thinking, signature: block.thinkingSignature };
|
|
31
33
|
}
|
|
32
|
-
function hasReplayThinkingBlock(message) {
|
|
33
|
-
return message.content.some((block) => readReplayThinkingBlock(block) !== undefined);
|
|
34
|
+
function hasReplayThinkingBlock(message, allowEmptySignature) {
|
|
35
|
+
return message.content.some((block) => readReplayThinkingBlock(block, allowEmptySignature) !== undefined);
|
|
34
36
|
}
|
|
35
|
-
function legacyProviderWouldEmitAssistantBlock(block
|
|
37
|
+
function legacyProviderWouldEmitAssistantBlock(block) {
|
|
36
38
|
if (!isObject(block) || typeof block.type !== "string")
|
|
37
39
|
return false;
|
|
38
40
|
if (block.type === "text") {
|
|
@@ -49,21 +51,17 @@ function legacyProviderWouldEmitAssistantBlock(block, allowEmptySignature) {
|
|
|
49
51
|
}
|
|
50
52
|
if (typeof block.thinking !== "string")
|
|
51
53
|
return false;
|
|
52
|
-
if (block.thinking.trim().length === 0)
|
|
53
|
-
return false;
|
|
54
54
|
const signature = typeof block.thinkingSignature === "string" ? block.thinkingSignature : undefined;
|
|
55
|
-
|
|
56
|
-
return true;
|
|
57
|
-
return allowEmptySignature;
|
|
55
|
+
return block.thinking.trim().length > 0 || (signature !== undefined && signature.trim().length > 0);
|
|
58
56
|
}
|
|
59
|
-
function legacyProviderWouldEmitAssistant(message, model
|
|
57
|
+
function legacyProviderWouldEmitAssistant(message, model) {
|
|
60
58
|
if (message.stopReason === "error" || message.stopReason === "aborted")
|
|
61
59
|
return false;
|
|
62
60
|
// This mirrors the relevant same-model branch in @earendil-works/pi-ai's
|
|
63
61
|
// transformMessages() + Anthropic convertMessages() pipeline closely enough
|
|
64
62
|
// to keep assistant ordinal mapping aligned with the provider payload.
|
|
65
63
|
if (isSameModelAssistant(message, model)) {
|
|
66
|
-
return message.content.some((block) => legacyProviderWouldEmitAssistantBlock(block
|
|
64
|
+
return message.content.some((block) => legacyProviderWouldEmitAssistantBlock(block));
|
|
67
65
|
}
|
|
68
66
|
return message.content.some((block) => {
|
|
69
67
|
if (!isObject(block) || typeof block.type !== "string")
|
|
@@ -96,11 +94,22 @@ function takeProviderBlock(providerBlocks, providerIndex, expectedType) {
|
|
|
96
94
|
}
|
|
97
95
|
return { block: undefined, nextProviderIndex: providerIndex };
|
|
98
96
|
}
|
|
99
|
-
function
|
|
97
|
+
function nonThinkingBlocksAlign(message, providerBlocks) {
|
|
98
|
+
const sourceTypes = message.content.flatMap((block) => {
|
|
99
|
+
if (!isObject(block) || typeof block.type !== "string")
|
|
100
|
+
return [];
|
|
101
|
+
if (block.type === "text")
|
|
102
|
+
return typeof block.text === "string" && block.text.trim().length > 0 ? ["text"] : [];
|
|
103
|
+
return block.type === "toolCall" ? ["tool_use"] : [];
|
|
104
|
+
});
|
|
105
|
+
const providerTypes = providerBlocks.filter((block) => !isThinkingLikeAnthropicBlock(block)).map((block) => block.type);
|
|
106
|
+
return sourceTypes.length === providerTypes.length && sourceTypes.every((type, index) => type === providerTypes[index]);
|
|
107
|
+
}
|
|
108
|
+
function repairAssistantContent(originalMessage, providerBlocks, allowEmptySignature) {
|
|
100
109
|
const repaired = [];
|
|
101
110
|
let providerIndex = 0;
|
|
102
111
|
for (const originalBlock of originalMessage.content) {
|
|
103
|
-
const replayBlock = readReplayThinkingBlock(originalBlock);
|
|
112
|
+
const replayBlock = readReplayThinkingBlock(originalBlock, allowEmptySignature);
|
|
104
113
|
if (replayBlock) {
|
|
105
114
|
if (isThinkingLikeAnthropicBlock(providerBlocks[providerIndex])) {
|
|
106
115
|
providerIndex += 1;
|
|
@@ -158,11 +167,11 @@ function getAnthropicAssistantContent(message) {
|
|
|
158
167
|
*
|
|
159
168
|
* Anthropic requires thinking/redacted_thinking blocks from replayed assistant
|
|
160
169
|
* messages to remain byte-for-byte identical to the original response. The
|
|
161
|
-
* upstream pi-ai Anthropic converter
|
|
162
|
-
*
|
|
163
|
-
*
|
|
164
|
-
*
|
|
165
|
-
* unchanged.
|
|
170
|
+
* upstream pi-ai Anthropic converter can sanitize thinking text and drop signed
|
|
171
|
+
* empty thinking. convertToLlm normalizes raw redacted_thinking blocks in its
|
|
172
|
+
* transient, non-mutating LLM-compatible messages before this hook, then this guard
|
|
173
|
+
* restores exact same-model payloads while leaving non-Anthropic and cross-model
|
|
174
|
+
* payloads unchanged.
|
|
166
175
|
*/
|
|
167
176
|
export function restoreAnthropicReplayThinkingBlocks(payload, sourceMessages, model) {
|
|
168
177
|
if (model.api !== "anthropic-messages")
|
|
@@ -175,21 +184,22 @@ export function restoreAnthropicReplayThinkingBlocks(payload, sourceMessages, mo
|
|
|
175
184
|
.filter((entry) => entry.content !== undefined && isObject(entry.message));
|
|
176
185
|
if (assistantPayloads.length === 0)
|
|
177
186
|
return payload;
|
|
187
|
+
const emittingSourceAssistants = sourceMessages.filter((message) => message.role === "assistant" && legacyProviderWouldEmitAssistant(message, model));
|
|
188
|
+
// Fail closed if pi-ai's converter emission behavior drifts from the model above;
|
|
189
|
+
// ordinal restoration must never splice thinking into a different assistant.
|
|
190
|
+
if (emittingSourceAssistants.length !== assistantPayloads.length)
|
|
191
|
+
return payload;
|
|
178
192
|
const allowEmptySignature = isObject(model.compat) && model.compat.allowEmptySignature === true;
|
|
179
|
-
let assistantPayloadOrdinal = 0;
|
|
180
193
|
let nextPayloadMessages;
|
|
181
|
-
for (const sourceMessage of
|
|
182
|
-
if (sourceMessage.role !== "assistant")
|
|
183
|
-
continue;
|
|
184
|
-
if (!legacyProviderWouldEmitAssistant(sourceMessage, model, allowEmptySignature))
|
|
185
|
-
continue;
|
|
194
|
+
for (const [assistantPayloadOrdinal, sourceMessage] of emittingSourceAssistants.entries()) {
|
|
186
195
|
const payloadAssistant = assistantPayloads[assistantPayloadOrdinal];
|
|
187
|
-
|
|
188
|
-
|
|
189
|
-
|
|
190
|
-
|
|
196
|
+
if (!isSameModelAssistant(sourceMessage, model) || !hasReplayThinkingBlock(sourceMessage, allowEmptySignature))
|
|
197
|
+
continue;
|
|
198
|
+
// A second fail-closed guard verifies the non-thinking shape before replacing
|
|
199
|
+
// signed blocks, protecting against equal-count ordinal misalignment.
|
|
200
|
+
if (!nonThinkingBlocksAlign(sourceMessage, payloadAssistant.content))
|
|
191
201
|
continue;
|
|
192
|
-
const repairedContent = repairAssistantContent(sourceMessage, payloadAssistant.content);
|
|
202
|
+
const repairedContent = repairAssistantContent(sourceMessage, payloadAssistant.content, allowEmptySignature);
|
|
193
203
|
if (JSON.stringify(repairedContent) === JSON.stringify(payloadAssistant.content))
|
|
194
204
|
continue;
|
|
195
205
|
nextPayloadMessages ??= [...payloadMessages];
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"anthropic-thinking-guard.js","sourceRoot":"","sources":["../../src/core/anthropic-thinking-guard.ts"],"names":[],"mappings":"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","sourcesContent":["import type { Api, AssistantMessage, Message, Model } from \"@earendil-works/pi-ai/compat\";\n\ntype JsonObject = Record<string, unknown>;\n\ntype AnthropicContentBlock = JsonObject & { type: string };\n\ntype ReplayThinkingBlock =\n\t| { type: \"thinking\"; thinking: string; signature: string }\n\t| { type: \"redacted_thinking\"; data: string };\n\nfunction isObject(value: unknown): value is JsonObject {\n\treturn value !== null && typeof value === \"object\" && !Array.isArray(value);\n}\n\nfunction isAnthropicContentBlock(value: unknown): value is AnthropicContentBlock {\n\treturn isObject(value) && typeof value.type === \"string\";\n}\n\nfunction isThinkingLikeAnthropicBlock(value: unknown): boolean {\n\tif (!isAnthropicContentBlock(value)) return false;\n\treturn value.type === \"thinking\" || value.type === \"redacted_thinking\";\n}\n\nfunction isSameModelAssistant(message: AssistantMessage, model: Model<Api>): boolean {\n\treturn message.provider === model.provider && message.api === model.api && message.model === model.id;\n}\n\nfunction readReplayThinkingBlock(block: unknown): ReplayThinkingBlock | undefined {\n\tif (!isObject(block) || typeof block.type !== \"string\") return undefined;\n\n\tif (block.type === \"redacted_thinking\") {\n\t\treturn typeof block.data === \"string\" ? { type: \"redacted_thinking\", data: block.data } : undefined;\n\t}\n\n\tif (block.type !== \"thinking\") return undefined;\n\n\tif (block.redacted === true) {\n\t\treturn typeof block.thinkingSignature === \"string\"\n\t\t\t? { type: \"redacted_thinking\", data: block.thinkingSignature }\n\t\t\t: undefined;\n\t}\n\n\treturn typeof block.thinking === \"string\" && typeof block.thinkingSignature === \"string\"\n\t\t? { type: \"thinking\", thinking: block.thinking, signature: block.thinkingSignature }\n\t\t: undefined;\n}\n\nfunction hasReplayThinkingBlock(message: AssistantMessage): boolean {\n\treturn message.content.some((block) => readReplayThinkingBlock(block) !== undefined);\n}\n\nfunction legacyProviderWouldEmitAssistantBlock(block: unknown, allowEmptySignature: boolean): boolean {\n\tif (!isObject(block) || typeof block.type !== \"string\") return false;\n\n\tif (block.type === \"text\") {\n\t\treturn typeof block.text === \"string\" && block.text.trim().length > 0;\n\t}\n\n\tif (block.type === \"toolCall\") {\n\t\treturn true;\n\t}\n\n\tif (block.type !== \"thinking\") {\n\t\treturn false;\n\t}\n\n\tif (block.redacted === true) {\n\t\treturn true;\n\t}\n\n\tif (typeof block.thinking !== \"string\") return false;\n\tif (block.thinking.trim().length === 0) return false;\n\n\tconst signature = typeof block.thinkingSignature === \"string\" ? block.thinkingSignature : undefined;\n\tif (signature !== undefined && signature.trim().length > 0) return true;\n\treturn allowEmptySignature;\n}\n\nfunction legacyProviderWouldEmitAssistant(message: AssistantMessage, model: Model<Api>, allowEmptySignature: boolean): boolean {\n\tif (message.stopReason === \"error\" || message.stopReason === \"aborted\") return false;\n\n\t// This mirrors the relevant same-model branch in @earendil-works/pi-ai's\n\t// transformMessages() + Anthropic convertMessages() pipeline closely enough\n\t// to keep assistant ordinal mapping aligned with the provider payload.\n\tif (isSameModelAssistant(message, model)) {\n\t\treturn message.content.some((block) => legacyProviderWouldEmitAssistantBlock(block, allowEmptySignature));\n\t}\n\n\treturn message.content.some((block) => {\n\t\tif (!isObject(block) || typeof block.type !== \"string\") return false;\n\t\tif (block.type === \"text\") return typeof block.text === \"string\" && block.text.trim().length > 0;\n\t\tif (block.type === \"toolCall\") return true;\n\t\tif (block.type !== \"thinking\") return false;\n\t\tif (block.redacted === true) return false;\n\t\treturn typeof block.thinking === \"string\" && block.thinking.trim().length > 0;\n\t});\n}\n\nfunction fallbackTextBlock(block: JsonObject): AnthropicContentBlock | undefined {\n\treturn typeof block.text === \"string\" && block.text.trim().length > 0\n\t\t? { type: \"text\", text: block.text }\n\t\t: undefined;\n}\n\nfunction fallbackToolUseBlock(block: JsonObject): AnthropicContentBlock | undefined {\n\tif (typeof block.id !== \"string\" || typeof block.name !== \"string\") return undefined;\n\treturn { type: \"tool_use\", id: block.id, name: block.name, input: block.arguments ?? {} };\n}\n\nfunction takeProviderBlock(\n\tproviderBlocks: readonly AnthropicContentBlock[],\n\tproviderIndex: number,\n\texpectedType: string,\n): { block: AnthropicContentBlock | undefined; nextProviderIndex: number } {\n\tconst providerBlock = providerBlocks[providerIndex];\n\tif (providerBlock?.type === expectedType) {\n\t\treturn { block: providerBlock, nextProviderIndex: providerIndex + 1 };\n\t}\n\treturn { block: undefined, nextProviderIndex: providerIndex };\n}\n\nfunction repairAssistantContent(\n\toriginalMessage: AssistantMessage,\n\tproviderBlocks: readonly AnthropicContentBlock[],\n): AnthropicContentBlock[] {\n\tconst repaired: AnthropicContentBlock[] = [];\n\tlet providerIndex = 0;\n\n\tfor (const originalBlock of originalMessage.content) {\n\t\tconst replayBlock = readReplayThinkingBlock(originalBlock);\n\t\tif (replayBlock) {\n\t\t\tif (isThinkingLikeAnthropicBlock(providerBlocks[providerIndex])) {\n\t\t\t\tproviderIndex += 1;\n\t\t\t}\n\t\t\trepaired.push({ ...replayBlock });\n\t\t\tcontinue;\n\t\t}\n\n\t\tif (!isObject(originalBlock) || typeof originalBlock.type !== \"string\") continue;\n\n\t\tif (originalBlock.type === \"text\") {\n\t\t\tconst providerText = takeProviderBlock(providerBlocks, providerIndex, \"text\");\n\t\t\tif (providerText.block) {\n\t\t\t\trepaired.push(providerText.block);\n\t\t\t\tproviderIndex = providerText.nextProviderIndex;\n\t\t\t\tcontinue;\n\t\t\t}\n\t\t\tconst fallback = fallbackTextBlock(originalBlock);\n\t\t\tif (fallback) repaired.push(fallback);\n\t\t\tcontinue;\n\t\t}\n\n\t\tif (originalBlock.type === \"toolCall\") {\n\t\t\tconst providerToolUse = takeProviderBlock(providerBlocks, providerIndex, \"tool_use\");\n\t\t\tif (providerToolUse.block) {\n\t\t\t\trepaired.push(providerToolUse.block);\n\t\t\t\tproviderIndex = providerToolUse.nextProviderIndex;\n\t\t\t\tcontinue;\n\t\t\t}\n\t\t\tconst fallback = fallbackToolUseBlock(originalBlock);\n\t\t\tif (fallback) repaired.push(fallback);\n\t\t}\n\t}\n\n\tfor (; providerIndex < providerBlocks.length; providerIndex += 1) {\n\t\trepaired.push(providerBlocks[providerIndex]);\n\t}\n\n\treturn repaired;\n}\n\nfunction getAnthropicMessages(payload: unknown): unknown[] | undefined {\n\tif (!isObject(payload)) return undefined;\n\treturn Array.isArray(payload.messages) ? payload.messages : undefined;\n}\n\nfunction getAnthropicAssistantContent(message: unknown): AnthropicContentBlock[] | undefined {\n\tif (!isObject(message) || message.role !== \"assistant\") return undefined;\n\tif (!Array.isArray(message.content)) return undefined;\n\tconst content = message.content.filter(isAnthropicContentBlock);\n\treturn content.length === message.content.length ? content : undefined;\n}\n\n/**\n * Restore same-model Anthropic replay thinking blocks after provider payload\n * construction and extension payload hooks.\n *\n * Anthropic requires thinking/redacted_thinking blocks from replayed assistant\n * messages to remain byte-for-byte identical to the original response. The\n * upstream pi-ai Anthropic converter currently still sanitizes thinking text,\n * drops signed empty thinking, and does not understand raw redacted_thinking\n * blocks. This guard repairs the already-built Anthropic payload from the\n * pre-provider LLM messages while leaving non-Anthropic and cross-model payloads\n * unchanged.\n */\nexport function restoreAnthropicReplayThinkingBlocks(payload: unknown, sourceMessages: readonly Message[], model: Model<Api>): unknown {\n\tif (model.api !== \"anthropic-messages\") return payload;\n\n\tconst payloadMessages = getAnthropicMessages(payload);\n\tif (!payloadMessages) return payload;\n\n\tconst assistantPayloads = payloadMessages\n\t\t.map((message, index) => ({ message, index, content: getAnthropicAssistantContent(message) }))\n\t\t.filter(\n\t\t\t(entry): entry is { message: JsonObject; index: number; content: AnthropicContentBlock[] } =>\n\t\t\t\tentry.content !== undefined && isObject(entry.message),\n\t\t);\n\n\tif (assistantPayloads.length === 0) return payload;\n\n\tconst allowEmptySignature = isObject(model.compat) && model.compat.allowEmptySignature === true;\n\tlet assistantPayloadOrdinal = 0;\n\tlet nextPayloadMessages: unknown[] | undefined;\n\n\tfor (const sourceMessage of sourceMessages) {\n\t\tif (sourceMessage.role !== \"assistant\") continue;\n\t\tif (!legacyProviderWouldEmitAssistant(sourceMessage, model, allowEmptySignature)) continue;\n\n\t\tconst payloadAssistant = assistantPayloads[assistantPayloadOrdinal];\n\t\tassistantPayloadOrdinal += 1;\n\t\tif (!payloadAssistant) break;\n\n\t\tif (!isSameModelAssistant(sourceMessage, model) || !hasReplayThinkingBlock(sourceMessage)) continue;\n\n\t\tconst repairedContent = repairAssistantContent(sourceMessage, payloadAssistant.content);\n\t\tif (JSON.stringify(repairedContent) === JSON.stringify(payloadAssistant.content)) continue;\n\n\t\tnextPayloadMessages ??= [...payloadMessages];\n\t\tnextPayloadMessages[payloadAssistant.index] = {\n\t\t\t...payloadAssistant.message,\n\t\t\tcontent: repairedContent,\n\t\t};\n\t}\n\n\tif (!nextPayloadMessages || !isObject(payload)) return payload;\n\treturn { ...payload, messages: nextPayloadMessages };\n}\n"]}
|
|
1
|
+
{"version":3,"file":"anthropic-thinking-guard.js","sourceRoot":"","sources":["../../src/core/anthropic-thinking-guard.ts"],"names":[],"mappings":"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","sourcesContent":["import type { Api, AssistantMessage, Message, Model } from \"@earendil-works/pi-ai/compat\";\n\ntype JsonObject = Record<string, unknown>;\n\ntype AnthropicContentBlock = JsonObject & { type: string };\n\ntype ReplayThinkingBlock =\n\t| { type: \"thinking\"; thinking: string; signature: string }\n\t| { type: \"redacted_thinking\"; data: string };\n\nfunction isObject(value: unknown): value is JsonObject {\n\treturn value !== null && typeof value === \"object\" && !Array.isArray(value);\n}\n\nfunction isAnthropicContentBlock(value: unknown): value is AnthropicContentBlock {\n\treturn isObject(value) && typeof value.type === \"string\";\n}\n\nfunction isThinkingLikeAnthropicBlock(value: unknown): boolean {\n\tif (!isAnthropicContentBlock(value)) return false;\n\treturn value.type === \"thinking\" || value.type === \"redacted_thinking\";\n}\n\nfunction isSameModelAssistant(message: AssistantMessage, model: Model<Api>): boolean {\n\treturn message.provider === model.provider && message.api === model.api && message.model === model.id;\n}\n\nfunction readReplayThinkingBlock(block: unknown, allowEmptySignature = false): ReplayThinkingBlock | undefined {\n\tif (!isObject(block) || typeof block.type !== \"string\") return undefined;\n\n\tif (block.type === \"redacted_thinking\") {\n\t\treturn typeof block.data === \"string\" ? { type: \"redacted_thinking\", data: block.data } : undefined;\n\t}\n\n\tif (block.type !== \"thinking\") return undefined;\n\n\tif (block.redacted === true) {\n\t\treturn typeof block.thinkingSignature === \"string\"\n\t\t\t? { type: \"redacted_thinking\", data: block.thinkingSignature }\n\t\t\t: undefined;\n\t}\n\n\tif (typeof block.thinking !== \"string\" || typeof block.thinkingSignature !== \"string\") return undefined;\n\tif (!allowEmptySignature && block.thinkingSignature.trim().length === 0) return undefined;\n\treturn { type: \"thinking\", thinking: block.thinking, signature: block.thinkingSignature };\n}\n\nfunction hasReplayThinkingBlock(message: AssistantMessage, allowEmptySignature: boolean): boolean {\n\treturn message.content.some((block) => readReplayThinkingBlock(block, allowEmptySignature) !== undefined);\n}\n\nfunction legacyProviderWouldEmitAssistantBlock(block: unknown): boolean {\n\tif (!isObject(block) || typeof block.type !== \"string\") return false;\n\n\tif (block.type === \"text\") {\n\t\treturn typeof block.text === \"string\" && block.text.trim().length > 0;\n\t}\n\n\tif (block.type === \"toolCall\") {\n\t\treturn true;\n\t}\n\n\tif (block.type !== \"thinking\") {\n\t\treturn false;\n\t}\n\n\tif (block.redacted === true) {\n\t\treturn true;\n\t}\n\n\tif (typeof block.thinking !== \"string\") return false;\n\tconst signature = typeof block.thinkingSignature === \"string\" ? block.thinkingSignature : undefined;\n\treturn block.thinking.trim().length > 0 || (signature !== undefined && signature.trim().length > 0);\n}\n\nfunction legacyProviderWouldEmitAssistant(message: AssistantMessage, model: Model<Api>): boolean {\n\tif (message.stopReason === \"error\" || message.stopReason === \"aborted\") return false;\n\n\t// This mirrors the relevant same-model branch in @earendil-works/pi-ai's\n\t// transformMessages() + Anthropic convertMessages() pipeline closely enough\n\t// to keep assistant ordinal mapping aligned with the provider payload.\n\tif (isSameModelAssistant(message, model)) {\n\t\treturn message.content.some((block) => legacyProviderWouldEmitAssistantBlock(block));\n\t}\n\n\treturn message.content.some((block) => {\n\t\tif (!isObject(block) || typeof block.type !== \"string\") return false;\n\t\tif (block.type === \"text\") return typeof block.text === \"string\" && block.text.trim().length > 0;\n\t\tif (block.type === \"toolCall\") return true;\n\t\tif (block.type !== \"thinking\") return false;\n\t\tif (block.redacted === true) return false;\n\t\treturn typeof block.thinking === \"string\" && block.thinking.trim().length > 0;\n\t});\n}\n\nfunction fallbackTextBlock(block: JsonObject): AnthropicContentBlock | undefined {\n\treturn typeof block.text === \"string\" && block.text.trim().length > 0\n\t\t? { type: \"text\", text: block.text }\n\t\t: undefined;\n}\n\nfunction fallbackToolUseBlock(block: JsonObject): AnthropicContentBlock | undefined {\n\tif (typeof block.id !== \"string\" || typeof block.name !== \"string\") return undefined;\n\treturn { type: \"tool_use\", id: block.id, name: block.name, input: block.arguments ?? {} };\n}\n\nfunction takeProviderBlock(\n\tproviderBlocks: readonly AnthropicContentBlock[],\n\tproviderIndex: number,\n\texpectedType: string,\n): { block: AnthropicContentBlock | undefined; nextProviderIndex: number } {\n\tconst providerBlock = providerBlocks[providerIndex];\n\tif (providerBlock?.type === expectedType) {\n\t\treturn { block: providerBlock, nextProviderIndex: providerIndex + 1 };\n\t}\n\treturn { block: undefined, nextProviderIndex: providerIndex };\n}\n\nfunction nonThinkingBlocksAlign(message: AssistantMessage, providerBlocks: readonly AnthropicContentBlock[]): boolean {\n\tconst sourceTypes = message.content.flatMap((block) => {\n\t\tif (!isObject(block) || typeof block.type !== \"string\") return [];\n\t\tif (block.type === \"text\") return typeof block.text === \"string\" && block.text.trim().length > 0 ? [\"text\"] : [];\n\t\treturn block.type === \"toolCall\" ? [\"tool_use\"] : [];\n\t});\n\tconst providerTypes = providerBlocks.filter((block) => !isThinkingLikeAnthropicBlock(block)).map((block) => block.type);\n\treturn sourceTypes.length === providerTypes.length && sourceTypes.every((type, index) => type === providerTypes[index]);\n}\n\nfunction repairAssistantContent(\n\toriginalMessage: AssistantMessage,\n\tproviderBlocks: readonly AnthropicContentBlock[],\n\tallowEmptySignature: boolean,\n): AnthropicContentBlock[] {\n\tconst repaired: AnthropicContentBlock[] = [];\n\tlet providerIndex = 0;\n\n\tfor (const originalBlock of originalMessage.content) {\n\t\tconst replayBlock = readReplayThinkingBlock(originalBlock, allowEmptySignature);\n\t\tif (replayBlock) {\n\t\t\tif (isThinkingLikeAnthropicBlock(providerBlocks[providerIndex])) {\n\t\t\t\tproviderIndex += 1;\n\t\t\t}\n\t\t\trepaired.push({ ...replayBlock });\n\t\t\tcontinue;\n\t\t}\n\n\t\tif (!isObject(originalBlock) || typeof originalBlock.type !== \"string\") continue;\n\n\t\tif (originalBlock.type === \"text\") {\n\t\t\tconst providerText = takeProviderBlock(providerBlocks, providerIndex, \"text\");\n\t\t\tif (providerText.block) {\n\t\t\t\trepaired.push(providerText.block);\n\t\t\t\tproviderIndex = providerText.nextProviderIndex;\n\t\t\t\tcontinue;\n\t\t\t}\n\t\t\tconst fallback = fallbackTextBlock(originalBlock);\n\t\t\tif (fallback) repaired.push(fallback);\n\t\t\tcontinue;\n\t\t}\n\n\t\tif (originalBlock.type === \"toolCall\") {\n\t\t\tconst providerToolUse = takeProviderBlock(providerBlocks, providerIndex, \"tool_use\");\n\t\t\tif (providerToolUse.block) {\n\t\t\t\trepaired.push(providerToolUse.block);\n\t\t\t\tproviderIndex = providerToolUse.nextProviderIndex;\n\t\t\t\tcontinue;\n\t\t\t}\n\t\t\tconst fallback = fallbackToolUseBlock(originalBlock);\n\t\t\tif (fallback) repaired.push(fallback);\n\t\t}\n\t}\n\n\tfor (; providerIndex < providerBlocks.length; providerIndex += 1) {\n\t\trepaired.push(providerBlocks[providerIndex]);\n\t}\n\n\treturn repaired;\n}\n\nfunction getAnthropicMessages(payload: unknown): unknown[] | undefined {\n\tif (!isObject(payload)) return undefined;\n\treturn Array.isArray(payload.messages) ? payload.messages : undefined;\n}\n\nfunction getAnthropicAssistantContent(message: unknown): AnthropicContentBlock[] | undefined {\n\tif (!isObject(message) || message.role !== \"assistant\") return undefined;\n\tif (!Array.isArray(message.content)) return undefined;\n\tconst content = message.content.filter(isAnthropicContentBlock);\n\treturn content.length === message.content.length ? content : undefined;\n}\n\n/**\n * Restore same-model Anthropic replay thinking blocks after provider payload\n * construction and extension payload hooks.\n *\n * Anthropic requires thinking/redacted_thinking blocks from replayed assistant\n * messages to remain byte-for-byte identical to the original response. The\n * upstream pi-ai Anthropic converter can sanitize thinking text and drop signed\n * empty thinking. convertToLlm normalizes raw redacted_thinking blocks in its\n * transient, non-mutating LLM-compatible messages before this hook, then this guard\n * restores exact same-model payloads while leaving non-Anthropic and cross-model\n * payloads unchanged.\n */\nexport function restoreAnthropicReplayThinkingBlocks(payload: unknown, sourceMessages: readonly Message[], model: Model<Api>): unknown {\n\tif (model.api !== \"anthropic-messages\") return payload;\n\n\tconst payloadMessages = getAnthropicMessages(payload);\n\tif (!payloadMessages) return payload;\n\n\tconst assistantPayloads = payloadMessages\n\t\t.map((message, index) => ({ message, index, content: getAnthropicAssistantContent(message) }))\n\t\t.filter(\n\t\t\t(entry): entry is { message: JsonObject; index: number; content: AnthropicContentBlock[] } =>\n\t\t\t\tentry.content !== undefined && isObject(entry.message),\n\t\t);\n\n\tif (assistantPayloads.length === 0) return payload;\n\n\tconst emittingSourceAssistants = sourceMessages.filter(\n\t\t(message): message is AssistantMessage => message.role === \"assistant\" && legacyProviderWouldEmitAssistant(message, model),\n\t);\n\t// Fail closed if pi-ai's converter emission behavior drifts from the model above;\n\t// ordinal restoration must never splice thinking into a different assistant.\n\tif (emittingSourceAssistants.length !== assistantPayloads.length) return payload;\n\n\tconst allowEmptySignature = isObject(model.compat) && model.compat.allowEmptySignature === true;\n\tlet nextPayloadMessages: unknown[] | undefined;\n\n\tfor (const [assistantPayloadOrdinal, sourceMessage] of emittingSourceAssistants.entries()) {\n\t\tconst payloadAssistant = assistantPayloads[assistantPayloadOrdinal];\n\n\t\tif (!isSameModelAssistant(sourceMessage, model) || !hasReplayThinkingBlock(sourceMessage, allowEmptySignature)) continue;\n\t\t// A second fail-closed guard verifies the non-thinking shape before replacing\n\t\t// signed blocks, protecting against equal-count ordinal misalignment.\n\t\tif (!nonThinkingBlocksAlign(sourceMessage, payloadAssistant.content)) continue;\n\n\t\tconst repairedContent = repairAssistantContent(sourceMessage, payloadAssistant.content, allowEmptySignature);\n\t\tif (JSON.stringify(repairedContent) === JSON.stringify(payloadAssistant.content)) continue;\n\n\t\tnextPayloadMessages ??= [...payloadMessages];\n\t\tnextPayloadMessages[payloadAssistant.index] = {\n\t\t\t...payloadAssistant.message,\n\t\t\tcontent: repairedContent,\n\t\t};\n\t}\n\n\tif (!nextPayloadMessages || !isObject(payload)) return payload;\n\treturn { ...payload, messages: nextPayloadMessages };\n}\n"]}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"atomic-guide-command.d.ts","sourceRoot":"","sources":["../../src/core/atomic-guide-command.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,wBAAwB,CAAC;AAG/D,eAAO,MAAM,yBAAyB,WAAW,CAAC;AAClD,eAAO,MAAM,gCAAgC,qCACT,CAAC;AA2NrC,QAAA,MAAM,cAAc;mBAEV,UAAU;;oBAET,UAAU;0BACJ,oBAAoB;;;mBAI3B,WAAW;;oBAEV,WAAW;0BACL,iBAAiB;;;mBAIxB,SAAS;;oBAER,SAAS;0BACH,0BAA0B;;;mBAIjC,WAAW;;oBAEV,YAAY;0BACN,sBAAsB;;EASpC,CAAC;AAEJ,KAAK,kBAAkB,GAAG,CAAC,OAAO,cAAc,CAAC,CAAC,MAAM,CAAC,CAAC;AAC1D,KAAK,sBAAsB,GAAG,kBAAkB,CAAC,MAAM,CAAC,CAAC;AAEzD,MAAM,MAAM,qBAAqB,GAAG,kBAAkB,CAAC,OAAO,CAAC,CAAC;AAEhE,MAAM,MAAM,eAAe,GAAG,MAAM,GAAG,sBAAsB,CAAC;AAE9D,eAAO,MAAM,yBAAyB,EAAE,SAAS,qBAAqB,EACtB,CAAC;AAiBjD,wBAAgB,uBAAuB,CACrC,MAAM,EAAE,MAAM,GACb,MAAM,IAAI,qBAAqB,CAEjC;AAoCD,wBAAgB,wBAAwB,CAAC,IAAI,EAAE,MAAM,GAAG,eAAe,CAOtE;AAED,wBAAgB,iCAAiC,CAC/C,MAAM,EAAE,MAAM,GACb,gBAAgB,EAAE,GAAG,IAAI,CAa3B;AAED,iBAAS,yBAAyB,CAAC,GAAG,EAAE,MAAM,GAAG,MAAM,CActD;AAED,wBAAgB,qBAAqB,CACnC,IAAI,EAAE,eAAe,EACrB,GAAG,EAAE,MAAM,GACV,MAAM,CAGR;AAED,wBAAgB,wBAAwB,CACtC,MAAM,EAAE,qBAAqB,GAC5B,eAAe,CAEjB","sourcesContent":["import * as path from \"node:path\";\nimport type { AutocompleteItem } from \"@earendil-works/pi-tui\";\nimport { getChangelogPath, parseChangelog } from \"../utils/changelog.ts\";\n\nexport const ATOMIC_GUIDE_COMMAND_NAME = \"atomic\";\nexport const ATOMIC_GUIDE_COMMAND_DESCRIPTION =\n \"Atomic onboarding and help guide\";\n\nconst OVERVIEW = `# Atomic overview\n\nAtomic turns one-off prompts into developer workflows: on-call debugging, repo research that turns into implementation, testing and review loops, and larger multi-stage automation. Workflows are the default for non-trivial work and requests with inherent structure plus a verifiable objective, including implementation, build, debugging, bug-fix, migration, new-feature, scoped multi-file, or validation-heavy docs/code work. Loop-shaped prompts like \\`do X until Y\\`, \\`repeat until\\`, \\`iterate until\\`, \\`review/fix until passing\\`, or \\`run checks and fix until green\\` should map to a workflow unless the task is a tiny deterministic direct edit or simple answer. Use \\`/workflow goal\\` for small-to-medium changes with a clear work surface, exact outcome, and named validation; keep \\`/workflow ralph\\` for larger migrations, broad refactors, and multi-package research-first implementation work. Start Atomic in a project with \\`atomic\\`, then talk to it normally. Use \\`@file\\` to attach files, \\`!command\\` to run shell output through the model, and \\`!!command\\` to run shell output without adding it to context.\n\n## Core session commands\n\n| Command | Use |\n|---|---|\n| \\`/login\\` | configure auth |\n| \\`/model\\` | switch model |\n| \\`/settings\\` | thinking level, theme, message delivery, transport |\n| \\`/new\\`, \\`/resume\\` | start or resume sessions |\n| \\`/tree\\`, \\`/fork\\`, \\`/clone\\` | branch or navigate session history |\n| \\`/compact\\` | delete safe older context verbatim |\n| \\`/hotkeys\\`, \\`/changelog\\` | local help and release notes |\n\n## Examples of using Atomic\n\n| Goal | How to use |\n|---|---|\n| On-call / broken behavior | Use \\`/workflow goal objective=\"Reproduce the failure, patch the root cause, and validate it\"\\` for a focused fix loop; reserve direct debugger/subagent calls for narrow diagnosis or truly tiny deterministic fixes |\n| Research → spec → implementation | Chain \\`/skill:research-codebase\\` → \\`/skill:create-spec\\` → \\`/workflow goal objective=\"...\"\\` for bounded scoped work with explicit validation; add \\`create_pr=true\\` for Goal's final PR handoff after approval, or use \\`/workflow ralph ...\\` when the work needs research-first broad refactoring |\n| Testing / regression hardening | Use \\`/workflow goal objective=\"Add the regression coverage, fix failures, and finish when focused tests pass\"\\`; loop wording like review/fix/test until passing is workflow-shaped |\n| Large repo discovery | Run \\`/parallel codebase-locator \"map the area\" -> codebase-analyzer \"trace the current flow\" -> codebase-pattern-finder \"find patterns\" --bg\\`, or \\`/workflow deep-research-codebase\\` for whole-repo synthesis |\n| UI / product polish | Run \\`/skill:impeccable\\` for interface critique and refinement, or \\`/workflow open-claude-design\\` for generation + refinement loops |\n\n## Built-in workflows\n\n| Workflow | When to use | How to run |\n|---|---|---|\n| \\`deep-research-codebase\\` | broad repo or cross-cutting research before you decide what to change (for one area, use \\`/skill:research-codebase\\`; this indexes the whole repo) | \\`/workflow deep-research-codebase prompt=\"How do payment retries work end to end?\"\\` |\n| \\`goal\\` | small-to-medium scoped changes when you can name the work surface, outcome, and validation, including bug fixes, debugging, scoped multi-file edits, and test/fix loops; keeps receipts in a ledger, stops as \\`complete\\`, \\`blocked\\`, or \\`needs_human\\`, and can run a final PR handoff with \\`create_pr=true\\` after approval | \\`/workflow goal objective=\"Implement specs/<date>-<topic>.md, run focused tests, and validate the changed behavior\"\\` |\n| \\`ralph\\` | larger migrations, new features, broad refactors, and multi-package changes where you want Atomic to research first, delegate, review, and iterate; add \\`create_pr=true\\` only when you want the final pull-request stage and report | \\`/workflow ralph prompt=\"Migrate the database layer to Drizzle\" create_pr=true\\` |\n| \\`open-claude-design\\` | UI and design-system work that benefits from generation and refinement loops | \\`/workflow open-claude-design prompt=\"Refresh the settings page hierarchy\"\\` |\n\nUse \\`/workflow list\\` to see what is available and \\`/workflow inputs <name>\\` to inspect inputs in your environment.\n\n## Top skills\n\n| Skill | When to use | How to run |\n|---|---|---|\n| \\`research-codebase\\` | write a grounded research artifact for one subsystem or question | \\`/skill:research-codebase how the rate limiter works in src/middleware/\\` |\n| \\`create-spec\\` | turn research into an implementation-ready plan | \\`/skill:create-spec from research/docs/<date>-<topic>.md\\` |\n| \\`tdd\\` | do test-first feature or bug work | \\`/skill:tdd\\` |\n| \\`prompt-engineer\\` | tighten a vague prompt before a long run | \\`/skill:prompt-engineer Draft a sharper implementation prompt for ...\\` |\n| \\`subagent\\` | learn delegation patterns and exact \\`/run\\`, \\`/parallel\\`, and \\`/chain\\` usage | \\`/skill:subagent\\` |\n| \\`impeccable\\` | critique or refine frontend and product UI | \\`/skill:impeccable\\` |\n\n## Subagents\n\nSubagents are focused child Atomic sessions you can point at one job inside the repo.\n\n| Built-in subagent | Use |\n|---|---|\n| \\`codebase-locator\\` | find relevant files, tests, entrypoints, and configs |\n| \\`codebase-analyzer\\` | explain current behavior with file:line refs |\n| \\`codebase-pattern-finder\\` | find existing code to model after |\n| \\`debugger\\` | reproduce, diagnose, and fix broken behavior |\n\nHow the direct commands map to repo work:\n- \\`/run\\` = one specialist on one job, for example \\`/run codebase-locator \"Map the webhook retry flow\"\\`\n- \\`/parallel\\` = several independent specialists at once, for example \\`/parallel codebase-locator \"map retry files\" -> codebase-pattern-finder \"find existing retry/backoff patterns\" -> codebase-online-researcher \"research current retry guidance\" --bg\\`\n- \\`/chain\\` = ordered handoffs, for example \\`/chain codebase-locator \"find the auth files\" -> codebase-analyzer \"trace the auth flow\" -> debugger \"patch the failing auth edge case\"\\`\n\n─────────────────────────────────────────────────────────────────\n\nWhere to next:\n\n\\`/atomic example\\` — see the pieces used on a code task\n\\`/atomic workflows\\` — learn when to use workflows`;\n\nconst EXAMPLE = `# Practical example\n\nThis is an example of a spec-driven development process using Atomic workflows. Use it when you are new to a repo or the task has non-trivial scope. Type the examples below into the Atomic TUI chat after starting \\`atomic\\` in your project.\n\n## 1. Research what exists\n\nUse \\`/skill:research-codebase\\` for a scoped area, subsystem, or directory:\n\n\\`/skill:research-codebase how the rate limiter works in src/middleware/\\`\n\nUse \\`deep-research-codebase\\` when the answer spans the whole repo or a cross-cutting implementation path:\n\n\\`/workflow deep-research-codebase prompt=\"How do payment retries work end to end?\"\\`\n\nIf the research prompt is vague, tighten it first with \\`/skill:prompt-engineer\\`:\n\n\\`/skill:prompt-engineer Draft a sharper repo-research prompt for understanding payment retries end to end, including retries, queues, and failure handling.\\`\n\n## 2. Create a spec when requirements are fuzzy\n\nSkip this if the implementation request is already precise.\n\n\\`/skill:create-spec from research/docs/<date>-<topic>.md\\`\n\n## 3. Implement with review built in\n\nDefault to a workflow for non-trivial implementation, build, debugging, bug-fix, migration, new-feature, scoped multi-file, or docs/code-change work when validation matters. Direct chat is best reserved for tiny deterministic single-file/no-test/no-review edits or simple answers.\n\nFor small-to-medium scoped changes where you can identify the work surface, exact outcome, and validation, use \\`goal\\`:\n\n\\`/workflow goal objective=\"Implement specs/<date>-<topic>.md, run focused tests, and finish when the documented behavior is validated\"\\`\n\nIf the request is loop-shaped — for example \\`do X until Y\\`, \\`repeat until\\`, \\`iterate until\\`, \\`review/fix until passing\\`, or \\`run checks and fix until green\\` — make the stop condition explicit in the Goal objective:\n\n\\`/workflow goal objective=\"Fix the flaky checkout test, adjust the smallest necessary code, and finish when the focused test passes three times\"\\`\n\nFor larger migrations, broad refactors, new features, or multi-package changes that need research-first implementation, use \\`ralph\\`:\n\n\\`/workflow ralph prompt=\"Migrate the database layer to Drizzle\"\\`\n\nAdd \\`create_pr=true\\` only when you want the final pull-request stage and report after the review gate approves.\n\n## 4. Decide and land\n\nIf you used \\`goal\\`, the workflow already persisted receipts in a goal ledger and reviewer-gated completion. Use its final status — \\`complete\\`, \\`blocked\\`, or \\`needs_human\\` — plus the remaining-work report to decide whether to ship, unblock, or clarify. If you enabled \\`create_pr=true\\`, use its final pull-request report to decide whether to ship or iterate again.\n\nIf you used \\`ralph\\`, the workflow transformed the prompt into a research question, researched the codebase, delegated implementation through sub-agents, reviewed, and iterated. If you enabled \\`create_pr=true\\`, use its final pull-request report to decide whether to ship or iterate again.\n\nIf you implemented directly instead of using a workflow, you can still run:\n\n\\`/parallel-review current diff\\`\n\nAtomic will synthesize reviewer feedback and ask before applying fixes.\n\n─────────────────────────────────────────────────────────────────\n\nWhere to next:\n\n\\`/atomic workflows\\` — learn when to use workflows\n\\`/atomic overview\\` — quick refresh`;\n\nconst WORKFLOWS = `# Workflows primer\n\nA workflow is a TypeScript-defined pipeline exported from \\`workflow({...})\\`. It can run tasks, chains, parallel fan-out, human-in-the-loop prompts, background status, and model fallback chains.\n\nUse workflows by default for non-trivial work with a verifiable objective: implementation, build, debugging, bug-fix, migration, new-feature, scoped multi-file, validation-heavy docs/code changes, or any prompt with a stop condition such as \\`do X until Y\\`, \\`repeat until\\`, \\`iterate until\\`, or \\`review/fix until passing\\`. Skip workflows only for tiny deterministic direct edits or simple answers where tracking would add more overhead than value.\n\nYou do not have to write TypeScript to add one. Describe the workflow you want in plain chat — goal, inputs, stages, which steps are parallel or sequential, handoff/output shape, and any model or thinking-level preferences — and Atomic will use the workflow docs to scaffold a reusable definition under \\`.atomic/workflows/\\` and reload it for you. Hand-edit the TypeScript afterward when you want precise control.\n\n## Built-in workflows\n\n| Workflow | When to use | How to run |\n|---|---|---|\n| \\`deep-research-codebase\\` | broad repo or cross-cutting research before you decide what to change (for one area, use \\`/skill:research-codebase\\`; this indexes the whole repo) | \\`/workflow deep-research-codebase prompt=\"How do payment retries work end to end?\"\\` |\n| \\`goal\\` | small-to-medium scoped changes with a clear outcome and named validation, including bug fixes, debugging, scoped multi-file edits, and test/fix loops; add \\`create_pr=true\\` only for final PR handoff after approval | \\`/workflow goal objective=\"Update the CLI docs, include one usage example, and verify the docs build passes\"\\` |\n| \\`ralph\\` | larger migrations, new features, broad refactors, and multi-package research-first implementation work | \\`/workflow ralph prompt=\"Migrate the database layer to Drizzle\" create_pr=true\\` |\n| \\`open-claude-design\\` | frontend and product design work | \\`/workflow open-claude-design prompt=\"Refresh the settings page hierarchy\"\\` |\n\nUse \\`/workflow inputs <name>\\` to inspect the exact inputs in your environment.\n\nUse \\`/skill:research-codebase ...\\` when you want research on one subsystem, directory, or focused question. Use \\`/workflow deep-research-codebase ...\\` when the answer needs end-to-end tracing across many parts of the repo.\n\nIf you are drafting research, reviewer, or synthesis prompts for a workflow, use \\`/skill:prompt-engineer\\` first. It is a good fit when a stage prompt feels vague, overloaded, or underspecified.\n\n## What good workflow authoring looks like\n\nA good workflow request is explicit about stage purpose, model choice, handoff, and the decision each step must return.\n\nExample: ask Atomic in chat with something like this:\n\n~~~text\nCreate a reusable workflow called review-changes.\n\nIt should accept one required text input called target for a diff, PR summary, or review target.\n\nRun two independent review stages in parallel with fresh context:\n- one reviewer focused on correctness, regressions, and missing tests using openai-codex/gpt-5.5 at xhigh thinking\n- one reviewer focused on edge cases, maintainability, and hidden risks using anthropic/claude-opus-4-8 at xhigh thinking\n\nThen add an aggregate stage that consolidates both reviews, deduplicates overlap, keeps only evidence-backed issues, and separates blockers from optional suggestions using openai/gpt-5.5 at high thinking.\n\nFinally add an adjudicate stage using anthropic/claude-sonnet-4 at high thinking that decides what to fix now, what to defer, and what to reject. Return a short action list with rationale.\n\nThe workflow should return structured output with consolidated_review and decision fields.\n~~~\n\nWhy this is good:\n- it names the workflow and required input\n- it specifies which stages are parallel vs sequential\n- each stage has one job\n- it defines the handoff and final outputs\n- it calls out model choice and thinking level where that matters\n\n## Run and inspect\n\n\\`/workflow list\\`\n\n\\`/workflow inputs goal\\`\n\n\\`/workflow goal objective=\"Fix the settings form validation bug, add the focused test, and finish when invalid emails show the inline error without submitting\"\\`\n\n\\`/workflow inputs ralph\\`\n\n\\`/workflow ralph prompt=\"Migrate the database layer to Drizzle\" create_pr=true\\`\n\n\\`/workflow status\\`\n\n\\`/workflow connect <run-id>\\`\n\n\\`/workflow interrupt <run-id>\\`\n\n\\`/workflow resume <run-id>\\`\n\nWorkflows run as background tasks. Use F2 or \\`/workflow connect <run-id>\\` for the graph viewer. Human-in-the-loop prompts appear there, not as chat modals, and awaiting-input states do not wake the main chat agent. Completion and failure notices are steered back into the main chat; answers submitted in the workflow UI interrupt stale main-chat questions so the model does not ask again.\n\n## Author your own\n\nDescribe your workflow in plain chat — say what you want the workflow to accomplish, what inputs it should accept, what stages should run, and what final output or decision it should return. Atomic will use the workflow docs to scaffold a reusable definition under \\`.atomic/workflows/\\`, ask clarifying questions when stage purpose, models, or handoffs are ambiguous, and run \\`/workflow reload\\` so you can launch it immediately.\n\n─────────────────────────────────────────────────────────────────\n\nWhere to next:\n\n\\`/atomic example\\` — see workflows in a normal task flow\n\\`/atomic overview\\` — quick refresh`;\n\nconst GUIDE_SECTIONS = [\n {\n name: \"overview\",\n aliases: [],\n label: \"overview\",\n description: \"30-second overview\",\n render: () => OVERVIEW,\n },\n {\n name: \"workflows\",\n aliases: [\"workflow\"],\n label: \"workflows\",\n description: \"Workflow primer\",\n render: () => WORKFLOWS,\n },\n {\n name: \"example\",\n aliases: [\"examples\"],\n label: \"example\",\n description: \"Practical first workflow\",\n render: () => EXAMPLE,\n },\n {\n name: \"whats-new\",\n aliases: [\"what's new\", \"whats new\", \"news\", \"updates\", \"changelog\"],\n label: \"what's new\",\n description: \"Recent release notes\",\n render: readLatestStableChangelog,\n },\n] as const satisfies readonly {\n readonly name: string;\n readonly aliases: readonly string[];\n readonly label: string;\n readonly description: string;\n readonly render: (cwd: string) => string;\n}[];\n\ntype AtomicGuideSection = (typeof GUIDE_SECTIONS)[number];\ntype AtomicGuideSectionName = AtomicGuideSection[\"name\"];\n\nexport type AtomicGuideHelpChoice = AtomicGuideSection[\"label\"];\n\nexport type AtomicGuideMode = \"help\" | AtomicGuideSectionName;\n\nexport const ATOMIC_GUIDE_HELP_CHOICES: readonly AtomicGuideHelpChoice[] =\n GUIDE_SECTIONS.map((section) => section.label);\n\nconst GUIDE_SECTIONS_BY_NAME = new Map<\n AtomicGuideSectionName,\n AtomicGuideSection\n>(GUIDE_SECTIONS.map((section) => [section.name, section]));\nconst GUIDE_SECTIONS_BY_LABEL = new Map<string, AtomicGuideSection>(\n GUIDE_SECTIONS.map((section) => [section.label, section]),\n);\nconst GUIDE_SECTIONS_BY_INPUT = new Map<string, AtomicGuideSection>(\n GUIDE_SECTIONS.flatMap((section) =>\n [section.name, section.label, ...section.aliases].map(\n (input) => [input, section] as const,\n ),\n ),\n);\n\nexport function isAtomicGuideHelpChoice(\n choice: string,\n): choice is AtomicGuideHelpChoice {\n return GUIDE_SECTIONS_BY_LABEL.has(choice);\n}\n\nconst ATOMIC_GUIDE_TRAILING_PUNCTUATION = \"?!.,;:\";\n\nfunction stripTrailingAtomicGuidePunctuation(value: string): string {\n let end = value.length;\n while (\n end > 0 &&\n ATOMIC_GUIDE_TRAILING_PUNCTUATION.includes(value.charAt(end - 1))\n ) {\n end--;\n }\n return value.slice(0, end);\n}\n\nfunction getGuideSectionForChoice(\n choice: string,\n): AtomicGuideSection | undefined {\n return GUIDE_SECTIONS_BY_LABEL.get(choice);\n}\n\nfunction getGuideSectionForMode(\n mode: AtomicGuideSectionName,\n): AtomicGuideSection {\n const section = GUIDE_SECTIONS_BY_NAME.get(mode);\n if (!section) throw new Error(`Unknown Atomic guide section: ${mode}`);\n return section;\n}\n\nfunction getAtomicGuideHelpMenu(): string {\n const sectionHelp = GUIDE_SECTIONS.map(\n (section) => `- \\`${section.label}\\` — run \\`/atomic ${section.label}\\``,\n ).join(\"\\n\");\n return `# Atomic\\n\\nSelect where to start:\\n\\n${sectionHelp}`;\n}\n\nexport function normalizeAtomicGuideMode(args: string): AtomicGuideMode {\n const normalized = stripTrailingAtomicGuidePunctuation(\n args.trim().toLowerCase(),\n );\n if (!normalized) return \"help\";\n\n return GUIDE_SECTIONS_BY_INPUT.get(normalized)?.name ?? \"help\";\n}\n\nexport function getAtomicGuideArgumentCompletions(\n prefix: string,\n): AutocompleteItem[] | null {\n const query = prefix.trim().toLowerCase();\n const items = GUIDE_SECTIONS.map((section) => ({\n value: section.label,\n label: section.label,\n description: section.description,\n }));\n const filtered = query\n ? items.filter(\n (item) => item.value.startsWith(query) || item.label.startsWith(query),\n )\n : items;\n return filtered.length > 0 ? filtered : null;\n}\n\nfunction readLatestStableChangelog(cwd: string): string {\n const changelogPath = getChangelogPath();\n const stableSections = parseChangelog(changelogPath)\n .filter((entry) => entry.prerelease === null)\n .slice(0, 3)\n .map((entry) => entry.content.trim())\n .filter(Boolean);\n\n if (stableSections.length === 0) {\n return `# What's new\\n\\nNo stable release sections were found. Try \\`/changelog\\` for the interactive changelog viewer.\\n\\n─────────────────────────────────────────────────────────────────\\n\\nWhere to next:\\n\\n\\`/atomic example\\` — see a practical first workflow\\n\\`/atomic overview\\` — quick refresh`;\n }\n\n const relativePath = path.relative(cwd, changelogPath) || changelogPath;\n return `# What's new\\n\\n${stableSections.join(\"\\n\\n\")}\\n\\nSource: \\`${relativePath}\\`\\n\\n─────────────────────────────────────────────────────────────────\\n\\nWhere to next:\\n\\n\\`/atomic example\\` — see a practical first workflow\\n\\`/atomic overview\\` — quick refresh`;\n}\n\nexport function getAtomicGuideMessage(\n mode: AtomicGuideMode,\n cwd: string,\n): string {\n if (mode === \"help\") return getAtomicGuideHelpMenu();\n return getGuideSectionForMode(mode).render(cwd);\n}\n\nexport function atomicGuideModeForChoice(\n choice: AtomicGuideHelpChoice,\n): AtomicGuideMode {\n return getGuideSectionForChoice(choice)?.name ?? \"help\";\n}\n"]}
|
|
1
|
+
{"version":3,"file":"atomic-guide-command.d.ts","sourceRoot":"","sources":["../../src/core/atomic-guide-command.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,wBAAwB,CAAC;AAG/D,eAAO,MAAM,yBAAyB,WAAW,CAAC;AAClD,eAAO,MAAM,gCAAgC,qCACT,CAAC;AA2NrC,QAAA,MAAM,cAAc;mBAEV,UAAU;;oBAET,UAAU;0BACJ,oBAAoB;;;mBAI3B,WAAW;;oBAEV,WAAW;0BACL,iBAAiB;;;mBAIxB,SAAS;;oBAER,SAAS;0BACH,0BAA0B;;;mBAIjC,WAAW;;oBAEV,YAAY;0BACN,sBAAsB;;EASpC,CAAC;AAEJ,KAAK,kBAAkB,GAAG,CAAC,OAAO,cAAc,CAAC,CAAC,MAAM,CAAC,CAAC;AAC1D,KAAK,sBAAsB,GAAG,kBAAkB,CAAC,MAAM,CAAC,CAAC;AAEzD,MAAM,MAAM,qBAAqB,GAAG,kBAAkB,CAAC,OAAO,CAAC,CAAC;AAEhE,MAAM,MAAM,eAAe,GAAG,MAAM,GAAG,sBAAsB,CAAC;AAE9D,eAAO,MAAM,yBAAyB,EAAE,SAAS,qBAAqB,EACtB,CAAC;AAiBjD,wBAAgB,uBAAuB,CACrC,MAAM,EAAE,MAAM,GACb,MAAM,IAAI,qBAAqB,CAEjC;AAoCD,wBAAgB,wBAAwB,CAAC,IAAI,EAAE,MAAM,GAAG,eAAe,CAOtE;AAED,wBAAgB,iCAAiC,CAC/C,MAAM,EAAE,MAAM,GACb,gBAAgB,EAAE,GAAG,IAAI,CAa3B;AAED,iBAAS,yBAAyB,CAAC,GAAG,EAAE,MAAM,GAAG,MAAM,CActD;AAED,wBAAgB,qBAAqB,CACnC,IAAI,EAAE,eAAe,EACrB,GAAG,EAAE,MAAM,GACV,MAAM,CAGR;AAED,wBAAgB,wBAAwB,CACtC,MAAM,EAAE,qBAAqB,GAC5B,eAAe,CAEjB","sourcesContent":["import * as path from \"node:path\";\nimport type { AutocompleteItem } from \"@earendil-works/pi-tui\";\nimport { getChangelogPath, parseChangelog } from \"../utils/changelog.ts\";\n\nexport const ATOMIC_GUIDE_COMMAND_NAME = \"atomic\";\nexport const ATOMIC_GUIDE_COMMAND_DESCRIPTION =\n \"Atomic onboarding and help guide\";\n\nconst OVERVIEW = `# Atomic overview\n\nAtomic supports a least-orchestration hierarchy: keep interactive, exploratory, conceptual, and conversation-led work inline; use bounded single, chain, or parallel subagents while the parent remains in control; and use workflows when the user clearly delegates a well-defined autonomous job that is likely long-running/background-oriented or materially needs durable stages, artifacts/checkpoints, resumability, HIL, gates, retries, or bounded loops. Multiple steps, files, tests, validation, or parallelism alone do not require a workflow. Loop or stop-condition phrasing such as \\`do X until Y\\`, \\`repeat until\\`, \\`iterate until\\`, \\`review/fix until passing\\`, \\`run checks and fix until green\\`, or \\`keep going until done\\` is a key workflow signal when the user delegates execution, because it defines control flow and a completion condition that should be tracked. When workflow execution fits, Atomic may always author a custom TypeScript \\`workflow({...})\\` inline with normal coding tools if that shape best achieves the task; it is not limited to installed workflows or direct modes. Named workflows can be builtin, project, user, or package supplied; direct task/tasks/chain modes cover one-off tracked shapes. Start Atomic in a project with \\`atomic\\`, then talk to it normally. Use \\`@file\\` to attach files, \\`!command\\` to run shell output through the model, and \\`!!command\\` to run shell output without adding it to context.\n\n## Core session commands\n\n| Command | Use |\n|---|---|\n| \\`/login\\` | configure auth |\n| \\`/model\\` | switch model |\n| \\`/settings\\` | thinking level, theme, message delivery, transport |\n| \\`/new\\`, \\`/resume\\` | start or resume sessions |\n| \\`/tree\\`, \\`/fork\\`, \\`/clone\\` | branch or navigate session history |\n| \\`/compact\\` | delete safe older context verbatim |\n| \\`/hotkeys\\`, \\`/changelog\\` | local help and release notes |\n\n## Examples of using Atomic\n\n| Goal | How to use |\n|---|---|\n| On-call / broken behavior | Reproduce and diagnose inline or with a debugger subagent, using bounded specialists when useful; choose \\`goal\\` only when a clearly delegated repair materially needs a durable ledger, bounded worker turns, or reviewer-gated completion |\n| Research → spec → implementation | Use \\`/skill:research-codebase\\`, \\`/skill:create-spec\\`, and bounded subagents while the parent remains in control; choose a workflow only for a clearly delegated autonomous job with durable execution needs |\n| Testing / regression hardening | Keep focused test/fix work inline or bounded. Loop or stop-condition wording is a key workflow signal when the user delegates execution; use \\`goal\\` when the run should track retries, evidence, convergence, and an explicit stop condition |\n| Large repo discovery | Run \\`/parallel codebase-locator \"map the area\" -> codebase-analyzer \"trace the current flow\" -> codebase-pattern-finder \"find patterns\" --bg\\`, or \\`/workflow deep-research-codebase\\` for whole-repo synthesis |\n| UI / product polish | Run \\`/skill:impeccable\\` for interface critique and refinement, or \\`/workflow open-claude-design\\` for generation + refinement loops |\n\n## Built-in workflows\n\n| Workflow | When to use | How to run |\n|---|---|---|\n| \\`deep-research-codebase\\` | broad repo or cross-cutting research before you decide what to change (for one area, use \\`/skill:research-codebase\\`; this indexes the whole repo) | \\`/workflow deep-research-codebase prompt=\"How do payment retries work end to end?\"\\` |\n| \\`goal\\` | autonomous work that benefits from a durable goal ledger, bounded worker turns, named validation, and reviewer-gated completion; add \\`create_pr=true\\` only for final PR handoff after approval | \\`/workflow goal objective=\"Implement specs/<date>-<topic>.md, run focused tests, and validate the changed behavior\"\\` |\n| \\`ralph\\` | autonomous work that benefits from a durable research-first pipeline, delegated implementation, and iterative review | \\`/workflow ralph prompt=\"Migrate the database layer to Drizzle\" create_pr=true\\` |\n| \\`open-claude-design\\` | UI and design-system work that benefits from generation and refinement loops | \\`/workflow open-claude-design prompt=\"Refresh the settings page hierarchy\"\\` |\n\nUse \\`/workflow list\\` to see what is available and \\`/workflow inputs <name>\\` to inspect inputs in your environment.\n\n## Top skills\n\n| Skill | When to use | How to run |\n|---|---|---|\n| \\`research-codebase\\` | write a grounded research artifact for one subsystem or question | \\`/skill:research-codebase how the rate limiter works in src/middleware/\\` |\n| \\`create-spec\\` | turn research into an implementation-ready plan | \\`/skill:create-spec from research/docs/<date>-<topic>.md\\` |\n| \\`tdd\\` | do test-first feature or bug work | \\`/skill:tdd\\` |\n| \\`prompt-engineer\\` | tighten a vague prompt before a long run | \\`/skill:prompt-engineer Draft a sharper implementation prompt for ...\\` |\n| \\`subagent\\` | learn delegation patterns and exact \\`/run\\`, \\`/parallel\\`, and \\`/chain\\` usage | \\`/skill:subagent\\` |\n| \\`impeccable\\` | critique or refine frontend and product UI | \\`/skill:impeccable\\` |\n\n## Subagents\n\nSubagents are focused child Atomic sessions you can point at one job inside the repo.\n\n| Built-in subagent | Use |\n|---|---|\n| \\`codebase-locator\\` | find relevant files, tests, entrypoints, and configs |\n| \\`codebase-analyzer\\` | explain current behavior with file:line refs |\n| \\`codebase-pattern-finder\\` | find existing code to model after |\n| \\`debugger\\` | reproduce, diagnose, and fix broken behavior |\n\nHow the direct commands map to repo work:\n- \\`/run\\` = one specialist on one job, for example \\`/run codebase-locator \"Map the webhook retry flow\"\\`\n- \\`/parallel\\` = several independent specialists at once, for example \\`/parallel codebase-locator \"map retry files\" -> codebase-pattern-finder \"find existing retry/backoff patterns\" -> codebase-online-researcher \"research current retry guidance\" --bg\\`\n- \\`/chain\\` = ordered handoffs, for example \\`/chain codebase-locator \"find the auth files\" -> codebase-analyzer \"trace the auth flow\" -> debugger \"patch the failing auth edge case\"\\`\n\n─────────────────────────────────────────────────────────────────\n\nWhere to next:\n\n\\`/atomic example\\` — see the pieces used on a code task\n\\`/atomic workflows\\` — learn when to use workflows`;\n\nconst EXAMPLE = `# Practical example\n\nThis example shows a spec-driven development process whose clearly delegated autonomous implementation benefits from durable workflow execution. For interactive or conversation-led work, stay inline or use bounded subagents while the parent remains in control. Type the examples below into the Atomic TUI chat after starting \\`atomic\\` in your project.\n\n## 1. Research what exists\n\nUse \\`/skill:research-codebase\\` for a scoped area, subsystem, or directory:\n\n\\`/skill:research-codebase how the rate limiter works in src/middleware/\\`\n\nUse \\`deep-research-codebase\\` when the answer spans the whole repo or a cross-cutting implementation path:\n\n\\`/workflow deep-research-codebase prompt=\"How do payment retries work end to end?\"\\`\n\nIf the research prompt is vague, tighten it first with \\`/skill:prompt-engineer\\`:\n\n\\`/skill:prompt-engineer Draft a sharper repo-research prompt for understanding payment retries end to end, including retries, queues, and failure handling.\\`\n\n## 2. Create a spec when requirements are fuzzy\n\nSkip this if the implementation request is already precise.\n\n\\`/skill:create-spec from research/docs/<date>-<topic>.md\\`\n\n## 3. Implement with review built in\n\nKeep interactive or conversation-led implementation inline. Use bounded subagents when specialist delegation helps, and choose a workflow only when the user clearly delegates an autonomous job whose long-running/background nature or durable execution needs justify it; files, tests, and validation alone do not.\n\nWhen the job needs a durable goal ledger, bounded worker turns, and reviewer-gated completion, use \\`goal\\`:\n\n\\`/workflow goal objective=\"Implement specs/<date>-<topic>.md, run focused tests, and finish when the documented behavior is validated\"\\`\n\nLoop or stop-condition phrasing is a key workflow signal. When the user delegates a loop such as \\`do X until Y\\`, \\`repeat until\\`, \\`iterate until\\`, \\`review/fix until passing\\`, \\`run checks and fix until green\\`, or \\`keep going until done\\`, make the stop condition explicit in the Goal objective:\n\n\\`/workflow goal objective=\"Fix the flaky checkout test, adjust the smallest necessary code, and finish when the focused test passes three times\"\\`\n\nWhen a clearly delegated autonomous job benefits from a durable research-first pipeline with orchestration and iterative review, use \\`ralph\\`:\n\n\\`/workflow ralph prompt=\"Migrate the database layer to Drizzle\"\\`\n\nAdd \\`create_pr=true\\` only when you want the final pull-request stage and report after the review gate approves.\n\n## 4. Decide and land\n\nIf you used \\`goal\\`, the workflow already persisted receipts in a goal ledger and reviewer-gated completion. Use its final status — \\`complete\\`, \\`blocked\\`, or \\`needs_human\\` — plus the remaining-work report to decide whether to ship, unblock, or clarify. If you enabled \\`create_pr=true\\`, use its final pull-request report to decide whether to ship or iterate again.\n\nIf you used \\`ralph\\`, the workflow transformed the prompt into a research question, researched the codebase, delegated implementation through sub-agents, reviewed, and iterated. If you enabled \\`create_pr=true\\`, use its final pull-request report to decide whether to ship or iterate again.\n\nIf you implemented directly instead of using a workflow, you can still run:\n\n\\`/parallel-review current diff\\`\n\nAtomic will synthesize reviewer feedback and ask before applying fixes.\n\n─────────────────────────────────────────────────────────────────\n\nWhere to next:\n\n\\`/atomic workflows\\` — learn when to use workflows\n\\`/atomic overview\\` — quick refresh`;\n\nconst WORKFLOWS = `# Workflows primer\n\nA workflow is a TypeScript-defined pipeline exported from \\`workflow({...})\\`. It can run tasks, chains, parallel fan-out, human-in-the-loop prompts, background status, and model fallback chains.\n\nUse workflows for clearly delegated, well-defined autonomous jobs that are likely long-running/background-oriented or materially need durable stages, artifacts/checkpoints, resumability, HIL, gates, retries, or bounded loops. Keep interactive exploration inline and use bounded subagents when the parent should remain in control. Multiple steps, files, tests, validation, or parallelism alone do not require a workflow, but loop or stop-condition phrasing such as \\`do X until Y\\`, \\`repeat until\\`, \\`iterate until\\`, \\`review/fix until passing\\`, \\`run checks and fix until green\\`, or \\`keep going until done\\` is a key workflow signal when the user delegates execution.\n\nNamed workflows may be builtin, project, user, or package supplied, and direct task/tasks/chain modes cover one-off tracked shapes. When workflow execution fits, Atomic may always author a custom TypeScript \\`workflow({...})\\` inline with normal coding tools if that shape best achieves the task; it is not limited to installed workflows or direct modes. Atomic writes the definition, reloads it, and runs it.\n\n## Built-in workflows\n\n| Workflow | When to use | How to run |\n|---|---|---|\n| \\`deep-research-codebase\\` | broad repo or cross-cutting research before you decide what to change (for one area, use \\`/skill:research-codebase\\`; this indexes the whole repo) | \\`/workflow deep-research-codebase prompt=\"How do payment retries work end to end?\"\\` |\n| \\`goal\\` | autonomous work that benefits from a durable goal ledger, bounded worker turns, named validation, and reviewer-gated completion; add \\`create_pr=true\\` only for final PR handoff after approval | \\`/workflow goal objective=\"Update the CLI docs, include one usage example, and verify the docs build passes\"\\` |\n| \\`ralph\\` | autonomous work that benefits from a durable research-first pipeline, delegated implementation, and iterative review | \\`/workflow ralph prompt=\"Migrate the database layer to Drizzle\" create_pr=true\\` |\n| \\`open-claude-design\\` | frontend and product design work | \\`/workflow open-claude-design prompt=\"Refresh the settings page hierarchy\"\\` |\n\nUse \\`/workflow inputs <name>\\` to inspect the exact inputs in your environment.\n\nUse \\`/skill:research-codebase ...\\` when you want research on one subsystem, directory, or focused question. Use \\`/workflow deep-research-codebase ...\\` when the answer needs end-to-end tracing across many parts of the repo.\n\nIf you are drafting research, reviewer, or synthesis prompts for a workflow, use \\`/skill:prompt-engineer\\` first. It is a good fit when a stage prompt feels vague, overloaded, or underspecified.\n\n## What good workflow authoring looks like\n\nA good workflow request is explicit about stage purpose, model choice, handoff, and the decision each step must return.\n\nExample: ask Atomic in chat with something like this:\n\n~~~text\nCreate a reusable workflow called review-changes.\n\nIt should accept one required text input called target for a diff, PR summary, or review target.\n\nRun two independent review stages in parallel with fresh context:\n- one reviewer focused on correctness, regressions, and missing tests using openai-codex/gpt-5.5 at xhigh thinking\n- one reviewer focused on edge cases, maintainability, and hidden risks using anthropic/claude-opus-4-8 at xhigh thinking\n\nThen add an aggregate stage that consolidates both reviews, deduplicates overlap, keeps only evidence-backed issues, and separates blockers from optional suggestions using openai/gpt-5.5 at high thinking.\n\nFinally add an adjudicate stage using anthropic/claude-sonnet-4 at high thinking that decides what to fix now, what to defer, and what to reject. Return a short action list with rationale.\n\nThe workflow should return structured output with consolidated_review and decision fields.\n~~~\n\nWhy this is good:\n- it names the workflow and required input\n- it specifies which stages are parallel vs sequential\n- each stage has one job\n- it defines the handoff and final outputs\n- it calls out model choice and thinking level where that matters\n\n## Run and inspect\n\n\\`/workflow list\\`\n\n\\`/workflow inputs goal\\`\n\n\\`/workflow goal objective=\"Fix the settings form validation bug, add the focused test, and finish when invalid emails show the inline error without submitting\"\\`\n\n\\`/workflow inputs ralph\\`\n\n\\`/workflow ralph prompt=\"Migrate the database layer to Drizzle\" create_pr=true\\`\n\n\\`/workflow status\\`\n\n\\`/workflow connect <run-id>\\`\n\n\\`/workflow interrupt <run-id>\\`\n\n\\`/workflow resume <run-id>\\`\n\nWorkflows run as background tasks. Use F2 or \\`/workflow connect <run-id>\\` for the graph viewer. Human-in-the-loop prompts appear there, not as chat modals, and awaiting-input states do not wake the main chat agent. Completion and failure notices are steered back into the main chat; answers submitted in the workflow UI interrupt stale main-chat questions so the model does not ask again.\n\n## Author your own\n\nDescribe your workflow in plain chat — say what you want the workflow to accomplish, what inputs it should accept, what stages should run, and what final output or decision it should return. Atomic will use the workflow docs to scaffold a reusable definition under \\`.atomic/workflows/\\`, ask clarifying questions when stage purpose, models, or handoffs are ambiguous, and run \\`/workflow reload\\` so you can launch it immediately.\n\n─────────────────────────────────────────────────────────────────\n\nWhere to next:\n\n\\`/atomic example\\` — see workflows in a normal task flow\n\\`/atomic overview\\` — quick refresh`;\n\nconst GUIDE_SECTIONS = [\n {\n name: \"overview\",\n aliases: [],\n label: \"overview\",\n description: \"30-second overview\",\n render: () => OVERVIEW,\n },\n {\n name: \"workflows\",\n aliases: [\"workflow\"],\n label: \"workflows\",\n description: \"Workflow primer\",\n render: () => WORKFLOWS,\n },\n {\n name: \"example\",\n aliases: [\"examples\"],\n label: \"example\",\n description: \"Practical first workflow\",\n render: () => EXAMPLE,\n },\n {\n name: \"whats-new\",\n aliases: [\"what's new\", \"whats new\", \"news\", \"updates\", \"changelog\"],\n label: \"what's new\",\n description: \"Recent release notes\",\n render: readLatestStableChangelog,\n },\n] as const satisfies readonly {\n readonly name: string;\n readonly aliases: readonly string[];\n readonly label: string;\n readonly description: string;\n readonly render: (cwd: string) => string;\n}[];\n\ntype AtomicGuideSection = (typeof GUIDE_SECTIONS)[number];\ntype AtomicGuideSectionName = AtomicGuideSection[\"name\"];\n\nexport type AtomicGuideHelpChoice = AtomicGuideSection[\"label\"];\n\nexport type AtomicGuideMode = \"help\" | AtomicGuideSectionName;\n\nexport const ATOMIC_GUIDE_HELP_CHOICES: readonly AtomicGuideHelpChoice[] =\n GUIDE_SECTIONS.map((section) => section.label);\n\nconst GUIDE_SECTIONS_BY_NAME = new Map<\n AtomicGuideSectionName,\n AtomicGuideSection\n>(GUIDE_SECTIONS.map((section) => [section.name, section]));\nconst GUIDE_SECTIONS_BY_LABEL = new Map<string, AtomicGuideSection>(\n GUIDE_SECTIONS.map((section) => [section.label, section]),\n);\nconst GUIDE_SECTIONS_BY_INPUT = new Map<string, AtomicGuideSection>(\n GUIDE_SECTIONS.flatMap((section) =>\n [section.name, section.label, ...section.aliases].map(\n (input) => [input, section] as const,\n ),\n ),\n);\n\nexport function isAtomicGuideHelpChoice(\n choice: string,\n): choice is AtomicGuideHelpChoice {\n return GUIDE_SECTIONS_BY_LABEL.has(choice);\n}\n\nconst ATOMIC_GUIDE_TRAILING_PUNCTUATION = \"?!.,;:\";\n\nfunction stripTrailingAtomicGuidePunctuation(value: string): string {\n let end = value.length;\n while (\n end > 0 &&\n ATOMIC_GUIDE_TRAILING_PUNCTUATION.includes(value.charAt(end - 1))\n ) {\n end--;\n }\n return value.slice(0, end);\n}\n\nfunction getGuideSectionForChoice(\n choice: string,\n): AtomicGuideSection | undefined {\n return GUIDE_SECTIONS_BY_LABEL.get(choice);\n}\n\nfunction getGuideSectionForMode(\n mode: AtomicGuideSectionName,\n): AtomicGuideSection {\n const section = GUIDE_SECTIONS_BY_NAME.get(mode);\n if (!section) throw new Error(`Unknown Atomic guide section: ${mode}`);\n return section;\n}\n\nfunction getAtomicGuideHelpMenu(): string {\n const sectionHelp = GUIDE_SECTIONS.map(\n (section) => `- \\`${section.label}\\` — run \\`/atomic ${section.label}\\``,\n ).join(\"\\n\");\n return `# Atomic\\n\\nSelect where to start:\\n\\n${sectionHelp}`;\n}\n\nexport function normalizeAtomicGuideMode(args: string): AtomicGuideMode {\n const normalized = stripTrailingAtomicGuidePunctuation(\n args.trim().toLowerCase(),\n );\n if (!normalized) return \"help\";\n\n return GUIDE_SECTIONS_BY_INPUT.get(normalized)?.name ?? \"help\";\n}\n\nexport function getAtomicGuideArgumentCompletions(\n prefix: string,\n): AutocompleteItem[] | null {\n const query = prefix.trim().toLowerCase();\n const items = GUIDE_SECTIONS.map((section) => ({\n value: section.label,\n label: section.label,\n description: section.description,\n }));\n const filtered = query\n ? items.filter(\n (item) => item.value.startsWith(query) || item.label.startsWith(query),\n )\n : items;\n return filtered.length > 0 ? filtered : null;\n}\n\nfunction readLatestStableChangelog(cwd: string): string {\n const changelogPath = getChangelogPath();\n const stableSections = parseChangelog(changelogPath)\n .filter((entry) => entry.prerelease === null)\n .slice(0, 3)\n .map((entry) => entry.content.trim())\n .filter(Boolean);\n\n if (stableSections.length === 0) {\n return `# What's new\\n\\nNo stable release sections were found. Try \\`/changelog\\` for the interactive changelog viewer.\\n\\n─────────────────────────────────────────────────────────────────\\n\\nWhere to next:\\n\\n\\`/atomic example\\` — see a practical first workflow\\n\\`/atomic overview\\` — quick refresh`;\n }\n\n const relativePath = path.relative(cwd, changelogPath) || changelogPath;\n return `# What's new\\n\\n${stableSections.join(\"\\n\\n\")}\\n\\nSource: \\`${relativePath}\\`\\n\\n─────────────────────────────────────────────────────────────────\\n\\nWhere to next:\\n\\n\\`/atomic example\\` — see a practical first workflow\\n\\`/atomic overview\\` — quick refresh`;\n}\n\nexport function getAtomicGuideMessage(\n mode: AtomicGuideMode,\n cwd: string,\n): string {\n if (mode === \"help\") return getAtomicGuideHelpMenu();\n return getGuideSectionForMode(mode).render(cwd);\n}\n\nexport function atomicGuideModeForChoice(\n choice: AtomicGuideHelpChoice,\n): AtomicGuideMode {\n return getGuideSectionForChoice(choice)?.name ?? \"help\";\n}\n"]}
|
|
@@ -4,7 +4,7 @@ export const ATOMIC_GUIDE_COMMAND_NAME = "atomic";
|
|
|
4
4
|
export const ATOMIC_GUIDE_COMMAND_DESCRIPTION = "Atomic onboarding and help guide";
|
|
5
5
|
const OVERVIEW = `# Atomic overview
|
|
6
6
|
|
|
7
|
-
Atomic
|
|
7
|
+
Atomic supports a least-orchestration hierarchy: keep interactive, exploratory, conceptual, and conversation-led work inline; use bounded single, chain, or parallel subagents while the parent remains in control; and use workflows when the user clearly delegates a well-defined autonomous job that is likely long-running/background-oriented or materially needs durable stages, artifacts/checkpoints, resumability, HIL, gates, retries, or bounded loops. Multiple steps, files, tests, validation, or parallelism alone do not require a workflow. Loop or stop-condition phrasing such as \`do X until Y\`, \`repeat until\`, \`iterate until\`, \`review/fix until passing\`, \`run checks and fix until green\`, or \`keep going until done\` is a key workflow signal when the user delegates execution, because it defines control flow and a completion condition that should be tracked. When workflow execution fits, Atomic may always author a custom TypeScript \`workflow({...})\` inline with normal coding tools if that shape best achieves the task; it is not limited to installed workflows or direct modes. Named workflows can be builtin, project, user, or package supplied; direct task/tasks/chain modes cover one-off tracked shapes. Start Atomic in a project with \`atomic\`, then talk to it normally. Use \`@file\` to attach files, \`!command\` to run shell output through the model, and \`!!command\` to run shell output without adding it to context.
|
|
8
8
|
|
|
9
9
|
## Core session commands
|
|
10
10
|
|
|
@@ -22,9 +22,9 @@ Atomic turns one-off prompts into developer workflows: on-call debugging, repo r
|
|
|
22
22
|
|
|
23
23
|
| Goal | How to use |
|
|
24
24
|
|---|---|
|
|
25
|
-
| On-call / broken behavior |
|
|
26
|
-
| Research → spec → implementation |
|
|
27
|
-
| Testing / regression hardening |
|
|
25
|
+
| On-call / broken behavior | Reproduce and diagnose inline or with a debugger subagent, using bounded specialists when useful; choose \`goal\` only when a clearly delegated repair materially needs a durable ledger, bounded worker turns, or reviewer-gated completion |
|
|
26
|
+
| Research → spec → implementation | Use \`/skill:research-codebase\`, \`/skill:create-spec\`, and bounded subagents while the parent remains in control; choose a workflow only for a clearly delegated autonomous job with durable execution needs |
|
|
27
|
+
| Testing / regression hardening | Keep focused test/fix work inline or bounded. Loop or stop-condition wording is a key workflow signal when the user delegates execution; use \`goal\` when the run should track retries, evidence, convergence, and an explicit stop condition |
|
|
28
28
|
| Large repo discovery | Run \`/parallel codebase-locator "map the area" -> codebase-analyzer "trace the current flow" -> codebase-pattern-finder "find patterns" --bg\`, or \`/workflow deep-research-codebase\` for whole-repo synthesis |
|
|
29
29
|
| UI / product polish | Run \`/skill:impeccable\` for interface critique and refinement, or \`/workflow open-claude-design\` for generation + refinement loops |
|
|
30
30
|
|
|
@@ -33,8 +33,8 @@ Atomic turns one-off prompts into developer workflows: on-call debugging, repo r
|
|
|
33
33
|
| Workflow | When to use | How to run |
|
|
34
34
|
|---|---|---|
|
|
35
35
|
| \`deep-research-codebase\` | broad repo or cross-cutting research before you decide what to change (for one area, use \`/skill:research-codebase\`; this indexes the whole repo) | \`/workflow deep-research-codebase prompt="How do payment retries work end to end?"\` |
|
|
36
|
-
| \`goal\` |
|
|
37
|
-
| \`ralph\` |
|
|
36
|
+
| \`goal\` | autonomous work that benefits from a durable goal ledger, bounded worker turns, named validation, and reviewer-gated completion; add \`create_pr=true\` only for final PR handoff after approval | \`/workflow goal objective="Implement specs/<date>-<topic>.md, run focused tests, and validate the changed behavior"\` |
|
|
37
|
+
| \`ralph\` | autonomous work that benefits from a durable research-first pipeline, delegated implementation, and iterative review | \`/workflow ralph prompt="Migrate the database layer to Drizzle" create_pr=true\` |
|
|
38
38
|
| \`open-claude-design\` | UI and design-system work that benefits from generation and refinement loops | \`/workflow open-claude-design prompt="Refresh the settings page hierarchy"\` |
|
|
39
39
|
|
|
40
40
|
Use \`/workflow list\` to see what is available and \`/workflow inputs <name>\` to inspect inputs in your environment.
|
|
@@ -74,7 +74,7 @@ Where to next:
|
|
|
74
74
|
\`/atomic workflows\` — learn when to use workflows`;
|
|
75
75
|
const EXAMPLE = `# Practical example
|
|
76
76
|
|
|
77
|
-
This
|
|
77
|
+
This example shows a spec-driven development process whose clearly delegated autonomous implementation benefits from durable workflow execution. For interactive or conversation-led work, stay inline or use bounded subagents while the parent remains in control. Type the examples below into the Atomic TUI chat after starting \`atomic\` in your project.
|
|
78
78
|
|
|
79
79
|
## 1. Research what exists
|
|
80
80
|
|
|
@@ -98,17 +98,17 @@ Skip this if the implementation request is already precise.
|
|
|
98
98
|
|
|
99
99
|
## 3. Implement with review built in
|
|
100
100
|
|
|
101
|
-
|
|
101
|
+
Keep interactive or conversation-led implementation inline. Use bounded subagents when specialist delegation helps, and choose a workflow only when the user clearly delegates an autonomous job whose long-running/background nature or durable execution needs justify it; files, tests, and validation alone do not.
|
|
102
102
|
|
|
103
|
-
|
|
103
|
+
When the job needs a durable goal ledger, bounded worker turns, and reviewer-gated completion, use \`goal\`:
|
|
104
104
|
|
|
105
105
|
\`/workflow goal objective="Implement specs/<date>-<topic>.md, run focused tests, and finish when the documented behavior is validated"\`
|
|
106
106
|
|
|
107
|
-
|
|
107
|
+
Loop or stop-condition phrasing is a key workflow signal. When the user delegates a loop such as \`do X until Y\`, \`repeat until\`, \`iterate until\`, \`review/fix until passing\`, \`run checks and fix until green\`, or \`keep going until done\`, make the stop condition explicit in the Goal objective:
|
|
108
108
|
|
|
109
109
|
\`/workflow goal objective="Fix the flaky checkout test, adjust the smallest necessary code, and finish when the focused test passes three times"\`
|
|
110
110
|
|
|
111
|
-
|
|
111
|
+
When a clearly delegated autonomous job benefits from a durable research-first pipeline with orchestration and iterative review, use \`ralph\`:
|
|
112
112
|
|
|
113
113
|
\`/workflow ralph prompt="Migrate the database layer to Drizzle"\`
|
|
114
114
|
|
|
@@ -136,17 +136,17 @@ const WORKFLOWS = `# Workflows primer
|
|
|
136
136
|
|
|
137
137
|
A workflow is a TypeScript-defined pipeline exported from \`workflow({...})\`. It can run tasks, chains, parallel fan-out, human-in-the-loop prompts, background status, and model fallback chains.
|
|
138
138
|
|
|
139
|
-
Use workflows
|
|
139
|
+
Use workflows for clearly delegated, well-defined autonomous jobs that are likely long-running/background-oriented or materially need durable stages, artifacts/checkpoints, resumability, HIL, gates, retries, or bounded loops. Keep interactive exploration inline and use bounded subagents when the parent should remain in control. Multiple steps, files, tests, validation, or parallelism alone do not require a workflow, but loop or stop-condition phrasing such as \`do X until Y\`, \`repeat until\`, \`iterate until\`, \`review/fix until passing\`, \`run checks and fix until green\`, or \`keep going until done\` is a key workflow signal when the user delegates execution.
|
|
140
140
|
|
|
141
|
-
|
|
141
|
+
Named workflows may be builtin, project, user, or package supplied, and direct task/tasks/chain modes cover one-off tracked shapes. When workflow execution fits, Atomic may always author a custom TypeScript \`workflow({...})\` inline with normal coding tools if that shape best achieves the task; it is not limited to installed workflows or direct modes. Atomic writes the definition, reloads it, and runs it.
|
|
142
142
|
|
|
143
143
|
## Built-in workflows
|
|
144
144
|
|
|
145
145
|
| Workflow | When to use | How to run |
|
|
146
146
|
|---|---|---|
|
|
147
147
|
| \`deep-research-codebase\` | broad repo or cross-cutting research before you decide what to change (for one area, use \`/skill:research-codebase\`; this indexes the whole repo) | \`/workflow deep-research-codebase prompt="How do payment retries work end to end?"\` |
|
|
148
|
-
| \`goal\` |
|
|
149
|
-
| \`ralph\` |
|
|
148
|
+
| \`goal\` | autonomous work that benefits from a durable goal ledger, bounded worker turns, named validation, and reviewer-gated completion; add \`create_pr=true\` only for final PR handoff after approval | \`/workflow goal objective="Update the CLI docs, include one usage example, and verify the docs build passes"\` |
|
|
149
|
+
| \`ralph\` | autonomous work that benefits from a durable research-first pipeline, delegated implementation, and iterative review | \`/workflow ralph prompt="Migrate the database layer to Drizzle" create_pr=true\` |
|
|
150
150
|
| \`open-claude-design\` | frontend and product design work | \`/workflow open-claude-design prompt="Refresh the settings page hierarchy"\` |
|
|
151
151
|
|
|
152
152
|
Use \`/workflow inputs <name>\` to inspect the exact inputs in your environment.
|