@oh-my-pi/pi-coding-agent 15.12.3 → 15.13.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +347 -7
- package/dist/cli.js +1615 -1231
- package/dist/types/async/job-manager.d.ts +15 -0
- package/dist/types/autolearn/controller.d.ts +25 -0
- package/dist/types/autolearn/managed-skills.d.ts +45 -0
- package/dist/types/autoresearch/state.d.ts +1 -1
- package/dist/types/autoresearch/tools/init-experiment.d.ts +1 -1
- package/dist/types/autoresearch/tools/log-experiment.d.ts +1 -1
- package/dist/types/autoresearch/tools/run-experiment.d.ts +1 -1
- package/dist/types/autoresearch/tools/update-notes.d.ts +1 -1
- package/dist/types/autoresearch/types.d.ts +1 -1
- package/dist/types/cli/args.d.ts +19 -2
- package/dist/types/cli/models-cli.d.ts +49 -0
- package/dist/types/cli/session-picker.d.ts +1 -1
- package/dist/types/cli/setup-cli.d.ts +1 -1
- package/dist/types/cli/setup-model-picker.d.ts +14 -0
- package/dist/types/collab/protocol.d.ts +1 -1
- package/dist/types/commands/launch.d.ts +0 -3
- package/dist/types/commands/models.d.ts +33 -0
- package/dist/types/commands/say.d.ts +24 -0
- package/dist/types/commands/token.d.ts +25 -0
- package/dist/types/commit/agentic/tools/analyze-file.d.ts +1 -1
- package/dist/types/commit/agentic/tools/git-file-diff.d.ts +1 -1
- package/dist/types/commit/agentic/tools/git-hunk.d.ts +1 -1
- package/dist/types/commit/agentic/tools/git-overview.d.ts +1 -1
- package/dist/types/commit/agentic/tools/propose-changelog.d.ts +1 -1
- package/dist/types/commit/agentic/tools/propose-commit.d.ts +1 -1
- package/dist/types/commit/agentic/tools/recent-commits.d.ts +1 -1
- package/dist/types/commit/agentic/tools/schemas.d.ts +1 -1
- package/dist/types/commit/agentic/tools/split-commit.d.ts +1 -1
- package/dist/types/commit/changelog/generate.d.ts +1 -1
- package/dist/types/commit/shared-llm.d.ts +1 -1
- package/dist/types/config/keybindings.d.ts +3 -3
- package/dist/types/config/model-registry.d.ts +17 -0
- package/dist/types/config/models-config-schema.d.ts +13 -1
- package/dist/types/config/models-config.d.ts +8 -2
- package/dist/types/config/settings-schema.d.ts +281 -58
- package/dist/types/edit/hashline/params.d.ts +1 -1
- package/dist/types/edit/modes/apply-patch.d.ts +1 -1
- package/dist/types/edit/modes/patch.d.ts +1 -1
- package/dist/types/edit/modes/replace.d.ts +1 -1
- package/dist/types/export/html/index.d.ts +2 -1
- package/dist/types/extensibility/custom-commands/types.d.ts +2 -2
- package/dist/types/extensibility/custom-tools/types.d.ts +2 -2
- package/dist/types/extensibility/extensions/model-api.d.ts +17 -0
- package/dist/types/extensibility/extensions/runner.d.ts +3 -1
- package/dist/types/extensibility/extensions/types.d.ts +49 -3
- package/dist/types/extensibility/hooks/index.d.ts +2 -1
- package/dist/types/extensibility/hooks/types.d.ts +2 -2
- package/dist/types/extensibility/plugins/legacy-pi-compat.d.ts +9 -0
- package/dist/types/extensibility/plugins/loader.d.ts +11 -0
- package/dist/types/extensibility/shared-events.d.ts +1 -1
- package/dist/types/extensibility/skills.d.ts +10 -0
- package/dist/types/goals/guided-setup.d.ts +18 -0
- package/dist/types/goals/state.d.ts +1 -1
- package/dist/types/goals/tools/goal-tool.d.ts +1 -1
- package/dist/types/hindsight/transcript.d.ts +1 -1
- package/dist/types/index.d.ts +5 -0
- package/dist/types/internal-urls/local-protocol.d.ts +4 -2
- package/dist/types/lsp/types.d.ts +1 -1
- package/dist/types/main.d.ts +4 -3
- package/dist/types/mcp/manager.d.ts +8 -0
- package/dist/types/mcp/startup-events.d.ts +11 -0
- package/dist/types/memories/index.d.ts +7 -0
- package/dist/types/memory-backend/local-backend.d.ts +4 -3
- package/dist/types/mnemopi/config.d.ts +28 -0
- package/dist/types/modes/acp/acp-agent.d.ts +1 -2
- package/dist/types/modes/components/agent-hub.d.ts +6 -0
- package/dist/types/modes/components/assistant-message.d.ts +1 -2
- package/dist/types/modes/components/compaction-summary-message.d.ts +15 -1
- package/dist/types/modes/components/custom-editor.d.ts +39 -1
- package/dist/types/modes/components/custom-editor.test.d.ts +1 -0
- package/dist/types/modes/components/index.d.ts +1 -0
- package/dist/types/modes/components/logout-account-selector.d.ts +8 -0
- package/dist/types/modes/components/session-selector.d.ts +1 -1
- package/dist/types/modes/components/status-line/component.d.ts +9 -5
- package/dist/types/modes/components/status-line/types.d.ts +2 -1
- package/dist/types/modes/components/tool-execution.d.ts +26 -16
- package/dist/types/modes/components/transcript-container.d.ts +23 -2
- package/dist/types/modes/components/tree-selector.d.ts +1 -1
- package/dist/types/modes/components/usage-row.d.ts +3 -0
- package/dist/types/modes/controllers/command-controller.d.ts +2 -2
- package/dist/types/modes/controllers/event-controller.d.ts +0 -17
- package/dist/types/modes/controllers/input-controller.d.ts +14 -0
- package/dist/types/modes/controllers/selector-controller.d.ts +3 -1
- package/dist/types/modes/gradient-highlight.d.ts +9 -4
- package/dist/types/modes/image-references.d.ts +6 -0
- package/dist/types/modes/interactive-mode.d.ts +27 -6
- package/dist/types/modes/magic-keywords.d.ts +13 -1
- package/dist/types/modes/rpc/rpc-mode.d.ts +35 -1
- package/dist/types/modes/rpc/rpc-types.d.ts +9 -1
- package/dist/types/modes/runtime-init.d.ts +4 -0
- package/dist/types/modes/theme/theme.d.ts +13 -2
- package/dist/types/modes/types.d.ts +8 -7
- package/dist/types/modes/utils/ui-helpers.d.ts +1 -1
- package/dist/types/registry/agent-registry.d.ts +17 -0
- package/dist/types/secrets/obfuscator.d.ts +1 -1
- package/dist/types/session/agent-session.d.ts +28 -35
- package/dist/types/session/agent-storage.d.ts +2 -1
- package/dist/types/session/indexed-session-storage.d.ts +3 -3
- package/dist/types/session/messages.d.ts +8 -10
- package/dist/types/session/session-context.d.ts +39 -0
- package/dist/types/session/session-entries.d.ts +159 -0
- package/dist/types/session/session-listing.d.ts +69 -0
- package/dist/types/session/session-loader.d.ts +16 -0
- package/dist/types/session/session-manager.d.ts +85 -462
- package/dist/types/session/session-migrations.d.ts +12 -0
- package/dist/types/session/session-paths.d.ts +25 -0
- package/dist/types/session/session-persistence.d.ts +8 -0
- package/dist/types/session/session-storage.d.ts +11 -7
- package/dist/types/session/snapcompact-inline.d.ts +12 -1
- package/dist/types/session/snapcompact-savings-journal.d.ts +46 -0
- package/dist/types/session/tool-choice-queue.d.ts +6 -6
- package/dist/types/slash-commands/helpers/logout.d.ts +15 -0
- package/dist/types/stt/asr-client.d.ts +90 -0
- package/dist/types/stt/asr-protocol.d.ts +97 -0
- package/dist/types/stt/asr-worker.d.ts +2 -0
- package/dist/types/stt/downloader.d.ts +38 -0
- package/dist/types/stt/endpointer.d.ts +59 -0
- package/dist/types/stt/index.d.ts +5 -1
- package/dist/types/stt/models.d.ts +120 -0
- package/dist/types/stt/recorder.d.ts +17 -0
- package/dist/types/stt/stt-controller.d.ts +6 -0
- package/dist/types/stt/transcriber.d.ts +5 -7
- package/dist/types/stt/wav.d.ts +29 -0
- package/dist/types/system-prompt.d.ts +4 -0
- package/dist/types/task/executor.d.ts +2 -0
- package/dist/types/task/index.d.ts +9 -1
- package/dist/types/task/types.d.ts +37 -1
- package/dist/types/tools/ask.d.ts +1 -1
- package/dist/types/tools/ast-edit.d.ts +1 -1
- package/dist/types/tools/ast-grep.d.ts +1 -1
- package/dist/types/tools/bash.d.ts +3 -3
- package/dist/types/tools/browser/cmux/cmux-tab.d.ts +202 -0
- package/dist/types/tools/browser/cmux/rpc.d.ts +70 -0
- package/dist/types/tools/browser/cmux/socket-client.d.ts +19 -0
- package/dist/types/tools/browser/registry.d.ts +16 -3
- package/dist/types/tools/browser/render.d.ts +2 -0
- package/dist/types/tools/browser/tab-protocol.d.ts +2 -0
- package/dist/types/tools/browser/tab-supervisor.d.ts +16 -4
- package/dist/types/tools/browser.d.ts +3 -1
- package/dist/types/tools/checkpoint.d.ts +1 -1
- package/dist/types/tools/debug.d.ts +1 -1
- package/dist/types/tools/eval-render.d.ts +1 -1
- package/dist/types/tools/eval.d.ts +1 -1
- package/dist/types/tools/find.d.ts +1 -1
- package/dist/types/tools/gh.d.ts +1 -1
- package/dist/types/tools/image-gen.d.ts +1 -1
- package/dist/types/tools/index.d.ts +14 -2
- package/dist/types/tools/inspect-image.d.ts +1 -1
- package/dist/types/tools/irc.d.ts +2 -1
- package/dist/types/tools/job.d.ts +1 -1
- package/dist/types/tools/learn.d.ts +51 -0
- package/dist/types/tools/manage-skill.d.ts +40 -0
- package/dist/types/tools/memory-edit.d.ts +1 -1
- package/dist/types/tools/memory-recall.d.ts +1 -1
- package/dist/types/tools/memory-reflect.d.ts +1 -1
- package/dist/types/tools/memory-retain.d.ts +1 -1
- package/dist/types/tools/plan-mode-guard.d.ts +10 -0
- package/dist/types/tools/read.d.ts +1 -1
- package/dist/types/tools/render-mermaid.d.ts +1 -1
- package/dist/types/tools/renderers.d.ts +7 -11
- package/dist/types/tools/resolve.d.ts +1 -1
- package/dist/types/tools/review.d.ts +1 -1
- package/dist/types/tools/search-tool-bm25.d.ts +1 -1
- package/dist/types/tools/search.d.ts +1 -1
- package/dist/types/tools/ssh.d.ts +2 -2
- package/dist/types/tools/todo.d.ts +2 -2
- package/dist/types/tools/tts.d.ts +26 -1
- package/dist/types/tools/write.d.ts +2 -2
- package/dist/types/tts/downloader.d.ts +20 -0
- package/dist/types/tts/index.d.ts +8 -0
- package/dist/types/tts/models.d.ts +82 -0
- package/dist/types/tts/player.d.ts +32 -0
- package/dist/types/tts/runtime.d.ts +6 -0
- package/dist/types/tts/streaming-player.d.ts +41 -0
- package/dist/types/tts/tts-client.d.ts +93 -0
- package/dist/types/tts/tts-protocol.d.ts +95 -0
- package/dist/types/tts/tts-worker.d.ts +2 -0
- package/dist/types/tts/vocalizer.d.ts +41 -0
- package/dist/types/tts/wav.d.ts +8 -0
- package/dist/types/utils/clipboard.d.ts +4 -3
- package/dist/types/utils/image-loading.d.ts +18 -1
- package/dist/types/utils/thinking-display.d.ts +17 -0
- package/dist/types/utils/tool-choice.d.ts +8 -0
- package/dist/types/utils/tools-manager.d.ts +2 -1
- package/dist/types/utils/tools-manager.test.d.ts +1 -0
- package/dist/types/web/scrapers/github.d.ts +1 -1
- package/dist/types/web/search/index.d.ts +1 -1
- package/package.json +17 -16
- package/src/async/job-manager.ts +49 -0
- package/src/autolearn/controller.ts +139 -0
- package/src/autolearn/managed-skills.ts +257 -0
- package/src/autoresearch/state.ts +1 -1
- package/src/autoresearch/storage.ts +2 -1
- package/src/autoresearch/tools/init-experiment.ts +1 -1
- package/src/autoresearch/tools/log-experiment.ts +1 -1
- package/src/autoresearch/tools/run-experiment.ts +1 -1
- package/src/autoresearch/tools/update-notes.ts +1 -1
- package/src/autoresearch/types.ts +1 -1
- package/src/cli/args.ts +56 -10
- package/src/cli/auth-gateway-cli.ts +1 -1
- package/src/cli/bench-cli.ts +1 -1
- package/src/cli/dry-balance-cli.ts +1 -1
- package/src/cli/models-cli.ts +427 -0
- package/src/cli/session-picker.ts +2 -1
- package/src/cli/setup-cli.ts +148 -47
- package/src/cli/setup-model-picker.ts +43 -0
- package/src/cli-commands.ts +3 -0
- package/src/cli.ts +45 -13
- package/src/collab/host.ts +10 -13
- package/src/collab/protocol.ts +1 -1
- package/src/commands/launch.ts +0 -3
- package/src/commands/models.ts +61 -0
- package/src/commands/say.ts +102 -0
- package/src/commands/setup.ts +1 -1
- package/src/commands/token.ts +89 -0
- package/src/commit/agentic/tools/analyze-file.ts +4 -1
- package/src/commit/agentic/tools/git-file-diff.ts +1 -1
- package/src/commit/agentic/tools/git-hunk.ts +1 -1
- package/src/commit/agentic/tools/git-overview.ts +1 -1
- package/src/commit/agentic/tools/propose-changelog.ts +1 -1
- package/src/commit/agentic/tools/propose-commit.ts +1 -1
- package/src/commit/agentic/tools/recent-commits.ts +1 -1
- package/src/commit/agentic/tools/schemas.ts +1 -1
- package/src/commit/agentic/tools/split-commit.ts +1 -1
- package/src/commit/analysis/summary.ts +1 -1
- package/src/commit/changelog/generate.ts +1 -1
- package/src/commit/shared-llm.ts +1 -1
- package/src/config/keybindings.ts +2 -2
- package/src/config/model-discovery.ts +11 -5
- package/src/config/model-registry.ts +79 -21
- package/src/config/model-resolver.ts +2 -2
- package/src/config/models-config-schema.ts +5 -2
- package/src/config/models-config.ts +2 -1
- package/src/config/settings-schema.ts +266 -32
- package/src/config/settings.ts +10 -0
- package/src/discovery/builtin.ts +23 -1
- package/src/discovery/claude-plugins.ts +44 -5
- package/src/discovery/helpers.ts +41 -1
- package/src/edit/hashline/params.ts +1 -1
- package/src/edit/modes/apply-patch.ts +1 -1
- package/src/edit/modes/patch.ts +1 -1
- package/src/edit/modes/replace.ts +1 -1
- package/src/eval/__tests__/budget-bridge.test.ts +1 -1
- package/src/eval/agent-bridge.ts +1 -1
- package/src/eval/completion-bridge.ts +1 -1
- package/src/eval/js/shared/prelude.txt +69 -17
- package/src/export/html/index.ts +3 -6
- package/src/export/html/template.js +24 -2
- package/src/export/html/tool-views.generated.js +2 -2
- package/src/extensibility/custom-commands/loader.ts +1 -1
- package/src/extensibility/custom-commands/types.ts +2 -2
- package/src/extensibility/custom-tools/loader.ts +1 -1
- package/src/extensibility/custom-tools/types.ts +2 -2
- package/src/extensibility/extensions/loader.ts +2 -2
- package/src/extensibility/extensions/model-api.ts +41 -0
- package/src/extensibility/extensions/runner.ts +4 -0
- package/src/extensibility/extensions/types.ts +54 -3
- package/src/extensibility/extensions/wrapper.ts +41 -5
- package/src/extensibility/hooks/index.ts +2 -1
- package/src/extensibility/hooks/loader.ts +1 -1
- package/src/extensibility/hooks/types.ts +2 -2
- package/src/extensibility/plugins/legacy-pi-compat.ts +43 -13
- package/src/extensibility/plugins/loader.ts +30 -19
- package/src/extensibility/plugins/manager.ts +221 -90
- package/src/extensibility/shared-events.ts +1 -1
- package/src/extensibility/skills.ts +101 -5
- package/src/goals/guided-setup.ts +133 -0
- package/src/goals/state.ts +1 -1
- package/src/goals/tools/goal-tool.ts +1 -1
- package/src/hindsight/transcript.ts +1 -1
- package/src/index.ts +5 -0
- package/src/internal-urls/docs-index.generated.ts +13 -10
- package/src/internal-urls/history-protocol.ts +1 -1
- package/src/internal-urls/local-protocol.ts +29 -7
- package/src/lsp/types.ts +1 -1
- package/src/main.ts +27 -32
- package/src/mcp/config-writer.ts +7 -3
- package/src/mcp/manager.ts +11 -0
- package/src/mcp/startup-events.ts +21 -0
- package/src/mcp/transports/stdio.ts +2 -1
- package/src/memories/index.ts +149 -12
- package/src/memories/storage.ts +2 -1
- package/src/memory-backend/local-backend.ts +11 -5
- package/src/mnemopi/backend.ts +1 -0
- package/src/mnemopi/config.ts +112 -12
- package/src/modes/acp/acp-agent.ts +8 -53
- package/src/modes/acp/acp-event-mapper.ts +5 -1
- package/src/modes/components/agent-hub.ts +51 -5
- package/src/modes/components/assistant-message.ts +12 -44
- package/src/modes/components/compaction-summary-message.ts +125 -26
- package/src/modes/components/custom-editor.test.ts +96 -0
- package/src/modes/components/custom-editor.ts +164 -8
- package/src/modes/components/index.ts +1 -0
- package/src/modes/components/logout-account-selector.ts +130 -0
- package/src/modes/components/mcp-add-wizard.ts +1 -1
- package/src/modes/components/model-selector.ts +2 -2
- package/src/modes/components/session-selector.ts +1 -1
- package/src/modes/components/settings-defs.ts +7 -0
- package/src/modes/components/status-line/component.ts +54 -157
- package/src/modes/components/status-line/segments.ts +1 -1
- package/src/modes/components/status-line/types.ts +2 -1
- package/src/modes/components/tool-execution.ts +82 -43
- package/src/modes/components/transcript-container.ts +70 -1
- package/src/modes/components/tree-selector.ts +1 -1
- package/src/modes/components/usage-row.ts +18 -0
- package/src/modes/components/user-message.ts +4 -2
- package/src/modes/controllers/command-controller.ts +14 -16
- package/src/modes/controllers/event-controller.ts +101 -73
- package/src/modes/controllers/extension-ui-controller.ts +6 -0
- package/src/modes/controllers/input-controller.ts +311 -57
- package/src/modes/controllers/mcp-command-controller.ts +44 -3
- package/src/modes/controllers/selector-controller.ts +68 -12
- package/src/modes/controllers/streaming-reveal.ts +4 -3
- package/src/modes/gradient-highlight.ts +21 -9
- package/src/modes/image-references.ts +20 -0
- package/src/modes/interactive-mode.ts +288 -48
- package/src/modes/magic-keywords.ts +27 -5
- package/src/modes/rpc/rpc-mode.ts +146 -14
- package/src/modes/rpc/rpc-subagents.ts +2 -2
- package/src/modes/rpc/rpc-types.ts +8 -2
- package/src/modes/runtime-init.ts +28 -3
- package/src/modes/theme/theme.ts +99 -51
- package/src/modes/types.ts +6 -7
- package/src/modes/utils/hotkeys-markdown.ts +1 -1
- package/src/modes/utils/ui-helpers.ts +36 -7
- package/src/priority.json +5 -1
- package/src/prompts/agents/task.md +1 -0
- package/src/prompts/goals/guided-goal-interview.md +8 -0
- package/src/prompts/goals/guided-goal-system.md +12 -0
- package/src/prompts/memories/read-path.md +6 -0
- package/src/prompts/system/autolearn-guidance-learn.md +1 -0
- package/src/prompts/system/autolearn-guidance.md +7 -0
- package/src/prompts/system/autolearn-nudge.md +3 -0
- package/src/prompts/system/eager-task.md +7 -0
- package/src/prompts/system/eager-todo.md +11 -6
- package/src/prompts/system/empty-stop-retry.md +4 -6
- package/src/prompts/system/subagent-system-prompt.md +4 -0
- package/src/prompts/system/system-prompt.md +10 -5
- package/src/prompts/system/title-marker-instruction.md +1 -0
- package/src/prompts/system/title-system-marker.md +16 -0
- package/src/prompts/tools/job.md +1 -0
- package/src/prompts/tools/learn.md +7 -0
- package/src/prompts/tools/manage-skill.md +9 -0
- package/src/prompts/tools/task.md +3 -0
- package/src/registry/agent-registry.ts +30 -0
- package/src/sdk.ts +103 -43
- package/src/secrets/obfuscator.ts +1 -1
- package/src/session/agent-session.ts +331 -318
- package/src/session/agent-storage.ts +18 -9
- package/src/session/history-storage.ts +3 -2
- package/src/session/indexed-session-storage.ts +7 -10
- package/src/session/messages.ts +9 -11
- package/src/session/session-context.ts +352 -0
- package/src/session/session-dump-format.ts +4 -2
- package/src/session/session-entries.ts +194 -0
- package/src/session/session-listing.ts +588 -0
- package/src/session/session-loader.ts +106 -0
- package/src/session/session-manager.ts +968 -3064
- package/src/session/session-migrations.ts +78 -0
- package/src/session/session-paths.ts +193 -0
- package/src/session/session-persistence.ts +131 -0
- package/src/session/session-storage.ts +91 -30
- package/src/session/snapcompact-inline.ts +21 -1
- package/src/session/snapcompact-savings-journal.ts +113 -0
- package/src/session/tool-choice-queue.ts +23 -11
- package/src/slash-commands/builtin-registry.ts +40 -4
- package/src/slash-commands/helpers/logout.ts +88 -0
- package/src/stt/asr-client.ts +520 -0
- package/src/stt/asr-protocol.ts +65 -0
- package/src/stt/asr-worker.ts +790 -0
- package/src/stt/downloader.ts +107 -47
- package/src/stt/endpointer.ts +259 -0
- package/src/stt/index.ts +5 -1
- package/src/stt/models.ts +150 -0
- package/src/stt/recorder.ts +247 -60
- package/src/stt/stt-controller.ts +201 -22
- package/src/stt/transcriber.ts +37 -68
- package/src/stt/wav.ts +173 -0
- package/src/system-prompt.ts +8 -0
- package/src/task/agents.ts +1 -2
- package/src/task/executor.ts +49 -15
- package/src/task/index.ts +60 -6
- package/src/task/render.ts +83 -8
- package/src/task/types.ts +54 -1
- package/src/tools/ask.ts +9 -1
- package/src/tools/ast-edit.ts +1 -1
- package/src/tools/ast-grep.ts +1 -1
- package/src/tools/bash.ts +5 -4
- package/src/tools/browser/cmux/cmux-tab.ts +1264 -0
- package/src/tools/browser/cmux/rpc.ts +156 -0
- package/src/tools/browser/cmux/socket-client.ts +309 -0
- package/src/tools/browser/registry.ts +37 -3
- package/src/tools/browser/render.ts +6 -1
- package/src/tools/browser/tab-protocol.ts +2 -0
- package/src/tools/browser/tab-supervisor.ts +189 -18
- package/src/tools/browser/tab-worker.ts +1 -1
- package/src/tools/browser.ts +16 -1
- package/src/tools/checkpoint.ts +1 -1
- package/src/tools/debug.ts +1 -1
- package/src/tools/eval-render.ts +4 -3
- package/src/tools/eval.ts +11 -6
- package/src/tools/fetch.ts +13 -2
- package/src/tools/find.ts +1 -1
- package/src/tools/gh.ts +1 -1
- package/src/tools/github-cache.ts +2 -1
- package/src/tools/image-gen.ts +1 -1
- package/src/tools/index.ts +43 -5
- package/src/tools/inspect-image.ts +3 -1
- package/src/tools/irc.ts +11 -3
- package/src/tools/job.ts +15 -3
- package/src/tools/learn.ts +144 -0
- package/src/tools/manage-skill.ts +104 -0
- package/src/tools/memory-edit.ts +1 -1
- package/src/tools/memory-recall.ts +1 -1
- package/src/tools/memory-reflect.ts +1 -1
- package/src/tools/memory-retain.ts +1 -1
- package/src/tools/plan-mode-guard.ts +53 -19
- package/src/tools/read.ts +8 -2
- package/src/tools/render-mermaid.ts +1 -1
- package/src/tools/renderers.ts +7 -11
- package/src/tools/report-tool-issue.ts +3 -2
- package/src/tools/resolve.ts +1 -1
- package/src/tools/review.ts +1 -1
- package/src/tools/search-tool-bm25.ts +1 -1
- package/src/tools/search.ts +1 -1
- package/src/tools/ssh.ts +5 -4
- package/src/tools/todo.ts +2 -2
- package/src/tools/tts.ts +204 -93
- package/src/tools/write.ts +19 -3
- package/src/tts/downloader.ts +64 -0
- package/src/tts/index.ts +8 -0
- package/src/tts/models.ts +137 -0
- package/src/tts/player.ts +137 -0
- package/src/tts/runtime.ts +21 -0
- package/src/tts/streaming-player.ts +266 -0
- package/src/tts/tts-client.ts +647 -0
- package/src/tts/tts-protocol.ts +60 -0
- package/src/tts/tts-worker.ts +497 -0
- package/src/tts/vocalizer.ts +162 -0
- package/src/tts/wav.ts +58 -0
- package/src/utils/clipboard.ts +35 -18
- package/src/utils/image-loading.ts +35 -4
- package/src/utils/thinking-display.ts +37 -0
- package/src/utils/title-generator.ts +48 -5
- package/src/utils/tool-choice.ts +16 -0
- package/src/utils/tools-manager.test.ts +25 -0
- package/src/utils/tools-manager.ts +19 -1
- package/src/web/scrapers/github.ts +96 -0
- package/src/web/search/index.ts +14 -1
- package/src/web/search/providers/searxng.ts +13 -1
- package/dist/types/cli/list-models.d.ts +0 -30
- package/dist/types/stt/setup.d.ts +0 -18
- package/src/cli/list-models.ts +0 -194
- package/src/stt/setup.ts +0 -52
- package/src/stt/transcribe.py +0 -70
package/src/mnemopi/config.ts
CHANGED
|
@@ -1,8 +1,9 @@
|
|
|
1
|
+
import { Database } from "bun:sqlite";
|
|
2
|
+
import * as fs from "node:fs";
|
|
1
3
|
import * as path from "node:path";
|
|
2
4
|
import type { MnemopiOptions } from "@oh-my-pi/pi-mnemopi";
|
|
3
|
-
import { getMemoriesDir } from "@oh-my-pi/pi-utils";
|
|
5
|
+
import { getMemoriesDir, logger } from "@oh-my-pi/pi-utils";
|
|
4
6
|
import type { Settings } from "../config/settings";
|
|
5
|
-
import * as git from "../utils/git";
|
|
6
7
|
|
|
7
8
|
export type MnemopiLlmMode = "none" | "smol" | "remote";
|
|
8
9
|
|
|
@@ -42,15 +43,29 @@ export function loadMnemopiConfig(settings: Settings, agentDir: string): Mnemopi
|
|
|
42
43
|
const configuredDbPath = settings.get("mnemopi.dbPath");
|
|
43
44
|
const cwd = settings.getCwd();
|
|
44
45
|
const scoping = settings.get("mnemopi.scoping");
|
|
45
|
-
const
|
|
46
|
+
const dbPath = configuredDbPath ?? path.join(getMemoriesDir(agentDir), "mnemopi", "mnemopi.db");
|
|
47
|
+
const scope = computeMnemopiBankScope(settings.get("mnemopi.bank"), cwd, scoping);
|
|
48
|
+
const recallBanks =
|
|
49
|
+
scoping === "global" ? scope.recallBanks : extendRecallWithLegacyBanks(scope.recallBanks, dbPath, cwd);
|
|
46
50
|
const llmMode = settings.get("mnemopi.llmMode");
|
|
51
|
+
const embeddingOverride = settings.get("mnemopi.embeddingModel");
|
|
52
|
+
const embeddingVariant = settings.get("mnemopi.embeddingVariant");
|
|
53
|
+
// Map the variant explicitly rather than indexing an object with the raw config
|
|
54
|
+
// value (which could resolve an inherited property like `__proto__`); any value
|
|
55
|
+
// other than the multilingual variant falls back to the English default.
|
|
56
|
+
const variantModel =
|
|
57
|
+
embeddingVariant === "multilingual" ? "intfloat/multilingual-e5-large" : "BAAI/bge-base-en-v1.5";
|
|
58
|
+
// Precedence: explicit `mnemopi.embeddingModel` setting > `MNEMOPI_EMBEDDING_MODEL`
|
|
59
|
+
// env (documented model-level override) > variant-derived default. Without the env
|
|
60
|
+
// term a variant default would silently shadow a user's configured env model.
|
|
61
|
+
const embeddingModel = embeddingOverride?.trim() || Bun.env.MNEMOPI_EMBEDDING_MODEL?.trim() || variantModel;
|
|
47
62
|
return {
|
|
48
|
-
dbPath
|
|
63
|
+
dbPath,
|
|
49
64
|
baseBank: scope.baseBank,
|
|
50
65
|
bank: scope.bank,
|
|
51
66
|
globalBank: scope.globalBank,
|
|
52
67
|
retainBank: scope.retainBank,
|
|
53
|
-
recallBanks
|
|
68
|
+
recallBanks,
|
|
54
69
|
scoping,
|
|
55
70
|
autoRecall: settings.get("mnemopi.autoRecall"),
|
|
56
71
|
autoRetain: settings.get("mnemopi.autoRetain"),
|
|
@@ -65,7 +80,7 @@ export function loadMnemopiConfig(settings: Settings, agentDir: string): Mnemopi
|
|
|
65
80
|
providerOptions: {
|
|
66
81
|
noEmbeddings: settings.get("mnemopi.noEmbeddings"),
|
|
67
82
|
debug: settings.get("mnemopi.debug"),
|
|
68
|
-
embeddingModel
|
|
83
|
+
embeddingModel,
|
|
69
84
|
embeddingApiUrl: settings.get("mnemopi.embeddingApiUrl"),
|
|
70
85
|
embeddingApiKey: settings.get("mnemopi.embeddingApiKey"),
|
|
71
86
|
llm:
|
|
@@ -86,7 +101,11 @@ export function loadMnemopiConfig(settings: Settings, agentDir: string): Mnemopi
|
|
|
86
101
|
|
|
87
102
|
const DEFAULT_SHARED_BANK = "default";
|
|
88
103
|
|
|
89
|
-
|
|
104
|
+
// Cap legacy-bank scanning at session start so a pathological banks/
|
|
105
|
+
// directory cannot dominate startup latency.
|
|
106
|
+
const LEGACY_BANK_SCAN_LIMIT = 64;
|
|
107
|
+
|
|
108
|
+
export interface MnemopiBankScope {
|
|
90
109
|
baseBank: string;
|
|
91
110
|
bank: string;
|
|
92
111
|
globalBank: string;
|
|
@@ -94,9 +113,19 @@ interface MnemopiBankScope {
|
|
|
94
113
|
recallBanks: readonly string[];
|
|
95
114
|
}
|
|
96
115
|
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
116
|
+
/**
|
|
117
|
+
* Resolve write/recall banks for a session.
|
|
118
|
+
*
|
|
119
|
+
* Mnemopi has no tag-filtered recall, so `per-project-tagged` maps to a
|
|
120
|
+
* project-local write bank plus a shared recall-visible bank. The project
|
|
121
|
+
* bank is derived purely from {@link cwd} — see {@link projectBank} for the
|
|
122
|
+
* stability contract.
|
|
123
|
+
*/
|
|
124
|
+
export function computeMnemopiBankScope(
|
|
125
|
+
configured: string | undefined,
|
|
126
|
+
cwd: string,
|
|
127
|
+
scoping: MnemopiScoping,
|
|
128
|
+
): MnemopiBankScope {
|
|
100
129
|
const project = projectBank(configured, cwd);
|
|
101
130
|
const globalBank = sharedBank(configured);
|
|
102
131
|
switch (scoping) {
|
|
@@ -131,8 +160,17 @@ function sharedBank(configured: string | undefined): string {
|
|
|
131
160
|
return sanitizeBankName(configured) ?? DEFAULT_SHARED_BANK;
|
|
132
161
|
}
|
|
133
162
|
|
|
163
|
+
/**
|
|
164
|
+
* Derive the per-project bank id from `cwd` alone.
|
|
165
|
+
*
|
|
166
|
+
* Earlier versions resolved the enclosing git root before hashing, which
|
|
167
|
+
* made the bank id unstable: removing or adding a `.git` anywhere above the
|
|
168
|
+
* cwd repointed the same conversation directory to a different bank and
|
|
169
|
+
* fragmented memories (#2412). The git lookup is gone here; the rescue path
|
|
170
|
+
* for already-fragmented installs lives in {@link extendRecallWithLegacyBanks}.
|
|
171
|
+
*/
|
|
134
172
|
function projectBank(configured: string | undefined, cwd: string): string {
|
|
135
|
-
const projectRoot =
|
|
173
|
+
const projectRoot = path.resolve(cwd || ".");
|
|
136
174
|
const project = projectBankSegment(projectRoot);
|
|
137
175
|
const base = sanitizeBankName(configured);
|
|
138
176
|
return limitBankName(base ? `${base}-${project}` : project);
|
|
@@ -140,7 +178,69 @@ function projectBank(configured: string | undefined, cwd: string): string {
|
|
|
140
178
|
|
|
141
179
|
function projectBankSegment(projectRoot: string): string {
|
|
142
180
|
const project = sanitizeBankName(path.basename(projectRoot)) ?? "default";
|
|
143
|
-
return limitBankName(`${project}-${Bun.hash(
|
|
181
|
+
return limitBankName(`${project}-${Bun.hash(projectRoot).toString(36)}`);
|
|
182
|
+
}
|
|
183
|
+
|
|
184
|
+
/**
|
|
185
|
+
* Discover sibling banks under `<dbDir>/banks/` whose `working_memory` rows
|
|
186
|
+
* all carry the active `cwd` in `metadata_json.$.cwd`, and add those safe
|
|
187
|
+
* single-cwd banks to the recall set. This rescues memories stranded by a
|
|
188
|
+
* previous, less-stable bank derivation (#2412) without recalling mixed-cwd
|
|
189
|
+
* legacy banks wholesale under per-project isolation.
|
|
190
|
+
*
|
|
191
|
+
* Robust by design: a missing banks directory, unreadable bank dir, or
|
|
192
|
+
* corrupt SQLite file is silently skipped. Scanning is capped at
|
|
193
|
+
* {@link LEGACY_BANK_SCAN_LIMIT} to bound startup cost.
|
|
194
|
+
*/
|
|
195
|
+
export function extendRecallWithLegacyBanks(
|
|
196
|
+
resolved: readonly string[],
|
|
197
|
+
dbPath: string,
|
|
198
|
+
cwd: string,
|
|
199
|
+
): readonly string[] {
|
|
200
|
+
const banksDir = path.join(path.dirname(dbPath), "banks");
|
|
201
|
+
const cwdAbs = path.resolve(cwd || ".");
|
|
202
|
+
let entries: fs.Dirent[];
|
|
203
|
+
try {
|
|
204
|
+
entries = fs.readdirSync(banksDir, { withFileTypes: true });
|
|
205
|
+
} catch {
|
|
206
|
+
return resolved;
|
|
207
|
+
}
|
|
208
|
+
const have = new Set(resolved);
|
|
209
|
+
const extras: string[] = [];
|
|
210
|
+
let scanned = 0;
|
|
211
|
+
for (const entry of entries) {
|
|
212
|
+
if (!entry.isDirectory() || have.has(entry.name)) continue;
|
|
213
|
+
if (scanned >= LEGACY_BANK_SCAN_LIMIT) break;
|
|
214
|
+
scanned++;
|
|
215
|
+
const candidate = path.join(banksDir, entry.name, "mnemopi.db");
|
|
216
|
+
if (bankOnlyHasCwd(candidate, cwdAbs)) extras.push(entry.name);
|
|
217
|
+
}
|
|
218
|
+
return extras.length === 0 ? resolved : [...resolved, ...extras];
|
|
219
|
+
}
|
|
220
|
+
|
|
221
|
+
function bankOnlyHasCwd(dbPath: string, cwd: string): boolean {
|
|
222
|
+
let db: Database | undefined;
|
|
223
|
+
try {
|
|
224
|
+
db = new Database(dbPath, { readonly: true });
|
|
225
|
+
const row = db
|
|
226
|
+
.prepare<{ matching: number; unsafe: number }, [string, string]>(`
|
|
227
|
+
SELECT
|
|
228
|
+
SUM(CASE WHEN json_extract(metadata_json, '$.cwd') = ? THEN 1 ELSE 0 END) AS matching,
|
|
229
|
+
SUM(CASE WHEN json_extract(metadata_json, '$.cwd') IS NULL OR json_extract(metadata_json, '$.cwd') <> ? THEN 1 ELSE 0 END) AS unsafe
|
|
230
|
+
FROM working_memory
|
|
231
|
+
`)
|
|
232
|
+
.get(cwd, cwd);
|
|
233
|
+
return (row?.matching ?? 0) > 0 && (row?.unsafe ?? 0) === 0;
|
|
234
|
+
} catch (error) {
|
|
235
|
+
logger.debug("Mnemopi: legacy bank probe failed", { dbPath, error: String(error) });
|
|
236
|
+
return false;
|
|
237
|
+
} finally {
|
|
238
|
+
try {
|
|
239
|
+
db?.close();
|
|
240
|
+
} catch {
|
|
241
|
+
// nothing to do — read-only handle.
|
|
242
|
+
}
|
|
243
|
+
}
|
|
144
244
|
}
|
|
145
245
|
|
|
146
246
|
function sanitizeBankName(value: string | undefined): string | undefined {
|
|
@@ -31,14 +31,11 @@ import {
|
|
|
31
31
|
type ResumeSessionResponse,
|
|
32
32
|
type SessionConfigOption,
|
|
33
33
|
type SessionInfo,
|
|
34
|
-
type SessionModelState,
|
|
35
34
|
type SessionModeState,
|
|
36
35
|
type SessionNotification,
|
|
37
36
|
type SessionUpdate,
|
|
38
37
|
type SetSessionConfigOptionRequest,
|
|
39
38
|
type SetSessionConfigOptionResponse,
|
|
40
|
-
type SetSessionModelRequest,
|
|
41
|
-
type SetSessionModelResponse,
|
|
42
39
|
type SetSessionModeRequest,
|
|
43
40
|
type SetSessionModeResponse,
|
|
44
41
|
type Usage,
|
|
@@ -66,17 +63,16 @@ import { theme } from "../../modes/theme/theme";
|
|
|
66
63
|
import { type PlanApprovalDetails, resolveApprovedPlan } from "../../plan-mode/approved-plan";
|
|
67
64
|
import type { AgentSession, AgentSessionEvent } from "../../session/agent-session";
|
|
68
65
|
import { isSilentAbort, SKILL_PROMPT_MESSAGE_TYPE } from "../../session/messages";
|
|
69
|
-
import {
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
type UsageStatistics,
|
|
73
|
-
} from "../../session/session-manager";
|
|
66
|
+
import type { UsageStatistics } from "../../session/session-entries";
|
|
67
|
+
import type { SessionInfo as StoredSessionInfo } from "../../session/session-listing";
|
|
68
|
+
import { SessionManager } from "../../session/session-manager";
|
|
74
69
|
import { executeAcpBuiltinSlashCommand } from "../../slash-commands/acp-builtins";
|
|
75
70
|
import { buildAvailableSlashCommands, toAcpAvailableCommands } from "../../slash-commands/available-commands";
|
|
76
71
|
import { AUTO_THINKING, parseConfiguredThinkingLevel } from "../../thinking";
|
|
77
72
|
import { normalizeLocalScheme } from "../../tools/path-utils";
|
|
78
73
|
import { runResolveInvocation } from "../../tools/resolve";
|
|
79
74
|
import { ToolError } from "../../tools/tool-errors";
|
|
75
|
+
import { getVisibleThinkingText } from "../../utils/thinking-display";
|
|
80
76
|
import { createAcpClientBridge } from "./acp-client-bridge";
|
|
81
77
|
import {
|
|
82
78
|
buildToolCallStartUpdate,
|
|
@@ -121,7 +117,6 @@ type PromptQueueState = {
|
|
|
121
117
|
type PromptLifecycleError = Error & { readonly code: "ACP_SESSION_CLOSED" };
|
|
122
118
|
|
|
123
119
|
type PromptTurnState = {
|
|
124
|
-
userMessageId: string;
|
|
125
120
|
cancelRequested: boolean;
|
|
126
121
|
settled: boolean;
|
|
127
122
|
/**
|
|
@@ -465,7 +460,6 @@ export class AcpAgent implements Agent {
|
|
|
465
460
|
const response: NewSessionResponse = {
|
|
466
461
|
sessionId: record.session.sessionId,
|
|
467
462
|
configOptions: this.#buildConfigOptions(record.session),
|
|
468
|
-
models: this.#buildModelState(record.session),
|
|
469
463
|
modes: this.#buildModeState(record.session),
|
|
470
464
|
};
|
|
471
465
|
this.#scheduleBootstrapUpdates(record.session.sessionId);
|
|
@@ -478,7 +472,6 @@ export class AcpAgent implements Agent {
|
|
|
478
472
|
await this.#replaySessionHistory(record);
|
|
479
473
|
const response: LoadSessionResponse = {
|
|
480
474
|
configOptions: this.#buildConfigOptions(record.session),
|
|
481
|
-
models: this.#buildModelState(record.session),
|
|
482
475
|
modes: this.#buildModeState(record.session),
|
|
483
476
|
};
|
|
484
477
|
this.#scheduleBootstrapUpdates(record.session.sessionId);
|
|
@@ -507,7 +500,6 @@ export class AcpAgent implements Agent {
|
|
|
507
500
|
const record = await this.#resumeManagedSession(params.sessionId, params.cwd, params.mcpServers ?? []);
|
|
508
501
|
const response: ResumeSessionResponse = {
|
|
509
502
|
configOptions: this.#buildConfigOptions(record.session),
|
|
510
|
-
models: this.#buildModelState(record.session),
|
|
511
503
|
modes: this.#buildModeState(record.session),
|
|
512
504
|
};
|
|
513
505
|
this.#scheduleBootstrapUpdates(record.session.sessionId);
|
|
@@ -520,7 +512,6 @@ export class AcpAgent implements Agent {
|
|
|
520
512
|
const response: ForkSessionResponse = {
|
|
521
513
|
sessionId: record.session.sessionId,
|
|
522
514
|
configOptions: this.#buildConfigOptions(record.session),
|
|
523
|
-
models: this.#buildModelState(record.session),
|
|
524
515
|
modes: this.#buildModeState(record.session),
|
|
525
516
|
};
|
|
526
517
|
this.#scheduleBootstrapUpdates(record.session.sessionId);
|
|
@@ -588,13 +579,6 @@ export class AcpAgent implements Agent {
|
|
|
588
579
|
return { configOptions: this.#buildConfigOptions(record.session) };
|
|
589
580
|
}
|
|
590
581
|
|
|
591
|
-
async unstable_setSessionModel(params: SetSessionModelRequest): Promise<SetSessionModelResponse> {
|
|
592
|
-
const record = this.#getSessionRecord(params.sessionId);
|
|
593
|
-
await this.#setModelById(record.session, params.modelId);
|
|
594
|
-
await this.#pushConfigOptionUpdate(record);
|
|
595
|
-
return {};
|
|
596
|
-
}
|
|
597
|
-
|
|
598
582
|
async prompt(params: PromptRequest): Promise<PromptResponse> {
|
|
599
583
|
const record = this.#getSessionRecord(params.sessionId);
|
|
600
584
|
const activeTurn = record.promptTurn;
|
|
@@ -633,7 +617,6 @@ export class AcpAgent implements Agent {
|
|
|
633
617
|
const converted = this.#convertPromptBlocks(params.prompt);
|
|
634
618
|
const pendingPrompt = Promise.withResolvers<PromptResponse>();
|
|
635
619
|
record.promptTurn = {
|
|
636
|
-
userMessageId: params.messageId ?? crypto.randomUUID(),
|
|
637
620
|
cancelRequested: false,
|
|
638
621
|
settled: false,
|
|
639
622
|
cleanup: undefined,
|
|
@@ -766,7 +749,6 @@ export class AcpAgent implements Agent {
|
|
|
766
749
|
this.#cloneUsageStatistics(record.session.sessionManager.getUsageStatistics()),
|
|
767
750
|
record.session.sessionManager.getUsageStatistics(),
|
|
768
751
|
),
|
|
769
|
-
userMessageId: promptTurn?.userMessageId,
|
|
770
752
|
});
|
|
771
753
|
return;
|
|
772
754
|
}
|
|
@@ -844,7 +826,6 @@ export class AcpAgent implements Agent {
|
|
|
844
826
|
this.#finishPrompt(record, {
|
|
845
827
|
stopReason: "cancelled",
|
|
846
828
|
usage: this.#buildTurnUsage(promptTurn.usageBaseline, record.session.sessionManager.getUsageStatistics()),
|
|
847
|
-
userMessageId: promptTurn.userMessageId,
|
|
848
829
|
});
|
|
849
830
|
return cleanup;
|
|
850
831
|
}
|
|
@@ -1162,7 +1143,6 @@ export class AcpAgent implements Agent {
|
|
|
1162
1143
|
this.#finishPrompt(record, {
|
|
1163
1144
|
stopReason: this.#resolveStopReason(event, promptTurn.cancelRequested),
|
|
1164
1145
|
usage: this.#buildTurnUsage(promptTurn.usageBaseline, record.session.sessionManager.getUsageStatistics()),
|
|
1165
|
-
userMessageId: promptTurn.userMessageId,
|
|
1166
1146
|
});
|
|
1167
1147
|
}
|
|
1168
1148
|
}
|
|
@@ -1385,28 +1365,6 @@ export class AcpAgent implements Agent {
|
|
|
1385
1365
|
return configOptions;
|
|
1386
1366
|
}
|
|
1387
1367
|
|
|
1388
|
-
#buildModelState(session: AgentSession): SessionModelState | undefined {
|
|
1389
|
-
const models = session.getAvailableModels();
|
|
1390
|
-
if (models.length === 0) {
|
|
1391
|
-
return undefined;
|
|
1392
|
-
}
|
|
1393
|
-
|
|
1394
|
-
const availableModels = models.map(model => ({
|
|
1395
|
-
modelId: this.#toModelId(model),
|
|
1396
|
-
name: model.name,
|
|
1397
|
-
description: `${model.provider}/${model.id}`,
|
|
1398
|
-
}));
|
|
1399
|
-
const currentModelId = session.model ? this.#toModelId(session.model) : availableModels[0]?.modelId;
|
|
1400
|
-
if (!currentModelId) {
|
|
1401
|
-
return undefined;
|
|
1402
|
-
}
|
|
1403
|
-
|
|
1404
|
-
return {
|
|
1405
|
-
availableModels,
|
|
1406
|
-
currentModelId,
|
|
1407
|
-
};
|
|
1408
|
-
}
|
|
1409
|
-
|
|
1410
1368
|
#buildThinkingOptions(session: AgentSession): Array<{ value: string; name: string; description?: string }> {
|
|
1411
1369
|
return [
|
|
1412
1370
|
{ value: THINKING_OFF, name: "Off" },
|
|
@@ -1948,17 +1906,14 @@ export class AcpAgent implements Agent {
|
|
|
1948
1906
|
});
|
|
1949
1907
|
continue;
|
|
1950
1908
|
}
|
|
1951
|
-
if (
|
|
1952
|
-
|
|
1953
|
-
|
|
1954
|
-
typeof item.thinking === "string" &&
|
|
1955
|
-
item.thinking.length > 0
|
|
1956
|
-
) {
|
|
1909
|
+
if (item.type === "thinking" && "thinking" in item && typeof item.thinking === "string") {
|
|
1910
|
+
const thinking = getVisibleThinkingText(item);
|
|
1911
|
+
if (thinking.length === 0) continue;
|
|
1957
1912
|
notifications.push({
|
|
1958
1913
|
sessionId,
|
|
1959
1914
|
update: {
|
|
1960
1915
|
sessionUpdate: "agent_thought_chunk",
|
|
1961
|
-
content: { type: "text", text:
|
|
1916
|
+
content: { type: "text", text: thinking },
|
|
1962
1917
|
messageId,
|
|
1963
1918
|
},
|
|
1964
1919
|
});
|
|
@@ -9,6 +9,7 @@ import type {
|
|
|
9
9
|
import type { AgentSessionEvent } from "../../session/agent-session";
|
|
10
10
|
import { resolveToCwd } from "../../tools/path-utils";
|
|
11
11
|
import type { TodoStatus } from "../../tools/todo";
|
|
12
|
+
import { hasVisibleThinking } from "../../utils/thinking-display";
|
|
12
13
|
|
|
13
14
|
interface MessageProgress {
|
|
14
15
|
textEmitted: boolean;
|
|
@@ -256,13 +257,16 @@ function mapAssistantMessageUpdate(
|
|
|
256
257
|
progress.textEmitted = true;
|
|
257
258
|
}
|
|
258
259
|
break;
|
|
259
|
-
case "thinking_delta":
|
|
260
|
+
case "thinking_delta": {
|
|
261
|
+
const block = event.assistantMessageEvent.partial?.content?.[event.assistantMessageEvent.contentIndex];
|
|
262
|
+
if (block?.type === "thinking" && !hasVisibleThinking(block)) return [];
|
|
260
263
|
sessionUpdate = "agent_thought_chunk";
|
|
261
264
|
text = event.assistantMessageEvent.delta;
|
|
262
265
|
if (text.length > 0 && progress) {
|
|
263
266
|
progress.thoughtEmitted = true;
|
|
264
267
|
}
|
|
265
268
|
break;
|
|
269
|
+
}
|
|
266
270
|
case "done":
|
|
267
271
|
if (progress?.textEmitted) {
|
|
268
272
|
return [];
|
|
@@ -16,6 +16,7 @@
|
|
|
16
16
|
import * as fs from "node:fs";
|
|
17
17
|
import * as path from "node:path";
|
|
18
18
|
import type { AgentMessage, AgentTool } from "@oh-my-pi/pi-agent-core";
|
|
19
|
+
import type { Usage } from "@oh-my-pi/pi-ai";
|
|
19
20
|
import { Container, Editor, matchesKey, ScrollView, Text, type TUI } from "@oh-my-pi/pi-tui";
|
|
20
21
|
import { formatAge, formatBytes, formatDuration, formatNumber, getProjectDir, logger } from "@oh-my-pi/pi-utils";
|
|
21
22
|
import { COLLAB_PROMPT_MESSAGE_TYPE, type CollabPromptDetails } from "../../collab/protocol";
|
|
@@ -35,10 +36,11 @@ import {
|
|
|
35
36
|
type SkillPromptDetails,
|
|
36
37
|
USER_INTERRUPT_LABEL,
|
|
37
38
|
} from "../../session/messages";
|
|
38
|
-
import type { SessionMessageEntry } from "../../session/session-
|
|
39
|
-
import { parseSessionEntries } from "../../session/session-
|
|
39
|
+
import type { SessionMessageEntry } from "../../session/session-entries";
|
|
40
|
+
import { parseSessionEntries } from "../../session/session-loader";
|
|
40
41
|
import { createIrcMessageCard } from "../../tools/irc";
|
|
41
42
|
import { replaceTabs, TRUNCATE_LENGTHS, truncateToWidth } from "../../tools/render-utils";
|
|
43
|
+
import { hasVisibleThinking } from "../../utils/thinking-display";
|
|
42
44
|
import type { ObservableSession, SessionObserverRegistry } from "../session-observer-registry";
|
|
43
45
|
import { getEditorTheme, theme } from "../theme/theme";
|
|
44
46
|
import { matchesSelectDown, matchesSelectUp } from "../utils/keybinding-matchers";
|
|
@@ -46,7 +48,7 @@ import { AssistantMessageComponent } from "./assistant-message";
|
|
|
46
48
|
import { BashExecutionComponent } from "./bash-execution";
|
|
47
49
|
import { BranchSummaryMessageComponent } from "./branch-summary-message";
|
|
48
50
|
import { CollabPromptMessageComponent } from "./collab-prompt-message";
|
|
49
|
-
import { CompactionSummaryMessageComponent } from "./compaction-summary-message";
|
|
51
|
+
import { CompactionSummaryMessageComponent, createHandoffSummaryMessageComponent } from "./compaction-summary-message";
|
|
50
52
|
import { CustomMessageComponent } from "./custom-message";
|
|
51
53
|
import { DynamicBorder } from "./dynamic-border";
|
|
52
54
|
import { EvalExecutionComponent } from "./eval-execution";
|
|
@@ -56,6 +58,7 @@ import { SkillMessageComponent } from "./skill-message";
|
|
|
56
58
|
import { formatContextUsage } from "./status-line/context-thresholds";
|
|
57
59
|
import { ToolExecutionComponent } from "./tool-execution";
|
|
58
60
|
import { TranscriptBlock, TranscriptContainer } from "./transcript-container";
|
|
61
|
+
import { createUsageRowBlock } from "./usage-row";
|
|
59
62
|
import { UserMessageComponent } from "./user-message";
|
|
60
63
|
|
|
61
64
|
/** Lines per page for PageUp/PageDown */
|
|
@@ -212,6 +215,7 @@ export class AgentHubOverlayComponent extends Container {
|
|
|
212
215
|
#chatPendingTools = new Map<string, ToolExecutionComponent | ReadToolGroupComponent>();
|
|
213
216
|
#chatReadArgs = new Map<string, Record<string, unknown>>();
|
|
214
217
|
#chatReadGroup: ReadToolGroupComponent | null = null;
|
|
218
|
+
#pendingUsage: Usage | undefined;
|
|
215
219
|
#chatWaitingPoll: ToolExecutionComponent | null = null;
|
|
216
220
|
#chatExpandables: Array<{ setExpanded(expanded: boolean): void }> = [];
|
|
217
221
|
#chatExpanded = false;
|
|
@@ -263,6 +267,15 @@ export class AgentHubOverlayComponent extends Container {
|
|
|
263
267
|
this.#refreshRows();
|
|
264
268
|
}
|
|
265
269
|
|
|
270
|
+
/**
|
|
271
|
+
* Whether the table view has no agents to show (every registered agent except
|
|
272
|
+
* Main, after the persisted-subagent scan in the constructor). The double-←
|
|
273
|
+
* gesture reads this to stay inert when there is nothing to open.
|
|
274
|
+
*/
|
|
275
|
+
get isEmpty(): boolean {
|
|
276
|
+
return this.#rows.length === 0;
|
|
277
|
+
}
|
|
278
|
+
|
|
266
279
|
/** Tear down every subscription and timer. Called by the overlay owner on close. */
|
|
267
280
|
dispose(): void {
|
|
268
281
|
for (const unsubscribe of this.#unsubscribers.splice(0)) unsubscribe();
|
|
@@ -437,6 +450,7 @@ export class AgentHubOverlayComponent extends Container {
|
|
|
437
450
|
#renderRow(ref: AgentRef, selected: boolean, width: number): string {
|
|
438
451
|
const cursor = selected ? theme.fg("accent", theme.nav.cursor) : " ";
|
|
439
452
|
const parts: string[] = [statusBadge(ref.status), theme.bold(replaceTabs(ref.id))];
|
|
453
|
+
parts.push(theme.fg("dim", replaceTabs(ref.displayName)));
|
|
440
454
|
parts.push(theme.fg("dim", ref.parentId ? `${ref.kind} · of ${ref.parentId}` : ref.kind));
|
|
441
455
|
const observed = this.#observableFor(ref.id);
|
|
442
456
|
const task = observed?.description ?? observed?.progress?.task;
|
|
@@ -849,6 +863,7 @@ export class AgentHubOverlayComponent extends Container {
|
|
|
849
863
|
this.#chatPendingTools.clear();
|
|
850
864
|
this.#chatReadArgs.clear();
|
|
851
865
|
this.#chatReadGroup = null;
|
|
866
|
+
this.#pendingUsage = undefined;
|
|
852
867
|
this.#chatWaitingPoll = null;
|
|
853
868
|
this.#chatExpandables = [];
|
|
854
869
|
this.#chatLog.dispose();
|
|
@@ -868,6 +883,13 @@ export class AgentHubOverlayComponent extends Container {
|
|
|
868
883
|
this.#appendChatMessage(entries[i].message);
|
|
869
884
|
}
|
|
870
885
|
this.#chatBuiltCount = entries.length;
|
|
886
|
+
// Flush the trailing turn's usage row only once its tools are materialized.
|
|
887
|
+
// A read (or any tool) whose toolResult lands in a later debounced sync stays
|
|
888
|
+
// pending in #chatReadArgs / #chatPendingTools; flushing now would emit the
|
|
889
|
+
// row above it. The sync that drains the maps flushes it below the tools.
|
|
890
|
+
if (this.#chatReadArgs.size === 0 && this.#chatPendingTools.size === 0) {
|
|
891
|
+
this.#flushPendingUsage();
|
|
892
|
+
}
|
|
871
893
|
}
|
|
872
894
|
|
|
873
895
|
#trackExpandable(component: { setExpanded(expanded: boolean): void }): void {
|
|
@@ -897,7 +919,21 @@ export class AgentHubOverlayComponent extends Container {
|
|
|
897
919
|
return this.#chatReadGroup;
|
|
898
920
|
}
|
|
899
921
|
|
|
922
|
+
// The per-turn token-usage row must land below the turn's tool blocks, but
|
|
923
|
+
// normal `read` calls only materialize their group in #appendToolResult. Defer
|
|
924
|
+
// the row: stash it on the assistant message and flush once the turn's tools
|
|
925
|
+
// are placed — before the next non-toolResult message and at the end of each
|
|
926
|
+
// sync pass — sealing the read run so the row sits under it.
|
|
927
|
+
#flushPendingUsage(): void {
|
|
928
|
+
if (!this.#pendingUsage) return;
|
|
929
|
+
this.#chatReadGroup?.seal();
|
|
930
|
+
this.#chatReadGroup = null;
|
|
931
|
+
this.#chatLog.addChild(createUsageRowBlock(this.#pendingUsage));
|
|
932
|
+
this.#pendingUsage = undefined;
|
|
933
|
+
}
|
|
934
|
+
|
|
900
935
|
#appendChatMessage(message: AgentMessage): void {
|
|
936
|
+
if (message.role !== "toolResult") this.#flushPendingUsage();
|
|
901
937
|
switch (message.role) {
|
|
902
938
|
case "assistant":
|
|
903
939
|
this.#appendAssistantMessage(message);
|
|
@@ -986,13 +1022,12 @@ export class AgentHubOverlayComponent extends Container {
|
|
|
986
1022
|
const assistantComponent = new AssistantMessageComponent(message, this.#hideThinkingBlock?.() ?? false, () =>
|
|
987
1023
|
this.#requestRender(),
|
|
988
1024
|
);
|
|
989
|
-
assistantComponent.setUsageInfo(message.usage);
|
|
990
1025
|
this.#chatLog.addChild(assistantComponent);
|
|
991
1026
|
|
|
992
1027
|
const hasVisibleAssistantContent = message.content.some(
|
|
993
1028
|
content =>
|
|
994
1029
|
(content.type === "text" && content.text.trim().length > 0) ||
|
|
995
|
-
(content.type === "thinking" && content
|
|
1030
|
+
(content.type === "thinking" && hasVisibleThinking(content)),
|
|
996
1031
|
);
|
|
997
1032
|
if (hasVisibleAssistantContent) {
|
|
998
1033
|
// New visible turn content closes the current read run (mirrors rebuild).
|
|
@@ -1065,6 +1100,8 @@ export class AgentHubOverlayComponent extends Container {
|
|
|
1065
1100
|
this.#chatPendingTools.set(content.id, component);
|
|
1066
1101
|
}
|
|
1067
1102
|
}
|
|
1103
|
+
|
|
1104
|
+
this.#pendingUsage = settings.get("display.showTokenUsage") ? message.usage : undefined;
|
|
1068
1105
|
}
|
|
1069
1106
|
|
|
1070
1107
|
#appendToolResult(message: Extract<AgentMessage, { role: "toolResult" }>): void {
|
|
@@ -1178,6 +1215,15 @@ export class AgentHubOverlayComponent extends Container {
|
|
|
1178
1215
|
this.#chatLog.addChild(card);
|
|
1179
1216
|
return;
|
|
1180
1217
|
}
|
|
1218
|
+
const handoffComponent = createHandoffSummaryMessageComponent(
|
|
1219
|
+
message as CustomMessage<unknown>,
|
|
1220
|
+
this.#chatExpanded,
|
|
1221
|
+
);
|
|
1222
|
+
if (handoffComponent) {
|
|
1223
|
+
this.#trackExpandable(handoffComponent);
|
|
1224
|
+
this.#chatLog.addChild(handoffComponent);
|
|
1225
|
+
return;
|
|
1226
|
+
}
|
|
1181
1227
|
const component = new CustomMessageComponent(
|
|
1182
1228
|
message as CustomMessage<unknown>,
|
|
1183
1229
|
this.#getMessageRenderer?.(message.customType),
|
|
@@ -1,11 +1,10 @@
|
|
|
1
|
-
import type { AssistantMessage, ImageContent
|
|
1
|
+
import type { AssistantMessage, ImageContent } from "@oh-my-pi/pi-ai";
|
|
2
2
|
import { Container, Image, type ImageBudget, ImageProtocol, Markdown, Spacer, TERMINAL, Text } from "@oh-my-pi/pi-tui";
|
|
3
|
-
import { formatNumber } from "@oh-my-pi/pi-utils";
|
|
4
|
-
import { settings } from "../../config/settings";
|
|
5
3
|
import type { AssistantThinkingRenderer } from "../../extensibility/extensions/types";
|
|
6
4
|
import { getMarkdownTheme, theme } from "../../modes/theme/theme";
|
|
7
5
|
import { resolveAbortLabel, shouldRenderAbortReason } from "../../session/messages";
|
|
8
6
|
import { getPreviewLines, resolveImageOptions, TRUNCATE_LENGTHS } from "../../tools/render-utils";
|
|
7
|
+
import { getVisibleThinkingText, hasVisibleThinking } from "../../utils/thinking-display";
|
|
9
8
|
|
|
10
9
|
/**
|
|
11
10
|
* Max lines of a turn-ending provider error rendered inline in the transcript.
|
|
@@ -23,7 +22,6 @@ export class AssistantMessageComponent extends Container {
|
|
|
23
22
|
#contentContainer: Container;
|
|
24
23
|
#lastMessage?: AssistantMessage;
|
|
25
24
|
#toolImagesByCallId = new Map<string, ImageContent[]>();
|
|
26
|
-
#usageInfo?: Usage;
|
|
27
25
|
#convertedKittyImages = new Map<string, ImageContent>();
|
|
28
26
|
#kittyConversionsInFlight = new Set<string>();
|
|
29
27
|
#transcriptBlockFinalized: boolean;
|
|
@@ -39,11 +37,9 @@ export class AssistantMessageComponent extends Container {
|
|
|
39
37
|
/**
|
|
40
38
|
* Monotonic content version reported to the transcript container via
|
|
41
39
|
* {@link getTranscriptBlockVersion}. Bumped by {@link updateContent} — the
|
|
42
|
-
* choke point every mutator funnels through, including
|
|
43
|
-
*
|
|
44
|
-
* turn's `agent_start`, late tool-result images, async Kitty conversions
|
|
45
|
-
* and `setUsageInfo`. Without it, the container's committed-scrollback
|
|
46
|
-
* bypass would replay this block's pre-mutation bytes forever.
|
|
40
|
+
* choke point every mutator funnels through, including post-finalize changes
|
|
41
|
+
* such as `setErrorPinned(false)` restoring the inline error at the next
|
|
42
|
+
* turn's `agent_start`, late tool-result images, and async Kitty conversions.
|
|
47
43
|
*/
|
|
48
44
|
#blockVersion = 0;
|
|
49
45
|
/** Whether the last updateContent carried an in-flight streaming partial; such
|
|
@@ -184,13 +180,6 @@ export class AssistantMessageComponent extends Container {
|
|
|
184
180
|
}
|
|
185
181
|
}
|
|
186
182
|
|
|
187
|
-
setUsageInfo(usage: Usage): void {
|
|
188
|
-
this.#usageInfo = usage;
|
|
189
|
-
if (this.#lastMessage) {
|
|
190
|
-
this.updateContent(this.#lastMessage, { transient: this.#lastUpdateTransient });
|
|
191
|
-
}
|
|
192
|
-
}
|
|
193
|
-
|
|
194
183
|
#renderToolImages(): void {
|
|
195
184
|
const imageEntries = Array.from(this.#toolImagesByCallId.entries()).flatMap(([toolCallId, images]) =>
|
|
196
185
|
images.map((image, index) => ({ image, key: `${toolCallId}:${index}` })),
|
|
@@ -245,7 +234,7 @@ export class AssistantMessageComponent extends Container {
|
|
|
245
234
|
if (content.type === "text") {
|
|
246
235
|
parts.push(content.text.trim() ? "T1" : "T0");
|
|
247
236
|
} else if (content.type === "thinking") {
|
|
248
|
-
if (!content
|
|
237
|
+
if (!hasVisibleThinking(content)) parts.push("K0");
|
|
249
238
|
else if (this.hideThinkingBlock) parts.push("KH");
|
|
250
239
|
else parts.push("KV");
|
|
251
240
|
} else {
|
|
@@ -255,12 +244,6 @@ export class AssistantMessageComponent extends Container {
|
|
|
255
244
|
parts.push(`O:${content.type}`);
|
|
256
245
|
}
|
|
257
246
|
}
|
|
258
|
-
if (settings.get("display.showTokenUsage") && this.#usageInfo) {
|
|
259
|
-
const u = this.#usageInfo;
|
|
260
|
-
parts.push(`u:${u.input + u.cacheWrite}:${u.output}:${u.cacheRead}`);
|
|
261
|
-
} else {
|
|
262
|
-
parts.push("u:");
|
|
263
|
-
}
|
|
264
247
|
return parts.join("|");
|
|
265
248
|
}
|
|
266
249
|
|
|
@@ -284,7 +267,7 @@ export class AssistantMessageComponent extends Container {
|
|
|
284
267
|
for (const item of this.#fastPathItems) {
|
|
285
268
|
if (item.blockType === "thinking") {
|
|
286
269
|
const content = message.content[item.contentIndex];
|
|
287
|
-
if (content?.type === "thinking" && content
|
|
270
|
+
if (content?.type === "thinking" && getVisibleThinkingText(content) !== item.lastText) return false;
|
|
288
271
|
}
|
|
289
272
|
}
|
|
290
273
|
}
|
|
@@ -312,7 +295,7 @@ export class AssistantMessageComponent extends Container {
|
|
|
312
295
|
if (item.blockType === "text" && content?.type === "text") {
|
|
313
296
|
newText = content.text.trim();
|
|
314
297
|
} else if (item.blockType === "thinking" && content?.type === "thinking") {
|
|
315
|
-
newText = content
|
|
298
|
+
newText = getVisibleThinkingText(content);
|
|
316
299
|
} else {
|
|
317
300
|
// Block at this index is gone or changed type (index shift) — fail closed.
|
|
318
301
|
this.#fastPathKey = undefined;
|
|
@@ -347,7 +330,7 @@ export class AssistantMessageComponent extends Container {
|
|
|
347
330
|
const hasVisibleContent = message.content.some(
|
|
348
331
|
c =>
|
|
349
332
|
(c.type === "text" && c.text.trim()) ||
|
|
350
|
-
(!this.hideThinkingBlock && c.type === "thinking" && c
|
|
333
|
+
(!this.hideThinkingBlock && c.type === "thinking" && hasVisibleThinking(c)),
|
|
351
334
|
);
|
|
352
335
|
|
|
353
336
|
// Render content in order
|
|
@@ -362,7 +345,8 @@ export class AssistantMessageComponent extends Container {
|
|
|
362
345
|
md.transientRenderCache = this.#lastUpdateTransient;
|
|
363
346
|
this.#contentContainer.addChild(md);
|
|
364
347
|
captureItems?.push({ md, contentIndex: i, blockType: "text", lastText: trimmed });
|
|
365
|
-
} else if (content.type === "thinking" && content
|
|
348
|
+
} else if (content.type === "thinking" && hasVisibleThinking(content)) {
|
|
349
|
+
const thinkingText = getVisibleThinkingText(content);
|
|
366
350
|
if (this.hideThinkingBlock) {
|
|
367
351
|
thinkingIndex += 1;
|
|
368
352
|
continue;
|
|
@@ -371,9 +355,8 @@ export class AssistantMessageComponent extends Container {
|
|
|
371
355
|
// This avoids a superfluous blank line before separately-rendered tool execution blocks.
|
|
372
356
|
const hasVisibleContentAfter = message.content
|
|
373
357
|
.slice(i + 1)
|
|
374
|
-
.some(c => (c.type === "text" && c.text.trim()) || (c.type === "thinking" && c
|
|
358
|
+
.some(c => (c.type === "text" && c.text.trim()) || (c.type === "thinking" && hasVisibleThinking(c)));
|
|
375
359
|
|
|
376
|
-
const thinkingText = content.thinking.trim();
|
|
377
360
|
// Thinking traces in thinkingText color, italic
|
|
378
361
|
const md = new Markdown(thinkingText, 1, 0, getMarkdownTheme(), {
|
|
379
362
|
color: (text: string) => theme.fg("thinkingText", text),
|
|
@@ -415,21 +398,6 @@ export class AssistantMessageComponent extends Container {
|
|
|
415
398
|
) {
|
|
416
399
|
this.#appendErrorBlock(message.errorMessage);
|
|
417
400
|
}
|
|
418
|
-
|
|
419
|
-
// Token usage metadata
|
|
420
|
-
if (settings.get("display.showTokenUsage") && this.#usageInfo) {
|
|
421
|
-
const usage = this.#usageInfo;
|
|
422
|
-
const totalInput = usage.input + usage.cacheWrite;
|
|
423
|
-
const parts: string[] = [];
|
|
424
|
-
parts.push(`${theme.icon.input} ${formatNumber(totalInput)}`);
|
|
425
|
-
parts.push(`${theme.icon.output} ${formatNumber(usage.output)}`);
|
|
426
|
-
if (usage.cacheRead > 0) {
|
|
427
|
-
parts.push(`cache: ${formatNumber(usage.cacheRead)}`);
|
|
428
|
-
}
|
|
429
|
-
this.#contentContainer.addChild(new Spacer(1));
|
|
430
|
-
this.#contentContainer.addChild(new Text(theme.fg("dim", parts.join(" ")), 1, 0));
|
|
431
|
-
}
|
|
432
|
-
|
|
433
401
|
// Store fast-path state for next call
|
|
434
402
|
if (shouldCapture) {
|
|
435
403
|
this.#fastPathItems = captureItems;
|