@oh-my-pi/pi-coding-agent 15.10.10 → 15.10.12
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 +142 -7
- package/dist/cli.js +23108 -0
- package/dist/tokenizers.linux-x64-gnu-xcjh3jwk.node +0 -0
- package/dist/types/async/job-manager.d.ts +18 -0
- package/dist/types/cli/args.d.ts +2 -1
- package/dist/types/cli/dry-balance-cli.d.ts +1 -1
- package/dist/types/cli/gallery-cli.d.ts +1 -1
- package/dist/types/cli/gallery-fixtures/types.d.ts +1 -1
- package/dist/types/cli/usage-cli.d.ts +72 -0
- package/dist/types/cli-commands.d.ts +12 -0
- package/dist/types/commands/launch.d.ts +5 -1
- package/dist/types/commands/read.d.ts +1 -1
- package/dist/types/commands/usage.d.ts +25 -0
- package/dist/types/config/api-key-resolver.d.ts +3 -0
- package/dist/types/config/append-only-context-mode.d.ts +2 -1
- package/dist/types/config/model-discovery.d.ts +55 -0
- package/dist/types/config/model-registry.d.ts +8 -219
- package/dist/types/config/model-resolver.d.ts +34 -10
- package/dist/types/config/model-roles.d.ts +28 -0
- package/dist/types/config/models-config-schema.d.ts +523 -42
- package/dist/types/config/models-config.d.ts +385 -0
- package/dist/types/config/settings-schema.d.ts +41 -8
- package/dist/types/config/settings.d.ts +8 -1
- package/dist/types/debug/log-viewer.d.ts +1 -1
- package/dist/types/debug/raw-sse.d.ts +1 -1
- package/dist/types/edit/hashline/noop-loop-guard.d.ts +72 -0
- package/dist/types/eval/backend.d.ts +0 -2
- package/dist/types/eval/idle-timeout.d.ts +0 -4
- package/dist/types/eval/js/shared/rewrite-imports.d.ts +6 -6
- package/dist/types/eval/py/executor.d.ts +5 -0
- package/dist/types/eval/py/kernel.d.ts +6 -1
- package/dist/types/eval/py/runtime.d.ts +9 -0
- package/dist/types/exec/bash-executor.d.ts +2 -0
- package/dist/types/export/html/template.generated.d.ts +1 -1
- package/dist/types/extensibility/extensions/runner.d.ts +3 -2
- package/dist/types/extensibility/extensions/types.d.ts +6 -3
- package/dist/types/hindsight/mental-models.d.ts +17 -8
- package/dist/types/internal-urls/artifact-protocol.d.ts +2 -2
- package/dist/types/internal-urls/types.d.ts +1 -1
- package/dist/types/lsp/edits.d.ts +9 -0
- package/dist/types/lsp/index.d.ts +2 -2
- package/dist/types/lsp/types.d.ts +2 -0
- package/dist/types/lsp/utils.d.ts +3 -0
- package/dist/types/mcp/json-rpc.d.ts +5 -0
- package/dist/types/memory-backend/index.d.ts +1 -0
- package/dist/types/memory-backend/runtime.d.ts +4 -0
- package/dist/types/memory-backend/types.d.ts +66 -1
- package/dist/types/mnemopi/state.d.ts +11 -1
- package/dist/types/modes/components/agent-dashboard.d.ts +1 -1
- package/dist/types/modes/components/assistant-message.d.ts +3 -1
- package/dist/types/modes/components/bash-execution.d.ts +1 -1
- package/dist/types/modes/components/copy-selector.d.ts +1 -1
- package/dist/types/modes/components/dynamic-border.d.ts +1 -1
- package/dist/types/modes/components/extensions/extension-dashboard.d.ts +1 -1
- package/dist/types/modes/components/extensions/extension-list.d.ts +1 -1
- package/dist/types/modes/components/extensions/inspector-panel.d.ts +1 -1
- package/dist/types/modes/components/footer.d.ts +1 -1
- package/dist/types/modes/components/hook-editor.d.ts +5 -0
- package/dist/types/modes/components/hook-input.d.ts +4 -0
- package/dist/types/modes/components/hook-selector.d.ts +1 -1
- package/dist/types/modes/components/model-selector.d.ts +1 -1
- package/dist/types/modes/components/plan-review-overlay.d.ts +1 -1
- package/dist/types/modes/components/session-observer-overlay.d.ts +1 -1
- package/dist/types/modes/components/session-selector.d.ts +1 -1
- package/dist/types/modes/components/status-line/component.d.ts +1 -1
- package/dist/types/modes/components/tiny-title-download-progress.d.ts +1 -1
- package/dist/types/modes/components/transcript-container.d.ts +25 -6
- package/dist/types/modes/components/tree-selector.d.ts +1 -1
- package/dist/types/modes/components/user-message-selector.d.ts +1 -1
- package/dist/types/modes/components/user-message.d.ts +2 -1
- package/dist/types/modes/components/visual-truncate.d.ts +1 -1
- package/dist/types/modes/components/welcome.d.ts +19 -3
- package/dist/types/modes/controllers/mcp-command-controller.d.ts +1 -1
- package/dist/types/modes/controllers/streaming-reveal.d.ts +1 -1
- package/dist/types/modes/index.d.ts +3 -3
- package/dist/types/modes/interactive-mode.d.ts +8 -3
- package/dist/types/modes/oauth-manual-input.d.ts +7 -0
- package/dist/types/modes/rpc/rpc-client.d.ts +39 -2
- package/dist/types/modes/rpc/rpc-mode.d.ts +31 -2
- package/dist/types/modes/rpc/rpc-subagents.d.ts +24 -0
- package/dist/types/modes/rpc/rpc-types.d.ts +75 -1
- package/dist/types/modes/setup-wizard/index.d.ts +5 -1
- package/dist/types/modes/setup-wizard/lazy.d.ts +2 -0
- package/dist/types/modes/setup-wizard/scenes/sign-in.d.ts +1 -1
- package/dist/types/modes/setup-wizard/scenes/types.d.ts +1 -1
- package/dist/types/modes/setup-wizard/scenes/web-search.d.ts +1 -1
- package/dist/types/modes/setup-wizard/wizard-overlay.d.ts +1 -1
- package/dist/types/modes/types.d.ts +4 -1
- package/dist/types/secrets/index.d.ts +1 -1
- package/dist/types/secrets/obfuscator.d.ts +8 -2
- package/dist/types/session/agent-session.d.ts +15 -3
- package/dist/types/session/auth-broker-config.d.ts +4 -0
- package/dist/types/session/session-manager.d.ts +1 -1
- package/dist/types/session/streaming-output.d.ts +23 -0
- package/dist/types/slash-commands/acp-builtins.d.ts +16 -0
- package/dist/types/slash-commands/builtin-registry.d.ts +1 -0
- package/dist/types/slash-commands/helpers/stats-dashboard.d.ts +13 -0
- package/dist/types/slash-commands/types.d.ts +1 -1
- package/dist/types/ssh/connection-manager.d.ts +8 -0
- package/dist/types/system-prompt.d.ts +2 -0
- package/dist/types/task/executor.d.ts +1 -0
- package/dist/types/task/index.d.ts +2 -2
- package/dist/types/task/parallel.d.ts +2 -2
- package/dist/types/task/types.d.ts +8 -0
- package/dist/types/task/worktree.d.ts +2 -0
- package/dist/types/thinking.d.ts +4 -0
- package/dist/types/tiny/title-client.d.ts +11 -0
- package/dist/types/tiny/title-protocol.d.ts +1 -0
- package/dist/types/tools/ask.d.ts +4 -0
- package/dist/types/tools/conflict-detect.d.ts +16 -0
- package/dist/types/tools/github-cache.d.ts +7 -0
- package/dist/types/tools/index.d.ts +6 -0
- package/dist/types/tools/sqlite-reader.d.ts +3 -0
- package/dist/types/tui/output-block.d.ts +3 -3
- package/dist/types/utils/changelog.d.ts +8 -0
- package/dist/types/utils/git.d.ts +15 -2
- package/dist/types/utils/title-generator.d.ts +3 -2
- package/dist/types/web/scrapers/readthedocs.d.ts +3 -0
- package/dist/types/web/scrapers/types.d.ts +12 -0
- package/dist/types/web/search/providers/codex.d.ts +1 -1
- package/dist/types/web/search/providers/gemini.d.ts +1 -1
- package/examples/extensions/tools.ts +5 -4
- package/package.json +14 -11
- package/scripts/build-binary.ts +18 -23
- package/scripts/bundle-dist.ts +81 -0
- package/scripts/{dev-launch → omp} +1 -1
- package/scripts/{dev-launch-preload.ts → omp.ts} +1 -1
- package/src/async/job-manager.ts +57 -3
- package/src/auto-thinking/classifier.ts +1 -0
- package/src/autoresearch/dashboard.ts +1 -1
- package/src/autoresearch/prompt-setup.md +6 -6
- package/src/autoresearch/prompt.md +6 -6
- package/src/capability/fs.ts +10 -0
- package/src/cli/args.ts +4 -1
- package/src/cli/auth-gateway-cli.ts +1 -3
- package/src/cli/dry-balance-cli.ts +1 -1
- package/src/cli/gallery-cli.ts +1 -1
- package/src/cli/gallery-fixtures/fs.ts +1 -1
- package/src/cli/gallery-fixtures/types.ts +5 -1
- package/src/cli/list-models.ts +2 -1
- package/src/cli/usage-cli.ts +603 -0
- package/src/cli-commands.ts +30 -0
- package/src/cli.ts +76 -13
- package/src/commands/complete.ts +1 -1
- package/src/commands/launch.ts +5 -1
- package/src/commands/read.ts +6 -3
- package/src/commands/usage.ts +35 -0
- package/src/commit/agentic/agent.ts +1 -1
- package/src/commit/model-selection.ts +4 -3
- package/src/config/api-key-resolver.ts +8 -6
- package/src/config/append-only-context-mode.ts +6 -12
- package/src/config/model-discovery.ts +554 -0
- package/src/config/model-registry.ts +320 -1041
- package/src/config/model-resolver.ts +173 -156
- package/src/config/model-roles.ts +74 -0
- package/src/config/models-config-schema.ts +57 -8
- package/src/config/models-config.ts +129 -0
- package/src/config/settings-schema.ts +61 -19
- package/src/config/settings.ts +98 -4
- package/src/dap/client.ts +124 -37
- package/src/dap/session.ts +259 -158
- package/src/debug/log-viewer.ts +1 -1
- package/src/debug/raw-sse.ts +1 -1
- package/src/edit/diff.ts +47 -3
- package/src/edit/hashline/block-resolver.ts +20 -1
- package/src/edit/hashline/diff.ts +36 -1
- package/src/edit/hashline/execute.ts +47 -4
- package/src/edit/hashline/noop-loop-guard.ts +99 -0
- package/src/edit/index.ts +16 -1
- package/src/edit/modes/patch.ts +52 -0
- package/src/edit/modes/replace.ts +56 -22
- package/src/edit/notebook.ts +22 -2
- package/src/edit/renderer.ts +36 -10
- package/src/eval/__tests__/completion-bridge.test.ts +1 -1
- package/src/eval/backend.ts +0 -2
- package/src/eval/completion-bridge.ts +3 -1
- package/src/eval/idle-timeout.ts +2 -9
- package/src/eval/js/context-manager.ts +6 -8
- package/src/eval/js/executor.ts +6 -2
- package/src/eval/js/index.ts +0 -2
- package/src/eval/js/shared/helpers.ts +5 -6
- package/src/eval/js/shared/local-module-loader.ts +1 -1
- package/src/eval/js/shared/prelude.txt +62 -1
- package/src/eval/js/shared/rewrite-imports.ts +40 -22
- package/src/eval/js/shared/runtime.ts +1 -1
- package/src/eval/py/executor.ts +29 -7
- package/src/eval/py/index.ts +6 -3
- package/src/eval/py/kernel.ts +43 -4
- package/src/eval/py/runner.py +107 -3
- package/src/eval/py/runtime.ts +37 -0
- package/src/exec/bash-executor.ts +85 -4
- package/src/export/html/template.generated.ts +1 -1
- package/src/export/html/template.js +3 -1
- package/src/extensibility/extensions/get-commands-handler.ts +2 -1
- package/src/extensibility/extensions/runner.ts +6 -1
- package/src/extensibility/extensions/types.ts +6 -2
- package/src/extensibility/plugins/legacy-pi-compat.ts +20 -3
- package/src/hindsight/bank.ts +17 -2
- package/src/hindsight/mental-models.ts +59 -12
- package/src/hindsight/state.ts +6 -1
- package/src/internal-urls/artifact-protocol.ts +11 -2
- package/src/internal-urls/docs-index.generated.ts +11 -11
- package/src/internal-urls/issue-pr-protocol.ts +12 -5
- package/src/internal-urls/router.ts +1 -1
- package/src/internal-urls/types.ts +1 -1
- package/src/lib/xai-http.ts +1 -1
- package/src/lsp/client.ts +118 -38
- package/src/lsp/clients/biome-client.ts +101 -39
- package/src/lsp/edits.ts +143 -95
- package/src/lsp/index.ts +31 -22
- package/src/lsp/render.ts +1 -1
- package/src/lsp/types.ts +2 -0
- package/src/lsp/utils.ts +28 -10
- package/src/main.ts +183 -23
- package/src/mcp/json-rpc.ts +35 -5
- package/src/mcp/transports/stdio.ts +7 -1
- package/src/memories/index.ts +4 -1
- package/src/memory-backend/index.ts +1 -0
- package/src/memory-backend/local-backend.ts +9 -0
- package/src/memory-backend/off-backend.ts +9 -0
- package/src/memory-backend/runtime.ts +66 -0
- package/src/memory-backend/types.ts +81 -1
- package/src/mnemopi/backend.ts +176 -7
- package/src/mnemopi/state.ts +38 -2
- package/src/modes/acp/acp-agent.ts +119 -11
- package/src/modes/components/agent-dashboard.ts +10 -7
- package/src/modes/components/assistant-message.ts +32 -28
- package/src/modes/components/bash-execution.ts +1 -1
- package/src/modes/components/copy-selector.ts +1 -1
- package/src/modes/components/diff.ts +13 -2
- package/src/modes/components/dynamic-border.ts +12 -3
- package/src/modes/components/extensions/extension-dashboard.ts +8 -5
- package/src/modes/components/extensions/extension-list.ts +1 -1
- package/src/modes/components/extensions/inspector-panel.ts +1 -1
- package/src/modes/components/footer.ts +4 -2
- package/src/modes/components/history-search.ts +1 -1
- package/src/modes/components/hook-editor.ts +8 -0
- package/src/modes/components/hook-input.ts +8 -0
- package/src/modes/components/hook-selector.ts +2 -2
- package/src/modes/components/model-selector.ts +4 -2
- package/src/modes/components/plan-review-overlay.ts +1 -1
- package/src/modes/components/session-observer-overlay.ts +2 -2
- package/src/modes/components/session-selector.ts +1 -1
- package/src/modes/components/settings-selector.ts +5 -1
- package/src/modes/components/status-line/component.ts +119 -35
- package/src/modes/components/tiny-title-download-progress.ts +1 -1
- package/src/modes/components/transcript-container.ts +258 -53
- package/src/modes/components/tree-selector.ts +3 -3
- package/src/modes/components/user-message-selector.ts +1 -1
- package/src/modes/components/user-message.ts +17 -5
- package/src/modes/components/visual-truncate.ts +1 -1
- package/src/modes/components/welcome.ts +108 -26
- package/src/modes/controllers/command-controller.ts +11 -4
- package/src/modes/controllers/event-controller.ts +73 -4
- package/src/modes/controllers/input-controller.ts +2 -1
- package/src/modes/controllers/mcp-command-controller.ts +39 -4
- package/src/modes/controllers/selector-controller.ts +1 -1
- package/src/modes/controllers/streaming-reveal.ts +85 -18
- package/src/modes/index.ts +3 -21
- package/src/modes/interactive-mode.ts +42 -18
- package/src/modes/oauth-manual-input.ts +30 -3
- package/src/modes/rpc/rpc-client.ts +154 -3
- package/src/modes/rpc/rpc-mode.ts +97 -12
- package/src/modes/rpc/rpc-subagents.ts +265 -0
- package/src/modes/rpc/rpc-types.ts +81 -1
- package/src/modes/setup-wizard/index.ts +12 -2
- package/src/modes/setup-wizard/lazy.ts +16 -0
- package/src/modes/setup-wizard/scenes/glyph.ts +1 -1
- package/src/modes/setup-wizard/scenes/providers.ts +1 -1
- package/src/modes/setup-wizard/scenes/sign-in.ts +1 -1
- package/src/modes/setup-wizard/scenes/theme.ts +1 -1
- package/src/modes/setup-wizard/scenes/types.ts +1 -1
- package/src/modes/setup-wizard/scenes/web-search.ts +1 -1
- package/src/modes/setup-wizard/wizard-overlay.ts +1 -1
- package/src/modes/types.ts +4 -1
- package/src/prompts/agents/explore.md +2 -2
- package/src/prompts/agents/librarian.md +1 -2
- package/src/prompts/agents/oracle.md +1 -1
- package/src/prompts/agents/plan.md +5 -5
- package/src/prompts/agents/task.md +5 -5
- package/src/prompts/ci-green-request.md +5 -7
- package/src/prompts/goals/goal-budget-limit.md +2 -2
- package/src/prompts/goals/goal-continuation.md +4 -4
- package/src/prompts/goals/goal-mode-active.md +1 -1
- package/src/prompts/memories/read-path.md +1 -1
- package/src/prompts/memories/stage_one_system.md +2 -2
- package/src/prompts/review-custom-request.md +1 -1
- package/src/prompts/system/agent-creation-architect.md +2 -2
- package/src/prompts/system/auto-continue.md +1 -1
- package/src/prompts/system/background-tan-dispatch.md +1 -1
- package/src/prompts/system/btw-user.md +2 -2
- package/src/prompts/system/commit-message-system.md +13 -1
- package/src/prompts/system/custom-system-prompt.md +1 -1
- package/src/prompts/system/eager-todo.md +2 -2
- package/src/prompts/system/irc-incoming.md +1 -1
- package/src/prompts/system/manual-continue.md +1 -1
- package/src/prompts/system/omfg-user.md +3 -4
- package/src/prompts/system/orchestrate-notice.md +9 -9
- package/src/prompts/system/plan-mode-active.md +4 -4
- package/src/prompts/system/plan-mode-subagent.md +4 -5
- package/src/prompts/system/plan-mode-tool-decision-reminder.md +1 -1
- package/src/prompts/system/project-prompt.md +2 -2
- package/src/prompts/system/subagent-system-prompt.md +4 -4
- package/src/prompts/system/system-prompt.md +13 -24
- package/src/prompts/system/title-system.md +2 -2
- package/src/prompts/system/ttsr-tool-reminder.md +1 -1
- package/src/prompts/system/workflow-notice.md +1 -1
- package/src/prompts/tools/ast-edit.md +1 -1
- package/src/prompts/tools/ast-grep.md +2 -2
- package/src/prompts/tools/bash.md +5 -7
- package/src/prompts/tools/browser.md +7 -7
- package/src/prompts/tools/debug.md +1 -1
- package/src/prompts/tools/eval.md +3 -3
- package/src/prompts/tools/find.md +0 -1
- package/src/prompts/tools/github.md +8 -7
- package/src/prompts/tools/goal.md +1 -1
- package/src/prompts/tools/image-gen.md +1 -1
- package/src/prompts/tools/inspect-image-system.md +1 -1
- package/src/prompts/tools/irc.md +15 -15
- package/src/prompts/tools/lsp.md +2 -2
- package/src/prompts/tools/patch.md +2 -2
- package/src/prompts/tools/read.md +3 -4
- package/src/prompts/tools/recall.md +1 -1
- package/src/prompts/tools/reflect.md +1 -1
- package/src/prompts/tools/render-mermaid.md +2 -2
- package/src/prompts/tools/replace.md +4 -10
- package/src/prompts/tools/rewind.md +2 -2
- package/src/prompts/tools/search-tool-bm25.md +1 -9
- package/src/prompts/tools/search.md +0 -1
- package/src/prompts/tools/ssh.md +0 -4
- package/src/prompts/tools/task.md +2 -3
- package/src/prompts/tools/todo.md +1 -1
- package/src/sdk.ts +31 -11
- package/src/secrets/index.ts +8 -1
- package/src/secrets/obfuscator.ts +39 -18
- package/src/session/agent-session.ts +223 -64
- package/src/session/auth-broker-config.ts +30 -1
- package/src/session/session-manager.ts +2 -2
- package/src/session/streaming-output.ts +188 -11
- package/src/slash-commands/acp-builtins.ts +24 -0
- package/src/slash-commands/builtin-registry.ts +40 -0
- package/src/slash-commands/helpers/stats-dashboard.ts +85 -0
- package/src/slash-commands/types.ts +1 -1
- package/src/ssh/connection-manager.ts +27 -0
- package/src/system-prompt.ts +14 -0
- package/src/task/commands.ts +2 -1
- package/src/task/executor.ts +74 -65
- package/src/task/index.ts +146 -68
- package/src/task/parallel.ts +3 -3
- package/src/task/render.ts +20 -5
- package/src/task/types.ts +9 -0
- package/src/task/worktree.ts +64 -56
- package/src/thinking.ts +9 -1
- package/src/tiny/title-client.ts +60 -16
- package/src/tiny/title-protocol.ts +1 -1
- package/src/tiny/worker.ts +6 -4
- package/src/tools/archive-reader.ts +30 -2
- package/src/tools/ask.ts +104 -21
- package/src/tools/ast-edit.ts +25 -5
- package/src/tools/auto-generated-guard.ts +20 -3
- package/src/tools/bash-interactive.ts +27 -7
- package/src/tools/bash.ts +100 -18
- package/src/tools/browser/launch.ts +11 -2
- package/src/tools/browser/readable.ts +19 -2
- package/src/tools/browser/registry.ts +4 -1
- package/src/tools/browser/render.ts +2 -2
- package/src/tools/browser/tab-supervisor.ts +55 -16
- package/src/tools/conflict-detect.ts +50 -4
- package/src/tools/debug.ts +1 -1
- package/src/tools/eval-render.ts +5 -5
- package/src/tools/eval.ts +0 -2
- package/src/tools/fetch.ts +33 -10
- package/src/tools/gh-cache-invalidation.ts +63 -8
- package/src/tools/gh-renderer.ts +1 -1
- package/src/tools/gh.ts +172 -29
- package/src/tools/github-cache.ts +70 -6
- package/src/tools/image-gen.ts +14 -13
- package/src/tools/index.ts +13 -1
- package/src/tools/inspect-image.ts +1 -0
- package/src/tools/irc.ts +5 -1
- package/src/tools/job.ts +1 -1
- package/src/tools/read.ts +202 -61
- package/src/tools/render-utils.ts +3 -3
- package/src/tools/resolve.ts +1 -1
- package/src/tools/search.ts +92 -29
- package/src/tools/sqlite-reader.ts +17 -5
- package/src/tools/ssh.ts +8 -8
- package/src/tools/todo.ts +38 -8
- package/src/tools/write.ts +118 -18
- package/src/tui/output-block.ts +4 -4
- package/src/utils/changelog.ts +27 -1
- package/src/utils/commit-message-generator.ts +1 -0
- package/src/utils/file-mentions.ts +2 -1
- package/src/utils/git.ts +267 -13
- package/src/utils/title-generator.ts +24 -5
- package/src/web/scrapers/arxiv.ts +1 -1
- package/src/web/scrapers/go-pkg.ts +1 -1
- package/src/web/scrapers/iacr.ts +1 -1
- package/src/web/scrapers/readthedocs.ts +1 -1
- package/src/web/scrapers/twitter.ts +2 -1
- package/src/web/scrapers/types.ts +87 -8
- package/src/web/scrapers/wikipedia.ts +1 -1
- package/src/web/scrapers/youtube.ts +6 -1
- package/src/web/search/index.ts +1 -1
- package/src/web/search/providers/codex.ts +2 -1
- package/src/web/search/providers/gemini.ts +2 -3
- package/src/web/search/render.ts +8 -6
- package/dist/types/config/model-equivalence.d.ts +0 -24
- package/dist/types/config/model-id-affixes.d.ts +0 -12
- package/dist/types/config/model-provider-priority.d.ts +0 -1
- package/dist/types/exec/idle-timeout-watchdog.d.ts +0 -18
- package/src/config/model-equivalence.ts +0 -875
- package/src/config/model-id-affixes.ts +0 -81
- package/src/config/model-provider-priority.ts +0 -56
- package/src/exec/idle-timeout-watchdog.ts +0 -126
|
@@ -23,6 +23,45 @@ function countGraphemes(text: string): number {
|
|
|
23
23
|
return count;
|
|
24
24
|
}
|
|
25
25
|
|
|
26
|
+
/** Count graphemes of `text` from code-unit offset `start`, also reporting the
|
|
27
|
+
* start offset of the final grapheme (where an append could extend a cluster). */
|
|
28
|
+
function countGraphemesFrom(text: string, start: number): { count: number; tailStart: number } {
|
|
29
|
+
let count = 0;
|
|
30
|
+
let tailStart = start;
|
|
31
|
+
for (const seg of getSegmenter().segment(start === 0 ? text : text.slice(start))) {
|
|
32
|
+
count += 1;
|
|
33
|
+
tailStart = start + seg.index;
|
|
34
|
+
}
|
|
35
|
+
return { count, tailStart };
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
/** Memoizes per-block grapheme counts across reveal ticks. Streaming blocks only
|
|
39
|
+
* grow by appending, and an append can only alter the final grapheme cluster of
|
|
40
|
+
* the previous text, so only the suffix from that cluster needs re-segmenting. */
|
|
41
|
+
class BlockUnitCounter {
|
|
42
|
+
#entries = new Map<number, { text: string; count: number; tailStart: number }>();
|
|
43
|
+
|
|
44
|
+
count(index: number, text: string): number {
|
|
45
|
+
const entry = this.#entries.get(index);
|
|
46
|
+
if (entry !== undefined) {
|
|
47
|
+
if (entry.text === text) return entry.count;
|
|
48
|
+
if (entry.count > 0 && text.length > entry.text.length && text.startsWith(entry.text)) {
|
|
49
|
+
const tail = countGraphemesFrom(text, entry.tailStart);
|
|
50
|
+
const next = { text, count: entry.count - 1 + tail.count, tailStart: tail.tailStart };
|
|
51
|
+
this.#entries.set(index, next);
|
|
52
|
+
return next.count;
|
|
53
|
+
}
|
|
54
|
+
}
|
|
55
|
+
const full = countGraphemesFrom(text, 0);
|
|
56
|
+
this.#entries.set(index, { text, count: full.count, tailStart: full.tailStart });
|
|
57
|
+
return full.count;
|
|
58
|
+
}
|
|
59
|
+
|
|
60
|
+
reset(): void {
|
|
61
|
+
this.#entries.clear();
|
|
62
|
+
}
|
|
63
|
+
}
|
|
64
|
+
|
|
26
65
|
function sliceGraphemes(text: string, units: number): string {
|
|
27
66
|
if (units <= 0 || text.length === 0) return "";
|
|
28
67
|
let count = 0;
|
|
@@ -51,9 +90,9 @@ export function visibleUnits(message: AssistantMessage, hideThinking: boolean):
|
|
|
51
90
|
function revealTextBlock(
|
|
52
91
|
block: Extract<AssistantContentBlock, { type: "text" }>,
|
|
53
92
|
remaining: number,
|
|
93
|
+
units: number,
|
|
54
94
|
): AssistantContentBlock {
|
|
55
95
|
if (remaining <= 0) return block.text.length === 0 ? block : { ...block, text: "" };
|
|
56
|
-
const units = countGraphemes(block.text);
|
|
57
96
|
if (remaining >= units) return block;
|
|
58
97
|
return { ...block, text: sliceGraphemes(block.text, remaining) };
|
|
59
98
|
}
|
|
@@ -61,9 +100,9 @@ function revealTextBlock(
|
|
|
61
100
|
function revealThinkingBlock(
|
|
62
101
|
block: Extract<AssistantContentBlock, { type: "thinking" }>,
|
|
63
102
|
remaining: number,
|
|
103
|
+
units: number,
|
|
64
104
|
): AssistantContentBlock {
|
|
65
105
|
if (remaining <= 0) return block.thinking.length === 0 ? block : { ...block, thinking: "" };
|
|
66
|
-
const units = countGraphemes(block.thinking);
|
|
67
106
|
if (remaining >= units) return block;
|
|
68
107
|
return { ...block, thinking: sliceGraphemes(block.thinking, remaining) };
|
|
69
108
|
}
|
|
@@ -72,16 +111,20 @@ export function buildDisplayMessage(
|
|
|
72
111
|
target: AssistantMessage,
|
|
73
112
|
revealed: number,
|
|
74
113
|
hideThinking: boolean,
|
|
114
|
+
countOf: (index: number, text: string) => number = (_index, text) => countGraphemes(text),
|
|
75
115
|
): AssistantMessage {
|
|
76
116
|
let remaining = Math.max(0, Math.floor(revealed));
|
|
77
117
|
const content: AssistantContentBlock[] = [];
|
|
78
|
-
for (
|
|
118
|
+
for (let i = 0; i < target.content.length; i++) {
|
|
119
|
+
const block = target.content[i]!;
|
|
79
120
|
if (block.type === "text") {
|
|
80
|
-
|
|
81
|
-
|
|
121
|
+
const units = countOf(i, block.text);
|
|
122
|
+
content.push(revealTextBlock(block, remaining, units));
|
|
123
|
+
remaining = Math.max(0, remaining - units);
|
|
82
124
|
} else if (block.type === "thinking" && !hideThinking) {
|
|
83
|
-
|
|
84
|
-
|
|
125
|
+
const units = countOf(i, block.thinking);
|
|
126
|
+
content.push(revealThinkingBlock(block, remaining, units));
|
|
127
|
+
remaining = Math.max(0, remaining - units);
|
|
85
128
|
} else {
|
|
86
129
|
content.push(block);
|
|
87
130
|
}
|
|
@@ -103,6 +146,8 @@ export class StreamingRevealController {
|
|
|
103
146
|
#revealed = 0;
|
|
104
147
|
#hideThinkingBlock = false;
|
|
105
148
|
#smoothStreaming = true;
|
|
149
|
+
readonly #unitCounter = new BlockUnitCounter();
|
|
150
|
+
readonly #countOf = (index: number, text: string): number => this.#unitCounter.count(index, text);
|
|
106
151
|
|
|
107
152
|
constructor(options: StreamingRevealControllerOptions) {
|
|
108
153
|
this.#getSmoothStreaming = options.getSmoothStreaming;
|
|
@@ -121,15 +166,15 @@ export class StreamingRevealController {
|
|
|
121
166
|
component.updateContent(message);
|
|
122
167
|
return;
|
|
123
168
|
}
|
|
124
|
-
const total = visibleUnits(message
|
|
169
|
+
const total = this.#visibleUnits(message);
|
|
125
170
|
if (message.content.some(block => block.type === "toolCall")) {
|
|
126
171
|
// A tool call is a transcript-order boundary: finish any leading
|
|
127
172
|
// assistant text before EventController renders the separate tool card.
|
|
128
173
|
this.#revealed = total;
|
|
129
|
-
component.updateContent(buildDisplayMessage(message, this.#revealed, this.#hideThinkingBlock));
|
|
174
|
+
component.updateContent(buildDisplayMessage(message, this.#revealed, this.#hideThinkingBlock, this.#countOf));
|
|
130
175
|
return;
|
|
131
176
|
}
|
|
132
|
-
this.#renderCurrent();
|
|
177
|
+
this.#renderCurrent(total);
|
|
133
178
|
this.#syncTimer(total);
|
|
134
179
|
}
|
|
135
180
|
|
|
@@ -140,19 +185,21 @@ export class StreamingRevealController {
|
|
|
140
185
|
this.#component.updateContent(message);
|
|
141
186
|
return;
|
|
142
187
|
}
|
|
143
|
-
const total = visibleUnits(message
|
|
188
|
+
const total = this.#visibleUnits(message);
|
|
144
189
|
if (message.content.some(block => block.type === "toolCall")) {
|
|
145
190
|
// A tool call is a transcript-order boundary: finish any leading
|
|
146
191
|
// assistant text before EventController renders the separate tool card.
|
|
147
192
|
this.#revealed = total;
|
|
148
193
|
this.#stopTimer();
|
|
149
|
-
this.#component.updateContent(
|
|
194
|
+
this.#component.updateContent(
|
|
195
|
+
buildDisplayMessage(message, this.#revealed, this.#hideThinkingBlock, this.#countOf),
|
|
196
|
+
);
|
|
150
197
|
return;
|
|
151
198
|
}
|
|
152
199
|
if (this.#revealed > total) {
|
|
153
200
|
this.#revealed = total;
|
|
154
201
|
}
|
|
155
|
-
this.#renderCurrent();
|
|
202
|
+
this.#renderCurrent(total);
|
|
156
203
|
this.#syncTimer(total);
|
|
157
204
|
}
|
|
158
205
|
|
|
@@ -161,14 +208,32 @@ export class StreamingRevealController {
|
|
|
161
208
|
this.#target = undefined;
|
|
162
209
|
this.#component = undefined;
|
|
163
210
|
this.#revealed = 0;
|
|
211
|
+
this.#unitCounter.reset();
|
|
212
|
+
}
|
|
213
|
+
|
|
214
|
+
/** Total reveal units of `message`, memoized per block across ticks. */
|
|
215
|
+
#visibleUnits(message: AssistantMessage): number {
|
|
216
|
+
let total = 0;
|
|
217
|
+
for (let i = 0; i < message.content.length; i++) {
|
|
218
|
+
const block = message.content[i]!;
|
|
219
|
+
if (block.type === "text") {
|
|
220
|
+
total += this.#unitCounter.count(i, block.text);
|
|
221
|
+
} else if (block.type === "thinking" && !this.#hideThinkingBlock) {
|
|
222
|
+
total += this.#unitCounter.count(i, block.thinking);
|
|
223
|
+
}
|
|
224
|
+
}
|
|
225
|
+
return total;
|
|
164
226
|
}
|
|
165
227
|
|
|
166
|
-
#renderCurrent(): void {
|
|
228
|
+
#renderCurrent(total = this.#target ? this.#visibleUnits(this.#target) : 0): void {
|
|
167
229
|
if (!this.#target || !this.#component) return;
|
|
168
|
-
this.#component.updateContent(
|
|
230
|
+
this.#component.updateContent(
|
|
231
|
+
buildDisplayMessage(this.#target, this.#revealed, this.#hideThinkingBlock, this.#countOf),
|
|
232
|
+
{ transient: this.#revealed < total },
|
|
233
|
+
);
|
|
169
234
|
}
|
|
170
235
|
|
|
171
|
-
#syncTimer(total = this.#target ? visibleUnits(this.#target
|
|
236
|
+
#syncTimer(total = this.#target ? this.#visibleUnits(this.#target) : 0): void {
|
|
172
237
|
if (!this.#target || !this.#component || this.#revealed >= total) {
|
|
173
238
|
this.#stopTimer();
|
|
174
239
|
return;
|
|
@@ -197,13 +262,15 @@ export class StreamingRevealController {
|
|
|
197
262
|
this.stop();
|
|
198
263
|
return;
|
|
199
264
|
}
|
|
200
|
-
const total = visibleUnits(target
|
|
265
|
+
const total = this.#visibleUnits(target);
|
|
201
266
|
if (this.#revealed >= total) {
|
|
202
267
|
this.#stopTimer();
|
|
203
268
|
return;
|
|
204
269
|
}
|
|
205
270
|
this.#revealed = Math.min(total, this.#revealed + nextStep(total - this.#revealed));
|
|
206
|
-
component.updateContent(buildDisplayMessage(target, this.#revealed, this.#hideThinkingBlock)
|
|
271
|
+
component.updateContent(buildDisplayMessage(target, this.#revealed, this.#hideThinkingBlock, this.#countOf), {
|
|
272
|
+
transient: this.#revealed < total,
|
|
273
|
+
});
|
|
207
274
|
this.#requestRender();
|
|
208
275
|
if (this.#revealed >= total) {
|
|
209
276
|
this.#stopTimer();
|
package/src/modes/index.ts
CHANGED
|
@@ -8,27 +8,9 @@ import { postmortem } from "@oh-my-pi/pi-utils";
|
|
|
8
8
|
* barrel does not pull print, RPC server, or ACP server mode into the normal
|
|
9
9
|
* TUI graph.
|
|
10
10
|
*/
|
|
11
|
-
export
|
|
12
|
-
export
|
|
13
|
-
|
|
14
|
-
type ModelInfo,
|
|
15
|
-
RpcClient,
|
|
16
|
-
type RpcClientCustomTool,
|
|
17
|
-
type RpcClientOptions,
|
|
18
|
-
type RpcClientToolContext,
|
|
19
|
-
type RpcClientToolResult,
|
|
20
|
-
type RpcEventListener,
|
|
21
|
-
} from "./rpc/rpc-client";
|
|
22
|
-
export type {
|
|
23
|
-
RpcCommand,
|
|
24
|
-
RpcHostToolCallRequest,
|
|
25
|
-
RpcHostToolCancelRequest,
|
|
26
|
-
RpcHostToolDefinition,
|
|
27
|
-
RpcHostToolResult,
|
|
28
|
-
RpcHostToolUpdate,
|
|
29
|
-
RpcResponse,
|
|
30
|
-
RpcSessionState,
|
|
31
|
-
} from "./rpc/rpc-types";
|
|
11
|
+
export * from "./interactive-mode";
|
|
12
|
+
export * from "./rpc/rpc-client";
|
|
13
|
+
export * from "./rpc/rpc-types";
|
|
32
14
|
|
|
33
15
|
postmortem.register("terminal-restore", () => {
|
|
34
16
|
emergencyTerminalRestore();
|
|
@@ -12,14 +12,8 @@ import {
|
|
|
12
12
|
ThinkingLevel,
|
|
13
13
|
} from "@oh-my-pi/pi-agent-core";
|
|
14
14
|
import type { CompactionOutcome } from "@oh-my-pi/pi-agent-core/compaction";
|
|
15
|
-
import {
|
|
16
|
-
|
|
17
|
-
type ImageContent,
|
|
18
|
-
type Message,
|
|
19
|
-
type Model,
|
|
20
|
-
modelsAreEqual,
|
|
21
|
-
type UsageReport,
|
|
22
|
-
} from "@oh-my-pi/pi-ai";
|
|
15
|
+
import type { AssistantMessage, ImageContent, Message, Model, UsageReport } from "@oh-my-pi/pi-ai";
|
|
16
|
+
import { modelsAreEqual } from "@oh-my-pi/pi-catalog/models";
|
|
23
17
|
import type { Component, EditorTheme, LoaderMessageColorFn, OverlayHandle, SlashCommand } from "@oh-my-pi/pi-tui";
|
|
24
18
|
import {
|
|
25
19
|
Container,
|
|
@@ -49,7 +43,7 @@ import {
|
|
|
49
43
|
import chalk from "chalk";
|
|
50
44
|
import { reset as resetCapabilities } from "../capability";
|
|
51
45
|
import { KeybindingsManager } from "../config/keybindings";
|
|
52
|
-
import { MODEL_ROLES, type ModelRole } from "../config/model-
|
|
46
|
+
import { MODEL_ROLES, type ModelRole } from "../config/model-roles";
|
|
53
47
|
import { isSettingsInitialized, onStatusLineSessionAccentChanged, Settings, settings } from "../config/settings";
|
|
54
48
|
import { clearClaudePluginRootsCache } from "../discovery/helpers";
|
|
55
49
|
import type {
|
|
@@ -65,6 +59,7 @@ import { BUILTIN_SLASH_COMMANDS, loadSlashCommands } from "../extensibility/slas
|
|
|
65
59
|
import type { Goal, GoalModeState } from "../goals/state";
|
|
66
60
|
import { resolveLocalUrlToPath } from "../internal-urls";
|
|
67
61
|
import { LSP_STARTUP_EVENT_CHANNEL, type LspStartupEvent } from "../lsp/startup-events";
|
|
62
|
+
import type { MCPManager } from "../mcp";
|
|
68
63
|
import {
|
|
69
64
|
humanizePlanTitle,
|
|
70
65
|
type PlanApprovalDetails,
|
|
@@ -80,8 +75,10 @@ import { HistoryStorage } from "../session/history-storage";
|
|
|
80
75
|
import type { SessionContext, SessionManager } from "../session/session-manager";
|
|
81
76
|
import { getRecentSessions } from "../session/session-manager";
|
|
82
77
|
import type { ShakeMode } from "../session/shake-types";
|
|
78
|
+
import { BUILTIN_SLASH_COMMAND_RESERVED_NAMES } from "../slash-commands/builtin-registry";
|
|
83
79
|
import { formatDuration } from "../slash-commands/helpers/format";
|
|
84
80
|
import { STTController, type SttState } from "../stt";
|
|
81
|
+
import { discoverTitleSystemPromptFile, resolvePromptInput } from "../system-prompt";
|
|
85
82
|
import type { LspStartupServerInfo } from "../tools";
|
|
86
83
|
import { normalizeLocalScheme } from "../tools/path-utils";
|
|
87
84
|
import { setAutoQaConsentHandler } from "../tools/report-tool-issue";
|
|
@@ -129,6 +126,7 @@ import {
|
|
|
129
126
|
} from "./loop-limit";
|
|
130
127
|
import { OAuthManualInputManager } from "./oauth-manual-input";
|
|
131
128
|
import { SessionObserverRegistry } from "./session-observer-registry";
|
|
129
|
+
import { runProviderSetupWizard } from "./setup-wizard/lazy";
|
|
132
130
|
import { interruptHint } from "./shared";
|
|
133
131
|
import { type ShimmerPalette, shimmerEnabled, shimmerSegments, shimmerText } from "./theme/shimmer";
|
|
134
132
|
import type { Theme } from "./theme/theme";
|
|
@@ -266,6 +264,7 @@ export class InteractiveMode implements InteractiveModeContext {
|
|
|
266
264
|
keybindings: KeybindingsManager;
|
|
267
265
|
agent: Agent;
|
|
268
266
|
historyStorage?: HistoryStorage;
|
|
267
|
+
titleSystemPrompt?: string;
|
|
269
268
|
|
|
270
269
|
ui: TUI;
|
|
271
270
|
chatContainer: TranscriptContainer;
|
|
@@ -355,7 +354,7 @@ export class InteractiveMode implements InteractiveModeContext {
|
|
|
355
354
|
#planReviewOverlay: PlanReviewOverlay | undefined;
|
|
356
355
|
#planReviewOverlayHandle: OverlayHandle | undefined;
|
|
357
356
|
readonly lspServers: LspStartupServerInfo[] | undefined = undefined;
|
|
358
|
-
mcpManager?:
|
|
357
|
+
mcpManager?: MCPManager;
|
|
359
358
|
readonly #toolUiContextSetter: (uiContext: ExtensionUIContext, hasUI: boolean) => void;
|
|
360
359
|
|
|
361
360
|
readonly #btwController: BtwController;
|
|
@@ -386,8 +385,9 @@ export class InteractiveMode implements InteractiveModeContext {
|
|
|
386
385
|
changelogMarkdown: string | undefined = undefined,
|
|
387
386
|
setToolUIContext: (uiContext: ExtensionUIContext, hasUI: boolean) => void = () => {},
|
|
388
387
|
lspServers: LspStartupServerInfo[] | undefined = undefined,
|
|
389
|
-
mcpManager?:
|
|
388
|
+
mcpManager?: MCPManager,
|
|
390
389
|
eventBus?: EventBus,
|
|
390
|
+
titleSystemPrompt?: string,
|
|
391
391
|
) {
|
|
392
392
|
this.session = session;
|
|
393
393
|
this.sessionManager = session.sessionManager;
|
|
@@ -400,6 +400,7 @@ export class InteractiveMode implements InteractiveModeContext {
|
|
|
400
400
|
this.lspServers = lspServers;
|
|
401
401
|
this.mcpManager = mcpManager;
|
|
402
402
|
this.#eventBus = eventBus;
|
|
403
|
+
this.titleSystemPrompt = titleSystemPrompt;
|
|
403
404
|
if (eventBus) {
|
|
404
405
|
this.#eventBusUnsubscribers.push(
|
|
405
406
|
eventBus.on(LSP_STARTUP_EVENT_CHANNEL, data => {
|
|
@@ -453,9 +454,8 @@ export class InteractiveMode implements InteractiveModeContext {
|
|
|
453
454
|
|
|
454
455
|
this.hideThinkingBlock = settings.get("hideThinkingBlock");
|
|
455
456
|
|
|
456
|
-
const builtinCommandNames = new Set(BUILTIN_SLASH_COMMANDS.map(c => c.name));
|
|
457
457
|
const hookCommands: SlashCommand[] = (
|
|
458
|
-
this.session.extensionRunner?.getRegisteredCommands(
|
|
458
|
+
this.session.extensionRunner?.getRegisteredCommands(BUILTIN_SLASH_COMMAND_RESERVED_NAMES) ?? []
|
|
459
459
|
).map(cmd => ({
|
|
460
460
|
name: cmd.name,
|
|
461
461
|
description: cmd.description ?? "(hook command)",
|
|
@@ -685,6 +685,13 @@ export class InteractiveMode implements InteractiveModeContext {
|
|
|
685
685
|
this.updateEditorTopBorder();
|
|
686
686
|
}
|
|
687
687
|
|
|
688
|
+
/** Reload the title-generation system prompt override for the provided working directory. */
|
|
689
|
+
async refreshTitleSystemPrompt(cwd?: string): Promise<void> {
|
|
690
|
+
const basePath = cwd ?? this.sessionManager.getCwd();
|
|
691
|
+
const titleSystemPromptSource = discoverTitleSystemPromptFile(basePath);
|
|
692
|
+
this.titleSystemPrompt = await resolvePromptInput(titleSystemPromptSource, "title system prompt");
|
|
693
|
+
}
|
|
694
|
+
|
|
688
695
|
/** Reload slash commands and autocomplete for the provided working directory. */
|
|
689
696
|
async refreshSlashCommandState(cwd?: string): Promise<void> {
|
|
690
697
|
const basePath = cwd ?? this.sessionManager.getCwd();
|
|
@@ -719,6 +726,7 @@ export class InteractiveMode implements InteractiveModeContext {
|
|
|
719
726
|
// Re-warm plugin roots, capabilities, slash commands, and the ssh tool so
|
|
720
727
|
// the next prompt sees everything scoped to the new project directory.
|
|
721
728
|
clearClaudePluginRootsCache();
|
|
729
|
+
await this.refreshTitleSystemPrompt(newCwd);
|
|
722
730
|
resetCapabilities();
|
|
723
731
|
await this.refreshSlashCommandState(newCwd);
|
|
724
732
|
await this.session.refreshSshTool({ activateIfAvailable: true });
|
|
@@ -1700,6 +1708,15 @@ export class InteractiveMode implements InteractiveModeContext {
|
|
|
1700
1708
|
}
|
|
1701
1709
|
}
|
|
1702
1710
|
|
|
1711
|
+
async #hasPlanModeDraftContent(planFilePath: string): Promise<boolean> {
|
|
1712
|
+
const candidates = new Set<string>([planFilePath, ...(await this.#listLocalPlanFiles())]);
|
|
1713
|
+
for (const candidate of candidates) {
|
|
1714
|
+
const content = await this.#readPlanFile(candidate);
|
|
1715
|
+
if (content !== null && content.trim().length > 0) return true;
|
|
1716
|
+
}
|
|
1717
|
+
return false;
|
|
1718
|
+
}
|
|
1719
|
+
|
|
1703
1720
|
/** `local://` URLs of plan files in the session-local root, newest first.
|
|
1704
1721
|
* A fallback for `resolveApprovedPlan` when the agent dropped `extra.title`,
|
|
1705
1722
|
* so the plan it wrote is still found by scanning recent `*-plan.md` files. */
|
|
@@ -2004,11 +2021,14 @@ export class InteractiveMode implements InteractiveModeContext {
|
|
|
2004
2021
|
return;
|
|
2005
2022
|
}
|
|
2006
2023
|
if (this.planModeEnabled) {
|
|
2007
|
-
const
|
|
2008
|
-
|
|
2009
|
-
|
|
2010
|
-
|
|
2011
|
-
|
|
2024
|
+
const planFilePath = this.planModePlanFilePath ?? (await this.#getPlanFilePath());
|
|
2025
|
+
if (await this.#hasPlanModeDraftContent(planFilePath)) {
|
|
2026
|
+
const confirmed = await this.showHookConfirm(
|
|
2027
|
+
"Exit plan mode?",
|
|
2028
|
+
"This exits plan mode without approving a plan.",
|
|
2029
|
+
);
|
|
2030
|
+
if (!confirmed) return;
|
|
2031
|
+
}
|
|
2012
2032
|
await this.#exitPlanMode({ paused: true });
|
|
2013
2033
|
return;
|
|
2014
2034
|
}
|
|
@@ -3159,6 +3179,10 @@ export class InteractiveMode implements InteractiveModeContext {
|
|
|
3159
3179
|
return this.#selectorController.showOAuthSelector(mode, providerId);
|
|
3160
3180
|
}
|
|
3161
3181
|
|
|
3182
|
+
showProviderSetup(): Promise<void> {
|
|
3183
|
+
return runProviderSetupWizard(this);
|
|
3184
|
+
}
|
|
3185
|
+
|
|
3162
3186
|
showHookConfirm(title: string, message: string): Promise<boolean> {
|
|
3163
3187
|
return this.#extensionUiController.showHookConfirm(title, message);
|
|
3164
3188
|
}
|
|
@@ -3,6 +3,10 @@ type PendingInput = {
|
|
|
3
3
|
resolve: (value: string) => void;
|
|
4
4
|
reject: (error: Error) => void;
|
|
5
5
|
};
|
|
6
|
+
type ClaimedInput = {
|
|
7
|
+
promise: Promise<string>;
|
|
8
|
+
clear: (reason?: string) => void;
|
|
9
|
+
};
|
|
6
10
|
|
|
7
11
|
export class OAuthManualInputManager {
|
|
8
12
|
#pending?: PendingInput;
|
|
@@ -12,9 +16,27 @@ export class OAuthManualInputManager {
|
|
|
12
16
|
this.clear("Manual OAuth input superseded by a new login");
|
|
13
17
|
}
|
|
14
18
|
|
|
15
|
-
const
|
|
16
|
-
this.#pending =
|
|
17
|
-
return promise;
|
|
19
|
+
const pending = this.#createPending(providerId);
|
|
20
|
+
this.#pending = pending;
|
|
21
|
+
return pending.promise;
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
tryWaitForInput(providerId: string): Promise<string> | undefined {
|
|
25
|
+
if (this.#pending) return undefined;
|
|
26
|
+
return this.waitForInput(providerId);
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
tryClaimInput(providerId: string): ClaimedInput | undefined {
|
|
30
|
+
if (this.#pending) return undefined;
|
|
31
|
+
const pending = this.#createPending(providerId);
|
|
32
|
+
this.#pending = pending;
|
|
33
|
+
return {
|
|
34
|
+
promise: pending.promise,
|
|
35
|
+
clear: (reason?: string) => {
|
|
36
|
+
if (this.#pending !== pending) return;
|
|
37
|
+
this.clear(reason);
|
|
38
|
+
},
|
|
39
|
+
};
|
|
18
40
|
}
|
|
19
41
|
|
|
20
42
|
submit(input: string): boolean {
|
|
@@ -39,4 +61,9 @@ export class OAuthManualInputManager {
|
|
|
39
61
|
get pendingProviderId(): string | undefined {
|
|
40
62
|
return this.#pending?.providerId;
|
|
41
63
|
}
|
|
64
|
+
|
|
65
|
+
#createPending(providerId: string): PendingInput & { promise: Promise<string> } {
|
|
66
|
+
const { promise, resolve, reject } = Promise.withResolvers<string>();
|
|
67
|
+
return { providerId, resolve, reject, promise };
|
|
68
|
+
}
|
|
42
69
|
}
|
|
@@ -9,8 +9,9 @@ import type { AgentEvent, AgentMessage, AgentToolResult, ThinkingLevel } from "@
|
|
|
9
9
|
import type { CompactionResult } from "@oh-my-pi/pi-agent-core/compaction";
|
|
10
10
|
import type { ImageContent, Model } from "@oh-my-pi/pi-ai";
|
|
11
11
|
import { isRecord, ptree, readJsonl } from "@oh-my-pi/pi-utils";
|
|
12
|
+
import type { FileSink } from "bun";
|
|
12
13
|
import type { BashResult } from "../../exec/bash-executor";
|
|
13
|
-
import type { SessionStats } from "../../session/agent-session";
|
|
14
|
+
import type { AgentSessionEvent, SessionStats } from "../../session/agent-session";
|
|
14
15
|
import type {
|
|
15
16
|
RpcCommand,
|
|
16
17
|
RpcExtensionUIRequest,
|
|
@@ -22,6 +23,12 @@ import type {
|
|
|
22
23
|
RpcHostToolUpdate,
|
|
23
24
|
RpcResponse,
|
|
24
25
|
RpcSessionState,
|
|
26
|
+
RpcSubagentEventFrame,
|
|
27
|
+
RpcSubagentLifecycleFrame,
|
|
28
|
+
RpcSubagentMessagesResult,
|
|
29
|
+
RpcSubagentProgressFrame,
|
|
30
|
+
RpcSubagentSnapshot,
|
|
31
|
+
RpcSubagentSubscriptionLevel,
|
|
25
32
|
} from "./rpc-types";
|
|
26
33
|
|
|
27
34
|
/** Distributive Omit that works with union types */
|
|
@@ -52,6 +59,10 @@ export interface RpcClientOptions {
|
|
|
52
59
|
export type ModelInfo = Pick<Model, "provider" | "id" | "contextWindow" | "reasoning" | "thinking">;
|
|
53
60
|
|
|
54
61
|
export type RpcEventListener = (event: AgentEvent) => void;
|
|
62
|
+
export type RpcSessionEventListener = (event: AgentSessionEvent) => void;
|
|
63
|
+
export type RpcSubagentLifecycleListener = (payload: RpcSubagentLifecycleFrame["payload"]) => void;
|
|
64
|
+
export type RpcSubagentProgressListener = (payload: RpcSubagentProgressFrame["payload"]) => void;
|
|
65
|
+
export type RpcSubagentEventListener = (payload: RpcSubagentEventFrame["payload"]) => void;
|
|
55
66
|
|
|
56
67
|
export interface RpcClientToolContext<TDetails = unknown> {
|
|
57
68
|
toolCallId: string;
|
|
@@ -92,6 +103,23 @@ const agentEventTypes = new Set<AgentEvent["type"]>([
|
|
|
92
103
|
"tool_execution_end",
|
|
93
104
|
]);
|
|
94
105
|
|
|
106
|
+
const sessionEventTypes = new Set<AgentSessionEvent["type"]>([
|
|
107
|
+
...agentEventTypes,
|
|
108
|
+
"auto_compaction_start",
|
|
109
|
+
"auto_compaction_end",
|
|
110
|
+
"auto_retry_start",
|
|
111
|
+
"auto_retry_end",
|
|
112
|
+
"retry_fallback_applied",
|
|
113
|
+
"retry_fallback_succeeded",
|
|
114
|
+
"ttsr_triggered",
|
|
115
|
+
"todo_reminder",
|
|
116
|
+
"todo_auto_clear",
|
|
117
|
+
"irc_message",
|
|
118
|
+
"notice",
|
|
119
|
+
"thinking_level_changed",
|
|
120
|
+
"goal_updated",
|
|
121
|
+
]);
|
|
122
|
+
|
|
95
123
|
function isRpcResponse(value: unknown): value is RpcResponse {
|
|
96
124
|
if (!isRecord(value)) return false;
|
|
97
125
|
if (value.type !== "response") return false;
|
|
@@ -111,6 +139,28 @@ function isAgentEvent(value: unknown): value is AgentEvent {
|
|
|
111
139
|
return agentEventTypes.has(type as AgentEvent["type"]);
|
|
112
140
|
}
|
|
113
141
|
|
|
142
|
+
function isAgentSessionEvent(value: unknown): value is AgentSessionEvent {
|
|
143
|
+
if (!isRecord(value)) return false;
|
|
144
|
+
const type = value.type;
|
|
145
|
+
if (typeof type !== "string") return false;
|
|
146
|
+
return sessionEventTypes.has(type as AgentSessionEvent["type"]);
|
|
147
|
+
}
|
|
148
|
+
|
|
149
|
+
function isRpcSubagentLifecycleFrame(value: unknown): value is RpcSubagentLifecycleFrame {
|
|
150
|
+
if (!isRecord(value)) return false;
|
|
151
|
+
return value.type === "subagent_lifecycle" && isRecord(value.payload);
|
|
152
|
+
}
|
|
153
|
+
|
|
154
|
+
function isRpcSubagentProgressFrame(value: unknown): value is RpcSubagentProgressFrame {
|
|
155
|
+
if (!isRecord(value)) return false;
|
|
156
|
+
return value.type === "subagent_progress" && isRecord(value.payload);
|
|
157
|
+
}
|
|
158
|
+
|
|
159
|
+
function isRpcSubagentEventFrame(value: unknown): value is RpcSubagentEventFrame {
|
|
160
|
+
if (!isRecord(value)) return false;
|
|
161
|
+
return value.type === "subagent_event" && isRecord(value.payload);
|
|
162
|
+
}
|
|
163
|
+
|
|
114
164
|
function isRpcHostToolCallRequest(value: unknown): value is RpcHostToolCallRequest {
|
|
115
165
|
if (!isRecord(value)) return false;
|
|
116
166
|
return (
|
|
@@ -148,6 +198,10 @@ function normalizeToolResult<TDetails>(result: RpcClientToolResult<TDetails>): A
|
|
|
148
198
|
export class RpcClient {
|
|
149
199
|
#process: ptree.ChildProcess | null = null;
|
|
150
200
|
#eventListeners: RpcEventListener[] = [];
|
|
201
|
+
#sessionEventListeners: RpcSessionEventListener[] = [];
|
|
202
|
+
#subagentLifecycleListeners = new Set<RpcSubagentLifecycleListener>();
|
|
203
|
+
#subagentProgressListeners = new Set<RpcSubagentProgressListener>();
|
|
204
|
+
#subagentEventListeners = new Set<RpcSubagentEventListener>();
|
|
151
205
|
#pendingRequests: Map<string, { resolve: (response: RpcResponse) => void; reject: (error: Error) => void }> =
|
|
152
206
|
new Map();
|
|
153
207
|
#customTools: RpcClientCustomTool[] = [];
|
|
@@ -286,6 +340,43 @@ export class RpcClient {
|
|
|
286
340
|
};
|
|
287
341
|
}
|
|
288
342
|
|
|
343
|
+
/**
|
|
344
|
+
* Subscribe to all top-level session events, including non-core session state events.
|
|
345
|
+
*/
|
|
346
|
+
onSessionEvent(listener: RpcSessionEventListener): () => void {
|
|
347
|
+
this.#sessionEventListeners.push(listener);
|
|
348
|
+
return () => {
|
|
349
|
+
const index = this.#sessionEventListeners.indexOf(listener);
|
|
350
|
+
if (index !== -1) {
|
|
351
|
+
this.#sessionEventListeners.splice(index, 1);
|
|
352
|
+
}
|
|
353
|
+
};
|
|
354
|
+
}
|
|
355
|
+
|
|
356
|
+
/**
|
|
357
|
+
* Subscribe to subagent lifecycle frames after setSubagentSubscription("progress" | "events").
|
|
358
|
+
*/
|
|
359
|
+
onSubagentLifecycle(listener: RpcSubagentLifecycleListener): () => void {
|
|
360
|
+
this.#subagentLifecycleListeners.add(listener);
|
|
361
|
+
return () => this.#subagentLifecycleListeners.delete(listener);
|
|
362
|
+
}
|
|
363
|
+
|
|
364
|
+
/**
|
|
365
|
+
* Subscribe to aggregated subagent progress frames after setSubagentSubscription("progress" | "events").
|
|
366
|
+
*/
|
|
367
|
+
onSubagentProgress(listener: RpcSubagentProgressListener): () => void {
|
|
368
|
+
this.#subagentProgressListeners.add(listener);
|
|
369
|
+
return () => this.#subagentProgressListeners.delete(listener);
|
|
370
|
+
}
|
|
371
|
+
|
|
372
|
+
/**
|
|
373
|
+
* Subscribe to raw subagent session events. Call setSubagentSubscription(\"events\") to enable them server-side.
|
|
374
|
+
*/
|
|
375
|
+
onSubagentEvent(listener: RpcSubagentEventListener): () => void {
|
|
376
|
+
this.#subagentEventListeners.add(listener);
|
|
377
|
+
return () => this.#subagentEventListeners.delete(listener);
|
|
378
|
+
}
|
|
379
|
+
|
|
289
380
|
/**
|
|
290
381
|
* Get collected stderr output (useful for debugging).
|
|
291
382
|
*/
|
|
@@ -358,6 +449,40 @@ export class RpcClient {
|
|
|
358
449
|
return this.#getData(response);
|
|
359
450
|
}
|
|
360
451
|
|
|
452
|
+
/**
|
|
453
|
+
* Configure subagent frames emitted by the RPC server. Servers default to "off".
|
|
454
|
+
* "progress" emits lifecycle/progress frames; "events" additionally emits raw subagent session events.
|
|
455
|
+
*/
|
|
456
|
+
async setSubagentSubscription(level: RpcSubagentSubscriptionLevel): Promise<RpcSubagentSubscriptionLevel> {
|
|
457
|
+
const response = await this.#send({ type: "set_subagent_subscription", level });
|
|
458
|
+
return this.#getData<{ level: RpcSubagentSubscriptionLevel }>(response).level;
|
|
459
|
+
}
|
|
460
|
+
|
|
461
|
+
/**
|
|
462
|
+
* Return the RPC server's current subagent snapshot.
|
|
463
|
+
*/
|
|
464
|
+
async getSubagents(): Promise<RpcSubagentSnapshot[]> {
|
|
465
|
+
const response = await this.#send({ type: "get_subagents" });
|
|
466
|
+
return this.#getData<{ subagents: RpcSubagentSnapshot[] }>(response).subagents;
|
|
467
|
+
}
|
|
468
|
+
|
|
469
|
+
/**
|
|
470
|
+
* Read persisted transcript entries for a tracked subagent session.
|
|
471
|
+
*/
|
|
472
|
+
async getSubagentMessages(selector: {
|
|
473
|
+
subagentId?: string;
|
|
474
|
+
sessionFile?: string;
|
|
475
|
+
fromByte?: number;
|
|
476
|
+
}): Promise<RpcSubagentMessagesResult> {
|
|
477
|
+
const response = await this.#send({
|
|
478
|
+
type: "get_subagent_messages",
|
|
479
|
+
subagentId: selector.subagentId,
|
|
480
|
+
sessionFile: selector.sessionFile,
|
|
481
|
+
fromByte: selector.fromByte,
|
|
482
|
+
});
|
|
483
|
+
return this.#getData<RpcSubagentMessagesResult>(response);
|
|
484
|
+
}
|
|
485
|
+
|
|
361
486
|
/**
|
|
362
487
|
* Set model by provider and ID.
|
|
363
488
|
*/
|
|
@@ -679,9 +804,35 @@ export class RpcClient {
|
|
|
679
804
|
return;
|
|
680
805
|
}
|
|
681
806
|
|
|
807
|
+
if (isRpcSubagentLifecycleFrame(data)) {
|
|
808
|
+
for (const listener of this.#subagentLifecycleListeners) {
|
|
809
|
+
listener(data.payload);
|
|
810
|
+
}
|
|
811
|
+
return;
|
|
812
|
+
}
|
|
813
|
+
|
|
814
|
+
if (isRpcSubagentProgressFrame(data)) {
|
|
815
|
+
for (const listener of this.#subagentProgressListeners) {
|
|
816
|
+
listener(data.payload);
|
|
817
|
+
}
|
|
818
|
+
return;
|
|
819
|
+
}
|
|
820
|
+
|
|
821
|
+
if (isRpcSubagentEventFrame(data)) {
|
|
822
|
+
for (const listener of this.#subagentEventListeners) {
|
|
823
|
+
listener(data.payload);
|
|
824
|
+
}
|
|
825
|
+
return;
|
|
826
|
+
}
|
|
827
|
+
|
|
828
|
+
if (!isAgentSessionEvent(data)) return;
|
|
829
|
+
|
|
830
|
+
for (const listener of this.#sessionEventListeners) {
|
|
831
|
+
listener(data);
|
|
832
|
+
}
|
|
833
|
+
|
|
682
834
|
if (!isAgentEvent(data)) return;
|
|
683
835
|
|
|
684
|
-
// Otherwise it's an event
|
|
685
836
|
for (const listener of this.#eventListeners) {
|
|
686
837
|
listener(data);
|
|
687
838
|
}
|
|
@@ -789,7 +940,7 @@ export class RpcClient {
|
|
|
789
940
|
if (!this.#process?.stdin) {
|
|
790
941
|
throw new Error("Client not started");
|
|
791
942
|
}
|
|
792
|
-
const stdin = this.#process.stdin as
|
|
943
|
+
const stdin = this.#process.stdin as FileSink;
|
|
793
944
|
stdin.write(`${JSON.stringify(frame)}\n`);
|
|
794
945
|
const flushResult = stdin.flush();
|
|
795
946
|
if (isPromise(flushResult)) {
|