@oh-my-pi/pi-coding-agent 7.0.0 → 8.0.1
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 +87 -0
- package/README.md +1 -1
- package/docs/hooks.md +2 -2
- package/docs/sdk.md +1 -1
- package/package.json +12 -11
- package/scripts/format-prompts.ts +143 -0
- package/scripts/generate-template.ts +1 -1
- package/src/cli/args.ts +3 -3
- package/src/cli/config-cli.ts +4 -4
- package/src/cli/file-processor.ts +3 -3
- package/src/cli/list-models.ts +2 -2
- package/src/cli/plugin-cli.ts +3 -3
- package/src/cli/session-picker.ts +2 -2
- package/src/cli/setup-cli.ts +2 -2
- package/src/cli/stats-cli.ts +1 -1
- package/src/cli/update-cli.ts +2 -2
- package/src/{core → config}/keybindings.ts +1 -1
- package/src/{core → config}/model-registry.ts +1 -1
- package/src/{core → config}/model-resolver.ts +3 -3
- package/src/{core → config}/prompt-templates.ts +2 -2
- package/src/{core → config}/settings-manager.ts +6 -6
- package/src/{core/cursor/exec-bridge.ts → cursor.ts} +4 -4
- package/src/discovery/agents-md.ts +4 -4
- package/src/discovery/builtin.ts +17 -17
- package/src/discovery/claude.ts +12 -12
- package/src/discovery/cline.ts +6 -6
- package/src/discovery/codex.ts +21 -21
- package/src/discovery/cursor.ts +9 -9
- package/src/discovery/gemini.ts +9 -9
- package/src/discovery/github.ts +6 -6
- package/src/discovery/helpers.ts +4 -4
- package/src/discovery/index.ts +16 -16
- package/src/discovery/mcp-json.ts +4 -4
- package/src/discovery/ssh.ts +4 -4
- package/src/discovery/vscode.ts +4 -4
- package/src/discovery/windsurf.ts +6 -6
- package/src/{core/tools/exa → exa}/company.ts +2 -3
- package/src/{core/tools/exa → exa}/index.ts +2 -2
- package/src/{core/tools/exa → exa}/linkedin.ts +2 -3
- package/src/{core/tools/exa → exa}/mcp-client.ts +2 -2
- package/src/{core/tools/exa → exa}/render.ts +3 -3
- package/src/{core/tools/exa → exa}/researcher.ts +1 -1
- package/src/{core/tools/exa → exa}/search.ts +2 -10
- package/src/{core/tools/exa → exa}/websets.ts +1 -1
- package/src/{core → exec}/bash-executor.ts +22 -6
- package/src/{core → export}/custom-share.ts +1 -1
- package/src/{core/export-html → export/html}/index.ts +3 -3
- package/src/{core → export}/ttsr.ts +2 -2
- package/src/{core → extensibility}/custom-commands/bundled/review/index.ts +4 -4
- package/src/{core → extensibility}/custom-commands/loader.ts +3 -3
- package/src/{core → extensibility}/custom-commands/types.ts +1 -1
- package/src/{core → extensibility}/custom-tools/loader.ts +9 -9
- package/src/{core → extensibility}/custom-tools/types.ts +6 -6
- package/src/{core → extensibility}/custom-tools/wrapper.ts +1 -1
- package/src/{core → extensibility}/extensions/loader.ts +8 -8
- package/src/{core → extensibility}/extensions/runner.ts +3 -3
- package/src/{core → extensibility}/extensions/types.ts +15 -15
- package/src/{core → extensibility}/extensions/wrapper.ts +1 -1
- package/src/{core → extensibility}/hooks/index.ts +1 -1
- package/src/{core → extensibility}/hooks/loader.ts +7 -7
- package/src/{core → extensibility}/hooks/runner.ts +4 -4
- package/src/{core → extensibility}/hooks/types.ts +9 -9
- package/src/{core → extensibility}/plugins/doctor.ts +1 -1
- package/src/{core → extensibility}/plugins/installer.ts +2 -3
- package/src/{core → extensibility}/plugins/paths.ts +1 -1
- package/src/{core → extensibility}/skills.ts +8 -48
- package/src/{core → extensibility}/slash-commands.ts +6 -6
- package/src/index.ts +127 -128
- package/src/internal-urls/agent-protocol.ts +126 -0
- package/src/internal-urls/artifact-protocol.ts +93 -0
- package/src/internal-urls/index.ts +28 -0
- package/src/internal-urls/json-query.ts +126 -0
- package/src/internal-urls/router.ts +69 -0
- package/src/internal-urls/rule-protocol.ts +56 -0
- package/src/internal-urls/skill-protocol.ts +112 -0
- package/src/internal-urls/types.ts +48 -0
- package/src/{core/python-executor.ts → ipy/executor.ts} +51 -11
- package/src/{core/python-gateway-coordinator.ts → ipy/gateway-coordinator.ts} +41 -325
- package/src/{core/python-kernel.ts → ipy/kernel.ts} +38 -10
- package/src/ipy/prelude.ts +3 -0
- package/src/{core/tools/lsp → lsp}/client.ts +7 -6
- package/src/{core/tools/lsp → lsp}/clients/biome-client.ts +1 -1
- package/src/{core/tools/lsp → lsp}/clients/index.ts +1 -1
- package/src/{core/tools/lsp → lsp}/clients/lsp-linter-client.ts +4 -4
- package/src/{core/tools/lsp → lsp}/config.ts +1 -1
- package/src/{core/tools/lsp → lsp}/index.ts +16 -15
- package/src/{core/tools/lsp → lsp}/render.ts +2 -2
- package/src/{core/tools/lsp → lsp}/types.ts +14 -16
- package/src/{core/tools/lsp → lsp}/utils.ts +1 -1
- package/src/main.ts +12 -12
- package/src/{core/mcp → mcp}/config.ts +8 -8
- package/src/{core/mcp → mcp}/loader.ts +5 -6
- package/src/{core/mcp → mcp}/manager.ts +2 -2
- package/src/{core/mcp → mcp}/tool-bridge.ts +35 -6
- package/src/{core/mcp → mcp}/tool-cache.ts +1 -1
- package/src/{core/mcp → mcp}/transports/http.ts +7 -1
- package/src/{core/mcp → mcp}/transports/stdio.ts +1 -1
- package/src/{core/mcp → mcp}/types.ts +1 -1
- package/src/migrations.ts +2 -2
- package/src/modes/{interactive/components → components}/armin.ts +1 -1
- package/src/modes/{interactive/components → components}/assistant-message.ts +1 -1
- package/src/modes/{interactive/components → components}/bash-execution.ts +37 -29
- package/src/modes/{interactive/components → components}/bordered-loader.ts +1 -1
- package/src/modes/{interactive/components → components}/branch-summary-message.ts +2 -2
- package/src/modes/{interactive/components → components}/compaction-summary-message.ts +2 -2
- package/src/modes/{interactive/components → components}/custom-message.ts +3 -3
- package/src/modes/{interactive/components → components}/diff.ts +1 -1
- package/src/modes/{interactive/components → components}/dynamic-border.ts +1 -1
- package/src/modes/{interactive/components → components}/extensions/extension-dashboard.ts +3 -3
- package/src/modes/{interactive/components → components}/extensions/extension-list.ts +2 -2
- package/src/modes/{interactive/components → components}/extensions/inspector-panel.ts +1 -1
- package/src/modes/{interactive/components → components}/extensions/state-manager.ts +11 -17
- package/src/modes/{interactive/components → components}/extensions/types.ts +1 -1
- package/src/modes/{interactive/components → components}/footer.ts +3 -3
- package/src/modes/{interactive/components → components}/history-search.ts +2 -2
- package/src/modes/{interactive/components → components}/hook-editor.ts +1 -1
- package/src/modes/{interactive/components → components}/hook-input.ts +1 -1
- package/src/modes/{interactive/components → components}/hook-message.ts +3 -3
- package/src/modes/{interactive/components → components}/hook-selector.ts +1 -1
- package/src/modes/{interactive/components → components}/keybinding-hints.ts +2 -2
- package/src/modes/{interactive/components → components}/login-dialog.ts +1 -1
- package/src/modes/{interactive/components → components}/model-selector.ts +5 -5
- package/src/modes/{interactive/components → components}/oauth-selector.ts +2 -2
- package/src/modes/{interactive/components → components}/plugin-settings.ts +3 -3
- package/src/modes/{interactive/components → components}/python-execution.ts +35 -24
- package/src/modes/{interactive/components → components}/queue-mode-selector.ts +1 -1
- package/src/modes/{interactive/components → components}/read-tool-group.ts +2 -2
- package/src/modes/{interactive/components → components}/session-selector.ts +3 -3
- package/src/modes/{interactive/components → components}/settings-defs.ts +2 -2
- package/src/modes/{interactive/components → components}/settings-selector.ts +2 -2
- package/src/modes/{interactive/components → components}/show-images-selector.ts +1 -1
- package/src/modes/{interactive/components → components}/status-line/segments.ts +2 -2
- package/src/modes/{interactive/components → components}/status-line/separators.ts +1 -1
- package/src/modes/{interactive/components → components}/status-line/types.ts +2 -2
- package/src/modes/{interactive/components → components}/status-line-segment-editor.ts +2 -2
- package/src/modes/{interactive/components → components}/status-line.ts +3 -3
- package/src/modes/{interactive/components → components}/theme-selector.ts +1 -1
- package/src/modes/{interactive/components → components}/thinking-selector.ts +1 -1
- package/src/modes/{interactive/components → components}/todo-display.ts +3 -4
- package/src/modes/{interactive/components → components}/todo-reminder.ts +2 -2
- package/src/modes/{interactive/components → components}/tool-execution.ts +8 -8
- package/src/modes/{interactive/components → components}/tree-selector.ts +3 -3
- package/src/modes/{interactive/components → components}/ttsr-notification.ts +2 -2
- package/src/modes/{interactive/components → components}/user-message-selector.ts +1 -1
- package/src/modes/{interactive/components → components}/user-message.ts +1 -1
- package/src/modes/{interactive/components → components}/welcome.ts +2 -2
- package/src/modes/{interactive/controllers → controllers}/command-controller.ts +32 -30
- package/src/modes/{interactive/controllers → controllers}/event-controller.ts +9 -9
- package/src/modes/{interactive/controllers → controllers}/extension-ui-controller.ts +8 -8
- package/src/modes/{interactive/controllers → controllers}/input-controller.ts +6 -6
- package/src/modes/{interactive/controllers → controllers}/selector-controller.ts +16 -16
- package/src/modes/index.ts +1 -1
- package/src/modes/{interactive/interactive-mode.ts → interactive-mode.ts} +14 -14
- package/src/modes/print-mode.ts +1 -1
- package/src/modes/rpc/rpc-client.ts +3 -3
- package/src/modes/rpc/rpc-mode.ts +3 -3
- package/src/modes/rpc/rpc-types.ts +3 -3
- package/src/modes/{interactive/theme → theme}/theme.ts +1 -1
- package/src/modes/{interactive/types.ts → types.ts} +8 -9
- package/src/modes/{interactive/utils → utils}/ui-helpers.ts +20 -27
- package/src/{core/tools/patch → patch}/applicator.ts +1 -1
- package/src/{core/tools/patch → patch}/diff.ts +1 -1
- package/src/{core/tools/patch → patch}/index.ts +31 -36
- package/src/{core/tools/patch → patch}/shared.ts +9 -6
- package/src/prompts/agents/explore.md +83 -46
- package/src/prompts/agents/init.md +9 -4
- package/src/prompts/agents/plan.md +8 -7
- package/src/prompts/agents/reviewer.md +36 -18
- package/src/prompts/agents/task.md +4 -4
- package/src/prompts/compaction/branch-summary-preamble.md +0 -1
- package/src/prompts/review-request.md +0 -1
- package/src/prompts/system/custom-system-prompt.md +2 -14
- package/src/prompts/system/file-operations.md +0 -2
- package/src/prompts/system/system-prompt.md +147 -138
- package/src/prompts/system/web-search.md +26 -0
- package/src/prompts/tools/ask.md +31 -24
- package/src/prompts/tools/bash.md +20 -17
- package/src/prompts/tools/calculator.md +9 -5
- package/src/prompts/tools/fetch.md +16 -0
- package/src/prompts/tools/find.md +15 -5
- package/src/prompts/tools/gemini-image.md +21 -6
- package/src/prompts/tools/grep.md +28 -12
- package/src/prompts/tools/lsp.md +35 -14
- package/src/prompts/tools/patch.md +39 -41
- package/src/prompts/tools/python.md +59 -76
- package/src/prompts/tools/read.md +23 -22
- package/src/prompts/tools/replace.md +19 -12
- package/src/prompts/tools/ssh.md +21 -28
- package/src/prompts/tools/task.md +54 -44
- package/src/prompts/tools/todo-write.md +52 -163
- package/src/prompts/tools/web-search.md +16 -9
- package/src/prompts/tools/write.md +13 -2
- package/src/{core/sdk.ts → sdk.ts} +65 -34
- package/src/{core → session}/agent-session.ts +45 -37
- package/src/{core → session}/agent-storage.ts +2 -2
- package/src/session/artifacts.ts +110 -0
- package/src/{core → session}/auth-storage.ts +1 -1
- package/src/{core → session}/compaction/branch-summarization.ts +5 -5
- package/src/{core → session}/compaction/compaction.ts +6 -6
- package/src/{core → session}/compaction/utils.ts +3 -3
- package/src/{core → session}/history-storage.ts +1 -1
- package/src/{core → session}/messages.ts +6 -8
- package/src/{core → session}/session-manager.ts +2 -2
- package/src/{core → session}/storage-migration.ts +2 -2
- package/src/session/streaming-output.ts +177 -0
- package/src/{core/ssh → ssh}/connection-manager.ts +1 -1
- package/src/{core/ssh → ssh}/ssh-executor.ts +19 -4
- package/src/{core/ssh → ssh}/sshfs-mount.ts +1 -1
- package/src/{core/system-prompt.ts → system-prompt.ts} +8 -37
- package/src/{core/tools/task → task}/agents.ts +8 -8
- package/src/{core/tools/task → task}/commands.ts +5 -6
- package/src/{core/tools/task → task}/discovery.ts +3 -3
- package/src/{core/tools/task → task}/executor.ts +34 -44
- package/src/{core/tools/task → task}/index.ts +206 -50
- package/src/{core/tools/task → task}/render.ts +80 -23
- package/src/{core/tools/task → task}/subprocess-tool-registry.ts +1 -1
- package/src/task/template.ts +47 -0
- package/src/{core/tools/task → task}/types.ts +19 -27
- package/src/{core/tools/task → task}/worker-protocol.ts +8 -4
- package/src/{core/tools/task → task}/worker.ts +34 -29
- package/src/task/worktree.ts +166 -0
- package/src/{core/tools → tools}/ask.ts +13 -21
- package/src/{core/tools → tools}/bash-interceptor.ts +1 -1
- package/src/{core/tools → tools}/bash.ts +61 -63
- package/src/{core/tools → tools}/calculator.ts +4 -4
- package/src/{core/tools → tools}/complete.ts +1 -1
- package/src/{core/tools → tools}/context.ts +2 -2
- package/src/{core/tools/web-fetch.ts → tools/fetch.ts} +97 -76
- package/src/{core/tools → tools}/find.ts +80 -104
- package/src/{core/tools → tools}/gemini-image.ts +420 -29
- package/src/{core/tools → tools}/grep.ts +155 -164
- package/src/{core/tools → tools}/index.ts +63 -56
- package/src/tools/list-limit.ts +40 -0
- package/src/{core/tools → tools}/ls.ts +44 -35
- package/src/{core/tools → tools}/notebook.ts +3 -3
- package/src/tools/output-meta.ts +443 -0
- package/src/tools/output-utils.ts +63 -0
- package/src/{core/tools → tools}/python.ts +105 -89
- package/src/tools/read.ts +882 -0
- package/src/{core/tools → tools}/render-utils.ts +1 -1
- package/src/{core/tools → tools}/renderers.ts +8 -10
- package/src/{core/tools → tools}/review.ts +2 -2
- package/src/{core/tools → tools}/ssh.ts +56 -59
- package/src/{core/tools → tools}/todo-write.ts +12 -23
- package/src/tools/tool-errors.ts +95 -0
- package/src/tools/tool-result.ts +92 -0
- package/src/{core/tools → tools}/truncate.ts +2 -2
- package/src/{core/tools → tools}/write.ts +15 -13
- package/src/utils/changelog.ts +1 -1
- package/src/{core → utils}/file-mentions.ts +4 -4
- package/src/utils/image-convert.ts +1 -1
- package/src/utils/image-resize.ts +1 -1
- package/src/utils/shell.ts +1 -1
- package/src/{core → utils}/title-generator.ts +4 -4
- package/src/utils/tools-manager.ts +1 -1
- package/src/{core/tools/web-scrapers → web/scrapers}/choosealicense.ts +1 -1
- package/src/{core/tools/web-scrapers → web/scrapers}/twitter.ts +3 -2
- package/src/{core/tools/web-scrapers → web/scrapers}/types.ts +4 -2
- package/src/{core/tools/web-scrapers → web/scrapers}/utils.ts +1 -1
- package/src/{core/tools/web-scrapers → web/scrapers}/youtube.ts +14 -13
- package/src/{core/tools/web-search → web/search}/auth.ts +4 -4
- package/src/{core/tools/web-search → web/search}/index.ts +22 -71
- package/src/{core/tools/web-search → web/search}/providers/anthropic.ts +7 -10
- package/src/{core/tools/web-search → web/search}/providers/exa.ts +2 -2
- package/src/{core/tools/web-search → web/search}/providers/perplexity.ts +4 -16
- package/src/{core/tools/web-search → web/search}/render.ts +3 -3
- package/tsconfig.json +25 -0
- package/scripts/migrate-sessions.sh +0 -93
- package/src/core/index.ts +0 -56
- package/src/core/python-prelude.ts +0 -3
- package/src/core/ssh-executor.ts +0 -5
- package/src/core/streaming-output.ts +0 -115
- package/src/core/tools/output.ts +0 -519
- package/src/core/tools/read.ts +0 -717
- package/src/core/tools/task/template.ts +0 -37
- package/src/prompts/tools/output.md +0 -47
- package/src/prompts/tools/web-fetch.md +0 -9
- package/src/vendor/photon/photon_rs_bg.wasm.b64.js +0 -1
- /package/src/{core/tools/exa → exa}/types.ts +0 -0
- /package/src/{core → exec}/exec.ts +0 -0
- /package/src/{core/export-html → export/html}/template.css +0 -0
- /package/src/{core/export-html → export/html}/template.generated.ts +0 -0
- /package/src/{core/export-html → export/html}/template.html +0 -0
- /package/src/{core/export-html → export/html}/template.js +0 -0
- /package/src/{core/export-html → export/html}/template.macro.ts +0 -0
- /package/src/{core/export-html → export/html}/vendor/highlight.min.js +0 -0
- /package/src/{core/export-html → export/html}/vendor/marked.min.js +0 -0
- /package/src/{core → extensibility}/custom-commands/index.ts +0 -0
- /package/src/{core → extensibility}/custom-tools/index.ts +0 -0
- /package/src/{core → extensibility}/extensions/index.ts +0 -0
- /package/src/{core → extensibility}/hooks/tool-wrapper.ts +0 -0
- /package/src/{core → extensibility}/plugins/index.ts +0 -0
- /package/src/{core → extensibility}/plugins/loader.ts +0 -0
- /package/src/{core → extensibility}/plugins/manager.ts +0 -0
- /package/src/{core → extensibility}/plugins/parser.ts +0 -0
- /package/src/{core → extensibility}/plugins/types.ts +0 -0
- /package/src/{core/python-modules.ts → ipy/modules.ts} +0 -0
- /package/src/{core/python-prelude.py → ipy/prelude.py} +0 -0
- /package/src/{core/tools/lsp → lsp}/defaults.json +0 -0
- /package/src/{core/tools/lsp → lsp}/edits.ts +0 -0
- /package/src/{core/tools/lsp → lsp}/lspmux.ts +0 -0
- /package/src/{core/tools/lsp → lsp}/rust-analyzer.ts +0 -0
- /package/src/{core/mcp → mcp}/client.ts +0 -0
- /package/src/{core/mcp → mcp}/index.ts +0 -0
- /package/src/{core/mcp → mcp}/json-rpc.ts +0 -0
- /package/src/{core/mcp → mcp}/transports/index.ts +0 -0
- /package/src/modes/{interactive/components → components}/countdown-timer.ts +0 -0
- /package/src/modes/{interactive/components → components}/custom-editor.ts +0 -0
- /package/src/modes/{interactive/components → components}/extensions/index.ts +0 -0
- /package/src/modes/{interactive/components → components}/index.ts +0 -0
- /package/src/modes/{interactive/components → components}/status-line/index.ts +0 -0
- /package/src/modes/{interactive/components → components}/status-line/presets.ts +0 -0
- /package/src/modes/{interactive/components → components}/visual-truncate.ts +0 -0
- /package/src/modes/{interactive/theme → theme}/dark.json +0 -0
- /package/src/modes/{interactive/theme → theme}/defaults/alabaster.json +0 -0
- /package/src/modes/{interactive/theme → theme}/defaults/amethyst.json +0 -0
- /package/src/modes/{interactive/theme → theme}/defaults/anthracite.json +0 -0
- /package/src/modes/{interactive/theme → theme}/defaults/basalt.json +0 -0
- /package/src/modes/{interactive/theme → theme}/defaults/birch.json +0 -0
- /package/src/modes/{interactive/theme → theme}/defaults/dark-abyss.json +0 -0
- /package/src/modes/{interactive/theme → theme}/defaults/dark-arctic.json +0 -0
- /package/src/modes/{interactive/theme → theme}/defaults/dark-aurora.json +0 -0
- /package/src/modes/{interactive/theme → theme}/defaults/dark-catppuccin.json +0 -0
- /package/src/modes/{interactive/theme → theme}/defaults/dark-cavern.json +0 -0
- /package/src/modes/{interactive/theme → theme}/defaults/dark-copper.json +0 -0
- /package/src/modes/{interactive/theme → theme}/defaults/dark-cosmos.json +0 -0
- /package/src/modes/{interactive/theme → theme}/defaults/dark-cyberpunk.json +0 -0
- /package/src/modes/{interactive/theme → theme}/defaults/dark-dracula.json +0 -0
- /package/src/modes/{interactive/theme → theme}/defaults/dark-eclipse.json +0 -0
- /package/src/modes/{interactive/theme → theme}/defaults/dark-ember.json +0 -0
- /package/src/modes/{interactive/theme → theme}/defaults/dark-equinox.json +0 -0
- /package/src/modes/{interactive/theme → theme}/defaults/dark-forest.json +0 -0
- /package/src/modes/{interactive/theme → theme}/defaults/dark-github.json +0 -0
- /package/src/modes/{interactive/theme → theme}/defaults/dark-gruvbox.json +0 -0
- /package/src/modes/{interactive/theme → theme}/defaults/dark-lavender.json +0 -0
- /package/src/modes/{interactive/theme → theme}/defaults/dark-lunar.json +0 -0
- /package/src/modes/{interactive/theme → theme}/defaults/dark-midnight.json +0 -0
- /package/src/modes/{interactive/theme → theme}/defaults/dark-monochrome.json +0 -0
- /package/src/modes/{interactive/theme → theme}/defaults/dark-monokai.json +0 -0
- /package/src/modes/{interactive/theme → theme}/defaults/dark-nebula.json +0 -0
- /package/src/modes/{interactive/theme → theme}/defaults/dark-nord.json +0 -0
- /package/src/modes/{interactive/theme → theme}/defaults/dark-ocean.json +0 -0
- /package/src/modes/{interactive/theme → theme}/defaults/dark-one.json +0 -0
- /package/src/modes/{interactive/theme → theme}/defaults/dark-rainforest.json +0 -0
- /package/src/modes/{interactive/theme → theme}/defaults/dark-reef.json +0 -0
- /package/src/modes/{interactive/theme → theme}/defaults/dark-retro.json +0 -0
- /package/src/modes/{interactive/theme → theme}/defaults/dark-rose-pine.json +0 -0
- /package/src/modes/{interactive/theme → theme}/defaults/dark-sakura.json +0 -0
- /package/src/modes/{interactive/theme → theme}/defaults/dark-slate.json +0 -0
- /package/src/modes/{interactive/theme → theme}/defaults/dark-solarized.json +0 -0
- /package/src/modes/{interactive/theme → theme}/defaults/dark-solstice.json +0 -0
- /package/src/modes/{interactive/theme → theme}/defaults/dark-starfall.json +0 -0
- /package/src/modes/{interactive/theme → theme}/defaults/dark-sunset.json +0 -0
- /package/src/modes/{interactive/theme → theme}/defaults/dark-swamp.json +0 -0
- /package/src/modes/{interactive/theme → theme}/defaults/dark-synthwave.json +0 -0
- /package/src/modes/{interactive/theme → theme}/defaults/dark-taiga.json +0 -0
- /package/src/modes/{interactive/theme → theme}/defaults/dark-terminal.json +0 -0
- /package/src/modes/{interactive/theme → theme}/defaults/dark-tokyo-night.json +0 -0
- /package/src/modes/{interactive/theme → theme}/defaults/dark-tundra.json +0 -0
- /package/src/modes/{interactive/theme → theme}/defaults/dark-twilight.json +0 -0
- /package/src/modes/{interactive/theme → theme}/defaults/dark-volcanic.json +0 -0
- /package/src/modes/{interactive/theme → theme}/defaults/graphite.json +0 -0
- /package/src/modes/{interactive/theme → theme}/defaults/index.ts +0 -0
- /package/src/modes/{interactive/theme → theme}/defaults/light-arctic.json +0 -0
- /package/src/modes/{interactive/theme → theme}/defaults/light-aurora-day.json +0 -0
- /package/src/modes/{interactive/theme → theme}/defaults/light-canyon.json +0 -0
- /package/src/modes/{interactive/theme → theme}/defaults/light-catppuccin.json +0 -0
- /package/src/modes/{interactive/theme → theme}/defaults/light-cirrus.json +0 -0
- /package/src/modes/{interactive/theme → theme}/defaults/light-coral.json +0 -0
- /package/src/modes/{interactive/theme → theme}/defaults/light-cyberpunk.json +0 -0
- /package/src/modes/{interactive/theme → theme}/defaults/light-dawn.json +0 -0
- /package/src/modes/{interactive/theme → theme}/defaults/light-dunes.json +0 -0
- /package/src/modes/{interactive/theme → theme}/defaults/light-eucalyptus.json +0 -0
- /package/src/modes/{interactive/theme → theme}/defaults/light-forest.json +0 -0
- /package/src/modes/{interactive/theme → theme}/defaults/light-frost.json +0 -0
- /package/src/modes/{interactive/theme → theme}/defaults/light-github.json +0 -0
- /package/src/modes/{interactive/theme → theme}/defaults/light-glacier.json +0 -0
- /package/src/modes/{interactive/theme → theme}/defaults/light-gruvbox.json +0 -0
- /package/src/modes/{interactive/theme → theme}/defaults/light-haze.json +0 -0
- /package/src/modes/{interactive/theme → theme}/defaults/light-honeycomb.json +0 -0
- /package/src/modes/{interactive/theme → theme}/defaults/light-lagoon.json +0 -0
- /package/src/modes/{interactive/theme → theme}/defaults/light-lavender.json +0 -0
- /package/src/modes/{interactive/theme → theme}/defaults/light-meadow.json +0 -0
- /package/src/modes/{interactive/theme → theme}/defaults/light-mint.json +0 -0
- /package/src/modes/{interactive/theme → theme}/defaults/light-monochrome.json +0 -0
- /package/src/modes/{interactive/theme → theme}/defaults/light-ocean.json +0 -0
- /package/src/modes/{interactive/theme → theme}/defaults/light-one.json +0 -0
- /package/src/modes/{interactive/theme → theme}/defaults/light-opal.json +0 -0
- /package/src/modes/{interactive/theme → theme}/defaults/light-orchard.json +0 -0
- /package/src/modes/{interactive/theme → theme}/defaults/light-paper.json +0 -0
- /package/src/modes/{interactive/theme → theme}/defaults/light-prism.json +0 -0
- /package/src/modes/{interactive/theme → theme}/defaults/light-retro.json +0 -0
- /package/src/modes/{interactive/theme → theme}/defaults/light-sand.json +0 -0
- /package/src/modes/{interactive/theme → theme}/defaults/light-savanna.json +0 -0
- /package/src/modes/{interactive/theme → theme}/defaults/light-solarized.json +0 -0
- /package/src/modes/{interactive/theme → theme}/defaults/light-soleil.json +0 -0
- /package/src/modes/{interactive/theme → theme}/defaults/light-sunset.json +0 -0
- /package/src/modes/{interactive/theme → theme}/defaults/light-synthwave.json +0 -0
- /package/src/modes/{interactive/theme → theme}/defaults/light-tokyo-night.json +0 -0
- /package/src/modes/{interactive/theme → theme}/defaults/light-wetland.json +0 -0
- /package/src/modes/{interactive/theme → theme}/defaults/light-zenith.json +0 -0
- /package/src/modes/{interactive/theme → theme}/defaults/limestone.json +0 -0
- /package/src/modes/{interactive/theme → theme}/defaults/mahogany.json +0 -0
- /package/src/modes/{interactive/theme → theme}/defaults/marble.json +0 -0
- /package/src/modes/{interactive/theme → theme}/defaults/obsidian.json +0 -0
- /package/src/modes/{interactive/theme → theme}/defaults/onyx.json +0 -0
- /package/src/modes/{interactive/theme → theme}/defaults/pearl.json +0 -0
- /package/src/modes/{interactive/theme → theme}/defaults/porcelain.json +0 -0
- /package/src/modes/{interactive/theme → theme}/defaults/quartz.json +0 -0
- /package/src/modes/{interactive/theme → theme}/defaults/sandstone.json +0 -0
- /package/src/modes/{interactive/theme → theme}/defaults/titanium.json +0 -0
- /package/src/modes/{interactive/theme → theme}/light.json +0 -0
- /package/src/modes/{interactive/theme → theme}/theme-schema.json +0 -0
- /package/src/{core/tools/patch → patch}/fuzzy.ts +0 -0
- /package/src/{core/tools/patch → patch}/normalize.ts +0 -0
- /package/src/{core/tools/patch → patch}/normative.ts +0 -0
- /package/src/{core/tools/patch → patch}/parser.ts +0 -0
- /package/src/{core/tools/patch → patch}/types.ts +0 -0
- /package/src/{core → session}/compaction/index.ts +0 -0
- /package/src/{core → session}/session-storage.ts +0 -0
- /package/src/{core/tools/task → task}/name-generator.ts +0 -0
- /package/src/{core/tools/task → task}/omp-command.ts +0 -0
- /package/src/{core/tools/task → task}/parallel.ts +0 -0
- /package/src/{core/tools → tools}/jtd-to-json-schema.ts +0 -0
- /package/src/{core/tools → tools}/path-utils.ts +0 -0
- /package/src/{core → utils}/event-bus.ts +0 -0
- /package/src/{core → utils}/frontmatter.ts +0 -0
- /package/src/{core → utils}/terminal-notify.ts +0 -0
- /package/src/{core → utils}/timings.ts +0 -0
- /package/src/{core → utils}/utils.ts +0 -0
- /package/src/{core/tools/web-scrapers → web/scrapers}/artifacthub.ts +0 -0
- /package/src/{core/tools/web-scrapers → web/scrapers}/arxiv.ts +0 -0
- /package/src/{core/tools/web-scrapers → web/scrapers}/aur.ts +0 -0
- /package/src/{core/tools/web-scrapers → web/scrapers}/biorxiv.ts +0 -0
- /package/src/{core/tools/web-scrapers → web/scrapers}/bluesky.ts +0 -0
- /package/src/{core/tools/web-scrapers → web/scrapers}/brew.ts +0 -0
- /package/src/{core/tools/web-scrapers → web/scrapers}/cheatsh.ts +0 -0
- /package/src/{core/tools/web-scrapers → web/scrapers}/chocolatey.ts +0 -0
- /package/src/{core/tools/web-scrapers → web/scrapers}/cisa-kev.ts +0 -0
- /package/src/{core/tools/web-scrapers → web/scrapers}/clojars.ts +0 -0
- /package/src/{core/tools/web-scrapers → web/scrapers}/coingecko.ts +0 -0
- /package/src/{core/tools/web-scrapers → web/scrapers}/crates-io.ts +0 -0
- /package/src/{core/tools/web-scrapers → web/scrapers}/crossref.ts +0 -0
- /package/src/{core/tools/web-scrapers → web/scrapers}/devto.ts +0 -0
- /package/src/{core/tools/web-scrapers → web/scrapers}/discogs.ts +0 -0
- /package/src/{core/tools/web-scrapers → web/scrapers}/discourse.ts +0 -0
- /package/src/{core/tools/web-scrapers → web/scrapers}/dockerhub.ts +0 -0
- /package/src/{core/tools/web-scrapers → web/scrapers}/fdroid.ts +0 -0
- /package/src/{core/tools/web-scrapers → web/scrapers}/firefox-addons.ts +0 -0
- /package/src/{core/tools/web-scrapers → web/scrapers}/flathub.ts +0 -0
- /package/src/{core/tools/web-scrapers → web/scrapers}/github-gist.ts +0 -0
- /package/src/{core/tools/web-scrapers → web/scrapers}/github.ts +0 -0
- /package/src/{core/tools/web-scrapers → web/scrapers}/gitlab.ts +0 -0
- /package/src/{core/tools/web-scrapers → web/scrapers}/go-pkg.ts +0 -0
- /package/src/{core/tools/web-scrapers → web/scrapers}/hackage.ts +0 -0
- /package/src/{core/tools/web-scrapers → web/scrapers}/hackernews.ts +0 -0
- /package/src/{core/tools/web-scrapers → web/scrapers}/hex.ts +0 -0
- /package/src/{core/tools/web-scrapers → web/scrapers}/huggingface.ts +0 -0
- /package/src/{core/tools/web-scrapers → web/scrapers}/iacr.ts +0 -0
- /package/src/{core/tools/web-scrapers → web/scrapers}/index.ts +0 -0
- /package/src/{core/tools/web-scrapers → web/scrapers}/jetbrains-marketplace.ts +0 -0
- /package/src/{core/tools/web-scrapers → web/scrapers}/lemmy.ts +0 -0
- /package/src/{core/tools/web-scrapers → web/scrapers}/lobsters.ts +0 -0
- /package/src/{core/tools/web-scrapers → web/scrapers}/mastodon.ts +0 -0
- /package/src/{core/tools/web-scrapers → web/scrapers}/maven.ts +0 -0
- /package/src/{core/tools/web-scrapers → web/scrapers}/mdn.ts +0 -0
- /package/src/{core/tools/web-scrapers → web/scrapers}/metacpan.ts +0 -0
- /package/src/{core/tools/web-scrapers → web/scrapers}/musicbrainz.ts +0 -0
- /package/src/{core/tools/web-scrapers → web/scrapers}/npm.ts +0 -0
- /package/src/{core/tools/web-scrapers → web/scrapers}/nuget.ts +0 -0
- /package/src/{core/tools/web-scrapers → web/scrapers}/nvd.ts +0 -0
- /package/src/{core/tools/web-scrapers → web/scrapers}/ollama.ts +0 -0
- /package/src/{core/tools/web-scrapers → web/scrapers}/open-vsx.ts +0 -0
- /package/src/{core/tools/web-scrapers → web/scrapers}/opencorporates.ts +0 -0
- /package/src/{core/tools/web-scrapers → web/scrapers}/openlibrary.ts +0 -0
- /package/src/{core/tools/web-scrapers → web/scrapers}/orcid.ts +0 -0
- /package/src/{core/tools/web-scrapers → web/scrapers}/osv.ts +0 -0
- /package/src/{core/tools/web-scrapers → web/scrapers}/packagist.ts +0 -0
- /package/src/{core/tools/web-scrapers → web/scrapers}/pub-dev.ts +0 -0
- /package/src/{core/tools/web-scrapers → web/scrapers}/pubmed.ts +0 -0
- /package/src/{core/tools/web-scrapers → web/scrapers}/pypi.ts +0 -0
- /package/src/{core/tools/web-scrapers → web/scrapers}/rawg.ts +0 -0
- /package/src/{core/tools/web-scrapers → web/scrapers}/readthedocs.ts +0 -0
- /package/src/{core/tools/web-scrapers → web/scrapers}/reddit.ts +0 -0
- /package/src/{core/tools/web-scrapers → web/scrapers}/repology.ts +0 -0
- /package/src/{core/tools/web-scrapers → web/scrapers}/rfc.ts +0 -0
- /package/src/{core/tools/web-scrapers → web/scrapers}/rubygems.ts +0 -0
- /package/src/{core/tools/web-scrapers → web/scrapers}/searchcode.ts +0 -0
- /package/src/{core/tools/web-scrapers → web/scrapers}/sec-edgar.ts +0 -0
- /package/src/{core/tools/web-scrapers → web/scrapers}/semantic-scholar.ts +0 -0
- /package/src/{core/tools/web-scrapers → web/scrapers}/snapcraft.ts +0 -0
- /package/src/{core/tools/web-scrapers → web/scrapers}/sourcegraph.ts +0 -0
- /package/src/{core/tools/web-scrapers → web/scrapers}/spdx.ts +0 -0
- /package/src/{core/tools/web-scrapers → web/scrapers}/spotify.ts +0 -0
- /package/src/{core/tools/web-scrapers → web/scrapers}/stackoverflow.ts +0 -0
- /package/src/{core/tools/web-scrapers → web/scrapers}/terraform.ts +0 -0
- /package/src/{core/tools/web-scrapers → web/scrapers}/tldr.ts +0 -0
- /package/src/{core/tools/web-scrapers → web/scrapers}/vimeo.ts +0 -0
- /package/src/{core/tools/web-scrapers → web/scrapers}/vscode-marketplace.ts +0 -0
- /package/src/{core/tools/web-scrapers → web/scrapers}/w3c.ts +0 -0
- /package/src/{core/tools/web-scrapers → web/scrapers}/wikidata.ts +0 -0
- /package/src/{core/tools/web-scrapers → web/scrapers}/wikipedia.ts +0 -0
- /package/src/{core/tools/web-search → web/search}/types.ts +0 -0
|
@@ -3,30 +3,33 @@ import type { AgentTool, AgentToolContext, AgentToolResult, AgentToolUpdateCallb
|
|
|
3
3
|
import type { Component } from "@oh-my-pi/pi-tui";
|
|
4
4
|
import { Text, truncateToWidth } from "@oh-my-pi/pi-tui";
|
|
5
5
|
import { Type } from "@sinclair/typebox";
|
|
6
|
-
import {
|
|
7
|
-
import type
|
|
8
|
-
import
|
|
9
|
-
import {
|
|
10
|
-
import type {
|
|
11
|
-
import
|
|
6
|
+
import { renderPromptTemplate } from "$c/config/prompt-templates";
|
|
7
|
+
import { type BashExecutorOptions, executeBash } from "$c/exec/bash-executor";
|
|
8
|
+
import type { RenderResultOptions } from "$c/extensibility/custom-tools/types";
|
|
9
|
+
import { truncateToVisualLines } from "$c/modes/components/visual-truncate";
|
|
10
|
+
import type { Theme } from "$c/modes/theme/theme";
|
|
11
|
+
import bashDescription from "$c/prompts/tools/bash.md" with { type: "text" };
|
|
12
|
+
import type { OutputMeta } from "$c/tools/output-meta";
|
|
13
|
+
import { ToolError } from "$c/tools/tool-errors";
|
|
14
|
+
|
|
12
15
|
import { checkBashInterception, checkSimpleLsInterception } from "./bash-interceptor";
|
|
13
16
|
import type { ToolSession } from "./index";
|
|
17
|
+
import { allocateOutputArtifact, createTailBuffer } from "./output-utils";
|
|
14
18
|
import { resolveToCwd } from "./path-utils";
|
|
15
19
|
import { ToolUIKit } from "./render-utils";
|
|
16
|
-
import {
|
|
20
|
+
import { toolResult } from "./tool-result";
|
|
21
|
+
import { DEFAULT_MAX_BYTES } from "./truncate";
|
|
17
22
|
|
|
18
23
|
export const BASH_DEFAULT_PREVIEW_LINES = 10;
|
|
19
24
|
|
|
20
25
|
const bashSchema = Type.Object({
|
|
21
|
-
command: Type.String({ description: "
|
|
22
|
-
timeout: Type.Optional(Type.Number({ description: "Timeout in seconds (
|
|
23
|
-
cwd: Type.Optional(Type.String({ description: "Working directory
|
|
26
|
+
command: Type.String({ description: "Command to execute" }),
|
|
27
|
+
timeout: Type.Optional(Type.Number({ description: "Timeout in seconds (default: 300)" })),
|
|
28
|
+
cwd: Type.Optional(Type.String({ description: "Working directory (default: cwd)" })),
|
|
24
29
|
});
|
|
25
30
|
|
|
26
31
|
export interface BashToolDetails {
|
|
27
|
-
|
|
28
|
-
fullOutputPath?: string;
|
|
29
|
-
fullOutput?: string;
|
|
32
|
+
meta?: OutputMeta;
|
|
30
33
|
}
|
|
31
34
|
|
|
32
35
|
export interface BashToolOptions {}
|
|
@@ -51,7 +54,7 @@ export class BashTool implements AgentTool<typeof bashSchema, BashToolDetails> {
|
|
|
51
54
|
|
|
52
55
|
public async execute(
|
|
53
56
|
_toolCallId: string,
|
|
54
|
-
{ command, timeout, cwd }: { command: string; timeout?: number; cwd?: string },
|
|
57
|
+
{ command, timeout: rawTimeout = 300, cwd }: { command: string; timeout?: number; cwd?: string },
|
|
55
58
|
signal?: AbortSignal,
|
|
56
59
|
onUpdate?: AgentToolUpdateCallback<BashToolDetails>,
|
|
57
60
|
ctx?: AgentToolContext,
|
|
@@ -61,12 +64,12 @@ export class BashTool implements AgentTool<typeof bashSchema, BashToolDetails> {
|
|
|
61
64
|
const rules = this.session.settings?.getBashInterceptorRules?.();
|
|
62
65
|
const interception = checkBashInterception(command, ctx?.toolNames ?? [], rules);
|
|
63
66
|
if (interception.block) {
|
|
64
|
-
throw new
|
|
67
|
+
throw new ToolError(interception.message ?? "Command blocked");
|
|
65
68
|
}
|
|
66
69
|
if (this.session.settings?.getBashInterceptorSimpleLsEnabled?.() !== false) {
|
|
67
70
|
const lsInterception = checkSimpleLsInterception(command, ctx?.toolNames ?? []);
|
|
68
71
|
if (lsInterception.block) {
|
|
69
|
-
throw new
|
|
72
|
+
throw new ToolError(lsInterception.message ?? "Command blocked");
|
|
70
73
|
}
|
|
71
74
|
}
|
|
72
75
|
}
|
|
@@ -76,26 +79,39 @@ export class BashTool implements AgentTool<typeof bashSchema, BashToolDetails> {
|
|
|
76
79
|
try {
|
|
77
80
|
cwdStat = await Bun.file(commandCwd).stat();
|
|
78
81
|
} catch {
|
|
79
|
-
throw new
|
|
82
|
+
throw new ToolError(`Working directory does not exist: ${commandCwd}`);
|
|
80
83
|
}
|
|
81
84
|
if (!cwdStat.isDirectory()) {
|
|
82
|
-
throw new
|
|
85
|
+
throw new ToolError(`Working directory is not a directory: ${commandCwd}`);
|
|
83
86
|
}
|
|
84
87
|
|
|
85
|
-
//
|
|
86
|
-
let
|
|
88
|
+
// Auto-convert milliseconds to seconds if value > 1000 (16+ min is unreasonable)
|
|
89
|
+
let timeoutSec = rawTimeout > 1000 ? rawTimeout / 1000 : rawTimeout;
|
|
90
|
+
// Clamp to reasonable range: 1s - 3600s (1 hour)
|
|
91
|
+
timeoutSec = Math.max(1, Math.min(3600, timeoutSec));
|
|
92
|
+
const timeoutMs = timeoutSec * 1000;
|
|
93
|
+
|
|
94
|
+
// Track output for streaming updates (tail only)
|
|
95
|
+
const tailBuffer = createTailBuffer(DEFAULT_MAX_BYTES);
|
|
96
|
+
|
|
97
|
+
// Set up artifacts environment and allocation
|
|
98
|
+
const artifactsDir = this.session.getArtifactsDir?.();
|
|
99
|
+
const extraEnv = artifactsDir ? { ARTIFACTS: artifactsDir } : undefined;
|
|
100
|
+
const { artifactPath, artifactId } = await allocateOutputArtifact(this.session, "bash");
|
|
87
101
|
|
|
88
102
|
const executorOptions: BashExecutorOptions = {
|
|
89
103
|
cwd: commandCwd,
|
|
90
|
-
timeout:
|
|
104
|
+
timeout: timeoutMs,
|
|
91
105
|
signal,
|
|
106
|
+
env: extraEnv,
|
|
107
|
+
artifactPath,
|
|
108
|
+
artifactId,
|
|
92
109
|
onChunk: (chunk) => {
|
|
93
|
-
|
|
110
|
+
tailBuffer.append(chunk);
|
|
94
111
|
if (onUpdate) {
|
|
95
|
-
const truncation = truncateTail(currentOutput);
|
|
96
112
|
onUpdate({
|
|
97
|
-
content: [{ type: "text", text:
|
|
98
|
-
details:
|
|
113
|
+
content: [{ type: "text", text: tailBuffer.text() }],
|
|
114
|
+
details: {},
|
|
99
115
|
});
|
|
100
116
|
}
|
|
101
117
|
},
|
|
@@ -104,33 +120,18 @@ export class BashTool implements AgentTool<typeof bashSchema, BashToolDetails> {
|
|
|
104
120
|
// Handle errors
|
|
105
121
|
const result = await executeBash(command, executorOptions);
|
|
106
122
|
if (result.cancelled) {
|
|
107
|
-
throw new
|
|
123
|
+
throw new ToolError(result.output || "Command aborted");
|
|
108
124
|
}
|
|
109
125
|
|
|
110
|
-
|
|
111
|
-
const
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
let details: BashToolDetails | undefined;
|
|
115
|
-
|
|
116
|
-
if (truncation.truncated) {
|
|
117
|
-
details = {
|
|
118
|
-
truncation,
|
|
119
|
-
fullOutputPath: result.fullOutputPath,
|
|
120
|
-
fullOutput: currentOutput,
|
|
121
|
-
};
|
|
122
|
-
outputText += formatTailTruncationNotice(truncation, {
|
|
123
|
-
fullOutputPath: result.fullOutputPath,
|
|
124
|
-
originalContent: result.output,
|
|
125
|
-
});
|
|
126
|
-
}
|
|
126
|
+
const outputText = result.output || "(no output)";
|
|
127
|
+
const details: BashToolDetails = {};
|
|
128
|
+
const resultBuilder = toolResult(details).text(outputText).truncationFromSummary(result, { direction: "tail" });
|
|
127
129
|
|
|
128
130
|
if (result.exitCode !== 0 && result.exitCode !== undefined) {
|
|
129
|
-
|
|
130
|
-
throw new Error(outputText);
|
|
131
|
+
throw new ToolError(`${outputText}\n\nCommand exited with code ${result.exitCode}`);
|
|
131
132
|
}
|
|
132
133
|
|
|
133
|
-
return
|
|
134
|
+
return resultBuilder.done();
|
|
134
135
|
}
|
|
135
136
|
}
|
|
136
137
|
|
|
@@ -147,6 +148,8 @@ interface BashRenderArgs {
|
|
|
147
148
|
interface BashRenderContext {
|
|
148
149
|
/** Raw output text */
|
|
149
150
|
output?: string;
|
|
151
|
+
/** Whether output came from artifact storage */
|
|
152
|
+
isFullOutput?: boolean;
|
|
150
153
|
/** Whether output is expanded */
|
|
151
154
|
expanded?: boolean;
|
|
152
155
|
/** Number of preview lines when collapsed */
|
|
@@ -198,38 +201,33 @@ export const bashToolRenderer = {
|
|
|
198
201
|
const ui = new ToolUIKit(uiTheme);
|
|
199
202
|
const { renderContext } = options;
|
|
200
203
|
const details = result.details;
|
|
201
|
-
|
|
202
204
|
const expanded = renderContext?.expanded ?? options.expanded;
|
|
203
205
|
const previewLines = renderContext?.previewLines ?? BASH_DEFAULT_PREVIEW_LINES;
|
|
204
206
|
|
|
205
207
|
// Get output from context (preferred) or fall back to result content
|
|
206
208
|
const output = renderContext?.output ?? (result.content?.find((c) => c.type === "text")?.text ?? "").trim();
|
|
207
|
-
const
|
|
208
|
-
const
|
|
209
|
-
const showingFullOutput = expanded && fullOutput !== undefined;
|
|
209
|
+
const displayOutput = output;
|
|
210
|
+
const showingFullOutput = expanded && renderContext?.isFullOutput === true;
|
|
210
211
|
|
|
211
212
|
// Build truncation warning lines (static, doesn't depend on width)
|
|
212
|
-
const truncation = details?.truncation;
|
|
213
|
-
const fullOutputPath = details?.fullOutputPath;
|
|
213
|
+
const truncation = details?.meta?.truncation;
|
|
214
214
|
const timeoutSeconds = renderContext?.timeout;
|
|
215
215
|
const timeoutLine =
|
|
216
216
|
typeof timeoutSeconds === "number"
|
|
217
217
|
? uiTheme.fg("dim", ui.wrapBrackets(`Timeout: ${timeoutSeconds}s`))
|
|
218
218
|
: undefined;
|
|
219
219
|
let warningLine: string | undefined;
|
|
220
|
-
if (
|
|
220
|
+
if (truncation && !showingFullOutput) {
|
|
221
221
|
const warnings: string[] = [];
|
|
222
|
-
if (
|
|
223
|
-
warnings.push(`Full output:
|
|
222
|
+
if (truncation?.artifactId) {
|
|
223
|
+
warnings.push(`Full output: artifact://${truncation.artifactId}`);
|
|
224
224
|
}
|
|
225
|
-
if (truncation
|
|
226
|
-
|
|
227
|
-
|
|
228
|
-
|
|
229
|
-
|
|
230
|
-
|
|
231
|
-
);
|
|
232
|
-
}
|
|
225
|
+
if (truncation.truncatedBy === "lines") {
|
|
226
|
+
warnings.push(`Truncated: showing ${truncation.outputLines} of ${truncation.totalLines} lines`);
|
|
227
|
+
} else {
|
|
228
|
+
warnings.push(
|
|
229
|
+
`Truncated: ${truncation.outputLines} lines shown (${ui.formatBytes(truncation.outputBytes)} limit)`,
|
|
230
|
+
);
|
|
233
231
|
}
|
|
234
232
|
if (warnings.length > 0) {
|
|
235
233
|
warningLine = uiTheme.fg("warning", ui.wrapBrackets(warnings.join(". ")));
|
|
@@ -3,10 +3,10 @@ import type { Component } from "@oh-my-pi/pi-tui";
|
|
|
3
3
|
import { Text } from "@oh-my-pi/pi-tui";
|
|
4
4
|
import { untilAborted } from "@oh-my-pi/pi-utils";
|
|
5
5
|
import { Type } from "@sinclair/typebox";
|
|
6
|
-
import
|
|
7
|
-
import
|
|
8
|
-
import type {
|
|
9
|
-
import
|
|
6
|
+
import { renderPromptTemplate } from "$c/config/prompt-templates";
|
|
7
|
+
import type { RenderResultOptions } from "$c/extensibility/custom-tools/types";
|
|
8
|
+
import type { Theme } from "$c/modes/theme/theme";
|
|
9
|
+
import calculatorDescription from "$c/prompts/tools/calculator.md" with { type: "text" };
|
|
10
10
|
import type { ToolSession } from "./index";
|
|
11
11
|
import {
|
|
12
12
|
formatCount,
|
|
@@ -9,9 +9,9 @@ import { StringEnum } from "@oh-my-pi/pi-ai";
|
|
|
9
9
|
import type { Static, TObject } from "@sinclair/typebox";
|
|
10
10
|
import { Type } from "@sinclair/typebox";
|
|
11
11
|
import Ajv, { type ErrorObject, type ValidateFunction } from "ajv";
|
|
12
|
+
import { subprocessToolRegistry } from "$c/task/subprocess-tool-registry";
|
|
12
13
|
import type { ToolSession } from "./index";
|
|
13
14
|
import { jtdToJsonSchema } from "./jtd-to-json-schema";
|
|
14
|
-
import { subprocessToolRegistry } from "./task/subprocess-tool-registry";
|
|
15
15
|
|
|
16
16
|
export interface CompleteDetails {
|
|
17
17
|
data: unknown;
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import type { AgentToolContext, ToolCallContext } from "@oh-my-pi/pi-agent-core";
|
|
2
|
-
import type { CustomToolContext } from "
|
|
3
|
-
import type { ExtensionUIContext } from "
|
|
2
|
+
import type { CustomToolContext } from "$c/extensibility/custom-tools/types";
|
|
3
|
+
import type { ExtensionUIContext } from "$c/extensibility/extensions/types";
|
|
4
4
|
|
|
5
5
|
declare module "@oh-my-pi/pi-agent-core" {
|
|
6
6
|
interface AgentToolContext extends CustomToolContext {
|
|
@@ -1,5 +1,4 @@
|
|
|
1
|
-
import { rm } from "node:fs/promises";
|
|
2
|
-
import { tmpdir } from "node:os";
|
|
1
|
+
import { mkdir, rm } from "node:fs/promises";
|
|
3
2
|
import * as path from "node:path";
|
|
4
3
|
import type { AgentTool, AgentToolContext, AgentToolResult, AgentToolUpdateCallback } from "@oh-my-pi/pi-agent-core";
|
|
5
4
|
import type { Component } from "@oh-my-pi/pi-tui";
|
|
@@ -8,26 +7,26 @@ import { ptree } from "@oh-my-pi/pi-utils";
|
|
|
8
7
|
import { type Static, Type } from "@sinclair/typebox";
|
|
9
8
|
import { nanoid } from "nanoid";
|
|
10
9
|
import { parse as parseHtml } from "node-html-parser";
|
|
11
|
-
import {
|
|
12
|
-
import
|
|
13
|
-
import {
|
|
14
|
-
import
|
|
15
|
-
import {
|
|
10
|
+
import { renderPromptTemplate } from "$c/config/prompt-templates";
|
|
11
|
+
import type { RenderResultOptions } from "$c/extensibility/custom-tools/types";
|
|
12
|
+
import { type Theme, theme } from "$c/modes/theme/theme";
|
|
13
|
+
import fetchDescription from "$c/prompts/tools/fetch.md" with { type: "text" };
|
|
14
|
+
import type { OutputMeta } from "$c/tools/output-meta";
|
|
15
|
+
import { ToolAbortError } from "$c/tools/tool-errors";
|
|
16
|
+
import { ensureTool } from "$c/utils/tools-manager";
|
|
17
|
+
import { specialHandlers } from "$c/web/scrapers/index";
|
|
18
|
+
import type { RenderResult } from "$c/web/scrapers/types";
|
|
19
|
+
import { finalizeOutput, loadPage, MAX_OUTPUT_CHARS } from "$c/web/scrapers/types";
|
|
20
|
+
import { convertWithMarkitdown, fetchBinary } from "$c/web/scrapers/utils";
|
|
16
21
|
import type { ToolSession } from "./index";
|
|
22
|
+
import { applyListLimit } from "./list-limit";
|
|
17
23
|
import { formatExpandHint } from "./render-utils";
|
|
18
|
-
import {
|
|
19
|
-
import type { RenderResult } from "./web-scrapers/types";
|
|
20
|
-
import { finalizeOutput, loadPage } from "./web-scrapers/types";
|
|
21
|
-
import { convertWithMarkitdown, fetchBinary } from "./web-scrapers/utils";
|
|
24
|
+
import { toolResult } from "./tool-result";
|
|
22
25
|
|
|
23
26
|
// =============================================================================
|
|
24
27
|
// Types and Constants
|
|
25
28
|
// =============================================================================
|
|
26
29
|
|
|
27
|
-
const MIN_TIMEOUT = 1_000;
|
|
28
|
-
const DEFAULT_TIMEOUT = 20_000;
|
|
29
|
-
const MAX_TIMEOUT = 45_000;
|
|
30
|
-
|
|
31
30
|
// Convertible document types (markitdown supported)
|
|
32
31
|
const CONVERTIBLE_MIMES = new Set([
|
|
33
32
|
"application/pdf",
|
|
@@ -246,7 +245,7 @@ async function tryMdSuffix(url: string, timeout: number, signal?: AbortSignal):
|
|
|
246
245
|
if (signal?.aborted) {
|
|
247
246
|
return null;
|
|
248
247
|
}
|
|
249
|
-
const result = await loadPage(candidate, { timeout
|
|
248
|
+
const result = await loadPage(candidate, { timeout, signal });
|
|
250
249
|
if (result.ok && result.content.trim().length > 100 && !looksLikeHtml(result.content)) {
|
|
251
250
|
return result.content;
|
|
252
251
|
}
|
|
@@ -448,9 +447,10 @@ function parseFeedToMarkdown(content: string, maxItems = 10): string {
|
|
|
448
447
|
async function renderHtmlToText(
|
|
449
448
|
html: string,
|
|
450
449
|
timeout: number,
|
|
450
|
+
scratchDir: string,
|
|
451
451
|
): Promise<{ content: string; ok: boolean; method: string }> {
|
|
452
|
-
|
|
453
|
-
const tmpFile = path.join(
|
|
452
|
+
await mkdir(scratchDir, { recursive: true });
|
|
453
|
+
const tmpFile = path.join(scratchDir, `omp-${nanoid()}.html`);
|
|
454
454
|
|
|
455
455
|
try {
|
|
456
456
|
await Bun.write(tmpFile, html);
|
|
@@ -532,7 +532,7 @@ function formatJson(content: string): string {
|
|
|
532
532
|
async function handleSpecialUrls(url: string, timeout: number, signal?: AbortSignal): Promise<RenderResult | null> {
|
|
533
533
|
for (const handler of specialHandlers) {
|
|
534
534
|
if (signal?.aborted) {
|
|
535
|
-
throw new
|
|
535
|
+
throw new ToolAbortError();
|
|
536
536
|
}
|
|
537
537
|
const result = await handler(url, timeout, signal);
|
|
538
538
|
if (result) return result;
|
|
@@ -550,13 +550,14 @@ async function handleSpecialUrls(url: string, timeout: number, signal?: AbortSig
|
|
|
550
550
|
async function renderUrl(
|
|
551
551
|
url: string,
|
|
552
552
|
timeout: number,
|
|
553
|
-
raw: boolean
|
|
553
|
+
raw: boolean,
|
|
554
|
+
scratchDir: string,
|
|
554
555
|
signal?: AbortSignal,
|
|
555
556
|
): Promise<RenderResult> {
|
|
556
557
|
const notes: string[] = [];
|
|
557
558
|
const fetchedAt = new Date().toISOString();
|
|
558
559
|
if (signal?.aborted) {
|
|
559
|
-
throw new
|
|
560
|
+
throw new ToolAbortError();
|
|
560
561
|
}
|
|
561
562
|
|
|
562
563
|
// Handle internal protocol URLs (e.g., pi-internal://) - return empty
|
|
@@ -586,7 +587,7 @@ async function renderUrl(
|
|
|
586
587
|
// Step 2: Fetch page
|
|
587
588
|
const response = await loadPage(url, { timeout, signal });
|
|
588
589
|
if (signal?.aborted) {
|
|
589
|
-
throw new
|
|
590
|
+
throw new ToolAbortError();
|
|
590
591
|
}
|
|
591
592
|
if (!response.ok) {
|
|
592
593
|
return {
|
|
@@ -787,11 +788,11 @@ async function renderUrl(
|
|
|
787
788
|
}
|
|
788
789
|
|
|
789
790
|
if (signal?.aborted) {
|
|
790
|
-
throw new
|
|
791
|
+
throw new ToolAbortError();
|
|
791
792
|
}
|
|
792
793
|
|
|
793
794
|
// Step 6: Render HTML with lynx or html2text
|
|
794
|
-
const htmlResult = await renderHtmlToText(rawContent, timeout);
|
|
795
|
+
const htmlResult = await renderHtmlToText(rawContent, timeout, scratchDir);
|
|
795
796
|
if (!htmlResult.ok) {
|
|
796
797
|
notes.push("html rendering failed (lynx/html2text unavailable)");
|
|
797
798
|
const output = finalizeOutput(rawContent);
|
|
@@ -871,66 +872,68 @@ async function renderUrl(
|
|
|
871
872
|
// Tool Definition
|
|
872
873
|
// =============================================================================
|
|
873
874
|
|
|
874
|
-
const
|
|
875
|
-
url: Type.String({ description: "
|
|
876
|
-
timeout: Type.Optional(Type.Number({ description: "Timeout in seconds (default: 20
|
|
877
|
-
raw: Type.Optional(
|
|
878
|
-
Type.Boolean({ description: "Return raw content without site-specific rendering or LLM-friendly transforms" }),
|
|
879
|
-
),
|
|
875
|
+
const fetchSchema = Type.Object({
|
|
876
|
+
url: Type.String({ description: "URL to fetch" }),
|
|
877
|
+
timeout: Type.Optional(Type.Number({ description: "Timeout in seconds (default: 20)" })),
|
|
878
|
+
raw: Type.Optional(Type.Boolean({ description: "Return raw HTML without transforms" })),
|
|
880
879
|
});
|
|
881
880
|
|
|
882
|
-
export interface
|
|
881
|
+
export interface FetchToolDetails {
|
|
883
882
|
url: string;
|
|
884
883
|
finalUrl: string;
|
|
885
884
|
contentType: string;
|
|
886
885
|
method: string;
|
|
887
886
|
truncated: boolean;
|
|
888
887
|
notes: string[];
|
|
888
|
+
meta?: OutputMeta;
|
|
889
889
|
}
|
|
890
890
|
|
|
891
|
-
export class
|
|
892
|
-
public readonly name = "
|
|
893
|
-
public readonly label = "
|
|
891
|
+
export class FetchTool implements AgentTool<typeof fetchSchema, FetchToolDetails> {
|
|
892
|
+
public readonly name = "fetch";
|
|
893
|
+
public readonly label = "Fetch";
|
|
894
894
|
public readonly description: string;
|
|
895
|
-
public readonly parameters =
|
|
895
|
+
public readonly parameters = fetchSchema;
|
|
896
|
+
private readonly session: ToolSession;
|
|
896
897
|
|
|
897
|
-
constructor(
|
|
898
|
-
this.
|
|
898
|
+
constructor(session: ToolSession) {
|
|
899
|
+
this.session = session;
|
|
900
|
+
this.description = renderPromptTemplate(fetchDescription);
|
|
899
901
|
}
|
|
900
902
|
|
|
901
903
|
public async execute(
|
|
902
904
|
_toolCallId: string,
|
|
903
|
-
params: Static<typeof
|
|
905
|
+
params: Static<typeof fetchSchema>,
|
|
904
906
|
signal?: AbortSignal,
|
|
905
|
-
_onUpdate?: AgentToolUpdateCallback<
|
|
907
|
+
_onUpdate?: AgentToolUpdateCallback<FetchToolDetails>,
|
|
906
908
|
_context?: AgentToolContext,
|
|
907
|
-
): Promise<AgentToolResult<
|
|
908
|
-
const { url, timeout =
|
|
909
|
+
): Promise<AgentToolResult<FetchToolDetails>> {
|
|
910
|
+
const { url, timeout: rawTimeout = 20, raw = false } = params;
|
|
911
|
+
|
|
912
|
+
// Auto-convert milliseconds to seconds if value > 1000 (16+ min is unreasonable)
|
|
913
|
+
const timeoutSec = rawTimeout > 1000 ? rawTimeout / 1000 : rawTimeout;
|
|
914
|
+
|
|
915
|
+
// Clamp to valid range (seconds)
|
|
916
|
+
const effectiveTimeout = Math.min(Math.max(timeoutSec, 1), 45);
|
|
909
917
|
|
|
910
918
|
if (signal?.aborted) {
|
|
911
|
-
throw new
|
|
919
|
+
throw new ToolAbortError();
|
|
912
920
|
}
|
|
913
921
|
|
|
914
|
-
|
|
915
|
-
const
|
|
916
|
-
|
|
917
|
-
const result = await renderUrl(url, effectiveTimeout, raw, signal);
|
|
922
|
+
const scratchDir = this.session.getArtifactsDir?.() ?? this.session.cwd;
|
|
923
|
+
const result = await renderUrl(url, effectiveTimeout, raw, scratchDir, signal);
|
|
918
924
|
|
|
919
925
|
// Format output
|
|
920
926
|
let output = "";
|
|
921
927
|
output += `URL: ${result.finalUrl}\n`;
|
|
922
928
|
output += `Content-Type: ${result.contentType}\n`;
|
|
923
929
|
output += `Method: ${result.method}\n`;
|
|
924
|
-
if (result.truncated) {
|
|
925
|
-
output += `Warning: Output was truncated\n`;
|
|
926
|
-
}
|
|
927
930
|
if (result.notes.length > 0) {
|
|
928
931
|
output += `Notes: ${result.notes.join("; ")}\n`;
|
|
929
932
|
}
|
|
930
933
|
output += `\n---\n\n`;
|
|
931
934
|
output += result.content;
|
|
932
935
|
|
|
933
|
-
const details:
|
|
936
|
+
const details: FetchToolDetails = {
|
|
934
937
|
url: result.url,
|
|
935
938
|
finalUrl: result.finalUrl,
|
|
936
939
|
contentType: result.contentType,
|
|
@@ -939,10 +942,21 @@ export class WebFetchTool implements AgentTool<typeof webFetchSchema, WebFetchTo
|
|
|
939
942
|
notes: result.notes,
|
|
940
943
|
};
|
|
941
944
|
|
|
942
|
-
|
|
943
|
-
|
|
944
|
-
|
|
945
|
-
|
|
945
|
+
const resultBuilder = toolResult(details).text(output).sourceUrl(result.finalUrl);
|
|
946
|
+
if (result.truncated) {
|
|
947
|
+
const outputLines = result.content.split("\n").length;
|
|
948
|
+
const outputBytes = Buffer.byteLength(result.content, "utf-8");
|
|
949
|
+
const totalBytes = Math.max(outputBytes + 1, MAX_OUTPUT_CHARS + 1);
|
|
950
|
+
const totalLines = outputLines + 1;
|
|
951
|
+
resultBuilder.truncationFromText(result.content, {
|
|
952
|
+
direction: "tail",
|
|
953
|
+
totalLines,
|
|
954
|
+
totalBytes,
|
|
955
|
+
maxBytes: MAX_OUTPUT_CHARS,
|
|
956
|
+
});
|
|
957
|
+
}
|
|
958
|
+
|
|
959
|
+
return resultBuilder.done();
|
|
946
960
|
}
|
|
947
961
|
}
|
|
948
962
|
|
|
@@ -967,32 +981,26 @@ function getDomain(url: string): string {
|
|
|
967
981
|
}
|
|
968
982
|
}
|
|
969
983
|
|
|
970
|
-
/** Get first N lines of text as preview */
|
|
971
|
-
function getPreviewLines(text: string, maxLines: number, maxLineLen: number, ellipsis: string): string[] {
|
|
972
|
-
const lines = text.split("\n").filter((l) => l.trim());
|
|
973
|
-
return lines.slice(0, maxLines).map((l) => truncate(l.trim(), maxLineLen, ellipsis));
|
|
974
|
-
}
|
|
975
|
-
|
|
976
984
|
/** Count non-empty lines */
|
|
977
985
|
function countNonEmptyLines(text: string): number {
|
|
978
986
|
return text.split("\n").filter((l) => l.trim()).length;
|
|
979
987
|
}
|
|
980
988
|
|
|
981
|
-
/** Render
|
|
982
|
-
export function
|
|
989
|
+
/** Render fetch call (URL preview) */
|
|
990
|
+
export function renderFetchCall(
|
|
983
991
|
args: { url: string; timeout?: number; raw?: boolean },
|
|
984
992
|
uiTheme: Theme = theme,
|
|
985
993
|
): Component {
|
|
986
994
|
const domain = getDomain(args.url);
|
|
987
995
|
const path = truncate(args.url.replace(/^https?:\/\/[^/]+/, ""), 50, uiTheme.format.ellipsis);
|
|
988
996
|
const icon = uiTheme.styledSymbol("status.pending", "muted");
|
|
989
|
-
const text = `${icon} ${uiTheme.fg("toolTitle", "
|
|
997
|
+
const text = `${icon} ${uiTheme.fg("toolTitle", "Fetch")} ${uiTheme.fg("accent", domain)}${uiTheme.fg("dim", path)}`;
|
|
990
998
|
return new Text(text, 0, 0);
|
|
991
999
|
}
|
|
992
1000
|
|
|
993
|
-
/** Render
|
|
994
|
-
export function
|
|
995
|
-
result: { content: Array<{ type: string; text?: string }>; details?:
|
|
1001
|
+
/** Render fetch result with tree-based layout */
|
|
1002
|
+
export function renderFetchResult(
|
|
1003
|
+
result: { content: Array<{ type: string; text?: string }>; details?: FetchToolDetails },
|
|
996
1004
|
options: RenderResultOptions,
|
|
997
1005
|
uiTheme: Theme = theme,
|
|
998
1006
|
): Component {
|
|
@@ -1006,7 +1014,9 @@ export function renderWebFetchResult(
|
|
|
1006
1014
|
const domain = getDomain(details.finalUrl);
|
|
1007
1015
|
const hasRedirect = details.url !== details.finalUrl;
|
|
1008
1016
|
const hasNotes = details.notes.length > 0;
|
|
1009
|
-
const
|
|
1017
|
+
const truncation = details.meta?.truncation;
|
|
1018
|
+
const truncated = Boolean(details.truncated || truncation);
|
|
1019
|
+
const statusIcon = truncated
|
|
1010
1020
|
? uiTheme.styledSymbol("status.warning", "warning")
|
|
1011
1021
|
: uiTheme.styledSymbol("status.success", "success");
|
|
1012
1022
|
const expandHint = formatExpandHint(uiTheme, expanded);
|
|
@@ -1021,6 +1031,7 @@ export function renderWebFetchResult(
|
|
|
1021
1031
|
: contentText;
|
|
1022
1032
|
const lineCount = countNonEmptyLines(contentBody);
|
|
1023
1033
|
const charCount = contentBody.trim().length;
|
|
1034
|
+
const contentLines = contentBody.split("\n").filter((l) => l.trim());
|
|
1024
1035
|
|
|
1025
1036
|
if (!expanded) {
|
|
1026
1037
|
// Collapsed view: metadata + preview
|
|
@@ -1031,14 +1042,19 @@ export function renderWebFetchResult(
|
|
|
1031
1042
|
if (hasRedirect) {
|
|
1032
1043
|
metaLines.push(`${uiTheme.fg("muted", "Final URL:")} ${uiTheme.fg("mdLinkUrl", details.finalUrl)}`);
|
|
1033
1044
|
}
|
|
1034
|
-
if (
|
|
1045
|
+
if (truncated) {
|
|
1035
1046
|
metaLines.push(uiTheme.fg("warning", `${uiTheme.status.warning} Output truncated`));
|
|
1047
|
+
if (truncation?.artifactId) {
|
|
1048
|
+
metaLines.push(uiTheme.fg("warning", `Full output: artifact://${truncation.artifactId}`));
|
|
1049
|
+
}
|
|
1036
1050
|
}
|
|
1037
1051
|
if (hasNotes) {
|
|
1038
1052
|
metaLines.push(`${uiTheme.fg("muted", "Notes:")} ${details.notes.join("; ")}`);
|
|
1039
1053
|
}
|
|
1040
1054
|
|
|
1041
|
-
const
|
|
1055
|
+
const previewLimit = 3;
|
|
1056
|
+
const previewList = applyListLimit(contentLines, { headLimit: previewLimit });
|
|
1057
|
+
const previewLines = previewList.items.map((line) => truncate(line.trim(), 100, uiTheme.format.ellipsis));
|
|
1042
1058
|
const detailLines: string[] = [...metaLines];
|
|
1043
1059
|
|
|
1044
1060
|
if (previewLines.length === 0) {
|
|
@@ -1049,7 +1065,7 @@ export function renderWebFetchResult(
|
|
|
1049
1065
|
}
|
|
1050
1066
|
}
|
|
1051
1067
|
|
|
1052
|
-
const remaining = Math.max(0,
|
|
1068
|
+
const remaining = Math.max(0, contentLines.length - previewLines.length);
|
|
1053
1069
|
if (remaining > 0) {
|
|
1054
1070
|
detailLines.push(uiTheme.fg("muted", `${uiTheme.format.ellipsis} ${remaining} more lines`));
|
|
1055
1071
|
} else {
|
|
@@ -1074,8 +1090,11 @@ export function renderWebFetchResult(
|
|
|
1074
1090
|
const lineLabel = `${lineCount} line${lineCount === 1 ? "" : "s"}`;
|
|
1075
1091
|
metaLines.push(`${uiTheme.fg("muted", "Lines:")} ${lineLabel}`);
|
|
1076
1092
|
metaLines.push(`${uiTheme.fg("muted", "Chars:")} ${charCount}`);
|
|
1077
|
-
if (
|
|
1093
|
+
if (truncated) {
|
|
1078
1094
|
metaLines.push(uiTheme.fg("warning", `${uiTheme.status.warning} Output truncated`));
|
|
1095
|
+
if (truncation?.artifactId) {
|
|
1096
|
+
metaLines.push(uiTheme.fg("warning", `Full output: artifact://${truncation.artifactId}`));
|
|
1097
|
+
}
|
|
1079
1098
|
}
|
|
1080
1099
|
if (hasNotes) {
|
|
1081
1100
|
metaLines.push(`${uiTheme.fg("muted", "Notes:")} ${details.notes.join("; ")}`);
|
|
@@ -1089,8 +1108,10 @@ export function renderWebFetchResult(
|
|
|
1089
1108
|
}
|
|
1090
1109
|
|
|
1091
1110
|
text += `\n ${uiTheme.fg("dim", uiTheme.tree.last)} ${uiTheme.fg("accent", "Content Preview")}`;
|
|
1092
|
-
const
|
|
1093
|
-
const
|
|
1111
|
+
const previewLimit = 12;
|
|
1112
|
+
const previewList = applyListLimit(contentLines, { headLimit: previewLimit });
|
|
1113
|
+
const previewLines = previewList.items.map((line) => truncate(line.trim(), 120, uiTheme.format.ellipsis));
|
|
1114
|
+
const remaining = Math.max(0, contentLines.length - previewLines.length);
|
|
1094
1115
|
const contentPrefix = uiTheme.fg("dim", " ");
|
|
1095
1116
|
|
|
1096
1117
|
if (previewLines.length === 0) {
|
|
@@ -1109,7 +1130,7 @@ export function renderWebFetchResult(
|
|
|
1109
1130
|
return new Text(text, 0, 0);
|
|
1110
1131
|
}
|
|
1111
1132
|
|
|
1112
|
-
export const
|
|
1113
|
-
renderCall:
|
|
1114
|
-
renderResult:
|
|
1133
|
+
export const fetchToolRenderer = {
|
|
1134
|
+
renderCall: renderFetchCall,
|
|
1135
|
+
renderResult: renderFetchResult,
|
|
1115
1136
|
};
|