@fased/fased 0.1.55 → 0.1.57
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/config/capability-catalog.json +12 -0
- package/dist/agents/authenticated-model-catalog.js +3 -2
- package/dist/agents/bash-tools.exec-host-node.js +1 -1
- package/dist/agents/bash-tools.exec.js +1 -1
- package/dist/agents/copilot-dynamic-headers.js +37 -0
- package/dist/agents/current-model-catalog.js +6 -3
- package/dist/agents/model-catalog-snapshot.js +124 -0
- package/dist/agents/model-catalog-source.js +2 -2
- package/dist/agents/model-catalog.js +1 -1
- package/dist/agents/model-metadata.js +34 -6
- package/dist/agents/openai-codex-app-server.js +524 -0
- package/dist/agents/openai-codex-runtime-component.js +39 -0
- package/dist/agents/pi-embedded-runner/compact.js +3 -3
- package/dist/agents/pi-embedded-runner/extra-params.js +170 -94
- package/dist/agents/pi-embedded-runner/model.js +62 -1
- package/dist/agents/pi-embedded-runner/moonshot-stream-wrappers.js +46 -0
- package/dist/agents/pi-embedded-runner/openai-stream-wrappers.js +221 -0
- package/dist/agents/pi-embedded-runner/run/attempt.js +6 -4
- package/dist/agents/pi-embedded-runner/run.js +5 -2
- package/dist/agents/pi-embedded-runner/utils.js +1 -1
- package/dist/agents/pi-embedded-runner.js +1 -1
- package/dist/agents/pi-tools.js +2 -2
- package/dist/agents/tools/discord-actions-messaging.js +1 -1
- package/dist/agents/tools/message-tool.js +1 -1
- package/dist/agents/tools/session-status-tool.js +3 -3
- package/dist/agents/tools/slack-actions.js +1 -1
- package/dist/agents/tools/tts-tool.js +1 -1
- package/dist/auto-reply/reply/commands-models.js +1 -1
- package/dist/auto-reply/reply/directive-handling.impl.js +4 -1
- package/dist/auto-reply/reply/dispatch-acp.js +1 -1
- package/dist/auto-reply/reply/dispatch-from-config.js +1 -1
- package/dist/auto-reply/reply/get-reply-run.js +20 -2
- package/dist/auto-reply/reply/model-selection.js +1 -1
- package/dist/auto-reply/reply/session-reset-model.js +1 -1
- package/dist/auto-reply/status.js +1 -1
- package/dist/auto-reply/thinking.js +1 -1
- package/dist/brand.js +1 -1
- package/dist/browser/cdp.helpers.js +2 -2
- package/dist/browser/chrome.js +2 -2
- package/dist/browser/extension-relay.js +7 -7
- package/dist/build-info.json +3 -3
- package/dist/canvas-host/a2ui/.bundle.hash +1 -1
- package/dist/capabilities/install.js +43 -0
- package/dist/cli/components-cli.js +9 -31
- package/dist/cli/cron-cli/register.cron-add.js +1 -1
- package/dist/cli/hooks-cli.js +1 -1
- package/dist/cli/plugins-cli.js +3 -3
- package/dist/cli/program/register.agent.js +1 -1
- package/dist/cli/update-cli/update-command.js +50 -12
- package/dist/commands/agent.js +22 -3
- package/dist/commands/auth-choice.apply.openai.js +9 -0
- package/dist/commands/auth-choice.apply.plugin-provider.js +1 -1
- package/dist/commands/doctor-config-flow.js +1 -1
- package/dist/commands/hosted-dashboard-probe.js +3 -3
- package/dist/commands/model-picker.js +4 -3
- package/dist/commands/models/list.probe.js +1 -1
- package/dist/commands/models/list.registry.js +3 -2
- package/dist/commands/models/list.status-command.js +2 -2
- package/dist/commands/onboard-channels.js +1 -1
- package/dist/commands/onboarding/plugin-install.js +2 -2
- package/dist/commands/openai-codex-model-default.js +3 -2
- package/dist/config/zod-schema.agent-defaults.js +4 -2
- package/dist/config/zod-schema.agent-runtime.js +4 -2
- package/dist/config/zod-schema.core.js +4 -2
- package/dist/control-ui/assets/{app-D2RaTXoV.js → app-DltSyY4Y.js} +1723 -1716
- package/dist/control-ui/assets/chat-model-ref-Djkv93yn.js +2 -0
- package/dist/control-ui/assets/{index-D2nC6I-9.js → index-D5JlBp7f.js} +3 -3
- package/dist/control-ui/assets/{providers-CyjiG5Jw.js → providers-Cc89iMdx.js} +3 -3
- package/dist/control-ui/index.html +1 -1
- package/dist/control-ui/version.json +1 -1
- package/dist/cron/isolated-agent/run.js +6 -2
- package/dist/cron/service/jobs.js +11 -1
- package/dist/discord/monitor/gateway-plugin.js +2 -2
- package/dist/discord/voice/manager.js +1 -1
- package/dist/gateway/client.js +4 -4
- package/dist/gateway/protocol/schema/agents-models-skills.js +106 -5
- package/dist/gateway/server-methods/hooks.js +1 -1
- package/dist/gateway/server-methods/models.js +15 -7
- package/dist/gateway/server-methods/plugins-marketplace.js +3 -3
- package/dist/gateway/server-methods/services.js +1 -1
- package/dist/gateway/server-methods/sessions.js +1 -1
- package/dist/gateway/server-methods/tts.js +2 -2
- package/dist/gateway/server-model-catalog.js +1 -1
- package/dist/gateway/sessions-patch.js +27 -24
- package/dist/light-update-status.js +11 -11
- package/dist/plugin-sdk/{accounts-CeRNo5Ae.js → accounts-CmMwe9Dt.js} +1 -1
- package/dist/plugin-sdk/{actions-OMRHtXPj.js → actions-DYViFQiX.js} +4 -4
- package/dist/plugin-sdk/{active-listener-BlIkS3iR.js → active-listener-DVbpcisf.js} +1 -1
- package/dist/plugin-sdk/{agent-scope-BbgPlhtw.js → agent-scope-CCjfjKoO.js} +1 -1
- package/dist/plugin-sdk/{allow-list-BYeKk0Sy.js → allow-list-DyAxs4yw.js} +1 -1
- package/dist/plugin-sdk/{audio-preflight-B2n3a2Tj.js → audio-preflight-D-Mfay8i.js} +44 -48
- package/dist/plugin-sdk/{audit-Ppg6dR_b.js → audit-JImYFOzJ.js} +1 -1
- package/dist/plugin-sdk/{channel-access-configure-B6IAGlE0.js → channel-access-configure-B_qYjml8.js} +1 -1
- package/dist/plugin-sdk/{channel-access-af8dWWRv.js → channel-access-cxCK2mci.js} +1 -1
- package/dist/plugin-sdk/{channel-adapters.discord-IOZP8Cv5.js → channel-adapters.discord-BS4S4Svh.js} +1 -1
- package/dist/plugin-sdk/channel-plugin-common.d.ts +3 -3
- package/dist/plugin-sdk/channel-plugin-common.js +5 -5
- package/dist/plugin-sdk/{chunk-CD76Byie.js → chunk-CF8nvZNj.js} +1 -1
- package/dist/plugin-sdk/{chunk-items-Bu19zrYH.js → chunk-items-yLFoO571.js} +1 -1
- package/dist/plugin-sdk/command-status.d.ts +2 -2
- package/dist/plugin-sdk/command-status.js +44 -48
- package/dist/plugin-sdk/{commands-registry-DgS55tNj.js → commands-registry-CK4KmMG0.js} +2 -2
- package/dist/plugin-sdk/{common-CWvfeiX0.js → common-Cky4hpqr.js} +1 -1
- package/dist/plugin-sdk/{config-CYDETqcF.js → config-Dbxj_jUP.js} +1153 -17
- package/dist/plugin-sdk/{config-schema-CQ4EVcQG.js → config-schema-aKPMn6ML.js} +96084 -81132
- package/dist/plugin-sdk/device-pair.d.ts +1 -1
- package/dist/plugin-sdk/device-pair.js +2 -3
- package/dist/plugin-sdk/{diagnostic-Dfn1iERm.js → diagnostic-DLL_zekv.js} +3 -3
- package/dist/plugin-sdk/{directory-live-DatqU-eS.js → directory-live-CSuYxdwk.js} +1 -1
- package/dist/plugin-sdk/{directory-live-ClwN5KKq.js → directory-live-Dw7ZgC9_.js} +1 -1
- package/dist/plugin-sdk/discord.d.ts +6 -6
- package/dist/plugin-sdk/discord.js +32 -33
- package/dist/plugin-sdk/{draft-stream-controls-D4Tb_iS_.js → draft-stream-controls-BqchW1vi.js} +1 -1
- package/dist/plugin-sdk/{fetch-guard-BuYrl6q2.js → fetch-guard-CeG6u6ld.js} +1 -1
- package/dist/plugin-sdk/{filesystem-manager-B9DDPgfU.js → filesystem-manager-ZoHU8oA7.js} +3 -3
- package/dist/plugin-sdk/{fs-safe-BG-VzVkL.js → fs-safe-g4g7GT02.js} +2 -2
- package/dist/plugin-sdk/{group-mentions-BxDgHCgj.d.ts → group-mentions-BHRff6j8.d.ts} +1 -1
- package/dist/plugin-sdk/{guilds-BeT3iHHJ.js → guilds-CDhRIX57.js} +1 -1
- package/dist/plugin-sdk/{handle-action-B75UVKxF.js → handle-action-BSNDD2Vc.js} +25 -26
- package/dist/plugin-sdk/{helpers-BuEwju6y.js → helpers-CDo2XBSr.js} +1 -1
- package/dist/plugin-sdk/{image-ops-C66HPeAZ.js → image-ops-DbeBxbn4.js} +1 -1
- package/dist/plugin-sdk/index.d.ts +18 -18
- package/dist/plugin-sdk/index.js +48 -52
- package/dist/plugin-sdk/{login-Amr2DpKU.js → login-CWXvFTd8.js} +3 -3
- package/dist/plugin-sdk/{login-qr-DMQNEi9m.js → login-qr-CJB2zjmM.js} +4 -4
- package/dist/plugin-sdk/{manager-Bvpq49BI.js → manager-CbiFFLKS.js} +8 -8
- package/dist/plugin-sdk/{markdown-tables-DmQ7oXOm.js → markdown-tables-Bskt9r8i.js} +1 -1
- package/dist/plugin-sdk/{media-ByLQbEwJ.js → media-B3aAg5rh.js} +5 -5
- package/dist/plugin-sdk/{memory-search-C3C0bD2H.js → memory-search-DTjIMw8J.js} +1 -1
- package/dist/plugin-sdk/{monitor-K_u6daGa.js → monitor-BJs6z7AT.js} +52 -56
- package/dist/plugin-sdk/{monitor-S_7LrvSj.js → monitor-BYGbTI5V.js} +62 -66
- package/dist/plugin-sdk/{openresponses-http-BrDJUZXR.js → openresponses-http-BGCl2dS2.js} +44 -48
- package/dist/plugin-sdk/{optional-runtime-dependency-CbYjAC2b.js → optional-runtime-dependency-BlTVkcAg.js} +1 -1
- package/dist/plugin-sdk/{outbound-BuDafBBI.js → outbound-CIemga5_.js} +9 -9
- package/dist/plugin-sdk/{outbound-attachment-DmZmUqFP.js → outbound-attachment-2RckWqrk.js} +2 -2
- package/dist/plugin-sdk/{pairing-message-D0-UWGFJ.d.ts → pairing-message-C403mq4K.d.ts} +2 -2
- package/dist/plugin-sdk/{pairing-message-e4D4eBDA.js → pairing-message-r-VQfhFB.js} +1 -1
- package/dist/plugin-sdk/{pairing-store-T3IGoGZg.js → pairing-store-uPnLfGgB.js} +2 -2
- package/dist/plugin-sdk/{path-alias-guards-Dg3gU-MA.js → path-alias-guards-DjgDArrp.js} +1 -1
- package/dist/plugin-sdk/{pi-model-discovery-DvAG_Png.js → pi-model-discovery-BpEilAym.js} +1 -1
- package/dist/plugin-sdk/{pi-model-discovery-runtime-NjkUgjIf.js → pi-model-discovery-runtime-DwNdFaz-.js} +3 -3
- package/dist/plugin-sdk/{probe-Dlk0Jxpw.js → probe-BFroeK3g.js} +1 -1
- package/dist/plugin-sdk/{probe-Cyb-DGA3.js → probe-CJb5uR8B.js} +2 -2
- package/dist/plugin-sdk/{probe-D8JAILir.js → probe-l_whvGLY.js} +1 -1
- package/dist/plugin-sdk/provider-web-search-config-contract.d.ts +2 -2
- package/dist/plugin-sdk/{pw-ai-D7eW43DL.js → pw-ai-H7UgunQQ.js} +7 -9
- package/dist/plugin-sdk/{qmd-manager-DCUE21Kj.js → qmd-manager-DSyx77KY.js} +4 -4
- package/dist/plugin-sdk/{query-expansion-Zr9qQixm.js → query-expansion-CAI2kKLQ.js} +1 -1
- package/dist/plugin-sdk/{replies-BMIPmEoP.js → replies-CKMwkH4G.js} +4 -4
- package/dist/plugin-sdk/{reply-prefix-Bqzm6DC1.js → reply-prefix-CeVw7Mn2.js} +1 -1
- package/dist/plugin-sdk/{resolve-channels-ChWKWtA9.js → resolve-channels-87LZrFk_.js} +2 -2
- package/dist/plugin-sdk/{resolve-channels-zEnvugag.js → resolve-channels-_-nV-EK2.js} +1 -1
- package/dist/plugin-sdk/{resolve-outbound-target-CXCqUUPV.js → resolve-outbound-target-B68fSoGi.js} +2 -2
- package/dist/plugin-sdk/{resolve-route-DJN-SUSt.js → resolve-route-B8fOfihG.js} +2 -2
- package/dist/plugin-sdk/{resolve-users-BTvjQuui.js → resolve-users-DN9VQBwv.js} +1 -1
- package/dist/plugin-sdk/{resolve-users-CTzoruIZ.js → resolve-users-V6dHh_2B.js} +2 -2
- package/dist/plugin-sdk/{retry-policy-CY1qY6d7.js → retry-policy-B6GQldxB.js} +1 -1
- package/dist/plugin-sdk/{runtime-dependency-DvdRNMvs.js → runtime-dependency-DlqVSsSs.js} +124 -16
- package/dist/plugin-sdk/{runtime-CgOkQe0w.js → runtime-nVJl3PlS.js} +4 -4
- package/dist/plugin-sdk/{sandbox-paths-lj7_EVuA.js → sandbox-paths-Dx2lUqCu.js} +2 -2
- package/dist/plugin-sdk/sat-runtime.d.ts +3 -3
- package/dist/plugin-sdk/sat-runtime.js +45 -11
- package/dist/plugin-sdk/{send-2ITqny2W.js → send-BCJ4hi3t.js} +10 -10
- package/dist/plugin-sdk/{send-Cr-dj6S-.js → send-BHokB4TR.js} +6 -6
- package/dist/plugin-sdk/{send-BAz22RZr.js → send-CPK_HlYW.js} +9 -9
- package/dist/plugin-sdk/{send-eTxqFFsw.js → send-D3DQOg2a.js} +8 -8
- package/dist/plugin-sdk/{send-BG3RWyil.js → send-hSu1HWms.js} +13 -13
- package/dist/plugin-sdk/{session-C8nJmmVE.js → session-DQ4Dr-mf.js} +3 -3
- package/dist/plugin-sdk/{skill-commands-Rm5by9S8.js → skill-commands-CmdoKLh_.js} +103 -103
- package/dist/plugin-sdk/{slack-xvIVvyEM.js → slack-B70NHpMF.js} +65 -69
- package/dist/plugin-sdk/{slack-actions-BNIALJTA.js → slack-actions-fSmP981b.js} +21 -22
- package/dist/plugin-sdk/slack.d.ts +6 -6
- package/dist/plugin-sdk/slack.js +14 -14
- package/dist/plugin-sdk/{ssrf-BZG8Ztod.js → ssrf-fG4UHKBw.js} +180 -2
- package/dist/plugin-sdk/{sticker-cache-D3oDiu2u.js → sticker-cache-B4dG2sKU.js} +3 -3
- package/dist/plugin-sdk/{tables-DS5L7lCA.js → tables-EX4Hy-a-.js} +2 -2
- package/dist/plugin-sdk/{device-pairing-D2Yq-_U6.js → tailscale-status-DwpNdO3Z.js} +104 -2
- package/dist/plugin-sdk/{targets-D6lUomJc.js → targets-BeGUCGWK.js} +2 -2
- package/dist/plugin-sdk/{telegram-actions-MSFkDn0m.js → telegram-actions-CM8SJgc9.js} +49 -53
- package/dist/plugin-sdk/telegram.d.ts +6 -6
- package/dist/plugin-sdk/telegram.js +12 -12
- package/dist/plugin-sdk/{thread-bindings.lifecycle-Ry6Vcgw3.js → thread-bindings.lifecycle-tHK_1mvp.js} +3 -3
- package/dist/plugin-sdk/{thread-bindings.state-C0stmvNk.js → thread-bindings.state-D7xG1GHu.js} +2 -2
- package/dist/plugin-sdk/{tmp-fased-dir-D91GExk4.d.ts → tmp-fased-dir-Ouj58axY.d.ts} +2 -2
- package/dist/plugin-sdk/{types-DVTIpopt.d.ts → types-B4hj6HgR.d.ts} +2 -2
- package/dist/plugin-sdk/{types-BzadOItY.d.ts → types-DyhXnYUr.d.ts} +1 -1
- package/dist/plugin-sdk/{types-DKvBJHfH.d.ts → types-dWZFX1fk.d.ts} +28 -3
- package/dist/plugin-sdk/{types.plugin-BiHPaDTF.d.ts → types.plugin-_fbu40Re.d.ts} +7 -5
- package/dist/plugin-sdk/{web-DRNJxHXA.js → web-BFolfZ3i.js} +53 -57
- package/dist/plugin-sdk/{whatsapp-actions-BDXZF2R5.js → whatsapp-actions-CYmleHCz.js} +19 -20
- package/dist/plugin-sdk/{whatsapp-heartbeat-CKgmwCGr.js → whatsapp-heartbeat-BEwm4GK3.js} +2 -2
- package/dist/plugin-sdk/whatsapp.d.ts +11 -11
- package/dist/plugin-sdk/whatsapp.js +15 -15
- package/dist/plugin-sdk/{wsl-Biw7Mj39.js → wsl-BtMDzMv5.js} +53 -53
- package/dist/plugin-sdk/{zod-schema.providers-core-CIzCjXH9.d.ts → zod-schema.providers-core-FaYR6KdD.d.ts} +61 -61
- package/dist/plugins/lifecycle.js +1 -1
- package/dist/plugins/manifest-registry.js +26 -0
- package/dist/plugins/manifest.js +2 -0
- package/dist/plugins/marketplace.js +1 -1
- package/dist/plugins/runtime/index.js +1 -1
- package/dist/plugins/update.js +1 -1
- package/dist/providers/github-copilot-model-discovery.js +51 -0
- package/dist/providers/openai-codex-model-discovery.js +176 -0
- package/dist/providers/refresh.js +116 -34
- package/dist/providers/registry.js +2 -2
- package/dist/providers/runtime-model-catalog.js +97 -28
- package/dist/shared/model-thinking.js +13 -2
- package/dist/telegram/bot-message-context.js +1 -1
- package/dist/wizard/onboarding.finalize.js +1 -1
- package/extensions/acpx/package.json +1 -1
- package/extensions/bluebubbles/package.json +1 -1
- package/extensions/copilot-proxy/package.json +1 -1
- package/extensions/diagnostics-otel/package.json +1 -1
- package/extensions/fased-federation/package.json +1 -1
- package/extensions/google-gemini-cli-auth/package.json +1 -1
- package/extensions/imessage/package.json +1 -1
- package/extensions/irc/package.json +1 -1
- package/extensions/line/package.json +1 -1
- package/extensions/llm-task/package.json +1 -1
- package/extensions/lobster/package.json +1 -1
- package/extensions/matrix/CHANGELOG.md +12 -0
- package/extensions/matrix/package.json +1 -1
- package/extensions/mattermost/package.json +1 -1
- package/extensions/memory-core/package.json +2 -2
- package/extensions/memory-lancedb/package.json +1 -1
- package/extensions/minimax-portal-auth/package.json +1 -1
- package/extensions/msteams/CHANGELOG.md +12 -0
- package/extensions/msteams/package.json +1 -1
- package/extensions/nextcloud-talk/package.json +1 -1
- package/extensions/nostr/CHANGELOG.md +12 -0
- package/extensions/nostr/package.json +1 -1
- package/extensions/open-prose/package.json +1 -1
- package/extensions/sat-mining/package.json +1 -1
- package/extensions/signal/package.json +1 -1
- package/extensions/synology-chat/package.json +1 -1
- package/extensions/tlon/package.json +1 -1
- package/extensions/twitch/CHANGELOG.md +12 -0
- package/extensions/twitch/package.json +1 -1
- package/extensions/voice-call/CHANGELOG.md +12 -0
- package/extensions/voice-call/package.json +1 -1
- package/extensions/zalo/CHANGELOG.md +12 -0
- package/extensions/zalo/package.json +1 -1
- package/extensions/zalouser/CHANGELOG.md +12 -0
- package/extensions/zalouser/package.json +1 -1
- package/package.json +2 -1
- package/dist/control-ui/assets/chat-model-ref-BZFblCeY.js +0 -2
- package/dist/plugin-sdk/ip-C70a-YlD.js +0 -181
- package/dist/plugin-sdk/tailscale-status-ClsquRGs.js +0 -104
- package/dist/plugin-sdk/wallet-status-f0HagNeO.js +0 -11947
- package/dist/plugin-sdk/ws-CocpWGhl.js +0 -114
- /package/dist/plugin-sdk/{blocks-input-Dcitfh7h.js → blocks-input-Bg-8S2pl.js} +0 -0
- /package/dist/plugin-sdk/{channel-activity-Cg1xRoc2.js → channel-activity-DBDMQ3yI.js} +0 -0
- /package/dist/plugin-sdk/{channel-core-BOkyXXLa.js → channel-core-CFRs8LPy.js} +0 -0
- /package/dist/plugin-sdk/{client-D2N7hqVu.js → client-pI228AVT.js} +0 -0
- /package/dist/plugin-sdk/{command-poll-backoff-NAePk3eL.js → command-poll-backoff-yJU83wEq.js} +0 -0
- /package/dist/plugin-sdk/{date-time-CE3Uer3C.js → date-time-uUevHscU.js} +0 -0
- /package/dist/plugin-sdk/{diagnostic-session-state-HO94DMou.js → diagnostic-session-state-DqgfGYqZ.js} +0 -0
- /package/dist/plugin-sdk/{draft-stream-loop-CKyHn8IX.js → draft-stream-loop-CrOPfV3F.js} +0 -0
- /package/dist/plugin-sdk/{fetch-Cu-ahkie.js → fetch-BtmoPIlf.js} +0 -0
- /package/dist/plugin-sdk/{gateway-registry-DFsoY6C0.js → gateway-registry-DZDsqicG.js} +0 -0
- /package/dist/plugin-sdk/{inbound-context-BFnIdcqI.js → inbound-context-DrAcXE0y.js} +0 -0
- /package/dist/plugin-sdk/{internal-qo16nNU1.js → internal-CG_nHo-2.js} +0 -0
- /package/dist/plugin-sdk/{pairing-token-N_6Jbt1L.js → pairing-token-Cs3BRKc0.js} +0 -0
- /package/dist/plugin-sdk/{polls-DQrR-qT3.js → polls-DKQXVfJp.js} +0 -0
- /package/dist/plugin-sdk/{proxy-7xs_rsnV.js → proxy-DWpYcsvR.js} +0 -0
- /package/dist/plugin-sdk/{qmd-scope-D1sSG_Rx.js → qmd-scope-CdX34VCV.js} +0 -0
- /package/dist/plugin-sdk/{redact-identifier-Q3tkvxhm.js → redact-identifier-Lt7t3l7S.js} +0 -0
- /package/dist/plugin-sdk/{redact-sensitive-url-dPvnFFsK.js → redact-sensitive-url-g-ukZjwA.js} +0 -0
- /package/dist/plugin-sdk/{render-Bwu_WxwA.js → render-e7fENCYH.js} +0 -0
- /package/dist/plugin-sdk/{reply-reference-BkbK_DWT.js → reply-reference-Bqk-7HXE.js} +0 -0
- /package/dist/plugin-sdk/{secure-random-Bl-AVLVb.js → secure-random-BIkG-k4s.js} +0 -0
- /package/dist/plugin-sdk/{shared-clhhbWN3.js → shared-CBgp_GBw.js} +0 -0
- /package/dist/plugin-sdk/{target-errors-C_SVKoEv.js → target-errors-Ckufe179.js} +0 -0
- /package/dist/plugin-sdk/{targets-BDvvnlph.js → targets-CoMJ1ry1.js} +0 -0
- /package/dist/plugin-sdk/{tokens-BvtlOzVP.js → tokens-BbnqfVuu.js} +0 -0
- /package/dist/plugin-sdk/{tool-loop-detection-CWphm1k_.js → tool-loop-detection-Bp8bPJLs.js} +0 -0
- /package/dist/plugin-sdk/{ui-e020ouhJ.js → ui-Be8cLHIS.js} +0 -0
- /package/dist/plugin-sdk/{with-timeout-BYrRAYFV.js → with-timeout-ckWB8rTo.js} +0 -0
|
@@ -2,9 +2,9 @@ import { t as __exportAll } from "./rolldown-runtime-Cbj13DAv.js";
|
|
|
2
2
|
import { c as CHANNEL_IDS, f as normalizeChatChannelId, t as createSubsystemLogger, u as CORE_RUNTIME_CHANNEL_IDS } from "./subsystem-DBPNbQDQ.js";
|
|
3
3
|
import { c as expandHomePrefix, n as resolveConfigPath, o as resolveOAuthPath, r as resolveDefaultConfigCandidates, s as resolveStateDir, u as resolveRequiredHomeDir } from "./paths-BEmvSyOV.js";
|
|
4
4
|
import { C as isPlainObject$2, c as isRecord$3, h as resolveUserPath, p as resolveConfigDir, t as CONFIG_DIR } from "./utils-CYk9EKoq.js";
|
|
5
|
-
import {
|
|
5
|
+
import { H as resolveAgentModelFallbackValues, I as isNotFoundPathError, L as isPathInside$2, O as resolveFasedAgentPackageRootSync, R as isSymlinkOpenError, U as resolveAgentModelPrimaryValue, V as MAX_AGENT_MODEL_FALLBACKS, W as toAgentModelListLike, i as resolveAgentConfig, j as openBoundaryFileSync, k as canUseBoundaryFileOpen, l as resolveAgentWorkspaceDir, o as resolveAgentEffectiveModelPrimary, u as resolveDefaultAgentId } from "./agent-scope-CCjfjKoO.js";
|
|
6
6
|
import { h as isBlockedObjectKey, s as normalizeAgentId, t as DEFAULT_AGENT_ID } from "./session-key-HSJ2KQTc.js";
|
|
7
|
-
import { n as runExec } from "./exec-DQ8j4Fm3.js";
|
|
7
|
+
import { n as runExec, t as runCommandWithTimeout } from "./exec-DQ8j4Fm3.js";
|
|
8
8
|
import { n as redactSensitiveText } from "./redact-Bm8vu_ju.js";
|
|
9
9
|
import { a as saveJsonFile, i as loadJsonFile, r as resolveCopilotApiToken, t as DEFAULT_COPILOT_API_BASE_URL } from "./github-copilot-token-CUK__1s1.js";
|
|
10
10
|
import { t as runTasksWithConcurrency } from "./run-with-concurrency-BsDJWzgM.js";
|
|
@@ -31,10 +31,64 @@ import AjvPkg from "ajv";
|
|
|
31
31
|
import { z } from "zod";
|
|
32
32
|
|
|
33
33
|
//#region src/plugins/slots.ts
|
|
34
|
+
const SLOT_BY_KIND = { memory: "memory" };
|
|
34
35
|
const DEFAULT_SLOT_BY_KEY = { memory: "memory-core" };
|
|
36
|
+
function slotKeyForPluginKind(kind) {
|
|
37
|
+
if (!kind) return null;
|
|
38
|
+
return SLOT_BY_KIND[kind] ?? null;
|
|
39
|
+
}
|
|
35
40
|
function defaultSlotIdForKey(slotKey) {
|
|
36
41
|
return DEFAULT_SLOT_BY_KEY[slotKey];
|
|
37
42
|
}
|
|
43
|
+
function applyExclusiveSlotSelection(params) {
|
|
44
|
+
const slotKey = slotKeyForPluginKind(params.selectedKind);
|
|
45
|
+
if (!slotKey) return {
|
|
46
|
+
config: params.config,
|
|
47
|
+
warnings: [],
|
|
48
|
+
changed: false
|
|
49
|
+
};
|
|
50
|
+
const warnings = [];
|
|
51
|
+
const pluginsConfig = params.config.plugins ?? {};
|
|
52
|
+
const prevSlot = pluginsConfig.slots?.[slotKey];
|
|
53
|
+
const slots = {
|
|
54
|
+
...pluginsConfig.slots,
|
|
55
|
+
[slotKey]: params.selectedId
|
|
56
|
+
};
|
|
57
|
+
const inferredPrevSlot = prevSlot ?? defaultSlotIdForKey(slotKey);
|
|
58
|
+
if (inferredPrevSlot && inferredPrevSlot !== params.selectedId) warnings.push(`Exclusive slot "${slotKey}" switched from "${inferredPrevSlot}" to "${params.selectedId}".`);
|
|
59
|
+
const entries = { ...pluginsConfig.entries };
|
|
60
|
+
const disabledIds = [];
|
|
61
|
+
if (params.registry) for (const plugin of params.registry.plugins) {
|
|
62
|
+
if (plugin.id === params.selectedId) continue;
|
|
63
|
+
if (plugin.kind !== params.selectedKind) continue;
|
|
64
|
+
const entry = entries[plugin.id];
|
|
65
|
+
if (!entry || entry.enabled !== false) {
|
|
66
|
+
entries[plugin.id] = {
|
|
67
|
+
...entry,
|
|
68
|
+
enabled: false
|
|
69
|
+
};
|
|
70
|
+
disabledIds.push(plugin.id);
|
|
71
|
+
}
|
|
72
|
+
}
|
|
73
|
+
if (disabledIds.length > 0) warnings.push(`Disabled other "${slotKey}" slot plugins: ${disabledIds.toSorted().join(", ")}.`);
|
|
74
|
+
if (!(prevSlot !== params.selectedId || disabledIds.length > 0)) return {
|
|
75
|
+
config: params.config,
|
|
76
|
+
warnings: [],
|
|
77
|
+
changed: false
|
|
78
|
+
};
|
|
79
|
+
return {
|
|
80
|
+
config: {
|
|
81
|
+
...params.config,
|
|
82
|
+
plugins: {
|
|
83
|
+
...pluginsConfig,
|
|
84
|
+
slots,
|
|
85
|
+
entries
|
|
86
|
+
}
|
|
87
|
+
},
|
|
88
|
+
warnings,
|
|
89
|
+
changed: true
|
|
90
|
+
};
|
|
91
|
+
}
|
|
38
92
|
|
|
39
93
|
//#endregion
|
|
40
94
|
//#region src/plugins/config-state.ts
|
|
@@ -1216,6 +1270,17 @@ function resolveArchiveKind(filePath) {
|
|
|
1216
1270
|
if (TAR_SUFFIXES.some((suffix) => lower.endsWith(suffix))) return "tar";
|
|
1217
1271
|
return null;
|
|
1218
1272
|
}
|
|
1273
|
+
async function resolvePackedRootDir(extractDir) {
|
|
1274
|
+
const direct = path.join(extractDir, "package");
|
|
1275
|
+
try {
|
|
1276
|
+
if ((await fs$1.stat(direct)).isDirectory()) return direct;
|
|
1277
|
+
} catch {}
|
|
1278
|
+
const dirs = (await fs$1.readdir(extractDir, { withFileTypes: true })).filter((entry) => entry.isDirectory()).map((entry) => entry.name);
|
|
1279
|
+
if (dirs.length !== 1) throw new Error(`unexpected archive layout (dirs: ${dirs.join(", ")})`);
|
|
1280
|
+
const onlyDir = dirs[0];
|
|
1281
|
+
if (!onlyDir) throw new Error("unexpected archive layout (no package dir found)");
|
|
1282
|
+
return path.join(extractDir, onlyDir);
|
|
1283
|
+
}
|
|
1219
1284
|
async function withTimeout(promise, timeoutMs, label) {
|
|
1220
1285
|
let timeoutId;
|
|
1221
1286
|
try {
|
|
@@ -1473,9 +1538,351 @@ async function extractArchive(params) {
|
|
|
1473
1538
|
limits: params.limits
|
|
1474
1539
|
}), params.timeoutMs, label);
|
|
1475
1540
|
}
|
|
1541
|
+
async function fileExists(filePath) {
|
|
1542
|
+
try {
|
|
1543
|
+
await fs$1.stat(filePath);
|
|
1544
|
+
return true;
|
|
1545
|
+
} catch {
|
|
1546
|
+
return false;
|
|
1547
|
+
}
|
|
1548
|
+
}
|
|
1549
|
+
async function readJsonFile(filePath) {
|
|
1550
|
+
const raw = await fs$1.readFile(filePath, "utf-8");
|
|
1551
|
+
return JSON.parse(raw);
|
|
1552
|
+
}
|
|
1553
|
+
|
|
1554
|
+
//#endregion
|
|
1555
|
+
//#region src/infra/install-source-utils.ts
|
|
1556
|
+
async function withTempDir(prefix, fn) {
|
|
1557
|
+
const tmpDir = await fs$1.mkdtemp(path.join(os.tmpdir(), prefix));
|
|
1558
|
+
try {
|
|
1559
|
+
return await fn(tmpDir);
|
|
1560
|
+
} finally {
|
|
1561
|
+
await fs$1.rm(tmpDir, {
|
|
1562
|
+
recursive: true,
|
|
1563
|
+
force: true
|
|
1564
|
+
}).catch(() => void 0);
|
|
1565
|
+
}
|
|
1566
|
+
}
|
|
1567
|
+
async function resolveArchiveSourcePath(archivePath) {
|
|
1568
|
+
const resolved = resolveUserPath(archivePath);
|
|
1569
|
+
if (!await fileExists(resolved)) return {
|
|
1570
|
+
ok: false,
|
|
1571
|
+
error: `archive not found: ${resolved}`
|
|
1572
|
+
};
|
|
1573
|
+
if (!resolveArchiveKind(resolved)) return {
|
|
1574
|
+
ok: false,
|
|
1575
|
+
error: `unsupported archive: ${resolved}`
|
|
1576
|
+
};
|
|
1577
|
+
return {
|
|
1578
|
+
ok: true,
|
|
1579
|
+
path: resolved
|
|
1580
|
+
};
|
|
1581
|
+
}
|
|
1582
|
+
function toOptionalString(value) {
|
|
1583
|
+
if (typeof value !== "string") return;
|
|
1584
|
+
const trimmed = value.trim();
|
|
1585
|
+
return trimmed.length > 0 ? trimmed : void 0;
|
|
1586
|
+
}
|
|
1587
|
+
function parseResolvedSpecFromId(id) {
|
|
1588
|
+
const at = id.lastIndexOf("@");
|
|
1589
|
+
if (at <= 0 || at >= id.length - 1) return;
|
|
1590
|
+
const name = id.slice(0, at).trim();
|
|
1591
|
+
const version = id.slice(at + 1).trim();
|
|
1592
|
+
if (!name || !version) return;
|
|
1593
|
+
return `${name}@${version}`;
|
|
1594
|
+
}
|
|
1595
|
+
function normalizeNpmPackEntry(entry) {
|
|
1596
|
+
if (!entry || typeof entry !== "object") return null;
|
|
1597
|
+
const rec = entry;
|
|
1598
|
+
const name = toOptionalString(rec.name);
|
|
1599
|
+
const version = toOptionalString(rec.version);
|
|
1600
|
+
const id = toOptionalString(rec.id);
|
|
1601
|
+
const resolvedSpec = (name && version ? `${name}@${version}` : void 0) ?? (id ? parseResolvedSpecFromId(id) : void 0);
|
|
1602
|
+
return {
|
|
1603
|
+
filename: toOptionalString(rec.filename),
|
|
1604
|
+
metadata: {
|
|
1605
|
+
name,
|
|
1606
|
+
version,
|
|
1607
|
+
resolvedSpec,
|
|
1608
|
+
integrity: toOptionalString(rec.integrity),
|
|
1609
|
+
shasum: toOptionalString(rec.shasum)
|
|
1610
|
+
}
|
|
1611
|
+
};
|
|
1612
|
+
}
|
|
1613
|
+
function parseNpmPackJsonOutput(raw) {
|
|
1614
|
+
const trimmed = raw.trim();
|
|
1615
|
+
if (!trimmed) return null;
|
|
1616
|
+
const candidates = [trimmed];
|
|
1617
|
+
const arrayStart = trimmed.indexOf("[");
|
|
1618
|
+
if (arrayStart > 0) candidates.push(trimmed.slice(arrayStart));
|
|
1619
|
+
for (const candidate of candidates) {
|
|
1620
|
+
let parsed;
|
|
1621
|
+
try {
|
|
1622
|
+
parsed = JSON.parse(candidate);
|
|
1623
|
+
} catch {
|
|
1624
|
+
continue;
|
|
1625
|
+
}
|
|
1626
|
+
const entries = Array.isArray(parsed) ? parsed : [parsed];
|
|
1627
|
+
let fallback = null;
|
|
1628
|
+
for (let i = entries.length - 1; i >= 0; i -= 1) {
|
|
1629
|
+
const normalized = normalizeNpmPackEntry(entries[i]);
|
|
1630
|
+
if (!normalized) continue;
|
|
1631
|
+
if (!fallback) fallback = normalized;
|
|
1632
|
+
if (normalized.filename) return normalized;
|
|
1633
|
+
}
|
|
1634
|
+
if (fallback) return fallback;
|
|
1635
|
+
}
|
|
1636
|
+
return null;
|
|
1637
|
+
}
|
|
1638
|
+
function parsePackedArchiveFromStdout(stdout) {
|
|
1639
|
+
const lines = stdout.split(/\r?\n/).map((line) => line.trim()).filter(Boolean);
|
|
1640
|
+
for (let index = lines.length - 1; index >= 0; index -= 1) {
|
|
1641
|
+
const match = lines[index]?.match(/([^\s"']+\.tgz)/);
|
|
1642
|
+
if (match?.[1]) return match[1];
|
|
1643
|
+
}
|
|
1644
|
+
}
|
|
1645
|
+
async function findPackedArchiveInDir(cwd) {
|
|
1646
|
+
const archives = (await fs$1.readdir(cwd, { withFileTypes: true }).catch(() => [])).filter((entry) => entry.isFile() && entry.name.endsWith(".tgz"));
|
|
1647
|
+
if (archives.length === 0) return;
|
|
1648
|
+
if (archives.length === 1) return archives[0]?.name;
|
|
1649
|
+
const sortedByMtime = await Promise.all(archives.map(async (entry) => ({
|
|
1650
|
+
name: entry.name,
|
|
1651
|
+
mtimeMs: (await fs$1.stat(path.join(cwd, entry.name))).mtimeMs
|
|
1652
|
+
})));
|
|
1653
|
+
sortedByMtime.sort((a, b) => b.mtimeMs - a.mtimeMs);
|
|
1654
|
+
return sortedByMtime[0]?.name;
|
|
1655
|
+
}
|
|
1656
|
+
async function packNpmSpecToArchive(params) {
|
|
1657
|
+
const res = await runCommandWithTimeout([
|
|
1658
|
+
"npm",
|
|
1659
|
+
"pack",
|
|
1660
|
+
params.spec,
|
|
1661
|
+
"--ignore-scripts",
|
|
1662
|
+
"--json"
|
|
1663
|
+
], {
|
|
1664
|
+
timeoutMs: Math.max(params.timeoutMs, 3e5),
|
|
1665
|
+
cwd: params.cwd,
|
|
1666
|
+
env: {
|
|
1667
|
+
COREPACK_ENABLE_DOWNLOAD_PROMPT: "0",
|
|
1668
|
+
NPM_CONFIG_IGNORE_SCRIPTS: "true"
|
|
1669
|
+
}
|
|
1670
|
+
});
|
|
1671
|
+
if (res.code !== 0) {
|
|
1672
|
+
const raw = res.stderr.trim() || res.stdout.trim();
|
|
1673
|
+
if (/E404|is not in this registry/i.test(raw)) return {
|
|
1674
|
+
ok: false,
|
|
1675
|
+
error: `Package not found on npm: ${params.spec}. See https://docs.fased.ai/tools/plugin for installable plugins.`
|
|
1676
|
+
};
|
|
1677
|
+
return {
|
|
1678
|
+
ok: false,
|
|
1679
|
+
error: `npm pack failed: ${raw}`
|
|
1680
|
+
};
|
|
1681
|
+
}
|
|
1682
|
+
const parsedJson = parseNpmPackJsonOutput(res.stdout || "");
|
|
1683
|
+
let packed = parsedJson?.filename ?? parsePackedArchiveFromStdout(res.stdout || "");
|
|
1684
|
+
if (!packed) packed = await findPackedArchiveInDir(params.cwd);
|
|
1685
|
+
if (!packed) return {
|
|
1686
|
+
ok: false,
|
|
1687
|
+
error: "npm pack produced no archive"
|
|
1688
|
+
};
|
|
1689
|
+
let archivePath = path.isAbsolute(packed) ? packed : path.join(params.cwd, packed);
|
|
1690
|
+
if (!await fileExists(archivePath)) {
|
|
1691
|
+
const fallbackPacked = await findPackedArchiveInDir(params.cwd);
|
|
1692
|
+
if (!fallbackPacked) return {
|
|
1693
|
+
ok: false,
|
|
1694
|
+
error: "npm pack produced no archive"
|
|
1695
|
+
};
|
|
1696
|
+
archivePath = path.join(params.cwd, fallbackPacked);
|
|
1697
|
+
}
|
|
1698
|
+
return {
|
|
1699
|
+
ok: true,
|
|
1700
|
+
archivePath,
|
|
1701
|
+
metadata: parsedJson?.metadata ?? {}
|
|
1702
|
+
};
|
|
1703
|
+
}
|
|
1704
|
+
|
|
1705
|
+
//#endregion
|
|
1706
|
+
//#region src/infra/install-flow.ts
|
|
1707
|
+
async function withExtractedArchiveRoot(params) {
|
|
1708
|
+
return await withTempDir(params.tempDirPrefix, async (tmpDir) => {
|
|
1709
|
+
const extractDir = path.join(tmpDir, "extract");
|
|
1710
|
+
await fs$1.mkdir(extractDir, { recursive: true });
|
|
1711
|
+
params.logger?.info?.(`Extracting ${params.archivePath}…`);
|
|
1712
|
+
try {
|
|
1713
|
+
await extractArchive({
|
|
1714
|
+
archivePath: params.archivePath,
|
|
1715
|
+
destDir: extractDir,
|
|
1716
|
+
timeoutMs: params.timeoutMs,
|
|
1717
|
+
logger: params.logger
|
|
1718
|
+
});
|
|
1719
|
+
} catch (err) {
|
|
1720
|
+
return {
|
|
1721
|
+
ok: false,
|
|
1722
|
+
error: `failed to extract archive: ${String(err)}`
|
|
1723
|
+
};
|
|
1724
|
+
}
|
|
1725
|
+
let rootDir = "";
|
|
1726
|
+
try {
|
|
1727
|
+
rootDir = await resolveInstallRootDir(extractDir, params.rootMarkers);
|
|
1728
|
+
} catch (err) {
|
|
1729
|
+
return {
|
|
1730
|
+
ok: false,
|
|
1731
|
+
error: String(err)
|
|
1732
|
+
};
|
|
1733
|
+
}
|
|
1734
|
+
return await params.onExtracted(rootDir);
|
|
1735
|
+
});
|
|
1736
|
+
}
|
|
1737
|
+
async function hasAnyRootMarker(rootDir, rootMarkers) {
|
|
1738
|
+
for (const marker of rootMarkers) {
|
|
1739
|
+
if (!marker || path.isAbsolute(marker) || marker.includes("..")) continue;
|
|
1740
|
+
if (await fileExists(path.join(rootDir, marker))) return true;
|
|
1741
|
+
}
|
|
1742
|
+
return false;
|
|
1743
|
+
}
|
|
1744
|
+
async function resolveInstallRootDir(extractDir, rootMarkers) {
|
|
1745
|
+
const markers = rootMarkers?.filter(Boolean) ?? [];
|
|
1746
|
+
if (markers.length === 0) return await resolvePackedRootDir(extractDir);
|
|
1747
|
+
if (await hasAnyRootMarker(extractDir, markers)) return extractDir;
|
|
1748
|
+
const entries = await fs$1.readdir(extractDir, { withFileTypes: true });
|
|
1749
|
+
const markerDirs = [];
|
|
1750
|
+
for (const entry of entries) {
|
|
1751
|
+
if (!entry.isDirectory()) continue;
|
|
1752
|
+
if (await hasAnyRootMarker(path.join(extractDir, entry.name), markers)) markerDirs.push(entry.name);
|
|
1753
|
+
}
|
|
1754
|
+
if (markerDirs.length === 1) return path.join(extractDir, markerDirs[0]);
|
|
1755
|
+
if (markerDirs.length > 1) throw new Error(`unexpected archive layout (marker dirs: ${markerDirs.join(", ")})`);
|
|
1756
|
+
return await resolvePackedRootDir(extractDir);
|
|
1757
|
+
}
|
|
1758
|
+
|
|
1759
|
+
//#endregion
|
|
1760
|
+
//#region src/infra/install-mode-options.ts
|
|
1761
|
+
function resolveInstallModeOptions(params, defaultLogger) {
|
|
1762
|
+
return {
|
|
1763
|
+
logger: params.logger ?? defaultLogger,
|
|
1764
|
+
mode: params.mode ?? "install",
|
|
1765
|
+
dryRun: params.dryRun ?? false
|
|
1766
|
+
};
|
|
1767
|
+
}
|
|
1768
|
+
function resolveTimedInstallModeOptions(params, defaultLogger, defaultTimeoutMs = 12e4) {
|
|
1769
|
+
return {
|
|
1770
|
+
...resolveInstallModeOptions(params, defaultLogger),
|
|
1771
|
+
timeoutMs: params.timeoutMs ?? defaultTimeoutMs
|
|
1772
|
+
};
|
|
1773
|
+
}
|
|
1774
|
+
|
|
1775
|
+
//#endregion
|
|
1776
|
+
//#region src/infra/install-package-dir.ts
|
|
1777
|
+
function isObjectRecord(value) {
|
|
1778
|
+
return Boolean(value) && typeof value === "object" && !Array.isArray(value);
|
|
1779
|
+
}
|
|
1780
|
+
async function sanitizeManifestForNpmInstall(targetDir) {
|
|
1781
|
+
const manifestPath = path.join(targetDir, "package.json");
|
|
1782
|
+
let manifestRaw = "";
|
|
1783
|
+
try {
|
|
1784
|
+
manifestRaw = await fs$1.readFile(manifestPath, "utf-8");
|
|
1785
|
+
} catch {
|
|
1786
|
+
return;
|
|
1787
|
+
}
|
|
1788
|
+
let manifest;
|
|
1789
|
+
try {
|
|
1790
|
+
const parsed = JSON.parse(manifestRaw);
|
|
1791
|
+
if (!isObjectRecord(parsed)) return;
|
|
1792
|
+
manifest = parsed;
|
|
1793
|
+
} catch {
|
|
1794
|
+
return;
|
|
1795
|
+
}
|
|
1796
|
+
const devDependencies = manifest.devDependencies;
|
|
1797
|
+
if (!isObjectRecord(devDependencies)) return;
|
|
1798
|
+
const filteredEntries = Object.entries(devDependencies).filter(([, rawSpec]) => {
|
|
1799
|
+
return !(typeof rawSpec === "string" ? rawSpec.trim() : "").startsWith("workspace:");
|
|
1800
|
+
});
|
|
1801
|
+
if (filteredEntries.length === Object.keys(devDependencies).length) return;
|
|
1802
|
+
if (filteredEntries.length === 0) delete manifest.devDependencies;
|
|
1803
|
+
else manifest.devDependencies = Object.fromEntries(filteredEntries);
|
|
1804
|
+
await fs$1.writeFile(manifestPath, `${JSON.stringify(manifest, null, 2)}\n`, "utf-8");
|
|
1805
|
+
}
|
|
1806
|
+
async function installPackageDir(params) {
|
|
1807
|
+
params.logger?.info?.(`Installing to ${params.targetDir}…`);
|
|
1808
|
+
let backupDir = null;
|
|
1809
|
+
if (params.mode === "update" && await fileExists(params.targetDir)) {
|
|
1810
|
+
const backupRoot = path.join(path.dirname(params.targetDir), ".fased-install-backups");
|
|
1811
|
+
backupDir = path.join(backupRoot, `${path.basename(params.targetDir)}-${Date.now()}`);
|
|
1812
|
+
await fs$1.mkdir(backupRoot, { recursive: true });
|
|
1813
|
+
await fs$1.rename(params.targetDir, backupDir);
|
|
1814
|
+
}
|
|
1815
|
+
const rollback = async () => {
|
|
1816
|
+
if (!backupDir) return;
|
|
1817
|
+
await fs$1.rm(params.targetDir, {
|
|
1818
|
+
recursive: true,
|
|
1819
|
+
force: true
|
|
1820
|
+
}).catch(() => void 0);
|
|
1821
|
+
await fs$1.rename(backupDir, params.targetDir).catch(() => void 0);
|
|
1822
|
+
};
|
|
1823
|
+
try {
|
|
1824
|
+
await fs$1.cp(params.sourceDir, params.targetDir, { recursive: true });
|
|
1825
|
+
} catch (err) {
|
|
1826
|
+
await rollback();
|
|
1827
|
+
return {
|
|
1828
|
+
ok: false,
|
|
1829
|
+
error: `${params.copyErrorPrefix}: ${String(err)}`
|
|
1830
|
+
};
|
|
1831
|
+
}
|
|
1832
|
+
try {
|
|
1833
|
+
await params.afterCopy?.();
|
|
1834
|
+
} catch (err) {
|
|
1835
|
+
await rollback();
|
|
1836
|
+
return {
|
|
1837
|
+
ok: false,
|
|
1838
|
+
error: `post-copy validation failed: ${String(err)}`
|
|
1839
|
+
};
|
|
1840
|
+
}
|
|
1841
|
+
if (params.hasDeps) {
|
|
1842
|
+
await sanitizeManifestForNpmInstall(params.targetDir);
|
|
1843
|
+
params.logger?.info?.(params.depsLogMessage);
|
|
1844
|
+
const npmRes = await runCommandWithTimeout([
|
|
1845
|
+
"npm",
|
|
1846
|
+
"install",
|
|
1847
|
+
"--omit=dev",
|
|
1848
|
+
"--loglevel=error",
|
|
1849
|
+
"--ignore-scripts",
|
|
1850
|
+
"--legacy-peer-deps"
|
|
1851
|
+
], {
|
|
1852
|
+
timeoutMs: Math.max(params.timeoutMs, 3e5),
|
|
1853
|
+
cwd: params.targetDir
|
|
1854
|
+
});
|
|
1855
|
+
if (npmRes.code !== 0) {
|
|
1856
|
+
await rollback();
|
|
1857
|
+
return {
|
|
1858
|
+
ok: false,
|
|
1859
|
+
error: `npm install failed: ${npmRes.stderr.trim() || npmRes.stdout.trim()}`
|
|
1860
|
+
};
|
|
1861
|
+
}
|
|
1862
|
+
}
|
|
1863
|
+
try {
|
|
1864
|
+
await params.afterInstall?.();
|
|
1865
|
+
} catch (err) {
|
|
1866
|
+
await rollback();
|
|
1867
|
+
return {
|
|
1868
|
+
ok: false,
|
|
1869
|
+
error: `post-install validation failed: ${String(err)}`
|
|
1870
|
+
};
|
|
1871
|
+
}
|
|
1872
|
+
if (backupDir) await fs$1.rm(backupDir, {
|
|
1873
|
+
recursive: true,
|
|
1874
|
+
force: true
|
|
1875
|
+
}).catch(() => void 0);
|
|
1876
|
+
return { ok: true };
|
|
1877
|
+
}
|
|
1476
1878
|
|
|
1477
1879
|
//#endregion
|
|
1478
1880
|
//#region src/infra/install-safe-path.ts
|
|
1881
|
+
function unscopedPackageName(name) {
|
|
1882
|
+
const trimmed = name.trim();
|
|
1883
|
+
if (!trimmed) return trimmed;
|
|
1884
|
+
return trimmed.includes("/") ? trimmed.split("/").pop() ?? trimmed : trimmed;
|
|
1885
|
+
}
|
|
1479
1886
|
function safeDirName(input) {
|
|
1480
1887
|
const trimmed = input.trim();
|
|
1481
1888
|
if (!trimmed) return trimmed;
|
|
@@ -1496,6 +1903,150 @@ function resolveSafeInstallDir(params) {
|
|
|
1496
1903
|
};
|
|
1497
1904
|
}
|
|
1498
1905
|
|
|
1906
|
+
//#endregion
|
|
1907
|
+
//#region src/infra/npm-integrity.ts
|
|
1908
|
+
async function resolveNpmIntegrityDrift(params) {
|
|
1909
|
+
if (!params.expectedIntegrity || !params.resolution.integrity) return { proceed: true };
|
|
1910
|
+
if (params.expectedIntegrity === params.resolution.integrity) return { proceed: true };
|
|
1911
|
+
const integrityDrift = {
|
|
1912
|
+
expectedIntegrity: params.expectedIntegrity,
|
|
1913
|
+
actualIntegrity: params.resolution.integrity
|
|
1914
|
+
};
|
|
1915
|
+
const payload = params.createPayload({
|
|
1916
|
+
spec: params.spec,
|
|
1917
|
+
expectedIntegrity: integrityDrift.expectedIntegrity,
|
|
1918
|
+
actualIntegrity: integrityDrift.actualIntegrity,
|
|
1919
|
+
resolution: params.resolution
|
|
1920
|
+
});
|
|
1921
|
+
let proceed = true;
|
|
1922
|
+
if (params.onIntegrityDrift) proceed = await params.onIntegrityDrift(payload);
|
|
1923
|
+
else params.warn?.(payload);
|
|
1924
|
+
return {
|
|
1925
|
+
integrityDrift,
|
|
1926
|
+
proceed,
|
|
1927
|
+
payload
|
|
1928
|
+
};
|
|
1929
|
+
}
|
|
1930
|
+
async function resolveNpmIntegrityDriftWithDefaultMessage(params) {
|
|
1931
|
+
const driftResult = await resolveNpmIntegrityDrift({
|
|
1932
|
+
spec: params.spec,
|
|
1933
|
+
expectedIntegrity: params.expectedIntegrity,
|
|
1934
|
+
resolution: params.resolution,
|
|
1935
|
+
createPayload: (drift) => ({ ...drift }),
|
|
1936
|
+
onIntegrityDrift: params.onIntegrityDrift,
|
|
1937
|
+
warn: (driftPayload) => {
|
|
1938
|
+
params.warn?.(`Integrity drift detected for ${driftPayload.resolution.resolvedSpec ?? driftPayload.spec}: expected ${driftPayload.expectedIntegrity}, got ${driftPayload.actualIntegrity}`);
|
|
1939
|
+
}
|
|
1940
|
+
});
|
|
1941
|
+
if (!driftResult.proceed && driftResult.payload) return {
|
|
1942
|
+
integrityDrift: driftResult.integrityDrift,
|
|
1943
|
+
error: `aborted: npm package integrity drift detected for ${driftResult.payload.resolution.resolvedSpec ?? driftResult.payload.spec}`
|
|
1944
|
+
};
|
|
1945
|
+
return { integrityDrift: driftResult.integrityDrift };
|
|
1946
|
+
}
|
|
1947
|
+
|
|
1948
|
+
//#endregion
|
|
1949
|
+
//#region src/infra/npm-pack-install.ts
|
|
1950
|
+
async function installFromNpmSpecArchiveWithInstaller(params) {
|
|
1951
|
+
return await installFromNpmSpecArchive({
|
|
1952
|
+
tempDirPrefix: params.tempDirPrefix,
|
|
1953
|
+
spec: params.spec,
|
|
1954
|
+
timeoutMs: params.timeoutMs,
|
|
1955
|
+
expectedIntegrity: params.expectedIntegrity,
|
|
1956
|
+
onIntegrityDrift: params.onIntegrityDrift,
|
|
1957
|
+
warn: params.warn,
|
|
1958
|
+
installFromArchive: async ({ archivePath }) => await params.installFromArchive({
|
|
1959
|
+
archivePath,
|
|
1960
|
+
...params.archiveInstallParams
|
|
1961
|
+
})
|
|
1962
|
+
});
|
|
1963
|
+
}
|
|
1964
|
+
function isSuccessfulInstallResult(result) {
|
|
1965
|
+
return result.ok;
|
|
1966
|
+
}
|
|
1967
|
+
function describeMissingNpmPackMetadata(metadata) {
|
|
1968
|
+
const missing = [];
|
|
1969
|
+
if (!metadata.name) missing.push("name");
|
|
1970
|
+
if (!metadata.version) missing.push("version");
|
|
1971
|
+
if (!metadata.integrity && !metadata.shasum) missing.push("integrity or shasum");
|
|
1972
|
+
return missing;
|
|
1973
|
+
}
|
|
1974
|
+
function validateNpmPackMetadata(params) {
|
|
1975
|
+
const missing = describeMissingNpmPackMetadata(params.metadata);
|
|
1976
|
+
if (missing.length === 0) return null;
|
|
1977
|
+
return `npm pack did not report ${missing.join(", ")} for ${params.spec}; refusing unpinned npm plugin install`;
|
|
1978
|
+
}
|
|
1979
|
+
function finalizeNpmSpecArchiveInstall(flowResult) {
|
|
1980
|
+
if (!flowResult.ok) return flowResult;
|
|
1981
|
+
const installResult = flowResult.installResult;
|
|
1982
|
+
if (!isSuccessfulInstallResult(installResult)) return installResult;
|
|
1983
|
+
return {
|
|
1984
|
+
...installResult,
|
|
1985
|
+
npmResolution: flowResult.npmResolution,
|
|
1986
|
+
...flowResult.integrityDrift ? { integrityDrift: flowResult.integrityDrift } : {}
|
|
1987
|
+
};
|
|
1988
|
+
}
|
|
1989
|
+
async function installFromNpmSpecArchive(params) {
|
|
1990
|
+
return await withTempDir(params.tempDirPrefix, async (tmpDir) => {
|
|
1991
|
+
const packedResult = await packNpmSpecToArchive({
|
|
1992
|
+
spec: params.spec,
|
|
1993
|
+
timeoutMs: params.timeoutMs,
|
|
1994
|
+
cwd: tmpDir
|
|
1995
|
+
});
|
|
1996
|
+
if (!packedResult.ok) return packedResult;
|
|
1997
|
+
const metadataError = validateNpmPackMetadata({
|
|
1998
|
+
spec: params.spec,
|
|
1999
|
+
metadata: packedResult.metadata
|
|
2000
|
+
});
|
|
2001
|
+
if (metadataError) return {
|
|
2002
|
+
ok: false,
|
|
2003
|
+
error: metadataError
|
|
2004
|
+
};
|
|
2005
|
+
const npmResolution = {
|
|
2006
|
+
...packedResult.metadata,
|
|
2007
|
+
resolvedAt: (/* @__PURE__ */ new Date()).toISOString()
|
|
2008
|
+
};
|
|
2009
|
+
const driftResult = await resolveNpmIntegrityDriftWithDefaultMessage({
|
|
2010
|
+
spec: params.spec,
|
|
2011
|
+
expectedIntegrity: params.expectedIntegrity,
|
|
2012
|
+
resolution: npmResolution,
|
|
2013
|
+
onIntegrityDrift: params.onIntegrityDrift,
|
|
2014
|
+
warn: params.warn
|
|
2015
|
+
});
|
|
2016
|
+
if (driftResult.error) return {
|
|
2017
|
+
ok: false,
|
|
2018
|
+
error: driftResult.error
|
|
2019
|
+
};
|
|
2020
|
+
return {
|
|
2021
|
+
ok: true,
|
|
2022
|
+
installResult: await params.installFromArchive({ archivePath: packedResult.archivePath }),
|
|
2023
|
+
npmResolution,
|
|
2024
|
+
integrityDrift: driftResult.integrityDrift
|
|
2025
|
+
};
|
|
2026
|
+
});
|
|
2027
|
+
}
|
|
2028
|
+
|
|
2029
|
+
//#endregion
|
|
2030
|
+
//#region src/infra/npm-registry-spec.ts
|
|
2031
|
+
function validateRegistryNpmSpec(rawSpec) {
|
|
2032
|
+
const spec = rawSpec.trim();
|
|
2033
|
+
if (!spec) return "missing npm spec";
|
|
2034
|
+
if (/\s/.test(spec)) return "unsupported npm spec: whitespace is not allowed";
|
|
2035
|
+
if (spec.includes("://")) return "unsupported npm spec: URLs are not allowed";
|
|
2036
|
+
if (spec.includes("#")) return "unsupported npm spec: git refs are not allowed";
|
|
2037
|
+
if (spec.includes(":")) return "unsupported npm spec: protocol specs are not allowed";
|
|
2038
|
+
const at = spec.lastIndexOf("@");
|
|
2039
|
+
const hasVersion = at > 0;
|
|
2040
|
+
const name = hasVersion ? spec.slice(0, at) : spec;
|
|
2041
|
+
const version = hasVersion ? spec.slice(at + 1) : "";
|
|
2042
|
+
if (!(name.startsWith("@") ? /^@[a-z0-9][a-z0-9-._~]*\/[a-z0-9][a-z0-9-._~]*$/.test(name) : /^[a-z0-9][a-z0-9-._~]*$/.test(name))) return "unsupported npm spec: expected <name> or <name>@<version> from the npm registry";
|
|
2043
|
+
if (hasVersion) {
|
|
2044
|
+
if (!version) return "unsupported npm spec: missing version/tag after @";
|
|
2045
|
+
if (/[\\/]/.test(version)) return "unsupported npm spec: invalid version/tag";
|
|
2046
|
+
}
|
|
2047
|
+
return null;
|
|
2048
|
+
}
|
|
2049
|
+
|
|
1499
2050
|
//#endregion
|
|
1500
2051
|
//#region src/security/scan-paths.ts
|
|
1501
2052
|
function isPathInside$1(basePath, candidatePath) {
|
|
@@ -1504,6 +2055,9 @@ function isPathInside$1(basePath, candidatePath) {
|
|
|
1504
2055
|
const rel = path.relative(base, candidate);
|
|
1505
2056
|
return rel === "" || !rel.startsWith(`..${path.sep}`) && rel !== ".." && !path.isAbsolute(rel);
|
|
1506
2057
|
}
|
|
2058
|
+
function extensionUsesSkippedScannerPath(entry) {
|
|
2059
|
+
return entry.split(/[\\/]+/).filter(Boolean).some((segment) => segment === "node_modules" || segment.startsWith(".") && segment !== "." && segment !== "..");
|
|
2060
|
+
}
|
|
1507
2061
|
|
|
1508
2062
|
//#endregion
|
|
1509
2063
|
//#region src/infra/errors.ts
|
|
@@ -1519,6 +2073,12 @@ function extractErrorCode(err) {
|
|
|
1519
2073
|
function isErrno(err) {
|
|
1520
2074
|
return Boolean(err && typeof err === "object" && "code" in err);
|
|
1521
2075
|
}
|
|
2076
|
+
/**
|
|
2077
|
+
* Check if an error has a specific errno code.
|
|
2078
|
+
*/
|
|
2079
|
+
function hasErrnoCode(err, code) {
|
|
2080
|
+
return isErrno(err) && err.code === code;
|
|
2081
|
+
}
|
|
1522
2082
|
function formatErrorMessage(err) {
|
|
1523
2083
|
let formatted;
|
|
1524
2084
|
if (err instanceof Error) formatted = err.message || err.name || "Error";
|
|
@@ -1539,7 +2099,243 @@ function formatUncaughtError(err) {
|
|
|
1539
2099
|
|
|
1540
2100
|
//#endregion
|
|
1541
2101
|
//#region src/security/skill-scanner.ts
|
|
2102
|
+
const SCANNABLE_EXTENSIONS = new Set([
|
|
2103
|
+
".js",
|
|
2104
|
+
".ts",
|
|
2105
|
+
".mjs",
|
|
2106
|
+
".cjs",
|
|
2107
|
+
".mts",
|
|
2108
|
+
".cts",
|
|
2109
|
+
".jsx",
|
|
2110
|
+
".tsx"
|
|
2111
|
+
]);
|
|
2112
|
+
const DEFAULT_MAX_SCAN_FILES = 500;
|
|
1542
2113
|
const DEFAULT_MAX_FILE_BYTES = 1024 * 1024;
|
|
2114
|
+
function isScannable(filePath) {
|
|
2115
|
+
return SCANNABLE_EXTENSIONS.has(path.extname(filePath).toLowerCase());
|
|
2116
|
+
}
|
|
2117
|
+
const LINE_RULES = [
|
|
2118
|
+
{
|
|
2119
|
+
ruleId: "dangerous-exec",
|
|
2120
|
+
severity: "critical",
|
|
2121
|
+
message: "Shell command execution detected (child_process)",
|
|
2122
|
+
pattern: /\b(exec|execSync|spawn|spawnSync|execFile|execFileSync)\s*\(/,
|
|
2123
|
+
requiresContext: /child_process/
|
|
2124
|
+
},
|
|
2125
|
+
{
|
|
2126
|
+
ruleId: "dynamic-code-execution",
|
|
2127
|
+
severity: "critical",
|
|
2128
|
+
message: "Dynamic code execution detected",
|
|
2129
|
+
pattern: /\beval\s*\(|new\s+Function\s*\(/
|
|
2130
|
+
},
|
|
2131
|
+
{
|
|
2132
|
+
ruleId: "crypto-mining",
|
|
2133
|
+
severity: "critical",
|
|
2134
|
+
message: "Possible crypto-mining reference detected",
|
|
2135
|
+
pattern: /stratum\+tcp|stratum\+ssl|coinhive|cryptonight|xmrig/i
|
|
2136
|
+
},
|
|
2137
|
+
{
|
|
2138
|
+
ruleId: "suspicious-network",
|
|
2139
|
+
severity: "warn",
|
|
2140
|
+
message: "WebSocket connection to non-standard port",
|
|
2141
|
+
pattern: /new\s+WebSocket\s*\(\s*["']wss?:\/\/[^"']*:(\d+)/
|
|
2142
|
+
}
|
|
2143
|
+
];
|
|
2144
|
+
const STANDARD_PORTS = new Set([
|
|
2145
|
+
80,
|
|
2146
|
+
443,
|
|
2147
|
+
8080,
|
|
2148
|
+
8443,
|
|
2149
|
+
3e3
|
|
2150
|
+
]);
|
|
2151
|
+
const SOURCE_RULES = [
|
|
2152
|
+
{
|
|
2153
|
+
ruleId: "potential-exfiltration",
|
|
2154
|
+
severity: "warn",
|
|
2155
|
+
message: "File read combined with network send — possible data exfiltration",
|
|
2156
|
+
pattern: /readFileSync|readFile/,
|
|
2157
|
+
requiresContext: /\bfetch\b|\bpost\b|http\.request/i
|
|
2158
|
+
},
|
|
2159
|
+
{
|
|
2160
|
+
ruleId: "obfuscated-code",
|
|
2161
|
+
severity: "warn",
|
|
2162
|
+
message: "Hex-encoded string sequence detected (possible obfuscation)",
|
|
2163
|
+
pattern: /(\\x[0-9a-fA-F]{2}){6,}/
|
|
2164
|
+
},
|
|
2165
|
+
{
|
|
2166
|
+
ruleId: "obfuscated-code",
|
|
2167
|
+
severity: "warn",
|
|
2168
|
+
message: "Large base64 payload with decode call detected (possible obfuscation)",
|
|
2169
|
+
pattern: /(?:atob|Buffer\.from)\s*\(\s*["'][A-Za-z0-9+/=]{200,}["']/
|
|
2170
|
+
},
|
|
2171
|
+
{
|
|
2172
|
+
ruleId: "env-harvesting",
|
|
2173
|
+
severity: "critical",
|
|
2174
|
+
message: "Environment variable access combined with network send — possible credential harvesting",
|
|
2175
|
+
pattern: /process\.env/,
|
|
2176
|
+
requiresContext: /\bfetch\b|\bpost\b|http\.request/i
|
|
2177
|
+
}
|
|
2178
|
+
];
|
|
2179
|
+
function truncateEvidence(evidence, maxLen = 120) {
|
|
2180
|
+
if (evidence.length <= maxLen) return evidence;
|
|
2181
|
+
return `${evidence.slice(0, maxLen)}…`;
|
|
2182
|
+
}
|
|
2183
|
+
function scanSource(source, filePath) {
|
|
2184
|
+
const findings = [];
|
|
2185
|
+
const lines = source.split("\n");
|
|
2186
|
+
const matchedLineRules = /* @__PURE__ */ new Set();
|
|
2187
|
+
for (const rule of LINE_RULES) {
|
|
2188
|
+
if (matchedLineRules.has(rule.ruleId)) continue;
|
|
2189
|
+
if (rule.requiresContext && !rule.requiresContext.test(source)) continue;
|
|
2190
|
+
for (let i = 0; i < lines.length; i++) {
|
|
2191
|
+
const line = lines[i];
|
|
2192
|
+
const match = rule.pattern.exec(line);
|
|
2193
|
+
if (!match) continue;
|
|
2194
|
+
if (rule.ruleId === "suspicious-network") {
|
|
2195
|
+
const port = parseInt(match[1], 10);
|
|
2196
|
+
if (STANDARD_PORTS.has(port)) continue;
|
|
2197
|
+
}
|
|
2198
|
+
findings.push({
|
|
2199
|
+
ruleId: rule.ruleId,
|
|
2200
|
+
severity: rule.severity,
|
|
2201
|
+
file: filePath,
|
|
2202
|
+
line: i + 1,
|
|
2203
|
+
message: rule.message,
|
|
2204
|
+
evidence: truncateEvidence(line.trim())
|
|
2205
|
+
});
|
|
2206
|
+
matchedLineRules.add(rule.ruleId);
|
|
2207
|
+
break;
|
|
2208
|
+
}
|
|
2209
|
+
}
|
|
2210
|
+
const matchedSourceRules = /* @__PURE__ */ new Set();
|
|
2211
|
+
for (const rule of SOURCE_RULES) {
|
|
2212
|
+
const ruleKey = `${rule.ruleId}::${rule.message}`;
|
|
2213
|
+
if (matchedSourceRules.has(ruleKey)) continue;
|
|
2214
|
+
if (!rule.pattern.test(source)) continue;
|
|
2215
|
+
if (rule.requiresContext && !rule.requiresContext.test(source)) continue;
|
|
2216
|
+
let matchLine = 0;
|
|
2217
|
+
let matchEvidence = "";
|
|
2218
|
+
for (let i = 0; i < lines.length; i++) if (rule.pattern.test(lines[i])) {
|
|
2219
|
+
matchLine = i + 1;
|
|
2220
|
+
matchEvidence = lines[i].trim();
|
|
2221
|
+
break;
|
|
2222
|
+
}
|
|
2223
|
+
if (matchLine === 0) {
|
|
2224
|
+
matchLine = 1;
|
|
2225
|
+
matchEvidence = source.slice(0, 120);
|
|
2226
|
+
}
|
|
2227
|
+
findings.push({
|
|
2228
|
+
ruleId: rule.ruleId,
|
|
2229
|
+
severity: rule.severity,
|
|
2230
|
+
file: filePath,
|
|
2231
|
+
line: matchLine,
|
|
2232
|
+
message: rule.message,
|
|
2233
|
+
evidence: truncateEvidence(matchEvidence)
|
|
2234
|
+
});
|
|
2235
|
+
matchedSourceRules.add(ruleKey);
|
|
2236
|
+
}
|
|
2237
|
+
return findings;
|
|
2238
|
+
}
|
|
2239
|
+
function normalizeScanOptions(opts) {
|
|
2240
|
+
return {
|
|
2241
|
+
includeFiles: opts?.includeFiles ?? [],
|
|
2242
|
+
maxFiles: Math.max(1, opts?.maxFiles ?? DEFAULT_MAX_SCAN_FILES),
|
|
2243
|
+
maxFileBytes: Math.max(1, opts?.maxFileBytes ?? DEFAULT_MAX_FILE_BYTES)
|
|
2244
|
+
};
|
|
2245
|
+
}
|
|
2246
|
+
async function walkDirWithLimit(dirPath, maxFiles) {
|
|
2247
|
+
const files = [];
|
|
2248
|
+
const stack = [dirPath];
|
|
2249
|
+
while (stack.length > 0 && files.length < maxFiles) {
|
|
2250
|
+
const currentDir = stack.pop();
|
|
2251
|
+
if (!currentDir) break;
|
|
2252
|
+
const entries = await fs$1.readdir(currentDir, { withFileTypes: true });
|
|
2253
|
+
for (const entry of entries) {
|
|
2254
|
+
if (files.length >= maxFiles) break;
|
|
2255
|
+
if (entry.name.startsWith(".") || entry.name === "node_modules") continue;
|
|
2256
|
+
const fullPath = path.join(currentDir, entry.name);
|
|
2257
|
+
if (entry.isDirectory()) stack.push(fullPath);
|
|
2258
|
+
else if (isScannable(entry.name)) files.push(fullPath);
|
|
2259
|
+
}
|
|
2260
|
+
}
|
|
2261
|
+
return files;
|
|
2262
|
+
}
|
|
2263
|
+
async function resolveForcedFiles(params) {
|
|
2264
|
+
if (params.includeFiles.length === 0) return [];
|
|
2265
|
+
const seen = /* @__PURE__ */ new Set();
|
|
2266
|
+
const out = [];
|
|
2267
|
+
for (const rawIncludePath of params.includeFiles) {
|
|
2268
|
+
const includePath = path.resolve(params.rootDir, rawIncludePath);
|
|
2269
|
+
if (!isPathInside$1(params.rootDir, includePath)) continue;
|
|
2270
|
+
if (!isScannable(includePath)) continue;
|
|
2271
|
+
if (seen.has(includePath)) continue;
|
|
2272
|
+
let st = null;
|
|
2273
|
+
try {
|
|
2274
|
+
st = await fs$1.stat(includePath);
|
|
2275
|
+
} catch (err) {
|
|
2276
|
+
if (hasErrnoCode(err, "ENOENT")) continue;
|
|
2277
|
+
throw err;
|
|
2278
|
+
}
|
|
2279
|
+
if (!st?.isFile()) continue;
|
|
2280
|
+
out.push(includePath);
|
|
2281
|
+
seen.add(includePath);
|
|
2282
|
+
}
|
|
2283
|
+
return out;
|
|
2284
|
+
}
|
|
2285
|
+
async function collectScannableFiles(dirPath, opts) {
|
|
2286
|
+
const forcedFiles = await resolveForcedFiles({
|
|
2287
|
+
rootDir: dirPath,
|
|
2288
|
+
includeFiles: opts.includeFiles
|
|
2289
|
+
});
|
|
2290
|
+
if (forcedFiles.length >= opts.maxFiles) return forcedFiles.slice(0, opts.maxFiles);
|
|
2291
|
+
const walkedFiles = await walkDirWithLimit(dirPath, opts.maxFiles);
|
|
2292
|
+
const seen = new Set(forcedFiles.map((f) => path.resolve(f)));
|
|
2293
|
+
const out = [...forcedFiles];
|
|
2294
|
+
for (const walkedFile of walkedFiles) {
|
|
2295
|
+
if (out.length >= opts.maxFiles) break;
|
|
2296
|
+
const resolved = path.resolve(walkedFile);
|
|
2297
|
+
if (seen.has(resolved)) continue;
|
|
2298
|
+
out.push(walkedFile);
|
|
2299
|
+
seen.add(resolved);
|
|
2300
|
+
}
|
|
2301
|
+
return out;
|
|
2302
|
+
}
|
|
2303
|
+
async function readScannableSource(filePath, maxFileBytes) {
|
|
2304
|
+
let st = null;
|
|
2305
|
+
try {
|
|
2306
|
+
st = await fs$1.stat(filePath);
|
|
2307
|
+
} catch (err) {
|
|
2308
|
+
if (hasErrnoCode(err, "ENOENT")) return null;
|
|
2309
|
+
throw err;
|
|
2310
|
+
}
|
|
2311
|
+
if (!st?.isFile() || st.size > maxFileBytes) return null;
|
|
2312
|
+
try {
|
|
2313
|
+
return await fs$1.readFile(filePath, "utf-8");
|
|
2314
|
+
} catch (err) {
|
|
2315
|
+
if (hasErrnoCode(err, "ENOENT")) return null;
|
|
2316
|
+
throw err;
|
|
2317
|
+
}
|
|
2318
|
+
}
|
|
2319
|
+
async function scanDirectoryWithSummary(dirPath, opts) {
|
|
2320
|
+
const scanOptions = normalizeScanOptions(opts);
|
|
2321
|
+
const files = await collectScannableFiles(dirPath, scanOptions);
|
|
2322
|
+
const allFindings = [];
|
|
2323
|
+
let scannedFiles = 0;
|
|
2324
|
+
for (const file of files) {
|
|
2325
|
+
const source = await readScannableSource(file, scanOptions.maxFileBytes);
|
|
2326
|
+
if (source == null) continue;
|
|
2327
|
+
scannedFiles += 1;
|
|
2328
|
+
const findings = scanSource(source, file);
|
|
2329
|
+
allFindings.push(...findings);
|
|
2330
|
+
}
|
|
2331
|
+
return {
|
|
2332
|
+
scannedFiles,
|
|
2333
|
+
critical: allFindings.filter((f) => f.severity === "critical").length,
|
|
2334
|
+
warn: allFindings.filter((f) => f.severity === "warn").length,
|
|
2335
|
+
info: allFindings.filter((f) => f.severity === "info").length,
|
|
2336
|
+
findings: allFindings
|
|
2337
|
+
};
|
|
2338
|
+
}
|
|
1543
2339
|
|
|
1544
2340
|
//#endregion
|
|
1545
2341
|
//#region src/project.ts
|
|
@@ -1736,6 +2532,7 @@ function loadPluginManifest(rootDir) {
|
|
|
1736
2532
|
manifestPath
|
|
1737
2533
|
};
|
|
1738
2534
|
const enabledByDefault = raw.enabledByDefault === true;
|
|
2535
|
+
const runtimeOnly = raw.runtimeOnly === true;
|
|
1739
2536
|
const legacyPluginIds = normalizeStringList(raw.legacyPluginIds);
|
|
1740
2537
|
const autoEnableWhenConfiguredProviders = normalizeStringList(raw.autoEnableWhenConfiguredProviders);
|
|
1741
2538
|
const kind = typeof raw.kind === "string" ? raw.kind : void 0;
|
|
@@ -1758,6 +2555,7 @@ function loadPluginManifest(rootDir) {
|
|
|
1758
2555
|
manifest: {
|
|
1759
2556
|
id,
|
|
1760
2557
|
configSchema,
|
|
2558
|
+
...runtimeOnly ? { runtimeOnly: true } : {},
|
|
1761
2559
|
...enabledByDefault ? { enabledByDefault } : {},
|
|
1762
2560
|
...legacyPluginIds.length > 0 ? { legacyPluginIds } : {},
|
|
1763
2561
|
...autoEnableWhenConfiguredProviders.length > 0 ? { autoEnableWhenConfiguredProviders } : {},
|
|
@@ -1790,14 +2588,120 @@ function getPackageManifestMetadata(manifest) {
|
|
|
1790
2588
|
return manifest[MANIFEST_KEY];
|
|
1791
2589
|
}
|
|
1792
2590
|
|
|
2591
|
+
//#endregion
|
|
2592
|
+
//#region src/plugins/package-extensions.ts
|
|
2593
|
+
function normalizeEntry(entry) {
|
|
2594
|
+
if (typeof entry !== "string") return null;
|
|
2595
|
+
const trimmed = entry.trim();
|
|
2596
|
+
if (!trimmed || path.isAbsolute(trimmed)) return null;
|
|
2597
|
+
const normalized = trimmed.replace(/^\.\/+/, "");
|
|
2598
|
+
if (!normalized || normalized === "." || normalized === "..") return null;
|
|
2599
|
+
return normalized;
|
|
2600
|
+
}
|
|
2601
|
+
async function inferExtensionsFromLegacyPluginManifest(params) {
|
|
2602
|
+
if (!params.pluginManifest) return [];
|
|
2603
|
+
const packageDir = path.resolve(params.packageDir);
|
|
2604
|
+
const candidates = [
|
|
2605
|
+
params.manifest.main,
|
|
2606
|
+
params.manifest.module,
|
|
2607
|
+
...DEFAULT_PLUGIN_ENTRY_CANDIDATES
|
|
2608
|
+
];
|
|
2609
|
+
const seen = /* @__PURE__ */ new Set();
|
|
2610
|
+
const entries = [];
|
|
2611
|
+
for (const candidate of candidates) {
|
|
2612
|
+
const normalized = normalizeEntry(candidate);
|
|
2613
|
+
if (!normalized || seen.has(normalized)) continue;
|
|
2614
|
+
seen.add(normalized);
|
|
2615
|
+
const resolved = path.resolve(packageDir, normalized);
|
|
2616
|
+
if (!isPathInside$1(packageDir, resolved)) continue;
|
|
2617
|
+
if (await fileExists(resolved)) entries.push(normalized);
|
|
2618
|
+
}
|
|
2619
|
+
return entries;
|
|
2620
|
+
}
|
|
2621
|
+
async function resolvePluginPackageExtensions(params) {
|
|
2622
|
+
let manifestKey = null;
|
|
2623
|
+
let extensions = params.manifest[MANIFEST_KEY]?.extensions;
|
|
2624
|
+
if (Array.isArray(extensions)) manifestKey = MANIFEST_KEY;
|
|
2625
|
+
if (Array.isArray(extensions)) {
|
|
2626
|
+
const list = extensions.map((e) => typeof e === "string" ? e.trim() : "").filter(Boolean);
|
|
2627
|
+
if (list.length === 0) throw new Error(`package.json ${manifestKey ?? MANIFEST_KEY}.extensions is empty`);
|
|
2628
|
+
return {
|
|
2629
|
+
extensions: list,
|
|
2630
|
+
source: "fased"
|
|
2631
|
+
};
|
|
2632
|
+
}
|
|
2633
|
+
const inferred = await inferExtensionsFromLegacyPluginManifest(params);
|
|
2634
|
+
if (inferred.length > 0) return {
|
|
2635
|
+
extensions: inferred,
|
|
2636
|
+
source: "legacy-plugin-manifest"
|
|
2637
|
+
};
|
|
2638
|
+
throw new Error(`package.json missing ${MANIFEST_KEY}.extensions`);
|
|
2639
|
+
}
|
|
2640
|
+
|
|
1793
2641
|
//#endregion
|
|
1794
2642
|
//#region src/plugins/install.ts
|
|
2643
|
+
function normalizeExpectedPluginIds(params) {
|
|
2644
|
+
const ids = /* @__PURE__ */ new Set();
|
|
2645
|
+
for (const raw of [params.expectedPluginId, ...params.expectedPluginIds ?? []]) {
|
|
2646
|
+
const trimmed = typeof raw === "string" ? raw.trim() : "";
|
|
2647
|
+
if (!trimmed) continue;
|
|
2648
|
+
ids.add(unscopedPackageName(trimmed));
|
|
2649
|
+
}
|
|
2650
|
+
return [...ids].toSorted((left, right) => left.localeCompare(right));
|
|
2651
|
+
}
|
|
2652
|
+
const defaultLogger = {};
|
|
1795
2653
|
function validatePluginId(pluginId) {
|
|
1796
2654
|
if (!pluginId) return "invalid plugin name: missing";
|
|
1797
2655
|
if (pluginId === "." || pluginId === "..") return "invalid plugin name: reserved path segment";
|
|
1798
2656
|
if (pluginId.includes("/") || pluginId.includes("\\")) return "invalid plugin name: path separators not allowed";
|
|
1799
2657
|
return null;
|
|
1800
2658
|
}
|
|
2659
|
+
function countManifestEntries(value) {
|
|
2660
|
+
return Object.keys(value ?? {}).length;
|
|
2661
|
+
}
|
|
2662
|
+
function listManifestKeys(value) {
|
|
2663
|
+
return Object.keys(value ?? {}).map((entry) => entry.trim()).filter(Boolean).toSorted((left, right) => left.localeCompare(right));
|
|
2664
|
+
}
|
|
2665
|
+
function isTypeScriptExtensionEntry(entry) {
|
|
2666
|
+
const ext = path.extname(entry.trim()).toLowerCase();
|
|
2667
|
+
return ext === ".ts" || ext === ".tsx" || ext === ".mts" || ext === ".cts";
|
|
2668
|
+
}
|
|
2669
|
+
function buildRuntimeWarnings(extensions) {
|
|
2670
|
+
const sourceEntries = extensions.map((entry) => entry.trim()).filter(Boolean).filter(isTypeScriptExtensionEntry).toSorted((left, right) => left.localeCompare(right));
|
|
2671
|
+
if (sourceEntries.length === 0) return [];
|
|
2672
|
+
return [`package exposes TypeScript extension ${sourceEntries.length === 1 ? "entry" : "entries"} (${sourceEntries.join(", ")}); publish compiled JavaScript runtime output before enabling this plugin`];
|
|
2673
|
+
}
|
|
2674
|
+
function buildInstallPackageReview(params) {
|
|
2675
|
+
const dependencyKinds = [];
|
|
2676
|
+
const dependencyCount = countManifestEntries(params.manifest.dependencies);
|
|
2677
|
+
const optionalDependencyCount = countManifestEntries(params.manifest.optionalDependencies);
|
|
2678
|
+
const peerDependencyCount = countManifestEntries(params.manifest.peerDependencies);
|
|
2679
|
+
const totalDependencyCount = dependencyCount + optionalDependencyCount + peerDependencyCount;
|
|
2680
|
+
if (dependencyCount > 0) dependencyKinds.push(`dependencies:${dependencyCount}`);
|
|
2681
|
+
if (optionalDependencyCount > 0) dependencyKinds.push(`optionalDependencies:${optionalDependencyCount}`);
|
|
2682
|
+
if (peerDependencyCount > 0) dependencyKinds.push(`peerDependencies:${peerDependencyCount}`);
|
|
2683
|
+
const scriptNames = listManifestKeys(params.manifest.scripts);
|
|
2684
|
+
const dependencyWarnings = totalDependencyCount > 0 ? [`package declares ${totalDependencyCount} dependenc${totalDependencyCount === 1 ? "y" : "ies"}; Fased installs runtime dependencies with npm --ignore-scripts`] : [];
|
|
2685
|
+
const scriptWarnings = scriptNames.length > 0 ? [`package declares npm scripts (${scriptNames.join(", ")}); Fased pack/install paths use --ignore-scripts`] : [];
|
|
2686
|
+
const runtimeWarnings = buildRuntimeWarnings(params.extensions);
|
|
2687
|
+
return {
|
|
2688
|
+
pluginId: params.pluginId,
|
|
2689
|
+
packageName: params.manifest.name || void 0,
|
|
2690
|
+
version: params.manifest.version || void 0,
|
|
2691
|
+
extensions: params.extensions,
|
|
2692
|
+
kind: params.pluginManifest?.kind,
|
|
2693
|
+
channels: params.pluginManifest?.channels ?? [],
|
|
2694
|
+
providers: params.pluginManifest?.providers ?? [],
|
|
2695
|
+
skills: params.pluginManifest?.skills ?? [],
|
|
2696
|
+
tools: params.pluginManifest?.contracts?.tools ?? [],
|
|
2697
|
+
dependencyCount: totalDependencyCount,
|
|
2698
|
+
dependencyKinds,
|
|
2699
|
+
scriptNames,
|
|
2700
|
+
dependencyWarnings,
|
|
2701
|
+
scriptWarnings,
|
|
2702
|
+
runtimeWarnings
|
|
2703
|
+
};
|
|
2704
|
+
}
|
|
1801
2705
|
function resolvePluginInstallDir(pluginId, extensionsDir) {
|
|
1802
2706
|
const extensionsBase = extensionsDir ? resolveUserPath(extensionsDir) : path.join(CONFIG_DIR, "extensions");
|
|
1803
2707
|
const pluginIdError = validatePluginId(pluginId);
|
|
@@ -1810,6 +2714,197 @@ function resolvePluginInstallDir(pluginId, extensionsDir) {
|
|
|
1810
2714
|
if (!targetDirResult.ok) throw new Error(targetDirResult.error);
|
|
1811
2715
|
return targetDirResult.path;
|
|
1812
2716
|
}
|
|
2717
|
+
async function installPluginFromPackageDir(params) {
|
|
2718
|
+
const { logger, timeoutMs, mode, dryRun } = resolveTimedInstallModeOptions(params, defaultLogger);
|
|
2719
|
+
const manifestPath = path.join(params.packageDir, "package.json");
|
|
2720
|
+
if (!await fileExists(manifestPath)) return {
|
|
2721
|
+
ok: false,
|
|
2722
|
+
error: "extracted package missing package.json"
|
|
2723
|
+
};
|
|
2724
|
+
let manifest;
|
|
2725
|
+
try {
|
|
2726
|
+
manifest = await readJsonFile(manifestPath);
|
|
2727
|
+
} catch (err) {
|
|
2728
|
+
return {
|
|
2729
|
+
ok: false,
|
|
2730
|
+
error: `invalid package.json: ${String(err)}`
|
|
2731
|
+
};
|
|
2732
|
+
}
|
|
2733
|
+
const pkgName = typeof manifest.name === "string" ? manifest.name : "";
|
|
2734
|
+
const npmPluginId = pkgName ? unscopedPackageName(pkgName) : "plugin";
|
|
2735
|
+
const pluginManifestResult = loadPluginManifest(params.packageDir);
|
|
2736
|
+
const manifestPlugin = pluginManifestResult.ok && pluginManifestResult.manifest.id ? pluginManifestResult.manifest : void 0;
|
|
2737
|
+
const manifestPluginId = pluginManifestResult.ok && pluginManifestResult.manifest.id ? unscopedPackageName(pluginManifestResult.manifest.id) : void 0;
|
|
2738
|
+
let extensions;
|
|
2739
|
+
try {
|
|
2740
|
+
const resolvedExtensions = await resolvePluginPackageExtensions({
|
|
2741
|
+
manifest,
|
|
2742
|
+
packageDir: params.packageDir,
|
|
2743
|
+
pluginManifest: manifestPlugin
|
|
2744
|
+
});
|
|
2745
|
+
extensions = resolvedExtensions.extensions;
|
|
2746
|
+
if (resolvedExtensions.source === "legacy-plugin-manifest") logger.info?.(`Plugin "${manifestPlugin?.id ?? npmPluginId}" uses legacy plugin manifest entry inference; prefer package.json fased.extensions for new packages.`);
|
|
2747
|
+
} catch (err) {
|
|
2748
|
+
return {
|
|
2749
|
+
ok: false,
|
|
2750
|
+
error: String(err)
|
|
2751
|
+
};
|
|
2752
|
+
}
|
|
2753
|
+
const pluginId = manifestPluginId ?? npmPluginId;
|
|
2754
|
+
const pluginIdError = validatePluginId(pluginId);
|
|
2755
|
+
if (pluginIdError) return {
|
|
2756
|
+
ok: false,
|
|
2757
|
+
error: pluginIdError
|
|
2758
|
+
};
|
|
2759
|
+
const expectedPluginIds = normalizeExpectedPluginIds(params);
|
|
2760
|
+
if (expectedPluginIds.length > 0 && !expectedPluginIds.includes(pluginId)) return {
|
|
2761
|
+
ok: false,
|
|
2762
|
+
error: `plugin id mismatch: expected ${expectedPluginIds.join(" or ")}, got ${pluginId}`
|
|
2763
|
+
};
|
|
2764
|
+
if (manifestPluginId && manifestPluginId !== npmPluginId) logger.info?.(`Plugin manifest id "${manifestPluginId}" differs from npm package name "${npmPluginId}"; using manifest id as the config key.`);
|
|
2765
|
+
const packageDir = path.resolve(params.packageDir);
|
|
2766
|
+
const forcedScanEntries = [];
|
|
2767
|
+
for (const entry of extensions) {
|
|
2768
|
+
const resolvedEntry = path.resolve(packageDir, entry);
|
|
2769
|
+
if (!isPathInside$1(packageDir, resolvedEntry)) {
|
|
2770
|
+
logger.warn?.(`extension entry escapes plugin directory and will not be scanned: ${entry}`);
|
|
2771
|
+
continue;
|
|
2772
|
+
}
|
|
2773
|
+
if (extensionUsesSkippedScannerPath(entry)) logger.warn?.(`extension entry is in a hidden/node_modules path and will receive targeted scan coverage: ${entry}`);
|
|
2774
|
+
forcedScanEntries.push(resolvedEntry);
|
|
2775
|
+
}
|
|
2776
|
+
try {
|
|
2777
|
+
const scanSummary = await scanDirectoryWithSummary(params.packageDir, { includeFiles: forcedScanEntries });
|
|
2778
|
+
if (scanSummary.critical > 0) {
|
|
2779
|
+
const criticalDetails = scanSummary.findings.filter((f) => f.severity === "critical").map((f) => `${f.message} (${f.file}:${f.line})`).join("; ");
|
|
2780
|
+
logger.warn?.(`WARNING: Plugin "${pluginId}" contains dangerous code patterns: ${criticalDetails}`);
|
|
2781
|
+
} else if (scanSummary.warn > 0) logger.warn?.(`Plugin "${pluginId}" has ${scanSummary.warn} suspicious code pattern(s). Run "fased security audit --deep" for details.`);
|
|
2782
|
+
} catch (err) {
|
|
2783
|
+
logger.warn?.(`Plugin "${pluginId}" code safety scan failed (${String(err)}). Installation continues; run "fased security audit --deep" after install.`);
|
|
2784
|
+
}
|
|
2785
|
+
const extensionsDir = params.extensionsDir ? resolveUserPath(params.extensionsDir) : path.join(CONFIG_DIR, "extensions");
|
|
2786
|
+
await fs$1.mkdir(extensionsDir, { recursive: true });
|
|
2787
|
+
const targetDirResult = resolveSafeInstallDir({
|
|
2788
|
+
baseDir: extensionsDir,
|
|
2789
|
+
id: pluginId,
|
|
2790
|
+
invalidNameMessage: "invalid plugin name: path traversal detected"
|
|
2791
|
+
});
|
|
2792
|
+
if (!targetDirResult.ok) return {
|
|
2793
|
+
ok: false,
|
|
2794
|
+
error: targetDirResult.error
|
|
2795
|
+
};
|
|
2796
|
+
const targetDir = targetDirResult.path;
|
|
2797
|
+
if (mode === "install" && await fileExists(targetDir)) return {
|
|
2798
|
+
ok: false,
|
|
2799
|
+
error: `plugin already exists: ${targetDir} (delete it first)`
|
|
2800
|
+
};
|
|
2801
|
+
if (dryRun) return {
|
|
2802
|
+
ok: true,
|
|
2803
|
+
pluginId,
|
|
2804
|
+
targetDir,
|
|
2805
|
+
manifestName: pkgName || void 0,
|
|
2806
|
+
version: typeof manifest.version === "string" ? manifest.version : void 0,
|
|
2807
|
+
extensions,
|
|
2808
|
+
review: buildInstallPackageReview({
|
|
2809
|
+
pluginId,
|
|
2810
|
+
manifest,
|
|
2811
|
+
extensions,
|
|
2812
|
+
pluginManifest: manifestPlugin
|
|
2813
|
+
})
|
|
2814
|
+
};
|
|
2815
|
+
const hasDeps = Boolean(manifest.dependencies && Object.keys(manifest.dependencies).length > 0 || manifest.optionalDependencies && Object.keys(manifest.optionalDependencies).length > 0);
|
|
2816
|
+
const installRes = await installPackageDir({
|
|
2817
|
+
sourceDir: params.packageDir,
|
|
2818
|
+
targetDir,
|
|
2819
|
+
mode,
|
|
2820
|
+
timeoutMs,
|
|
2821
|
+
logger,
|
|
2822
|
+
copyErrorPrefix: "failed to copy plugin",
|
|
2823
|
+
hasDeps,
|
|
2824
|
+
depsLogMessage: "Installing plugin dependencies…",
|
|
2825
|
+
afterCopy: async () => {
|
|
2826
|
+
for (const entry of extensions) {
|
|
2827
|
+
const resolvedEntry = path.resolve(targetDir, entry);
|
|
2828
|
+
if (!isPathInside$1(targetDir, resolvedEntry)) {
|
|
2829
|
+
logger.warn?.(`extension entry escapes plugin directory: ${entry}`);
|
|
2830
|
+
continue;
|
|
2831
|
+
}
|
|
2832
|
+
if (!await fileExists(resolvedEntry)) logger.warn?.(`extension entry not found: ${entry}`);
|
|
2833
|
+
}
|
|
2834
|
+
}
|
|
2835
|
+
});
|
|
2836
|
+
if (!installRes.ok) return installRes;
|
|
2837
|
+
return {
|
|
2838
|
+
ok: true,
|
|
2839
|
+
pluginId,
|
|
2840
|
+
targetDir,
|
|
2841
|
+
manifestName: pkgName || void 0,
|
|
2842
|
+
version: typeof manifest.version === "string" ? manifest.version : void 0,
|
|
2843
|
+
extensions,
|
|
2844
|
+
review: buildInstallPackageReview({
|
|
2845
|
+
pluginId,
|
|
2846
|
+
manifest,
|
|
2847
|
+
extensions,
|
|
2848
|
+
pluginManifest: manifestPlugin
|
|
2849
|
+
})
|
|
2850
|
+
};
|
|
2851
|
+
}
|
|
2852
|
+
async function installPluginFromArchive(params) {
|
|
2853
|
+
const logger = params.logger ?? defaultLogger;
|
|
2854
|
+
const timeoutMs = params.timeoutMs ?? 12e4;
|
|
2855
|
+
const mode = params.mode ?? "install";
|
|
2856
|
+
const archivePathResult = await resolveArchiveSourcePath(params.archivePath);
|
|
2857
|
+
if (!archivePathResult.ok) return archivePathResult;
|
|
2858
|
+
const archivePath = archivePathResult.path;
|
|
2859
|
+
return await withExtractedArchiveRoot({
|
|
2860
|
+
archivePath,
|
|
2861
|
+
tempDirPrefix: "fased-plugin-",
|
|
2862
|
+
timeoutMs,
|
|
2863
|
+
logger,
|
|
2864
|
+
onExtracted: async (packageDir) => await installPluginFromPackageDir({
|
|
2865
|
+
packageDir,
|
|
2866
|
+
extensionsDir: params.extensionsDir,
|
|
2867
|
+
timeoutMs,
|
|
2868
|
+
logger,
|
|
2869
|
+
mode,
|
|
2870
|
+
dryRun: params.dryRun,
|
|
2871
|
+
expectedPluginId: params.expectedPluginId,
|
|
2872
|
+
expectedPluginIds: params.expectedPluginIds
|
|
2873
|
+
})
|
|
2874
|
+
});
|
|
2875
|
+
}
|
|
2876
|
+
async function installPluginFromNpmSpec(params) {
|
|
2877
|
+
const { logger, timeoutMs, mode, dryRun } = resolveTimedInstallModeOptions(params, defaultLogger);
|
|
2878
|
+
const expectedPluginId = params.expectedPluginId;
|
|
2879
|
+
const expectedPluginIds = params.expectedPluginIds;
|
|
2880
|
+
const spec = params.spec.trim();
|
|
2881
|
+
const specError = validateRegistryNpmSpec(spec);
|
|
2882
|
+
if (specError) return {
|
|
2883
|
+
ok: false,
|
|
2884
|
+
error: specError
|
|
2885
|
+
};
|
|
2886
|
+
logger.info?.(`Downloading ${spec}…`);
|
|
2887
|
+
return finalizeNpmSpecArchiveInstall(await installFromNpmSpecArchiveWithInstaller({
|
|
2888
|
+
tempDirPrefix: "fased-npm-pack-",
|
|
2889
|
+
spec,
|
|
2890
|
+
timeoutMs,
|
|
2891
|
+
expectedIntegrity: params.expectedIntegrity,
|
|
2892
|
+
onIntegrityDrift: params.onIntegrityDrift,
|
|
2893
|
+
warn: (message) => {
|
|
2894
|
+
logger.warn?.(message);
|
|
2895
|
+
},
|
|
2896
|
+
installFromArchive: installPluginFromArchive,
|
|
2897
|
+
archiveInstallParams: {
|
|
2898
|
+
extensionsDir: params.extensionsDir,
|
|
2899
|
+
timeoutMs,
|
|
2900
|
+
logger,
|
|
2901
|
+
mode,
|
|
2902
|
+
dryRun,
|
|
2903
|
+
expectedPluginId,
|
|
2904
|
+
expectedPluginIds
|
|
2905
|
+
}
|
|
2906
|
+
}));
|
|
2907
|
+
}
|
|
1813
2908
|
|
|
1814
2909
|
//#endregion
|
|
1815
2910
|
//#region src/plugins/uninstall.ts
|
|
@@ -2036,6 +3131,7 @@ const MAX_THINKING_LEVELS = [
|
|
|
2036
3131
|
"xhigh",
|
|
2037
3132
|
"max"
|
|
2038
3133
|
];
|
|
3134
|
+
const ULTRA_THINKING_LEVELS = [...MAX_THINKING_LEVELS, "ultra"];
|
|
2039
3135
|
const XHIGH_MODEL_REFS = [
|
|
2040
3136
|
"openai/gpt-5.6",
|
|
2041
3137
|
"openai/gpt-5.6-terra",
|
|
@@ -2088,6 +3184,7 @@ function normalizeThinkLevel(raw) {
|
|
|
2088
3184
|
const collapsed = key.replace(/[\s_-]+/g, "");
|
|
2089
3185
|
if (collapsed === "xhigh" || collapsed === "extrahigh") return "xhigh";
|
|
2090
3186
|
if (key === "max") return "max";
|
|
3187
|
+
if (key === "ultra") return "ultra";
|
|
2091
3188
|
if (key === "off") return "off";
|
|
2092
3189
|
if ([
|
|
2093
3190
|
"on",
|
|
@@ -2111,7 +3208,6 @@ function normalizeThinkLevel(raw) {
|
|
|
2111
3208
|
].includes(key)) return "medium";
|
|
2112
3209
|
if ([
|
|
2113
3210
|
"high",
|
|
2114
|
-
"ultra",
|
|
2115
3211
|
"ultrathink",
|
|
2116
3212
|
"think-hard",
|
|
2117
3213
|
"thinkhardest",
|
|
@@ -2145,6 +3241,9 @@ function normalizeThinkingLevels(values) {
|
|
|
2145
3241
|
return levels;
|
|
2146
3242
|
}
|
|
2147
3243
|
function listGenericThinkingLevels(provider, model) {
|
|
3244
|
+
const normalizedProvider = normalizeProviderId$2(provider);
|
|
3245
|
+
const normalizedModel = model?.trim().toLowerCase();
|
|
3246
|
+
if (normalizedProvider === "openai-codex" && (normalizedModel === "gpt-5.6-sol" || normalizedModel === "gpt-5.6-terra")) return [...ULTRA_THINKING_LEVELS];
|
|
2148
3247
|
if (supportsMaxThinking(provider, model)) return [...MAX_THINKING_LEVELS];
|
|
2149
3248
|
return supportsXHighThinking(provider, model) ? [...XHIGH_THINKING_LEVELS] : [...BASE_THINKING_LEVELS];
|
|
2150
3249
|
}
|
|
@@ -2229,6 +3328,9 @@ function listThinkingLevels(provider, model) {
|
|
|
2229
3328
|
function listThinkingLevelLabels(provider, model) {
|
|
2230
3329
|
return listThinkingLevels(provider, model);
|
|
2231
3330
|
}
|
|
3331
|
+
function supportsThinkingLevel(provider, model, level) {
|
|
3332
|
+
return listThinkingLevels(provider, model).includes(level);
|
|
3333
|
+
}
|
|
2232
3334
|
function formatThinkingLevels(provider, model, separator = ", ") {
|
|
2233
3335
|
return listThinkingLevelLabels(provider, model).join(separator);
|
|
2234
3336
|
}
|
|
@@ -4244,6 +5346,7 @@ function buildXiaomiModelCapabilityOverrides(routeId = "xiaomi") {
|
|
|
4244
5346
|
|
|
4245
5347
|
//#endregion
|
|
4246
5348
|
//#region src/providers/litellm-models.ts
|
|
5349
|
+
const LITELLM_BASE_URL = "http://localhost:4000/v1";
|
|
4247
5350
|
const LITELLM_DEFAULT_MODEL_ID = "default";
|
|
4248
5351
|
const LITELLM_DEFAULT_MODEL_REF = `litellm/${LITELLM_DEFAULT_MODEL_ID}`;
|
|
4249
5352
|
const LITELLM_DEFAULT_COST = {
|
|
@@ -5009,7 +6112,7 @@ const OPENAI_PROVIDER_MANIFEST = {
|
|
|
5009
6112
|
id: "openai-codex",
|
|
5010
6113
|
route: OPENAI_CODEX_ROUTE_ID,
|
|
5011
6114
|
kind: "oauth",
|
|
5012
|
-
label: "
|
|
6115
|
+
label: "ChatGPT sign-in",
|
|
5013
6116
|
hint: "Open the OpenAI sign-in URL, finish login in the browser, then Fased completes the OAuth flow."
|
|
5014
6117
|
}, {
|
|
5015
6118
|
id: "openai-api-key",
|
|
@@ -5780,9 +6883,6 @@ function getProviderBrandManifestForRoute(route) {
|
|
|
5780
6883
|
function isOpenAISignInRuntimeModelSupported(id) {
|
|
5781
6884
|
return OPENAI_SIGN_IN_RUNTIME_MODEL_ID_SET.has(id.trim().toLowerCase());
|
|
5782
6885
|
}
|
|
5783
|
-
function isOpenAISignInCatalogModel(id) {
|
|
5784
|
-
return OPENAI_SIGN_IN_MODEL_ID_SET.has(id.trim().toLowerCase());
|
|
5785
|
-
}
|
|
5786
6886
|
function lookupProviderManifestModelCapability(provider, model) {
|
|
5787
6887
|
const providerId = provider.trim().toLowerCase();
|
|
5788
6888
|
const modelId = model.trim().toLowerCase();
|
|
@@ -6563,6 +7663,13 @@ const PLUGIN_ORIGIN_RANK = {
|
|
|
6563
7663
|
const registryCache = /* @__PURE__ */ new Map();
|
|
6564
7664
|
const DEFAULT_MANIFEST_CACHE_MS = 200;
|
|
6565
7665
|
const LEGACY_REMOVED_PLUGIN_IDS$2 = /* @__PURE__ */ new Set();
|
|
7666
|
+
function isRuntimeOnlyComponent(params) {
|
|
7667
|
+
if (params.manifest.runtimeOnly === true) return true;
|
|
7668
|
+
return params.manifest.id === "openai-runtime" && params.candidate.packageName === "@fased/openai-runtime";
|
|
7669
|
+
}
|
|
7670
|
+
function clearPluginManifestRegistryCache() {
|
|
7671
|
+
registryCache.clear();
|
|
7672
|
+
}
|
|
6566
7673
|
function resolveManifestCacheMs(env) {
|
|
6567
7674
|
const raw = env.FASED_PLUGIN_MANIFEST_CACHE_MS?.trim();
|
|
6568
7675
|
if (raw === "" || raw === "0") return 0;
|
|
@@ -6620,6 +7727,7 @@ function buildRecord(params) {
|
|
|
6620
7727
|
});
|
|
6621
7728
|
return {
|
|
6622
7729
|
id: params.manifest.id,
|
|
7730
|
+
runtimeOnly: isRuntimeOnlyComponent(params) ? true : void 0,
|
|
6623
7731
|
name: normalizeManifestLabel(params.manifest.name) ?? params.candidate.packageName,
|
|
6624
7732
|
description: normalizeManifestLabel(params.manifest.description) ?? params.candidate.packageDescription,
|
|
6625
7733
|
version: normalizeManifestLabel(params.manifest.version) ?? params.candidate.packageVersion,
|
|
@@ -6734,6 +7842,25 @@ function loadPluginManifestRegistry(params) {
|
|
|
6734
7842
|
}
|
|
6735
7843
|
continue;
|
|
6736
7844
|
}
|
|
7845
|
+
if (isRuntimeOnlyComponent({
|
|
7846
|
+
manifest,
|
|
7847
|
+
candidate
|
|
7848
|
+
}) && records[existing.recordIndex]?.runtimeOnly === true) {
|
|
7849
|
+
if (PLUGIN_ORIGIN_RANK[candidate.origin] < PLUGIN_ORIGIN_RANK[existing.candidate.origin]) {
|
|
7850
|
+
records[existing.recordIndex] = buildRecord({
|
|
7851
|
+
manifest,
|
|
7852
|
+
candidate,
|
|
7853
|
+
manifestPath: manifestRes.manifestPath,
|
|
7854
|
+
schemaCacheKey,
|
|
7855
|
+
configSchema
|
|
7856
|
+
});
|
|
7857
|
+
seenIds.set(manifest.id, {
|
|
7858
|
+
candidate,
|
|
7859
|
+
recordIndex: existing.recordIndex
|
|
7860
|
+
});
|
|
7861
|
+
}
|
|
7862
|
+
continue;
|
|
7863
|
+
}
|
|
6737
7864
|
diagnostics.push({
|
|
6738
7865
|
level: "warn",
|
|
6739
7866
|
pluginId: manifest.id,
|
|
@@ -11115,7 +12242,8 @@ const OPENAI_CODEX_MODELS = [
|
|
|
11115
12242
|
input: ["text", "image"],
|
|
11116
12243
|
contextWindow: 105e4,
|
|
11117
12244
|
maxTokens: 128e3,
|
|
11118
|
-
api: "openai-codex-responses"
|
|
12245
|
+
api: "openai-codex-responses",
|
|
12246
|
+
compat: { responsesLite: true }
|
|
11119
12247
|
}),
|
|
11120
12248
|
model({
|
|
11121
12249
|
id: "gpt-5.6-terra",
|
|
@@ -11124,7 +12252,8 @@ const OPENAI_CODEX_MODELS = [
|
|
|
11124
12252
|
input: ["text", "image"],
|
|
11125
12253
|
contextWindow: 105e4,
|
|
11126
12254
|
maxTokens: 128e3,
|
|
11127
|
-
api: "openai-codex-responses"
|
|
12255
|
+
api: "openai-codex-responses",
|
|
12256
|
+
compat: { responsesLite: true }
|
|
11128
12257
|
}),
|
|
11129
12258
|
model({
|
|
11130
12259
|
id: "gpt-5.6-luna",
|
|
@@ -11133,7 +12262,8 @@ const OPENAI_CODEX_MODELS = [
|
|
|
11133
12262
|
input: ["text", "image"],
|
|
11134
12263
|
contextWindow: 105e4,
|
|
11135
12264
|
maxTokens: 128e3,
|
|
11136
|
-
api: "openai-codex-responses"
|
|
12265
|
+
api: "openai-codex-responses",
|
|
12266
|
+
compat: { responsesLite: true }
|
|
11137
12267
|
}),
|
|
11138
12268
|
model({
|
|
11139
12269
|
id: "gpt-5.5",
|
|
@@ -18095,7 +19225,8 @@ const ModelCapabilitySchema = z.object({
|
|
|
18095
19225
|
z.literal("medium"),
|
|
18096
19226
|
z.literal("high"),
|
|
18097
19227
|
z.literal("xhigh"),
|
|
18098
|
-
z.literal("max")
|
|
19228
|
+
z.literal("max"),
|
|
19229
|
+
z.literal("ultra")
|
|
18099
19230
|
])).optional(),
|
|
18100
19231
|
defaultThinkingLevel: z.union([
|
|
18101
19232
|
z.literal("off"),
|
|
@@ -18104,7 +19235,8 @@ const ModelCapabilitySchema = z.object({
|
|
|
18104
19235
|
z.literal("medium"),
|
|
18105
19236
|
z.literal("high"),
|
|
18106
19237
|
z.literal("xhigh"),
|
|
18107
|
-
z.literal("max")
|
|
19238
|
+
z.literal("max"),
|
|
19239
|
+
z.literal("ultra")
|
|
18108
19240
|
]).optional(),
|
|
18109
19241
|
thinkingMode: z.union([
|
|
18110
19242
|
z.literal("openai-reasoning-effort"),
|
|
@@ -19020,7 +20152,8 @@ const AgentEntrySchema = z.object({
|
|
|
19020
20152
|
z.literal("medium"),
|
|
19021
20153
|
z.literal("high"),
|
|
19022
20154
|
z.literal("xhigh"),
|
|
19023
|
-
z.literal("max")
|
|
20155
|
+
z.literal("max"),
|
|
20156
|
+
z.literal("ultra")
|
|
19024
20157
|
]).optional(),
|
|
19025
20158
|
reasoningDefault: z.union([
|
|
19026
20159
|
z.literal("off"),
|
|
@@ -19029,7 +20162,8 @@ const AgentEntrySchema = z.object({
|
|
|
19029
20162
|
z.literal("medium"),
|
|
19030
20163
|
z.literal("high"),
|
|
19031
20164
|
z.literal("xhigh"),
|
|
19032
|
-
z.literal("max")
|
|
20165
|
+
z.literal("max"),
|
|
20166
|
+
z.literal("ultra")
|
|
19033
20167
|
]).optional(),
|
|
19034
20168
|
fastModeDefault: z.boolean().optional(),
|
|
19035
20169
|
skills: z.array(z.string()).optional(),
|
|
@@ -19180,7 +20314,8 @@ const AgentDefaultsSchema = z.object({
|
|
|
19180
20314
|
z.literal("medium"),
|
|
19181
20315
|
z.literal("high"),
|
|
19182
20316
|
z.literal("xhigh"),
|
|
19183
|
-
z.literal("max")
|
|
20317
|
+
z.literal("max"),
|
|
20318
|
+
z.literal("ultra")
|
|
19184
20319
|
]).optional(),
|
|
19185
20320
|
reasoningDefault: z.union([
|
|
19186
20321
|
z.literal("off"),
|
|
@@ -19189,7 +20324,8 @@ const AgentDefaultsSchema = z.object({
|
|
|
19189
20324
|
z.literal("medium"),
|
|
19190
20325
|
z.literal("high"),
|
|
19191
20326
|
z.literal("xhigh"),
|
|
19192
|
-
z.literal("max")
|
|
20327
|
+
z.literal("max"),
|
|
20328
|
+
z.literal("ultra")
|
|
19193
20329
|
]).optional(),
|
|
19194
20330
|
fastModeDefault: z.boolean().optional(),
|
|
19195
20331
|
verboseDefault: z.union([
|
|
@@ -23405,4 +24541,4 @@ async function writeConfigFile(cfg, options = {}) {
|
|
|
23405
24541
|
}
|
|
23406
24542
|
|
|
23407
24543
|
//#endregion
|
|
23408
|
-
export { resetConfigOverrides as $,
|
|
24544
|
+
export { resetConfigOverrides as $, DEFAULT_CONTEXT_TOKENS as $i, ANTHROPIC_PROVIDER_BRAND_ID as $n, QWEN_API_ROUTE_ID as $r, resolveSubagentSpawnModelSelection as $t, GroupPolicySchema as A, listProviderBrandManifests as Ai, markAuthProfileGood as An, MINIMAX_PORTAL_ROUTE_ID as Ar, isSafeExecutableValue as At, MODEL_APIS as B, OPENCODE_ZEN_MODEL_IDS as Bi, normalizeProviderId$1 as Bn, OPENAI_API_MODEL_IDS as Br, buildModelAliasIndex as Bt, resolveIMessageAttachmentRoots as C, applyTestPluginDefaults as Ca, XIAOMI_ROUTE_ID as Ci, markAuthProfileFailure as Cn, LITELLM_PROVIDER_BRAND_ID as Cr, unwrapKnownDispatchWrapperInvocation as Ct, BlockStreamingCoalesceSchema as D, resolveMemorySlotDecision as Da, getProviderBrandManifestForRoute as Di, dedupeProfileIds as Dn, MINIMAX_API_ROUTE_ID as Dr, normalizeSafeBinProfileFixtures as Dt, ToolPolicySchema as E, resolveEffectiveEnableState as Ea, ZAI_ROUTE_ID as Ei, resolveApiKeyForProfile as En, LMSTUDIO_ROUTE_ID as Er, SAFE_BIN_PROFILES as Et, TtsConfigSchema as F, XIAOMI_MODEL_IDS as Fi, acquireFileLock as Fn, MOONSHOT_MODEL_IDS as Fr, resolveTelegramPreviewStreamMode as Ft, isAvatarDataUrl as G, BASE_THINKING_LEVELS as Gi, safeStatSync as Gn, OPENCODE_ZEN_ROUTE_ID as Gr, normalizeModelRef as Gt, parseDurationMs as H, CLOUDFLARE_AI_GATEWAY_MODEL_IDS as Hi, loadPluginManifestRegistry as Hn, OPENAI_CODEX_ROUTE_ID as Hr, inferUniqueProviderFromConfiguredModels as Ht, TtsModeSchema as I, VERCEL_AI_GATEWAY_MODEL_IDS as Ii, withFileLock as In, MOONSHOT_PROVIDER_BRAND_ID as Ir, DEFAULT_SUBAGENT_MAX_SPAWN_DEPTH as It, isSupportedLocalAvatarExtension as J, listThinkingLevels as Ji, normalizeSecretInput as Jn, OPENROUTER_ROUTE_ID as Jr, resolveConfiguredModelRef as Jt, isAvatarHttpUrl as K, formatThinkingLevels as Ki, resolveAuthProfileDisplayLabel as Kn, OPENROUTER_MODEL_IDS as Kr, normalizeProviderId as Kt, TtsProviderSchema as L, VENICE_MODEL_IDS as Li, resolveProcessScopedMap as Ln, MOONSHOT_ROUTE_ID as Lr, resolveAgentMaxConcurrent as Lt, MarkdownTableModeSchema as M, providerModelRecommendationRank as Mi, resolveAuthStorePathForDisplay as Mn, MISTRAL_MODEL_IDS as Mr, resolveDiscordPreviewStreamMode as Mt, ReplyRuntimeConfigSchemaShape as N, resolveProviderRouteModelCapability as Ni, resolveFasedAgentAgentDir as Nn, MISTRAL_PROVIDER_BRAND_ID as Nr, resolveSlackNativeStreaming as Nt, DmConfigSchema as O, resolvePluginAdminRpcActionGrant as Oa, isOpenAISignInRuntimeModelSupported as Oi, listProfilesForProvider as On, MINIMAX_CN_ROUTE_ID as Or, resolveSafeBinProfiles as Ot, TtsAutoSchema as P, LITELLM_BASE_URL as Pi, resolveFasedAgentDir as Pn, MISTRAL_ROUTE_ID as Pr, resolveSlackStreamingMode as Pt, getConfigOverrides as Q, supportsXHighThinking as Qi, ANTHROPIC_MODEL_IDS as Qn, QWEN_API_MODEL_IDS as Qr, resolveReasoningDefault as Qt, normalizeAllowFrom as R, TOGETHER_MODEL_IDS as Ri, isPidAlive as Rn, OLLAMA_PROVIDER_BRAND_ID as Rr, buildAllowedModelSet as Rt, mergeInboundPathRoots as S, parseBooleanValue as Sa, XIAOMI_PROVIDER_BRAND_ID as Si, isProfileInCooldown as Sn, KIMI_CODING_ROUTE_ID as Sr, isShellWrapperExecutable as St, normalizeScpRemoteHost as T, normalizePluginsConfig as Ta, ZAI_PROVIDER_BRAND_ID as Ti, resolveProfilesUnavailableReason as Tn, LMSTUDIO_PROVIDER_BRAND_ID as Tr, splitShellArgs as Tt, parseByteSize as U, CLOUDFLARE_AI_GATEWAY_PROVIDER_BRAND_ID as Ui, discoverFasedAgentPlugins as Un, OPENAI_PROVIDER_BRAND_ID as Ur, isCliProvider as Ut, getBlockedNetworkModeReason as V, HUGGINGFACE_MODEL_IDS as Vi, clearPluginManifestRegistryCache as Vn, OPENAI_API_ROUTE_ID as Vr, findNormalizedProviderValue as Vt, AVATAR_MAX_BYTES as W, CLOUDFLARE_AI_GATEWAY_ROUTE_ID as Wi, isPathInside as Wn, OPENCODE_ZEN_PROVIDER_BRAND_ID as Wr, modelKey as Wt, resolveAvatarMime as X, resolveModelThinkingCapability as Xi, coerceSecretRef as Xn, QIANFAN_PROVIDER_BRAND_ID as Xr, resolveExplicitConfiguredModelRef as Xt, isWorkspaceRelativeAvatarPath as Y, normalizeThinkLevel as Yi, assertSecretInputResolved as Yn, QIANFAN_MODEL_IDS as Yr, resolveDefaultModelForAgent as Yt, validateJsonSchemaValue as Z, supportsThinkingLevel as Zi, splitTrailingAuthProfile as Zn, QIANFAN_ROUTE_ID as Zr, resolveModelRefFromString as Zt, TELEGRAM_COMMAND_NAME_PATTERN as _, sanitizeHostExecEnv as _a, VOLCENGINE_PROVIDER_BRAND_ID as _i, normalizeModelCatalogProviderId as _n, GOOGLE_GEMINI_MODEL_IDS as _r, matchAllowlist as _t, readConfigFileSnapshotForWrite as a, getPackageManifestMetadata as aa, TOGETHER_PROVIDER_BRAND_ID as ai, getApiKeyForModel as an, BYTEPLUS_PROVIDER_BRAND_ID as ar, unsetConfigValueAtPath as at, DEFAULT_IMESSAGE_ATTACHMENT_ROOTS as b, resolveCliName as ba, XAI_PROVIDER_BRAND_ID as bi, resolveAuthProfileOrder as bn, HUGGINGFACE_ROUTE_ID as br, extractShellWrapperInlineCommand as bt, validateConfigObjectWithPlugins as c, formatErrorMessage as ca, VENICE_ROUTE_ID as ci, resolveApiKeyForProvider as cn, CHUTES_PROVIDER_BRAND_ID as cr, isTrustedSafeBinPath as ct, GoogleChatConfigSchema as d, extractArchive as da, VLLM_PROVIDER_BRAND_ID as di, CURRENT_MODEL_PROVIDER_CATALOG as dn, COPILOT_PROXY_MODEL_IDS as dr, validateSafeBinArgv as dt, DEFAULT_MODEL as ea, QWEN_CODING_PLAN_MODEL_IDS as ei, resolveThinkingDefault as en, ANTHROPIC_ROUTE_ID as er, setConfigOverride as et, IMessageConfigSchema as f, getShellPathFromLoginShell as fa, VLLM_ROUTE_ID as fi, cloneCurrentModelProvider as fn, COPILOT_PROXY_ROUTE_ID as fr, analyzeShellCommand as ft, TelegramConfigSchema as g, isDangerousHostInheritedEnvVarName as ga, VOLCENGINE_PLAN_ROUTE_ID as gi, normalizeModelCatalogModelId as gn, GOOGLE_GEMINI_CLI_ROUTE_ID as gr, DEFAULT_SAFE_BINS as gt, SlackConfigSchema as h, isDangerousHostEnvVarName as ha, VOLCENGINE_MODEL_IDS as hi, mergeModelCatalogRowsByAuthority as hn, GOOGLE_API_ROUTE_ID as hr, splitCommandChain as ht, readConfigFileSnapshot as i, resolvePluginInstallDir as ia, SYNTHETIC_ROUTE_ID as ii, resolveImplicitProviders as in, BYTEPLUS_PLAN_ROUTE_ID as ir, setConfigValueAtPath as it, MarkdownConfigSchema as j, lookupProviderManifestModelCapability as ji, ensureAuthProfileStore as jn, MINIMAX_PROVIDER_BRAND_ID as jr, mapStreamingModeToSlackLegacyDraftStreamMode as jt, DmPolicySchema as k, applyExclusiveSlotSelection as ka, isStandardProviderCatalogEntry as ki, listProvidersWithStoredCredentials as kn, MINIMAX_MODEL_IDS as kr, applyMergePatch as kt, WhatsAppConfigSchema as l, formatUncaughtError as la, VERCEL_AI_GATEWAY_PROVIDER_BRAND_ID as li, resolveEnvApiKey as ln, CHUTES_ROUTE_ID as lr, listWritableExplicitTrustedSafeBinDirs as lt, SignalConfigSchema as m, isDangerousHostEnvOverrideVarName as ma, VOLCENGINE_CODING_ROUTE_ID as mi, buildModelCatalogMergeKey as mn, CUSTOM_PROVIDER_ROUTE_ID as mr, isWindowsPlatform as mt, loadConfig as n, VERSION as na, QWEN_PROVIDER_BRAND_ID as ni, normalizeProviders as nn, BYTEPLUS_CODING_ROUTE_ID as nr, getConfigValueAtPath as nt, resolveConfigSnapshotHash as o, MANIFEST_KEY as oa, TOGETHER_ROUTE_ID as oi, getCustomProviderApiKey as on, BYTEPLUS_ROUTE_ID as or, ensurePluginAllowlisted as ot, MSTeamsConfigSchema as p, resolveShellEnvFallbackTimeoutMs as pa, VOLCENGINE_CODING_MODEL_IDS as pi, listCurrentModelCatalogRows as pn, CUSTOM_PROVIDER_BRAND_ID as pr, buildEnforcedShellCommand as pt, isPathWithinRoot as q, formatXHighModelHint as qi, isPrivateNetworkBaseUrl as qn, OPENROUTER_PROVIDER_BRAND_ID as qr, parseModelRef as qt, parseConfigJson5 as r, installPluginFromNpmSpec as ra, SYNTHETIC_PROVIDER_BRAND_ID as ri, resolveImplicitCopilotProvider as rn, BYTEPLUS_MODEL_IDS as rr, parseConfigPath as rt, writeConfigFile as s, extractErrorCode as sa, VENICE_PROVIDER_BRAND_ID as si, requireApiKey as sn, CHUTES_MODEL_IDS as sr, getTrustedSafeBinDirs as st, createConfigIO as t, DEFAULT_PROVIDER as ta, QWEN_CODING_PLAN_ROUTE_ID as ti, normalizeGoogleModelId as tn, BYTEPLUS_CODING_MODEL_IDS as tr, unsetConfigOverride as tt, DiscordConfigSchema as u, isErrno as ua, VERCEL_AI_GATEWAY_ROUTE_ID as ui, resolveModelAuthMode as un, COPILOT_PROVIDER_BRAND_ID as ur, normalizeTrustedSafeBinDirs as ut, normalizeTelegramCommandName as v, resolveOwnerDisplaySetting as va, VOLCENGINE_ROUTE_ID as vi, normalizeProviderCatalogRows as vn, GOOGLE_PROVIDER_BRAND_ID as vr, resolveAllowlistCandidatePath as vt, resolveIMessageRemoteAttachmentRoots as w, isPluginRuntimeSessionReadAllowed as wa, ZAI_MODEL_IDS as wi, markAuthProfileUsed as wn, LITELLM_ROUTE_ID as wr, unwrapKnownShellMultiplexerInvocation as wt, isInboundPathAllowed as x, isTruthyEnvValue as xa, XAI_ROUTE_ID as xi, getSoonestCooldownExpiry as xn, KIMI_CODING_MODEL_IDS as xr, isDispatchWrapperExecutable as xt, resolveTelegramCustomCommands as y, formatCliCommand as ya, XAI_MODEL_IDS as yi, auth_profiles_exports as yn, HUGGINGFACE_PROVIDER_BRAND_ID as yr, resolveCommandResolutionFromArgv as yt, requireOpenAllowFrom as z, SYNTHETIC_MODEL_IDS as zi, findNormalizedProviderValue$1 as zn, OLLAMA_ROUTE_ID as zr, buildConfiguredAllowlistKeys as zt };
|