@bastani/atomic 0.9.4-alpha.1 → 0.9.4-alpha.11
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 +109 -0
- package/dist/builtin/cursor/CHANGELOG.md +24 -0
- package/dist/builtin/cursor/package.json +4 -4
- package/dist/builtin/intercom/CHANGELOG.md +24 -0
- package/dist/builtin/intercom/package.json +2 -2
- package/dist/builtin/mcp/CHANGELOG.md +24 -0
- package/dist/builtin/mcp/package.json +4 -4
- package/dist/builtin/subagents/CHANGELOG.md +52 -0
- 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 +1 -1
- package/dist/builtin/subagents/agents/worker.md +2 -2
- package/dist/builtin/subagents/package.json +4 -4
- package/dist/builtin/subagents/src/runs/background/async-execution-chain.ts +11 -1
- package/dist/builtin/subagents/src/runs/background/async-execution-single.ts +11 -1
- package/dist/builtin/subagents/src/runs/background/async-execution-types.ts +2 -0
- package/dist/builtin/subagents/src/runs/background/subagent-runner-step.ts +27 -4
- package/dist/builtin/subagents/src/runs/background/subagent-runner-streaming.ts +25 -0
- 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 +1 -0
- package/dist/builtin/subagents/src/runs/foreground/chain-execution-types.ts +2 -0
- package/dist/builtin/subagents/src/runs/foreground/chain-execution.ts +3 -1
- package/dist/builtin/subagents/src/runs/foreground/execution-attempt.ts +22 -0
- package/dist/builtin/subagents/src/runs/foreground/execution-run-sync.ts +15 -5
- package/dist/builtin/subagents/src/runs/foreground/subagent-executor-async.ts +5 -1
- 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 +4 -1
- package/dist/builtin/subagents/src/runs/foreground/subagent-executor-single.ts +4 -1
- package/dist/builtin/subagents/src/runs/shared/attempt-watchdog.ts +126 -0
- package/dist/builtin/subagents/src/runs/shared/model-candidate-filter.ts +53 -0
- package/dist/builtin/subagents/src/runs/shared/model-fallback.ts +52 -53
- package/dist/builtin/subagents/src/runs/shared/parallel-utils.ts +2 -0
- package/dist/builtin/subagents/src/shared/model-info.ts +16 -0
- package/dist/builtin/subagents/src/shared/types-config.ts +2 -0
- package/dist/builtin/subagents/src/slash/slash-commands.ts +2 -2
- package/dist/builtin/subagents/src/tui/render-result-compact.ts +3 -2
- package/dist/builtin/subagents/src/tui/render-result.ts +3 -3
- package/dist/builtin/subagents/src/tui/render-widget-graph.ts +4 -3
- package/dist/builtin/subagents/src/tui/render-widget.ts +10 -4
- package/dist/builtin/web-access/CHANGELOG.md +24 -0
- package/dist/builtin/web-access/package.json +2 -2
- package/dist/builtin/workflows/CHANGELOG.md +54 -0
- package/dist/builtin/workflows/builtin/deep-research-codebase-utils.ts +24 -22
- package/dist/builtin/workflows/builtin/goal-runner.ts +12 -23
- package/dist/builtin/workflows/builtin/open-claude-design-runner.ts +4 -4
- package/dist/builtin/workflows/builtin/ralph-models.ts +53 -75
- package/dist/builtin/workflows/package.json +2 -2
- package/dist/builtin/workflows/src/runs/shared/model-fallback-failures.ts +59 -1
- package/dist/builtin/workflows/src/tui/keybindings-adapter.ts +4 -0
- package/dist/builtin/workflows/src/tui/overlay-adapter.ts +4 -0
- package/dist/builtin/workflows/src/tui/stage-chat-view-input.ts +12 -1
- package/dist/builtin/workflows/src/tui/stage-chat-view-state.ts +2 -0
- package/dist/builtin/workflows/src/tui/stage-chat-view-types.ts +6 -0
- package/dist/builtin/workflows/src/tui/stage-chat-view.ts +4 -0
- package/dist/builtin/workflows/src/tui/workflow-attach-pane-types.ts +4 -0
- package/dist/builtin/workflows/src/tui/workflow-attach-pane.ts +8 -9
- package/dist/bun/cli.d.ts.map +1 -1
- package/dist/bun/cli.js +3 -2
- package/dist/bun/cli.js.map +1 -1
- package/dist/cli/file-processor.d.ts.map +1 -1
- package/dist/cli/file-processor.js +13 -25
- package/dist/cli/file-processor.js.map +1 -1
- package/dist/cli.d.ts.map +1 -1
- package/dist/cli.js +15 -5
- package/dist/cli.js.map +1 -1
- package/dist/config.d.ts +10 -3
- package/dist/config.d.ts.map +1 -1
- package/dist/config.js +18 -1
- package/dist/config.js.map +1 -1
- package/dist/core/agent-session-auto-compaction.d.ts.map +1 -1
- package/dist/core/agent-session-auto-compaction.js +8 -1
- 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 +16 -8
- package/dist/core/agent-session-events.js.map +1 -1
- package/dist/core/agent-session-export.d.ts.map +1 -1
- package/dist/core/agent-session-export.js +4 -2
- package/dist/core/agent-session-export.js.map +1 -1
- package/dist/core/agent-session-extension-bindings.d.ts +5 -1
- package/dist/core/agent-session-extension-bindings.d.ts.map +1 -1
- package/dist/core/agent-session-extension-bindings.js +18 -7
- package/dist/core/agent-session-extension-bindings.js.map +1 -1
- package/dist/core/agent-session-methods.d.ts +13 -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 +2 -0
- package/dist/core/agent-session-prompt.d.ts.map +1 -1
- package/dist/core/agent-session-prompt.js +15 -2
- package/dist/core/agent-session-prompt.js.map +1 -1
- package/dist/core/agent-session-retry.d.ts +2 -0
- package/dist/core/agent-session-retry.d.ts.map +1 -1
- package/dist/core/agent-session-retry.js +66 -7
- package/dist/core/agent-session-retry.js.map +1 -1
- package/dist/core/agent-session-state.d.ts.map +1 -1
- package/dist/core/agent-session-state.js +2 -2
- package/dist/core/agent-session-state.js.map +1 -1
- package/dist/core/agent-session-tool-hooks.d.ts +7 -1
- package/dist/core/agent-session-tool-hooks.d.ts.map +1 -1
- package/dist/core/agent-session-tool-hooks.js +26 -4
- package/dist/core/agent-session-tool-hooks.js.map +1 -1
- package/dist/core/agent-session-tool-registry.d.ts.map +1 -1
- package/dist/core/agent-session-tool-registry.js +4 -0
- package/dist/core/agent-session-tool-registry.js.map +1 -1
- package/dist/core/agent-session-tree.d.ts.map +1 -1
- package/dist/core/agent-session-tree.js +3 -1
- package/dist/core/agent-session-tree.js.map +1 -1
- package/dist/core/agent-session-types.d.ts +4 -0
- package/dist/core/agent-session-types.d.ts.map +1 -1
- package/dist/core/agent-session-types.js.map +1 -1
- package/dist/core/agent-session.d.ts +5 -1
- package/dist/core/agent-session.d.ts.map +1 -1
- package/dist/core/agent-session.js +5 -0
- package/dist/core/agent-session.js.map +1 -1
- package/dist/core/async/format.d.ts +3 -0
- package/dist/core/async/format.d.ts.map +1 -0
- package/dist/core/async/format.js +50 -0
- package/dist/core/async/format.js.map +1 -0
- package/dist/core/async/job-manager.d.ts +39 -0
- package/dist/core/async/job-manager.d.ts.map +1 -0
- package/dist/core/async/job-manager.js +254 -0
- package/dist/core/async/job-manager.js.map +1 -0
- package/dist/core/async/session-manager.d.ts +18 -0
- package/dist/core/async/session-manager.d.ts.map +1 -0
- package/dist/core/async/session-manager.js +61 -0
- package/dist/core/async/session-manager.js.map +1 -0
- package/dist/core/async/types.d.ts +23 -0
- package/dist/core/async/types.d.ts.map +1 -0
- package/dist/core/async/types.js +2 -0
- package/dist/core/async/types.js.map +1 -0
- package/dist/core/copilot-model-catalog.d.ts +38 -74
- package/dist/core/copilot-model-catalog.d.ts.map +1 -1
- package/dist/core/copilot-model-catalog.js +177 -68
- package/dist/core/copilot-model-catalog.js.map +1 -1
- package/dist/core/copilot-model-static-fallbacks.d.ts +43 -0
- package/dist/core/copilot-model-static-fallbacks.d.ts.map +1 -0
- package/dist/core/copilot-model-static-fallbacks.js +50 -0
- package/dist/core/copilot-model-static-fallbacks.js.map +1 -0
- package/dist/core/copilot-model-synthesis.d.ts +10 -0
- package/dist/core/copilot-model-synthesis.d.ts.map +1 -0
- package/dist/core/copilot-model-synthesis.js +89 -0
- package/dist/core/copilot-model-synthesis.js.map +1 -0
- package/dist/core/extensions/api-types.d.ts +2 -1
- package/dist/core/extensions/api-types.d.ts.map +1 -1
- package/dist/core/extensions/api-types.js.map +1 -1
- package/dist/core/extensions/index.d.ts +1 -1
- package/dist/core/extensions/index.d.ts.map +1 -1
- package/dist/core/extensions/index.js.map +1 -1
- package/dist/core/extensions/loader-core.d.ts.map +1 -1
- package/dist/core/extensions/loader-core.js +3 -3
- package/dist/core/extensions/loader-core.js.map +1 -1
- package/dist/core/extensions/loader-virtual-modules.d.ts +11 -0
- package/dist/core/extensions/loader-virtual-modules.d.ts.map +1 -1
- package/dist/core/extensions/loader-virtual-modules.js +79 -11
- package/dist/core/extensions/loader-virtual-modules.js.map +1 -1
- package/dist/core/extensions/session-events.d.ts +7 -1
- package/dist/core/extensions/session-events.d.ts.map +1 -1
- package/dist/core/extensions/session-events.js.map +1 -1
- package/dist/core/http-dispatcher.d.ts +2 -0
- package/dist/core/http-dispatcher.d.ts.map +1 -1
- package/dist/core/http-dispatcher.js +38 -5
- package/dist/core/http-dispatcher.js.map +1 -1
- package/dist/core/model-registry-builtins.d.ts.map +1 -1
- package/dist/core/model-registry-builtins.js +40 -6
- package/dist/core/model-registry-builtins.js.map +1 -1
- package/dist/core/model-registry.d.ts.map +1 -1
- package/dist/core/model-registry.js +4 -3
- package/dist/core/model-registry.js.map +1 -1
- package/dist/core/model-resolver-defaults.d.ts.map +1 -1
- package/dist/core/model-resolver-defaults.js +1 -1
- package/dist/core/model-resolver-defaults.js.map +1 -1
- package/dist/core/resource-loader-reload.d.ts.map +1 -1
- package/dist/core/resource-loader-reload.js +6 -3
- package/dist/core/resource-loader-reload.js.map +1 -1
- package/dist/core/resource-loader-types.d.ts +6 -0
- package/dist/core/resource-loader-types.d.ts.map +1 -1
- package/dist/core/resource-loader-types.js.map +1 -1
- package/dist/core/session-manager-core.d.ts +2 -12
- package/dist/core/session-manager-core.d.ts.map +1 -1
- package/dist/core/session-manager-core.js +8 -16
- package/dist/core/session-manager-core.js.map +1 -1
- package/dist/core/settings-manager-resource-accessors.d.ts +1 -0
- package/dist/core/settings-manager-resource-accessors.d.ts.map +1 -1
- package/dist/core/settings-manager-resource-accessors.js +11 -0
- package/dist/core/settings-manager-resource-accessors.js.map +1 -1
- package/dist/core/settings-manager-ui-accessors.d.ts +2 -0
- package/dist/core/settings-manager-ui-accessors.d.ts.map +1 -1
- package/dist/core/settings-manager-ui-accessors.js +9 -0
- package/dist/core/settings-manager-ui-accessors.js.map +1 -1
- package/dist/core/settings-types.d.ts +2 -0
- package/dist/core/settings-types.d.ts.map +1 -1
- package/dist/core/settings-types.js.map +1 -1
- package/dist/core/timings.d.ts +7 -5
- package/dist/core/timings.d.ts.map +1 -1
- package/dist/core/timings.js +42 -24
- package/dist/core/timings.js.map +1 -1
- package/dist/core/tools/bash-async-execution.d.ts +25 -0
- package/dist/core/tools/bash-async-execution.d.ts.map +1 -0
- package/dist/core/tools/bash-async-execution.js +71 -0
- package/dist/core/tools/bash-async-execution.js.map +1 -0
- package/dist/core/tools/bash-async-jobs.d.ts +10 -0
- package/dist/core/tools/bash-async-jobs.d.ts.map +1 -1
- package/dist/core/tools/bash-async-jobs.js +18 -2
- package/dist/core/tools/bash-async-jobs.js.map +1 -1
- package/dist/core/tools/bash-async-output.d.ts +3 -1
- package/dist/core/tools/bash-async-output.d.ts.map +1 -1
- package/dist/core/tools/bash-async-output.js +4 -1
- package/dist/core/tools/bash-async-output.js.map +1 -1
- package/dist/core/tools/bash-pty-native.d.ts.map +1 -1
- package/dist/core/tools/bash-pty-native.js +2 -2
- package/dist/core/tools/bash-pty-native.js.map +1 -1
- package/dist/core/tools/bash.d.ts +10 -4
- package/dist/core/tools/bash.d.ts.map +1 -1
- package/dist/core/tools/bash.js +20 -38
- package/dist/core/tools/bash.js.map +1 -1
- package/dist/core/tools/read-selectors.d.ts.map +1 -1
- package/dist/core/tools/read-selectors.js +19 -1
- package/dist/core/tools/read-selectors.js.map +1 -1
- package/dist/core/tools/read.d.ts.map +1 -1
- package/dist/core/tools/read.js +12 -23
- package/dist/core/tools/read.js.map +1 -1
- package/dist/core/tools/search-native.d.ts.map +1 -1
- package/dist/core/tools/search-native.js +2 -2
- package/dist/core/tools/search-native.js.map +1 -1
- package/dist/index-extensions.d.ts +1 -1
- package/dist/index-extensions.d.ts.map +1 -1
- package/dist/index-extensions.js.map +1 -1
- package/dist/index.d.ts +1 -1
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js.map +1 -1
- package/dist/main-session.d.ts.map +1 -1
- package/dist/main-session.js +14 -5
- package/dist/main-session.js.map +1 -1
- package/dist/main.d.ts.map +1 -1
- package/dist/main.js +56 -32
- package/dist/main.js.map +1 -1
- package/dist/modes/interactive/components/assistant-message.d.ts +3 -1
- package/dist/modes/interactive/components/assistant-message.d.ts.map +1 -1
- package/dist/modes/interactive/components/assistant-message.js +22 -15
- package/dist/modes/interactive/components/assistant-message.js.map +1 -1
- package/dist/modes/interactive/components/chat-message-renderer.d.ts +1 -0
- package/dist/modes/interactive/components/chat-message-renderer.d.ts.map +1 -1
- package/dist/modes/interactive/components/chat-message-renderer.js +5 -5
- package/dist/modes/interactive/components/chat-message-renderer.js.map +1 -1
- package/dist/modes/interactive/components/chat-session-host-events.d.ts.map +1 -1
- package/dist/modes/interactive/components/chat-session-host-events.js +8 -0
- package/dist/modes/interactive/components/chat-session-host-events.js.map +1 -1
- package/dist/modes/interactive/components/chat-session-host-rendering.d.ts.map +1 -1
- package/dist/modes/interactive/components/chat-session-host-rendering.js +1 -0
- package/dist/modes/interactive/components/chat-session-host-rendering.js.map +1 -1
- package/dist/modes/interactive/components/user-message.d.ts +6 -2
- package/dist/modes/interactive/components/user-message.d.ts.map +1 -1
- package/dist/modes/interactive/components/user-message.js +16 -5
- package/dist/modes/interactive/components/user-message.js.map +1 -1
- package/dist/modes/interactive/interactive-agent-events.d.ts.map +1 -1
- package/dist/modes/interactive/interactive-agent-events.js +6 -1
- package/dist/modes/interactive/interactive-agent-events.js.map +1 -1
- package/dist/modes/interactive/interactive-deferred-startup.d.ts +2 -0
- package/dist/modes/interactive/interactive-deferred-startup.d.ts.map +1 -0
- package/dist/modes/interactive/interactive-deferred-startup.js +59 -0
- package/dist/modes/interactive/interactive-deferred-startup.js.map +1 -0
- package/dist/modes/interactive/interactive-editor-actions.d.ts.map +1 -1
- package/dist/modes/interactive/interactive-editor-actions.js +1 -0
- package/dist/modes/interactive/interactive-editor-actions.js.map +1 -1
- package/dist/modes/interactive/interactive-extension-context.d.ts.map +1 -1
- package/dist/modes/interactive/interactive-extension-context.js +1 -0
- package/dist/modes/interactive/interactive-extension-context.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 +6 -0
- package/dist/modes/interactive/interactive-mode-base.js.map +1 -1
- package/dist/modes/interactive/interactive-mode-deps.d.ts +1 -1
- package/dist/modes/interactive/interactive-mode-deps.d.ts.map +1 -1
- package/dist/modes/interactive/interactive-mode-deps.js +1 -1
- package/dist/modes/interactive/interactive-mode-deps.js.map +1 -1
- package/dist/modes/interactive/interactive-mode-surface.d.ts +2 -0
- 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-mode-types.d.ts +2 -0
- package/dist/modes/interactive/interactive-mode-types.d.ts.map +1 -1
- package/dist/modes/interactive/interactive-mode-types.js.map +1 -1
- package/dist/modes/interactive/interactive-mode.d.ts +1 -0
- package/dist/modes/interactive/interactive-mode.d.ts.map +1 -1
- package/dist/modes/interactive/interactive-mode.js +1 -0
- package/dist/modes/interactive/interactive-mode.js.map +1 -1
- package/dist/modes/interactive/interactive-model-routing.d.ts.map +1 -1
- package/dist/modes/interactive/interactive-model-routing.js +2 -4
- package/dist/modes/interactive/interactive-model-routing.js.map +1 -1
- package/dist/modes/interactive/interactive-render-chat.d.ts.map +1 -1
- package/dist/modes/interactive/interactive-render-chat.js +4 -3
- package/dist/modes/interactive/interactive-render-chat.js.map +1 -1
- package/dist/modes/interactive/interactive-session-runtime.d.ts.map +1 -1
- package/dist/modes/interactive/interactive-session-runtime.js +5 -2
- package/dist/modes/interactive/interactive-session-runtime.js.map +1 -1
- package/dist/modes/interactive/interactive-startup.d.ts.map +1 -1
- package/dist/modes/interactive/interactive-startup.js +11 -1
- package/dist/modes/interactive/interactive-startup.js.map +1 -1
- package/dist/modes/rpc/rpc-client.d.ts +28 -51
- package/dist/modes/rpc/rpc-client.d.ts.map +1 -1
- package/dist/modes/rpc/rpc-client.js +27 -51
- package/dist/modes/rpc/rpc-client.js.map +1 -1
- package/dist/modes/rpc/rpc-command-handler.d.ts.map +1 -1
- package/dist/modes/rpc/rpc-command-handler.js +19 -0
- package/dist/modes/rpc/rpc-command-handler.js.map +1 -1
- package/dist/modes/rpc/rpc-types.d.ts +26 -0
- package/dist/modes/rpc/rpc-types.d.ts.map +1 -1
- package/dist/modes/rpc/rpc-types.js.map +1 -1
- package/dist/rpc-entry.d.ts +3 -0
- package/dist/rpc-entry.d.ts.map +1 -0
- package/dist/rpc-entry.js +12 -0
- package/dist/rpc-entry.js.map +1 -0
- package/dist/utils/image-convert.d.ts +1 -0
- package/dist/utils/image-convert.d.ts.map +1 -1
- package/dist/utils/image-convert.js +21 -15
- package/dist/utils/image-convert.js.map +1 -1
- package/dist/utils/image-process.d.ts +18 -0
- package/dist/utils/image-process.d.ts.map +1 -0
- package/dist/utils/image-process.js +83 -0
- package/dist/utils/image-process.js.map +1 -0
- package/dist/utils/mime.d.ts.map +1 -1
- package/dist/utils/mime.js +41 -0
- package/dist/utils/mime.js.map +1 -1
- package/dist/utils/module-require.d.ts +11 -0
- package/dist/utils/module-require.d.ts.map +1 -0
- package/dist/utils/module-require.js +16 -0
- package/dist/utils/module-require.js.map +1 -0
- package/docs/compaction.md +2 -0
- package/docs/development.md +10 -0
- package/docs/extensions.md +11 -0
- package/docs/models.md +3 -3
- package/docs/providers.md +2 -1
- package/docs/rpc.md +60 -2
- package/docs/sdk.md +1 -1
- package/docs/settings.md +4 -1
- package/docs/subagents.md +6 -0
- package/docs/tools.md +4 -2
- package/docs/workflows.md +4 -2
- package/npm-shrinkwrap.json +138 -171
- package/package.json +19 -12
|
@@ -1,27 +1,42 @@
|
|
|
1
1
|
import { reviewDecisionSchema } from "./ralph-core.js";
|
|
2
2
|
|
|
3
|
+
// Model chains are curated from Atomic's agentic-coding benchmark
|
|
4
|
+
// (pass@1 / avg $ per task, 2026-07-02):
|
|
5
|
+
// - Placement principle: REVIEWERS get best-in-class verification quality
|
|
6
|
+
// (fable-5:xhigh 70%/$13.41 leads reviewer-A and the goal reviewer);
|
|
7
|
+
// EVERY OTHER stage gets the best measured performance-per-dollar
|
|
8
|
+
// (gpt-5.5:xhigh 67%/$7.23 for hard stages, gpt-5.5:medium 54%/$2.75 for
|
|
9
|
+
// workhorse stages, gpt-5.5:low $1.20 for retrieval).
|
|
10
|
+
// - Pareto frontier: gpt-5.5 low ($1.20/27%) → gpt-5.5 medium ($2.75/54%) →
|
|
11
|
+
// fable-5 low ($3.76/60%) → gpt-5.5 high ($5.10/64%) → fable-5 medium
|
|
12
|
+
// ($6.09/65%) → gpt-5.5 xhigh ($7.23/67%) → fable-5 high ($9.18/69%) →
|
|
13
|
+
// fable-5 xhigh ($13.41/70%).
|
|
14
|
+
// - Dropped as strictly dominated: claude-sonnet-5 (40-54% at $4-26, up to
|
|
15
|
+
// 268 steps), claude-sonnet-4.6 (30%/$5.52), gemini-3.1-pro (12%/$9.48),
|
|
16
|
+
// gemini-3.5-flash (37%/$7.34, 276k output tokens).
|
|
17
|
+
// - claude-opus-4.8 rides at :high — its value point (52%/$4.28); :xhigh
|
|
18
|
+
// doubles the cost for +2pts.
|
|
19
|
+
// - glm-5.2 is reviewer-C's diversity primary only (third model family
|
|
20
|
+
// decorrelates review errors); elsewhere it is a budget fallback. Note:
|
|
21
|
+
// GLM-5.2 has only two real reasoning tiers — its thinkingLevelMap collapses
|
|
22
|
+
// minimal/low/medium/high to "high" and xhigh to "max" — so chains only use
|
|
23
|
+
// :high (budget tier, 36%/$2.84) or :xhigh (best tier, 44%/$3.92); the
|
|
24
|
+
// openrouter/z-ai mirror maps :xhigh exclusively, so it is always :xhigh.
|
|
25
|
+
|
|
3
26
|
export const promptEngineerModelConfig = {
|
|
4
|
-
model: "
|
|
27
|
+
model: "openai-codex/gpt-5.5:xhigh",
|
|
5
28
|
fallbackModels: [
|
|
6
|
-
"openai-codex/gpt-5.5:xhigh",
|
|
7
29
|
"github-copilot/gpt-5.5:xhigh",
|
|
8
30
|
"openai/gpt-5.5:xhigh",
|
|
9
|
-
"
|
|
10
|
-
"
|
|
31
|
+
"anthropic/claude-fable-5:xhigh",
|
|
32
|
+
"github-copilot/claude-opus-4.8 (1m):high",
|
|
33
|
+
"anthropic/claude-opus-4-8:high",
|
|
11
34
|
"zai/glm-5.2:xhigh",
|
|
12
35
|
"zai-coding-cn/glm-5.2:xhigh",
|
|
13
|
-
"github-copilot/gemini-3.5-flash (1m):high",
|
|
14
|
-
"google/gemini-3.5-flash:high",
|
|
15
|
-
"google-vertex/gemini-3.5-flash:high",
|
|
16
|
-
"github-copilot/gemini-3.1-pro-preview (1m):high",
|
|
17
|
-
"google/gemini-3.1-pro-preview:high",
|
|
18
|
-
"google-vertex/gemini-3.1-pro-preview:high",
|
|
19
|
-
"openrouter/anthropic/claude-fable-5:xhigh",
|
|
20
36
|
"openrouter/openai/gpt-5.5:xhigh",
|
|
21
|
-
"openrouter/anthropic/claude-
|
|
22
|
-
"openrouter/
|
|
23
|
-
"openrouter/
|
|
24
|
-
"openrouter/google/gemini-3.1-pro-preview:high"
|
|
37
|
+
"openrouter/anthropic/claude-fable-5:xhigh",
|
|
38
|
+
"openrouter/anthropic/claude-opus-4-8:high",
|
|
39
|
+
"openrouter/z-ai/glm-5.2:xhigh"
|
|
25
40
|
],
|
|
26
41
|
excludedTools: ["ask_user_question"],
|
|
27
42
|
};
|
|
@@ -31,21 +46,15 @@ export const researchModelConfig = {
|
|
|
31
46
|
fallbackModels: [
|
|
32
47
|
"github-copilot/gpt-5.5:medium",
|
|
33
48
|
"openai/gpt-5.5:medium",
|
|
49
|
+
"anthropic/claude-fable-5:low",
|
|
34
50
|
"github-copilot/claude-opus-4.8 (1m):medium",
|
|
35
51
|
"anthropic/claude-opus-4-8:medium",
|
|
36
|
-
"zai/glm-5.2:
|
|
37
|
-
"zai-coding-cn/glm-5.2:
|
|
38
|
-
"github-copilot/gemini-3.5-flash (1m):medium",
|
|
39
|
-
"google/gemini-3.5-flash:medium",
|
|
40
|
-
"google-vertex/gemini-3.5-flash:medium",
|
|
41
|
-
"github-copilot/gemini-3.1-pro-preview (1m):medium",
|
|
42
|
-
"google/gemini-3.1-pro-preview:medium",
|
|
43
|
-
"google-vertex/gemini-3.1-pro-preview:medium",
|
|
52
|
+
"zai/glm-5.2:high",
|
|
53
|
+
"zai-coding-cn/glm-5.2:high",
|
|
44
54
|
"openrouter/openai/gpt-5.5:medium",
|
|
55
|
+
"openrouter/anthropic/claude-fable-5:low",
|
|
45
56
|
"openrouter/anthropic/claude-opus-4-8:medium",
|
|
46
|
-
"openrouter/z-ai/glm-5.2:
|
|
47
|
-
"openrouter/google/gemini-3.5-flash:medium",
|
|
48
|
-
"openrouter/google/gemini-3.1-pro-preview:medium"
|
|
57
|
+
"openrouter/z-ai/glm-5.2:xhigh"
|
|
49
58
|
],
|
|
50
59
|
excludedTools: ["ask_user_question"],
|
|
51
60
|
};
|
|
@@ -55,21 +64,15 @@ export const orchestratorModelConfig = {
|
|
|
55
64
|
fallbackModels: [
|
|
56
65
|
"github-copilot/gpt-5.5:medium",
|
|
57
66
|
"openai/gpt-5.5:medium",
|
|
67
|
+
"anthropic/claude-fable-5:low",
|
|
58
68
|
"github-copilot/claude-opus-4.8 (1m):medium",
|
|
59
69
|
"anthropic/claude-opus-4-8:medium",
|
|
60
|
-
"zai/glm-5.2:
|
|
61
|
-
"zai-coding-cn/glm-5.2:
|
|
62
|
-
"github-copilot/gemini-3.5-flash (1m):medium",
|
|
63
|
-
"google/gemini-3.5-flash:medium",
|
|
64
|
-
"google-vertex/gemini-3.5-flash:medium",
|
|
65
|
-
"github-copilot/gemini-3.1-pro-preview (1m):medium",
|
|
66
|
-
"google/gemini-3.1-pro-preview:medium",
|
|
67
|
-
"google-vertex/gemini-3.1-pro-preview:medium",
|
|
70
|
+
"zai/glm-5.2:high",
|
|
71
|
+
"zai-coding-cn/glm-5.2:high",
|
|
68
72
|
"openrouter/openai/gpt-5.5:medium",
|
|
73
|
+
"openrouter/anthropic/claude-fable-5:low",
|
|
69
74
|
"openrouter/anthropic/claude-opus-4-8:medium",
|
|
70
|
-
"openrouter/z-ai/glm-5.2:
|
|
71
|
-
"openrouter/google/gemini-3.5-flash:medium",
|
|
72
|
-
"openrouter/google/gemini-3.1-pro-preview:medium"
|
|
75
|
+
"openrouter/z-ai/glm-5.2:xhigh"
|
|
73
76
|
],
|
|
74
77
|
excludedTools: ["ask_user_question"],
|
|
75
78
|
};
|
|
@@ -77,25 +80,17 @@ export const orchestratorModelConfig = {
|
|
|
77
80
|
export const reviewerAModelConfig = {
|
|
78
81
|
model: "anthropic/claude-fable-5:xhigh",
|
|
79
82
|
fallbackModels: [
|
|
80
|
-
"github-copilot/claude-opus-4.8 (1m):xhigh",
|
|
81
|
-
"anthropic/claude-opus-4-8:xhigh",
|
|
82
83
|
"openai-codex/gpt-5.5:xhigh",
|
|
83
84
|
"github-copilot/gpt-5.5:xhigh",
|
|
84
85
|
"openai/gpt-5.5:xhigh",
|
|
86
|
+
"github-copilot/claude-opus-4.8 (1m):high",
|
|
87
|
+
"anthropic/claude-opus-4-8:high",
|
|
85
88
|
"zai/glm-5.2:xhigh",
|
|
86
89
|
"zai-coding-cn/glm-5.2:xhigh",
|
|
87
|
-
"github-copilot/gemini-3.5-flash (1m):high",
|
|
88
|
-
"google/gemini-3.5-flash:high",
|
|
89
|
-
"google-vertex/gemini-3.5-flash:high",
|
|
90
|
-
"github-copilot/gemini-3.1-pro-preview (1m):high",
|
|
91
|
-
"google/gemini-3.1-pro-preview:high",
|
|
92
|
-
"google-vertex/gemini-3.1-pro-preview:high",
|
|
93
90
|
"openrouter/anthropic/claude-fable-5:xhigh",
|
|
94
|
-
"openrouter/anthropic/claude-opus-4-8:xhigh",
|
|
95
91
|
"openrouter/openai/gpt-5.5:xhigh",
|
|
96
|
-
"openrouter/
|
|
97
|
-
"openrouter/
|
|
98
|
-
"openrouter/google/gemini-3.1-pro-preview:high"
|
|
92
|
+
"openrouter/anthropic/claude-opus-4-8:high",
|
|
93
|
+
"openrouter/z-ai/glm-5.2:xhigh"
|
|
99
94
|
],
|
|
100
95
|
excludedTools: ["ask_user_question"],
|
|
101
96
|
schema: reviewDecisionSchema,
|
|
@@ -107,22 +102,14 @@ export const reviewerBModelConfig = {
|
|
|
107
102
|
"github-copilot/gpt-5.5:xhigh",
|
|
108
103
|
"openai/gpt-5.5:xhigh",
|
|
109
104
|
"anthropic/claude-fable-5:xhigh",
|
|
110
|
-
"github-copilot/claude-opus-4.8 (1m):
|
|
111
|
-
"anthropic/claude-opus-4-8:
|
|
105
|
+
"github-copilot/claude-opus-4.8 (1m):high",
|
|
106
|
+
"anthropic/claude-opus-4-8:high",
|
|
112
107
|
"zai/glm-5.2:xhigh",
|
|
113
108
|
"zai-coding-cn/glm-5.2:xhigh",
|
|
114
|
-
"github-copilot/gemini-3.5-flash (1m):high",
|
|
115
|
-
"google/gemini-3.5-flash:high",
|
|
116
|
-
"google-vertex/gemini-3.5-flash:high",
|
|
117
|
-
"github-copilot/gemini-3.1-pro-preview (1m):high",
|
|
118
|
-
"google/gemini-3.1-pro-preview:high",
|
|
119
|
-
"google-vertex/gemini-3.1-pro-preview:high",
|
|
120
109
|
"openrouter/openai/gpt-5.5:xhigh",
|
|
121
110
|
"openrouter/anthropic/claude-fable-5:xhigh",
|
|
122
|
-
"openrouter/anthropic/claude-opus-4-8:
|
|
123
|
-
"openrouter/z-ai/glm-5.2:xhigh"
|
|
124
|
-
"openrouter/google/gemini-3.5-flash:high",
|
|
125
|
-
"openrouter/google/gemini-3.1-pro-preview:high"
|
|
111
|
+
"openrouter/anthropic/claude-opus-4-8:high",
|
|
112
|
+
"openrouter/z-ai/glm-5.2:xhigh"
|
|
126
113
|
],
|
|
127
114
|
excludedTools: ["ask_user_question"],
|
|
128
115
|
schema: reviewDecisionSchema,
|
|
@@ -132,26 +119,17 @@ export const reviewerCModelConfig = {
|
|
|
132
119
|
model: "zai/glm-5.2:xhigh",
|
|
133
120
|
fallbackModels: [
|
|
134
121
|
"zai-coding-cn/glm-5.2:xhigh",
|
|
135
|
-
"
|
|
136
|
-
"google/gemini-3.5-flash:high",
|
|
137
|
-
"google-vertex/gemini-3.5-flash:high",
|
|
138
|
-
"github-copilot/gemini-3.1-pro-preview (1m):high",
|
|
139
|
-
"google/gemini-3.1-pro-preview:high",
|
|
140
|
-
"google-vertex/gemini-3.1-pro-preview:high",
|
|
122
|
+
"openrouter/z-ai/glm-5.2:xhigh",
|
|
141
123
|
"openai-codex/gpt-5.5:xhigh",
|
|
142
124
|
"github-copilot/gpt-5.5:xhigh",
|
|
143
125
|
"openai/gpt-5.5:xhigh",
|
|
144
126
|
"anthropic/claude-fable-5:xhigh",
|
|
145
|
-
"github-copilot/claude-opus-4.8 (1m):
|
|
146
|
-
"anthropic/claude-opus-4-8:
|
|
147
|
-
"openrouter/anthropic/claude-fable-5:xhigh",
|
|
148
|
-
"openrouter/anthropic/claude-opus-4-8:xhigh",
|
|
127
|
+
"github-copilot/claude-opus-4.8 (1m):high",
|
|
128
|
+
"anthropic/claude-opus-4-8:high",
|
|
149
129
|
"openrouter/openai/gpt-5.5:xhigh",
|
|
150
|
-
"openrouter/
|
|
151
|
-
"openrouter/
|
|
152
|
-
"openrouter/google/gemini-3.1-pro-preview:high"
|
|
130
|
+
"openrouter/anthropic/claude-fable-5:xhigh",
|
|
131
|
+
"openrouter/anthropic/claude-opus-4-8:high"
|
|
153
132
|
],
|
|
154
133
|
excludedTools: ["ask_user_question"],
|
|
155
134
|
schema: reviewDecisionSchema,
|
|
156
135
|
};
|
|
157
|
-
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@bastani/workflows",
|
|
3
|
-
"version": "0.9.4-alpha.
|
|
3
|
+
"version": "0.9.4-alpha.11",
|
|
4
4
|
"private": true,
|
|
5
5
|
"description": "Atomic extension for multi-stage workflow authoring and execution.",
|
|
6
6
|
"contributors": [
|
|
@@ -83,7 +83,7 @@
|
|
|
83
83
|
},
|
|
84
84
|
"peerDependencies": {
|
|
85
85
|
"@bastani/atomic": "*",
|
|
86
|
-
"@earendil-works/pi-tui": "^0.80.
|
|
86
|
+
"@earendil-works/pi-tui": "^0.80.3"
|
|
87
87
|
},
|
|
88
88
|
"peerDependenciesMeta": {
|
|
89
89
|
"@bastani/atomic": {
|
|
@@ -49,7 +49,9 @@ export type ModelFallbackFailureKind =
|
|
|
49
49
|
| "rate_limit"
|
|
50
50
|
| "provider_unavailable"
|
|
51
51
|
| "network_timeout"
|
|
52
|
+
| "transport_error"
|
|
52
53
|
| "model_unavailable"
|
|
54
|
+
| "request_incompatible"
|
|
53
55
|
| "cancelled"
|
|
54
56
|
| "task_failure"
|
|
55
57
|
| "unknown";
|
|
@@ -76,7 +78,9 @@ const FALLBACKABLE_FAILURE_KINDS: ReadonlySet<ModelFallbackFailureKind> = new Se
|
|
|
76
78
|
"rate_limit",
|
|
77
79
|
"provider_unavailable",
|
|
78
80
|
"network_timeout",
|
|
81
|
+
"transport_error",
|
|
79
82
|
"model_unavailable",
|
|
83
|
+
"request_incompatible",
|
|
80
84
|
]);
|
|
81
85
|
|
|
82
86
|
function asRecord(value: unknown): Record<string, unknown> | undefined {
|
|
@@ -155,6 +159,9 @@ function normalizeCode(value: string | number | undefined): string | undefined {
|
|
|
155
159
|
|
|
156
160
|
function kindFromStatus(status: number | undefined): ModelFallbackFailureKind | undefined {
|
|
157
161
|
switch (status) {
|
|
162
|
+
case 400:
|
|
163
|
+
case 413: case 422:
|
|
164
|
+
return "request_incompatible";
|
|
158
165
|
case 401:
|
|
159
166
|
case 403:
|
|
160
167
|
return "auth_on_candidate_provider";
|
|
@@ -191,6 +198,15 @@ function refusalKindFromCode(code: string | number | undefined): ModelFallbackFa
|
|
|
191
198
|
}
|
|
192
199
|
}
|
|
193
200
|
|
|
201
|
+
const REQUEST_INCOMPATIBLE_CODES: ReadonlySet<string> = new Set([
|
|
202
|
+
"invalid_request", "invalid_request_error", "bad_request", "context_length_exceeded",
|
|
203
|
+
"request_too_large", "too_large", "request_entity_too_large", "max_tokens",
|
|
204
|
+
"max_context_length", "context_window_exceeded",
|
|
205
|
+
]);
|
|
206
|
+
function requestIncompatibleKindFromCode(code: string | number | undefined): ModelFallbackFailureKind | undefined {
|
|
207
|
+
const normalizedCode = normalizeCode(code);
|
|
208
|
+
return normalizedCode !== undefined && REQUEST_INCOMPATIBLE_CODES.has(normalizedCode) ? "request_incompatible" : undefined;
|
|
209
|
+
}
|
|
194
210
|
function kindFromCode(code: string | number | undefined): ModelFallbackFailureKind | undefined {
|
|
195
211
|
const normalizedCode = normalizeCode(code);
|
|
196
212
|
if (normalizedCode === undefined) return undefined;
|
|
@@ -198,6 +214,8 @@ function kindFromCode(code: string | number | undefined): ModelFallbackFailureKi
|
|
|
198
214
|
if (refusalKind !== undefined) return refusalKind;
|
|
199
215
|
const httpStatusKind = kindFromStatus(integerFrom(code));
|
|
200
216
|
if (httpStatusKind !== undefined) return httpStatusKind;
|
|
217
|
+
const requestIncompatibleKind = requestIncompatibleKindFromCode(code);
|
|
218
|
+
if (requestIncompatibleKind !== undefined) return requestIncompatibleKind;
|
|
201
219
|
|
|
202
220
|
switch (normalizedCode) {
|
|
203
221
|
case "auth":
|
|
@@ -246,6 +264,18 @@ function kindFromCode(code: string | number | undefined): ModelFallbackFailureKi
|
|
|
246
264
|
}
|
|
247
265
|
}
|
|
248
266
|
|
|
267
|
+
const REQUEST_INCOMPATIBLE_FAILURE_PATTERNS: readonly RegExp[] = [
|
|
268
|
+
/\bcontext[_\s-]?length(?:[_\s-]?exceeded)?\b/i,
|
|
269
|
+
/\bcontext[_\s-]?window(?:[_\s-]?exceeded)?\b/i,
|
|
270
|
+
/\bmax[_\s-]?context\b/i,
|
|
271
|
+
/\bmax[_\s-]?tokens?\b/i,
|
|
272
|
+
/\brequest(?:[_\s-]?entity)?[_\s-]?too[_\s-]?large\b/i,
|
|
273
|
+
/\btoo[_\s-]?large\b/i,
|
|
274
|
+
/\b(?:unsupported|unknown|invalid)\s+(?:tool|parameter|function)\b/i,
|
|
275
|
+
/\b(?:tool|parameter|function)\s+(?:not\s+(?:supported|found|allowed)|unknown|invalid)\b/i,
|
|
276
|
+
/\binvalid[_\s-]?request(?:[_\s-]?error)?\b/i,
|
|
277
|
+
/\bbad[_\s-]?request\b/i,
|
|
278
|
+
];
|
|
249
279
|
const PROVIDER_REFUSAL_FAILURE_PATTERNS: readonly RegExp[] = [
|
|
250
280
|
/\bfinish[_\s-]?reason\b[^\n]*\bcontent[_\s-]?filter\b/i,
|
|
251
281
|
/\bcontent[_\s-]?filter(?:ed|ing)?\b/i,
|
|
@@ -258,6 +288,17 @@ const PROVIDER_REFUSAL_FAILURE_PATTERNS: readonly RegExp[] = [
|
|
|
258
288
|
/\bprovider\b[^\n]*\brefus(?:e|al|ed|es|ing)?\b[^\n]*\b(?:prompt|request|content|policy|safety)\b/i,
|
|
259
289
|
];
|
|
260
290
|
|
|
291
|
+
const TRANSPORT_OUTAGE_FAILURE_PATTERNS: readonly RegExp[] = [
|
|
292
|
+
/^connection\s+error\.?$/i,
|
|
293
|
+
/^fetch\s+failed\.?$/i,
|
|
294
|
+
];
|
|
295
|
+
|
|
296
|
+
function transportOutageKindFromMessage(message: string): ModelFallbackFailureKind | undefined {
|
|
297
|
+
return TRANSPORT_OUTAGE_FAILURE_PATTERNS.some((pattern) => pattern.test(message.trim()))
|
|
298
|
+
? "transport_error"
|
|
299
|
+
: undefined;
|
|
300
|
+
}
|
|
301
|
+
|
|
261
302
|
function refusalKindFromMessage(message: string): ModelFallbackFailureKind | undefined {
|
|
262
303
|
if (CANCELLED_FAILURE_PATTERNS.some((pattern) => pattern.test(message))) return "cancelled";
|
|
263
304
|
if (NON_RETRYABLE_FAILURE_PATTERNS.some((pattern) => pattern.test(message))) return "task_failure";
|
|
@@ -268,6 +309,9 @@ function refusalKindFromMessage(message: string): ModelFallbackFailureKind | und
|
|
|
268
309
|
function fallbackKindFromMessage(message: string, name: string | undefined): ModelFallbackFailureKind | undefined {
|
|
269
310
|
const refusalKind = refusalKindFromMessage(message);
|
|
270
311
|
if (refusalKind !== undefined) return refusalKind;
|
|
312
|
+
const transportOutageKind = transportOutageKindFromMessage(message);
|
|
313
|
+
if (transportOutageKind !== undefined) return transportOutageKind;
|
|
314
|
+
if (REQUEST_INCOMPATIBLE_FAILURE_PATTERNS.some((pattern) => pattern.test(message))) return "request_incompatible";
|
|
271
315
|
const nameKind = kindFromCode(name);
|
|
272
316
|
if (nameKind !== undefined) return nameKind;
|
|
273
317
|
if (!RETRYABLE_MODEL_FAILURE_PATTERNS.some((pattern) => pattern.test(message))) return undefined;
|
|
@@ -305,6 +349,16 @@ function makeSignal(
|
|
|
305
349
|
};
|
|
306
350
|
}
|
|
307
351
|
|
|
352
|
+
function fallbackSignalFromDirectMessage(
|
|
353
|
+
value: unknown,
|
|
354
|
+
source: ModelFallbackFailureSource | undefined,
|
|
355
|
+
): ModelFallbackFailureSignal | undefined {
|
|
356
|
+
const message = directMessageFrom(value);
|
|
357
|
+
if (message === undefined) return undefined;
|
|
358
|
+
const kind = fallbackKindFromMessage(message, errorName(value));
|
|
359
|
+
return kind === undefined ? undefined : makeSignal(kind, value, source);
|
|
360
|
+
}
|
|
361
|
+
|
|
308
362
|
function fallbackSignalFromMessage(
|
|
309
363
|
value: unknown,
|
|
310
364
|
source: ModelFallbackFailureSource | undefined,
|
|
@@ -359,7 +413,6 @@ function structuredSignal(
|
|
|
359
413
|
if (isRefusalSignal(diagnosticSignal)) return diagnosticSignal;
|
|
360
414
|
firstNestedFallbackSignal ??= diagnosticSignal;
|
|
361
415
|
}
|
|
362
|
-
|
|
363
416
|
const cause = causeOf(value);
|
|
364
417
|
const causeSignal = structuredSignal(cause, nestedSeen, source)
|
|
365
418
|
?? fallbackSignalFromMessage(cause, source);
|
|
@@ -368,6 +421,11 @@ function structuredSignal(
|
|
|
368
421
|
firstNestedFallbackSignal ??= causeSignal;
|
|
369
422
|
}
|
|
370
423
|
|
|
424
|
+
// Direct-message classification runs after nested traversal so a generic wrapper
|
|
425
|
+
// ("invalid request"/"400 bad request") cannot mask a non-retryable nested signal.
|
|
426
|
+
const directMessageSignal = fallbackSignalFromDirectMessage(value, source);
|
|
427
|
+
if (directMessageSignal !== undefined) return directMessageSignal;
|
|
428
|
+
|
|
371
429
|
const statusKind = kindFromStatus(statusFrom(value));
|
|
372
430
|
if (statusKind !== undefined) return makeSignal(statusKind, value, source);
|
|
373
431
|
if (codeKind !== undefined) return makeSignal(codeKind, value, source);
|
|
@@ -38,6 +38,10 @@ export interface KeybindingsLike {
|
|
|
38
38
|
matches(data: string, action: string): boolean;
|
|
39
39
|
}
|
|
40
40
|
|
|
41
|
+
export const APP_ACTION = {
|
|
42
|
+
toolsExpand: "app.tools.expand",
|
|
43
|
+
} as const;
|
|
44
|
+
|
|
41
45
|
export const TUI_ACTION = {
|
|
42
46
|
editorCursorUp: "tui.editor.cursorUp",
|
|
43
47
|
editorCursorDown: "tui.editor.cursorDown",
|
|
@@ -48,6 +48,8 @@ export interface OverlayUISurface {
|
|
|
48
48
|
focusHostInlineCustomUi?: () => boolean;
|
|
49
49
|
getEditorComponent?: () => PiEditorFactory | undefined;
|
|
50
50
|
getChatRenderSettings?: () => OverlayChatRenderSettings | undefined;
|
|
51
|
+
getToolsExpanded?: () => boolean;
|
|
52
|
+
setToolsExpanded?: (expanded: boolean) => void;
|
|
51
53
|
getFooterDataProvider?: () => ReadonlyFooterDataProvider;
|
|
52
54
|
setStatus?: (key: string, value: string | undefined) => void;
|
|
53
55
|
}
|
|
@@ -334,6 +336,8 @@ export function buildGraphOverlayAdapter(
|
|
|
334
336
|
piKeybindings: keybindings,
|
|
335
337
|
piEditorFactory: ui?.getEditorComponent?.(),
|
|
336
338
|
getChatRenderSettings: ui?.getChatRenderSettings,
|
|
339
|
+
getToolsExpanded: ui?.getToolsExpanded,
|
|
340
|
+
setToolsExpanded: ui?.setToolsExpanded,
|
|
337
341
|
footerData: ui?.getFooterDataProvider?.(),
|
|
338
342
|
// Pi-tui owns terminal dimensions; thread its row count down
|
|
339
343
|
// so the overlay frame fills the actual viewport rather than
|
|
@@ -3,7 +3,7 @@ import {
|
|
|
3
3
|
handlePromptCardInput,
|
|
4
4
|
isPromptEscapeInput,
|
|
5
5
|
} from "./prompt-card.js";
|
|
6
|
-
import { isKeybindingsLike } from "./keybindings-adapter.js";
|
|
6
|
+
import { APP_ACTION, isKeybindingsLike, matchesAction } from "./keybindings-adapter.js";
|
|
7
7
|
import {
|
|
8
8
|
setComponentFocused,
|
|
9
9
|
setEditorFocused,
|
|
@@ -35,6 +35,7 @@ export function handleStageChatInput(
|
|
|
35
35
|
ctx.requestRender?.();
|
|
36
36
|
return true;
|
|
37
37
|
}
|
|
38
|
+
if (handleToolsExpandInput(ctx, data)) return true;
|
|
38
39
|
if (ctx.mountedCustomUi) {
|
|
39
40
|
return handleMountedCustomUiInput(ctx, data);
|
|
40
41
|
}
|
|
@@ -87,6 +88,16 @@ export function handleStageChatInput(
|
|
|
87
88
|
return ctx.chatHost.handleInput(data);
|
|
88
89
|
}
|
|
89
90
|
|
|
91
|
+
function handleToolsExpandInput(ctx: StageChatViewContext, data: string): boolean {
|
|
92
|
+
const keybindings = isKeybindingsLike(ctx.piKeybindings) ? ctx.piKeybindings : undefined;
|
|
93
|
+
if (!matchesAction(keybindings, data, APP_ACTION.toolsExpand)) return false;
|
|
94
|
+
const expanded = ctx.getToolsExpanded?.() === true;
|
|
95
|
+
ctx.setToolsExpanded?.(!expanded);
|
|
96
|
+
ctx.chatHost.invalidate();
|
|
97
|
+
ctx.requestRender?.();
|
|
98
|
+
return true;
|
|
99
|
+
}
|
|
100
|
+
|
|
90
101
|
function handleMountedCustomUiInput(
|
|
91
102
|
ctx: StageChatViewContext,
|
|
92
103
|
data: string,
|
|
@@ -57,6 +57,8 @@ export function initializeStageChatView(
|
|
|
57
57
|
ctx.piTheme = opts.piTheme;
|
|
58
58
|
ctx.piKeybindings = opts.piKeybindings;
|
|
59
59
|
ctx.piEditorFactory = opts.piEditorFactory;
|
|
60
|
+
ctx.getToolsExpanded = opts.getToolsExpanded;
|
|
61
|
+
ctx.setToolsExpanded = opts.setToolsExpanded;
|
|
60
62
|
ctx.stageUiBroker = opts.stageUiBroker ?? stageUiBroker;
|
|
61
63
|
ctx.canSubmitPrompt = opts.canSubmitPrompt;
|
|
62
64
|
ctx.mountedCustomUi = null;
|
|
@@ -63,6 +63,10 @@ export interface StageChatViewOpts {
|
|
|
63
63
|
getChatRenderSettings?: () =>
|
|
64
64
|
| Partial<Omit<ChatMessageRenderOptions, "ui" | "cwd">>
|
|
65
65
|
| undefined;
|
|
66
|
+
/** Parent host expansion state for tool-output/live-detail widgets. */
|
|
67
|
+
getToolsExpanded?: () => boolean;
|
|
68
|
+
/** Toggle parent host expansion state for tool-output/live-detail widgets. */
|
|
69
|
+
setToolsExpanded?: (expanded: boolean) => void;
|
|
66
70
|
/** Parent footer data provider inherited from the host UI for core footer/usage rendering. */
|
|
67
71
|
footerData?: ReadonlyFooterDataProvider;
|
|
68
72
|
/**
|
|
@@ -133,6 +137,8 @@ export interface StageChatViewContext {
|
|
|
133
137
|
piTheme: unknown;
|
|
134
138
|
piKeybindings: unknown;
|
|
135
139
|
piEditorFactory: StageChatViewOpts["piEditorFactory"] | undefined;
|
|
140
|
+
getToolsExpanded: (() => boolean) | undefined;
|
|
141
|
+
setToolsExpanded: ((expanded: boolean) => void) | undefined;
|
|
136
142
|
chatHost: ChatSessionHost<NoticeEntry>;
|
|
137
143
|
stageUiBroker: StageUiBroker;
|
|
138
144
|
canSubmitPrompt: ((runId: string, stageId: string, promptId: string) => boolean) | undefined;
|
|
@@ -83,6 +83,8 @@ export class StageChatView implements Component, Focusable {
|
|
|
83
83
|
private piTheme!: StageChatViewContext["piTheme"];
|
|
84
84
|
private piKeybindings!: StageChatViewContext["piKeybindings"];
|
|
85
85
|
private piEditorFactory!: StageChatViewContext["piEditorFactory"];
|
|
86
|
+
private getToolsExpanded!: StageChatViewContext["getToolsExpanded"];
|
|
87
|
+
private setToolsExpanded!: StageChatViewContext["setToolsExpanded"];
|
|
86
88
|
private chatHost!: StageChatViewContext["chatHost"];
|
|
87
89
|
private stageUiBroker!: StageChatViewContext["stageUiBroker"];
|
|
88
90
|
private canSubmitPrompt!: StageChatViewContext["canSubmitPrompt"];
|
|
@@ -213,6 +215,8 @@ export class StageChatView implements Component, Focusable {
|
|
|
213
215
|
void this.piTheme;
|
|
214
216
|
void this.piKeybindings;
|
|
215
217
|
void this.piEditorFactory;
|
|
218
|
+
void this.getToolsExpanded;
|
|
219
|
+
void this.setToolsExpanded;
|
|
216
220
|
void this.stageUiBroker;
|
|
217
221
|
void this.canSubmitPrompt;
|
|
218
222
|
void this.mountingRequestId;
|
|
@@ -41,6 +41,10 @@ export interface WorkflowAttachPaneOpts {
|
|
|
41
41
|
piEditorFactory?: (tui: TUI, theme: EditorTheme, keybindings: unknown) => EditorComponent;
|
|
42
42
|
/** Parent chat rendering settings and extension renderers, inherited from the host UI. */
|
|
43
43
|
getChatRenderSettings?: () => Partial<Omit<ChatMessageRenderOptions, "ui" | "cwd">> | undefined;
|
|
44
|
+
/** Parent host tool-output/live-detail expansion state, inherited from the host UI. */
|
|
45
|
+
getToolsExpanded?: () => boolean;
|
|
46
|
+
/** Parent host tool-output/live-detail expansion setter, inherited from the host UI. */
|
|
47
|
+
setToolsExpanded?: (expanded: boolean) => void;
|
|
44
48
|
/** Parent footer data provider, inherited so attached chats can render the core coding-agent footer. */
|
|
45
49
|
footerData?: ReadonlyFooterDataProvider;
|
|
46
50
|
/**
|
|
@@ -24,16 +24,9 @@ import type { ChatMessageRenderOptions, ReadonlyFooterDataProvider } from "@bast
|
|
|
24
24
|
import type { Store } from "../shared/store.js";
|
|
25
25
|
import type { GraphTheme } from "./graph-theme.js";
|
|
26
26
|
import { GraphView } from "./graph-view.js";
|
|
27
|
-
import {
|
|
28
|
-
StageChatView,
|
|
29
|
-
type StageChatDetachMetadata,
|
|
30
|
-
type StageChatDetachReason,
|
|
31
|
-
} from "./stage-chat-view.js";
|
|
27
|
+
import { StageChatView, type StageChatDetachMetadata, type StageChatDetachReason } from "./stage-chat-view.js";
|
|
32
28
|
import { Key, matchesKey } from "./text-helpers.js";
|
|
33
|
-
import type {
|
|
34
|
-
StageControlHandle,
|
|
35
|
-
StageControlRegistry,
|
|
36
|
-
} from "../runs/foreground/stage-control-registry.js";
|
|
29
|
+
import type { StageControlHandle, StageControlRegistry } from "../runs/foreground/stage-control-registry.js";
|
|
37
30
|
import type { StageUiBroker } from "../shared/stage-ui-broker.js";
|
|
38
31
|
import type { StageSnapshot, StoreSnapshot } from "../shared/store-types.js";
|
|
39
32
|
import { expandWorkflowGraph } from "../shared/expanded-workflow-graph.js";
|
|
@@ -68,6 +61,8 @@ export class WorkflowAttachPane implements Component {
|
|
|
68
61
|
private piKeybindings?: unknown;
|
|
69
62
|
private piEditorFactory?: (tui: TUI, theme: EditorTheme, keybindings: unknown) => EditorComponent;
|
|
70
63
|
private getChatRenderSettings?: () => Partial<Omit<ChatMessageRenderOptions, "ui" | "cwd">> | undefined;
|
|
64
|
+
private getToolsExpanded?: () => boolean;
|
|
65
|
+
private setToolsExpanded?: (expanded: boolean) => void;
|
|
71
66
|
private footerData?: ReadonlyFooterDataProvider;
|
|
72
67
|
private now: () => number;
|
|
73
68
|
private mode: WorkflowAttachPaneMode = "graph";
|
|
@@ -104,6 +99,8 @@ export class WorkflowAttachPane implements Component {
|
|
|
104
99
|
this.piKeybindings = opts.piKeybindings;
|
|
105
100
|
this.piEditorFactory = opts.piEditorFactory;
|
|
106
101
|
this.getChatRenderSettings = opts.getChatRenderSettings;
|
|
102
|
+
this.getToolsExpanded = opts.getToolsExpanded;
|
|
103
|
+
this.setToolsExpanded = opts.setToolsExpanded;
|
|
107
104
|
this.footerData = opts.footerData;
|
|
108
105
|
this.now = opts.now ?? Date.now;
|
|
109
106
|
this.unsubscribeStore = this.store.subscribe((snapshot) => this._handleStoreUpdate(snapshot));
|
|
@@ -197,6 +194,8 @@ export class WorkflowAttachPane implements Component {
|
|
|
197
194
|
piKeybindings: this.piKeybindings,
|
|
198
195
|
piEditorFactory: this.piEditorFactory,
|
|
199
196
|
getChatRenderSettings: this.getChatRenderSettings,
|
|
197
|
+
getToolsExpanded: this.getToolsExpanded,
|
|
198
|
+
setToolsExpanded: this.setToolsExpanded,
|
|
200
199
|
footerData: this.footerData,
|
|
201
200
|
getViewportRows: this.getViewportRows,
|
|
202
201
|
stageUiBroker: this.stageUiBroker,
|
package/dist/bun/cli.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"cli.d.ts","sourceRoot":"","sources":["../../src/bun/cli.ts"],"names":[],"mappings":"","sourcesContent":["#!/usr/bin/env node\nimport { APP_NAME } from \"../config.ts\";\n\nprocess.title = APP_NAME;\nprocess.emitWarning = (() => {}) as typeof process.emitWarning;\n\nimport { restoreSandboxEnv } from \"./restore-sandbox-env.ts\";\n\nrestoreSandboxEnv();\n\
|
|
1
|
+
{"version":3,"file":"cli.d.ts","sourceRoot":"","sources":["../../src/bun/cli.ts"],"names":[],"mappings":"","sourcesContent":["#!/usr/bin/env node\nimport { APP_NAME } from \"../config.ts\";\n\nprocess.title = APP_NAME;\nprocess.emitWarning = (() => {}) as typeof process.emitWarning;\n\nimport { restoreSandboxEnv } from \"./restore-sandbox-env.ts\";\n\nrestoreSandboxEnv();\n\n// No top-level await: the compiled binary is built with --bytecode (CJS),\n// which forbids TLA anywhere in the bundled graph.\nvoid import(\"./register-bedrock.ts\").then(() => import(\"../cli.ts\"));\n"]}
|
package/dist/bun/cli.js
CHANGED
|
@@ -4,6 +4,7 @@ process.title = APP_NAME;
|
|
|
4
4
|
process.emitWarning = (() => { });
|
|
5
5
|
import { restoreSandboxEnv } from "./restore-sandbox-env.js";
|
|
6
6
|
restoreSandboxEnv();
|
|
7
|
-
await
|
|
8
|
-
|
|
7
|
+
// No top-level await: the compiled binary is built with --bytecode (CJS),
|
|
8
|
+
// which forbids TLA anywhere in the bundled graph.
|
|
9
|
+
void import("./register-bedrock.js").then(() => import("../cli.js"));
|
|
9
10
|
//# sourceMappingURL=cli.js.map
|
package/dist/bun/cli.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"cli.js","sourceRoot":"","sources":["../../src/bun/cli.ts"],"names":[],"mappings":";AACA,OAAO,EAAE,QAAQ,EAAE,MAAM,cAAc,CAAC;AAExC,OAAO,CAAC,KAAK,GAAG,QAAQ,CAAC;AACzB,OAAO,CAAC,WAAW,GAAG,CAAC,GAAG,EAAE,GAAE,CAAC,CAA+B,CAAC;AAE/D,OAAO,EAAE,iBAAiB,EAAE,MAAM,0BAA0B,CAAC;AAE7D,iBAAiB,EAAE,CAAC;AAEpB,
|
|
1
|
+
{"version":3,"file":"cli.js","sourceRoot":"","sources":["../../src/bun/cli.ts"],"names":[],"mappings":";AACA,OAAO,EAAE,QAAQ,EAAE,MAAM,cAAc,CAAC;AAExC,OAAO,CAAC,KAAK,GAAG,QAAQ,CAAC;AACzB,OAAO,CAAC,WAAW,GAAG,CAAC,GAAG,EAAE,GAAE,CAAC,CAA+B,CAAC;AAE/D,OAAO,EAAE,iBAAiB,EAAE,MAAM,0BAA0B,CAAC;AAE7D,iBAAiB,EAAE,CAAC;AAEpB,0EAA0E;AAC1E,mDAAmD;AACnD,KAAK,MAAM,CAAC,uBAAuB,CAAC,CAAC,IAAI,CAAC,GAAG,EAAE,CAAC,MAAM,CAAC,WAAW,CAAC,CAAC,CAAC","sourcesContent":["#!/usr/bin/env node\nimport { APP_NAME } from \"../config.ts\";\n\nprocess.title = APP_NAME;\nprocess.emitWarning = (() => {}) as typeof process.emitWarning;\n\nimport { restoreSandboxEnv } from \"./restore-sandbox-env.ts\";\n\nrestoreSandboxEnv();\n\n// No top-level await: the compiled binary is built with --bytecode (CJS),\n// which forbids TLA anywhere in the bundled graph.\nvoid import(\"./register-bedrock.ts\").then(() => import(\"../cli.ts\"));\n"]}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"file-processor.d.ts","sourceRoot":"","sources":["../../src/cli/file-processor.ts"],"names":[],"mappings":"AAAA;;GAEG;AAGH,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,8BAA8B,CAAC;AAOjE,MAAM,WAAW,cAAc;IAC9B,IAAI,EAAE,MAAM,CAAC;IACb,MAAM,EAAE,YAAY,EAAE,CAAC;CACvB;AAED,MAAM,WAAW,kBAAkB;IAClC,oEAAoE;IACpE,gBAAgB,CAAC,EAAE,OAAO,CAAC;CAC3B;AAED,sEAAsE;AACtE,wBAAsB,oBAAoB,CAAC,QAAQ,EAAE,MAAM,EAAE,EAAE,OAAO,CAAC,EAAE,kBAAkB,GAAG,OAAO,CAAC,cAAc,CAAC,
|
|
1
|
+
{"version":3,"file":"file-processor.d.ts","sourceRoot":"","sources":["../../src/cli/file-processor.ts"],"names":[],"mappings":"AAAA;;GAEG;AAGH,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,8BAA8B,CAAC;AAOjE,MAAM,WAAW,cAAc;IAC9B,IAAI,EAAE,MAAM,CAAC;IACb,MAAM,EAAE,YAAY,EAAE,CAAC;CACvB;AAED,MAAM,WAAW,kBAAkB;IAClC,oEAAoE;IACpE,gBAAgB,CAAC,EAAE,OAAO,CAAC;CAC3B;AAED,sEAAsE;AACtE,wBAAsB,oBAAoB,CAAC,QAAQ,EAAE,MAAM,EAAE,EAAE,OAAO,CAAC,EAAE,kBAAkB,GAAG,OAAO,CAAC,cAAc,CAAC,CA+DpH","sourcesContent":["/**\n * Process @file CLI arguments into text content and image attachments\n */\n\nimport { access, readFile, stat } from \"node:fs/promises\";\nimport type { ImageContent } from \"@earendil-works/pi-ai/compat\";\nimport chalk from \"chalk\";\nimport { resolve } from \"path\";\nimport { resolveReadPath } from \"../core/tools/path-utils.ts\";\nimport { processImage } from \"../utils/image-process.ts\";\nimport { detectSupportedImageMimeTypeFromFile } from \"../utils/mime.ts\";\n\nexport interface ProcessedFiles {\n\ttext: string;\n\timages: ImageContent[];\n}\n\nexport interface ProcessFileOptions {\n\t/** Whether to auto-resize images to 2000x2000 max. Default: true */\n\tautoResizeImages?: boolean;\n}\n\n/** Process @file arguments into text content and image attachments */\nexport async function processFileArguments(fileArgs: string[], options?: ProcessFileOptions): Promise<ProcessedFiles> {\n\tconst autoResizeImages = options?.autoResizeImages ?? true;\n\tlet text = \"\";\n\tconst images: ImageContent[] = [];\n\n\tfor (const fileArg of fileArgs) {\n\t\t// Expand and resolve path (handles ~ expansion and macOS screenshot Unicode spaces)\n\t\tconst absolutePath = resolve(resolveReadPath(fileArg, process.cwd()));\n\n\t\t// Check if file exists\n\t\ttry {\n\t\t\tawait access(absolutePath);\n\t\t} catch {\n\t\t\tconsole.error(chalk.red(`Error: File not found: ${absolutePath}`));\n\t\t\tprocess.exit(1);\n\t\t}\n\n\t\t// Check if file is empty\n\t\tconst stats = await stat(absolutePath);\n\t\tif (stats.size === 0) {\n\t\t\t// Skip empty files\n\t\t\tcontinue;\n\t\t}\n\n\t\tconst mimeType = await detectSupportedImageMimeTypeFromFile(absolutePath);\n\n\t\tif (mimeType) {\n\t\t\t// Handle image file\n\t\t\tconst content = await readFile(absolutePath);\n\t\t\tconst processed = await processImage(content, mimeType, { autoResizeImages });\n\n\t\t\tif (!processed.ok) {\n\t\t\t\ttext += `<file name=\"${absolutePath}\">${processed.message}</file>\\n`;\n\t\t\t\tcontinue;\n\t\t\t}\n\n\t\t\tconst attachment: ImageContent = {\n\t\t\t\ttype: \"image\",\n\t\t\t\tmimeType: processed.mimeType,\n\t\t\t\tdata: processed.data,\n\t\t\t};\n\t\t\timages.push(attachment);\n\n\t\t\t// Add text reference to image with optional processing hints\n\t\t\tif (processed.hints.length > 0) {\n\t\t\t\ttext += `<file name=\"${absolutePath}\">${processed.hints.join(\"\\n\")}</file>\\n`;\n\t\t\t} else {\n\t\t\t\ttext += `<file name=\"${absolutePath}\"></file>\\n`;\n\t\t\t}\n\t\t} else {\n\t\t\t// Handle text file\n\t\t\ttry {\n\t\t\t\tconst content = await readFile(absolutePath, \"utf-8\");\n\t\t\t\ttext += `<file name=\"${absolutePath}\">\\n${content}\\n</file>\\n`;\n\t\t\t} catch (error: unknown) {\n\t\t\t\tconst message = error instanceof Error ? error.message : String(error);\n\t\t\t\tconsole.error(chalk.red(`Error: Could not read file ${absolutePath}: ${message}`));\n\t\t\t\tprocess.exit(1);\n\t\t\t}\n\t\t}\n\t}\n\n\treturn { text, images };\n}\n"]}
|
|
@@ -5,7 +5,7 @@ import { access, readFile, stat } from "node:fs/promises";
|
|
|
5
5
|
import chalk from "chalk";
|
|
6
6
|
import { resolve } from "path";
|
|
7
7
|
import { resolveReadPath } from "../core/tools/path-utils.js";
|
|
8
|
-
import {
|
|
8
|
+
import { processImage } from "../utils/image-process.js";
|
|
9
9
|
import { detectSupportedImageMimeTypeFromFile } from "../utils/mime.js";
|
|
10
10
|
/** Process @file arguments into text content and image attachments */
|
|
11
11
|
export async function processFileArguments(fileArgs, options) {
|
|
@@ -33,32 +33,20 @@ export async function processFileArguments(fileArgs, options) {
|
|
|
33
33
|
if (mimeType) {
|
|
34
34
|
// Handle image file
|
|
35
35
|
const content = await readFile(absolutePath);
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
if (!resized) {
|
|
41
|
-
text += `<file name="${absolutePath}">[Image omitted: could not be resized below the inline image size limit.]</file>\n`;
|
|
42
|
-
continue;
|
|
43
|
-
}
|
|
44
|
-
dimensionNote = formatDimensionNote(resized);
|
|
45
|
-
attachment = {
|
|
46
|
-
type: "image",
|
|
47
|
-
mimeType: resized.mimeType,
|
|
48
|
-
data: resized.data,
|
|
49
|
-
};
|
|
50
|
-
}
|
|
51
|
-
else {
|
|
52
|
-
attachment = {
|
|
53
|
-
type: "image",
|
|
54
|
-
mimeType,
|
|
55
|
-
data: content.toString("base64"),
|
|
56
|
-
};
|
|
36
|
+
const processed = await processImage(content, mimeType, { autoResizeImages });
|
|
37
|
+
if (!processed.ok) {
|
|
38
|
+
text += `<file name="${absolutePath}">${processed.message}</file>\n`;
|
|
39
|
+
continue;
|
|
57
40
|
}
|
|
41
|
+
const attachment = {
|
|
42
|
+
type: "image",
|
|
43
|
+
mimeType: processed.mimeType,
|
|
44
|
+
data: processed.data,
|
|
45
|
+
};
|
|
58
46
|
images.push(attachment);
|
|
59
|
-
// Add text reference to image with optional
|
|
60
|
-
if (
|
|
61
|
-
text += `<file name="${absolutePath}">${
|
|
47
|
+
// Add text reference to image with optional processing hints
|
|
48
|
+
if (processed.hints.length > 0) {
|
|
49
|
+
text += `<file name="${absolutePath}">${processed.hints.join("\n")}</file>\n`;
|
|
62
50
|
}
|
|
63
51
|
else {
|
|
64
52
|
text += `<file name="${absolutePath}"></file>\n`;
|