@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
|
@@ -12,15 +12,15 @@ export class McpLifecycleManager {
|
|
|
12
12
|
private allServers = new Map<string, ServerDefinition>();
|
|
13
13
|
private serverSettings = new Map<string, { idleTimeout?: number }>();
|
|
14
14
|
private globalIdleTimeout = 10 * 60 * 1000;
|
|
15
|
-
private healthCheckInterval
|
|
16
|
-
private onReconnect
|
|
17
|
-
private onReconnectFailure
|
|
18
|
-
private onIdleShutdown
|
|
19
|
-
private activeHealthCheck
|
|
20
|
-
private shutdownPromise
|
|
15
|
+
private healthCheckInterval: NodeJS.Timeout | undefined;
|
|
16
|
+
private onReconnect: ReconnectCallback | undefined;
|
|
17
|
+
private onReconnectFailure: ReconnectFailureCallback | undefined;
|
|
18
|
+
private onIdleShutdown: ((serverName: string) => void) | undefined;
|
|
19
|
+
private activeHealthCheck: Promise<void> | undefined;
|
|
20
|
+
private shutdownPromise: Promise<void> | undefined;
|
|
21
21
|
private stopped = false;
|
|
22
|
-
private healthSignal
|
|
23
|
-
private removeHealthAbortListener
|
|
22
|
+
private healthSignal: AbortSignal | undefined;
|
|
23
|
+
private removeHealthAbortListener: (() => void) | undefined;
|
|
24
24
|
|
|
25
25
|
constructor(
|
|
26
26
|
private readonly manager: McpServerManager,
|
|
@@ -7,9 +7,10 @@
|
|
|
7
7
|
import {
|
|
8
8
|
auth as runSdkAuth,
|
|
9
9
|
extractWWWAuthenticateParams,
|
|
10
|
+
LATEST_PROTOCOL_VERSION,
|
|
10
11
|
UnauthorizedError,
|
|
11
|
-
|
|
12
|
-
|
|
12
|
+
type AuthOptions,
|
|
13
|
+
} from "@modelcontextprotocol/client"
|
|
13
14
|
import open from "open"
|
|
14
15
|
import { McpOAuthProvider, type McpOAuthConfig } from "./mcp-oauth-provider.ts"
|
|
15
16
|
import {
|
|
@@ -30,6 +31,7 @@ import {
|
|
|
30
31
|
getOAuthState,
|
|
31
32
|
clearOAuthState,
|
|
32
33
|
getAuthBaseDir,
|
|
34
|
+
OAuthCredentialStoreError,
|
|
33
35
|
type AuthStorageOptions,
|
|
34
36
|
type StoredTokens,
|
|
35
37
|
} from "./mcp-auth.ts"
|
|
@@ -47,18 +49,24 @@ export interface McpOAuthRuntime {
|
|
|
47
49
|
|
|
48
50
|
export interface AuthenticateOptions {
|
|
49
51
|
onAuthorizationUrl?: (authorizationUrl: string) => void | Promise<void>
|
|
52
|
+
onAuthorizationInput?: (
|
|
53
|
+
authorizationUrl: string,
|
|
54
|
+
signal: AbortSignal,
|
|
55
|
+
) => Promise<string | undefined>
|
|
50
56
|
authStorageOptions?: AuthStorageOptions
|
|
51
57
|
signal?: AbortSignal
|
|
52
58
|
runtime?: McpOAuthRuntime
|
|
59
|
+
skipIssuerMetadataValidation?: boolean
|
|
53
60
|
}
|
|
54
61
|
|
|
55
|
-
type AuthDiscovery =
|
|
56
|
-
resourceMetadataUrl?: URL
|
|
57
|
-
scope?: string
|
|
58
|
-
}
|
|
62
|
+
type AuthDiscovery = Pick<AuthOptions, "resourceMetadataUrl" | "scope" | "skipIssuerMetadataValidation">
|
|
59
63
|
|
|
60
|
-
function
|
|
61
|
-
return
|
|
64
|
+
function applyOAuthConfig(discovery: AuthDiscovery, config: McpOAuthConfig): AuthDiscovery {
|
|
65
|
+
return {
|
|
66
|
+
...discovery,
|
|
67
|
+
...(config.scope !== undefined ? { scope: config.scope } : {}),
|
|
68
|
+
...(config.skipIssuerMetadataValidation === true ? { skipIssuerMetadataValidation: true } : {}),
|
|
69
|
+
}
|
|
62
70
|
}
|
|
63
71
|
|
|
64
72
|
type PendingAuth = {
|
|
@@ -208,6 +216,33 @@ export function extractOAuthConfig(definition: ServerEntry): McpOAuthConfig {
|
|
|
208
216
|
}
|
|
209
217
|
config.clientUri = clientUri
|
|
210
218
|
}
|
|
219
|
+
if (definition.oauth?.logoUri !== undefined) {
|
|
220
|
+
if (typeof definition.oauth.logoUri !== "string") {
|
|
221
|
+
throw new Error("OAuth logoUri must be a string")
|
|
222
|
+
}
|
|
223
|
+
const logoUri = interpolateEnvVars(definition.oauth.logoUri).trim()
|
|
224
|
+
if (!logoUri) {
|
|
225
|
+
throw new Error("OAuth logoUri must not be empty")
|
|
226
|
+
}
|
|
227
|
+
// Consent screens fetch this server-side, so a local path silently renders
|
|
228
|
+
// nothing. Fail here instead, where the message can say why.
|
|
229
|
+
let parsed: URL
|
|
230
|
+
try {
|
|
231
|
+
parsed = new URL(logoUri)
|
|
232
|
+
} catch {
|
|
233
|
+
throw new Error("OAuth logoUri must be an absolute http(s) URL")
|
|
234
|
+
}
|
|
235
|
+
if (parsed.protocol !== "https:" && parsed.protocol !== "http:") {
|
|
236
|
+
throw new Error("OAuth logoUri must be an absolute http(s) URL")
|
|
237
|
+
}
|
|
238
|
+
config.logoUri = logoUri
|
|
239
|
+
}
|
|
240
|
+
if (definition.oauth?.skipIssuerMetadataValidation !== undefined) {
|
|
241
|
+
if (typeof definition.oauth.skipIssuerMetadataValidation !== "boolean") {
|
|
242
|
+
throw new Error("OAuth skipIssuerMetadataValidation must be a boolean")
|
|
243
|
+
}
|
|
244
|
+
config.skipIssuerMetadataValidation = definition.oauth.skipIssuerMetadataValidation
|
|
245
|
+
}
|
|
211
246
|
return config
|
|
212
247
|
}
|
|
213
248
|
|
|
@@ -239,7 +274,7 @@ async function probeAuthDiscovery(serverUrl: string, definition?: ServerEntry, s
|
|
|
239
274
|
clientInfo: { name: "pi-mcp-adapter", version: "2.11.0" },
|
|
240
275
|
},
|
|
241
276
|
}),
|
|
242
|
-
signal: discoverySignal,
|
|
277
|
+
...(discoverySignal ? { signal: discoverySignal } : {}),
|
|
243
278
|
})
|
|
244
279
|
const { resourceMetadataUrl, scope } = extractWWWAuthenticateParams(response)
|
|
245
280
|
await response.body?.cancel().catch(() => {})
|
|
@@ -320,7 +355,7 @@ export async function startAuth(
|
|
|
320
355
|
},
|
|
321
356
|
}, authStorageOptions, runtime.signal)
|
|
322
357
|
try {
|
|
323
|
-
const discovery =
|
|
358
|
+
const discovery = applyOAuthConfig(await probeAuthDiscovery(serverUrl, definition, signal), config)
|
|
324
359
|
throwIfAborted(signal)
|
|
325
360
|
const result = await abortable(runSdkAuth(authProvider, { serverUrl, ...discovery }), signal)
|
|
326
361
|
throwIfAborted(signal)
|
|
@@ -386,7 +421,7 @@ export async function startAuth(
|
|
|
386
421
|
|
|
387
422
|
throwIfAborted(signal)
|
|
388
423
|
|
|
389
|
-
const discovery =
|
|
424
|
+
const discovery = applyOAuthConfig(await probeAuthDiscovery(serverUrl, definition, signal), config)
|
|
390
425
|
throwIfAborted(signal)
|
|
391
426
|
const result = await abortable(runSdkAuth(authProvider, { serverUrl, ...discovery }), signal)
|
|
392
427
|
throwIfAborted(signal)
|
|
@@ -537,6 +572,53 @@ export function parseAuthorizationCodeInput(input: string, expectedState?: strin
|
|
|
537
572
|
return parseAuthorizationRedirectInput(input, expectedState).code
|
|
538
573
|
}
|
|
539
574
|
|
|
575
|
+
type AuthorizationResponse = {
|
|
576
|
+
input: AuthorizationCodeInput
|
|
577
|
+
source: "callback" | "manual"
|
|
578
|
+
}
|
|
579
|
+
|
|
580
|
+
/**
|
|
581
|
+
* Wait for either the localhost callback or a manually pasted redirect URL.
|
|
582
|
+
* The manual input prompt is dismissed as soon as either path finishes.
|
|
583
|
+
*/
|
|
584
|
+
export async function waitForAuthorizationResponse(
|
|
585
|
+
callbackPromise: Promise<AuthorizationCodeInput>,
|
|
586
|
+
authorizationUrl: string,
|
|
587
|
+
expectedState: string,
|
|
588
|
+
onAuthorizationInput?: AuthenticateOptions["onAuthorizationInput"],
|
|
589
|
+
signal?: AbortSignal,
|
|
590
|
+
): Promise<AuthorizationResponse> {
|
|
591
|
+
if (!onAuthorizationInput) {
|
|
592
|
+
return {
|
|
593
|
+
input: await abortable(callbackPromise, signal),
|
|
594
|
+
source: "callback",
|
|
595
|
+
}
|
|
596
|
+
}
|
|
597
|
+
|
|
598
|
+
const inputController = new AbortController()
|
|
599
|
+
try {
|
|
600
|
+
const response = await abortable(Promise.race([
|
|
601
|
+
callbackPromise.then((input) => ({ input, source: "callback" as const })),
|
|
602
|
+
onAuthorizationInput(authorizationUrl, inputController.signal).then((input) => ({
|
|
603
|
+
input,
|
|
604
|
+
source: "manual" as const,
|
|
605
|
+
})),
|
|
606
|
+
]), signal)
|
|
607
|
+
|
|
608
|
+
if (response.source === "callback") return response
|
|
609
|
+
if (!response.input?.trim()) throw new Error("OAuth authentication cancelled")
|
|
610
|
+
if (!getSearchParamsFromInput(response.input.trim())) {
|
|
611
|
+
throw new Error("Paste the full OAuth callback URL, including its code and state parameters")
|
|
612
|
+
}
|
|
613
|
+
return {
|
|
614
|
+
input: parseAuthorizationRedirectInput(response.input, expectedState),
|
|
615
|
+
source: "manual",
|
|
616
|
+
}
|
|
617
|
+
} finally {
|
|
618
|
+
inputController.abort()
|
|
619
|
+
}
|
|
620
|
+
}
|
|
621
|
+
|
|
540
622
|
/**
|
|
541
623
|
* Complete OAuth authentication from manual user input.
|
|
542
624
|
*/
|
|
@@ -606,6 +688,7 @@ export async function completeAuth(
|
|
|
606
688
|
const result = await abortable(runSdkAuth(pendingAuth.authProvider, {
|
|
607
689
|
serverUrl: pendingAuth.serverUrl,
|
|
608
690
|
authorizationCode: code,
|
|
691
|
+
...(iss !== undefined ? { iss } : {}),
|
|
609
692
|
...pendingAuth.discovery,
|
|
610
693
|
}), signal)
|
|
611
694
|
throwIfAborted(signal)
|
|
@@ -657,10 +740,12 @@ export async function authenticate(
|
|
|
657
740
|
}
|
|
658
741
|
|
|
659
742
|
const operation = (async (): Promise<AuthStatus> => {
|
|
660
|
-
|
|
661
|
-
|
|
743
|
+
const { authorizationUrl } = await startAuth(serverName, serverUrl, definition, {
|
|
744
|
+
...options,
|
|
745
|
+
...(signal ? { signal } : {}),
|
|
746
|
+
runtime,
|
|
747
|
+
})
|
|
662
748
|
|
|
663
|
-
// If no auth URL needed, already authenticated
|
|
664
749
|
if (!authorizationUrl) {
|
|
665
750
|
return "authenticated"
|
|
666
751
|
}
|
|
@@ -694,14 +779,26 @@ export async function authenticate(
|
|
|
694
779
|
console.warn(`MCP Auth: Failed to open browser for ${serverName}; waiting for manual callback`, { error })
|
|
695
780
|
}
|
|
696
781
|
|
|
697
|
-
|
|
698
|
-
|
|
782
|
+
const authorizationResponse = await waitForAuthorizationResponse(
|
|
783
|
+
callbackPromise,
|
|
784
|
+
authorizationUrl,
|
|
785
|
+
oauthState,
|
|
786
|
+
options.onAuthorizationInput,
|
|
787
|
+
signal,
|
|
788
|
+
)
|
|
789
|
+
if (authorizationResponse.source === "manual") {
|
|
790
|
+
cancelPendingCallback(oauthState)
|
|
791
|
+
}
|
|
699
792
|
|
|
700
|
-
// The callback server accepted only the flow-local reserved state.
|
|
793
|
+
// The callback server accepted only the flow-local reserved state. Manual
|
|
794
|
+
// input is checked against the same state before token exchange.
|
|
701
795
|
throwIfAborted(signal)
|
|
702
796
|
|
|
703
|
-
|
|
704
|
-
|
|
797
|
+
return await completeAuth(serverName, authorizationResponse.input, {
|
|
798
|
+
...options,
|
|
799
|
+
...(signal ? { signal } : {}),
|
|
800
|
+
runtime,
|
|
801
|
+
})
|
|
705
802
|
} catch (error) {
|
|
706
803
|
if (oauthState) cancelPendingCallback(oauthState)
|
|
707
804
|
try {
|
|
@@ -740,25 +837,21 @@ export async function getValidToken(
|
|
|
740
837
|
const authStorageOptions = options.authStorageOptions ?? {}
|
|
741
838
|
const signal = combineAbortSignals(runtime.signal, options.signal)
|
|
742
839
|
throwIfAborted(signal)
|
|
743
|
-
// Check if we have valid tokens
|
|
744
840
|
const entry = await getAuthForUrl(serverName, serverUrl, authStorageOptions)
|
|
745
841
|
throwIfAborted(signal)
|
|
746
842
|
if (!entry?.tokens) {
|
|
747
843
|
return null
|
|
748
844
|
}
|
|
749
845
|
|
|
750
|
-
// Check expiration
|
|
751
846
|
const expired = await isTokenExpired(serverName, authStorageOptions)
|
|
752
847
|
if (expired === false) {
|
|
753
848
|
return entry.tokens
|
|
754
849
|
}
|
|
755
850
|
|
|
756
851
|
if (expired === true && entry.tokens.refreshToken) {
|
|
757
|
-
// Token is expired, try to refresh
|
|
758
852
|
console.log(`MCP Auth: Token expired for ${serverName}, attempting refresh`)
|
|
759
853
|
|
|
760
854
|
try {
|
|
761
|
-
// Create auth provider for token refresh
|
|
762
855
|
const authProvider = new McpOAuthProvider(serverName, serverUrl, {}, {
|
|
763
856
|
onRedirect: async () => {},
|
|
764
857
|
}, authStorageOptions, runtime.signal)
|
|
@@ -773,7 +866,11 @@ export async function getValidToken(
|
|
|
773
866
|
|
|
774
867
|
const discovery = await probeAuthDiscovery(serverUrl, undefined, signal)
|
|
775
868
|
throwIfAborted(signal)
|
|
776
|
-
const result = await abortable(runSdkAuth(authProvider, {
|
|
869
|
+
const result = await abortable(runSdkAuth(authProvider, {
|
|
870
|
+
serverUrl,
|
|
871
|
+
...discovery,
|
|
872
|
+
...(options.skipIssuerMetadataValidation === true ? { skipIssuerMetadataValidation: true } : {}),
|
|
873
|
+
}), signal)
|
|
777
874
|
throwIfAborted(signal)
|
|
778
875
|
if (result !== "AUTHORIZED") {
|
|
779
876
|
return null
|
|
@@ -785,7 +882,7 @@ export async function getValidToken(
|
|
|
785
882
|
authProvider.deactivate()
|
|
786
883
|
}
|
|
787
884
|
} catch (error) {
|
|
788
|
-
if (isAbortError(error, signal)) throw error
|
|
885
|
+
if (isAbortError(error, signal) || error instanceof OAuthCredentialStoreError) throw error
|
|
789
886
|
console.error(`MCP Auth: Token refresh failed for ${serverName}`, { error })
|
|
790
887
|
return null
|
|
791
888
|
}
|
|
@@ -22,7 +22,16 @@ import { resolveConfiguredOAuthDir } from './config.ts';
|
|
|
22
22
|
const require = createRequire(import.meta.url);
|
|
23
23
|
const AUTH_SECRET_SERVICE = 'pi-mcp-adapter.oauth';
|
|
24
24
|
const TEST_AUTH_STORE_ENV = 'PI_MCP_ADAPTER_TEST_AUTH_STORE';
|
|
25
|
-
|
|
25
|
+
/**
|
|
26
|
+
* Windows Credential Manager caps one value at CRED_MAX_CREDENTIAL_BLOB_SIZE
|
|
27
|
+
* (2560 bytes) and stores it as UTF-16, so the real ceiling is
|
|
28
|
+
* AUTH_SECRET_VALUE_LIMIT characters. Chunks must stay below that, and so must
|
|
29
|
+
* the threshold that decides whether to chunk at all, or oversized records still
|
|
30
|
+
* fail to persist on Windows.
|
|
31
|
+
*/
|
|
32
|
+
const AUTH_SECRET_CHUNK_SIZE = 1000;
|
|
33
|
+
/** Largest single value the strictest supported credential store accepts. */
|
|
34
|
+
const AUTH_SECRET_VALUE_LIMIT = 1280;
|
|
26
35
|
const KEYRING_RECOVERY_DISABLED_ENV = 'PI_MCP_ADAPTER_DISABLE_KEYRING_RECOVERY';
|
|
27
36
|
const KEYRING_RECOVERY_KEYCTL_ENV = 'PI_MCP_ADAPTER_KEYRING_RECOVERY_KEYCTL';
|
|
28
37
|
const KEYRING_RECOVERY_NODE_ENV = 'PI_MCP_ADAPTER_KEYRING_RECOVERY_NODE';
|
|
@@ -163,6 +172,22 @@ const keyringAuthSecretStore: AuthSecretStore = {
|
|
|
163
172
|
},
|
|
164
173
|
};
|
|
165
174
|
|
|
175
|
+
/** Mimics the Windows Credential Manager per-value ceiling for tests. */
|
|
176
|
+
const sizeLimitedAuthSecretStore: AuthSecretStore = {
|
|
177
|
+
read(account) {
|
|
178
|
+
return memoryAuthEntries.get(account);
|
|
179
|
+
},
|
|
180
|
+
write(account, payload) {
|
|
181
|
+
if (payload.length > AUTH_SECRET_VALUE_LIMIT) {
|
|
182
|
+
throw new Error(`Value of 'password encoded as UTF-16' is longer than the platform limit of ${AUTH_SECRET_VALUE_LIMIT * 2} chars`);
|
|
183
|
+
}
|
|
184
|
+
memoryAuthEntries.set(account, payload);
|
|
185
|
+
},
|
|
186
|
+
remove(account) {
|
|
187
|
+
memoryAuthEntries.delete(account);
|
|
188
|
+
},
|
|
189
|
+
};
|
|
190
|
+
|
|
166
191
|
const unavailableAuthSecretStore: AuthSecretStore = {
|
|
167
192
|
read() {
|
|
168
193
|
throw new Error('simulated secure credential store unavailable');
|
|
@@ -205,6 +230,7 @@ export function removeTestAuthSecretStoreEntry(account: string): void {
|
|
|
205
230
|
|
|
206
231
|
function getAuthSecretStore(): AuthSecretStore {
|
|
207
232
|
if (process.env[TEST_AUTH_STORE_ENV] === 'memory') return memoryAuthSecretStore;
|
|
233
|
+
if (process.env[TEST_AUTH_STORE_ENV] === 'sizelimited') return sizeLimitedAuthSecretStore;
|
|
208
234
|
if (process.env[TEST_AUTH_STORE_ENV] === 'unavailable') return unavailableAuthSecretStore;
|
|
209
235
|
if (process.env[TEST_AUTH_STORE_ENV] === 'keyrevoked') return keyRevokedAuthSecretStore;
|
|
210
236
|
return keyringAuthSecretStore;
|
|
@@ -401,7 +427,99 @@ function parseJsonPayload(serverName: string, payload: string, source: string):
|
|
|
401
427
|
}
|
|
402
428
|
|
|
403
429
|
function parseAuthEntryPayload(serverName: string, payload: string, source: string): AuthEntry {
|
|
404
|
-
|
|
430
|
+
const parsed = parseJsonPayload(serverName, payload, source);
|
|
431
|
+
const entry = toAuthEntry(parsed);
|
|
432
|
+
if (!entry) {
|
|
433
|
+
throw new Error(`Failed to parse OAuth credentials for ${serverName} from ${source}: invalid credential shape`);
|
|
434
|
+
}
|
|
435
|
+
return entry;
|
|
436
|
+
}
|
|
437
|
+
|
|
438
|
+
function toAuthEntry(value: unknown): AuthEntry | undefined {
|
|
439
|
+
const entry = toRecord(value);
|
|
440
|
+
if (!entry) return undefined;
|
|
441
|
+
|
|
442
|
+
const codeVerifier = optionalString(entry.codeVerifier);
|
|
443
|
+
const oauthState = optionalString(entry.oauthState);
|
|
444
|
+
const serverUrl = optionalString(entry.serverUrl);
|
|
445
|
+
if (codeVerifier === null || oauthState === null || serverUrl === null) return undefined;
|
|
446
|
+
|
|
447
|
+
const tokens = entry.tokens === undefined ? undefined : toStoredTokens(entry.tokens);
|
|
448
|
+
const clientInfo = entry.clientInfo === undefined ? undefined : toStoredClientInfo(entry.clientInfo);
|
|
449
|
+
if ((entry.tokens !== undefined && !tokens) || (entry.clientInfo !== undefined && !clientInfo)) return undefined;
|
|
450
|
+
|
|
451
|
+
const authEntry: AuthEntry = {};
|
|
452
|
+
if (tokens) authEntry.tokens = tokens;
|
|
453
|
+
if (clientInfo) authEntry.clientInfo = clientInfo;
|
|
454
|
+
if (codeVerifier !== undefined) authEntry.codeVerifier = codeVerifier;
|
|
455
|
+
if (oauthState !== undefined) authEntry.oauthState = oauthState;
|
|
456
|
+
if (serverUrl !== undefined) authEntry.serverUrl = serverUrl;
|
|
457
|
+
return authEntry;
|
|
458
|
+
}
|
|
459
|
+
|
|
460
|
+
function toStoredTokens(value: unknown): StoredTokens | undefined {
|
|
461
|
+
const tokens = toRecord(value);
|
|
462
|
+
if (!tokens || typeof tokens.accessToken !== 'string') return undefined;
|
|
463
|
+
|
|
464
|
+
const refreshToken = optionalString(tokens.refreshToken);
|
|
465
|
+
const scope = optionalString(tokens.scope);
|
|
466
|
+
const issuer = optionalString(tokens.issuer);
|
|
467
|
+
const expiresAt = optionalNumber(tokens.expiresAt);
|
|
468
|
+
if (refreshToken === null || scope === null || issuer === null || expiresAt === null) return undefined;
|
|
469
|
+
|
|
470
|
+
const storedTokens: StoredTokens = { accessToken: tokens.accessToken };
|
|
471
|
+
if (refreshToken !== undefined) storedTokens.refreshToken = refreshToken;
|
|
472
|
+
if (expiresAt !== undefined) storedTokens.expiresAt = expiresAt;
|
|
473
|
+
if (scope !== undefined) storedTokens.scope = scope;
|
|
474
|
+
if (issuer !== undefined) storedTokens.issuer = issuer;
|
|
475
|
+
return storedTokens;
|
|
476
|
+
}
|
|
477
|
+
|
|
478
|
+
function toStoredClientInfo(value: unknown): StoredClientInfo | undefined {
|
|
479
|
+
const clientInfo = toRecord(value);
|
|
480
|
+
if (!clientInfo || typeof clientInfo.clientId !== 'string') return undefined;
|
|
481
|
+
|
|
482
|
+
const clientSecret = optionalString(clientInfo.clientSecret);
|
|
483
|
+
const issuer = optionalString(clientInfo.issuer);
|
|
484
|
+
const clientIdIssuedAt = optionalNumber(clientInfo.clientIdIssuedAt);
|
|
485
|
+
const clientSecretExpiresAt = optionalNumber(clientInfo.clientSecretExpiresAt);
|
|
486
|
+
const configPreRegistered = optionalBoolean(clientInfo.configPreRegistered);
|
|
487
|
+
if (clientSecret === null || issuer === null || clientIdIssuedAt === null || clientSecretExpiresAt === null || configPreRegistered === null) return undefined;
|
|
488
|
+
|
|
489
|
+
const storedClient: StoredClientInfo = { clientId: clientInfo.clientId };
|
|
490
|
+
const redirectUris = stringArray(clientInfo.redirectUris);
|
|
491
|
+
if (clientSecret !== undefined) storedClient.clientSecret = clientSecret;
|
|
492
|
+
if (clientIdIssuedAt !== undefined) storedClient.clientIdIssuedAt = clientIdIssuedAt;
|
|
493
|
+
if (clientSecretExpiresAt !== undefined) storedClient.clientSecretExpiresAt = clientSecretExpiresAt;
|
|
494
|
+
if (redirectUris !== undefined) storedClient.redirectUris = redirectUris;
|
|
495
|
+
if (issuer !== undefined) storedClient.issuer = issuer;
|
|
496
|
+
if (configPreRegistered !== undefined) storedClient.configPreRegistered = configPreRegistered;
|
|
497
|
+
return storedClient;
|
|
498
|
+
}
|
|
499
|
+
|
|
500
|
+
function toRecord(value: unknown): Record<string, unknown> | undefined {
|
|
501
|
+
return typeof value === 'object' && value !== null && !Array.isArray(value)
|
|
502
|
+
? value as Record<string, unknown>
|
|
503
|
+
: undefined;
|
|
504
|
+
}
|
|
505
|
+
|
|
506
|
+
function optionalString(value: unknown): string | null | undefined {
|
|
507
|
+
if (value === undefined) return undefined;
|
|
508
|
+
return typeof value === 'string' ? value : null;
|
|
509
|
+
}
|
|
510
|
+
|
|
511
|
+
function optionalNumber(value: unknown): number | null | undefined {
|
|
512
|
+
if (value === undefined) return undefined;
|
|
513
|
+
return typeof value === 'number' ? value : null;
|
|
514
|
+
}
|
|
515
|
+
|
|
516
|
+
function optionalBoolean(value: unknown): boolean | null | undefined {
|
|
517
|
+
if (value === undefined) return undefined;
|
|
518
|
+
return typeof value === 'boolean' ? value : null;
|
|
519
|
+
}
|
|
520
|
+
|
|
521
|
+
function stringArray(value: unknown): string[] | undefined {
|
|
522
|
+
return Array.isArray(value) && value.every(uri => typeof uri === 'string') ? value : undefined;
|
|
405
523
|
}
|
|
406
524
|
|
|
407
525
|
function isAuthEntryChunkManifest(value: unknown): value is AuthEntryChunkManifest {
|