@oh-my-pi/pi-coding-agent 15.10.9 → 15.10.11
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +117 -0
- package/dist/cli.js +23087 -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 +1 -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/commands/launch.d.ts +1 -1
- package/dist/types/commands/read.d.ts +1 -1
- package/dist/types/commands/usage.d.ts +25 -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 +20 -219
- package/dist/types/config/model-resolver.d.ts +16 -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 +12 -16
- package/dist/types/config/settings.d.ts +1 -1
- package/dist/types/debug/log-viewer.d.ts +1 -1
- package/dist/types/debug/raw-sse.d.ts +1 -1
- package/dist/types/debug/terminal-info.d.ts +0 -1
- 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/export/html/template.generated.d.ts +1 -1
- package/dist/types/extensibility/extensions/types.d.ts +3 -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/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 +31 -26
- 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/interactive-mode.d.ts +1 -1
- 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 +2 -1
- package/dist/types/session/agent-session.d.ts +1 -1
- package/dist/types/session/auth-broker-config.d.ts +4 -0
- package/dist/types/session/session-manager.d.ts +1 -1
- package/dist/types/slash-commands/helpers/stats-dashboard.d.ts +13 -0
- package/dist/types/ssh/connection-manager.d.ts +8 -0
- package/dist/types/task/discovery.d.ts +1 -2
- package/dist/types/task/parallel.d.ts +2 -2
- package/dist/types/task/worktree.d.ts +2 -0
- package/dist/types/tiny/title-client.d.ts +1 -1
- 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/sqlite-reader.d.ts +3 -0
- package/dist/types/tools/todo.d.ts +2 -0
- package/dist/types/tui/output-block.d.ts +3 -3
- package/dist/types/utils/changelog.d.ts +8 -0
- 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/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 +1 -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 +7 -12
- package/src/cli/usage-cli.ts +603 -0
- package/src/cli-commands.ts +1 -0
- package/src/cli.ts +69 -5
- package/src/commands/complete.ts +1 -1
- package/src/commands/launch.ts +1 -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 +1 -1
- package/src/config/append-only-context-mode.ts +6 -12
- package/src/config/model-discovery.ts +554 -0
- package/src/config/model-registry.ts +308 -1025
- package/src/config/model-resolver.ts +113 -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 +18 -14
- package/src/config/settings.ts +37 -1
- 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/debug/terminal-info.ts +0 -3
- package/src/edit/diff.ts +95 -18
- package/src/edit/hashline/block-resolver.ts +20 -1
- package/src/edit/hashline/diff.ts +36 -1
- package/src/edit/hashline/execute.ts +8 -2
- 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 +2 -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 +49 -23
- package/src/eval/js/shared/runtime.ts +1 -1
- package/src/eval/py/index.ts +0 -2
- package/src/eval/py/kernel.ts +19 -0
- package/src/eval/py/runner.py +107 -3
- package/src/exec/bash-executor.ts +3 -1
- package/src/export/html/template.generated.ts +1 -1
- package/src/export/html/template.js +3 -1
- package/src/extensibility/extensions/types.ts +3 -2
- package/src/extensibility/plugins/legacy-pi-compat.ts +20 -3
- 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 +10 -10
- 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 +165 -17
- package/src/mcp/json-rpc.ts +35 -5
- package/src/mcp/transports/stdio.ts +7 -1
- package/src/memories/index.ts +2 -1
- package/src/mnemopi/backend.ts +25 -3
- package/src/mnemopi/state.ts +38 -2
- package/src/modes/components/agent-dashboard.ts +10 -7
- package/src/modes/components/assistant-message.ts +19 -13
- 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 +1 -1
- 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 +66 -54
- 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 +1 -1
- package/src/modes/components/tiny-title-download-progress.ts +1 -1
- package/src/modes/components/transcript-container.ts +373 -141
- 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 +10 -3
- package/src/modes/controllers/event-controller.ts +73 -49
- package/src/modes/controllers/input-controller.ts +5 -5
- package/src/modes/controllers/mcp-command-controller.ts +1 -1
- package/src/modes/controllers/selector-controller.ts +1 -5
- package/src/modes/controllers/streaming-reveal.ts +85 -18
- package/src/modes/interactive-mode.ts +5 -19
- 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 +2 -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 +15 -26
- 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 +8 -10
- 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 +6 -2
- package/src/sdk.ts +23 -10
- package/src/session/agent-session.ts +44 -10
- package/src/session/auth-broker-config.ts +30 -1
- package/src/session/session-manager.ts +2 -2
- package/src/session/streaming-output.ts +23 -2
- package/src/slash-commands/builtin-registry.ts +20 -0
- package/src/slash-commands/helpers/stats-dashboard.ts +85 -0
- package/src/ssh/connection-manager.ts +27 -0
- package/src/task/commands.ts +2 -1
- package/src/task/discovery.ts +17 -24
- package/src/task/executor.ts +61 -53
- package/src/task/index.ts +137 -60
- package/src/task/parallel.ts +3 -3
- package/src/task/render.ts +2 -2
- package/src/task/worktree.ts +64 -56
- package/src/thinking.ts +2 -1
- package/src/tiny/title-client.ts +32 -14
- 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 +54 -13
- 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 +3 -9
- 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 +51 -12
- 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/file-mentions.ts +2 -1
- 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/anthropic.ts +8 -2
- 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
|
@@ -36,6 +36,9 @@ export class AssistantMessageComponent extends Container {
|
|
|
36
36
|
* transcript keeps the error in history.
|
|
37
37
|
*/
|
|
38
38
|
#errorPinned = false;
|
|
39
|
+
/** Whether the last updateContent carried an in-flight streaming partial; such
|
|
40
|
+
* renders bypass the markdown module LRU (see Markdown.transientRenderCache). */
|
|
41
|
+
#lastUpdateTransient = false;
|
|
39
42
|
|
|
40
43
|
constructor(
|
|
41
44
|
message?: AssistantMessage,
|
|
@@ -59,7 +62,7 @@ export class AssistantMessageComponent extends Container {
|
|
|
59
62
|
override invalidate(): void {
|
|
60
63
|
super.invalidate();
|
|
61
64
|
if (this.#lastMessage) {
|
|
62
|
-
this.updateContent(this.#lastMessage);
|
|
65
|
+
this.updateContent(this.#lastMessage, { transient: this.#lastUpdateTransient });
|
|
63
66
|
}
|
|
64
67
|
}
|
|
65
68
|
|
|
@@ -75,7 +78,7 @@ export class AssistantMessageComponent extends Container {
|
|
|
75
78
|
if (this.#errorPinned === pinned) return;
|
|
76
79
|
this.#errorPinned = pinned;
|
|
77
80
|
if (this.#lastMessage) {
|
|
78
|
-
this.updateContent(this.#lastMessage);
|
|
81
|
+
this.updateContent(this.#lastMessage, { transient: this.#lastUpdateTransient });
|
|
79
82
|
}
|
|
80
83
|
}
|
|
81
84
|
|
|
@@ -123,7 +126,7 @@ export class AssistantMessageComponent extends Container {
|
|
|
123
126
|
this.#convertToolImagesForKitty(toolCallId, validImages);
|
|
124
127
|
}
|
|
125
128
|
if (this.#lastMessage) {
|
|
126
|
-
this.updateContent(this.#lastMessage);
|
|
129
|
+
this.updateContent(this.#lastMessage, { transient: this.#lastUpdateTransient });
|
|
127
130
|
}
|
|
128
131
|
}
|
|
129
132
|
|
|
@@ -146,7 +149,7 @@ export class AssistantMessageComponent extends Container {
|
|
|
146
149
|
mimeType: "image/png",
|
|
147
150
|
});
|
|
148
151
|
if (this.#lastMessage) {
|
|
149
|
-
this.updateContent(this.#lastMessage);
|
|
152
|
+
this.updateContent(this.#lastMessage, { transient: this.#lastUpdateTransient });
|
|
150
153
|
}
|
|
151
154
|
this.onImageUpdate?.();
|
|
152
155
|
})
|
|
@@ -159,7 +162,7 @@ export class AssistantMessageComponent extends Container {
|
|
|
159
162
|
setUsageInfo(usage: Usage): void {
|
|
160
163
|
this.#usageInfo = usage;
|
|
161
164
|
if (this.#lastMessage) {
|
|
162
|
-
this.updateContent(this.#lastMessage);
|
|
165
|
+
this.updateContent(this.#lastMessage, { transient: this.#lastUpdateTransient });
|
|
163
166
|
}
|
|
164
167
|
}
|
|
165
168
|
|
|
@@ -211,8 +214,9 @@ export class AssistantMessageComponent extends Container {
|
|
|
211
214
|
}
|
|
212
215
|
}
|
|
213
216
|
|
|
214
|
-
updateContent(message: AssistantMessage): void {
|
|
217
|
+
updateContent(message: AssistantMessage, opts?: { transient?: boolean }): void {
|
|
215
218
|
this.#lastMessage = message;
|
|
219
|
+
this.#lastUpdateTransient = opts?.transient === true;
|
|
216
220
|
|
|
217
221
|
// Clear content container
|
|
218
222
|
this.#contentContainer.clear();
|
|
@@ -228,7 +232,9 @@ export class AssistantMessageComponent extends Container {
|
|
|
228
232
|
if (content.type === "text" && content.text.trim()) {
|
|
229
233
|
// Assistant text messages with no background - trim the text
|
|
230
234
|
// Set paddingY=0 to avoid extra spacing before tool executions
|
|
231
|
-
|
|
235
|
+
const markdown = new Markdown(content.text.trim(), 1, 0, getMarkdownTheme());
|
|
236
|
+
markdown.transientRenderCache = this.#lastUpdateTransient;
|
|
237
|
+
this.#contentContainer.addChild(markdown);
|
|
232
238
|
} else if (content.type === "thinking" && content.thinking.trim()) {
|
|
233
239
|
// Add spacing only when another visible assistant content block follows.
|
|
234
240
|
// This avoids a superfluous blank line before separately-rendered tool execution blocks.
|
|
@@ -245,12 +251,12 @@ export class AssistantMessageComponent extends Container {
|
|
|
245
251
|
} else {
|
|
246
252
|
const thinkingText = content.thinking.trim();
|
|
247
253
|
// Thinking traces in thinkingText color, italic
|
|
248
|
-
|
|
249
|
-
|
|
250
|
-
|
|
251
|
-
|
|
252
|
-
|
|
253
|
-
);
|
|
254
|
+
const thinkingMarkdown = new Markdown(thinkingText, 1, 0, getMarkdownTheme(), {
|
|
255
|
+
color: (text: string) => theme.fg("thinkingText", text),
|
|
256
|
+
italic: true,
|
|
257
|
+
});
|
|
258
|
+
thinkingMarkdown.transientRenderCache = this.#lastUpdateTransient;
|
|
259
|
+
this.#contentContainer.addChild(thinkingMarkdown);
|
|
254
260
|
this.#appendThinkingExtensions(i, thinkingIndex, thinkingText);
|
|
255
261
|
thinkingIndex += 1;
|
|
256
262
|
if (hasVisibleContentAfter) {
|
|
@@ -126,7 +126,7 @@ export class BashExecutionComponent extends Container {
|
|
|
126
126
|
this.#updateDisplay();
|
|
127
127
|
}
|
|
128
128
|
|
|
129
|
-
override render(width: number): string[] {
|
|
129
|
+
override render(width: number): readonly string[] {
|
|
130
130
|
if (this.#displayDirty) {
|
|
131
131
|
this.#displayDirty = false;
|
|
132
132
|
this.#updateDisplay();
|
|
@@ -173,7 +173,7 @@ export class CopySelectorComponent implements Component {
|
|
|
173
173
|
return out;
|
|
174
174
|
}
|
|
175
175
|
|
|
176
|
-
render(width: number): string[] {
|
|
176
|
+
render(width: number): readonly string[] {
|
|
177
177
|
const height = process.stdout.rows || 40;
|
|
178
178
|
const flat = this.#flatten();
|
|
179
179
|
const cursorIdx = Math.max(
|
|
@@ -109,10 +109,16 @@ export function renderDiff(diffText: string, options: RenderDiffOptions = {}): s
|
|
|
109
109
|
const lines = sanitizeText(diffText).split("\n");
|
|
110
110
|
const result: string[] = [];
|
|
111
111
|
const parsedLines = lines.map(parseDiffLine);
|
|
112
|
+
// Reserve 3 gutter digits: a streaming preview re-renders this diff as it
|
|
113
|
+
// grows, and a width derived purely from the current max line number widens
|
|
114
|
+
// at the 100-line crossing — re-padding every already-rendered row, which
|
|
115
|
+
// breaks the transcript's append-only commit detection and forces a full
|
|
116
|
+
// recommit of the block into native scrollback. A constant gutter through
|
|
117
|
+
// 999 lines keeps streamed rows byte-identical to the final result render.
|
|
112
118
|
const lineNumberWidth = parsedLines.reduce((width, parsed) => {
|
|
113
119
|
const lineNumber = parsed?.lineNum.trim() ?? "";
|
|
114
120
|
return Math.max(width, lineNumber.length);
|
|
115
|
-
},
|
|
121
|
+
}, 3);
|
|
116
122
|
|
|
117
123
|
// Batch-highlight context (unedited) lines so consecutive lines tokenize
|
|
118
124
|
// with full multi-line context. Highlighting is a no-op when no language
|
|
@@ -142,7 +148,12 @@ export function renderDiff(diffText: string, options: RenderDiffOptions = {}): s
|
|
|
142
148
|
|
|
143
149
|
if (!parsed) {
|
|
144
150
|
prevLineNum = "";
|
|
145
|
-
|
|
151
|
+
// Blank gap rows (and legacy "..." markers from older transcripts)
|
|
152
|
+
// mark non-contiguous diff regions; display them as a single dim
|
|
153
|
+
// unicode ellipsis.
|
|
154
|
+
const trimmed = line.trim();
|
|
155
|
+
const isGapRow = trimmed.length === 0 || trimmed === "..." || trimmed === "…";
|
|
156
|
+
result.push(theme.fg("toolDiffContext", isGapRow ? "…" : replaceTabs(line, options.filePath)));
|
|
146
157
|
i++;
|
|
147
158
|
continue;
|
|
148
159
|
}
|
|
@@ -10,16 +10,25 @@ import { theme } from "../../modes/theme/theme";
|
|
|
10
10
|
*/
|
|
11
11
|
export class DynamicBorder implements Component {
|
|
12
12
|
#color: (str: string) => string;
|
|
13
|
+
#cachedWidth = -1;
|
|
14
|
+
#cachedLines: string[] | undefined;
|
|
13
15
|
|
|
14
16
|
constructor(color: (str: string) => string = str => theme.fg("border", str)) {
|
|
15
17
|
this.#color = color;
|
|
16
18
|
}
|
|
17
19
|
|
|
18
20
|
invalidate(): void {
|
|
19
|
-
|
|
21
|
+
this.#cachedWidth = -1;
|
|
22
|
+
this.#cachedLines = undefined;
|
|
20
23
|
}
|
|
21
24
|
|
|
22
|
-
render(width: number): string[] {
|
|
23
|
-
|
|
25
|
+
render(width: number): readonly string[] {
|
|
26
|
+
if (this.#cachedLines && this.#cachedWidth === width) {
|
|
27
|
+
return this.#cachedLines;
|
|
28
|
+
}
|
|
29
|
+
const lines = [this.#color(theme.boxSharp.horizontal.repeat(Math.max(1, width)))];
|
|
30
|
+
this.#cachedWidth = width;
|
|
31
|
+
this.#cachedLines = lines;
|
|
32
|
+
return lines;
|
|
24
33
|
}
|
|
25
34
|
}
|
|
@@ -137,7 +137,7 @@ export class ExtensionDashboard extends Container {
|
|
|
137
137
|
return Math.max(3, this.#computeBodyHeight() - 3);
|
|
138
138
|
}
|
|
139
139
|
|
|
140
|
-
override render(width: number): string[] {
|
|
140
|
+
override render(width: number): readonly string[] {
|
|
141
141
|
// Rebuild when terminal geometry changes so the full-screen overlay
|
|
142
142
|
// re-fits on resize.
|
|
143
143
|
if (this.#terminalRows() !== this.#builtRows || this.#uiWidth() !== this.#builtCols) {
|
|
@@ -145,10 +145,13 @@ export class ExtensionDashboard extends Container {
|
|
|
145
145
|
}
|
|
146
146
|
const lines = super.render(width);
|
|
147
147
|
// Pad to the full viewport so the dashboard covers the screen instead of
|
|
148
|
-
// letting the transcript peek through below it.
|
|
148
|
+
// letting the transcript peek through below it. Copy before padding — the
|
|
149
|
+
// container's render result is component-owned and must not be mutated.
|
|
149
150
|
const rows = this.#terminalRows();
|
|
150
|
-
|
|
151
|
-
|
|
151
|
+
if (lines.length >= rows) return lines;
|
|
152
|
+
const padded = lines.slice();
|
|
153
|
+
while (padded.length < rows) padded.push("");
|
|
154
|
+
return padded;
|
|
152
155
|
}
|
|
153
156
|
|
|
154
157
|
#buildLayout(): void {
|
|
@@ -367,7 +370,7 @@ class TwoColumnBody implements Component {
|
|
|
367
370
|
private readonly maxHeight: number,
|
|
368
371
|
) {}
|
|
369
372
|
|
|
370
|
-
render(width: number): string[] {
|
|
373
|
+
render(width: number): readonly string[] {
|
|
371
374
|
const leftWidth = Math.floor(width * 0.5);
|
|
372
375
|
const rightWidth = Math.max(0, width - leftWidth - 3);
|
|
373
376
|
|
|
@@ -18,7 +18,7 @@ export class InspectorPanel implements Component {
|
|
|
18
18
|
|
|
19
19
|
invalidate(): void {}
|
|
20
20
|
|
|
21
|
-
render(width: number): string[] {
|
|
21
|
+
render(width: number): readonly string[] {
|
|
22
22
|
if (!this.#extension) {
|
|
23
23
|
return [theme.fg("muted", "Select an extension"), theme.fg("dim", "to view details")];
|
|
24
24
|
}
|
|
@@ -110,7 +110,7 @@ export class FooterComponent implements Component {
|
|
|
110
110
|
return this.#cachedBranch;
|
|
111
111
|
}
|
|
112
112
|
|
|
113
|
-
render(width: number): string[] {
|
|
113
|
+
render(width: number): readonly string[] {
|
|
114
114
|
const state = this.session.state;
|
|
115
115
|
|
|
116
116
|
// Calculate cumulative usage from ALL session entries (not just post-compaction messages)
|
|
@@ -98,7 +98,7 @@ class HistoryResultsList implements Component {
|
|
|
98
98
|
// No cached state to invalidate currently
|
|
99
99
|
}
|
|
100
100
|
|
|
101
|
-
render(width: number): string[] {
|
|
101
|
+
render(width: number): readonly string[] {
|
|
102
102
|
const lines: string[] = [];
|
|
103
103
|
|
|
104
104
|
if (this.#results.length === 0) {
|
|
@@ -86,6 +86,14 @@ export class HookEditorComponent extends Container {
|
|
|
86
86
|
this.#onSubmitCallback(this.#editor.getExpandedText());
|
|
87
87
|
}
|
|
88
88
|
|
|
89
|
+
/** Route non-bracketed paste transports (e.g. kitty's OSC 5522 enhanced clipboard)
|
|
90
|
+
* into the inner editor, mirroring bracketed-paste semantics. Without this hook,
|
|
91
|
+
* enhanced-paste routing falls back to the main prompt editor hidden behind the
|
|
92
|
+
* dialog (#2127 routing contract). */
|
|
93
|
+
pasteText(text: string): void {
|
|
94
|
+
this.#editor.pasteText(text);
|
|
95
|
+
}
|
|
96
|
+
|
|
89
97
|
/** Prompt-style: raw Enter submits; Editor owns newline-producing sequences. */
|
|
90
98
|
#handlePromptStyleInput(keyData: string): void {
|
|
91
99
|
// Prompt-style keeps Escape as an explicit cancel key and also honors app.interrupt remaps.
|
|
@@ -73,6 +73,14 @@ export class HookInputComponent extends Container {
|
|
|
73
73
|
}
|
|
74
74
|
}
|
|
75
75
|
|
|
76
|
+
/** Route non-bracketed paste transports (e.g. kitty's OSC 5522 enhanced clipboard)
|
|
77
|
+
* into the inner input, mirroring bracketed-paste semantics. Pasting counts as
|
|
78
|
+
* interaction, so the timeout countdown resets like any keystroke. */
|
|
79
|
+
pasteText(text: string): void {
|
|
80
|
+
this.#countdown?.reset();
|
|
81
|
+
this.#input.pasteText(text);
|
|
82
|
+
}
|
|
83
|
+
|
|
76
84
|
dispose(): void {
|
|
77
85
|
this.#countdown?.dispose();
|
|
78
86
|
}
|
|
@@ -122,7 +122,7 @@ class OutlinedList extends Container {
|
|
|
122
122
|
this.invalidate();
|
|
123
123
|
}
|
|
124
124
|
|
|
125
|
-
render(width: number): string[] {
|
|
125
|
+
render(width: number): readonly string[] {
|
|
126
126
|
const borderColor = (text: string) => theme.fg("border", text);
|
|
127
127
|
const horizontal = borderColor(theme.boxSharp.horizontal.repeat(Math.max(1, width)));
|
|
128
128
|
const innerWidth = Math.max(1, width - 2);
|
|
@@ -645,7 +645,7 @@ export class HookSelectorComponent extends Container {
|
|
|
645
645
|
}
|
|
646
646
|
}
|
|
647
647
|
|
|
648
|
-
override render(width: number): string[] {
|
|
648
|
+
override render(width: number): readonly string[] {
|
|
649
649
|
const renderWidth = Math.max(1, width);
|
|
650
650
|
if (this.#lastRenderWidth !== renderWidth) {
|
|
651
651
|
this.#lastRenderWidth = renderWidth;
|
|
@@ -1,5 +1,7 @@
|
|
|
1
1
|
import { ThinkingLevel } from "@oh-my-pi/pi-agent-core";
|
|
2
|
-
import {
|
|
2
|
+
import type { Model } from "@oh-my-pi/pi-ai";
|
|
3
|
+
import { getSupportedEfforts } from "@oh-my-pi/pi-catalog/model-thinking";
|
|
4
|
+
import { modelsAreEqual } from "@oh-my-pi/pi-catalog/models";
|
|
3
5
|
import {
|
|
4
6
|
Container,
|
|
5
7
|
fuzzyFilter,
|
|
@@ -16,8 +18,8 @@ import {
|
|
|
16
18
|
} from "@oh-my-pi/pi-tui";
|
|
17
19
|
import { formatNumber } from "@oh-my-pi/pi-utils";
|
|
18
20
|
import type { ModelRegistry } from "../../config/model-registry";
|
|
19
|
-
import { getKnownRoleIds, getRoleInfo, MODEL_ROLE_IDS, MODEL_ROLES } from "../../config/model-registry";
|
|
20
21
|
import { getModelMatchPreferences, resolveModelRoleValue } from "../../config/model-resolver";
|
|
22
|
+
import { getKnownRoleIds, getRoleInfo, MODEL_ROLE_IDS, MODEL_ROLES } from "../../config/model-roles";
|
|
21
23
|
import type { Settings } from "../../config/settings";
|
|
22
24
|
import { type ThemeColor, theme } from "../../modes/theme/theme";
|
|
23
25
|
import { matchesSelectDown, matchesSelectUp } from "../../modes/utils/keybinding-matchers";
|
|
@@ -263,21 +265,26 @@ export class ModelSelectorComponent extends Container {
|
|
|
263
265
|
// Add bottom border
|
|
264
266
|
this.addChild(new DynamicBorder());
|
|
265
267
|
|
|
266
|
-
//
|
|
267
|
-
|
|
268
|
-
|
|
269
|
-
|
|
270
|
-
|
|
271
|
-
|
|
272
|
-
|
|
273
|
-
|
|
274
|
-
|
|
275
|
-
|
|
276
|
-
|
|
277
|
-
|
|
278
|
-
|
|
279
|
-
|
|
280
|
-
|
|
268
|
+
// Hydrate synchronously from the current registry snapshot so the first
|
|
269
|
+
// Enter after opening the selector acts on cached models instead of being
|
|
270
|
+
// dropped while the offline refresh promise is still pending. This stays
|
|
271
|
+
// on the open path, so it must remain cheap — heavy lifting lives in the
|
|
272
|
+
// registry's one-pass getCanonicalModelSelections.
|
|
273
|
+
this.#syncFromRegistryState();
|
|
274
|
+
|
|
275
|
+
// Reconcile with cached discovery state in the background. A --models
|
|
276
|
+
// scope is registry-independent, so the offline reload would only repeat
|
|
277
|
+
// the synchronous hydration above.
|
|
278
|
+
if (this.#scopedModels.length === 0) {
|
|
279
|
+
this.#modelRegistry
|
|
280
|
+
.refresh("offline")
|
|
281
|
+
.then(() => this.#syncFromRegistryState())
|
|
282
|
+
.catch(error => {
|
|
283
|
+
this.#errorMessage = error instanceof Error ? error.message : String(error);
|
|
284
|
+
this.#updateList();
|
|
285
|
+
})
|
|
286
|
+
.finally(() => this.#tui.requestRender());
|
|
287
|
+
}
|
|
281
288
|
}
|
|
282
289
|
|
|
283
290
|
#buildMenuRoleActions(): void {
|
|
@@ -477,37 +484,30 @@ export class ModelSelectorComponent extends Container {
|
|
|
477
484
|
|
|
478
485
|
const candidates = models.map(item => item.model);
|
|
479
486
|
this.#loadRoleModels(candidates);
|
|
480
|
-
const
|
|
487
|
+
const canonicalSelections = this.#modelRegistry.getCanonicalModelSelections({
|
|
481
488
|
availableOnly: this.#scopedModels.length === 0,
|
|
482
489
|
candidates,
|
|
483
490
|
});
|
|
484
|
-
const canonicalModels =
|
|
485
|
-
|
|
486
|
-
|
|
487
|
-
|
|
488
|
-
|
|
489
|
-
|
|
490
|
-
|
|
491
|
-
|
|
492
|
-
|
|
493
|
-
|
|
494
|
-
|
|
495
|
-
|
|
496
|
-
|
|
497
|
-
|
|
498
|
-
|
|
499
|
-
|
|
500
|
-
|
|
501
|
-
|
|
502
|
-
|
|
503
|
-
|
|
504
|
-
variantCount: record.variants.length,
|
|
505
|
-
searchText,
|
|
506
|
-
normalizedSearchText: normalizeSearchText(searchText),
|
|
507
|
-
compactSearchText: compactSearchText(searchText),
|
|
508
|
-
};
|
|
509
|
-
})
|
|
510
|
-
.filter((item): item is CanonicalModelItem => item !== undefined);
|
|
491
|
+
const canonicalModels = canonicalSelections.map(({ record, model: selectedModel }): CanonicalModelItem => {
|
|
492
|
+
const searchText = [
|
|
493
|
+
record.id,
|
|
494
|
+
record.name,
|
|
495
|
+
selectedModel.provider,
|
|
496
|
+
selectedModel.id,
|
|
497
|
+
selectedModel.name,
|
|
498
|
+
...record.variants.flatMap(variant => [variant.selector, variant.model.name]),
|
|
499
|
+
].join(" ");
|
|
500
|
+
return {
|
|
501
|
+
kind: "canonical",
|
|
502
|
+
id: record.id,
|
|
503
|
+
model: selectedModel,
|
|
504
|
+
selector: record.id,
|
|
505
|
+
variantCount: record.variants.length,
|
|
506
|
+
searchText,
|
|
507
|
+
normalizedSearchText: normalizeSearchText(searchText),
|
|
508
|
+
compactSearchText: compactSearchText(searchText),
|
|
509
|
+
};
|
|
510
|
+
});
|
|
511
511
|
|
|
512
512
|
this.#sortModels(models);
|
|
513
513
|
this.#sortCanonicalModels(canonicalModels);
|
|
@@ -523,12 +523,27 @@ export class ModelSelectorComponent extends Container {
|
|
|
523
523
|
);
|
|
524
524
|
}
|
|
525
525
|
|
|
526
|
-
|
|
527
|
-
|
|
528
|
-
|
|
529
|
-
|
|
530
|
-
|
|
526
|
+
/**
|
|
527
|
+
* Rebuild the visible model lists from the registry's in-memory state.
|
|
528
|
+
* Re-entrant: runs once synchronously at construction and again whenever a
|
|
529
|
+
* background refresh lands, so it re-applies the live search query and pins
|
|
530
|
+
* the highlighted item by selector — a refresh that reorders or inserts
|
|
531
|
+
* models must not yank the user's selection out from under a pending Enter.
|
|
532
|
+
*/
|
|
533
|
+
#syncFromRegistryState(): void {
|
|
534
|
+
const selectedKey = this.#getSelectedItem()?.selector;
|
|
531
535
|
this.#loadModelsFromCurrentRegistryState();
|
|
536
|
+
this.#buildProviderTabs();
|
|
537
|
+
this.#updateTabBar();
|
|
538
|
+
this.#applyTabFilter();
|
|
539
|
+
if (selectedKey) {
|
|
540
|
+
const visibleItems = this.#getVisibleItems();
|
|
541
|
+
const restoredIndex = visibleItems.findIndex(item => item.selector === selectedKey);
|
|
542
|
+
if (restoredIndex >= 0 && restoredIndex !== this.#selectedIndex) {
|
|
543
|
+
this.#selectedIndex = this.#coerceSelectedIndex(restoredIndex, visibleItems);
|
|
544
|
+
this.#updateList();
|
|
545
|
+
}
|
|
546
|
+
}
|
|
532
547
|
}
|
|
533
548
|
|
|
534
549
|
#buildProviderTabs(): void {
|
|
@@ -631,10 +646,7 @@ export class ModelSelectorComponent extends Container {
|
|
|
631
646
|
// here must stay purely in-memory — do not call modelRegistry.refresh()
|
|
632
647
|
// again or tab switches will pay an extra whole-registry reload after the
|
|
633
648
|
// network round-trip completes.
|
|
634
|
-
this.#
|
|
635
|
-
this.#buildProviderTabs();
|
|
636
|
-
this.#updateTabBar();
|
|
637
|
-
this.#applyTabFilter();
|
|
649
|
+
this.#syncFromRegistryState();
|
|
638
650
|
} catch (error) {
|
|
639
651
|
this.#errorMessage = error instanceof Error ? error.message : String(error);
|
|
640
652
|
this.#updateList();
|
|
@@ -754,7 +754,7 @@ export class PlanReviewOverlay implements Component {
|
|
|
754
754
|
return [theme.fg("dim", this.#buildHelp())];
|
|
755
755
|
}
|
|
756
756
|
|
|
757
|
-
render(width: number): string[] {
|
|
757
|
+
render(width: number): readonly string[] {
|
|
758
758
|
const termHeight = process.stdout.rows || 40;
|
|
759
759
|
const sidebarShown = this.#sidebarVisible(width);
|
|
760
760
|
this.#sidebarShown = sidebarShown;
|
|
@@ -118,12 +118,12 @@ export class SessionObserverOverlayComponent extends Container {
|
|
|
118
118
|
return pool.sort((a, b) => b.lastUpdate - a.lastUpdate)[0];
|
|
119
119
|
}
|
|
120
120
|
|
|
121
|
-
override render(width: number): string[] {
|
|
121
|
+
override render(width: number): readonly string[] {
|
|
122
122
|
return this.#renderViewer(width);
|
|
123
123
|
}
|
|
124
124
|
|
|
125
125
|
#setupViewer(): void {
|
|
126
|
-
this.
|
|
126
|
+
this.clear();
|
|
127
127
|
this.#scrollOffset = 0;
|
|
128
128
|
this.#selectedEntryIndex = 0;
|
|
129
129
|
this.#expandedEntries.clear();
|
|
@@ -631,8 +631,12 @@ export class SettingsSelectorComponent extends Container {
|
|
|
631
631
|
return;
|
|
632
632
|
}
|
|
633
633
|
|
|
634
|
-
// Escape
|
|
634
|
+
// Escape clears an active settings search before closing the panel.
|
|
635
635
|
if (matchesAppInterrupt(data) && !this.#currentSubmenu) {
|
|
636
|
+
if (this.#currentList?.hasSearchQuery()) {
|
|
637
|
+
this.#currentList.clearSearch();
|
|
638
|
+
return;
|
|
639
|
+
}
|
|
636
640
|
this.callbacks.onCancel();
|
|
637
641
|
return;
|
|
638
642
|
}
|
|
@@ -769,7 +769,7 @@ export class StatusLineComponent implements Component {
|
|
|
769
769
|
};
|
|
770
770
|
}
|
|
771
771
|
|
|
772
|
-
render(width: number): string[] {
|
|
772
|
+
render(width: number): readonly string[] {
|
|
773
773
|
// Only render hook statuses - main status is in editor's top border
|
|
774
774
|
const showHooks = this.#settings.showHookStatus ?? true;
|
|
775
775
|
if (!showHooks || this.#hookStatuses.size === 0) {
|
|
@@ -71,7 +71,7 @@ export class TinyTitleDownloadProgressComponent implements Component {
|
|
|
71
71
|
// No cached state.
|
|
72
72
|
}
|
|
73
73
|
|
|
74
|
-
render(width: number): string[] {
|
|
74
|
+
render(width: number): readonly string[] {
|
|
75
75
|
width = Math.max(1, width);
|
|
76
76
|
const spec = getTinyTitleModelSpec(this.#modelKey);
|
|
77
77
|
const border = theme.fg("border", theme.boxSharp.horizontal.repeat(width));
|