@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
package/src/tools/ssh.ts
CHANGED
|
@@ -1,23 +1,23 @@
|
|
|
1
1
|
import type { AgentTool, AgentToolContext, AgentToolResult, AgentToolUpdateCallback } from "@oh-my-pi/pi-agent-core";
|
|
2
|
-
import type { SSHHost } from "@oh-my-pi/pi-coding-agent/capability/ssh";
|
|
3
|
-
import { sshCapability } from "@oh-my-pi/pi-coding-agent/capability/ssh";
|
|
4
|
-
import { renderPromptTemplate } from "@oh-my-pi/pi-coding-agent/config/prompt-templates";
|
|
5
|
-
import { loadCapability } from "@oh-my-pi/pi-coding-agent/discovery";
|
|
6
|
-
import type { RenderResultOptions } from "@oh-my-pi/pi-coding-agent/extensibility/custom-tools/types";
|
|
7
|
-
import type { Theme } from "@oh-my-pi/pi-coding-agent/modes/theme/theme";
|
|
8
|
-
import sshDescriptionBase from "@oh-my-pi/pi-coding-agent/prompts/tools/ssh.md" with { type: "text" };
|
|
9
|
-
import type { SSHHostInfo } from "@oh-my-pi/pi-coding-agent/ssh/connection-manager";
|
|
10
|
-
import { ensureHostInfo, getHostInfoForHost } from "@oh-my-pi/pi-coding-agent/ssh/connection-manager";
|
|
11
|
-
import { executeSSH } from "@oh-my-pi/pi-coding-agent/ssh/ssh-executor";
|
|
12
|
-
import type { OutputMeta } from "@oh-my-pi/pi-coding-agent/tools/output-meta";
|
|
13
|
-
import { ToolError } from "@oh-my-pi/pi-coding-agent/tools/tool-errors";
|
|
14
|
-
import { renderOutputBlock, renderStatusLine } from "@oh-my-pi/pi-coding-agent/tui";
|
|
15
2
|
import type { Component } from "@oh-my-pi/pi-tui";
|
|
16
3
|
import { Text } from "@oh-my-pi/pi-tui";
|
|
17
4
|
import { Type } from "@sinclair/typebox";
|
|
5
|
+
import type { SSHHost } from "../capability/ssh";
|
|
6
|
+
import { sshCapability } from "../capability/ssh";
|
|
7
|
+
import { renderPromptTemplate } from "../config/prompt-templates";
|
|
8
|
+
import { loadCapability } from "../discovery";
|
|
9
|
+
import type { RenderResultOptions } from "../extensibility/custom-tools/types";
|
|
10
|
+
import type { Theme } from "../modes/theme/theme";
|
|
11
|
+
import sshDescriptionBase from "../prompts/tools/ssh.md" with { type: "text" };
|
|
12
|
+
import type { SSHHostInfo } from "../ssh/connection-manager";
|
|
13
|
+
import { ensureHostInfo, getHostInfoForHost } from "../ssh/connection-manager";
|
|
14
|
+
import { executeSSH } from "../ssh/ssh-executor";
|
|
15
|
+
import { renderOutputBlock, renderStatusLine } from "../tui";
|
|
18
16
|
import type { ToolSession } from ".";
|
|
17
|
+
import type { OutputMeta } from "./output-meta";
|
|
19
18
|
import { allocateOutputArtifact, createTailBuffer } from "./output-utils";
|
|
20
19
|
import { formatBytes, wrapBrackets } from "./render-utils";
|
|
20
|
+
import { ToolError } from "./tool-errors";
|
|
21
21
|
import { toolResult } from "./tool-result";
|
|
22
22
|
import { DEFAULT_MAX_BYTES } from "./truncate";
|
|
23
23
|
|
|
@@ -32,8 +32,8 @@ export interface SSHToolDetails {
|
|
|
32
32
|
meta?: OutputMeta;
|
|
33
33
|
}
|
|
34
34
|
|
|
35
|
-
function formatHostEntry(host: SSHHost): string {
|
|
36
|
-
const info = getHostInfoForHost(host);
|
|
35
|
+
async function formatHostEntry(host: SSHHost): Promise<string> {
|
|
36
|
+
const info = await getHostInfoForHost(host);
|
|
37
37
|
|
|
38
38
|
let shell: string;
|
|
39
39
|
if (!info) {
|
|
@@ -58,12 +58,12 @@ function formatHostEntry(host: SSHHost): string {
|
|
|
58
58
|
return `- ${host.name} (${host.host}) | ${shell}`;
|
|
59
59
|
}
|
|
60
60
|
|
|
61
|
-
function formatDescription(hosts: SSHHost[]): string {
|
|
61
|
+
async function formatDescription(hosts: SSHHost[]): Promise<string> {
|
|
62
62
|
const baseDescription = renderPromptTemplate(sshDescriptionBase);
|
|
63
63
|
if (hosts.length === 0) {
|
|
64
64
|
return baseDescription;
|
|
65
65
|
}
|
|
66
|
-
const hostList = hosts.map(formatHostEntry).join("\n");
|
|
66
|
+
const hostList = (await Promise.all(hosts.map(formatHostEntry))).join("\n");
|
|
67
67
|
return `${baseDescription}\n\nAvailable hosts:\n${hostList}`;
|
|
68
68
|
}
|
|
69
69
|
|
|
@@ -135,17 +135,12 @@ export class SshTool implements AgentTool<typeof sshSchema, SSHToolDetails> {
|
|
|
135
135
|
private readonly hostsByName: Map<string, SSHHost>;
|
|
136
136
|
private readonly hostNames: string[];
|
|
137
137
|
|
|
138
|
-
constructor(session: ToolSession, hostNames: string[], hostsByName: Map<string, SSHHost
|
|
138
|
+
constructor(session: ToolSession, hostNames: string[], hostsByName: Map<string, SSHHost>, description: string) {
|
|
139
139
|
this.session = session;
|
|
140
140
|
this.hostNames = hostNames;
|
|
141
141
|
this.hostsByName = hostsByName;
|
|
142
142
|
this.allowedHosts = new Set(hostNames);
|
|
143
|
-
|
|
144
|
-
const descriptionHosts = hostNames
|
|
145
|
-
.map((name) => hostsByName.get(name))
|
|
146
|
-
.filter((host): host is SSHHost => host !== undefined);
|
|
147
|
-
|
|
148
|
-
this.description = formatDescription(descriptionHosts);
|
|
143
|
+
this.description = description;
|
|
149
144
|
}
|
|
150
145
|
|
|
151
146
|
public async execute(
|
|
@@ -182,7 +177,7 @@ export class SshTool implements AgentTool<typeof sshSchema, SSHToolDetails> {
|
|
|
182
177
|
compatEnabled: hostInfo.compatEnabled,
|
|
183
178
|
artifactPath,
|
|
184
179
|
artifactId,
|
|
185
|
-
onChunk:
|
|
180
|
+
onChunk: chunk => {
|
|
186
181
|
tailBuffer.append(chunk);
|
|
187
182
|
if (onUpdate) {
|
|
188
183
|
onUpdate({
|
|
@@ -214,7 +209,13 @@ export async function loadSshTool(session: ToolSession): Promise<SshTool | null>
|
|
|
214
209
|
if (hostNames.length === 0) {
|
|
215
210
|
return null;
|
|
216
211
|
}
|
|
217
|
-
|
|
212
|
+
|
|
213
|
+
const descriptionHosts = hostNames
|
|
214
|
+
.map(name => hostsByName.get(name))
|
|
215
|
+
.filter((host): host is SSHHost => host !== undefined);
|
|
216
|
+
const description = await formatDescription(descriptionHosts);
|
|
217
|
+
|
|
218
|
+
return new SshTool(session, hostNames, hostsByName, description);
|
|
218
219
|
}
|
|
219
220
|
|
|
220
221
|
// =============================================================================
|
|
@@ -263,12 +264,12 @@ export const sshToolRenderer = {
|
|
|
263
264
|
);
|
|
264
265
|
const outputLines: string[] = [];
|
|
265
266
|
|
|
266
|
-
const textContent = result.content?.find(
|
|
267
|
+
const textContent = result.content?.find(c => c.type === "text")?.text ?? "";
|
|
267
268
|
const output = textContent.trimEnd();
|
|
268
269
|
|
|
269
270
|
if (output) {
|
|
270
271
|
if (expanded) {
|
|
271
|
-
outputLines.push(...output.split("\n").map(
|
|
272
|
+
outputLines.push(...output.split("\n").map(line => uiTheme.fg("toolOutput", line)));
|
|
272
273
|
} else if (renderContext?.visualLines) {
|
|
273
274
|
const { visualLines, skippedCount = 0, totalVisualLines = visualLines.length } = renderContext;
|
|
274
275
|
if (skippedCount > 0) {
|
|
@@ -279,7 +280,7 @@ export const sshToolRenderer = {
|
|
|
279
280
|
),
|
|
280
281
|
);
|
|
281
282
|
}
|
|
282
|
-
const styledVisual = visualLines.map(
|
|
283
|
+
const styledVisual = visualLines.map(line =>
|
|
283
284
|
line.includes("\x1b[") ? line : uiTheme.fg("toolOutput", line),
|
|
284
285
|
);
|
|
285
286
|
outputLines.push(...styledVisual);
|
|
@@ -288,7 +289,7 @@ export const sshToolRenderer = {
|
|
|
288
289
|
const maxLines = 5;
|
|
289
290
|
const displayLines = outputLinesRaw.slice(0, maxLines);
|
|
290
291
|
const remaining = outputLinesRaw.length - maxLines;
|
|
291
|
-
outputLines.push(...displayLines.map(
|
|
292
|
+
outputLines.push(...displayLines.map(line => uiTheme.fg("toolOutput", line)));
|
|
292
293
|
if (remaining > 0) {
|
|
293
294
|
outputLines.push(
|
|
294
295
|
uiTheme.fg("dim", `${uiTheme.format.ellipsis} (${remaining} more lines) (ctrl+o to expand)`),
|
package/src/tools/todo-write.ts
CHANGED
|
@@ -2,17 +2,17 @@ import { randomUUID } from "node:crypto";
|
|
|
2
2
|
import path from "node:path";
|
|
3
3
|
import type { AgentTool, AgentToolContext, AgentToolResult, AgentToolUpdateCallback } from "@oh-my-pi/pi-agent-core";
|
|
4
4
|
import { StringEnum } from "@oh-my-pi/pi-ai";
|
|
5
|
-
import { renderPromptTemplate } from "@oh-my-pi/pi-coding-agent/config/prompt-templates";
|
|
6
|
-
import type { RenderResultOptions } from "@oh-my-pi/pi-coding-agent/extensibility/custom-tools/types";
|
|
7
|
-
import type { Theme } from "@oh-my-pi/pi-coding-agent/modes/theme/theme";
|
|
8
|
-
import todoWriteDescription from "@oh-my-pi/pi-coding-agent/prompts/tools/todo-write.md" with { type: "text" };
|
|
9
|
-
import type { ToolSession } from "@oh-my-pi/pi-coding-agent/sdk";
|
|
10
|
-
import { renderStatusLine, renderTreeList } from "@oh-my-pi/pi-coding-agent/tui";
|
|
11
5
|
import type { Component } from "@oh-my-pi/pi-tui";
|
|
12
6
|
import { Text } from "@oh-my-pi/pi-tui";
|
|
13
7
|
import { logger } from "@oh-my-pi/pi-utils";
|
|
14
8
|
import { Type } from "@sinclair/typebox";
|
|
15
9
|
import chalk from "chalk";
|
|
10
|
+
import { renderPromptTemplate } from "../config/prompt-templates";
|
|
11
|
+
import type { RenderResultOptions } from "../extensibility/custom-tools/types";
|
|
12
|
+
import type { Theme } from "../modes/theme/theme";
|
|
13
|
+
import todoWriteDescription from "../prompts/tools/todo-write.md" with { type: "text" };
|
|
14
|
+
import type { ToolSession } from "../sdk";
|
|
15
|
+
import { renderStatusLine, renderTreeList } from "../tui";
|
|
16
16
|
import { PREVIEW_LIMITS } from "./render-utils";
|
|
17
17
|
|
|
18
18
|
const todoWriteSchema = Type.Object({
|
|
@@ -63,7 +63,7 @@ function normalizeTodoStatus(status?: string): TodoStatus {
|
|
|
63
63
|
}
|
|
64
64
|
|
|
65
65
|
function normalizeTodos(items: Array<{ id?: string; content?: string; status?: string }>): TodoItem[] {
|
|
66
|
-
return items.map(
|
|
66
|
+
return items.map(item => {
|
|
67
67
|
if (!item.content) {
|
|
68
68
|
throw new Error("Todo content is required.");
|
|
69
69
|
}
|
|
@@ -82,7 +82,7 @@ function normalizeTodos(items: Array<{ id?: string; content?: string; status?: s
|
|
|
82
82
|
function validateSequentialTodos(todos: TodoItem[]): { valid: boolean; error?: string } {
|
|
83
83
|
if (todos.length === 0) return { valid: true };
|
|
84
84
|
|
|
85
|
-
const firstIncompleteIndex = todos.findIndex(
|
|
85
|
+
const firstIncompleteIndex = todos.findIndex(todo => todo.status !== "completed");
|
|
86
86
|
if (firstIncompleteIndex >= 0) {
|
|
87
87
|
for (let i = firstIncompleteIndex + 1; i < todos.length; i++) {
|
|
88
88
|
if (todos[i].status === "completed") {
|
|
@@ -128,9 +128,9 @@ async function loadTodoFile(filePath: string): Promise<TodoFile | null> {
|
|
|
128
128
|
|
|
129
129
|
function formatTodoSummary(todos: TodoItem[]): string {
|
|
130
130
|
if (todos.length === 0) return "Todo list cleared.";
|
|
131
|
-
const completed = todos.filter(
|
|
132
|
-
const inProgress = todos.filter(
|
|
133
|
-
const pending = todos.filter(
|
|
131
|
+
const completed = todos.filter(t => t.status === "completed").length;
|
|
132
|
+
const inProgress = todos.filter(t => t.status === "in_progress").length;
|
|
133
|
+
const pending = todos.filter(t => t.status === "pending").length;
|
|
134
134
|
return `Saved ${todos.length} todos (${pending} pending, ${inProgress} in progress, ${completed} completed).`;
|
|
135
135
|
}
|
|
136
136
|
|
|
@@ -237,7 +237,7 @@ export const todoWriteToolRenderer = {
|
|
|
237
237
|
uiTheme,
|
|
238
238
|
);
|
|
239
239
|
if (todos.length === 0) {
|
|
240
|
-
const fallback = result.content?.find(
|
|
240
|
+
const fallback = result.content?.find(c => c.type === "text")?.text ?? "No todos";
|
|
241
241
|
return new Text([header, uiTheme.fg("dim", fallback)].join("\n"), 0, 0);
|
|
242
242
|
}
|
|
243
243
|
const lines = renderTreeList(
|
|
@@ -246,7 +246,7 @@ export const todoWriteToolRenderer = {
|
|
|
246
246
|
expanded,
|
|
247
247
|
maxCollapsed: PREVIEW_LIMITS.COLLAPSED_ITEMS,
|
|
248
248
|
itemType: "todo",
|
|
249
|
-
renderItem:
|
|
249
|
+
renderItem: todo => formatTodoLine(todo, uiTheme, ""),
|
|
250
250
|
},
|
|
251
251
|
uiTheme,
|
|
252
252
|
);
|
package/src/tools/tool-errors.ts
CHANGED
|
@@ -39,7 +39,7 @@ export class MultiError extends ToolError {
|
|
|
39
39
|
readonly errors: ErrorEntry[];
|
|
40
40
|
|
|
41
41
|
constructor(errors: ErrorEntry[]) {
|
|
42
|
-
super(errors.map(
|
|
42
|
+
super(errors.map(e => e.message).join("; "));
|
|
43
43
|
this.name = "MultiError";
|
|
44
44
|
this.errors = errors;
|
|
45
45
|
}
|
|
@@ -49,11 +49,11 @@ export class MultiError extends ToolError {
|
|
|
49
49
|
const e = this.errors[0];
|
|
50
50
|
return e.context ? `${e.context}: ${e.message}` : e.message;
|
|
51
51
|
}
|
|
52
|
-
return this.errors.map(
|
|
52
|
+
return this.errors.map(e => (e.context ? `${e.context}: ${e.message}` : e.message)).join("\n");
|
|
53
53
|
}
|
|
54
54
|
|
|
55
55
|
static from(errors: Array<string | ErrorEntry>): MultiError {
|
|
56
|
-
return new MultiError(errors.map(
|
|
56
|
+
return new MultiError(errors.map(e => (typeof e === "string" ? { message: e } : e)));
|
|
57
57
|
}
|
|
58
58
|
}
|
|
59
59
|
|
package/src/tools/tool-result.ts
CHANGED
|
@@ -1,13 +1,8 @@
|
|
|
1
1
|
import type { AgentToolResult } from "@oh-my-pi/pi-agent-core";
|
|
2
2
|
import type { ImageContent, TextContent } from "@oh-my-pi/pi-ai";
|
|
3
|
-
import type { OutputSummary } from "
|
|
4
|
-
import type {
|
|
5
|
-
|
|
6
|
-
TruncationOptions,
|
|
7
|
-
TruncationSummaryOptions,
|
|
8
|
-
TruncationTextOptions,
|
|
9
|
-
} from "@oh-my-pi/pi-coding-agent/tools/output-meta";
|
|
10
|
-
import { outputMeta } from "@oh-my-pi/pi-coding-agent/tools/output-meta";
|
|
3
|
+
import type { OutputSummary } from "../session/streaming-output";
|
|
4
|
+
import type { OutputMeta, TruncationOptions, TruncationSummaryOptions, TruncationTextOptions } from "./output-meta";
|
|
5
|
+
import { outputMeta } from "./output-meta";
|
|
11
6
|
import type { TruncationResult } from "./truncate";
|
|
12
7
|
|
|
13
8
|
type ToolContent = Array<TextContent | ImageContent>;
|
package/src/tools/write.ts
CHANGED
|
@@ -5,23 +5,18 @@ import type {
|
|
|
5
5
|
AgentToolUpdateCallback,
|
|
6
6
|
ToolCallContext,
|
|
7
7
|
} from "@oh-my-pi/pi-agent-core";
|
|
8
|
-
import { renderPromptTemplate } from "@oh-my-pi/pi-coding-agent/config/prompt-templates";
|
|
9
|
-
import type { RenderResultOptions } from "@oh-my-pi/pi-coding-agent/extensibility/custom-tools/types";
|
|
10
|
-
import {
|
|
11
|
-
createLspWritethrough,
|
|
12
|
-
type FileDiagnosticsResult,
|
|
13
|
-
type WritethroughCallback,
|
|
14
|
-
writethroughNoop,
|
|
15
|
-
} from "@oh-my-pi/pi-coding-agent/lsp";
|
|
16
|
-
import { getLanguageFromPath, type Theme } from "@oh-my-pi/pi-coding-agent/modes/theme/theme";
|
|
17
|
-
import writeDescription from "@oh-my-pi/pi-coding-agent/prompts/tools/write.md" with { type: "text" };
|
|
18
|
-
import type { ToolSession } from "@oh-my-pi/pi-coding-agent/sdk";
|
|
19
|
-
import { type OutputMeta, outputMeta } from "@oh-my-pi/pi-coding-agent/tools/output-meta";
|
|
20
|
-
import { renderCodeCell, renderStatusLine } from "@oh-my-pi/pi-coding-agent/tui";
|
|
21
8
|
import type { Component } from "@oh-my-pi/pi-tui";
|
|
22
9
|
import { Text } from "@oh-my-pi/pi-tui";
|
|
23
10
|
import { untilAborted } from "@oh-my-pi/pi-utils";
|
|
24
11
|
import { Type } from "@sinclair/typebox";
|
|
12
|
+
import { renderPromptTemplate } from "../config/prompt-templates";
|
|
13
|
+
import type { RenderResultOptions } from "../extensibility/custom-tools/types";
|
|
14
|
+
import { createLspWritethrough, type FileDiagnosticsResult, type WritethroughCallback, writethroughNoop } from "../lsp";
|
|
15
|
+
import { getLanguageFromPath, type Theme } from "../modes/theme/theme";
|
|
16
|
+
import writeDescription from "../prompts/tools/write.md" with { type: "text" };
|
|
17
|
+
import type { ToolSession } from "../sdk";
|
|
18
|
+
import { renderCodeCell, renderStatusLine } from "../tui";
|
|
19
|
+
import { type OutputMeta, outputMeta } from "./output-meta";
|
|
25
20
|
import { resolveToCwd } from "./path-utils";
|
|
26
21
|
import { formatDiagnostics, shortenPath } from "./render-utils";
|
|
27
22
|
import type { RenderCallOptions } from "./renderers";
|
|
@@ -49,7 +44,7 @@ function getLspBatchRequest(toolCall: ToolCallContext | undefined): { id: string
|
|
|
49
44
|
if (!hasOtherWrites) {
|
|
50
45
|
return undefined;
|
|
51
46
|
}
|
|
52
|
-
const hasLaterWrites = toolCall.toolCalls.slice(toolCall.index + 1).some(
|
|
47
|
+
const hasLaterWrites = toolCall.toolCalls.slice(toolCall.index + 1).some(call => LSP_BATCH_TOOLS.has(call.name));
|
|
53
48
|
return { id: toolCall.batchId, flush: !hasLaterWrites };
|
|
54
49
|
}
|
|
55
50
|
|
|
@@ -231,12 +226,12 @@ export const writeToolRenderer = {
|
|
|
231
226
|
}
|
|
232
227
|
|
|
233
228
|
if (result.details?.diagnostics) {
|
|
234
|
-
const diagText = formatDiagnostics(result.details.diagnostics, expanded, uiTheme,
|
|
229
|
+
const diagText = formatDiagnostics(result.details.diagnostics, expanded, uiTheme, fp =>
|
|
235
230
|
uiTheme.getLangIcon(getLanguageFromPath(fp)),
|
|
236
231
|
);
|
|
237
232
|
if (diagText.trim()) {
|
|
238
233
|
const diagLines = diagText.split("\n");
|
|
239
|
-
const firstNonEmpty = diagLines.findIndex(
|
|
234
|
+
const firstNonEmpty = diagLines.findIndex(line => line.trim());
|
|
240
235
|
outputLines.push(...(firstNonEmpty >= 0 ? diagLines.slice(firstNonEmpty) : []));
|
|
241
236
|
}
|
|
242
237
|
}
|
package/src/tui/code-cell.ts
CHANGED
|
@@ -1,14 +1,8 @@
|
|
|
1
1
|
/**
|
|
2
2
|
* Render a code cell with optional output section.
|
|
3
3
|
*/
|
|
4
|
-
|
|
5
|
-
import {
|
|
6
|
-
import {
|
|
7
|
-
formatDuration,
|
|
8
|
-
formatExpandHint,
|
|
9
|
-
formatMoreItems,
|
|
10
|
-
replaceTabs,
|
|
11
|
-
} from "@oh-my-pi/pi-coding-agent/tools/render-utils";
|
|
4
|
+
import { highlightCode, type Theme } from "../modes/theme/theme";
|
|
5
|
+
import { formatDuration, formatExpandHint, formatMoreItems, replaceTabs } from "../tools/render-utils";
|
|
12
6
|
import { renderOutputBlock } from "./output-block";
|
|
13
7
|
import type { State } from "./types";
|
|
14
8
|
import { getStateIcon } from "./utils";
|
|
@@ -96,7 +90,7 @@ export function renderCodeCell(options: CodeCellOptions, theme: Theme): string[]
|
|
|
96
90
|
const maxLines = expanded ? rawLines.length : Math.min(rawLines.length, outputMaxLines);
|
|
97
91
|
const displayLines = rawLines
|
|
98
92
|
.slice(0, maxLines)
|
|
99
|
-
.map(
|
|
93
|
+
.map(line => (line.includes("\x1b[") ? line : theme.fg("toolOutput", line)));
|
|
100
94
|
outputLines.push(...displayLines);
|
|
101
95
|
const remaining = rawLines.length - maxLines;
|
|
102
96
|
if (remaining > 0) {
|
package/src/tui/file-list.ts
CHANGED
|
@@ -1,9 +1,8 @@
|
|
|
1
1
|
/**
|
|
2
2
|
* Render file listings with optional icons and metadata.
|
|
3
3
|
*/
|
|
4
|
-
|
|
5
|
-
import
|
|
6
|
-
import { getLanguageFromPath } from "@oh-my-pi/pi-coding-agent/modes/theme/theme";
|
|
4
|
+
import type { Theme } from "../modes/theme/theme";
|
|
5
|
+
import { getLanguageFromPath } from "../modes/theme/theme";
|
|
7
6
|
import { renderTreeList } from "./tree-list";
|
|
8
7
|
|
|
9
8
|
export interface FileEntry {
|
|
@@ -28,7 +27,7 @@ export function renderFileList(options: FileListOptions, theme: Theme): string[]
|
|
|
28
27
|
expanded,
|
|
29
28
|
maxCollapsed,
|
|
30
29
|
itemType: "file",
|
|
31
|
-
renderItem:
|
|
30
|
+
renderItem: entry => {
|
|
32
31
|
const isDirectory = entry.isDirectory ?? entry.path.endsWith("/");
|
|
33
32
|
const displayPath = isDirectory && entry.path.endsWith("/") ? entry.path : entry.path;
|
|
34
33
|
const lang = isDirectory ? undefined : getLanguageFromPath(displayPath);
|
package/src/tui/output-block.ts
CHANGED
|
@@ -1,9 +1,8 @@
|
|
|
1
1
|
/**
|
|
2
2
|
* Bordered output container with optional header and sections.
|
|
3
3
|
*/
|
|
4
|
-
|
|
5
|
-
import type { Theme } from "@oh-my-pi/pi-coding-agent/modes/theme/theme";
|
|
6
4
|
import { visibleWidth } from "@oh-my-pi/pi-tui";
|
|
5
|
+
import type { Theme } from "../modes/theme/theme";
|
|
7
6
|
import type { State } from "./types";
|
|
8
7
|
import { getStateBgColor, padToWidth, truncateToWidth } from "./utils";
|
|
9
8
|
|
package/src/tui/status-line.ts
CHANGED
|
@@ -1,8 +1,7 @@
|
|
|
1
1
|
/**
|
|
2
2
|
* Standardized status header rendering for tool output.
|
|
3
3
|
*/
|
|
4
|
-
|
|
5
|
-
import type { Theme, ThemeColor } from "@oh-my-pi/pi-coding-agent/modes/theme/theme";
|
|
4
|
+
import type { Theme, ThemeColor } from "../modes/theme/theme";
|
|
6
5
|
import type { IconType } from "./types";
|
|
7
6
|
import { getStateIcon } from "./utils";
|
|
8
7
|
|
|
@@ -31,7 +30,7 @@ export function renderStatusLine(options: StatusLineOptions, theme: Theme): stri
|
|
|
31
30
|
line += ` ${theme.fg(color, `${theme.format.bracketLeft}${label}${theme.format.bracketRight}`)}`;
|
|
32
31
|
}
|
|
33
32
|
|
|
34
|
-
const meta = options.meta?.filter(
|
|
33
|
+
const meta = options.meta?.filter(value => value.trim().length > 0) ?? [];
|
|
35
34
|
if (meta.length > 0) {
|
|
36
35
|
line += ` ${theme.fg("dim", meta.join(theme.sep.dot))}`;
|
|
37
36
|
}
|
package/src/tui/tree-list.ts
CHANGED
|
@@ -1,9 +1,8 @@
|
|
|
1
1
|
/**
|
|
2
2
|
* Hierarchical tree list rendering helper.
|
|
3
3
|
*/
|
|
4
|
-
|
|
5
|
-
import
|
|
6
|
-
import { formatMoreItems } from "@oh-my-pi/pi-coding-agent/tools/render-utils";
|
|
4
|
+
import type { Theme } from "../modes/theme/theme";
|
|
5
|
+
import { formatMoreItems } from "../tools/render-utils";
|
|
7
6
|
import type { TreeContext } from "./types";
|
|
8
7
|
import { getTreeBranch, getTreeContinuePrefix } from "./utils";
|
|
9
8
|
|
package/src/tui/types.ts
CHANGED
|
@@ -1,8 +1,7 @@
|
|
|
1
1
|
/**
|
|
2
2
|
* Shared types for TUI rendering components.
|
|
3
3
|
*/
|
|
4
|
-
|
|
5
|
-
import type { Theme } from "@oh-my-pi/pi-coding-agent/modes/theme/theme";
|
|
4
|
+
import type { Theme } from "../modes/theme/theme";
|
|
6
5
|
|
|
7
6
|
export type State = "pending" | "running" | "success" | "error" | "warning";
|
|
8
7
|
export type IconType = "success" | "error" | "running" | "pending" | "warning" | "info";
|
package/src/tui/utils.ts
CHANGED
|
@@ -1,13 +1,12 @@
|
|
|
1
1
|
/**
|
|
2
2
|
* Shared helpers for tool-rendered UI components.
|
|
3
3
|
*/
|
|
4
|
-
|
|
5
|
-
import type { Theme, ThemeBg } from "@oh-my-pi/pi-coding-agent/modes/theme/theme";
|
|
6
4
|
import { truncateToWidth as truncateToWidthBase, visibleWidth } from "@oh-my-pi/pi-tui";
|
|
5
|
+
import type { Theme, ThemeBg } from "../modes/theme/theme";
|
|
7
6
|
import type { IconType, State } from "./types";
|
|
8
7
|
|
|
9
8
|
export function buildTreePrefix(ancestors: boolean[], theme: Theme): string {
|
|
10
|
-
return ancestors.map(
|
|
9
|
+
return ancestors.map(hasNext => (hasNext ? `${theme.tree.vertical} ` : " ")).join("");
|
|
11
10
|
}
|
|
12
11
|
|
|
13
12
|
export function getTreeBranch(isLast: boolean, theme: Theme): string {
|
package/src/utils/changelog.ts
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { isEnoent, logger } from "@oh-my-pi/pi-utils";
|
|
2
2
|
|
|
3
3
|
export interface ChangelogEntry {
|
|
4
4
|
major: number;
|
|
@@ -11,13 +11,9 @@ export interface ChangelogEntry {
|
|
|
11
11
|
* Parse changelog entries from CHANGELOG.md
|
|
12
12
|
* Scans for ## lines and collects content until next ## or EOF
|
|
13
13
|
*/
|
|
14
|
-
export function parseChangelog(changelogPath: string): ChangelogEntry[] {
|
|
15
|
-
if (!existsSync(changelogPath)) {
|
|
16
|
-
return [];
|
|
17
|
-
}
|
|
18
|
-
|
|
14
|
+
export async function parseChangelog(changelogPath: string): Promise<ChangelogEntry[]> {
|
|
19
15
|
try {
|
|
20
|
-
const content =
|
|
16
|
+
const content = await Bun.file(changelogPath).text();
|
|
21
17
|
const lines = content.split("\n");
|
|
22
18
|
const entries: ChangelogEntry[] = [];
|
|
23
19
|
|
|
@@ -65,7 +61,10 @@ export function parseChangelog(changelogPath: string): ChangelogEntry[] {
|
|
|
65
61
|
|
|
66
62
|
return entries;
|
|
67
63
|
} catch (error) {
|
|
68
|
-
|
|
64
|
+
if (isEnoent(error)) {
|
|
65
|
+
return [];
|
|
66
|
+
}
|
|
67
|
+
logger.error(`Warning: Could not parse changelog: ${error}`);
|
|
69
68
|
return [];
|
|
70
69
|
}
|
|
71
70
|
}
|
|
@@ -92,8 +91,8 @@ export function getNewEntries(entries: ChangelogEntry[], lastVersion: string): C
|
|
|
92
91
|
content: "",
|
|
93
92
|
};
|
|
94
93
|
|
|
95
|
-
return entries.filter(
|
|
94
|
+
return entries.filter(entry => compareVersions(entry, last) > 0);
|
|
96
95
|
}
|
|
97
96
|
|
|
98
97
|
// Re-export getChangelogPath from paths.ts for convenience
|
|
99
|
-
export { getChangelogPath } from "
|
|
98
|
+
export { getChangelogPath } from "../config";
|
package/src/utils/clipboard.ts
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
import
|
|
2
|
-
import
|
|
1
|
+
import * as fs from "node:fs/promises";
|
|
2
|
+
import * as os from "node:os";
|
|
3
3
|
import { $ } from "bun";
|
|
4
4
|
import { nanoid } from "nanoid";
|
|
5
5
|
|
|
@@ -16,23 +16,23 @@ function baseMimeType(mimeType: string): string {
|
|
|
16
16
|
|
|
17
17
|
function selectPreferredImageMimeType(mimeTypes: string[]): string | null {
|
|
18
18
|
const normalized = mimeTypes
|
|
19
|
-
.map(
|
|
19
|
+
.map(t => t.trim())
|
|
20
20
|
.filter(Boolean)
|
|
21
|
-
.map(
|
|
21
|
+
.map(t => ({ raw: t, base: baseMimeType(t) }));
|
|
22
22
|
|
|
23
23
|
for (const preferred of PREFERRED_IMAGE_MIME_TYPES) {
|
|
24
|
-
const match = normalized.find(
|
|
24
|
+
const match = normalized.find(t => t.base === preferred);
|
|
25
25
|
if (match) {
|
|
26
26
|
return match.raw;
|
|
27
27
|
}
|
|
28
28
|
}
|
|
29
29
|
|
|
30
|
-
const anyImage = normalized.find(
|
|
30
|
+
const anyImage = normalized.find(t => t.base.startsWith("image/"));
|
|
31
31
|
return anyImage?.raw ?? null;
|
|
32
32
|
}
|
|
33
33
|
|
|
34
34
|
export async function copyToClipboard(text: string): Promise<void> {
|
|
35
|
-
const p = platform();
|
|
35
|
+
const p = os.platform();
|
|
36
36
|
const timeout = 5000;
|
|
37
37
|
|
|
38
38
|
try {
|
|
@@ -83,7 +83,7 @@ export interface ClipboardImage {
|
|
|
83
83
|
* - Windows: uses PowerShell
|
|
84
84
|
*/
|
|
85
85
|
export async function readImageFromClipboard(): Promise<ClipboardImage | null> {
|
|
86
|
-
const p = platform();
|
|
86
|
+
const p = os.platform();
|
|
87
87
|
const timeout = 3000;
|
|
88
88
|
let promise: Promise<ClipboardImage | null>;
|
|
89
89
|
switch (p) {
|
|
@@ -125,7 +125,7 @@ async function readImageWayland(): Promise<ClipboardReadResult> {
|
|
|
125
125
|
|
|
126
126
|
const typeList = types
|
|
127
127
|
.split(/\r?\n/)
|
|
128
|
-
.map(
|
|
128
|
+
.map(t => t.trim())
|
|
129
129
|
.filter(Boolean);
|
|
130
130
|
|
|
131
131
|
const selectedType = selectPreferredImageMimeType(typeList);
|
|
@@ -149,7 +149,7 @@ async function readImageX11(): Promise<ClipboardReadResult> {
|
|
|
149
149
|
|
|
150
150
|
const candidateTypes = targets
|
|
151
151
|
.split(/\r?\n/)
|
|
152
|
-
.map(
|
|
152
|
+
.map(t => t.trim())
|
|
153
153
|
.filter(Boolean);
|
|
154
154
|
|
|
155
155
|
const selectedType = selectPreferredImageMimeType(candidateTypes);
|
|
@@ -207,7 +207,7 @@ async function readImageMacOS(): Promise<ClipboardImage | null> {
|
|
|
207
207
|
const file = Bun.file(tempFile);
|
|
208
208
|
if (await file.exists()) {
|
|
209
209
|
const buffer = await file.bytes();
|
|
210
|
-
await unlink(tempFile).catch(() => {});
|
|
210
|
+
await fs.unlink(tempFile).catch(() => {});
|
|
211
211
|
|
|
212
212
|
if (buffer.length > 0) {
|
|
213
213
|
return {
|
|
@@ -5,18 +5,12 @@
|
|
|
5
5
|
* we automatically inject the file contents as a FileMentionMessage
|
|
6
6
|
* so the agent doesn't need to read them manually.
|
|
7
7
|
*/
|
|
8
|
-
|
|
9
8
|
import path from "node:path";
|
|
10
9
|
import type { AgentMessage } from "@oh-my-pi/pi-agent-core";
|
|
11
|
-
import type { FileMentionMessage } from "
|
|
12
|
-
import { resolveReadPath } from "
|
|
13
|
-
import { formatAge } from "
|
|
14
|
-
import {
|
|
15
|
-
DEFAULT_MAX_BYTES,
|
|
16
|
-
formatSize,
|
|
17
|
-
truncateHead,
|
|
18
|
-
truncateStringToBytesFromStart,
|
|
19
|
-
} from "@oh-my-pi/pi-coding-agent/tools/truncate";
|
|
10
|
+
import type { FileMentionMessage } from "../session/messages";
|
|
11
|
+
import { resolveReadPath } from "../tools/path-utils";
|
|
12
|
+
import { formatAge } from "../tools/render-utils";
|
|
13
|
+
import { DEFAULT_MAX_BYTES, formatSize, truncateHead, truncateStringToBytesFromStart } from "../tools/truncate";
|
|
20
14
|
|
|
21
15
|
/** Regex to match @filepath patterns in text */
|
|
22
16
|
const FILE_MENTION_REGEX = /@([^\s@]+)/g;
|
package/src/utils/frontmatter.ts
CHANGED
|
@@ -38,7 +38,9 @@ export class FrontmatterError extends Error {
|
|
|
38
38
|
}
|
|
39
39
|
|
|
40
40
|
export interface FrontmatterOptions {
|
|
41
|
-
/** Source of the content */
|
|
41
|
+
/** Source of the content (alias: source) */
|
|
42
|
+
location?: unknown;
|
|
43
|
+
/** Source of the content (alias for location) */
|
|
42
44
|
source?: unknown;
|
|
43
45
|
/** Fallback frontmatter values */
|
|
44
46
|
fallback?: Record<string, unknown>;
|
|
@@ -56,7 +58,8 @@ export function parseFrontmatter(
|
|
|
56
58
|
content: string,
|
|
57
59
|
options?: FrontmatterOptions,
|
|
58
60
|
): { frontmatter: Record<string, unknown>; body: string } {
|
|
59
|
-
const { source, fallback, normalize = true, level = "warn" } = options ?? {};
|
|
61
|
+
const { location, source, fallback, normalize = true, level = "warn" } = options ?? {};
|
|
62
|
+
const loc = location ?? source;
|
|
60
63
|
const frontmatter: Record<string, unknown> = Object.assign({}, fallback);
|
|
61
64
|
|
|
62
65
|
const normalized = normalize ? stripHtmlComments(content.replace(/\r\n/g, "\n").replace(/\r/g, "\n")) : content;
|
|
@@ -77,7 +80,7 @@ export function parseFrontmatter(
|
|
|
77
80
|
const loaded = YAML.parse(metadata.replaceAll("\t", " ")) as Record<string, unknown> | null;
|
|
78
81
|
return { frontmatter: Object.assign(frontmatter, loaded), body: body };
|
|
79
82
|
} catch (error) {
|
|
80
|
-
const err = new FrontmatterError(toError(error),
|
|
83
|
+
const err = new FrontmatterError(toError(error), loc ?? `Inline '${truncate(content, 64)}'`);
|
|
81
84
|
if (level === "warn" || level === "fatal") {
|
|
82
85
|
logger.warn("Failed to parse YAML frontmatter", { err: err.toString() });
|
|
83
86
|
}
|
package/src/utils/fuzzy.ts
CHANGED
|
@@ -71,7 +71,7 @@ export function fuzzyFilter<T>(items: T[], query: string, getText: (item: T) =>
|
|
|
71
71
|
const tokens = query
|
|
72
72
|
.trim()
|
|
73
73
|
.split(/\s+/)
|
|
74
|
-
.filter(
|
|
74
|
+
.filter(t => t.length > 0);
|
|
75
75
|
|
|
76
76
|
if (tokens.length === 0) {
|
|
77
77
|
return items;
|
|
@@ -104,5 +104,5 @@ export function fuzzyFilter<T>(items: T[], query: string, getText: (item: T) =>
|
|
|
104
104
|
// Sort by score (asc, lower is better)
|
|
105
105
|
results.sort((a, b) => a.totalScore - b.totalScore);
|
|
106
106
|
|
|
107
|
-
return results.map(
|
|
107
|
+
return results.map(r => r.item);
|
|
108
108
|
}
|
package/src/utils/mime.ts
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import
|
|
1
|
+
import * as fs from "node:fs/promises";
|
|
2
2
|
import { fileTypeFromBuffer } from "file-type";
|
|
3
3
|
|
|
4
4
|
const IMAGE_MIME_TYPES = new Set(["image/jpeg", "image/png", "image/gif", "image/webp"]);
|
|
@@ -6,7 +6,7 @@ const IMAGE_MIME_TYPES = new Set(["image/jpeg", "image/png", "image/gif", "image
|
|
|
6
6
|
const FILE_TYPE_SNIFF_BYTES = 4100;
|
|
7
7
|
|
|
8
8
|
export async function detectSupportedImageMimeTypeFromFile(filePath: string): Promise<string | null> {
|
|
9
|
-
const fileHandle = await open(filePath, "r");
|
|
9
|
+
const fileHandle = await fs.open(filePath, "r");
|
|
10
10
|
try {
|
|
11
11
|
const buffer = Buffer.alloc(FILE_TYPE_SNIFF_BYTES);
|
|
12
12
|
const { bytesRead } = await fileHandle.read(buffer, 0, FILE_TYPE_SNIFF_BYTES, 0);
|