@oh-my-pi/pi-coding-agent 8.1.0 → 8.2.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 +21 -1
- package/docs/session.md +111 -46
- package/examples/custom-tools/hello/index.ts +1 -1
- package/examples/custom-tools/todo/index.ts +3 -4
- package/examples/extensions/api-demo.ts +0 -1
- package/examples/extensions/chalk-logger.ts +2 -3
- package/examples/extensions/hello.ts +0 -1
- package/examples/extensions/pirate.ts +0 -1
- package/examples/extensions/plan-mode.ts +15 -16
- package/examples/extensions/todo.ts +3 -4
- package/examples/extensions/tools.ts +1 -2
- package/examples/extensions/with-deps/index.ts +0 -1
- package/examples/hooks/auto-commit-on-exit.ts +1 -2
- package/examples/hooks/confirm-destructive.ts +0 -1
- package/examples/hooks/custom-compaction.ts +1 -2
- package/examples/hooks/dirty-repo-guard.ts +0 -1
- package/examples/hooks/file-trigger.ts +3 -4
- package/examples/hooks/git-checkpoint.ts +0 -1
- package/examples/hooks/handoff.ts +3 -4
- package/examples/hooks/permission-gate.ts +1 -2
- package/examples/hooks/protected-paths.ts +1 -2
- package/examples/hooks/qna.ts +2 -3
- package/examples/hooks/snake.ts +4 -5
- package/examples/hooks/status-line.ts +0 -1
- package/examples/sdk/01-minimal.ts +2 -3
- package/examples/sdk/02-custom-model.ts +2 -3
- package/examples/sdk/03-custom-prompt.ts +3 -4
- package/examples/sdk/04-skills.ts +2 -3
- package/examples/sdk/06-extensions.ts +1 -2
- package/examples/sdk/06-hooks.ts +6 -7
- package/examples/sdk/07-context-files.ts +0 -1
- package/examples/sdk/08-prompt-templates.ts +0 -1
- package/examples/sdk/08-slash-commands.ts +0 -1
- package/examples/sdk/09-api-keys-and-oauth.ts +0 -1
- package/examples/sdk/10-settings.ts +0 -1
- package/examples/sdk/11-sessions.ts +0 -1
- package/package.json +51 -23
- package/scripts/format-prompts.ts +0 -1
- package/src/capability/context-file.ts +2 -3
- package/src/capability/extension-module.ts +2 -3
- package/src/capability/extension.ts +2 -3
- package/src/capability/fs.ts +20 -21
- package/src/capability/hook.ts +2 -3
- package/src/capability/index.ts +15 -16
- package/src/capability/instruction.ts +2 -3
- package/src/capability/mcp.ts +2 -3
- package/src/capability/prompt.ts +2 -3
- package/src/capability/rule.ts +2 -3
- package/src/capability/settings.ts +1 -2
- package/src/capability/skill.ts +2 -3
- package/src/capability/slash-command.ts +2 -3
- package/src/capability/ssh.ts +2 -3
- package/src/capability/system-prompt.ts +2 -3
- package/src/capability/tool.ts +2 -3
- package/src/cli/args.ts +5 -6
- package/src/cli/config-cli.ts +6 -7
- package/src/cli/file-processor.ts +19 -17
- package/src/cli/jupyter-cli.ts +105 -0
- package/src/cli/list-models.ts +10 -11
- package/src/cli/plugin-cli.ts +20 -21
- package/src/cli/session-picker.ts +2 -3
- package/src/cli/setup-cli.ts +2 -3
- package/src/cli/stats-cli.ts +2 -3
- package/src/cli/update-cli.ts +25 -22
- package/src/commit/agentic/agent.ts +21 -23
- package/src/commit/agentic/fallback.ts +9 -9
- package/src/commit/agentic/index.ts +30 -38
- package/src/commit/agentic/state.ts +1 -6
- package/src/commit/agentic/tools/analyze-file.ts +15 -15
- package/src/commit/agentic/tools/git-file-diff.ts +3 -3
- package/src/commit/agentic/tools/git-hunk.ts +7 -7
- package/src/commit/agentic/tools/git-overview.ts +5 -5
- package/src/commit/agentic/tools/index.ts +14 -14
- package/src/commit/agentic/tools/propose-changelog.ts +6 -6
- package/src/commit/agentic/tools/propose-commit.ts +8 -8
- package/src/commit/agentic/tools/recent-commits.ts +2 -2
- package/src/commit/agentic/tools/split-commit.ts +19 -23
- package/src/commit/agentic/topo-sort.ts +1 -1
- package/src/commit/agentic/trivial.ts +3 -3
- package/src/commit/agentic/validation.ts +12 -12
- package/src/commit/analysis/conventional.ts +7 -11
- package/src/commit/analysis/index.ts +4 -4
- package/src/commit/analysis/scope.ts +4 -4
- package/src/commit/analysis/summary.ts +7 -9
- package/src/commit/analysis/validation.ts +1 -1
- package/src/commit/changelog/detect.ts +6 -6
- package/src/commit/changelog/generate.ts +7 -9
- package/src/commit/changelog/index.ts +13 -13
- package/src/commit/changelog/parse.ts +2 -2
- package/src/commit/cli.ts +1 -1
- package/src/commit/git/diff.ts +3 -3
- package/src/commit/git/index.ts +19 -24
- package/src/commit/index.ts +1 -1
- package/src/commit/map-reduce/index.ts +9 -9
- package/src/commit/map-reduce/map-phase.ts +19 -34
- package/src/commit/map-reduce/reduce-phase.ts +9 -11
- package/src/commit/message.ts +2 -2
- package/src/commit/model-selection.ts +3 -7
- package/src/commit/pipeline.ts +20 -22
- package/src/commit/utils/exclusions.ts +3 -3
- package/src/config/file-lock.ts +17 -7
- package/src/config/keybindings.ts +6 -8
- package/src/config/model-registry.ts +55 -37
- package/src/config/model-resolver.ts +18 -19
- package/src/config/prompt-templates.ts +11 -11
- package/src/config/settings-manager.ts +50 -34
- package/src/config.ts +60 -62
- package/src/cursor.ts +11 -9
- package/src/discovery/agents-md.ts +11 -12
- package/src/discovery/builtin.ts +68 -73
- package/src/discovery/claude.ts +41 -42
- package/src/discovery/cline.ts +11 -12
- package/src/discovery/codex.ts +52 -53
- package/src/discovery/cursor.ts +9 -10
- package/src/discovery/gemini.ts +17 -22
- package/src/discovery/github.ts +13 -14
- package/src/discovery/helpers.ts +35 -34
- package/src/discovery/index.ts +16 -18
- package/src/discovery/mcp-json.ts +8 -9
- package/src/discovery/ssh.ts +8 -9
- package/src/discovery/vscode.ts +4 -5
- package/src/discovery/windsurf.ts +6 -7
- package/src/exa/company.ts +1 -2
- package/src/exa/index.ts +2 -3
- package/src/exa/linkedin.ts +1 -2
- package/src/exa/mcp-client.ts +14 -16
- package/src/exa/render.ts +10 -11
- package/src/exa/researcher.ts +1 -2
- package/src/exa/search.ts +1 -2
- package/src/exa/types.ts +0 -1
- package/src/exa/websets.ts +1 -2
- package/src/exec/bash-executor.ts +3 -4
- package/src/exec/exec.ts +0 -1
- package/src/export/custom-share.ts +5 -6
- package/src/export/html/index.ts +24 -21
- package/src/export/ttsr.ts +2 -3
- package/src/extensibility/custom-commands/bundled/review/index.ts +7 -8
- package/src/extensibility/custom-commands/loader.ts +17 -14
- package/src/extensibility/custom-commands/types.ts +1 -2
- package/src/extensibility/custom-tools/loader.ts +10 -11
- package/src/extensibility/custom-tools/types.ts +6 -7
- package/src/extensibility/custom-tools/wrapper.ts +2 -3
- package/src/extensibility/extensions/loader.ts +75 -53
- package/src/extensibility/extensions/runner.ts +11 -12
- package/src/extensibility/extensions/types.ts +19 -26
- package/src/extensibility/extensions/wrapper.ts +3 -4
- package/src/extensibility/hooks/index.ts +1 -1
- package/src/extensibility/hooks/loader.ts +8 -9
- package/src/extensibility/hooks/runner.ts +7 -8
- package/src/extensibility/hooks/tool-wrapper.ts +0 -1
- package/src/extensibility/hooks/types.ts +10 -17
- package/src/extensibility/plugins/doctor.ts +3 -3
- package/src/extensibility/plugins/installer.ts +27 -27
- package/src/extensibility/plugins/loader.ts +59 -56
- package/src/extensibility/plugins/manager.ts +211 -171
- package/src/extensibility/plugins/parser.ts +1 -1
- package/src/extensibility/plugins/paths.ts +8 -8
- package/src/extensibility/skills.ts +63 -60
- package/src/extensibility/slash-commands.ts +10 -10
- package/src/index.ts +46 -46
- package/src/internal-urls/agent-protocol.ts +21 -11
- package/src/internal-urls/artifact-protocol.ts +17 -13
- package/src/internal-urls/router.ts +1 -2
- package/src/internal-urls/rule-protocol.ts +3 -4
- package/src/internal-urls/skill-protocol.ts +3 -4
- package/src/ipy/executor.ts +14 -10
- package/src/ipy/gateway-coordinator.ts +79 -90
- package/src/ipy/kernel.ts +32 -30
- package/src/ipy/modules.ts +13 -13
- package/src/lsp/client.ts +21 -10
- package/src/lsp/clients/biome-client.ts +1 -2
- package/src/lsp/clients/index.ts +3 -3
- package/src/lsp/clients/lsp-linter-client.ts +4 -5
- package/src/lsp/config.ts +15 -15
- package/src/lsp/edits.ts +4 -5
- package/src/lsp/index.ts +43 -44
- package/src/lsp/lspmux.ts +8 -8
- package/src/lsp/render.ts +10 -16
- package/src/lsp/utils.ts +3 -3
- package/src/main.ts +55 -34
- package/src/mcp/client.ts +2 -3
- package/src/mcp/config.ts +5 -6
- package/src/mcp/json-rpc.ts +0 -1
- package/src/mcp/loader.ts +3 -4
- package/src/mcp/manager.ts +17 -18
- package/src/mcp/tool-bridge.ts +4 -9
- package/src/mcp/tool-cache.ts +2 -3
- package/src/mcp/transports/http.ts +2 -4
- package/src/mcp/transports/stdio.ts +1 -2
- package/src/migrations.ts +60 -49
- package/src/modes/components/armin.ts +4 -5
- package/src/modes/components/assistant-message.ts +6 -6
- package/src/modes/components/bash-execution.ts +7 -8
- package/src/modes/components/bordered-loader.ts +3 -3
- package/src/modes/components/branch-summary-message.ts +3 -3
- package/src/modes/components/compaction-summary-message.ts +3 -3
- package/src/modes/components/countdown-timer.ts +0 -1
- package/src/modes/components/custom-message.ts +5 -5
- package/src/modes/components/diff.ts +1 -1
- package/src/modes/components/dynamic-border.ts +2 -2
- package/src/modes/components/extensions/extension-dashboard.ts +6 -7
- package/src/modes/components/extensions/extension-list.ts +2 -3
- package/src/modes/components/extensions/inspector-panel.ts +3 -4
- package/src/modes/components/extensions/state-manager.ts +25 -26
- package/src/modes/components/extensions/types.ts +1 -2
- package/src/modes/components/footer.ts +47 -43
- package/src/modes/components/history-search.ts +2 -2
- package/src/modes/components/hook-editor.ts +3 -4
- package/src/modes/components/hook-input.ts +2 -3
- package/src/modes/components/hook-message.ts +5 -5
- package/src/modes/components/hook-selector.ts +2 -3
- package/src/modes/components/keybinding-hints.ts +2 -3
- package/src/modes/components/login-dialog.ts +2 -2
- package/src/modes/components/model-selector.ts +12 -12
- package/src/modes/components/oauth-selector.ts +2 -2
- package/src/modes/components/plugin-settings.ts +20 -20
- package/src/modes/components/python-execution.ts +7 -8
- package/src/modes/components/queue-mode-selector.ts +3 -3
- package/src/modes/components/read-tool-group.ts +2 -2
- package/src/modes/components/session-selector.ts +4 -4
- package/src/modes/components/settings-defs.ts +77 -69
- package/src/modes/components/settings-selector.ts +16 -16
- package/src/modes/components/show-images-selector.ts +2 -2
- package/src/modes/components/status-line/segments.ts +4 -4
- package/src/modes/components/status-line/separators.ts +1 -1
- package/src/modes/components/status-line/types.ts +2 -2
- package/src/modes/components/status-line-segment-editor.ts +7 -8
- package/src/modes/components/status-line.ts +12 -12
- package/src/modes/components/theme-selector.ts +8 -7
- package/src/modes/components/thinking-selector.ts +4 -4
- package/src/modes/components/todo-display.ts +2 -2
- package/src/modes/components/todo-reminder.ts +4 -4
- package/src/modes/components/tool-execution.ts +11 -16
- package/src/modes/components/tree-selector.ts +11 -11
- package/src/modes/components/ttsr-notification.ts +5 -5
- package/src/modes/components/user-message-selector.ts +1 -1
- package/src/modes/components/user-message.ts +1 -1
- package/src/modes/components/visual-truncate.ts +0 -1
- package/src/modes/components/welcome.ts +4 -4
- package/src/modes/controllers/command-controller.ts +46 -47
- package/src/modes/controllers/event-controller.ts +16 -20
- package/src/modes/controllers/extension-ui-controller.ts +40 -46
- package/src/modes/controllers/input-controller.ts +17 -18
- package/src/modes/controllers/selector-controller.ts +103 -91
- package/src/modes/index.ts +3 -3
- package/src/modes/interactive-mode.ts +27 -29
- package/src/modes/print-mode.ts +12 -13
- package/src/modes/rpc/rpc-client.ts +7 -8
- package/src/modes/rpc/rpc-mode.ts +24 -25
- package/src/modes/rpc/rpc-types.ts +3 -4
- package/src/modes/theme/mermaid-cache.ts +2 -2
- package/src/modes/theme/theme.ts +128 -53
- package/src/modes/types.ts +10 -10
- package/src/modes/utils/ui-helpers.ts +17 -17
- package/src/patch/applicator.ts +18 -19
- package/src/patch/diff.ts +1 -2
- package/src/patch/fuzzy.ts +1 -2
- package/src/patch/index.ts +10 -11
- package/src/patch/normalize.ts +4 -4
- package/src/patch/normative.ts +1 -2
- package/src/patch/parser.ts +8 -9
- package/src/patch/shared.ts +12 -13
- package/src/sdk.ts +60 -63
- package/src/session/agent-session.ts +83 -84
- package/src/session/agent-storage.ts +11 -11
- package/src/session/artifacts.ts +8 -9
- package/src/session/auth-storage.ts +25 -29
- package/src/session/compaction/branch-summarization.ts +7 -10
- package/src/session/compaction/compaction.ts +8 -19
- package/src/session/compaction/utils.ts +6 -9
- package/src/session/history-storage.ts +10 -10
- package/src/session/messages.ts +4 -5
- package/src/session/session-manager.ts +76 -65
- package/src/session/session-storage.ts +57 -69
- package/src/session/storage-migration.ts +2 -3
- package/src/session/streaming-output.ts +2 -2
- package/src/ssh/connection-manager.ts +43 -50
- package/src/ssh/ssh-executor.ts +2 -2
- package/src/ssh/sshfs-mount.ts +11 -18
- package/src/system-prompt.ts +27 -34
- package/src/task/agents.ts +45 -30
- package/src/task/commands.ts +6 -7
- package/src/task/discovery.ts +39 -76
- package/src/task/executor.ts +14 -15
- package/src/task/index.ts +33 -36
- package/src/task/output-manager.ts +3 -4
- package/src/task/parallel.ts +0 -1
- package/src/task/render.ts +19 -20
- package/src/task/subprocess-tool-registry.ts +1 -2
- package/src/task/worker-protocol.ts +3 -3
- package/src/task/worker.ts +32 -38
- package/src/task/worktree.ts +19 -19
- package/src/tools/ask.ts +8 -9
- package/src/tools/bash-interceptor.ts +1 -5
- package/src/tools/bash.ts +19 -18
- package/src/tools/calculator.ts +12 -12
- package/src/tools/complete.ts +3 -4
- package/src/tools/context.ts +2 -2
- package/src/tools/fetch.ts +23 -26
- package/src/tools/find.ts +15 -16
- package/src/tools/gemini-image.ts +14 -14
- package/src/tools/grep.ts +27 -27
- package/src/tools/index.ts +78 -56
- package/src/tools/list-limit.ts +1 -1
- package/src/tools/ls.ts +7 -7
- package/src/tools/notebook.ts +5 -5
- package/src/tools/output-meta.ts +3 -4
- package/src/tools/output-utils.ts +1 -1
- package/src/tools/path-utils.ts +5 -5
- package/src/tools/python.ts +36 -37
- package/src/tools/read.ts +23 -23
- package/src/tools/render-utils.ts +8 -9
- package/src/tools/renderers.ts +6 -7
- package/src/tools/review.ts +8 -11
- package/src/tools/ssh.ts +31 -30
- package/src/tools/todo-write.ts +13 -13
- package/src/tools/tool-errors.ts +3 -3
- package/src/tools/tool-result.ts +3 -8
- package/src/tools/write.ts +11 -16
- package/src/tui/code-cell.ts +3 -9
- package/src/tui/file-list.ts +3 -4
- package/src/tui/output-block.ts +1 -2
- package/src/tui/status-line.ts +2 -3
- package/src/tui/tree-list.ts +2 -3
- package/src/tui/types.ts +1 -2
- package/src/tui/utils.ts +2 -3
- package/src/utils/changelog.ts +9 -10
- package/src/utils/clipboard.ts +11 -11
- package/src/utils/file-mentions.ts +4 -10
- package/src/utils/frontmatter.ts +6 -3
- package/src/utils/fuzzy.ts +2 -2
- package/src/utils/image-convert.ts +1 -1
- package/src/utils/image-resize.ts +1 -1
- package/src/utils/mime.ts +2 -2
- package/src/utils/shell-snapshot.ts +11 -13
- package/src/utils/shell.ts +4 -5
- package/src/utils/title-generator.ts +8 -9
- package/src/utils/tools-manager.ts +23 -23
- package/src/vendor/photon/index.js +1099 -1059
- package/src/vendor/photon/photon_rs_bg.wasm +0 -0
- package/src/web/scrapers/artifacthub.ts +1 -1
- package/src/web/scrapers/arxiv.ts +2 -2
- package/src/web/scrapers/bluesky.ts +2 -2
- package/src/web/scrapers/cheatsh.ts +1 -1
- package/src/web/scrapers/chocolatey.ts +2 -2
- package/src/web/scrapers/choosealicense.ts +5 -5
- package/src/web/scrapers/cisa-kev.ts +1 -1
- package/src/web/scrapers/crossref.ts +2 -2
- package/src/web/scrapers/devto.ts +3 -3
- package/src/web/scrapers/discogs.ts +3 -4
- package/src/web/scrapers/discourse.ts +1 -1
- package/src/web/scrapers/dockerhub.ts +1 -1
- package/src/web/scrapers/fdroid.ts +2 -2
- package/src/web/scrapers/firefox-addons.ts +3 -3
- package/src/web/scrapers/flathub.ts +1 -1
- package/src/web/scrapers/github.ts +3 -3
- package/src/web/scrapers/gitlab.ts +4 -4
- package/src/web/scrapers/hackernews.ts +2 -2
- package/src/web/scrapers/huggingface.ts +1 -1
- package/src/web/scrapers/iacr.ts +2 -2
- package/src/web/scrapers/index.ts +0 -1
- package/src/web/scrapers/jetbrains-marketplace.ts +1 -1
- package/src/web/scrapers/lemmy.ts +2 -2
- package/src/web/scrapers/maven.ts +2 -2
- package/src/web/scrapers/mdn.ts +2 -4
- package/src/web/scrapers/metacpan.ts +2 -2
- package/src/web/scrapers/musicbrainz.ts +1 -2
- package/src/web/scrapers/npm.ts +1 -1
- package/src/web/scrapers/nuget.ts +2 -2
- package/src/web/scrapers/nvd.ts +3 -3
- package/src/web/scrapers/ollama.ts +7 -9
- package/src/web/scrapers/opencorporates.ts +2 -2
- package/src/web/scrapers/openlibrary.ts +6 -6
- package/src/web/scrapers/orcid.ts +0 -1
- package/src/web/scrapers/osv.ts +2 -2
- package/src/web/scrapers/packagist.ts +1 -1
- package/src/web/scrapers/pubmed.ts +1 -2
- package/src/web/scrapers/rawg.ts +2 -2
- package/src/web/scrapers/readthedocs.ts +1 -2
- package/src/web/scrapers/repology.ts +2 -2
- package/src/web/scrapers/rfc.ts +1 -1
- package/src/web/scrapers/searchcode.ts +2 -2
- package/src/web/scrapers/semantic-scholar.ts +1 -1
- package/src/web/scrapers/snapcraft.ts +2 -2
- package/src/web/scrapers/sourcegraph.ts +1 -1
- package/src/web/scrapers/spdx.ts +3 -3
- package/src/web/scrapers/spotify.ts +0 -1
- package/src/web/scrapers/twitter.ts +1 -1
- package/src/web/scrapers/types.ts +1 -2
- package/src/web/scrapers/utils.ts +5 -5
- package/src/web/scrapers/wikidata.ts +3 -3
- package/src/web/scrapers/youtube.ts +9 -14
- package/src/web/search/auth.ts +4 -9
- package/src/web/search/index.ts +11 -21
- package/src/web/search/providers/anthropic.ts +3 -9
- package/src/web/search/providers/exa.ts +6 -10
- package/src/web/search/providers/perplexity.ts +5 -5
- package/src/web/search/render.ts +16 -18
- package/scripts/generate-wasm-b64.ts +0 -24
- package/src/commit/map-reduce/.map-phase.ts.kate-swp +0 -0
- package/src/task/.executor.ts.kate-swp +0 -0
- package/src/vendor/photon/photon_rs_bg.wasm.b64.js +0 -1
|
@@ -10,12 +10,11 @@
|
|
|
10
10
|
* - Events: AgentSessionEvent objects streamed as they occur
|
|
11
11
|
* - Extension UI: Extension UI requests are emitted, client responds with extension_ui_response
|
|
12
12
|
*/
|
|
13
|
-
|
|
14
|
-
import type { ExtensionUIContext, ExtensionUIDialogOptions } from "@oh-my-pi/pi-coding-agent/extensibility/extensions";
|
|
15
|
-
import { type Theme, theme } from "@oh-my-pi/pi-coding-agent/modes/theme/theme";
|
|
16
|
-
import type { AgentSession } from "@oh-my-pi/pi-coding-agent/session/agent-session";
|
|
17
13
|
import { readLines } from "@oh-my-pi/pi-utils";
|
|
18
14
|
import { nanoid } from "nanoid";
|
|
15
|
+
import type { ExtensionUIContext, ExtensionUIDialogOptions } from "../../extensibility/extensions";
|
|
16
|
+
import { type Theme, theme } from "../../modes/theme/theme";
|
|
17
|
+
import type { AgentSession } from "../../session/agent-session";
|
|
19
18
|
import type {
|
|
20
19
|
RpcCommand,
|
|
21
20
|
RpcExtensionUIRequest,
|
|
@@ -125,7 +124,7 @@ export async function runRpcMode(session: AgentSession): Promise<never> {
|
|
|
125
124
|
dialogOptions,
|
|
126
125
|
undefined,
|
|
127
126
|
{ method: "select", title, options, timeout: dialogOptions?.timeout },
|
|
128
|
-
|
|
127
|
+
response =>
|
|
129
128
|
"cancelled" in response && response.cancelled
|
|
130
129
|
? undefined
|
|
131
130
|
: "value" in response
|
|
@@ -139,7 +138,7 @@ export async function runRpcMode(session: AgentSession): Promise<never> {
|
|
|
139
138
|
dialogOptions,
|
|
140
139
|
false,
|
|
141
140
|
{ method: "confirm", title, message, timeout: dialogOptions?.timeout },
|
|
142
|
-
|
|
141
|
+
response =>
|
|
143
142
|
"cancelled" in response && response.cancelled
|
|
144
143
|
? false
|
|
145
144
|
: "confirmed" in response
|
|
@@ -157,7 +156,7 @@ export async function runRpcMode(session: AgentSession): Promise<never> {
|
|
|
157
156
|
dialogOptions,
|
|
158
157
|
undefined,
|
|
159
158
|
{ method: "input", title, placeholder, timeout: dialogOptions?.timeout },
|
|
160
|
-
|
|
159
|
+
response =>
|
|
161
160
|
"cancelled" in response && response.cancelled
|
|
162
161
|
? undefined
|
|
163
162
|
: "value" in response
|
|
@@ -271,17 +270,17 @@ export async function runRpcMode(session: AgentSession): Promise<never> {
|
|
|
271
270
|
return theme;
|
|
272
271
|
}
|
|
273
272
|
|
|
274
|
-
getAllThemes(): { name: string; path: string | undefined }[] {
|
|
275
|
-
return [];
|
|
273
|
+
getAllThemes(): Promise<{ name: string; path: string | undefined }[]> {
|
|
274
|
+
return Promise.resolve([]);
|
|
276
275
|
}
|
|
277
276
|
|
|
278
|
-
getTheme(_name: string): Theme | undefined {
|
|
279
|
-
return undefined;
|
|
277
|
+
getTheme(_name: string): Promise<Theme | undefined> {
|
|
278
|
+
return Promise.resolve(undefined);
|
|
280
279
|
}
|
|
281
280
|
|
|
282
|
-
setTheme(_theme: string | Theme): { success: boolean; error?: string } {
|
|
281
|
+
setTheme(_theme: string | Theme): Promise<{ success: boolean; error?: string }> {
|
|
283
282
|
// Theme switching not supported in RPC mode
|
|
284
|
-
return { success: false, error: "Theme switching not supported in RPC mode" };
|
|
283
|
+
return Promise.resolve({ success: false, error: "Theme switching not supported in RPC mode" });
|
|
285
284
|
}
|
|
286
285
|
|
|
287
286
|
setEditorComponent(): void {
|
|
@@ -296,12 +295,12 @@ export async function runRpcMode(session: AgentSession): Promise<never> {
|
|
|
296
295
|
// ExtensionActions
|
|
297
296
|
{
|
|
298
297
|
sendMessage: (message, options) => {
|
|
299
|
-
session.sendCustomMessage(message, options).catch(
|
|
298
|
+
session.sendCustomMessage(message, options).catch(e => {
|
|
300
299
|
output(error(undefined, "extension_send", e.message));
|
|
301
300
|
});
|
|
302
301
|
},
|
|
303
302
|
sendUserMessage: (content, options) => {
|
|
304
|
-
session.sendUserMessage(content, options).catch(
|
|
303
|
+
session.sendUserMessage(content, options).catch(e => {
|
|
305
304
|
output(error(undefined, "extension_send_user", e.message));
|
|
306
305
|
});
|
|
307
306
|
},
|
|
@@ -314,14 +313,14 @@ export async function runRpcMode(session: AgentSession): Promise<never> {
|
|
|
314
313
|
getActiveTools: () => session.getActiveToolNames(),
|
|
315
314
|
getAllTools: () => session.getAllToolNames(),
|
|
316
315
|
setActiveTools: (toolNames: string[]) => session.setActiveToolsByName(toolNames),
|
|
317
|
-
setModel: async
|
|
316
|
+
setModel: async model => {
|
|
318
317
|
const key = await session.modelRegistry.getApiKey(model);
|
|
319
318
|
if (!key) return false;
|
|
320
319
|
await session.setModel(model);
|
|
321
320
|
return true;
|
|
322
321
|
},
|
|
323
322
|
getThinkingLevel: () => session.thinkingLevel,
|
|
324
|
-
setThinkingLevel:
|
|
323
|
+
setThinkingLevel: level => session.setThinkingLevel(level),
|
|
325
324
|
},
|
|
326
325
|
// ExtensionContextActions
|
|
327
326
|
{
|
|
@@ -333,7 +332,7 @@ export async function runRpcMode(session: AgentSession): Promise<never> {
|
|
|
333
332
|
shutdownState.requested = true;
|
|
334
333
|
},
|
|
335
334
|
getContextUsage: () => session.getContextUsage(),
|
|
336
|
-
compact: async
|
|
335
|
+
compact: async instructionsOrOptions => {
|
|
337
336
|
const instructions = typeof instructionsOrOptions === "string" ? instructionsOrOptions : undefined;
|
|
338
337
|
const options =
|
|
339
338
|
instructionsOrOptions && typeof instructionsOrOptions === "object"
|
|
@@ -346,7 +345,7 @@ export async function runRpcMode(session: AgentSession): Promise<never> {
|
|
|
346
345
|
{
|
|
347
346
|
getContextUsage: () => session.getContextUsage(),
|
|
348
347
|
waitForIdle: () => session.agent.waitForIdle(),
|
|
349
|
-
newSession: async
|
|
348
|
+
newSession: async options => {
|
|
350
349
|
const success = await session.newSession({ parentSession: options?.parentSession });
|
|
351
350
|
// Note: setup callback runs but no UI feedback in RPC mode
|
|
352
351
|
if (success && options?.setup) {
|
|
@@ -354,7 +353,7 @@ export async function runRpcMode(session: AgentSession): Promise<never> {
|
|
|
354
353
|
}
|
|
355
354
|
return { cancelled: !success };
|
|
356
355
|
},
|
|
357
|
-
branch: async
|
|
356
|
+
branch: async entryId => {
|
|
358
357
|
const result = await session.branch(entryId);
|
|
359
358
|
return { cancelled: result.cancelled };
|
|
360
359
|
},
|
|
@@ -362,7 +361,7 @@ export async function runRpcMode(session: AgentSession): Promise<never> {
|
|
|
362
361
|
const result = await session.navigateTree(targetId, { summarize: options?.summarize });
|
|
363
362
|
return { cancelled: result.cancelled };
|
|
364
363
|
},
|
|
365
|
-
compact: async
|
|
364
|
+
compact: async instructionsOrOptions => {
|
|
366
365
|
const instructions = typeof instructionsOrOptions === "string" ? instructionsOrOptions : undefined;
|
|
367
366
|
const options =
|
|
368
367
|
instructionsOrOptions && typeof instructionsOrOptions === "object"
|
|
@@ -373,7 +372,7 @@ export async function runRpcMode(session: AgentSession): Promise<never> {
|
|
|
373
372
|
},
|
|
374
373
|
new RpcExtensionUIContext(pendingExtensionRequests, output),
|
|
375
374
|
);
|
|
376
|
-
extensionRunner.onError(
|
|
375
|
+
extensionRunner.onError(err => {
|
|
377
376
|
output({ type: "extension_error", extensionPath: err.extensionPath, event: err.event, error: err.error });
|
|
378
377
|
});
|
|
379
378
|
// Emit session_start event
|
|
@@ -383,7 +382,7 @@ export async function runRpcMode(session: AgentSession): Promise<never> {
|
|
|
383
382
|
}
|
|
384
383
|
|
|
385
384
|
// Output all agent events as JSON
|
|
386
|
-
session.subscribe(
|
|
385
|
+
session.subscribe(event => {
|
|
387
386
|
output(event);
|
|
388
387
|
});
|
|
389
388
|
|
|
@@ -405,7 +404,7 @@ export async function runRpcMode(session: AgentSession): Promise<never> {
|
|
|
405
404
|
images: command.images,
|
|
406
405
|
streamingBehavior: command.streamingBehavior,
|
|
407
406
|
})
|
|
408
|
-
.catch(
|
|
407
|
+
.catch(e => output(error(id, "prompt", e.message)));
|
|
409
408
|
return success(id, "prompt");
|
|
410
409
|
}
|
|
411
410
|
|
|
@@ -458,7 +457,7 @@ export async function runRpcMode(session: AgentSession): Promise<never> {
|
|
|
458
457
|
|
|
459
458
|
case "set_model": {
|
|
460
459
|
const models = session.getAvailableModels();
|
|
461
|
-
const model = models.find(
|
|
460
|
+
const model = models.find(m => m.provider === command.provider && m.id === command.modelId);
|
|
462
461
|
if (!model) {
|
|
463
462
|
return error(id, "set_model", `Model not found: ${command.provider}/${command.modelId}`);
|
|
464
463
|
}
|
|
@@ -4,12 +4,11 @@
|
|
|
4
4
|
* Commands are sent as JSON lines on stdin.
|
|
5
5
|
* Responses and events are emitted as JSON lines on stdout.
|
|
6
6
|
*/
|
|
7
|
-
|
|
8
7
|
import type { AgentMessage, ThinkingLevel } from "@oh-my-pi/pi-agent-core";
|
|
9
8
|
import type { ImageContent, Model } from "@oh-my-pi/pi-ai";
|
|
10
|
-
import type { BashResult } from "
|
|
11
|
-
import type { SessionStats } from "
|
|
12
|
-
import type { CompactionResult } from "
|
|
9
|
+
import type { BashResult } from "../../exec/bash-executor";
|
|
10
|
+
import type { SessionStats } from "../../session/agent-session";
|
|
11
|
+
import type { CompactionResult } from "../../session/compaction";
|
|
13
12
|
|
|
14
13
|
// ============================================================================
|
|
15
14
|
// RPC Commands (stdin)
|
|
@@ -54,7 +54,7 @@ export async function prerenderMermaid(
|
|
|
54
54
|
}
|
|
55
55
|
|
|
56
56
|
promises.push(
|
|
57
|
-
promise.then(
|
|
57
|
+
promise.then(image => {
|
|
58
58
|
pending.delete(hash);
|
|
59
59
|
if (image) {
|
|
60
60
|
cache.set(hash, image);
|
|
@@ -66,7 +66,7 @@ export async function prerenderMermaid(
|
|
|
66
66
|
}
|
|
67
67
|
|
|
68
68
|
const results = await Promise.all(promises);
|
|
69
|
-
const newImages = results.some(
|
|
69
|
+
const newImages = results.some(added => added);
|
|
70
70
|
|
|
71
71
|
if (newImages && onRenderNeeded) {
|
|
72
72
|
onRenderNeeded();
|
package/src/modes/theme/theme.ts
CHANGED
|
@@ -1,12 +1,12 @@
|
|
|
1
1
|
import * as fs from "node:fs";
|
|
2
2
|
import * as path from "node:path";
|
|
3
|
-
import { getCustomThemesDir } from "@oh-my-pi/pi-coding-agent/config";
|
|
4
3
|
import type { EditorTheme, MarkdownTheme, SelectListTheme, SymbolTheme } from "@oh-my-pi/pi-tui";
|
|
5
|
-
import { logger } from "@oh-my-pi/pi-utils";
|
|
4
|
+
import { adjustHsv, isEnoent, logger } from "@oh-my-pi/pi-utils";
|
|
6
5
|
import { type Static, Type } from "@sinclair/typebox";
|
|
7
6
|
import { TypeCompiler } from "@sinclair/typebox/compiler";
|
|
8
7
|
import chalk from "chalk";
|
|
9
8
|
import { highlight, supportsLanguage } from "cli-highlight";
|
|
9
|
+
import { getCustomThemesDir } from "../../config";
|
|
10
10
|
// Embed theme JSON files at build time
|
|
11
11
|
import darkThemeJson from "./dark.json" with { type: "json" };
|
|
12
12
|
import { defaultThemes } from "./defaults";
|
|
@@ -1600,16 +1600,18 @@ function getBuiltinThemes(): Record<string, ThemeJson> {
|
|
|
1600
1600
|
return BUILTIN_THEMES;
|
|
1601
1601
|
}
|
|
1602
1602
|
|
|
1603
|
-
export function getAvailableThemes(): string[] {
|
|
1603
|
+
export async function getAvailableThemes(): Promise<string[]> {
|
|
1604
1604
|
const themes = new Set<string>(Object.keys(getBuiltinThemes()));
|
|
1605
1605
|
const customThemesDir = getCustomThemesDir();
|
|
1606
|
-
|
|
1607
|
-
const files = fs.
|
|
1606
|
+
try {
|
|
1607
|
+
const files = await fs.promises.readdir(customThemesDir);
|
|
1608
1608
|
for (const file of files) {
|
|
1609
1609
|
if (file.endsWith(".json")) {
|
|
1610
1610
|
themes.add(file.slice(0, -5));
|
|
1611
1611
|
}
|
|
1612
1612
|
}
|
|
1613
|
+
} catch {
|
|
1614
|
+
// Directory doesn't exist or isn't readable
|
|
1613
1615
|
}
|
|
1614
1616
|
return Array.from(themes).sort();
|
|
1615
1617
|
}
|
|
@@ -1619,7 +1621,7 @@ export interface ThemeInfo {
|
|
|
1619
1621
|
path: string | undefined;
|
|
1620
1622
|
}
|
|
1621
1623
|
|
|
1622
|
-
export function getAvailableThemesWithPaths(): ThemeInfo[] {
|
|
1624
|
+
export async function getAvailableThemesWithPaths(): Promise<ThemeInfo[]> {
|
|
1623
1625
|
const result: ThemeInfo[] = [];
|
|
1624
1626
|
|
|
1625
1627
|
// Built-in themes (embedded, no file path)
|
|
@@ -1629,31 +1631,37 @@ export function getAvailableThemesWithPaths(): ThemeInfo[] {
|
|
|
1629
1631
|
|
|
1630
1632
|
// Custom themes
|
|
1631
1633
|
const customThemesDir = getCustomThemesDir();
|
|
1632
|
-
|
|
1633
|
-
|
|
1634
|
+
try {
|
|
1635
|
+
const files = await fs.promises.readdir(customThemesDir);
|
|
1636
|
+
for (const file of files) {
|
|
1634
1637
|
if (file.endsWith(".json")) {
|
|
1635
1638
|
const name = file.slice(0, -5);
|
|
1636
|
-
if (!result.some(
|
|
1639
|
+
if (!result.some(themeInfo => themeInfo.name === name)) {
|
|
1637
1640
|
result.push({ name, path: path.join(customThemesDir, file) });
|
|
1638
1641
|
}
|
|
1639
1642
|
}
|
|
1640
1643
|
}
|
|
1644
|
+
} catch {
|
|
1645
|
+
// Directory doesn't exist or isn't readable
|
|
1641
1646
|
}
|
|
1642
1647
|
|
|
1643
1648
|
return result.sort((a, b) => a.name.localeCompare(b.name));
|
|
1644
1649
|
}
|
|
1645
1650
|
|
|
1646
|
-
function loadThemeJson(name: string): ThemeJson {
|
|
1651
|
+
async function loadThemeJson(name: string): Promise<ThemeJson> {
|
|
1647
1652
|
const builtinThemes = getBuiltinThemes();
|
|
1648
1653
|
if (name in builtinThemes) {
|
|
1649
1654
|
return builtinThemes[name];
|
|
1650
1655
|
}
|
|
1651
1656
|
const customThemesDir = getCustomThemesDir();
|
|
1652
1657
|
const themePath = path.join(customThemesDir, `${name}.json`);
|
|
1653
|
-
|
|
1654
|
-
|
|
1658
|
+
let content: string;
|
|
1659
|
+
try {
|
|
1660
|
+
content = await Bun.file(themePath).text();
|
|
1661
|
+
} catch (err) {
|
|
1662
|
+
if (isEnoent(err)) throw new Error(`Theme not found: ${name}`);
|
|
1663
|
+
throw err;
|
|
1655
1664
|
}
|
|
1656
|
-
const content = fs.readFileSync(themePath, "utf-8");
|
|
1657
1665
|
let json: unknown;
|
|
1658
1666
|
try {
|
|
1659
1667
|
json = JSON.parse(content);
|
|
@@ -1678,7 +1686,7 @@ function loadThemeJson(name: string): ThemeJson {
|
|
|
1678
1686
|
let errorMessage = `Invalid theme "${name}":\n`;
|
|
1679
1687
|
if (missingColors.length > 0) {
|
|
1680
1688
|
errorMessage += `\nMissing required color tokens:\n`;
|
|
1681
|
-
errorMessage += missingColors.map(
|
|
1689
|
+
errorMessage += missingColors.map(c => ` - ${c}`).join("\n");
|
|
1682
1690
|
errorMessage += `\n\nPlease add these colors to your theme's "colors" object.`;
|
|
1683
1691
|
errorMessage += `\nSee the built-in themes (dark.json, light.json) for reference values.`;
|
|
1684
1692
|
}
|
|
@@ -1691,9 +1699,27 @@ function loadThemeJson(name: string): ThemeJson {
|
|
|
1691
1699
|
return json as ThemeJson;
|
|
1692
1700
|
}
|
|
1693
1701
|
|
|
1694
|
-
|
|
1702
|
+
interface CreateThemeOptions {
|
|
1703
|
+
mode?: ColorMode;
|
|
1704
|
+
symbolPresetOverride?: SymbolPreset;
|
|
1705
|
+
colorBlindMode?: boolean;
|
|
1706
|
+
}
|
|
1707
|
+
|
|
1708
|
+
/** HSV adjustment to shift green toward blue for colorblind mode (red-green colorblindness) */
|
|
1709
|
+
const COLORBLIND_ADJUSTMENT = { h: 60, s: 0.71 };
|
|
1710
|
+
|
|
1711
|
+
function createTheme(themeJson: ThemeJson, options: CreateThemeOptions = {}): Theme {
|
|
1712
|
+
const { mode, symbolPresetOverride, colorBlindMode } = options;
|
|
1695
1713
|
const colorMode = mode ?? detectColorMode();
|
|
1696
1714
|
const resolvedColors = resolveThemeColors(themeJson.colors, themeJson.vars);
|
|
1715
|
+
|
|
1716
|
+
if (colorBlindMode) {
|
|
1717
|
+
const added = resolvedColors.toolDiffAdded;
|
|
1718
|
+
if (typeof added === "string" && added.startsWith("#")) {
|
|
1719
|
+
resolvedColors.toolDiffAdded = adjustHsv(added, COLORBLIND_ADJUSTMENT);
|
|
1720
|
+
}
|
|
1721
|
+
}
|
|
1722
|
+
|
|
1697
1723
|
const fgColors: Record<ThemeColor, string | number> = {} as Record<ThemeColor, string | number>;
|
|
1698
1724
|
const bgColors: Record<ThemeBg, string | number> = {} as Record<ThemeBg, string | number>;
|
|
1699
1725
|
const bgColorKeys: Set<string> = new Set([
|
|
@@ -1718,14 +1744,14 @@ function createTheme(themeJson: ThemeJson, mode?: ColorMode, symbolPresetOverrid
|
|
|
1718
1744
|
return new Theme(fgColors, bgColors, colorMode, symbolPreset, symbolOverrides);
|
|
1719
1745
|
}
|
|
1720
1746
|
|
|
1721
|
-
function loadTheme(name: string,
|
|
1722
|
-
const themeJson = loadThemeJson(name);
|
|
1723
|
-
return createTheme(themeJson,
|
|
1747
|
+
async function loadTheme(name: string, options: CreateThemeOptions = {}): Promise<Theme> {
|
|
1748
|
+
const themeJson = await loadThemeJson(name);
|
|
1749
|
+
return createTheme(themeJson, options);
|
|
1724
1750
|
}
|
|
1725
1751
|
|
|
1726
|
-
export function getThemeByName(name: string): Theme | undefined {
|
|
1752
|
+
export async function getThemeByName(name: string): Promise<Theme | undefined> {
|
|
1727
1753
|
try {
|
|
1728
|
-
return loadTheme(name);
|
|
1754
|
+
return await loadTheme(name);
|
|
1729
1755
|
} catch {
|
|
1730
1756
|
return undefined;
|
|
1731
1757
|
}
|
|
@@ -1757,32 +1783,49 @@ function getDefaultTheme(): string {
|
|
|
1757
1783
|
export let theme: Theme;
|
|
1758
1784
|
let currentThemeName: string | undefined;
|
|
1759
1785
|
let currentSymbolPresetOverride: SymbolPreset | undefined;
|
|
1786
|
+
let currentColorBlindMode: boolean = false;
|
|
1760
1787
|
let themeWatcher: fs.FSWatcher | undefined;
|
|
1761
1788
|
let onThemeChangeCallback: (() => void) | undefined;
|
|
1762
1789
|
|
|
1763
|
-
|
|
1790
|
+
function getCurrentThemeOptions(): CreateThemeOptions {
|
|
1791
|
+
return {
|
|
1792
|
+
symbolPresetOverride: currentSymbolPresetOverride,
|
|
1793
|
+
colorBlindMode: currentColorBlindMode,
|
|
1794
|
+
};
|
|
1795
|
+
}
|
|
1796
|
+
|
|
1797
|
+
export async function initTheme(
|
|
1798
|
+
themeName?: string,
|
|
1799
|
+
enableWatcher: boolean = false,
|
|
1800
|
+
symbolPreset?: SymbolPreset,
|
|
1801
|
+
colorBlindMode?: boolean,
|
|
1802
|
+
): Promise<void> {
|
|
1764
1803
|
const name = themeName ?? getDefaultTheme();
|
|
1765
1804
|
currentThemeName = name;
|
|
1766
1805
|
currentSymbolPresetOverride = symbolPreset;
|
|
1806
|
+
currentColorBlindMode = colorBlindMode ?? false;
|
|
1767
1807
|
try {
|
|
1768
|
-
theme = loadTheme(name,
|
|
1808
|
+
theme = await loadTheme(name, getCurrentThemeOptions());
|
|
1769
1809
|
if (enableWatcher) {
|
|
1770
|
-
startThemeWatcher();
|
|
1810
|
+
await startThemeWatcher();
|
|
1771
1811
|
}
|
|
1772
1812
|
} catch (err) {
|
|
1773
1813
|
logger.debug("Theme loading failed, falling back to dark theme", { error: String(err) });
|
|
1774
1814
|
currentThemeName = "dark";
|
|
1775
|
-
theme = loadTheme("dark",
|
|
1815
|
+
theme = await loadTheme("dark", getCurrentThemeOptions());
|
|
1776
1816
|
// Don't start watcher for fallback theme
|
|
1777
1817
|
}
|
|
1778
1818
|
}
|
|
1779
1819
|
|
|
1780
|
-
export function setTheme(
|
|
1820
|
+
export async function setTheme(
|
|
1821
|
+
name: string,
|
|
1822
|
+
enableWatcher: boolean = false,
|
|
1823
|
+
): Promise<{ success: boolean; error?: string }> {
|
|
1781
1824
|
currentThemeName = name;
|
|
1782
1825
|
try {
|
|
1783
|
-
theme = loadTheme(name,
|
|
1826
|
+
theme = await loadTheme(name, getCurrentThemeOptions());
|
|
1784
1827
|
if (enableWatcher) {
|
|
1785
|
-
startThemeWatcher();
|
|
1828
|
+
await startThemeWatcher();
|
|
1786
1829
|
}
|
|
1787
1830
|
if (onThemeChangeCallback) {
|
|
1788
1831
|
onThemeChangeCallback();
|
|
@@ -1791,7 +1834,7 @@ export function setTheme(name: string, enableWatcher: boolean = false): { succes
|
|
|
1791
1834
|
} catch (error) {
|
|
1792
1835
|
// Theme is invalid - fall back to dark theme
|
|
1793
1836
|
currentThemeName = "dark";
|
|
1794
|
-
theme = loadTheme("dark",
|
|
1837
|
+
theme = await loadTheme("dark", getCurrentThemeOptions());
|
|
1795
1838
|
// Don't start watcher for fallback theme
|
|
1796
1839
|
return {
|
|
1797
1840
|
success: false,
|
|
@@ -1812,14 +1855,14 @@ export function setThemeInstance(themeInstance: Theme): void {
|
|
|
1812
1855
|
/**
|
|
1813
1856
|
* Set the symbol preset override, recreating the theme with the new preset.
|
|
1814
1857
|
*/
|
|
1815
|
-
export function setSymbolPreset(preset: SymbolPreset): void {
|
|
1858
|
+
export async function setSymbolPreset(preset: SymbolPreset): Promise<void> {
|
|
1816
1859
|
currentSymbolPresetOverride = preset;
|
|
1817
1860
|
if (currentThemeName) {
|
|
1818
1861
|
try {
|
|
1819
|
-
theme = loadTheme(currentThemeName,
|
|
1862
|
+
theme = await loadTheme(currentThemeName, getCurrentThemeOptions());
|
|
1820
1863
|
} catch {
|
|
1821
1864
|
// Fall back to dark theme with new preset
|
|
1822
|
-
theme = loadTheme("dark",
|
|
1865
|
+
theme = await loadTheme("dark", getCurrentThemeOptions());
|
|
1823
1866
|
}
|
|
1824
1867
|
if (onThemeChangeCallback) {
|
|
1825
1868
|
onThemeChangeCallback();
|
|
@@ -1834,6 +1877,32 @@ export function getSymbolPresetOverride(): SymbolPreset | undefined {
|
|
|
1834
1877
|
return currentSymbolPresetOverride;
|
|
1835
1878
|
}
|
|
1836
1879
|
|
|
1880
|
+
/**
|
|
1881
|
+
* Set color blind mode, recreating the theme with the new setting.
|
|
1882
|
+
* When enabled, uses blue instead of green for diff additions.
|
|
1883
|
+
*/
|
|
1884
|
+
export async function setColorBlindMode(enabled: boolean): Promise<void> {
|
|
1885
|
+
currentColorBlindMode = enabled;
|
|
1886
|
+
if (currentThemeName) {
|
|
1887
|
+
try {
|
|
1888
|
+
theme = await loadTheme(currentThemeName, getCurrentThemeOptions());
|
|
1889
|
+
} catch {
|
|
1890
|
+
// Fall back to dark theme
|
|
1891
|
+
theme = await loadTheme("dark", getCurrentThemeOptions());
|
|
1892
|
+
}
|
|
1893
|
+
if (onThemeChangeCallback) {
|
|
1894
|
+
onThemeChangeCallback();
|
|
1895
|
+
}
|
|
1896
|
+
}
|
|
1897
|
+
}
|
|
1898
|
+
|
|
1899
|
+
/**
|
|
1900
|
+
* Get the current color blind mode setting.
|
|
1901
|
+
*/
|
|
1902
|
+
export function getColorBlindMode(): boolean {
|
|
1903
|
+
return currentColorBlindMode;
|
|
1904
|
+
}
|
|
1905
|
+
|
|
1837
1906
|
export function onThemeChange(callback: () => void): void {
|
|
1838
1907
|
onThemeChangeCallback = callback;
|
|
1839
1908
|
}
|
|
@@ -1852,7 +1921,7 @@ export function isValidSymbolPreset(preset: string): preset is SymbolPreset {
|
|
|
1852
1921
|
return preset === "unicode" || preset === "nerd" || preset === "ascii";
|
|
1853
1922
|
}
|
|
1854
1923
|
|
|
1855
|
-
function startThemeWatcher(): void {
|
|
1924
|
+
async function startThemeWatcher(): Promise<void> {
|
|
1856
1925
|
// Stop existing watcher if any
|
|
1857
1926
|
if (themeWatcher) {
|
|
1858
1927
|
themeWatcher.close();
|
|
@@ -1873,34 +1942,40 @@ function startThemeWatcher(): void {
|
|
|
1873
1942
|
}
|
|
1874
1943
|
|
|
1875
1944
|
try {
|
|
1876
|
-
themeWatcher = fs.watch(themeFile,
|
|
1945
|
+
themeWatcher = fs.watch(themeFile, eventType => {
|
|
1877
1946
|
if (eventType === "change") {
|
|
1878
1947
|
// Debounce rapid changes
|
|
1879
1948
|
setTimeout(() => {
|
|
1880
|
-
|
|
1881
|
-
|
|
1882
|
-
|
|
1883
|
-
|
|
1884
|
-
|
|
1885
|
-
|
|
1886
|
-
}
|
|
1887
|
-
|
|
1888
|
-
|
|
1889
|
-
|
|
1949
|
+
loadTheme(currentThemeName!, getCurrentThemeOptions())
|
|
1950
|
+
.then(loadedTheme => {
|
|
1951
|
+
theme = loadedTheme;
|
|
1952
|
+
if (onThemeChangeCallback) {
|
|
1953
|
+
onThemeChangeCallback();
|
|
1954
|
+
}
|
|
1955
|
+
})
|
|
1956
|
+
.catch(err => {
|
|
1957
|
+
logger.debug("Theme reload error during file change", { error: String(err) });
|
|
1958
|
+
});
|
|
1890
1959
|
}, 100);
|
|
1891
1960
|
} else if (eventType === "rename") {
|
|
1892
1961
|
// File was deleted or renamed - fall back to default theme
|
|
1893
1962
|
setTimeout(() => {
|
|
1894
1963
|
if (!fs.existsSync(themeFile)) {
|
|
1895
1964
|
currentThemeName = "dark";
|
|
1896
|
-
|
|
1965
|
+
loadTheme("dark", getCurrentThemeOptions())
|
|
1966
|
+
.then(loadedTheme => {
|
|
1967
|
+
theme = loadedTheme;
|
|
1968
|
+
if (onThemeChangeCallback) {
|
|
1969
|
+
onThemeChangeCallback();
|
|
1970
|
+
}
|
|
1971
|
+
})
|
|
1972
|
+
.catch(err => {
|
|
1973
|
+
logger.debug("Theme reload error during rename fallback", { error: String(err) });
|
|
1974
|
+
});
|
|
1897
1975
|
if (themeWatcher) {
|
|
1898
1976
|
themeWatcher.close();
|
|
1899
1977
|
themeWatcher = undefined;
|
|
1900
1978
|
}
|
|
1901
|
-
if (onThemeChangeCallback) {
|
|
1902
|
-
onThemeChangeCallback();
|
|
1903
|
-
}
|
|
1904
1979
|
}
|
|
1905
1980
|
}, 100);
|
|
1906
1981
|
}
|
|
@@ -1971,10 +2046,10 @@ function ansi256ToHex(index: number): string {
|
|
|
1971
2046
|
* Get resolved theme colors as CSS-compatible hex strings.
|
|
1972
2047
|
* Used by HTML export to generate CSS custom properties.
|
|
1973
2048
|
*/
|
|
1974
|
-
export function getResolvedThemeColors(themeName?: string): Record<string, string
|
|
2049
|
+
export async function getResolvedThemeColors(themeName?: string): Promise<Record<string, string>> {
|
|
1975
2050
|
const name = themeName ?? getDefaultTheme();
|
|
1976
2051
|
const isLight = name === "light";
|
|
1977
|
-
const themeJson = loadThemeJson(name);
|
|
2052
|
+
const themeJson = await loadThemeJson(name);
|
|
1978
2053
|
const resolved = resolveThemeColors(themeJson.colors, themeJson.vars);
|
|
1979
2054
|
|
|
1980
2055
|
// Default text color for empty values (terminal uses default fg color)
|
|
@@ -2006,14 +2081,14 @@ export function isLightTheme(themeName?: string): boolean {
|
|
|
2006
2081
|
* Get explicit export colors from theme JSON, if specified.
|
|
2007
2082
|
* Returns undefined for each color that isn't explicitly set.
|
|
2008
2083
|
*/
|
|
2009
|
-
export function getThemeExportColors(themeName?: string): {
|
|
2084
|
+
export async function getThemeExportColors(themeName?: string): Promise<{
|
|
2010
2085
|
pageBg?: string;
|
|
2011
2086
|
cardBg?: string;
|
|
2012
2087
|
infoBg?: string;
|
|
2013
|
-
} {
|
|
2088
|
+
}> {
|
|
2014
2089
|
const name = themeName ?? getDefaultTheme();
|
|
2015
2090
|
try {
|
|
2016
|
-
const themeJson = loadThemeJson(name);
|
|
2091
|
+
const themeJson = await loadThemeJson(name);
|
|
2017
2092
|
const exportSection = themeJson.export;
|
|
2018
2093
|
if (!exportSection) return {};
|
|
2019
2094
|
|
|
@@ -2237,7 +2312,7 @@ export function getMarkdownTheme(): MarkdownTheme {
|
|
|
2237
2312
|
try {
|
|
2238
2313
|
return highlight(code, opts).split("\n");
|
|
2239
2314
|
} catch {
|
|
2240
|
-
return code.split("\n").map(
|
|
2315
|
+
return code.split("\n").map(line => theme.fg("mdCodeBlock", line));
|
|
2241
2316
|
}
|
|
2242
2317
|
},
|
|
2243
2318
|
};
|
package/src/modes/types.ts
CHANGED
|
@@ -1,14 +1,14 @@
|
|
|
1
1
|
import type { AgentMessage } from "@oh-my-pi/pi-agent-core";
|
|
2
2
|
import type { AssistantMessage, ImageContent, Message, UsageReport } from "@oh-my-pi/pi-ai";
|
|
3
|
-
import type { KeybindingsManager } from "@oh-my-pi/pi-coding-agent/config/keybindings";
|
|
4
|
-
import type { SettingsManager } from "@oh-my-pi/pi-coding-agent/config/settings-manager";
|
|
5
|
-
import type { ExtensionUIContext } from "@oh-my-pi/pi-coding-agent/extensibility/extensions";
|
|
6
|
-
import type { CompactOptions } from "@oh-my-pi/pi-coding-agent/extensibility/extensions/types";
|
|
7
|
-
import type { MCPManager } from "@oh-my-pi/pi-coding-agent/mcp";
|
|
8
|
-
import type { AgentSession, AgentSessionEvent } from "@oh-my-pi/pi-coding-agent/session/agent-session";
|
|
9
|
-
import type { HistoryStorage } from "@oh-my-pi/pi-coding-agent/session/history-storage";
|
|
10
|
-
import type { SessionContext, SessionManager } from "@oh-my-pi/pi-coding-agent/session/session-manager";
|
|
11
3
|
import type { Component, Container, Loader, Spacer, Text, TUI } from "@oh-my-pi/pi-tui";
|
|
4
|
+
import type { KeybindingsManager } from "../config/keybindings";
|
|
5
|
+
import type { SettingsManager } from "../config/settings-manager";
|
|
6
|
+
import type { ExtensionUIContext } from "../extensibility/extensions";
|
|
7
|
+
import type { CompactOptions } from "../extensibility/extensions/types";
|
|
8
|
+
import type { MCPManager } from "../mcp";
|
|
9
|
+
import type { AgentSession, AgentSessionEvent } from "../session/agent-session";
|
|
10
|
+
import type { HistoryStorage } from "../session/history-storage";
|
|
11
|
+
import type { SessionContext, SessionManager } from "../session/session-manager";
|
|
12
12
|
import type { AssistantMessageComponent } from "./components/assistant-message";
|
|
13
13
|
import type { BashExecutionComponent } from "./components/bash-execution";
|
|
14
14
|
import type { CustomEditor } from "./components/custom-editor";
|
|
@@ -132,9 +132,9 @@ export interface InteractiveModeContext {
|
|
|
132
132
|
handleExportCommand(text: string): Promise<void>;
|
|
133
133
|
handleShareCommand(): Promise<void>;
|
|
134
134
|
handleCopyCommand(): Promise<void>;
|
|
135
|
-
handleSessionCommand(): void
|
|
135
|
+
handleSessionCommand(): Promise<void>;
|
|
136
136
|
handleUsageCommand(reports?: UsageReport[] | null): Promise<void>;
|
|
137
|
-
handleChangelogCommand(): void
|
|
137
|
+
handleChangelogCommand(): Promise<void>;
|
|
138
138
|
handleHotkeysCommand(): void;
|
|
139
139
|
handleDumpCommand(): Promise<void>;
|
|
140
140
|
handleClearCommand(): Promise<void>;
|
|
@@ -1,20 +1,20 @@
|
|
|
1
1
|
import type { AgentMessage } from "@oh-my-pi/pi-agent-core";
|
|
2
2
|
import type { AssistantMessage, Message } from "@oh-my-pi/pi-ai";
|
|
3
|
-
import { AssistantMessageComponent } from "@oh-my-pi/pi-coding-agent/modes/components/assistant-message";
|
|
4
|
-
import { BashExecutionComponent } from "@oh-my-pi/pi-coding-agent/modes/components/bash-execution";
|
|
5
|
-
import { BranchSummaryMessageComponent } from "@oh-my-pi/pi-coding-agent/modes/components/branch-summary-message";
|
|
6
|
-
import { CompactionSummaryMessageComponent } from "@oh-my-pi/pi-coding-agent/modes/components/compaction-summary-message";
|
|
7
|
-
import { CustomMessageComponent } from "@oh-my-pi/pi-coding-agent/modes/components/custom-message";
|
|
8
|
-
import { DynamicBorder } from "@oh-my-pi/pi-coding-agent/modes/components/dynamic-border";
|
|
9
|
-
import { PythonExecutionComponent } from "@oh-my-pi/pi-coding-agent/modes/components/python-execution";
|
|
10
|
-
import { ReadToolGroupComponent } from "@oh-my-pi/pi-coding-agent/modes/components/read-tool-group";
|
|
11
|
-
import { ToolExecutionComponent } from "@oh-my-pi/pi-coding-agent/modes/components/tool-execution";
|
|
12
|
-
import { UserMessageComponent } from "@oh-my-pi/pi-coding-agent/modes/components/user-message";
|
|
13
|
-
import { theme } from "@oh-my-pi/pi-coding-agent/modes/theme/theme";
|
|
14
|
-
import type { CompactionQueuedMessage, InteractiveModeContext } from "@oh-my-pi/pi-coding-agent/modes/types";
|
|
15
|
-
import type { CustomMessage } from "@oh-my-pi/pi-coding-agent/session/messages";
|
|
16
|
-
import type { SessionContext } from "@oh-my-pi/pi-coding-agent/session/session-manager";
|
|
17
3
|
import { Spacer, Text, TruncatedText } from "@oh-my-pi/pi-tui";
|
|
4
|
+
import { AssistantMessageComponent } from "../../modes/components/assistant-message";
|
|
5
|
+
import { BashExecutionComponent } from "../../modes/components/bash-execution";
|
|
6
|
+
import { BranchSummaryMessageComponent } from "../../modes/components/branch-summary-message";
|
|
7
|
+
import { CompactionSummaryMessageComponent } from "../../modes/components/compaction-summary-message";
|
|
8
|
+
import { CustomMessageComponent } from "../../modes/components/custom-message";
|
|
9
|
+
import { DynamicBorder } from "../../modes/components/dynamic-border";
|
|
10
|
+
import { PythonExecutionComponent } from "../../modes/components/python-execution";
|
|
11
|
+
import { ReadToolGroupComponent } from "../../modes/components/read-tool-group";
|
|
12
|
+
import { ToolExecutionComponent } from "../../modes/components/tool-execution";
|
|
13
|
+
import { UserMessageComponent } from "../../modes/components/user-message";
|
|
14
|
+
import { theme } from "../../modes/theme/theme";
|
|
15
|
+
import type { CompactionQueuedMessage, InteractiveModeContext } from "../../modes/types";
|
|
16
|
+
import type { CustomMessage } from "../../session/messages";
|
|
17
|
+
import type { SessionContext } from "../../session/session-manager";
|
|
18
18
|
|
|
19
19
|
type TextBlock = { type: "text"; text: string };
|
|
20
20
|
|
|
@@ -33,7 +33,7 @@ export class UiHelpers {
|
|
|
33
33
|
typeof message.content === "string"
|
|
34
34
|
? [{ type: "text", text: message.content }]
|
|
35
35
|
: message.content.filter((content): content is TextBlock => content.type === "text");
|
|
36
|
-
return textBlocks.map(
|
|
36
|
+
return textBlocks.map(block => block.text).join("");
|
|
37
37
|
}
|
|
38
38
|
|
|
39
39
|
/**
|
|
@@ -306,7 +306,7 @@ export class UiHelpers {
|
|
|
306
306
|
|
|
307
307
|
showNewVersionNotification(newVersion: string): void {
|
|
308
308
|
this.ctx.chatContainer.addChild(new Spacer(1));
|
|
309
|
-
this.ctx.chatContainer.addChild(new DynamicBorder(
|
|
309
|
+
this.ctx.chatContainer.addChild(new DynamicBorder(text => theme.fg("warning", text)));
|
|
310
310
|
this.ctx.chatContainer.addChild(
|
|
311
311
|
new Text(
|
|
312
312
|
theme.bold(theme.fg("warning", "Update Available")) +
|
|
@@ -317,7 +317,7 @@ export class UiHelpers {
|
|
|
317
317
|
0,
|
|
318
318
|
),
|
|
319
319
|
);
|
|
320
|
-
this.ctx.chatContainer.addChild(new DynamicBorder(
|
|
320
|
+
this.ctx.chatContainer.addChild(new DynamicBorder(text => theme.fg("warning", text)));
|
|
321
321
|
this.ctx.ui.requestRender();
|
|
322
322
|
}
|
|
323
323
|
|