@herbertgao/pi-extensions 2026.8.2 → 2026.8.4
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 +50 -2
- package/examples/pi-footer.json +275 -0
- package/node_modules/@herbertgao/pi-cc-extensions/README.en.md +6 -8
- package/node_modules/@herbertgao/pi-cc-extensions/README.md +5 -7
- 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 +5 -3
- 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} +2 -6
- 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 +379 -85
- 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 +65 -775
- package/node_modules/@herbertgao/pi-cc-extensions/extensions/{feature → renderer}/markdown-enhance.ts +35 -31
- package/node_modules/@herbertgao/pi-cc-extensions/extensions/renderer/{mouse-hover.ts → mouse/hover.ts} +5 -5
- package/node_modules/@herbertgao/pi-cc-extensions/extensions/renderer/{mouse-interaction.ts → mouse/interaction.ts} +34 -35
- package/node_modules/@herbertgao/pi-cc-extensions/extensions/renderer/{mouse-layout.ts → mouse/layout.ts} +5 -21
- package/node_modules/@herbertgao/pi-cc-extensions/extensions/renderer/{mouse-packets.ts → mouse/packets.ts} +1 -1
- package/node_modules/@herbertgao/pi-cc-extensions/extensions/renderer/{mouse-scroll.ts → mouse/scroll.ts} +48 -37
- 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 +2 -2
- 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} +18 -8
- 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/utils/fullscreen-detect.ts +0 -27
- package/node_modules/@herbertgao/pi-cc-extensions/package.json +3 -3
- package/node_modules/@herbertgao/pi-subagents/CHANGELOG.md +6 -0
- package/node_modules/@herbertgao/pi-subagents/package.json +2 -2
- 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/index.ts +33 -35
- 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/pi-footer/CHANGELOG.md +145 -0
- package/node_modules/pi-footer/LICENSE +21 -0
- package/node_modules/pi-footer/README.md +354 -0
- package/node_modules/pi-footer/package.json +68 -0
- package/node_modules/pi-footer/src/cache.ts +106 -0
- package/node_modules/pi-footer/src/colors.ts +237 -0
- package/node_modules/pi-footer/src/config.ts +202 -0
- package/node_modules/pi-footer/src/event-widgets.ts +41 -0
- package/node_modules/pi-footer/src/extension-statuses.ts +102 -0
- package/node_modules/pi-footer/src/git.ts +135 -0
- package/node_modules/pi-footer/src/index.ts +268 -0
- package/node_modules/pi-footer/src/metrics.ts +141 -0
- package/node_modules/pi-footer/src/presets.ts +383 -0
- package/node_modules/pi-footer/src/render.ts +114 -0
- package/node_modules/pi-footer/src/separators.ts +52 -0
- package/node_modules/pi-footer/src/types.ts +122 -0
- package/node_modules/pi-footer/src/ui/color-level-confirm.ts +22 -0
- package/node_modules/pi-footer/src/ui/color-options.ts +195 -0
- package/node_modules/pi-footer/src/ui/config-lifecycle.ts +61 -0
- package/node_modules/pi-footer/src/ui/edit-colors.ts +13 -0
- package/node_modules/pi-footer/src/ui/events.ts +35 -0
- package/node_modules/pi-footer/src/ui/extension-status-picker.ts +60 -0
- package/node_modules/pi-footer/src/ui/extension-statuses.ts +73 -0
- package/node_modules/pi-footer/src/ui/fields.ts +252 -0
- package/node_modules/pi-footer/src/ui/global-menu.ts +126 -0
- package/node_modules/pi-footer/src/ui/helpers.ts +44 -0
- package/node_modules/pi-footer/src/ui/layout.ts +17 -0
- package/node_modules/pi-footer/src/ui/line-list.ts +19 -0
- package/node_modules/pi-footer/src/ui/model.ts +64 -0
- package/node_modules/pi-footer/src/ui/navigation.ts +29 -0
- package/node_modules/pi-footer/src/ui/option-edit.ts +93 -0
- package/node_modules/pi-footer/src/ui/overlay-render.ts +103 -0
- package/node_modules/pi-footer/src/ui/screen-context.ts +18 -0
- package/node_modules/pi-footer/src/ui/screen-controller.ts +27 -0
- package/node_modules/pi-footer/src/ui/screen-render.ts +32 -0
- package/node_modules/pi-footer/src/ui/screen-state.ts +20 -0
- package/node_modules/pi-footer/src/ui/screen.ts +243 -0
- package/node_modules/pi-footer/src/ui/screens/add-widget.ts +92 -0
- package/node_modules/pi-footer/src/ui/screens/confirm-exit.ts +52 -0
- package/node_modules/pi-footer/src/ui/screens/controller.ts +12 -0
- package/node_modules/pi-footer/src/ui/screens/edit-colors.ts +68 -0
- package/node_modules/pi-footer/src/ui/screens/edit-widget.ts +115 -0
- package/node_modules/pi-footer/src/ui/screens/extension-status-row.ts +61 -0
- package/node_modules/pi-footer/src/ui/screens/global.ts +75 -0
- package/node_modules/pi-footer/src/ui/screens/line-list.ts +108 -0
- package/node_modules/pi-footer/src/ui/screens/main.ts +99 -0
- package/node_modules/pi-footer/src/ui/screens/terminal.ts +121 -0
- package/node_modules/pi-footer/src/ui/screens/widget-list.ts +154 -0
- package/node_modules/pi-footer/src/ui/terminal-menu.ts +32 -0
- package/node_modules/pi-footer/src/ui/theme.ts +48 -0
- package/node_modules/pi-footer/src/ui/title-bar.ts +100 -0
- package/node_modules/pi-footer/src/ui/widget-actions.ts +76 -0
- package/node_modules/pi-footer/src/ui.ts +66 -0
- package/node_modules/pi-footer/src/widgets/context.ts +28 -0
- package/node_modules/pi-footer/src/widgets/core/active-tools.ts +17 -0
- package/node_modules/pi-footer/src/widgets/core/context-window.ts +24 -0
- package/node_modules/pi-footer/src/widgets/core/cwd-basename.ts +19 -0
- package/node_modules/pi-footer/src/widgets/core/cwd.ts +108 -0
- package/node_modules/pi-footer/src/widgets/core/event.ts +34 -0
- package/node_modules/pi-footer/src/widgets/core/external-status.ts +102 -0
- package/node_modules/pi-footer/src/widgets/core/model-provider.ts +20 -0
- package/node_modules/pi-footer/src/widgets/core/model.ts +35 -0
- package/node_modules/pi-footer/src/widgets/core/provider.ts +17 -0
- package/node_modules/pi-footer/src/widgets/core/session-name.ts +17 -0
- package/node_modules/pi-footer/src/widgets/core/text-verbosity.ts +17 -0
- package/node_modules/pi-footer/src/widgets/core/thinking-level.ts +17 -0
- package/node_modules/pi-footer/src/widgets/git/ahead-behind.ts +17 -0
- package/node_modules/pi-footer/src/widgets/git/branch.ts +81 -0
- package/node_modules/pi-footer/src/widgets/git/clean.ts +19 -0
- package/node_modules/pi-footer/src/widgets/git/deletions.ts +17 -0
- package/node_modules/pi-footer/src/widgets/git/diff.ts +38 -0
- package/node_modules/pi-footer/src/widgets/git/insertions.ts +17 -0
- package/node_modules/pi-footer/src/widgets/git/remote.ts +17 -0
- package/node_modules/pi-footer/src/widgets/git/root.ts +17 -0
- package/node_modules/pi-footer/src/widgets/git/sha.ts +17 -0
- package/node_modules/pi-footer/src/widgets/git/staged.ts +17 -0
- package/node_modules/pi-footer/src/widgets/git/status.ts +19 -0
- package/node_modules/pi-footer/src/widgets/git/unstaged.ts +17 -0
- package/node_modules/pi-footer/src/widgets/git/untracked.ts +17 -0
- package/node_modules/pi-footer/src/widgets/instance.ts +118 -0
- package/node_modules/pi-footer/src/widgets/layout/custom-text.ts +18 -0
- package/node_modules/pi-footer/src/widgets/layout/flex-separator.ts +32 -0
- package/node_modules/pi-footer/src/widgets/layout/separator.ts +57 -0
- package/node_modules/pi-footer/src/widgets/layout/spacer.ts +31 -0
- package/node_modules/pi-footer/src/widgets/options.ts +122 -0
- package/node_modules/pi-footer/src/widgets/project/runtime.ts +361 -0
- package/node_modules/pi-footer/src/widgets/registry.ts +223 -0
- package/node_modules/pi-footer/src/widgets/session/assistant-messages.ts +17 -0
- package/node_modules/pi-footer/src/widgets/session/compactions.ts +17 -0
- package/node_modules/pi-footer/src/widgets/session/elapsed.ts +18 -0
- package/node_modules/pi-footer/src/widgets/session/last-activity.ts +18 -0
- package/node_modules/pi-footer/src/widgets/session/messages.ts +19 -0
- package/node_modules/pi-footer/src/widgets/session/session-id.ts +17 -0
- package/node_modules/pi-footer/src/widgets/session/session-start.ts +18 -0
- package/node_modules/pi-footer/src/widgets/session/tool-results.ts +17 -0
- package/node_modules/pi-footer/src/widgets/session/total-messages.ts +19 -0
- package/node_modules/pi-footer/src/widgets/session/total-time.ts +18 -0
- package/node_modules/pi-footer/src/widgets/session/user-messages.ts +17 -0
- package/node_modules/pi-footer/src/widgets/store.ts +26 -0
- package/node_modules/pi-footer/src/widgets/tokens/cache-hit-rate.ts +55 -0
- package/node_modules/pi-footer/src/widgets/tokens/cache-read.ts +18 -0
- package/node_modules/pi-footer/src/widgets/tokens/cache-write.ts +18 -0
- package/node_modules/pi-footer/src/widgets/tokens/context-bar.ts +108 -0
- package/node_modules/pi-footer/src/widgets/tokens/context-length.ts +26 -0
- package/node_modules/pi-footer/src/widgets/tokens/context-remaining.ts +29 -0
- package/node_modules/pi-footer/src/widgets/tokens/context.ts +29 -0
- package/node_modules/pi-footer/src/widgets/tokens/cost.ts +51 -0
- package/node_modules/pi-footer/src/widgets/tokens/input-speed.ts +25 -0
- package/node_modules/pi-footer/src/widgets/tokens/input-tokens.ts +18 -0
- package/node_modules/pi-footer/src/widgets/tokens/output-speed.ts +25 -0
- package/node_modules/pi-footer/src/widgets/tokens/output-tokens.ts +18 -0
- package/node_modules/pi-footer/src/widgets/tokens/tokens.ts +20 -0
- package/node_modules/pi-footer/src/widgets/tokens/total-speed.ts +25 -0
- package/node_modules/pi-footer/src/widgets/tokens/total-tokens.ts +18 -0
- package/node_modules/pi-footer/src/widgets/types.ts +181 -0
- package/node_modules/pi-footer/src/widgets/utils/colors.ts +11 -0
- package/node_modules/pi-footer/src/widgets/utils/context.ts +112 -0
- package/node_modules/pi-footer/src/widgets/utils/session.ts +19 -0
- package/node_modules/pi-footer/src/widgets/utils/token-format.ts +78 -0
- package/node_modules/pi-mcp-adapter/CHANGELOG.md +19 -0
- package/node_modules/pi-mcp-adapter/README.md +19 -4
- package/node_modules/pi-mcp-adapter/agent-dir.ts +40 -0
- package/node_modules/pi-mcp-adapter/commands.ts +12 -2
- package/node_modules/pi-mcp-adapter/direct-tools.ts +6 -8
- package/node_modules/pi-mcp-adapter/index.ts +15 -3
- package/node_modules/pi-mcp-adapter/mcp-auth-flow.ts +87 -4
- package/node_modules/pi-mcp-adapter/mcp-callback-server.ts +138 -61
- package/node_modules/pi-mcp-adapter/mcp-oauth-provider.ts +43 -4
- package/node_modules/pi-mcp-adapter/oauth.ts +48 -0
- package/node_modules/pi-mcp-adapter/package.json +8 -2
- package/node_modules/pi-mcp-adapter/proxy-modes.ts +8 -10
- package/node_modules/pi-mcp-adapter/tool-registrar.ts +187 -3
- package/node_modules/pi-mcp-adapter/types.ts +2 -0
- 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 +25 -10
- 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,18 @@
|
|
|
1
|
+
import { defineWidget } from "../types.js";
|
|
2
|
+
import { formatTokenCount, tokenFormatStyleProperty } from "../utils/token-format.js";
|
|
3
|
+
|
|
4
|
+
export const OutputTokensWidget = defineWidget({
|
|
5
|
+
type: "output-tokens",
|
|
6
|
+
label: "Output Tokens",
|
|
7
|
+
category: "Tokens",
|
|
8
|
+
description: "Output token total",
|
|
9
|
+
dependencies: ["metrics"],
|
|
10
|
+
baseOptions: ["raw", "hideWhenZero", "icon"],
|
|
11
|
+
baseOptionDefaults: {},
|
|
12
|
+
properties: [tokenFormatStyleProperty()],
|
|
13
|
+
icons: { emoji: "⬇️", nerd: "", text: "out" },
|
|
14
|
+
defaultStyle: { fg: "white", bg: "default", bold: false },
|
|
15
|
+
render({ ctx, options, renderWidget }) {
|
|
16
|
+
return renderWidget(formatTokenCount(ctx.metrics.outputTokens, options.tokenFormatStyle));
|
|
17
|
+
},
|
|
18
|
+
});
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
import { defineWidget } from "../types.js";
|
|
2
|
+
import { formatTokenCount, tokenFormatStyleProperty } from "../utils/token-format.js";
|
|
3
|
+
|
|
4
|
+
export const TokensWidget = defineWidget({
|
|
5
|
+
type: "tokens",
|
|
6
|
+
label: "Input/Output Tokens",
|
|
7
|
+
category: "Tokens",
|
|
8
|
+
description: "Input and output token totals",
|
|
9
|
+
dependencies: ["metrics"],
|
|
10
|
+
baseOptions: ["raw", "icon"],
|
|
11
|
+
baseOptionDefaults: {},
|
|
12
|
+
properties: [tokenFormatStyleProperty()],
|
|
13
|
+
icons: { emoji: "🔢", nerd: "", text: "tok" },
|
|
14
|
+
defaultStyle: { fg: "cyan", bg: "default", bold: false },
|
|
15
|
+
render({ ctx, options, renderWidget }) {
|
|
16
|
+
return renderWidget(
|
|
17
|
+
`↑${formatTokenCount(ctx.metrics.inputTokens, options.tokenFormatStyle)} ↓${formatTokenCount(ctx.metrics.outputTokens, options.tokenFormatStyle)}`,
|
|
18
|
+
);
|
|
19
|
+
},
|
|
20
|
+
});
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
import { defineWidget } from "../types.js";
|
|
2
|
+
import { formatTokenSpeed, tokenFormatStyleProperty } from "../utils/token-format.js";
|
|
3
|
+
|
|
4
|
+
export const TotalSpeedWidget = defineWidget({
|
|
5
|
+
type: "total-speed",
|
|
6
|
+
label: "Total Speed",
|
|
7
|
+
category: "Tokens",
|
|
8
|
+
description: "Average total tokens per minute",
|
|
9
|
+
dependencies: ["metrics"],
|
|
10
|
+
baseOptions: ["raw", "hideWhenZero", "icon"],
|
|
11
|
+
baseOptionDefaults: {},
|
|
12
|
+
properties: [tokenFormatStyleProperty()],
|
|
13
|
+
icons: { emoji: "⚡", nerd: "↕", text: "tok/min" },
|
|
14
|
+
defaultStyle: { fg: "brightGreen", bg: "default", bold: false },
|
|
15
|
+
render({ ctx, options, renderWidget }) {
|
|
16
|
+
return renderWidget(
|
|
17
|
+
formatTokenSpeed(
|
|
18
|
+
ctx.metrics.totalTokens,
|
|
19
|
+
ctx.metrics.firstTimestampMs,
|
|
20
|
+
ctx.metrics.lastTimestampMs,
|
|
21
|
+
options.tokenFormatStyle,
|
|
22
|
+
),
|
|
23
|
+
);
|
|
24
|
+
},
|
|
25
|
+
});
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
import { defineWidget } from "../types.js";
|
|
2
|
+
import { formatTokenCount, tokenFormatStyleProperty } from "../utils/token-format.js";
|
|
3
|
+
|
|
4
|
+
export const TotalTokensWidget = defineWidget({
|
|
5
|
+
type: "total-tokens",
|
|
6
|
+
label: "Total Tokens",
|
|
7
|
+
category: "Tokens",
|
|
8
|
+
description: "Total token count",
|
|
9
|
+
dependencies: ["metrics"],
|
|
10
|
+
baseOptions: ["raw", "hideWhenZero", "icon"],
|
|
11
|
+
baseOptionDefaults: {},
|
|
12
|
+
properties: [tokenFormatStyleProperty()],
|
|
13
|
+
icons: { emoji: "🔢", nerd: "", text: "tok" },
|
|
14
|
+
defaultStyle: { fg: "cyan", bg: "default", bold: false },
|
|
15
|
+
render({ ctx, options, renderWidget }) {
|
|
16
|
+
return renderWidget(formatTokenCount(ctx.metrics.totalTokens, options.tokenFormatStyle));
|
|
17
|
+
},
|
|
18
|
+
});
|
|
@@ -0,0 +1,181 @@
|
|
|
1
|
+
import type { Theme } from "@earendil-works/pi-coding-agent";
|
|
2
|
+
|
|
3
|
+
import type { ColorLevel } from "../colors.js";
|
|
4
|
+
import type { GetExtensionStatuses } from "../extension-statuses.js";
|
|
5
|
+
import type {
|
|
6
|
+
IconMode,
|
|
7
|
+
StatuslineData,
|
|
8
|
+
WidgetEntry,
|
|
9
|
+
WidgetOptions,
|
|
10
|
+
WidgetStyle,
|
|
11
|
+
} from "../types.js";
|
|
12
|
+
|
|
13
|
+
export interface WidgetIconSet {
|
|
14
|
+
emoji: string;
|
|
15
|
+
nerd: string;
|
|
16
|
+
text: string;
|
|
17
|
+
}
|
|
18
|
+
|
|
19
|
+
export type PropertyKind = "boolean" | "number" | "choice" | "text";
|
|
20
|
+
|
|
21
|
+
export interface ChoiceOption<TId extends string = string> {
|
|
22
|
+
id: TId;
|
|
23
|
+
label: string;
|
|
24
|
+
list: string;
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
export type WidgetPropertyDefault = string | number | boolean;
|
|
28
|
+
|
|
29
|
+
// Edit-action discriminant for properties that open a dedicated editor flow. Extend as needed.
|
|
30
|
+
export type WidgetEditAction = "external-status-key";
|
|
31
|
+
|
|
32
|
+
export interface WidgetProperty {
|
|
33
|
+
id: string;
|
|
34
|
+
label: string;
|
|
35
|
+
kind: PropertyKind;
|
|
36
|
+
description: string;
|
|
37
|
+
default: WidgetPropertyDefault;
|
|
38
|
+
showWhen?: {
|
|
39
|
+
property: string;
|
|
40
|
+
equals: string | number | boolean;
|
|
41
|
+
};
|
|
42
|
+
options?: {
|
|
43
|
+
min?: number;
|
|
44
|
+
max?: number;
|
|
45
|
+
choices?: readonly ChoiceOption[];
|
|
46
|
+
label?: string;
|
|
47
|
+
showInFields?: boolean;
|
|
48
|
+
showInWidgets?: boolean;
|
|
49
|
+
showInColors?: boolean;
|
|
50
|
+
listProperty?: string;
|
|
51
|
+
quoteValue?: boolean;
|
|
52
|
+
editAction?: WidgetEditAction;
|
|
53
|
+
};
|
|
54
|
+
}
|
|
55
|
+
|
|
56
|
+
export type WidgetBaseOption = "raw" | "hideWhenEmpty" | "hideWhenZero" | "text" | "icon";
|
|
57
|
+
|
|
58
|
+
export interface WidgetRenderOptions extends WidgetStyle {
|
|
59
|
+
icons?: WidgetIconSet;
|
|
60
|
+
preservedTrimStyles?: string;
|
|
61
|
+
stripIncomingStyles?: boolean;
|
|
62
|
+
}
|
|
63
|
+
|
|
64
|
+
// The widget dependency set is the materialized snapshot (StatuslineData) plus the one live
|
|
65
|
+
// accessor that must never enter the snapshot — see F1 / pi live-accessor rule.
|
|
66
|
+
export type WidgetDependencyValues = StatuslineData & {
|
|
67
|
+
getExtensionStatuses: GetExtensionStatuses | undefined;
|
|
68
|
+
};
|
|
69
|
+
|
|
70
|
+
export type WidgetDependency = keyof WidgetDependencyValues;
|
|
71
|
+
|
|
72
|
+
export interface BaseWidgetContext {
|
|
73
|
+
iconMode: IconMode;
|
|
74
|
+
minimalist: boolean;
|
|
75
|
+
colorLevel: ColorLevel;
|
|
76
|
+
theme?: Theme;
|
|
77
|
+
requestRender?: () => void;
|
|
78
|
+
}
|
|
79
|
+
|
|
80
|
+
export type WidgetContext<TDeps extends readonly WidgetDependency[] = readonly []> =
|
|
81
|
+
BaseWidgetContext & Pick<WidgetDependencyValues, TDeps[number]>;
|
|
82
|
+
|
|
83
|
+
export type WidgetInstanceOptions<TOptions extends object> = WidgetOptions & TOptions;
|
|
84
|
+
|
|
85
|
+
export interface Widget<TOptions extends object = {}> {
|
|
86
|
+
readonly entry: WidgetEntry;
|
|
87
|
+
readonly id: string;
|
|
88
|
+
readonly type: WidgetEntry["type"];
|
|
89
|
+
enabled: boolean;
|
|
90
|
+
options: WidgetInstanceOptions<TOptions>;
|
|
91
|
+
|
|
92
|
+
render(ctx: WidgetContext): string | undefined;
|
|
93
|
+
toggle(enabled?: boolean): void;
|
|
94
|
+
update(options: Partial<WidgetInstanceOptions<TOptions>>): void;
|
|
95
|
+
toEntry(): WidgetEntry;
|
|
96
|
+
}
|
|
97
|
+
|
|
98
|
+
type BaseOptionsToObject<TBaseOptions extends readonly WidgetBaseOption[]> = Required<
|
|
99
|
+
Pick<WidgetOptions, TBaseOptions[number]>
|
|
100
|
+
>;
|
|
101
|
+
|
|
102
|
+
type WidgetChoiceValue<TProperty> = TProperty extends {
|
|
103
|
+
readonly kind: "choice";
|
|
104
|
+
readonly options: { readonly choices: readonly (infer TChoice)[] };
|
|
105
|
+
}
|
|
106
|
+
? TChoice extends { readonly id: infer TId extends string }
|
|
107
|
+
? TId
|
|
108
|
+
: string
|
|
109
|
+
: string;
|
|
110
|
+
|
|
111
|
+
type WidgetPropertyValue<TProperty extends Pick<WidgetProperty, "kind">> =
|
|
112
|
+
TProperty["kind"] extends "boolean"
|
|
113
|
+
? boolean
|
|
114
|
+
: TProperty["kind"] extends "number"
|
|
115
|
+
? number
|
|
116
|
+
: TProperty["kind"] extends "choice"
|
|
117
|
+
? WidgetChoiceValue<TProperty>
|
|
118
|
+
: string;
|
|
119
|
+
|
|
120
|
+
type PropertiesToObject<TProperties extends readonly WidgetProperty[]> = {
|
|
121
|
+
[TProperty in TProperties[number] as TProperty["id"]]: WidgetPropertyValue<TProperty>;
|
|
122
|
+
};
|
|
123
|
+
|
|
124
|
+
export type OptionsFor<TSpec extends Pick<WidgetSpec, "baseOptions" | "properties">> =
|
|
125
|
+
WidgetOptions &
|
|
126
|
+
BaseOptionsToObject<TSpec["baseOptions"]> &
|
|
127
|
+
PropertiesToObject<TSpec["properties"]> &
|
|
128
|
+
WidgetStyle;
|
|
129
|
+
|
|
130
|
+
export type ContextFor<TSpec extends Pick<WidgetSpec, "dependencies">> = BaseWidgetContext &
|
|
131
|
+
Pick<WidgetDependencyValues, TSpec["dependencies"][number]>;
|
|
132
|
+
|
|
133
|
+
export interface TypedWidgetRenderArgs<
|
|
134
|
+
TSpec extends Pick<WidgetSpec, "dependencies" | "baseOptions" | "properties">,
|
|
135
|
+
> {
|
|
136
|
+
readonly ctx: ContextFor<TSpec>;
|
|
137
|
+
readonly options: OptionsFor<TSpec>;
|
|
138
|
+
readonly renderWidget: (
|
|
139
|
+
value: string | undefined,
|
|
140
|
+
renderOptions?: WidgetRenderOptions,
|
|
141
|
+
) => string | undefined;
|
|
142
|
+
}
|
|
143
|
+
|
|
144
|
+
export interface WidgetSpec<
|
|
145
|
+
TType extends string = string,
|
|
146
|
+
TCategory extends string = string,
|
|
147
|
+
TDependencies extends readonly WidgetDependency[] = readonly WidgetDependency[],
|
|
148
|
+
TBaseOptions extends readonly WidgetBaseOption[] = readonly WidgetBaseOption[],
|
|
149
|
+
TProperties extends readonly WidgetProperty[] = readonly WidgetProperty[],
|
|
150
|
+
> {
|
|
151
|
+
readonly type: TType;
|
|
152
|
+
readonly label: string;
|
|
153
|
+
readonly category: TCategory;
|
|
154
|
+
readonly description: string;
|
|
155
|
+
readonly dependencies: TDependencies;
|
|
156
|
+
readonly baseOptions: TBaseOptions;
|
|
157
|
+
readonly baseOptionDefaults?: Partial<WidgetOptions>;
|
|
158
|
+
readonly properties: TProperties;
|
|
159
|
+
readonly icons: WidgetIconSet;
|
|
160
|
+
readonly defaultStyle: WidgetStyle;
|
|
161
|
+
readonly createOptionDefaults?: () => Partial<WidgetOptions>;
|
|
162
|
+
render(
|
|
163
|
+
args: TypedWidgetRenderArgs<{
|
|
164
|
+
readonly dependencies: TDependencies;
|
|
165
|
+
readonly baseOptions: TBaseOptions;
|
|
166
|
+
readonly properties: TProperties;
|
|
167
|
+
}>,
|
|
168
|
+
): string | undefined;
|
|
169
|
+
}
|
|
170
|
+
|
|
171
|
+
export function defineWidget<
|
|
172
|
+
const TType extends string,
|
|
173
|
+
const TCategory extends string,
|
|
174
|
+
const TDependencies extends readonly WidgetDependency[],
|
|
175
|
+
const TBaseOptions extends readonly WidgetBaseOption[],
|
|
176
|
+
const TProperties extends readonly WidgetProperty[],
|
|
177
|
+
>(
|
|
178
|
+
spec: WidgetSpec<TType, TCategory, TDependencies, TBaseOptions, TProperties>,
|
|
179
|
+
): WidgetSpec<TType, TCategory, TDependencies, TBaseOptions, TProperties> {
|
|
180
|
+
return spec;
|
|
181
|
+
}
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
import type { ColorName } from "../../colors.js";
|
|
2
|
+
|
|
3
|
+
export function colorPair(
|
|
4
|
+
fg: ColorName | undefined,
|
|
5
|
+
bg: ColorName | undefined,
|
|
6
|
+
): { fg?: ColorName; bg?: ColorName } {
|
|
7
|
+
return {
|
|
8
|
+
...(fg === undefined ? {} : { fg }),
|
|
9
|
+
...(bg === undefined ? {} : { bg }),
|
|
10
|
+
};
|
|
11
|
+
}
|
|
@@ -0,0 +1,112 @@
|
|
|
1
|
+
import { normalizeColor, type ConditionalColorFields } from "../../colors.js";
|
|
2
|
+
import type { WidgetOptions } from "../../types.js";
|
|
3
|
+
import { colorPair } from "./colors.js";
|
|
4
|
+
|
|
5
|
+
export function contextPercent(tokens: number | undefined, maxTokens: number | undefined) {
|
|
6
|
+
if (tokens === undefined || maxTokens === undefined || maxTokens <= 0) return undefined;
|
|
7
|
+
return Math.min(100, Math.max(0, (tokens / maxTokens) * 100));
|
|
8
|
+
}
|
|
9
|
+
|
|
10
|
+
interface ContextColorOptions extends WidgetOptions, ConditionalColorFields {
|
|
11
|
+
contextConditionalColors: boolean;
|
|
12
|
+
contextWarningPercent: number;
|
|
13
|
+
contextDangerPercent: number;
|
|
14
|
+
}
|
|
15
|
+
|
|
16
|
+
export function contextColors(
|
|
17
|
+
options: ContextColorOptions,
|
|
18
|
+
contextTokens: number | undefined,
|
|
19
|
+
contextMaxTokens: number | undefined,
|
|
20
|
+
) {
|
|
21
|
+
if (!options.contextConditionalColors) return colorPair(options.fg, options.bg);
|
|
22
|
+
const percent = contextPercent(contextTokens, contextMaxTokens);
|
|
23
|
+
if (percent === undefined) return colorPair(options.fg, options.bg);
|
|
24
|
+
|
|
25
|
+
if (percent >= options.contextDangerPercent) {
|
|
26
|
+
return colorPair(
|
|
27
|
+
normalizeColor(options.dangerFg) ?? options.fg,
|
|
28
|
+
normalizeColor(options.dangerBg) ?? options.bg,
|
|
29
|
+
);
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
if (percent >= options.contextWarningPercent) {
|
|
33
|
+
return colorPair(
|
|
34
|
+
normalizeColor(options.warningFg) ?? options.fg,
|
|
35
|
+
normalizeColor(options.warningBg) ?? options.bg,
|
|
36
|
+
);
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
return colorPair(options.fg, options.bg);
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
export function contextColorProperties() {
|
|
43
|
+
return [
|
|
44
|
+
{
|
|
45
|
+
id: "contextConditionalColors",
|
|
46
|
+
label: "Conditional colors",
|
|
47
|
+
kind: "boolean",
|
|
48
|
+
description: "Use warning/danger colors based on context usage",
|
|
49
|
+
default: false,
|
|
50
|
+
options: {
|
|
51
|
+
label: "with-colors",
|
|
52
|
+
showInWidgets: true,
|
|
53
|
+
showInColors: true,
|
|
54
|
+
listProperty: "",
|
|
55
|
+
},
|
|
56
|
+
},
|
|
57
|
+
{
|
|
58
|
+
id: "contextWarningPercent",
|
|
59
|
+
label: "Warning zone threshold",
|
|
60
|
+
kind: "number",
|
|
61
|
+
description: "Context usage percentage for warning colors",
|
|
62
|
+
default: 70,
|
|
63
|
+
showWhen: { property: "contextConditionalColors", equals: true },
|
|
64
|
+
options: { min: 0, max: 100, showInWidgets: false, showInColors: false },
|
|
65
|
+
},
|
|
66
|
+
{
|
|
67
|
+
id: "contextDangerPercent",
|
|
68
|
+
label: "Danger zone threshold",
|
|
69
|
+
kind: "number",
|
|
70
|
+
description: "Context usage percentage for danger colors",
|
|
71
|
+
default: 90,
|
|
72
|
+
showWhen: { property: "contextConditionalColors", equals: true },
|
|
73
|
+
options: { min: 0, max: 100, showInWidgets: false, showInColors: false },
|
|
74
|
+
},
|
|
75
|
+
{
|
|
76
|
+
id: "warningFg",
|
|
77
|
+
label: "Warning foreground",
|
|
78
|
+
kind: "text",
|
|
79
|
+
description: "Warning foreground",
|
|
80
|
+
default: "yellow",
|
|
81
|
+
showWhen: { property: "contextConditionalColors", equals: true },
|
|
82
|
+
options: { showInFields: false, showInWidgets: false, showInColors: false },
|
|
83
|
+
},
|
|
84
|
+
{
|
|
85
|
+
id: "warningBg",
|
|
86
|
+
label: "Warning background",
|
|
87
|
+
kind: "text",
|
|
88
|
+
description: "Warning background",
|
|
89
|
+
default: "default",
|
|
90
|
+
showWhen: { property: "contextConditionalColors", equals: true },
|
|
91
|
+
options: { showInFields: false, showInWidgets: false, showInColors: false },
|
|
92
|
+
},
|
|
93
|
+
{
|
|
94
|
+
id: "dangerFg",
|
|
95
|
+
label: "Danger foreground",
|
|
96
|
+
kind: "text",
|
|
97
|
+
description: "Danger foreground",
|
|
98
|
+
default: "red",
|
|
99
|
+
showWhen: { property: "contextConditionalColors", equals: true },
|
|
100
|
+
options: { showInFields: false, showInWidgets: false, showInColors: false },
|
|
101
|
+
},
|
|
102
|
+
{
|
|
103
|
+
id: "dangerBg",
|
|
104
|
+
label: "Danger background",
|
|
105
|
+
kind: "text",
|
|
106
|
+
description: "Danger background",
|
|
107
|
+
default: "default",
|
|
108
|
+
showWhen: { property: "contextConditionalColors", equals: true },
|
|
109
|
+
options: { showInFields: false, showInWidgets: false, showInColors: false },
|
|
110
|
+
},
|
|
111
|
+
] as const;
|
|
112
|
+
}
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
export function formatTime(timestamp: number | undefined): string {
|
|
2
|
+
if (timestamp === undefined) return "";
|
|
3
|
+
return new Date(timestamp).toLocaleTimeString([], { hour: "2-digit", minute: "2-digit" });
|
|
4
|
+
}
|
|
5
|
+
|
|
6
|
+
function formatDuration(ms: number): string {
|
|
7
|
+
if (!Number.isFinite(ms) || ms <= 0) return "0m";
|
|
8
|
+
const totalMinutes = Math.max(1, Math.floor(ms / 60_000));
|
|
9
|
+
const hours = Math.floor(totalMinutes / 60);
|
|
10
|
+
const minutes = totalMinutes % 60;
|
|
11
|
+
if (hours === 0) return `${minutes}m`;
|
|
12
|
+
return minutes === 0 ? `${hours}h` : `${hours}h ${minutes}m`;
|
|
13
|
+
}
|
|
14
|
+
|
|
15
|
+
export function formatElapsed(first: number | undefined, last: number | undefined): string {
|
|
16
|
+
if (first === undefined) return "0m";
|
|
17
|
+
const end = last === undefined || last < first ? Date.now() : last;
|
|
18
|
+
return formatDuration(end - first);
|
|
19
|
+
}
|
|
@@ -0,0 +1,78 @@
|
|
|
1
|
+
export function formatCount(value: number) {
|
|
2
|
+
if (value < 1000) return `${value}`;
|
|
3
|
+
if (value < 1000000) return `${trimFixed(value / 1000, 1)}k`;
|
|
4
|
+
return `${trimFixed(value / 1000000, 1)}m`;
|
|
5
|
+
}
|
|
6
|
+
|
|
7
|
+
export function formatPiTokenCount(value: number) {
|
|
8
|
+
if (value < 1000) return `${value}`;
|
|
9
|
+
if (value < 10000) return `${(value / 1000).toFixed(1)}k`;
|
|
10
|
+
if (value < 1000000) return `${Math.round(value / 1000)}k`;
|
|
11
|
+
if (value < 10000000) return `${(value / 1000000).toFixed(1)}M`;
|
|
12
|
+
return `${Math.round(value / 1000000)}M`;
|
|
13
|
+
}
|
|
14
|
+
|
|
15
|
+
function trimFixed(value: number, digits: number) {
|
|
16
|
+
return value.toFixed(digits).replace(/\.0$/, "");
|
|
17
|
+
}
|
|
18
|
+
const TOKEN_FORMAT_STYLES = {
|
|
19
|
+
default: {
|
|
20
|
+
label: "Default",
|
|
21
|
+
list: "Default",
|
|
22
|
+
format: formatCount,
|
|
23
|
+
},
|
|
24
|
+
compact: {
|
|
25
|
+
label: "Compact",
|
|
26
|
+
list: "Compact",
|
|
27
|
+
format: formatPiTokenCount,
|
|
28
|
+
},
|
|
29
|
+
} as const;
|
|
30
|
+
|
|
31
|
+
export type TokenFormatStyle = keyof typeof TOKEN_FORMAT_STYLES;
|
|
32
|
+
|
|
33
|
+
const TOKEN_FORMAT_STYLE_VALUES = Object.keys(TOKEN_FORMAT_STYLES) as TokenFormatStyle[];
|
|
34
|
+
|
|
35
|
+
const TOKEN_FORMAT_CHOICES = TOKEN_FORMAT_STYLE_VALUES.map((style) => ({
|
|
36
|
+
id: style,
|
|
37
|
+
label: TOKEN_FORMAT_STYLES[style].label,
|
|
38
|
+
list: TOKEN_FORMAT_STYLES[style].list,
|
|
39
|
+
}));
|
|
40
|
+
|
|
41
|
+
export function formatTokenCount(value: number, style: TokenFormatStyle) {
|
|
42
|
+
return TOKEN_FORMAT_STYLES[style].format(value);
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
export function formatTokenSpeed(
|
|
46
|
+
tokens: number,
|
|
47
|
+
first: number | undefined,
|
|
48
|
+
last: number | undefined,
|
|
49
|
+
tokenFormatStyle: TokenFormatStyle,
|
|
50
|
+
) {
|
|
51
|
+
if (
|
|
52
|
+
first === undefined ||
|
|
53
|
+
last === undefined ||
|
|
54
|
+
!Number.isFinite(first) ||
|
|
55
|
+
!Number.isFinite(last) ||
|
|
56
|
+
last <= first
|
|
57
|
+
) {
|
|
58
|
+
return "0/min";
|
|
59
|
+
}
|
|
60
|
+
const minutes = Math.max((last - first) / 60000, 1 / 60);
|
|
61
|
+
return `${formatTokenCount(Math.round(tokens / minutes), tokenFormatStyle)}/min`;
|
|
62
|
+
}
|
|
63
|
+
|
|
64
|
+
export function tokenFormatStyleProperty() {
|
|
65
|
+
return {
|
|
66
|
+
id: "tokenFormatStyle",
|
|
67
|
+
label: "Token format",
|
|
68
|
+
kind: "choice",
|
|
69
|
+
description: "Token display format",
|
|
70
|
+
default: "default",
|
|
71
|
+
options: {
|
|
72
|
+
choices: TOKEN_FORMAT_CHOICES,
|
|
73
|
+
showInWidgets: true,
|
|
74
|
+
showInColors: false,
|
|
75
|
+
listProperty: "format",
|
|
76
|
+
},
|
|
77
|
+
} as const;
|
|
78
|
+
}
|
|
@@ -7,6 +7,25 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
|
|
|
7
7
|
|
|
8
8
|
## [Unreleased]
|
|
9
9
|
|
|
10
|
+
## [2.23.0] - 2026-08-11
|
|
11
|
+
|
|
12
|
+
### Added
|
|
13
|
+
- Added interactive callback URL pasting to `/mcp-auth` for OAuth flows running on remote or headless machines. Thanks @trevorleibert-mixpanel for PR #330.
|
|
14
|
+
|
|
15
|
+
### Fixed
|
|
16
|
+
- Stopped load-time MCP initialization from printing a TUI startup error when Pi action methods are not bound yet. Thanks @21307369 for issue #327.
|
|
17
|
+
- Kept interactive OAuth authorization URLs clickable as a single terminal hyperlink. Thanks @rfccg for PR #329.
|
|
18
|
+
|
|
19
|
+
## [2.22.0] - 2026-08-11
|
|
20
|
+
|
|
21
|
+
### Added
|
|
22
|
+
- Added the `pi-mcp-adapter/oauth` subpath for URL-bound OAuth token reuse by cooperating Pi extensions. Thanks @ThePhoenixCoding for issue #323.
|
|
23
|
+
- Added `oauth.logoUri` for OAuth Dynamic Client Registration, with validation that requires an absolute HTTP(S) URL. Thanks @grinich for PR #321.
|
|
24
|
+
|
|
25
|
+
### Fixed
|
|
26
|
+
- Materialized binary MCP resources as private temporary files before model-facing output, with bounded per-session cleanup. Thanks @zenworr and @shaworr for PR #324.
|
|
27
|
+
- Named OAuth callback pages and dynamic client registrations after rebranded Pi hosts, while preserving stock Pi defaults and avoiding guessed client homepages. Thanks @grinich for PR #320.
|
|
28
|
+
|
|
10
29
|
## [2.21.2] - 2026-08-09
|
|
11
30
|
|
|
12
31
|
### Fixed
|
|
@@ -153,6 +153,17 @@ A supplied `config` is a complete, isolated snapshot. It is not merged with file
|
|
|
153
153
|
|
|
154
154
|
With `configPath` and no `config`, the adapter keeps normal file merge behavior, and that path takes precedence over argv and `--mcp-config`. The default export keeps the normal file-based behavior. OAuth credentials are stored in the operating system credential store and keyed by the configured server name; URL binding prevents credentials from being accepted for a different server URL. `settings.oauthDir` and `MCP_OAUTH_DIR` are used only as legacy plaintext import locations for older `tokens.json` files, not as credential namespaces. CSRF state and PKCE verifiers are flow-local, so concurrent authorization flows do not share transient secrets.
|
|
155
155
|
|
|
156
|
+
Cooperating Pi extensions can use `pi-mcp-adapter/oauth` to reuse URL-bound OAuth tokens without deep-importing private files:
|
|
157
|
+
|
|
158
|
+
```ts
|
|
159
|
+
import { getMcpOAuthTokensForUrl, updateMcpOAuthTokensForUrl } from "pi-mcp-adapter/oauth";
|
|
160
|
+
|
|
161
|
+
const tokens = await getMcpOAuthTokensForUrl("jira", "https://jira.example.com/mcp");
|
|
162
|
+
updateMcpOAuthTokensForUrl("jira", "https://jira.example.com/mcp", { accessToken: "..." });
|
|
163
|
+
```
|
|
164
|
+
|
|
165
|
+
The public subpath exposes only token read/update helpers plus a status helper. The async read path uses the adapter's refresh logic before it returns tokens. The helpers keep secure-store storage, URL binding, refresh persistence, chunk handling, legacy import, and fail-closed credential-store errors. They do not expose client registration secrets, PKCE verifiers, or OAuth state.
|
|
166
|
+
|
|
156
167
|
### Runtime status snapshots
|
|
157
168
|
|
|
158
169
|
Extensions can subscribe to the adapter's versioned shared event-bus channel instead of parsing `/mcp` or `mcp({})` output:
|
|
@@ -203,7 +214,8 @@ In the configuration examples below, `30000` is illustrative only. If `requestTi
|
|
|
203
214
|
| `oauth.scope` | Requested OAuth scopes |
|
|
204
215
|
| `oauth.redirectUri` | Exact localhost redirect URI for browser OAuth, including port and path, for providers that pre-register callbacks |
|
|
205
216
|
| `oauth.clientName` | Client display name advertised during Dynamic Client Registration fallback |
|
|
206
|
-
| `oauth.clientUri` | Client homepage URI advertised during Dynamic Client Registration fallback |
|
|
217
|
+
| `oauth.clientUri` | Client homepage URI advertised during Dynamic Client Registration fallback. Defaults to `piConfig.clientUri` from the host's manifest when set, and is omitted rather than guessed under a rebranded host |
|
|
218
|
+
| `oauth.logoUri` | Client logo URL advertised during Dynamic Client Registration fallback (RFC 7591 `logo_uri`). Must be an absolute `http(s)` URL — consent screens fetch it server-side, so local paths render nothing. Omitted from the registration request when unset |
|
|
207
219
|
| `oauth.skipIssuerMetadataValidation` | `true` disables the OAuth authorization-server metadata issuer check for this server. This weakens OAuth mix-up protection and should only be used for known-misconfigured internal servers while their metadata is being fixed. |
|
|
208
220
|
| `bearerToken` / `bearerTokenEnv` | Token or env var name; `bearerToken` supports `${VAR}` and `$env:VAR` interpolation. A leading `!` in `bearerToken` runs a command when the HTTP server connects; use `!!` for a literal leading `!`. |
|
|
209
221
|
| `lifecycle` | `"lazy"` (default), `"eager"`, `"keep-alive"`, or `"lazy-keep-alive"` |
|
|
@@ -253,7 +265,9 @@ The adapter owns only its client socket and closes that connection when the Pi r
|
|
|
253
265
|
|
|
254
266
|
### Remote/headless OAuth
|
|
255
267
|
|
|
256
|
-
If Pi is running on a remote server and
|
|
268
|
+
If Pi is running on a remote server, `/mcp-auth <server>` prints the authorization URL and opens a callback input. Open the URL in your local browser. After approval, the browser may fail to load the localhost callback page because localhost refers to your workstation; copy the full URL from its address bar and paste it into Pi. The input closes automatically instead when the browser can reach Pi's callback directly.
|
|
269
|
+
|
|
270
|
+
The same flow is available through the proxy tool for non-interactive clients. Persistent OAuth still requires an available OS credential store; on headless Linux that usually means an unlocked Secret Service/libsecret keyring. The adapter fails closed instead of falling back to plaintext credentials when the secure store is unavailable.
|
|
257
271
|
|
|
258
272
|
On Linux, if credential access fails because Pi inherited a revoked session keyring, the adapter uses a best-effort recovery path through `keyctl session - node <packaged helper>` so explicit re-authentication can write fresh credentials without killing a long-lived tmux server. This path requires `keyctl` and `node` on `PATH`; missing, locked, or otherwise unavailable credential stores still fail closed.
|
|
259
273
|
|
|
@@ -372,9 +386,10 @@ Oversized MCP tool/resource results are guarded by default so a single huge resp
|
|
|
372
386
|
|
|
373
387
|
- Inline text output is capped at **50 KiB / 2,000 lines** (matching Pi's built-in `bash` guard). Larger output is truncated to a head preview and the full text is saved to a temp file whose path is included in the result, so the agent can `read`/`grep` it.
|
|
374
388
|
- **Image content blocks pass through unchanged** — only text output is guarded. Images are delivered to the provider as native image content.
|
|
389
|
+
- Binary resource blobs up to **10 MiB** are decoded to private temp files and replaced with file references. Each session is limited to **100 MiB** and **10,000 files**. The files are removed at session teardown.
|
|
375
390
|
- In proxy mode, `details.mcpResult` is kept raw when its JSON is **≤ 16 KiB**; larger results are replaced with a compact summary (block counts, sizes, key previews) and the raw JSON is saved to a temp file. Direct tools keep their lean details and never carry `mcpResult`.
|
|
376
391
|
|
|
377
|
-
Tune the limits with the object form:
|
|
392
|
+
Tune the text and details limits with the object form:
|
|
378
393
|
|
|
379
394
|
```json
|
|
380
395
|
{
|
|
@@ -384,7 +399,7 @@ Tune the limits with the object form:
|
|
|
384
399
|
}
|
|
385
400
|
```
|
|
386
401
|
|
|
387
|
-
Set `"outputGuard": false` — or the env kill switch `MCP_OUTPUT_GUARD=0` — to disable
|
|
402
|
+
Set `"outputGuard": false` — or the env kill switch `MCP_OUTPUT_GUARD=0` — to disable text and details guarding. Binary resource materialization and its safety limits remain active. Output-guard spill files are created with mode `0600` under the system temp directory and are not cleaned up automatically; note that spilled MCP output may contain sensitive data.
|
|
388
403
|
|
|
389
404
|
### MCP Scripting
|
|
390
405
|
|
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import { readFileSync } from "node:fs";
|
|
1
2
|
import { homedir } from "node:os";
|
|
2
3
|
import { join, resolve } from "node:path";
|
|
3
4
|
|
|
@@ -18,3 +19,42 @@ export function getAgentDir(): string {
|
|
|
18
19
|
export function getAgentPath(...segments: string[]): string {
|
|
19
20
|
return join(getAgentDir(), ...segments);
|
|
20
21
|
}
|
|
22
|
+
|
|
23
|
+
/**
|
|
24
|
+
* What the host calls itself.
|
|
25
|
+
*
|
|
26
|
+
* pi supports rebranding through `piConfig.name` in the package.json that its
|
|
27
|
+
* `getPackageDir()` resolves, and distributions built on pi (arc, tau, …) point
|
|
28
|
+
* `PI_PACKAGE_DIR` at their own manifest. Read that manifest directly rather
|
|
29
|
+
* than importing pi: this package deliberately depends on pi-ai and pi-tui
|
|
30
|
+
* only, and `getAgentDir()` above reads its env var the same self-contained way.
|
|
31
|
+
*
|
|
32
|
+
* Falls back to "pi", which is what pi's own APP_NAME resolves to.
|
|
33
|
+
*/
|
|
34
|
+
function readPiConfig(): { name?: unknown; clientUri?: unknown } | undefined {
|
|
35
|
+
const dir = process.env.PI_PACKAGE_DIR?.trim()
|
|
36
|
+
if (!dir) return undefined
|
|
37
|
+
try {
|
|
38
|
+
const manifest = JSON.parse(readFileSync(join(resolve(dir), "package.json"), "utf8")) as {
|
|
39
|
+
piConfig?: { name?: unknown; clientUri?: unknown }
|
|
40
|
+
}
|
|
41
|
+
return manifest.piConfig
|
|
42
|
+
} catch {
|
|
43
|
+
return undefined
|
|
44
|
+
}
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
export function getAppName(): string {
|
|
48
|
+
const name = readPiConfig()?.name
|
|
49
|
+
return typeof name === "string" && name.trim() ? name.trim() : "pi"
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
/**
|
|
53
|
+
* Home page the host declares for itself, via `piConfig.clientUri` in the same
|
|
54
|
+
* manifest that carries `piConfig.name`. Only the distribution knows its own
|
|
55
|
+
* URL, so this is the one place it can come from without guessing.
|
|
56
|
+
*/
|
|
57
|
+
export function getAppClientUri(): string | undefined {
|
|
58
|
+
const uri = readPiConfig()?.clientUri
|
|
59
|
+
return typeof uri === "string" && uri.trim() ? uri.trim() : undefined
|
|
60
|
+
}
|
|
@@ -25,6 +25,10 @@ import { loadOnboardingState, markSetupCompleted as persistSetupCompleted, markS
|
|
|
25
25
|
import { openPath, resolveServerUrl, sanitizeTerminalText } from "./utils.ts";
|
|
26
26
|
import { isAbortError } from "./runtime-owner.ts";
|
|
27
27
|
|
|
28
|
+
function terminalHyperlink(label: string, url: string): string {
|
|
29
|
+
return `\u001B]8;;${sanitizeTerminalText(url)}\u001B\\${sanitizeTerminalText(label)}\u001B]8;;\u001B\\`;
|
|
30
|
+
}
|
|
31
|
+
|
|
28
32
|
export async function showStatus(state: McpExtensionState, ctx: ExtensionContext): Promise<void> {
|
|
29
33
|
if (!ctx.hasUI) return;
|
|
30
34
|
|
|
@@ -273,11 +277,17 @@ export async function authenticateServer(
|
|
|
273
277
|
...(authStorageOptions.baseDir ? { authStorageOptions } : {}),
|
|
274
278
|
onAuthorizationUrl: (authorizationUrl) => {
|
|
275
279
|
ui.notify(
|
|
276
|
-
`Open this URL to authenticate ${serverName}:\n\n${authorizationUrl}\n\n` +
|
|
277
|
-
"After approving,
|
|
280
|
+
`Open this URL to authenticate ${serverName}:\n\n${terminalHyperlink(authorizationUrl, authorizationUrl)}\n\n` +
|
|
281
|
+
"After approving, Pi will complete automatically if the browser can reach its localhost callback. " +
|
|
282
|
+
"On a remote machine, copy the full localhost URL from the browser address bar and paste it into Pi.",
|
|
278
283
|
"info"
|
|
279
284
|
);
|
|
280
285
|
},
|
|
286
|
+
onAuthorizationInput: (_authorizationUrl, inputSignal) => ui.input(
|
|
287
|
+
`Complete ${serverName} OAuth`,
|
|
288
|
+
"Paste the full callback URL, or wait for automatic completion",
|
|
289
|
+
{ signal: inputSignal },
|
|
290
|
+
),
|
|
281
291
|
...(signal ? { signal } : {}),
|
|
282
292
|
...(runtime ? { runtime } : {}),
|
|
283
293
|
});
|