@herbertgao/pi-extensions 2026.8.1 → 2026.8.3
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/README.md +13 -3
- package/node_modules/@czottmann/pi-automode/README.md +16 -2
- package/node_modules/@czottmann/pi-automode/docs/GLOSSARY.md +35 -0
- package/node_modules/@czottmann/pi-automode/docs/automode-classifier-flow.md +18 -9
- package/node_modules/@czottmann/pi-automode/docs/defaults.md +6 -2
- package/node_modules/@czottmann/pi-automode/examples/automode.local.json +6 -0
- package/node_modules/@czottmann/pi-automode/extensions/auto-mode/classifier.ts +11 -7
- package/node_modules/@czottmann/pi-automode/extensions/auto-mode/config.ts +100 -0
- package/node_modules/@czottmann/pi-automode/extensions/auto-mode/constants.ts +32 -0
- package/node_modules/@czottmann/pi-automode/extensions/auto-mode/extension.ts +78 -3
- package/node_modules/@czottmann/pi-automode/extensions/auto-mode/hard-deny.ts +16 -4
- package/node_modules/@czottmann/pi-automode/extensions/auto-mode/paths.ts +23 -1
- package/node_modules/@czottmann/pi-automode/extensions/auto-mode/permissions.ts +22 -1
- package/node_modules/@czottmann/pi-automode/extensions/auto-mode/types.ts +18 -2
- package/node_modules/@czottmann/pi-automode/package.json +4 -4
- package/node_modules/@dietrichgebert/ponytail/.opencode/command/ponytail-audit.md +5 -0
- package/node_modules/@dietrichgebert/ponytail/.opencode/command/ponytail-debt.md +5 -0
- package/node_modules/@dietrichgebert/ponytail/.opencode/command/ponytail-gain.md +5 -0
- package/node_modules/@dietrichgebert/ponytail/.opencode/command/ponytail-help.md +5 -0
- package/node_modules/@dietrichgebert/ponytail/.opencode/command/ponytail-review.md +5 -0
- package/node_modules/@dietrichgebert/ponytail/.opencode/command/ponytail.md +5 -0
- package/node_modules/@dietrichgebert/ponytail/.opencode/plugins/ponytail-frontmatter.cjs +23 -0
- package/node_modules/@dietrichgebert/ponytail/.opencode/plugins/ponytail.mjs +99 -0
- package/node_modules/@dietrichgebert/ponytail/.qoder/rules/ponytail.md +30 -0
- package/node_modules/@dietrichgebert/ponytail/.qoder-plugin/plugin.json +16 -0
- package/node_modules/@dietrichgebert/ponytail/AGENTS.md +32 -0
- package/node_modules/@dietrichgebert/ponytail/LICENSE +21 -0
- package/node_modules/@dietrichgebert/ponytail/README.es.md +298 -0
- package/node_modules/@dietrichgebert/ponytail/README.ko.md +315 -0
- package/node_modules/@dietrichgebert/ponytail/README.md +351 -0
- package/node_modules/@dietrichgebert/ponytail/assets/benchmark-3model.svg +21 -0
- package/node_modules/@dietrichgebert/ponytail/assets/benchmark-agentic.svg +62 -0
- package/node_modules/@dietrichgebert/ponytail/assets/logo-dark.png +0 -0
- package/node_modules/@dietrichgebert/ponytail/assets/logo-dark.svg +115 -0
- package/node_modules/@dietrichgebert/ponytail/assets/logo-greenpt-dark.svg +27 -0
- package/node_modules/@dietrichgebert/ponytail/assets/logo-greenpt.svg +27 -0
- package/node_modules/@dietrichgebert/ponytail/assets/logo.png +0 -0
- package/node_modules/@dietrichgebert/ponytail/assets/social-preview.png +0 -0
- package/node_modules/@dietrichgebert/ponytail/assets/waitlist-banner-es.png +0 -0
- package/node_modules/@dietrichgebert/ponytail/assets/waitlist-banner-ko.png +0 -0
- package/node_modules/@dietrichgebert/ponytail/assets/waitlist-banner.png +0 -0
- package/node_modules/@dietrichgebert/ponytail/hooks/claude-codex-hooks.json +44 -0
- package/node_modules/@dietrichgebert/ponytail/hooks/copilot-hooks.json +21 -0
- package/node_modules/@dietrichgebert/ponytail/hooks/ponytail-activate.js +96 -0
- package/node_modules/@dietrichgebert/ponytail/hooks/ponytail-config.js +169 -0
- package/node_modules/@dietrichgebert/ponytail/hooks/ponytail-instructions.js +98 -0
- package/node_modules/@dietrichgebert/ponytail/hooks/ponytail-mode-tracker.js +130 -0
- package/node_modules/@dietrichgebert/ponytail/hooks/ponytail-runtime.js +85 -0
- package/node_modules/@dietrichgebert/ponytail/hooks/ponytail-statusline.ps1 +24 -0
- package/node_modules/@dietrichgebert/ponytail/hooks/ponytail-statusline.sh +18 -0
- package/node_modules/@dietrichgebert/ponytail/hooks/ponytail-subagent.js +77 -0
- package/node_modules/@dietrichgebert/ponytail/hooks/qoder-hooks.json +26 -0
- package/node_modules/@dietrichgebert/ponytail/package.json +47 -0
- package/node_modules/@dietrichgebert/ponytail/pi-extension/index.js +211 -0
- package/node_modules/@dietrichgebert/ponytail/pi-extension/package.json +8 -0
- package/node_modules/@dietrichgebert/ponytail/scripts/uninstall.js +60 -0
- package/node_modules/@dietrichgebert/ponytail/skills/ponytail/SKILL.md +120 -0
- package/node_modules/@dietrichgebert/ponytail/skills/ponytail-audit/SKILL.md +41 -0
- package/node_modules/@dietrichgebert/ponytail/skills/ponytail-debt/SKILL.md +44 -0
- package/node_modules/@dietrichgebert/ponytail/skills/ponytail-gain/SKILL.md +50 -0
- package/node_modules/@dietrichgebert/ponytail/skills/ponytail-help/SKILL.md +71 -0
- package/node_modules/@dietrichgebert/ponytail/skills/ponytail-review/SKILL.md +57 -0
- package/node_modules/@herbertgao/pi-cc-extensions/README.en.md +6 -10
- package/node_modules/@herbertgao/pi-cc-extensions/README.md +5 -9
- package/node_modules/@herbertgao/pi-cc-extensions/assets/readme/hero.en.svg +101 -0
- package/node_modules/@herbertgao/pi-cc-extensions/extensions/config/config.ts +1 -17
- package/node_modules/@herbertgao/pi-cc-extensions/extensions/config/panel.ts +15 -9
- package/node_modules/@herbertgao/pi-cc-extensions/extensions/{utils/agent-summary.ts → feature/agent-summary/core.ts} +37 -35
- package/node_modules/@herbertgao/pi-cc-extensions/extensions/feature/{agent-summary.ts → agent-summary/index.ts} +3 -3
- package/node_modules/@herbertgao/pi-cc-extensions/extensions/feature/compact-thinking.ts +24 -83
- package/node_modules/@herbertgao/pi-cc-extensions/extensions/feature/context.ts +1 -1
- package/node_modules/@herbertgao/pi-cc-extensions/extensions/feature/{session-reference.ts → reference/index.ts} +1 -1
- package/node_modules/@herbertgao/pi-cc-extensions/extensions/feature/{agent-autocomplete.ts → reference/subagent.ts} +19 -9
- package/node_modules/@herbertgao/pi-cc-extensions/extensions/feature/{pi-startup-header.ts → shell/startup-header.ts} +1 -1
- package/node_modules/@herbertgao/pi-cc-extensions/extensions/feature/{working-message.ts → shell/working-message.ts} +5 -2
- package/node_modules/@herbertgao/pi-cc-extensions/extensions/index.ts +32 -28
- package/node_modules/@herbertgao/pi-cc-extensions/extensions/renderer/compact-mode.ts +452 -94
- package/node_modules/@herbertgao/pi-cc-extensions/extensions/renderer/default-mode.ts +727 -0
- package/node_modules/@herbertgao/pi-cc-extensions/extensions/renderer/index.ts +66 -776
- package/node_modules/@herbertgao/pi-cc-extensions/extensions/{feature → renderer}/markdown-enhance.ts +134 -11
- package/node_modules/@herbertgao/pi-cc-extensions/extensions/renderer/mouse/hover.ts +130 -0
- package/node_modules/@herbertgao/pi-cc-extensions/extensions/renderer/{mouse-interaction.ts → mouse/interaction.ts} +90 -568
- package/node_modules/@herbertgao/pi-cc-extensions/extensions/renderer/mouse/layout.ts +144 -0
- package/node_modules/@herbertgao/pi-cc-extensions/extensions/renderer/mouse/packets.ts +143 -0
- package/node_modules/@herbertgao/pi-cc-extensions/extensions/renderer/mouse/scroll.ts +195 -0
- package/node_modules/@herbertgao/pi-cc-extensions/extensions/renderer/{tool-diff → tool/diff}/ansi-utils.ts +56 -1
- package/node_modules/@herbertgao/pi-cc-extensions/extensions/renderer/{tool-diff → tool/diff}/diff-renderer.ts +4 -4
- package/node_modules/@herbertgao/pi-cc-extensions/extensions/renderer/{tool-diff → tool/diff}/line-width-safety.ts +1 -1
- package/node_modules/@herbertgao/pi-cc-extensions/extensions/renderer/tool/diff/write-display-utils.ts +12 -0
- package/node_modules/@herbertgao/pi-cc-extensions/extensions/renderer/{tool-diff → tool/diff}/write-execution.ts +1 -2
- package/node_modules/@herbertgao/pi-cc-extensions/extensions/renderer/{tool-grouping.ts → tool/grouping.ts} +27 -10
- package/node_modules/@herbertgao/pi-cc-extensions/extensions/renderer/{tool-result.ts → tool/result.ts} +4 -13
- package/node_modules/@herbertgao/pi-cc-extensions/extensions/renderer/transcript-refresh.ts +91 -0
- package/node_modules/@herbertgao/pi-cc-extensions/extensions/utils/fullscreen-detect.ts +0 -27
- package/node_modules/@herbertgao/pi-cc-extensions/package.json +3 -3
- package/node_modules/@herbertgao/pi-cc-extensions/themes/cc-dark.json +1 -0
- package/node_modules/@herbertgao/pi-cc-extensions/themes/cc-light.json +2 -2
- package/node_modules/@herbertgao/pi-stash/README.md +9 -9
- package/node_modules/@herbertgao/pi-stash/package.json +1 -1
- package/node_modules/@herbertgao/pi-stash/src/index.ts +2 -1
- package/node_modules/@herbertgao/pi-subagents/CHANGELOG.md +20 -0
- package/node_modules/@herbertgao/pi-subagents/README.md +6 -2
- package/node_modules/@herbertgao/pi-subagents/package.json +3 -3
- package/node_modules/@herbertgao/pi-subagents/src/agent-manager.ts +1 -0
- package/node_modules/@herbertgao/pi-subagents/src/agent-runner.ts +3 -1
- package/node_modules/@herbertgao/pi-subagents/src/custom-agents.ts +85 -11
- package/node_modules/@herbertgao/pi-subagents/src/index.ts +61 -39
- package/node_modules/@herbertgao/pi-subagents/src/nested-tools.ts +26 -35
- package/node_modules/@herbertgao/pi-subagents/src/prompts.ts +15 -1
- package/node_modules/@herbertgao/pi-subagents/src/settings.ts +12 -0
- package/node_modules/@herbertgao/pi-subagents/src/types.ts +2 -0
- package/node_modules/@narumitw/pi-btw/LICENSE +21 -0
- package/node_modules/@narumitw/pi-btw/README.md +210 -0
- package/node_modules/@narumitw/pi-btw/package.json +53 -0
- package/node_modules/@narumitw/pi-btw/src/bring-to-main.ts +632 -0
- package/node_modules/@narumitw/pi-btw/src/btw.ts +996 -0
- package/node_modules/@narumitw/pi-btw/src/fullscreen-ui.ts +339 -0
- package/node_modules/@narumitw/pi-btw/src/index.ts +1 -0
- package/node_modules/@narumitw/pi-btw/src/menu.ts +296 -0
- package/node_modules/@narumitw/pi-btw/src/settings.ts +237 -0
- package/node_modules/@narumitw/pi-btw/src/side-thread.ts +238 -0
- package/node_modules/@narumitw/pi-btw/src/text.ts +10 -0
- package/node_modules/@narumitw/pi-btw/src/transcript-pager.ts +620 -0
- package/node_modules/@pi-plugins/fast-mode/LICENSE +21 -0
- package/node_modules/@pi-plugins/fast-mode/README.md +92 -0
- package/node_modules/@pi-plugins/fast-mode/dist/index.d.mts +6 -0
- package/node_modules/@pi-plugins/fast-mode/dist/index.d.mts.map +1 -0
- package/node_modules/@pi-plugins/fast-mode/dist/index.mjs +2026 -0
- package/node_modules/@pi-plugins/fast-mode/dist/index.mjs.map +1 -0
- package/node_modules/@pi-plugins/fast-mode/package.json +73 -0
- package/node_modules/pi-mcp-adapter/CHANGELOG.md +78 -0
- package/node_modules/pi-mcp-adapter/README.md +80 -16
- package/node_modules/pi-mcp-adapter/agent-dir.ts +40 -0
- package/node_modules/pi-mcp-adapter/agent-plugin-loader.ts +377 -0
- package/node_modules/pi-mcp-adapter/commands.ts +21 -9
- package/node_modules/pi-mcp-adapter/config.ts +110 -49
- package/node_modules/pi-mcp-adapter/direct-tools.ts +40 -27
- package/node_modules/pi-mcp-adapter/elicitation-handler.ts +37 -36
- package/node_modules/pi-mcp-adapter/errors.ts +21 -17
- package/node_modules/pi-mcp-adapter/host-html-template.ts +13 -7
- package/node_modules/pi-mcp-adapter/index.ts +52 -17
- package/node_modules/pi-mcp-adapter/init.ts +9 -7
- package/node_modules/pi-mcp-adapter/json-schema-validator.ts +2 -2
- package/node_modules/pi-mcp-adapter/lifecycle.ts +8 -8
- package/node_modules/pi-mcp-adapter/logger.ts +1 -1
- package/node_modules/pi-mcp-adapter/mcp-auth-flow.ts +122 -25
- package/node_modules/pi-mcp-adapter/mcp-auth.ts +120 -2
- package/node_modules/pi-mcp-adapter/mcp-callback-server.ts +138 -61
- package/node_modules/pi-mcp-adapter/mcp-code.ts +13 -11
- package/node_modules/pi-mcp-adapter/mcp-oauth-provider.ts +62 -17
- package/node_modules/pi-mcp-adapter/mcp-output-guard.ts +15 -11
- package/node_modules/pi-mcp-adapter/mcp-panel.ts +34 -15
- package/node_modules/pi-mcp-adapter/mcp-probe.ts +131 -34
- package/node_modules/pi-mcp-adapter/mcp-script-worker.mjs +2 -2
- package/node_modules/pi-mcp-adapter/mcp-setup-panel.ts +7 -4
- package/node_modules/pi-mcp-adapter/mcp-trace.ts +59 -64
- package/node_modules/pi-mcp-adapter/metadata-cache.ts +34 -26
- package/node_modules/pi-mcp-adapter/npx-resolver.ts +6 -4
- package/node_modules/pi-mcp-adapter/oauth-handler.ts +1 -1
- package/node_modules/pi-mcp-adapter/oauth.ts +48 -0
- package/node_modules/pi-mcp-adapter/onboarding-state.ts +19 -11
- package/node_modules/pi-mcp-adapter/package.json +20 -9
- package/node_modules/pi-mcp-adapter/panel-keys.ts +20 -4
- package/node_modules/pi-mcp-adapter/prompts.ts +2 -2
- package/node_modules/pi-mcp-adapter/proxy-modes.ts +56 -21
- package/node_modules/pi-mcp-adapter/sampling-handler.ts +22 -15
- package/node_modules/pi-mcp-adapter/search-ranking.ts +2 -1
- package/node_modules/pi-mcp-adapter/server-manager.ts +165 -113
- package/node_modules/pi-mcp-adapter/session-recovery.ts +11 -12
- package/node_modules/pi-mcp-adapter/skills/mcp-scripting/SKILL.md +3 -3
- package/node_modules/pi-mcp-adapter/state.ts +3 -1
- package/node_modules/pi-mcp-adapter/tool-approval.ts +67 -4
- package/node_modules/pi-mcp-adapter/tool-metadata.ts +6 -5
- package/node_modules/pi-mcp-adapter/tool-registrar.ts +187 -3
- package/node_modules/pi-mcp-adapter/tool-result-renderer.ts +14 -2
- package/node_modules/pi-mcp-adapter/ts-shape.ts +9 -2
- package/node_modules/pi-mcp-adapter/types.ts +111 -22
- package/node_modules/pi-mcp-adapter/ui-app-bridge-helpers.ts +40 -0
- package/node_modules/pi-mcp-adapter/ui-resource-handler.ts +28 -19
- package/node_modules/pi-mcp-adapter/ui-server.ts +90 -58
- package/node_modules/pi-mcp-adapter/ui-session.ts +16 -14
- package/node_modules/pi-mcp-adapter/unix-socket-transport.ts +4 -4
- package/node_modules/pi-mcp-adapter/utils.ts +23 -9
- package/node_modules/pi-web-access/CHANGELOG.md +45 -0
- package/node_modules/pi-web-access/README.md +104 -29
- package/node_modules/pi-web-access/bocha.ts +221 -0
- package/node_modules/pi-web-access/curator-page.ts +113 -12
- package/node_modules/pi-web-access/curator-server.ts +56 -20
- package/node_modules/pi-web-access/datalab-pdf-extract.ts +568 -0
- package/node_modules/pi-web-access/duckduckgo.ts +123 -0
- package/node_modules/pi-web-access/extract.ts +288 -143
- package/node_modules/pi-web-access/feature-config.ts +29 -0
- package/node_modules/pi-web-access/gemini-api.ts +4 -0
- package/node_modules/pi-web-access/gemini-search.ts +45 -12
- package/node_modules/pi-web-access/gemini-web.ts +68 -3
- package/node_modules/pi-web-access/index.ts +160 -71
- package/node_modules/pi-web-access/jina-search.ts +284 -0
- package/node_modules/pi-web-access/kagi.ts +12 -12
- package/node_modules/pi-web-access/openai-search.ts +12 -2
- package/node_modules/pi-web-access/package.json +4 -3
- package/node_modules/pi-web-access/pdf-extract.ts +327 -228
- package/node_modules/pi-web-access/storage.ts +440 -2
- package/node_modules/pi-web-access/summary-model-scope.ts +1 -1
- package/node_modules/pi-web-access/summary-review.ts +4 -2
- package/node_modules/pi-web-access/video-extract.ts +10 -8
- package/node_modules/pi-web-access/xai-search.ts +12 -2
- package/node_modules/pi-web-access/youtube-extract.ts +2 -1
- package/node_modules/remote-pi/LICENSE +21 -0
- package/node_modules/remote-pi/README.md +675 -0
- package/node_modules/remote-pi/dist/actions/handlers.d.ts +122 -0
- package/node_modules/remote-pi/dist/actions/handlers.js +160 -0
- package/node_modules/remote-pi/dist/actions/handlers.js.map +1 -0
- package/node_modules/remote-pi/dist/actions/registry.d.ts +39 -0
- package/node_modules/remote-pi/dist/actions/registry.js +58 -0
- package/node_modules/remote-pi/dist/actions/registry.js.map +1 -0
- package/node_modules/remote-pi/dist/bin/supervisord.d.ts +2 -0
- package/node_modules/remote-pi/dist/bin/supervisord.js +86 -0
- package/node_modules/remote-pi/dist/bin/supervisord.js.map +1 -0
- package/node_modules/remote-pi/dist/commands/builtin_mirror.d.ts +58 -0
- package/node_modules/remote-pi/dist/commands/builtin_mirror.js +71 -0
- package/node_modules/remote-pi/dist/commands/builtin_mirror.js.map +1 -0
- package/node_modules/remote-pi/dist/commands/list_commands.d.ts +60 -0
- package/node_modules/remote-pi/dist/commands/list_commands.js +73 -0
- package/node_modules/remote-pi/dist/commands/list_commands.js.map +1 -0
- package/node_modules/remote-pi/dist/config.d.ts +62 -0
- package/node_modules/remote-pi/dist/config.js +115 -0
- package/node_modules/remote-pi/dist/config.js.map +1 -0
- package/node_modules/remote-pi/dist/daemon/client.d.ts +20 -0
- package/node_modules/remote-pi/dist/daemon/client.js +131 -0
- package/node_modules/remote-pi/dist/daemon/client.js.map +1 -0
- package/node_modules/remote-pi/dist/daemon/control_protocol.d.ts +176 -0
- package/node_modules/remote-pi/dist/daemon/control_protocol.js +63 -0
- package/node_modules/remote-pi/dist/daemon/control_protocol.js.map +1 -0
- package/node_modules/remote-pi/dist/daemon/cron_log.d.ts +45 -0
- package/node_modules/remote-pi/dist/daemon/cron_log.js +72 -0
- package/node_modules/remote-pi/dist/daemon/cron_log.js.map +1 -0
- package/node_modules/remote-pi/dist/daemon/cron_registry.d.ts +80 -0
- package/node_modules/remote-pi/dist/daemon/cron_registry.js +194 -0
- package/node_modules/remote-pi/dist/daemon/cron_registry.js.map +1 -0
- package/node_modules/remote-pi/dist/daemon/id.d.ts +24 -0
- package/node_modules/remote-pi/dist/daemon/id.js +36 -0
- package/node_modules/remote-pi/dist/daemon/id.js.map +1 -0
- package/node_modules/remote-pi/dist/daemon/install.d.ts +170 -0
- package/node_modules/remote-pi/dist/daemon/install.js +547 -0
- package/node_modules/remote-pi/dist/daemon/install.js.map +1 -0
- package/node_modules/remote-pi/dist/daemon/registry.d.ts +63 -0
- package/node_modules/remote-pi/dist/daemon/registry.js +153 -0
- package/node_modules/remote-pi/dist/daemon/registry.js.map +1 -0
- package/node_modules/remote-pi/dist/daemon/rpc_child.d.ts +194 -0
- package/node_modules/remote-pi/dist/daemon/rpc_child.js +389 -0
- package/node_modules/remote-pi/dist/daemon/rpc_child.js.map +1 -0
- package/node_modules/remote-pi/dist/daemon/supervisor.d.ts +93 -0
- package/node_modules/remote-pi/dist/daemon/supervisor.js +596 -0
- package/node_modules/remote-pi/dist/daemon/supervisor.js.map +1 -0
- package/node_modules/remote-pi/dist/extension_ui_bridge.d.ts +26 -0
- package/node_modules/remote-pi/dist/extension_ui_bridge.js +341 -0
- package/node_modules/remote-pi/dist/extension_ui_bridge.js.map +1 -0
- package/node_modules/remote-pi/dist/index.d.ts +213 -0
- package/node_modules/remote-pi/dist/index.js +4996 -0
- package/node_modules/remote-pi/dist/index.js.map +1 -0
- package/node_modules/remote-pi/dist/mcp/mesh_result.d.ts +10 -0
- package/node_modules/remote-pi/dist/mcp/mesh_result.js +42 -0
- package/node_modules/remote-pi/dist/mcp/mesh_result.js.map +1 -0
- package/node_modules/remote-pi/dist/mcp/mesh_server.d.ts +16 -0
- package/node_modules/remote-pi/dist/mcp/mesh_server.js +327 -0
- package/node_modules/remote-pi/dist/mcp/mesh_server.js.map +1 -0
- package/node_modules/remote-pi/dist/mesh/canonical.d.ts +30 -0
- package/node_modules/remote-pi/dist/mesh/canonical.js +61 -0
- package/node_modules/remote-pi/dist/mesh/canonical.js.map +1 -0
- package/node_modules/remote-pi/dist/mesh/client.d.ts +18 -0
- package/node_modules/remote-pi/dist/mesh/client.js +125 -0
- package/node_modules/remote-pi/dist/mesh/client.js.map +1 -0
- package/node_modules/remote-pi/dist/mesh/encoding.d.ts +38 -0
- package/node_modules/remote-pi/dist/mesh/encoding.js +216 -0
- package/node_modules/remote-pi/dist/mesh/encoding.js.map +1 -0
- package/node_modules/remote-pi/dist/mesh/self_revoke.d.ts +73 -0
- package/node_modules/remote-pi/dist/mesh/self_revoke.js +401 -0
- package/node_modules/remote-pi/dist/mesh/self_revoke.js.map +1 -0
- package/node_modules/remote-pi/dist/mesh/siblings.d.ts +49 -0
- package/node_modules/remote-pi/dist/mesh/siblings.js +159 -0
- package/node_modules/remote-pi/dist/mesh/siblings.js.map +1 -0
- package/node_modules/remote-pi/dist/mesh/types.d.ts +34 -0
- package/node_modules/remote-pi/dist/mesh/types.js +11 -0
- package/node_modules/remote-pi/dist/mesh/types.js.map +1 -0
- package/node_modules/remote-pi/dist/mesh/verify.d.ts +17 -0
- package/node_modules/remote-pi/dist/mesh/verify.js +86 -0
- package/node_modules/remote-pi/dist/mesh/verify.js.map +1 -0
- package/node_modules/remote-pi/dist/pairing/crypto.d.ts +8 -0
- package/node_modules/remote-pi/dist/pairing/crypto.js +22 -0
- package/node_modules/remote-pi/dist/pairing/crypto.js.map +1 -0
- package/node_modules/remote-pi/dist/pairing/handshake.d.ts +28 -0
- package/node_modules/remote-pi/dist/pairing/handshake.js +113 -0
- package/node_modules/remote-pi/dist/pairing/handshake.js.map +1 -0
- package/node_modules/remote-pi/dist/pairing/noise-sha256.d.ts +16 -0
- package/node_modules/remote-pi/dist/pairing/noise-sha256.js +103 -0
- package/node_modules/remote-pi/dist/pairing/noise-sha256.js.map +1 -0
- package/node_modules/remote-pi/dist/pairing/qr.d.ts +59 -0
- package/node_modules/remote-pi/dist/pairing/qr.js +125 -0
- package/node_modules/remote-pi/dist/pairing/qr.js.map +1 -0
- package/node_modules/remote-pi/dist/pairing/storage.d.ts +120 -0
- package/node_modules/remote-pi/dist/pairing/storage.js +604 -0
- package/node_modules/remote-pi/dist/pairing/storage.js.map +1 -0
- package/node_modules/remote-pi/dist/protocol/codec.d.ts +7 -0
- package/node_modules/remote-pi/dist/protocol/codec.js +49 -0
- package/node_modules/remote-pi/dist/protocol/codec.js.map +1 -0
- package/node_modules/remote-pi/dist/protocol/types.d.ts +393 -0
- package/node_modules/remote-pi/dist/protocol/types.js +2 -0
- package/node_modules/remote-pi/dist/protocol/types.js.map +1 -0
- package/node_modules/remote-pi/dist/rooms.d.ts +29 -0
- package/node_modules/remote-pi/dist/rooms.js +57 -0
- package/node_modules/remote-pi/dist/rooms.js.map +1 -0
- package/node_modules/remote-pi/dist/session/address.d.ts +49 -0
- package/node_modules/remote-pi/dist/session/address.js +58 -0
- package/node_modules/remote-pi/dist/session/address.js.map +1 -0
- package/node_modules/remote-pi/dist/session/agent_bridge.d.ts +55 -0
- package/node_modules/remote-pi/dist/session/agent_bridge.js +146 -0
- package/node_modules/remote-pi/dist/session/agent_bridge.js.map +1 -0
- package/node_modules/remote-pi/dist/session/bridge.d.ts +37 -0
- package/node_modules/remote-pi/dist/session/bridge.js +130 -0
- package/node_modules/remote-pi/dist/session/bridge.js.map +1 -0
- package/node_modules/remote-pi/dist/session/broker.d.ts +189 -0
- package/node_modules/remote-pi/dist/session/broker.js +507 -0
- package/node_modules/remote-pi/dist/session/broker.js.map +1 -0
- package/node_modules/remote-pi/dist/session/broker_remote.d.ts +74 -0
- package/node_modules/remote-pi/dist/session/broker_remote.js +583 -0
- package/node_modules/remote-pi/dist/session/broker_remote.js.map +1 -0
- package/node_modules/remote-pi/dist/session/cwd_lock.d.ts +33 -0
- package/node_modules/remote-pi/dist/session/cwd_lock.js +126 -0
- package/node_modules/remote-pi/dist/session/cwd_lock.js.map +1 -0
- package/node_modules/remote-pi/dist/session/envelope.d.ts +33 -0
- package/node_modules/remote-pi/dist/session/envelope.js +117 -0
- package/node_modules/remote-pi/dist/session/envelope.js.map +1 -0
- package/node_modules/remote-pi/dist/session/global_config.d.ts +33 -0
- package/node_modules/remote-pi/dist/session/global_config.js +73 -0
- package/node_modules/remote-pi/dist/session/global_config.js.map +1 -0
- package/node_modules/remote-pi/dist/session/ipc.d.ts +27 -0
- package/node_modules/remote-pi/dist/session/ipc.js +22 -0
- package/node_modules/remote-pi/dist/session/ipc.js.map +1 -0
- package/node_modules/remote-pi/dist/session/leader_election.d.ts +32 -0
- package/node_modules/remote-pi/dist/session/leader_election.js +106 -0
- package/node_modules/remote-pi/dist/session/leader_election.js.map +1 -0
- package/node_modules/remote-pi/dist/session/local_config.d.ts +55 -0
- package/node_modules/remote-pi/dist/session/local_config.js +157 -0
- package/node_modules/remote-pi/dist/session/local_config.js.map +1 -0
- package/node_modules/remote-pi/dist/session/mesh_message.d.ts +20 -0
- package/node_modules/remote-pi/dist/session/mesh_message.js +28 -0
- package/node_modules/remote-pi/dist/session/mesh_message.js.map +1 -0
- package/node_modules/remote-pi/dist/session/mesh_node.d.ts +116 -0
- package/node_modules/remote-pi/dist/session/mesh_node.js +573 -0
- package/node_modules/remote-pi/dist/session/mesh_node.js.map +1 -0
- package/node_modules/remote-pi/dist/session/peer.d.ts +139 -0
- package/node_modules/remote-pi/dist/session/peer.js +451 -0
- package/node_modules/remote-pi/dist/session/peer.js.map +1 -0
- package/node_modules/remote-pi/dist/session/peer_inventory.d.ts +13 -0
- package/node_modules/remote-pi/dist/session/peer_inventory.js +48 -0
- package/node_modules/remote-pi/dist/session/peer_inventory.js.map +1 -0
- package/node_modules/remote-pi/dist/session/peer_limits.d.ts +9 -0
- package/node_modules/remote-pi/dist/session/peer_limits.js +21 -0
- package/node_modules/remote-pi/dist/session/peer_limits.js.map +1 -0
- package/node_modules/remote-pi/dist/session/setup_wizard.d.ts +39 -0
- package/node_modules/remote-pi/dist/session/setup_wizard.js +63 -0
- package/node_modules/remote-pi/dist/session/setup_wizard.js.map +1 -0
- package/node_modules/remote-pi/dist/session/tool_gate.d.ts +5 -0
- package/node_modules/remote-pi/dist/session/tool_gate.js +11 -0
- package/node_modules/remote-pi/dist/session/tool_gate.js.map +1 -0
- package/node_modules/remote-pi/dist/session/tools.d.ts +24 -0
- package/node_modules/remote-pi/dist/session/tools.js +252 -0
- package/node_modules/remote-pi/dist/session/tools.js.map +1 -0
- package/node_modules/remote-pi/dist/session/wizard.d.ts +13 -0
- package/node_modules/remote-pi/dist/session/wizard.js +20 -0
- package/node_modules/remote-pi/dist/session/wizard.js.map +1 -0
- package/node_modules/remote-pi/dist/settings.d.ts +15 -0
- package/node_modules/remote-pi/dist/settings.js +52 -0
- package/node_modules/remote-pi/dist/settings.js.map +1 -0
- package/node_modules/remote-pi/dist/transport/peer_channel.d.ts +37 -0
- package/node_modules/remote-pi/dist/transport/peer_channel.js +98 -0
- package/node_modules/remote-pi/dist/transport/peer_channel.js.map +1 -0
- package/node_modules/remote-pi/dist/transport/pi_forward_client.d.ts +29 -0
- package/node_modules/remote-pi/dist/transport/pi_forward_client.js +62 -0
- package/node_modules/remote-pi/dist/transport/pi_forward_client.js.map +1 -0
- package/node_modules/remote-pi/dist/transport/relay_client.d.ts +91 -0
- package/node_modules/remote-pi/dist/transport/relay_client.js +206 -0
- package/node_modules/remote-pi/dist/transport/relay_client.js.map +1 -0
- package/node_modules/remote-pi/dist/ui/footer.d.ts +32 -0
- package/node_modules/remote-pi/dist/ui/footer.js +34 -0
- package/node_modules/remote-pi/dist/ui/footer.js.map +1 -0
- package/node_modules/remote-pi/docs/daemon.md +289 -0
- package/node_modules/remote-pi/package.json +88 -0
- package/node_modules/remote-pi/service-templates/launchd.plist.template +35 -0
- package/node_modules/remote-pi/service-templates/systemd.service.template +19 -0
- package/node_modules/remote-pi/service-templates/task-launcher.vbs.template +10 -0
- package/node_modules/remote-pi/service-templates/task-scheduler.xml.template +38 -0
- package/node_modules/remote-pi/skills/agent-network/SKILL.md +310 -0
- package/package.json +37 -12
- package/node_modules/@herbertgao/pi-cc-extensions/extensions/renderer/tool-diff/write-display-utils.ts +0 -29
- /package/node_modules/@herbertgao/pi-cc-extensions/extensions/feature/{session-reference-core.ts → reference/session.ts} +0 -0
- /package/node_modules/@herbertgao/pi-cc-extensions/extensions/feature/{pi-aliases.ts → shell/aliases.ts} +0 -0
- /package/node_modules/@herbertgao/pi-cc-extensions/extensions/renderer/{tool-diff → tool/diff}/ATTRIBUTION.md +0 -0
- /package/node_modules/@herbertgao/pi-cc-extensions/extensions/renderer/{tool-diff → tool/diff}/diff-presentation.ts +0 -0
- /package/node_modules/@herbertgao/pi-cc-extensions/extensions/renderer/{tool-diff → tool/diff}/index.ts +0 -0
- /package/node_modules/@herbertgao/pi-cc-extensions/extensions/renderer/{tool-diff → tool/diff}/render-utils.ts +0 -0
- /package/node_modules/@herbertgao/pi-cc-extensions/extensions/renderer/{tool-diff → tool/diff}/shiki-highlight.ts +0 -0
- /package/node_modules/@herbertgao/pi-cc-extensions/extensions/renderer/{tool-diff → tool/diff}/types.ts +0 -0
|
@@ -0,0 +1,144 @@
|
|
|
1
|
+
import { visibleWidth } from "@earendil-works/pi-tui";
|
|
2
|
+
import { isCompactAssistantComponent } from "../compact-mode.ts";
|
|
3
|
+
import { ToolGroupComponent } from "../tool/grouping.ts";
|
|
4
|
+
import { isToolExecutionComponent, stripTerminalSequencesPreservingLayout } from "./packets.ts";
|
|
5
|
+
import { getScrollButtonWidget } from "./scroll.ts";
|
|
6
|
+
|
|
7
|
+
export type ComponentRowHit = {
|
|
8
|
+
component: any;
|
|
9
|
+
row: number;
|
|
10
|
+
/** 内部工具命中时所属的展开 group;普通卡点击仍折叠整个 group。 */
|
|
11
|
+
group?: ToolGroupComponent;
|
|
12
|
+
};
|
|
13
|
+
|
|
14
|
+
/** 行内 [click to show more] 提示的命中列区间(1-based,含两端)。 */
|
|
15
|
+
export function collapsedHintHitbox(line: string): { startCol: number; endCol: number } | null {
|
|
16
|
+
const plain = stripTerminalSequencesPreservingLayout(line);
|
|
17
|
+
const match = /(\([^()\n]* \/ click\)|click to show more|to show more)(?=\)?\s*$)/.exec(plain);
|
|
18
|
+
if (!match?.[1]) return null;
|
|
19
|
+
const startCol = visibleWidth(plain.slice(0, match.index)) + 1;
|
|
20
|
+
return { startCol, endCol: startCol + visibleWidth(match[1]) - 1 };
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
/** 布局树点查询:返回 (x,y) 处最深含行 leaf box(屏幕行 → 组件局部行)。 */
|
|
24
|
+
export function fullscreenLeafAt(
|
|
25
|
+
layout: any,
|
|
26
|
+
x: number,
|
|
27
|
+
y: number,
|
|
28
|
+
): { box: any; localRow: number } | null {
|
|
29
|
+
const root = layout?.root;
|
|
30
|
+
if (!root) return null;
|
|
31
|
+
let best: { box: any; localRow: number } | null = null;
|
|
32
|
+
let bestDepth = -1;
|
|
33
|
+
const visit = (box: any, depth: number) => {
|
|
34
|
+
if (!box) return;
|
|
35
|
+
const clip = box.clip;
|
|
36
|
+
if (!clip || x < clip.x || x >= clip.x + clip.width || y < clip.y || y >= clip.y + clip.height)
|
|
37
|
+
return;
|
|
38
|
+
const isLeaf = !Array.isArray(box.children) || box.children.length === 0;
|
|
39
|
+
if (
|
|
40
|
+
isLeaf &&
|
|
41
|
+
y >= box.rect.y &&
|
|
42
|
+
y < box.rect.y + Math.max(1, box.rect.height) &&
|
|
43
|
+
depth > bestDepth
|
|
44
|
+
) {
|
|
45
|
+
best = { box, localRow: Math.max(0, y - box.rect.y) };
|
|
46
|
+
bestDepth = depth;
|
|
47
|
+
}
|
|
48
|
+
for (const child of box.children ?? []) visit(child, depth + 1);
|
|
49
|
+
};
|
|
50
|
+
visit(root, 0);
|
|
51
|
+
return best;
|
|
52
|
+
}
|
|
53
|
+
|
|
54
|
+
/** leaf 自身不带 scrollView;内容宽度由最近的 scroll 祖先决定。 */
|
|
55
|
+
export function fullscreenContentWidth(box: any, terminalWidth: number): number {
|
|
56
|
+
for (let current = box; current; current = current.parent) {
|
|
57
|
+
if (typeof current.scrollView?.getContentWidth === "function") {
|
|
58
|
+
return Math.max(1, current.scrollView.getContentWidth(terminalWidth));
|
|
59
|
+
}
|
|
60
|
+
}
|
|
61
|
+
return terminalWidth;
|
|
62
|
+
}
|
|
63
|
+
|
|
64
|
+
/** 点击列是否为官方滚动条列(放行官方拖动)。 */
|
|
65
|
+
export function isScrollbarColumnAt(layout: any, x: number): boolean {
|
|
66
|
+
let hit = false;
|
|
67
|
+
const visit = (box: any) => {
|
|
68
|
+
if (hit || !box) return;
|
|
69
|
+
if (box.scrollView?.isScrollbarVisible && x === box.rect.x + box.rect.width - 1) {
|
|
70
|
+
hit = true;
|
|
71
|
+
return;
|
|
72
|
+
}
|
|
73
|
+
for (const child of box.children ?? []) visit(child);
|
|
74
|
+
};
|
|
75
|
+
visit(layout?.root);
|
|
76
|
+
return hit;
|
|
77
|
+
}
|
|
78
|
+
|
|
79
|
+
/**
|
|
80
|
+
* 布局 leaf box 的组件通常是容器(documentContainer/dock 容器等),工具卡与
|
|
81
|
+
* widget 在其 children 内。按局部行遍历组件树,定位实际命中的子组件。
|
|
82
|
+
*/
|
|
83
|
+
export function componentAtLocalRow(
|
|
84
|
+
component: any,
|
|
85
|
+
localRow: number,
|
|
86
|
+
width: number,
|
|
87
|
+
): ComponentRowHit | null {
|
|
88
|
+
if (component instanceof ToolGroupComponent) {
|
|
89
|
+
// 展开的 group:头两行(空行 + 头行)归 group,其余行映射到内部工具。
|
|
90
|
+
const child = component.childAtRow(localRow, width);
|
|
91
|
+
return child ? { ...child, group: component } : { component, row: localRow };
|
|
92
|
+
}
|
|
93
|
+
if (isToolExecutionComponent(component)) {
|
|
94
|
+
return { component, row: localRow };
|
|
95
|
+
}
|
|
96
|
+
if (isCompactAssistantComponent(component)) {
|
|
97
|
+
// compact 摘要行整体作为可展开卡片(折叠摘要 / 展开内容)。
|
|
98
|
+
return { component, row: localRow };
|
|
99
|
+
}
|
|
100
|
+
if (component === getScrollButtonWidget()) {
|
|
101
|
+
return { component, row: localRow };
|
|
102
|
+
}
|
|
103
|
+
if (!Array.isArray(component.children)) return null;
|
|
104
|
+
let offset = 0;
|
|
105
|
+
for (const child of component.children) {
|
|
106
|
+
let lines: string[] = [];
|
|
107
|
+
try {
|
|
108
|
+
const rendered = child.render?.(width);
|
|
109
|
+
if (Array.isArray(rendered)) lines = rendered.map((line) => String(line));
|
|
110
|
+
} catch {
|
|
111
|
+
lines = [];
|
|
112
|
+
}
|
|
113
|
+
if (localRow < offset + lines.length) {
|
|
114
|
+
return (
|
|
115
|
+
componentAtLocalRow(child, localRow - offset, width) ?? {
|
|
116
|
+
component: child,
|
|
117
|
+
row: localRow - offset,
|
|
118
|
+
}
|
|
119
|
+
);
|
|
120
|
+
}
|
|
121
|
+
offset += lines.length;
|
|
122
|
+
}
|
|
123
|
+
return null;
|
|
124
|
+
}
|
|
125
|
+
|
|
126
|
+
/** fullscreen single-expand:group 作为整体,不继续递归其内部工具。 */
|
|
127
|
+
export function collectFullscreenToolCards(
|
|
128
|
+
component: any,
|
|
129
|
+
out: any[],
|
|
130
|
+
seen = new Set<any>(),
|
|
131
|
+
): void {
|
|
132
|
+
if (!component || typeof component !== "object" || seen.has(component)) return;
|
|
133
|
+
seen.add(component);
|
|
134
|
+
if (
|
|
135
|
+
isToolExecutionComponent(component) ||
|
|
136
|
+
component instanceof ToolGroupComponent ||
|
|
137
|
+
isCompactAssistantComponent(component)
|
|
138
|
+
) {
|
|
139
|
+
out.push(component);
|
|
140
|
+
return;
|
|
141
|
+
}
|
|
142
|
+
if (!Array.isArray(component.children)) return;
|
|
143
|
+
for (const child of component.children) collectFullscreenToolCards(child, out, seen);
|
|
144
|
+
}
|
|
@@ -0,0 +1,143 @@
|
|
|
1
|
+
import type { ExpandedToolIoView, ToolIoSection } from "../tool/result.ts";
|
|
2
|
+
|
|
3
|
+
/** SGR 鼠标协议包(code;col;row + M/m 终结符)。 */
|
|
4
|
+
export type SgrMousePacket = {
|
|
5
|
+
code: number;
|
|
6
|
+
col: number;
|
|
7
|
+
row: number;
|
|
8
|
+
final: "M" | "m";
|
|
9
|
+
};
|
|
10
|
+
|
|
11
|
+
/** Final painted placement of one outermost tool/group row after parent layout. */
|
|
12
|
+
export type FrameToolPlacement = {
|
|
13
|
+
component: any;
|
|
14
|
+
componentRow: number;
|
|
15
|
+
lineIndex: number;
|
|
16
|
+
/** Marker-stripped final line text as painted after parent layout. */
|
|
17
|
+
finalLine: string;
|
|
18
|
+
view?: ExpandedToolIoView;
|
|
19
|
+
section?: ToolIoSection;
|
|
20
|
+
};
|
|
21
|
+
|
|
22
|
+
/** Zero-width APC row marker (like pi CURSOR_MARKER); stripped before terminal output. */
|
|
23
|
+
const TOOL_FRAME_MARKER_RE = /\x1b_cc:t(\d+):(\d+)\x07/g;
|
|
24
|
+
const TOOL_VIEW_MARKER_RE = /\x1b_cc:v(\d+):([io])\x07/g;
|
|
25
|
+
export const toolFrameMarker = (id: number, row: number) => `\x1b_cc:t${id}:${row}\x07`;
|
|
26
|
+
|
|
27
|
+
/**
|
|
28
|
+
* 解析整段终端输入为 SGR 鼠标包序列;数据必须完全由连续 SGR 包组成
|
|
29
|
+
* (夹杂其他字节返回 null,交由常规输入链处理)。
|
|
30
|
+
*/
|
|
31
|
+
export function parseSgrMousePackets(data: string): SgrMousePacket[] | null {
|
|
32
|
+
const pattern = /\x1b\[<(\d+);(\d+);(\d+)([Mm])/g;
|
|
33
|
+
const packets: SgrMousePacket[] = [];
|
|
34
|
+
let offset = 0;
|
|
35
|
+
|
|
36
|
+
for (const match of data.matchAll(pattern)) {
|
|
37
|
+
if (match.index !== offset) return null;
|
|
38
|
+
offset = match.index + match[0].length;
|
|
39
|
+
packets.push({
|
|
40
|
+
code: Number(match[1]),
|
|
41
|
+
col: Number(match[2]),
|
|
42
|
+
row: Number(match[3]),
|
|
43
|
+
final: match[4] as "M" | "m",
|
|
44
|
+
});
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
return packets.length > 0 && offset === data.length ? packets : null;
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
/** 是否为左键按下(排除修饰键、32 表示 motion 事件)。 */
|
|
51
|
+
export function isSgrLeftPress(packet: SgrMousePacket): boolean {
|
|
52
|
+
const baseButton = packet.code & ~(4 | 8 | 16 | 32);
|
|
53
|
+
return packet.final === "M" && baseButton === 0 && (packet.code & 32) === 0;
|
|
54
|
+
}
|
|
55
|
+
|
|
56
|
+
/** 仅剥离终端序列、保留原布局(换行/空白不动),用于命中区间计算。 */
|
|
57
|
+
export function stripTerminalSequencesPreservingLayout(value: string): string {
|
|
58
|
+
return value
|
|
59
|
+
.replace(/\x1b\][^\x07]*(?:\x07|\x1b\\)/g, "")
|
|
60
|
+
.replace(/\x1b\[[0-?]*[ -/]*[@-~]/g, "");
|
|
61
|
+
}
|
|
62
|
+
|
|
63
|
+
/** 剥离终端序列并折叠空白(用于纯文本比较)。 */
|
|
64
|
+
export function stripTerminalSequences(value: string): string {
|
|
65
|
+
return stripTerminalSequencesPreservingLayout(value).replace(/\s+/g, " ").trim();
|
|
66
|
+
}
|
|
67
|
+
|
|
68
|
+
/** 工具执行组件识别(toolCallId + setExpanded + render)。 */
|
|
69
|
+
export function isToolExecutionComponent(value: any): boolean {
|
|
70
|
+
return Boolean(
|
|
71
|
+
value &&
|
|
72
|
+
typeof value === "object" &&
|
|
73
|
+
typeof value.toolCallId === "string" &&
|
|
74
|
+
typeof value.setExpanded === "function" &&
|
|
75
|
+
typeof value.render === "function",
|
|
76
|
+
);
|
|
77
|
+
}
|
|
78
|
+
|
|
79
|
+
/** 深度收集组件树中的工具执行组件(含 getMountedRoots 分支)。 */
|
|
80
|
+
export function collectToolComponents(component: any, tools: any[], seen = new Set<any>()): void {
|
|
81
|
+
if (!component || typeof component !== "object" || seen.has(component)) return;
|
|
82
|
+
seen.add(component);
|
|
83
|
+
if (isToolExecutionComponent(component)) {
|
|
84
|
+
tools.push(component);
|
|
85
|
+
return;
|
|
86
|
+
}
|
|
87
|
+
if (Array.isArray(component.children)) {
|
|
88
|
+
for (const child of component.children) collectToolComponents(child, tools, seen);
|
|
89
|
+
}
|
|
90
|
+
try {
|
|
91
|
+
const mounted = component.getMountedRoots?.();
|
|
92
|
+
if (Array.isArray(mounted)) {
|
|
93
|
+
for (const root of mounted) collectToolComponents(root, tools, seen);
|
|
94
|
+
}
|
|
95
|
+
} catch {
|
|
96
|
+
// renderer 切换中的惰性 Proxy 可能暂时没有 mounted roots。
|
|
97
|
+
}
|
|
98
|
+
}
|
|
99
|
+
|
|
100
|
+
/** 剥离一行中的零宽帧/视图 marker。 */
|
|
101
|
+
export function stripToolFrameMarkers(line: string): string {
|
|
102
|
+
return line.replace(TOOL_FRAME_MARKER_RE, "").replace(TOOL_VIEW_MARKER_RE, "");
|
|
103
|
+
}
|
|
104
|
+
|
|
105
|
+
/**
|
|
106
|
+
* 从渲染行中提取工具帧 placement(component/componentRow/lineIndex/finalLine
|
|
107
|
+
* 及其所属视图与 section),同时返回剥离 marker 后的行。
|
|
108
|
+
*/
|
|
109
|
+
export function extractToolFramePlacements(
|
|
110
|
+
lines: string[],
|
|
111
|
+
idToComponent: Map<number, any>,
|
|
112
|
+
idToView: Map<number, ExpandedToolIoView>,
|
|
113
|
+
): { lines: string[]; placements: FrameToolPlacement[] } {
|
|
114
|
+
const placements: FrameToolPlacement[] = [];
|
|
115
|
+
const cleaned = lines.map((line, lineIndex) => {
|
|
116
|
+
const toolMatches = [...line.matchAll(TOOL_FRAME_MARKER_RE)];
|
|
117
|
+
const viewMatches = [...line.matchAll(TOOL_VIEW_MARKER_RE)];
|
|
118
|
+
const finalLine = stripToolFrameMarkers(line);
|
|
119
|
+
let view: ExpandedToolIoView | undefined;
|
|
120
|
+
let section: ToolIoSection | undefined;
|
|
121
|
+
for (const match of viewMatches) {
|
|
122
|
+
const candidate = idToView.get(Number(match[1]));
|
|
123
|
+
if (!candidate) continue;
|
|
124
|
+
view = candidate;
|
|
125
|
+
section = match[2] === "i" ? "input" : "output";
|
|
126
|
+
break;
|
|
127
|
+
}
|
|
128
|
+
for (const match of toolMatches) {
|
|
129
|
+
const component = idToComponent.get(Number(match[1]));
|
|
130
|
+
if (!component) continue;
|
|
131
|
+
placements.push({
|
|
132
|
+
component,
|
|
133
|
+
componentRow: Number(match[2]),
|
|
134
|
+
lineIndex,
|
|
135
|
+
finalLine,
|
|
136
|
+
view,
|
|
137
|
+
section,
|
|
138
|
+
});
|
|
139
|
+
}
|
|
140
|
+
return finalLine;
|
|
141
|
+
});
|
|
142
|
+
return { lines: cleaned, placements };
|
|
143
|
+
}
|
|
@@ -0,0 +1,195 @@
|
|
|
1
|
+
import {
|
|
2
|
+
getKeybindings,
|
|
3
|
+
matchesKey,
|
|
4
|
+
truncateToWidth,
|
|
5
|
+
visibleWidth,
|
|
6
|
+
type Keybinding,
|
|
7
|
+
} from "@earendil-works/pi-tui";
|
|
8
|
+
import { config } from "../../config/config.ts";
|
|
9
|
+
import { isLazyProxyTui } from "../../utils/fullscreen-detect.ts";
|
|
10
|
+
import { parseSgrMousePackets } from "./packets.ts";
|
|
11
|
+
|
|
12
|
+
const ZENTUI_PAGE_UP_INPUT = /^\x1b\[5;9(?::[12])?~$|^\x1b\[57421;9(?::[12])?u$|^\x1b\[1;6A$/;
|
|
13
|
+
const ZENTUI_PAGE_DOWN_INPUT = /^\x1b\[6;9(?::[12])?~$|^\x1b\[57422;9(?::[12])?u$|^\x1b\[1;6B$/;
|
|
14
|
+
const SCROLL_BOTTOM_SHORTCUT = "ctrl+end";
|
|
15
|
+
|
|
16
|
+
/**
|
|
17
|
+
* 当前安装的 tui 宿主。宿主放本模块(滚动按钮/调度依赖它),
|
|
18
|
+
* 由 mouse-interaction 经 setToolMouseTui 维护;跨模块一律经绑定/setter 访问。
|
|
19
|
+
*
|
|
20
|
+
* 状态镜像到 globalThis(Symbol 槽):jiti 转译下经 re-export 链读取的
|
|
21
|
+
* 模块级 let 绑定是初始值快照(死绑定,实测恒 null),函数调用才是活引用。
|
|
22
|
+
* 跨模块读取一律用 getToolMouseTui(),避免拿到加载时的快照。
|
|
23
|
+
*/
|
|
24
|
+
const TOOL_MOUSE_TUI_SLOT = Symbol.for("pi.ccstyle.tool-mouse-tui");
|
|
25
|
+
(globalThis as any)[TOOL_MOUSE_TUI_SLOT] ??= null;
|
|
26
|
+
export function getToolMouseTui(): any {
|
|
27
|
+
return (globalThis as any)[TOOL_MOUSE_TUI_SLOT];
|
|
28
|
+
}
|
|
29
|
+
export function setToolMouseTui(tui: any): void {
|
|
30
|
+
(globalThis as any)[TOOL_MOUSE_TUI_SLOT] = tui;
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
// 滚动按钮状态同 toolMouseTui:镜像到 globalThis(Symbol 槽),跨模块读取
|
|
34
|
+
// 一律用 getter(jiti 转译下模块级 let 绑定是初始值快照)。
|
|
35
|
+
const SCROLL_BUTTON_STATE_SLOT = Symbol.for("pi.ccstyle.scroll-button-state");
|
|
36
|
+
type ScrollButtonState = { visible: boolean; hovered: boolean; widget: any };
|
|
37
|
+
function scrollButtonState(): ScrollButtonState {
|
|
38
|
+
const host = globalThis as any;
|
|
39
|
+
return (host[SCROLL_BUTTON_STATE_SLOT] ??= { visible: false, hovered: false, widget: null });
|
|
40
|
+
}
|
|
41
|
+
export function getScrollButtonVisible(): boolean {
|
|
42
|
+
return scrollButtonState().visible;
|
|
43
|
+
}
|
|
44
|
+
export function getScrollButtonHovered(): boolean {
|
|
45
|
+
return scrollButtonState().hovered;
|
|
46
|
+
}
|
|
47
|
+
export function getScrollButtonWidget(): any {
|
|
48
|
+
return scrollButtonState().widget;
|
|
49
|
+
}
|
|
50
|
+
export function setScrollButtonVisible(visible: boolean): void {
|
|
51
|
+
scrollButtonState().visible = visible;
|
|
52
|
+
}
|
|
53
|
+
|
|
54
|
+
/** 返回是否发生变化(调用方据此决定是否需要重渲染)。 */
|
|
55
|
+
export function setScrollButtonHovered(hovered: boolean): boolean {
|
|
56
|
+
if (hovered === scrollButtonState().hovered) return false;
|
|
57
|
+
scrollButtonState().hovered = hovered;
|
|
58
|
+
return true;
|
|
59
|
+
}
|
|
60
|
+
|
|
61
|
+
export function setScrollButtonWidget(widget: any): void {
|
|
62
|
+
scrollButtonState().widget = widget;
|
|
63
|
+
}
|
|
64
|
+
|
|
65
|
+
/** teardown 全量清零(visible/hovered/widget/sync 调度)。 */
|
|
66
|
+
export function resetScrollButtonState(): void {
|
|
67
|
+
scrollButtonState().visible = false;
|
|
68
|
+
scrollButtonState().hovered = false;
|
|
69
|
+
scrollButtonState().widget = null;
|
|
70
|
+
scrollButtonSyncScheduled = false;
|
|
71
|
+
}
|
|
72
|
+
|
|
73
|
+
let scrollButtonSyncScheduled = false;
|
|
74
|
+
|
|
75
|
+
export function toolMouseInteractionActive(): boolean {
|
|
76
|
+
if (config.mode === "off") return false;
|
|
77
|
+
if (isLazyProxyTui(getToolMouseTui())) return true;
|
|
78
|
+
return true;
|
|
79
|
+
}
|
|
80
|
+
|
|
81
|
+
/** 惰性 Proxy 官方 fullscreen(TuiAltScreen)判定。 */
|
|
82
|
+
export function fullscreenLazyTui(tui: any): boolean {
|
|
83
|
+
return isLazyProxyTui(tui) && tui.mode === "fullscreen";
|
|
84
|
+
}
|
|
85
|
+
|
|
86
|
+
/** 官方 fullscreen:是否已跟随 transcript 底部(按钮隐藏条件)。 */
|
|
87
|
+
export function isFullscreenAtBottom(tui: any): boolean {
|
|
88
|
+
const following = tui.isFollowingOutput ?? tui.getPrimaryScrollView?.()?.isFollowingEnd ?? true;
|
|
89
|
+
return Boolean(following);
|
|
90
|
+
}
|
|
91
|
+
|
|
92
|
+
function formatShortcut(shortcut: string): string {
|
|
93
|
+
return shortcut
|
|
94
|
+
.split("+")
|
|
95
|
+
.map((part) =>
|
|
96
|
+
part.length <= 1 ? part.toUpperCase() : `${part[0]?.toUpperCase() ?? ""}${part.slice(1)}`,
|
|
97
|
+
)
|
|
98
|
+
.join("+");
|
|
99
|
+
}
|
|
100
|
+
|
|
101
|
+
export function isScrollBottomInput(data: string): boolean {
|
|
102
|
+
return matchesKey(data, SCROLL_BOTTOM_SHORTCUT);
|
|
103
|
+
}
|
|
104
|
+
|
|
105
|
+
function isScrollNavigationInput(data: string): boolean {
|
|
106
|
+
if (
|
|
107
|
+
matchesKey(data, "pageUp") ||
|
|
108
|
+
matchesKey(data, "pageDown") ||
|
|
109
|
+
ZENTUI_PAGE_UP_INPUT.test(data) ||
|
|
110
|
+
ZENTUI_PAGE_DOWN_INPUT.test(data) ||
|
|
111
|
+
// 官方 fullscreen viewport 的可滚动键(half-page/prompt/top/bottom)。
|
|
112
|
+
[
|
|
113
|
+
"tui.altScreen.pageUp",
|
|
114
|
+
"tui.altScreen.pageDown",
|
|
115
|
+
"tui.altScreen.halfPageUp",
|
|
116
|
+
"tui.altScreen.halfPageDown",
|
|
117
|
+
"tui.altScreen.previousPrompt",
|
|
118
|
+
"tui.altScreen.nextPrompt",
|
|
119
|
+
"tui.altScreen.top",
|
|
120
|
+
"tui.altScreen.bottom",
|
|
121
|
+
].some((key) => getKeybindings().matches(data, key as Keybinding))
|
|
122
|
+
) {
|
|
123
|
+
return true;
|
|
124
|
+
}
|
|
125
|
+
const packets = parseSgrMousePackets(data);
|
|
126
|
+
return Boolean(
|
|
127
|
+
packets?.some((packet) => {
|
|
128
|
+
const baseButton = packet.code & ~(4 | 8 | 16 | 32);
|
|
129
|
+
return packet.final === "M" && (baseButton === 64 || baseButton === 65);
|
|
130
|
+
}),
|
|
131
|
+
);
|
|
132
|
+
}
|
|
133
|
+
|
|
134
|
+
function isAtTranscriptBottom(tui: any): boolean {
|
|
135
|
+
// 惰性 Proxy fullscreen:官方 viewport 以 isFollowingOutput 判定是否在底部。
|
|
136
|
+
if (fullscreenLazyTui(tui)) return isFullscreenAtBottom(tui);
|
|
137
|
+
return true;
|
|
138
|
+
}
|
|
139
|
+
|
|
140
|
+
export function hideScrollButton(tui: any): void {
|
|
141
|
+
const changed = getScrollButtonVisible() || getScrollButtonHovered();
|
|
142
|
+
setScrollButtonVisible(false);
|
|
143
|
+
setScrollButtonHovered(false);
|
|
144
|
+
if (changed) tui.requestRender?.();
|
|
145
|
+
}
|
|
146
|
+
|
|
147
|
+
export function scheduleScrollButtonSync(tui: any, data: string): void {
|
|
148
|
+
if (
|
|
149
|
+
!fullscreenLazyTui(tui) ||
|
|
150
|
+
!toolMouseInteractionActive() ||
|
|
151
|
+
!isScrollNavigationInput(data) ||
|
|
152
|
+
scrollButtonSyncScheduled
|
|
153
|
+
)
|
|
154
|
+
return;
|
|
155
|
+
scrollButtonSyncScheduled = true;
|
|
156
|
+
const previousLines = tui.previousLines;
|
|
157
|
+
const check = (attempt: number) => {
|
|
158
|
+
scrollButtonSyncScheduled = false;
|
|
159
|
+
if (getToolMouseTui() !== tui) return;
|
|
160
|
+
// Pi renders on its own frame timer. Inspect the resulting viewport before
|
|
161
|
+
// showing the button so empty or non-scrollable transcripts never flash it.
|
|
162
|
+
const rendered = tui.previousLines !== previousLines;
|
|
163
|
+
// fullscreen 下 isFollowingOutput 是即时状态,无需等待官方帧渲染。
|
|
164
|
+
if (!rendered && attempt < 4 && !fullscreenLazyTui(tui)) {
|
|
165
|
+
scrollButtonSyncScheduled = true;
|
|
166
|
+
const timer = setTimeout(() => check(attempt + 1), 16);
|
|
167
|
+
if (typeof timer === "object" && timer !== null && "unref" in timer) {
|
|
168
|
+
(timer as { unref: () => void }).unref();
|
|
169
|
+
}
|
|
170
|
+
return;
|
|
171
|
+
}
|
|
172
|
+
const nextVisible = !isAtTranscriptBottom(tui);
|
|
173
|
+
if (nextVisible !== getScrollButtonVisible()) {
|
|
174
|
+
setScrollButtonVisible(nextVisible);
|
|
175
|
+
tui.requestRender?.();
|
|
176
|
+
}
|
|
177
|
+
};
|
|
178
|
+
process.nextTick(() => check(0));
|
|
179
|
+
}
|
|
180
|
+
|
|
181
|
+
export function updateScrollButtonFromInput(tui: any, data: string): void {
|
|
182
|
+
if (!fullscreenLazyTui(tui) || !toolMouseInteractionActive()) return;
|
|
183
|
+
if (matchesKey(data, "enter") || matchesKey(data, "return")) hideScrollButton(tui);
|
|
184
|
+
}
|
|
185
|
+
|
|
186
|
+
export function renderScrollButton(width: number, theme: any): string[] {
|
|
187
|
+
if (!getScrollButtonVisible() || !fullscreenLazyTui(getToolMouseTui())) return [];
|
|
188
|
+
const shortcut = formatShortcut(SCROLL_BOTTOM_SHORTCUT);
|
|
189
|
+
const label = theme.fg(
|
|
190
|
+
getScrollButtonHovered() ? "text" : "accent",
|
|
191
|
+
`[ ↓ Back to bottom · ${shortcut} ]`,
|
|
192
|
+
);
|
|
193
|
+
const leftPad = Math.max(0, Math.floor((width - visibleWidth(label)) / 2));
|
|
194
|
+
return [`${" ".repeat(leftPad)}${truncateToWidth(label, width, "…")}`];
|
|
195
|
+
}
|
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
const ANSI_SGR_PATTERN = /\x1b\[([0-9;]*)m/g;
|
|
2
|
+
const ANSI_SGR_WITH_COLON_PATTERN = /\x1b\[([0-9;:]*)m/g;
|
|
2
3
|
const STYLE_RESET_PARAMS = [39, 22, 23, 24, 25, 27, 28, 29, 59] as const;
|
|
3
4
|
|
|
4
5
|
export { ANSI_SGR_PATTERN, STYLE_RESET_PARAMS };
|
|
@@ -108,6 +109,60 @@ export function filterSgrSequences(text: string, filter: (params: number[]) => n
|
|
|
108
109
|
});
|
|
109
110
|
}
|
|
110
111
|
|
|
112
|
+
function isValidColonForeground(segment: string): boolean {
|
|
113
|
+
const params = segment.split(":");
|
|
114
|
+
const isByte = (value: string | undefined) =>
|
|
115
|
+
value !== undefined && /^\d+$/.test(value) && Number(value) <= 255;
|
|
116
|
+
if (params[0] !== "38") return false;
|
|
117
|
+
if (params[1] === "5") return params.length === 3 && isByte(params[2]);
|
|
118
|
+
return (
|
|
119
|
+
params[1] === "2" &&
|
|
120
|
+
params.length === 6 &&
|
|
121
|
+
(params[2] === "" || /^\d+$/.test(params[2] ?? "")) &&
|
|
122
|
+
params.slice(3).every(isByte)
|
|
123
|
+
);
|
|
124
|
+
}
|
|
125
|
+
|
|
126
|
+
function sanitizeColonSgr(rawParams: string): string {
|
|
127
|
+
const segments = rawParams.split(";");
|
|
128
|
+
const sanitized: string[] = [];
|
|
129
|
+
for (let index = 0; index < segments.length; index++) {
|
|
130
|
+
const segment = segments[index] ?? "";
|
|
131
|
+
if (segment.includes(":")) {
|
|
132
|
+
const code = Number.parseInt(segment, 10);
|
|
133
|
+
if (code !== 48 && (code !== 38 || isValidColonForeground(segment))) {
|
|
134
|
+
sanitized.push(segment);
|
|
135
|
+
}
|
|
136
|
+
continue;
|
|
137
|
+
}
|
|
138
|
+
const param = Number.parseInt(segment, 10);
|
|
139
|
+
if (!Number.isFinite(param)) continue;
|
|
140
|
+
if (param === 0) {
|
|
141
|
+
sanitized.push(...STYLE_RESET_PARAMS.map(String));
|
|
142
|
+
continue;
|
|
143
|
+
}
|
|
144
|
+
if (param === 49 || (param >= 40 && param <= 47) || (param >= 100 && param <= 107)) {
|
|
145
|
+
continue;
|
|
146
|
+
}
|
|
147
|
+
if (param === 38 || param === 48) {
|
|
148
|
+
const mode = Number.parseInt(segments[index + 1] ?? "", 10);
|
|
149
|
+
const advance = mode === 5 ? 2 : mode === 2 ? 4 : 0;
|
|
150
|
+
if (advance > 0) {
|
|
151
|
+
if (param === 38) sanitized.push(...segments.slice(index, index + advance + 1));
|
|
152
|
+
index += advance;
|
|
153
|
+
continue;
|
|
154
|
+
}
|
|
155
|
+
}
|
|
156
|
+
sanitized.push(segment);
|
|
157
|
+
}
|
|
158
|
+
return sanitized.length > 0 ? `\x1b[${sanitized.join(";")}m` : "";
|
|
159
|
+
}
|
|
160
|
+
|
|
111
161
|
export function sanitizeAnsiForThemedOutput(text: string): string {
|
|
112
|
-
|
|
162
|
+
if (!text || !text.includes("\x1b[")) return text;
|
|
163
|
+
return text.replace(ANSI_SGR_WITH_COLON_PATTERN, (sequence, rawParams: string) =>
|
|
164
|
+
rawParams.includes(":")
|
|
165
|
+
? sanitizeColonSgr(rawParams)
|
|
166
|
+
: filterSgrSequences(sequence, stripBackgroundSgrParams),
|
|
167
|
+
);
|
|
113
168
|
}
|
|
@@ -30,11 +30,11 @@ import {
|
|
|
30
30
|
resolveDiffPresentationMode,
|
|
31
31
|
type DiffPresentationMode,
|
|
32
32
|
} from "./diff-presentation.ts";
|
|
33
|
-
import { sanitizeToolResultText } from "
|
|
33
|
+
import { sanitizeToolResultText } from "../../../utils/tool-result-sanitize.ts";
|
|
34
34
|
import { pluralize, sanitizeAnsiForThemedOutput } from "./render-utils.ts";
|
|
35
35
|
import { splitWriteContentLines } from "./write-display-utils.ts";
|
|
36
36
|
import { MAX_HL_CHARS, shikiHighlightCache } from "./shiki-highlight.ts";
|
|
37
|
-
import { showMoreHintText } from "
|
|
37
|
+
import { showMoreHintText } from "../../show-more-hint.ts";
|
|
38
38
|
import {
|
|
39
39
|
DEFAULT_TOOL_DISPLAY_CONFIG,
|
|
40
40
|
type DiffIndicatorMode,
|
|
@@ -2653,7 +2653,7 @@ export function renderEditDiffResult(
|
|
|
2653
2653
|
return cache.set(safeWidth, options.expanded, mode, configKey, hovered, clampedLines);
|
|
2654
2654
|
},
|
|
2655
2655
|
invalidate: cache.invalidate,
|
|
2656
|
-
};
|
|
2656
|
+
} as Component;
|
|
2657
2657
|
}
|
|
2658
2658
|
|
|
2659
2659
|
function renderWriteHeader(
|
|
@@ -3079,5 +3079,5 @@ export function renderWriteDiffResult(
|
|
|
3079
3079
|
return cache.set(safeWidth, options.expanded, mode, configKey, hovered, finalLines);
|
|
3080
3080
|
},
|
|
3081
3081
|
invalidate: cache.invalidate,
|
|
3082
|
-
};
|
|
3082
|
+
} as Component;
|
|
3083
3083
|
}
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { normalizeDiffRenderWidth } from "./diff-presentation.ts";
|
|
2
2
|
import { pluralize } from "./render-utils.ts";
|
|
3
|
-
import { showMoreHintText } from "
|
|
3
|
+
import { showMoreHintText } from "../../show-more-hint.ts";
|
|
4
4
|
|
|
5
5
|
export interface WidthMeasurementOps {
|
|
6
6
|
measure(text: string): number;
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
export function splitWriteContentLines(content: string): string[] {
|
|
2
|
+
if (!content) {
|
|
3
|
+
return [];
|
|
4
|
+
}
|
|
5
|
+
|
|
6
|
+
const normalized = content.replace(/\r\n?/g, "\n");
|
|
7
|
+
const lines = normalized.split("\n");
|
|
8
|
+
if (lines.length > 0 && lines[lines.length - 1] === "") {
|
|
9
|
+
lines.pop();
|
|
10
|
+
}
|
|
11
|
+
return lines;
|
|
12
|
+
}
|
|
@@ -94,13 +94,12 @@ export async function executeWriteWithMetadata(
|
|
|
94
94
|
await mkdir(dirname(absolutePath), { recursive: true });
|
|
95
95
|
throwIfAborted();
|
|
96
96
|
await writeFile(absolutePath, params.content, "utf8");
|
|
97
|
-
throwIfAborted();
|
|
98
97
|
store.set(toolCallId, metadata);
|
|
99
98
|
return {
|
|
100
99
|
content: [
|
|
101
100
|
{
|
|
102
101
|
type: "text",
|
|
103
|
-
text: `Successfully wrote ${params.content
|
|
102
|
+
text: `Successfully wrote ${Buffer.byteLength(params.content, "utf8")} bytes to ${params.path}`,
|
|
104
103
|
},
|
|
105
104
|
],
|
|
106
105
|
details: undefined,
|
|
@@ -1,8 +1,14 @@
|
|
|
1
1
|
import { AssistantMessageComponent, ToolExecutionComponent } from "@earendil-works/pi-coding-agent";
|
|
2
|
-
import {
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
2
|
+
import {
|
|
3
|
+
Container,
|
|
4
|
+
Spacer,
|
|
5
|
+
truncateToWidth,
|
|
6
|
+
visibleWidth,
|
|
7
|
+
type Component,
|
|
8
|
+
} from "@earendil-works/pi-tui";
|
|
9
|
+
import { TOOL_LOADING_INTERVAL_MS, toolLoadingIcon } from "../../utils/tool-loading-icon.ts";
|
|
10
|
+
import { sanitizeToolResultText } from "../../utils/tool-result-sanitize.ts";
|
|
11
|
+
import { showMoreHintText } from "../show-more-hint.ts";
|
|
6
12
|
|
|
7
13
|
const PATCH_KEY = Symbol.for("pi.ccstyle.tool-grouping-patch");
|
|
8
14
|
const PARENT_KEY = Symbol.for("pi.ccstyle.tool-grouping-parent");
|
|
@@ -95,7 +101,7 @@ function stripLeadingStatusIcon(line: string): string {
|
|
|
95
101
|
);
|
|
96
102
|
}
|
|
97
103
|
|
|
98
|
-
function stripBackgroundAnsi(line: string): string {
|
|
104
|
+
export function stripBackgroundAnsi(line: string): string {
|
|
99
105
|
return line.replace(/\x1b\[(?:4[0-9]|10[0-7]|48(?:(?:;|:)[0-9]+)+|49)m/g, "");
|
|
100
106
|
}
|
|
101
107
|
|
|
@@ -120,15 +126,25 @@ function stripLeadingSpaces(line: string, count: number): string {
|
|
|
120
126
|
return ansi + line.slice(offset);
|
|
121
127
|
}
|
|
122
128
|
|
|
123
|
-
|
|
129
|
+
/** 生成一行铺满 width 的 slot 背景行;bgAnsiOverride 可替换背景 ANSI(用于提亮等)。 */
|
|
130
|
+
export function paddedBackgroundRow(
|
|
131
|
+
theme: any,
|
|
132
|
+
slot: string,
|
|
133
|
+
content: string,
|
|
134
|
+
width: number,
|
|
135
|
+
bgAnsiOverride?: string,
|
|
136
|
+
): string {
|
|
124
137
|
const innerWidth = Math.max(0, width - 2);
|
|
125
138
|
const clipped = truncateToWidth(stripBackgroundAnsi(content), innerWidth, "");
|
|
126
139
|
const row = ` ${clipped}${" ".repeat(Math.max(0, innerWidth - visibleWidth(clipped)))} `;
|
|
127
|
-
if (typeof theme?.bg !== "function") return row;
|
|
128
140
|
const bgAnsi =
|
|
129
|
-
|
|
141
|
+
bgAnsiOverride ||
|
|
142
|
+
(typeof theme?.bg === "function"
|
|
143
|
+
? theme.getBgAnsi?.(slot) || theme.bg(slot, "").match(/^\x1b\[[0-?]*[ -/]*[@-~]/)?.[0] || ""
|
|
144
|
+
: "");
|
|
130
145
|
const stable = bgAnsi ? row.replace(/\x1b\[(?:0)?m/g, (reset) => reset + bgAnsi) : row;
|
|
131
|
-
return theme.bg(slot, stable);
|
|
146
|
+
if (!bgAnsi) return typeof theme?.bg === "function" ? theme.bg(slot, stable) : row;
|
|
147
|
+
return `${bgAnsi}${stable}\x1b[49m`;
|
|
132
148
|
}
|
|
133
149
|
|
|
134
150
|
function oneLine(value: unknown, max = 96): string {
|
|
@@ -285,7 +301,8 @@ export class ToolGroupComponent extends Container {
|
|
|
285
301
|
|
|
286
302
|
setExpanded(expanded: boolean): void {
|
|
287
303
|
this._expanded = expanded;
|
|
288
|
-
for (const tool of this.children)
|
|
304
|
+
for (const tool of this.children)
|
|
305
|
+
(tool as Component & { setExpanded?: (expanded: boolean) => void }).setExpanded?.(expanded);
|
|
289
306
|
}
|
|
290
307
|
|
|
291
308
|
setHintHovered(hovered: boolean): void {
|