@noxsoft/anima 2.0.2 → 2.0.4
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +1260 -28
- package/dist/accounts-Bth3PpPD.js +260 -0
- package/dist/accounts-D8CPKNkN.js +259 -0
- package/dist/acp-cli-ByK6lS6c.js +1081 -0
- package/dist/acp-cli-CaQCjIw4.js +1084 -0
- package/dist/agent-BgIkqd3F.js +725 -0
- package/dist/agent-N5BDcge4.js +725 -0
- package/dist/agent-events-COH7NDW2.js +182 -0
- package/dist/agent-scope-CPphqq-U.js +452 -0
- package/dist/agent-scope-DZgptr9J.js +452 -0
- package/dist/agent-scope-cj2QCT6R.js +112 -0
- package/dist/agents-NEudYMdg.js +774 -0
- package/dist/agents.config-Bujs-NIy.js +182 -0
- package/dist/agents.config-jp7OLssr.js +182 -0
- package/dist/argv-BMZMiW7v.js +73 -0
- package/dist/audit-C-UJhfdv.js +2401 -0
- package/dist/audit-CeCO7SK5.js +2401 -0
- package/dist/auth-BNZsOHGF.js +648 -0
- package/dist/auth-DMPZWzEa.js +639 -0
- package/dist/auth-choice-5VnaGMD-.js +2681 -0
- package/dist/auth-choice-DA2k4vs8.js +2681 -0
- package/dist/auth-health-B7FqA26_.js +149 -0
- package/dist/auth-health-VO_MPqVX.js +149 -0
- package/dist/auth-profiles-BDrNYX_n.js +1564 -0
- package/dist/auth-profiles-CxSHydjn.js +2689 -0
- package/dist/banner-BtDZPRzi.js +294 -0
- package/dist/browser-cli-8yQMpxb8.js +1679 -0
- package/dist/browser-cli-Czg3JtDH.js +1676 -0
- package/dist/build-info.json +3 -3
- package/dist/bundled/boot-md/handler.js +16 -16
- package/dist/bundled/bootstrap-extra-files/handler.js +4 -4
- package/dist/bundled/command-logger/handler.js +1 -1
- package/dist/bundled/session-memory/handler.js +5 -5
- package/dist/call-BIzCaKZb.js +282 -0
- package/dist/call-BYDpTVCZ.js +282 -0
- package/dist/canvas-host/a2ui/.bundle.hash +1 -1
- package/dist/catalog-CqKiUgu6.js +185 -0
- package/dist/catalog-DMfEg-oK.js +185 -0
- package/dist/channel-options-BrtCtyrT.js +32 -0
- package/dist/channel-options-CO21Gl8p.js +33 -0
- package/dist/channel-selection-Bbm1lq3P.js +51 -0
- package/dist/channel-selection-CqcX7Ocw.js +51 -0
- package/dist/channel-web-DrsT6OAE.js +2162 -0
- package/dist/channels-cli-Juyh1S6n.js +1304 -0
- package/dist/channels-cli-zNvi1m5c.js +1306 -0
- package/dist/channels-status-issues-CqzqshW4.js +18 -0
- package/dist/channels-status-issues-DdJdO866.js +18 -0
- package/dist/chrome-C4dOMO8z.js +1601 -0
- package/dist/chrome-DdcDzAtH.js +1629 -0
- package/dist/chrome-U3DRzjJD.js +1601 -0
- package/dist/chunk-D2nLsrEW.js +348 -0
- package/dist/clack-prompter-BI3RDW5w.js +92 -0
- package/dist/clack-prompter-Dwr1m_IZ.js +92 -0
- package/dist/cli/daemon-cli.js +1 -1
- package/dist/cli-C3cpDaz8.js +99 -0
- package/dist/cli-CjWUGdGC.js +101 -0
- package/dist/cli-session-BVjY_XrW.js +5463 -0
- package/dist/cli-session-gtuYN2Iq.js +5408 -0
- package/dist/client-Dswwze5_.js +1692 -0
- package/dist/client-LRKFjo4A.js +1692 -0
- package/dist/clipboard-BZKS9O1u.js +31 -0
- package/dist/clipboard-DES8b1AM.js +31 -0
- package/dist/command-format-CP1YTNCl.js +52 -0
- package/dist/command-format-CVL4K5cj.js +52 -0
- package/dist/command-format-G6N2zghg.js +38 -0
- package/dist/command-registry-BBvNvysr.js +248 -0
- package/dist/commands-AZ3n8Y2c.js +726 -0
- package/dist/commands-BMnD_QRY.js +726 -0
- package/dist/commands-registry-cFqZ6Ib4.js +766 -0
- package/dist/commands-registry-q13H7ng5.js +766 -0
- package/dist/common-CX5458fH.js +287 -0
- package/dist/common-DJbnT8ws.js +287 -0
- package/dist/completion-cli-BADRBcIl.js +432 -0
- package/dist/completion-cli-DMQgiObF.js +431 -0
- package/dist/config-CU-Axg8P.js +5704 -0
- package/dist/config-DaqbUdkI.js +5705 -0
- package/dist/config-cli-BPlbwiuA.js +244 -0
- package/dist/config-cli-DXgZJkPU.js +247 -0
- package/dist/config-guard-Ba49JNds.js +76 -0
- package/dist/config-guard-Cu0qMKZJ.js +93 -0
- package/dist/config-kVVm5EYV.js +6523 -0
- package/dist/config-sync-CzLnLTXt.js +91 -0
- package/dist/config-sync-DuydxPWx.js +91 -0
- package/dist/configure-CHgacLyi.js +960 -0
- package/dist/configure-DfHXDa1L.js +959 -0
- package/dist/context-DzgXOckU.js +60 -0
- package/dist/control-service-8_wKHwBa.js +72 -0
- package/dist/control-service-BtL1Jto_.js +72 -0
- package/dist/cron-cli-BCzSR2c0.js +448 -0
- package/dist/cron-cli-CCWNkykU.js +451 -0
- package/dist/daemon-cli-Bjkbu9Vy.js +565 -0
- package/dist/daemon-cli-CmlHcC1J.js +566 -0
- package/dist/daemon-cli.js +16 -16
- package/dist/daemon-runtime-C0tz7VAC.js +460 -0
- package/dist/daemon-runtime-rUTqCVwJ.js +460 -0
- package/dist/deliver-BBggsviM.js +1097 -0
- package/dist/deliver-CePITOl8.js +1162 -0
- package/dist/deliver-DFnVaetP.js +1097 -0
- package/dist/delivery-queue-BJQK3oh5.js +220 -0
- package/dist/deps-CeEKhrp7.js +42 -0
- package/dist/devices-cli-DQrDMrZH.js +198 -0
- package/dist/devices-cli-Oe-A1Dv0.js +195 -0
- package/dist/diagnostics-DxMFrBLO.js +35 -0
- package/dist/diagnostics-m79ZlMmZ.js +35 -0
- package/dist/directory-cli-BL6h8cGF.js +246 -0
- package/dist/directory-cli-Cjgmi_sj.js +243 -0
- package/dist/dispatcher-DAFbQM-c.js +100 -0
- package/dist/dispatcher-DNd40gUn.js +100 -0
- package/dist/dist-CqDI82ei.js +929 -0
- package/dist/dist-DnHRxR5U.js +929 -0
- package/dist/dns-cli-CFtV3BXK.js +200 -0
- package/dist/dns-cli-NyIHvQ5S.js +197 -0
- package/dist/dock-BdXLb5oY.js +753 -0
- package/dist/dock-jYICmNcI.js +753 -0
- package/dist/docs-cli-CrOaIK_H.js +161 -0
- package/dist/docs-cli-D_cmJDSr.js +159 -0
- package/dist/doctor-BpGxKrBl.js +1815 -0
- package/dist/doctor-D12wNQPU.js +1813 -0
- package/dist/doctor-completion-DeOfofek.js +92 -0
- package/dist/doctor-completion-DwjqdEcK.js +92 -0
- package/dist/doctor-config-flow-BI3mpkbd.js +1232 -0
- package/dist/doctor-config-flow-wMHheFkC.js +1232 -0
- package/dist/engine-BCtL-AMw.js +563 -0
- package/dist/engine-Bk_UT413.js +563 -0
- package/dist/entry.js +5 -5
- package/dist/env-v6411I8h.js +32 -0
- package/dist/exec-B7sUS164.js +1167 -0
- package/dist/exec-approvals-CroGJRUg.js +1221 -0
- package/dist/exec-approvals-cli-BTxF_RsH.js +371 -0
- package/dist/exec-approvals-cli-n1gyGwH2.js +368 -0
- package/dist/exec-mhSykkaa.js +255 -0
- package/dist/extensionAPI.js +3 -3
- package/dist/frontmatter-BmHq0vRD.js +204 -0
- package/dist/gateway-cli-DDBadlrS.js +19971 -0
- package/dist/gateway-cli-IZNkOMBe.js +19972 -0
- package/dist/gateway-rpc-Dtx8HN-n.js +28 -0
- package/dist/gateway-rpc-L2PVSqGj.js +28 -0
- package/dist/github-copilot-auth-DKyqDaGU.js +1418 -0
- package/dist/github-copilot-auth-DXpOMSd3.js +1418 -0
- package/dist/gmail-setup-utils-BKNczIJ9.js +428 -0
- package/dist/gmail-setup-utils-co0ppccC.js +428 -0
- package/dist/health-Bm8ZTvC3.js +1253 -0
- package/dist/health-DUf1gt4E.js +1258 -0
- package/dist/health-format-BksT6F68.js +208 -0
- package/dist/health-format-uzh1xYLD.js +208 -0
- package/dist/heartbeat-visibility-1TJb1Zao.js +98 -0
- package/dist/heartbeat-visibility-CwodtdcX.js +98 -0
- package/dist/help-format-C6cv_aZp.js +17 -0
- package/dist/helpers-N-uSFKOn.js +10 -0
- package/dist/hooks-cli-1POsXqOl.js +993 -0
- package/dist/hooks-cli-BGjILbze.js +991 -0
- package/dist/hooks-status-DE07n5RC.js +356 -0
- package/dist/hooks-status-Du-d1jde.js +356 -0
- package/dist/image-ops-B_AYV3tp.js +541 -0
- package/dist/image-ops-Bp0C6Mvr.js +541 -0
- package/dist/index.js +82 -82
- package/dist/init-9A0s7bWG.js +122 -0
- package/dist/init-DoyCHJDC.js +122 -0
- package/dist/installs-D1C9wHAq.js +383 -0
- package/dist/installs-Dh4dHayM.js +383 -0
- package/dist/ipv4-DCItfaJo.js +1964 -0
- package/dist/ipv4-DSOUVx0i.js +1964 -0
- package/dist/lanes-BvSnHq2h.js +232 -0
- package/dist/lifecycle-core-BY4WIf9g.js +388 -0
- package/dist/lifecycle-core-TQKyXO-6.js +387 -0
- package/dist/links-CNu_8RZl.js +15 -0
- package/dist/links-D2tt2ouh.js +15 -0
- package/dist/llm-slug-generator.js +4 -4
- package/dist/logging-BIeRw0WR.js +15 -0
- package/dist/logging-C7lb3Vjc.js +15 -0
- package/dist/login-DXWKewA2.js +59 -0
- package/dist/login-Fhh4uWmf.js +61 -0
- package/dist/login-pPs3UO38.js +61 -0
- package/dist/login-qr-CevLD8cV.js +326 -0
- package/dist/login-qr-GF2JMIy-.js +323 -0
- package/dist/login-qr-ZYYKD6Yt.js +321 -0
- package/dist/logs-cli-CzXbX8HZ.js +242 -0
- package/dist/logs-cli-D9ngH9PF.js +245 -0
- package/dist/manager-BD5rA3w0.js +3244 -0
- package/dist/manager-BDPgBQSH.js +3246 -0
- package/dist/manager-DRWMWM--.js +3244 -0
- package/dist/manifest-registry-DbvPaBXY.js +748 -0
- package/dist/manifest-registry-kHX_MFa1.js +748 -0
- package/dist/markdown-tables-CqwihY2m.js +347 -0
- package/dist/markdown-tables-DJV7eAJZ.js +348 -0
- package/dist/media-lUqN-0O9.js +1342 -0
- package/dist/memory-cli-BLXSpgnN.js +868 -0
- package/dist/memory-cli-BcGVkkRJ.js +869 -0
- package/dist/message-channel-D_jIO87f.js +110 -0
- package/dist/migrate-BpVOar4L.js +157 -0
- package/dist/migrate-CkgGDkWy.js +157 -0
- package/dist/model-selection-Cqt6aJ0G.js +2691 -0
- package/dist/models-CExsNQPH.js +2510 -0
- package/dist/models-cli-Ba3Jmwev.js +2739 -0
- package/dist/models-cli-iDAlsbL2.js +258 -0
- package/dist/net-0A_zcaQD.js +218 -0
- package/dist/node-cli-ATmwCXIk.js +1319 -0
- package/dist/node-cli-DYFR_V25.js +1322 -0
- package/dist/node-service-CN4LqR1A.js +67 -0
- package/dist/node-service-CWt3MdSC.js +67 -0
- package/dist/nodes-cli-BeVmhTz3.js +1197 -0
- package/dist/nodes-cli-QeJIfa18.js +1200 -0
- package/dist/nodes-screen-DHyWAlla.js +234 -0
- package/dist/nodes-screen-qs3jRBPk.js +234 -0
- package/dist/note-CSlg2BnB.js +73 -0
- package/dist/note-Ctvglhp1.js +73 -0
- package/dist/npm-registry-spec-DQd4M22q.js +351 -0
- package/dist/npm-registry-spec-PxisIMts.js +351 -0
- package/dist/onboard-DeruD10m.js +1166 -0
- package/dist/onboard-SAcu5N6N.js +1165 -0
- package/dist/onboard-channels-C4iSfFXR.js +672 -0
- package/dist/onboard-channels-oVTVgoyg.js +672 -0
- package/dist/onboard-helpers-B8roRwLP.js +365 -0
- package/dist/onboard-helpers-Dgh26hgP.js +365 -0
- package/dist/onboarding-Bi-ac8we.js +911 -0
- package/dist/onboarding-C2gjB2u8.js +910 -0
- package/dist/orchestrator-DlbAYMQP.js +357 -0
- package/dist/orchestrator-DlwVRVDA.js +357 -0
- package/dist/outbound-CkKgc6iR.js +2062 -0
- package/dist/outbound-Vfm5yDh3.js +214 -0
- package/dist/outbound-bs_VK51X.js +214 -0
- package/dist/outbound-send-deps-DDjiMfEL.js +55 -0
- package/dist/pairing-cli-CJYeuEik.js +118 -0
- package/dist/pairing-cli-mqopHI8s.js +121 -0
- package/dist/pairing-store-BsXzUDPv.js +388 -0
- package/dist/pairing-store-DoNj00-X.js +388 -0
- package/dist/path-env-C_xpiG8l.js +89 -0
- package/dist/path-env-DSSMHu5A.js +89 -0
- package/dist/paths-B1vRVCad.js +126 -0
- package/dist/paths-BMuHNFxg.js +238 -0
- package/dist/paths-BXQQzXGQ.js +129 -0
- package/dist/paths-Buw_geoe.js +54 -0
- package/dist/paths-DA9WYabg.js +222 -0
- package/dist/paths-DfQGx0_k.js +129 -0
- package/dist/pi-auth-json-DOPW3e4X.js +78 -0
- package/dist/pi-auth-json-MruLmI_X.js +82 -0
- package/dist/pi-auth-json-lae_wwwo.js +80 -0
- package/dist/pi-model-discovery-7q0GxMrp.js +3 -0
- package/dist/pi-tools.policy-Csmla32P.js +200 -0
- package/dist/pi-tools.policy-xYdDLEv9.js +200 -0
- package/dist/plugin-auto-enable-CViVVWgg.js +282 -0
- package/dist/plugin-auto-enable-CjZ238UI.js +282 -0
- package/dist/plugin-registry-B4Aw2hzq.js +32 -0
- package/dist/plugin-registry-DW81arxW.js +32 -0
- package/dist/plugin-sdk/cli/cli-name.d.ts +1 -1
- package/dist/plugin-sdk/config/paths.d.ts +2 -2
- package/dist/plugin-sdk/index.js +7 -7
- package/dist/plugins-DhcGAPDB.js +38 -0
- package/dist/plugins-DtghNRtM.js +168 -0
- package/dist/plugins-cli-4vWTmOAb.js +736 -0
- package/dist/plugins-cli-CdTMbP0X.js +734 -0
- package/dist/polls-D6eCdatA.js +1343 -0
- package/dist/ports-BtZx-JKD.js +96 -0
- package/dist/ports-C8bKN8s0.js +96 -0
- package/dist/ports-DHiKnPRX.js +344 -0
- package/dist/ports-vd93M_Pt.js +317 -0
- package/dist/program-CX3aUVeb.js +176 -0
- package/dist/program-context-BPos0ivo.js +496 -0
- package/dist/progress-oiAjiiNi.js +133 -0
- package/dist/prompt-style-Cm4wOtKm.js +9 -0
- package/dist/pw-ai-4QbK5YFe.js +1865 -0
- package/dist/pw-ai-BWz3Cxt7.js +1868 -0
- package/dist/pw-ai-C83HBue2.js +1867 -0
- package/dist/qmd-manager-BcMeZiGD.js +938 -0
- package/dist/qmd-manager-CPypGJ0P.js +935 -0
- package/dist/qmd-manager-CRrSkfia.js +937 -0
- package/dist/register.agent-DDY8KJhn.js +265 -0
- package/dist/register.agent-DKawm-9d.js +1003 -0
- package/dist/register.anima-CEWUo29k.js +193 -0
- package/dist/register.anima-DBWz2rk_.js +193 -0
- package/dist/register.configure-BX67qV8k.js +103 -0
- package/dist/register.configure-CWsySuiq.js +101 -0
- package/dist/register.maintenance-0k-ZNhDg.js +543 -0
- package/dist/register.maintenance-BIwx1fzX.js +543 -0
- package/dist/register.message-CXPsoakA.js +657 -0
- package/dist/register.message-DA3jvfgI.js +660 -0
- package/dist/register.onboard-C4HG7Hqv.js +170 -0
- package/dist/register.onboard-GOpdif-j.js +170 -0
- package/dist/register.setup-B17vZT7C.js +175 -0
- package/dist/register.setup-GJyUDCqh.js +175 -0
- package/dist/register.status-health-sessions-D5876dGx.js +313 -0
- package/dist/register.status-health-sessions-lOewVIZR.js +142 -0
- package/dist/register.subclis-Dwnujj5C.js +255 -0
- package/dist/reply-CR5T_oQJ.js +32212 -0
- package/dist/reply-prefix-BcrS4Umd.js +100 -0
- package/dist/reply-prefix-Btb5o2NH.js +100 -0
- package/dist/reply-r089HuRA.js +32212 -0
- package/dist/routes-B4czFzIb.js +1820 -0
- package/dist/routes-ucJWAk5O.js +1820 -0
- package/dist/rpc-BnKxnQ0v.js +70 -0
- package/dist/rpc-DgE-xnyx.js +70 -0
- package/dist/run-main-B74kv84C.js +371 -0
- package/dist/runtime-guard-CKFdts2L.js +60 -0
- package/dist/sandbox-CJTS3er6.js +858 -0
- package/dist/sandbox-DBSiVHt_.js +859 -0
- package/dist/sandbox-cli-CrkjyU5M.js +461 -0
- package/dist/sandbox-cli-D1r5y6Sz.js +458 -0
- package/dist/security-cli-BZUdnkhn.js +462 -0
- package/dist/security-cli-DS09ebvA.js +465 -0
- package/dist/server-context-C0xZbYhg.js +824 -0
- package/dist/server-context-DVh2z7om.js +824 -0
- package/dist/server-node-events-bu9lpkMH.js +233 -0
- package/dist/server-node-events-i1Rrww31.js +231 -0
- package/dist/service-CJJwLEor.js +642 -0
- package/dist/service-DxLxBhaU.js +642 -0
- package/dist/service-audit-DB4Y3Ekp.js +488 -0
- package/dist/service-audit-M8y4TXVb.js +488 -0
- package/dist/session-CGxOLFs2.js +179 -0
- package/dist/session-DTTbdKb0.js +181 -0
- package/dist/session-cost-usage-FcdJl9c3.js +600 -0
- package/dist/session-cost-usage-qdfsGU2a.js +600 -0
- package/dist/session-yOhWcsD2.js +181 -0
- package/dist/sessions-B-Cu7JZq.js +1296 -0
- package/dist/sessions-BgLN4KFr.js +180 -0
- package/dist/sessions-CnRjwdVr.js +1296 -0
- package/dist/sessions-wRKla1Qh.js +2038 -0
- package/dist/shared-DS3UaJSP.js +66 -0
- package/dist/shared-DxNHzky3.js +77 -0
- package/dist/shared-Qpt4hUDi.js +66 -0
- package/dist/shared-kzrojZ1B.js +77 -0
- package/dist/skill-scanner-DLJji5Ye.js +263 -0
- package/dist/skills-BWFIEp4j.js +807 -0
- package/dist/skills-DV4zKdCx.js +808 -0
- package/dist/skills-cli-BY53ILm2.js +289 -0
- package/dist/skills-cli-CO3gxl8A.js +286 -0
- package/dist/skills-status-DX5pcqY3.js +166 -0
- package/dist/skills-status-zhcKzGkp.js +166 -0
- package/dist/sqlite-B6MojU1I.js +321 -0
- package/dist/sqlite-CuprTGR7.js +453 -0
- package/dist/sqlite-dzD-jMjs.js +368 -0
- package/dist/start-Cu3aLoSf.js +297 -0
- package/dist/start-Dz7tMAl8.js +296 -0
- package/dist/status-CaSxhxfV.js +2132 -0
- package/dist/status-D2C0JCX3.js +2137 -0
- package/dist/status-DlFMsQzh.js +27 -0
- package/dist/status-G0CITnKR.js +27 -0
- package/dist/status.update-CHjhVxJY.js +79 -0
- package/dist/status.update-DVFelehi.js +79 -0
- package/dist/subagent-registry-3Xb4el-8.js +14 -0
- package/dist/subagent-registry-CdSjz14I.js +2760 -0
- package/dist/subagent-registry-DNDhbHWi.js +2759 -0
- package/dist/subsystem-DfKstnEK.js +860 -0
- package/dist/system-cli-B5mt0FWa.js +82 -0
- package/dist/system-cli-Dg3UQ3Zz.js +79 -0
- package/dist/systemd-B43AvOGx.js +452 -0
- package/dist/systemd-RpPE0XGg.js +452 -0
- package/dist/systemd-hints-DMJT-Bbc.js +36 -0
- package/dist/systemd-hints-vRInKcz9.js +36 -0
- package/dist/systemd-linger-Dzyxqsod.js +75 -0
- package/dist/systemd-linger-EujbmI5A.js +75 -0
- package/dist/table-DhXHfRX2.js +279 -0
- package/dist/table-bWCLW-3P.js +279 -0
- package/dist/timeout-Ddn-5kAO.js +232 -0
- package/dist/tokens-3psI_Qk2.js +14 -0
- package/dist/tokens-BaM53PEx.js +14 -0
- package/dist/trash-Bmxs1Rnm.js +23 -0
- package/dist/trash-C39a6hKA.js +23 -0
- package/dist/tui-BHgBWhHE.js +3894 -0
- package/dist/tui-cli-B9Sq5-cC.js +50 -0
- package/dist/tui-cli-Dw7v4JoJ.js +47 -0
- package/dist/tui-mUwDwqvd.js +3894 -0
- package/dist/update-DF0GHG0j.js +317 -0
- package/dist/update-DoZLVjva.js +317 -0
- package/dist/update-check-Bt1dVPVN.js +400 -0
- package/dist/update-check-D5qAKes7.js +400 -0
- package/dist/update-cli-BNu2Oi7H.js +1105 -0
- package/dist/update-cli-D36AmALA.js +1105 -0
- package/dist/update-runner-CNQQaTwA.js +894 -0
- package/dist/update-runner-CvxZmbu-.js +894 -0
- package/dist/usage-BGCwNnjk.js +4516 -0
- package/dist/utils-DZ8pnOD5.js +243 -0
- package/dist/web-B5QG839O.js +46842 -0
- package/dist/web-Cmnvk9v0.js +2203 -0
- package/dist/web-Cv2KnTnL.js +63 -0
- package/dist/webhooks-cli-B6y89Pj_.js +319 -0
- package/dist/webhooks-cli-BDzHON4w.js +316 -0
- package/dist/whatsapp-actions-C_5MwVxM.js +45 -0
- package/dist/whatsapp-actions-hgYA12To.js +53 -0
- package/dist/whatsapp-actions-zTiVOoOV.js +49 -0
- package/dist/widearea-dns-BeIdnISJ.js +127 -0
- package/dist/widearea-dns-CF1gxpJ-.js +127 -0
- package/dist/workspace-DLna1IxR.js +649 -0
- package/dist/ws-log-Q4wO1Ztb.js +267 -0
- package/dist/ws-log-xF0kxDzp.js +267 -0
- package/package.json +1 -2
- package/dist/accounts-Cc5E4IDO.js +0 -260
- package/dist/accounts-CcVrwKqv.js +0 -259
- package/dist/acp-cli-DvphOKuh.js +0 -1081
- package/dist/acp-cli-p28pQ65a.js +0 -1084
- package/dist/agent-Cj7uDJaZ.js +0 -725
- package/dist/agent-Cuj9-2sT.js +0 -725
- package/dist/agent-events-BEBQsyE5.js +0 -182
- package/dist/agent-scope-BVf4aSwY.js +0 -112
- package/dist/agent-scope-OZi7lb8S.js +0 -452
- package/dist/agent-scope-V1bi9OYL.js +0 -452
- package/dist/agents-BUWqn_Ui.js +0 -774
- package/dist/agents.config-Dvo2ULxs.js +0 -182
- package/dist/agents.config-d6H0_3oj.js +0 -182
- package/dist/argv-DqUHKf0o.js +0 -73
- package/dist/audit-C6okOOSh.js +0 -2401
- package/dist/audit-VWjIdwC7.js +0 -2401
- package/dist/auth-91o2YM96.js +0 -648
- package/dist/auth-choice-CAmACV13.js +0 -2681
- package/dist/auth-choice-p3SeHPj2.js +0 -2681
- package/dist/auth-health-B_jXrWe6.js +0 -149
- package/dist/auth-health-DCicUKYR.js +0 -149
- package/dist/auth-lZ26wsbN.js +0 -639
- package/dist/auth-profiles-CCDD56dU.js +0 -1564
- package/dist/auth-profiles-DxI8L7bs.js +0 -2689
- package/dist/banner-Cohn04J6.js +0 -294
- package/dist/browser-cli-DANzjztE.js +0 -1676
- package/dist/browser-cli-WjsVH741.js +0 -1679
- package/dist/call-BAHvlu2G.js +0 -282
- package/dist/call-Ct7EGP_L.js +0 -282
- package/dist/catalog-BAayBt1L.js +0 -185
- package/dist/catalog-BNsf97BM.js +0 -185
- package/dist/channel-options-Dx9nPlX8.js +0 -33
- package/dist/channel-options-ZdvXrTGs.js +0 -32
- package/dist/channel-selection-CujyiWGM.js +0 -51
- package/dist/channel-selection-DfGpCyh2.js +0 -51
- package/dist/channel-web-CC0hkgkR.js +0 -2162
- package/dist/channels-cli-D7lNBpIb.js +0 -1304
- package/dist/channels-cli-DUPG8WDv.js +0 -1306
- package/dist/channels-status-issues-DBc1pU_R.js +0 -18
- package/dist/channels-status-issues-DjO9MHIG.js +0 -18
- package/dist/chrome-Bi6iZ5sG.js +0 -1601
- package/dist/chrome-DNSv7Cpy.js +0 -1629
- package/dist/chrome-DScZx4Lk.js +0 -1601
- package/dist/chunk-mxPVo000.js +0 -348
- package/dist/clack-prompter-B0kl7shw.js +0 -92
- package/dist/clack-prompter-B1YxZdRy.js +0 -92
- package/dist/cli-CfHUkOD0.js +0 -101
- package/dist/cli-ClMrIh6l.js +0 -99
- package/dist/cli-session-BkPTd9Pk.js +0 -5463
- package/dist/cli-session-Dd8DKb5a.js +0 -5408
- package/dist/client-C1avc0vD.js +0 -1692
- package/dist/client-CC94YZrT.js +0 -1692
- package/dist/clipboard-B2fBy8tG.js +0 -31
- package/dist/clipboard-BbGnZskJ.js +0 -31
- package/dist/command-format-Clp46jkj.js +0 -38
- package/dist/command-format-DELazozB.js +0 -52
- package/dist/command-format-SkzzRqR1.js +0 -52
- package/dist/command-registry-DZ4hkmA0.js +0 -248
- package/dist/commands-DtYZJSPn.js +0 -568
- package/dist/commands-Dujk1JmY.js +0 -568
- package/dist/commands-registry-Bd0xbvwG.js +0 -766
- package/dist/commands-registry-DYfRSVF3.js +0 -766
- package/dist/common-D6bu0zHC.js +0 -287
- package/dist/common-zW9Y2P1B.js +0 -287
- package/dist/completion-cli-tSe7Pmqm.js +0 -431
- package/dist/completion-cli-vn4IScs5.js +0 -432
- package/dist/config-C8rUDJXY.js +0 -5704
- package/dist/config-CLZ_XGVw.js +0 -6523
- package/dist/config-SY8M0kM_.js +0 -5705
- package/dist/config-cli-1V7D2Wsw.js +0 -247
- package/dist/config-cli-CjWEC81L.js +0 -244
- package/dist/config-guard-BW2gpKj_.js +0 -93
- package/dist/config-guard-BvxuzHpo.js +0 -76
- package/dist/config-sync-CoIIbEOe.js +0 -91
- package/dist/config-sync-DvAttep0.js +0 -91
- package/dist/configure-Bf0oupCE.js +0 -959
- package/dist/configure-DRM-7zFf.js +0 -960
- package/dist/context-D5iEFzv9.js +0 -60
- package/dist/control-service-C8m8F9pr.js +0 -72
- package/dist/control-service-DKotCWCg.js +0 -72
- package/dist/cron-cli-DB_FLYHD.js +0 -448
- package/dist/cron-cli-bxm5lrrO.js +0 -451
- package/dist/daemon-cli-1LsOnICv.js +0 -566
- package/dist/daemon-cli-CC2NrJ7a.js +0 -565
- package/dist/daemon-runtime-BXZhtBL9.js +0 -460
- package/dist/daemon-runtime-DW4USC7r.js +0 -460
- package/dist/deliver-B4HuPwJA.js +0 -1162
- package/dist/deliver-LiY5oL52.js +0 -1097
- package/dist/deliver-xrmk7xjh.js +0 -1097
- package/dist/delivery-queue-TnQykYsg.js +0 -220
- package/dist/deps-CMMOiOsF.js +0 -42
- package/dist/devices-cli-Be5he2SA.js +0 -195
- package/dist/devices-cli-z6ecoFe9.js +0 -198
- package/dist/diagnostics-Dj75aEHN.js +0 -35
- package/dist/diagnostics-DlIw6fqD.js +0 -35
- package/dist/directory-cli-CEy-0nxj.js +0 -243
- package/dist/directory-cli-DpzKcigr.js +0 -246
- package/dist/dispatcher-10Shiuz3.js +0 -100
- package/dist/dispatcher-3Jae6AiW.js +0 -100
- package/dist/dns-cli-Bat1pkc-.js +0 -200
- package/dist/dns-cli-NohNyEo0.js +0 -197
- package/dist/dock-DbxBBv30.js +0 -753
- package/dist/dock-cPBY4qGl.js +0 -753
- package/dist/docs-cli-BWp6p-Tq.js +0 -161
- package/dist/docs-cli-x22FnZfL.js +0 -159
- package/dist/doctor-BrT5m_on.js +0 -1815
- package/dist/doctor-Pp2HVnjM.js +0 -1813
- package/dist/doctor-completion-DNTimX9o.js +0 -92
- package/dist/doctor-completion-ylN9QAJ6.js +0 -92
- package/dist/doctor-config-flow-D1w3700T.js +0 -1232
- package/dist/doctor-config-flow-Dq50iE1R.js +0 -1232
- package/dist/engine-B9avUJL5.js +0 -563
- package/dist/engine-BiUQ25D4.js +0 -563
- package/dist/env-0lJfCPsw.js +0 -32
- package/dist/exec-BenD3A5l.js +0 -1167
- package/dist/exec-Bv3pyjeM.js +0 -255
- package/dist/exec-approvals-CdLmKX2R.js +0 -1221
- package/dist/exec-approvals-cli-DXfV6G8H.js +0 -368
- package/dist/exec-approvals-cli-J2cZs10o.js +0 -371
- package/dist/frontmatter-YijVi0FQ.js +0 -204
- package/dist/gateway-cli-DOAbA0pc.js +0 -19972
- package/dist/gateway-cli-QpWtBhQy.js +0 -19971
- package/dist/gateway-rpc-DJKBil9s.js +0 -28
- package/dist/gateway-rpc-DVterpLP.js +0 -28
- package/dist/github-copilot-auth-4IUFp669.js +0 -1418
- package/dist/github-copilot-auth-C9E0IROs.js +0 -1418
- package/dist/gmail-setup-utils-BPo_LkKI.js +0 -428
- package/dist/gmail-setup-utils-D3Yqgor7.js +0 -428
- package/dist/health-BeZnqp6m.js +0 -1258
- package/dist/health-Cn2OoVWZ.js +0 -1253
- package/dist/health-format-CdP99j3Y.js +0 -208
- package/dist/health-format-JEChH08S.js +0 -208
- package/dist/heartbeat-visibility-BL3WAchI.js +0 -98
- package/dist/heartbeat-visibility-CQ9QimI7.js +0 -98
- package/dist/help-format-Dl4bsrLI.js +0 -17
- package/dist/helpers-ZKNRexvX.js +0 -10
- package/dist/hooks-cli-D99hXt7K.js +0 -991
- package/dist/hooks-cli-DMB8RiEO.js +0 -993
- package/dist/hooks-status-B-e96dZj.js +0 -356
- package/dist/hooks-status-C_9sE0ox.js +0 -356
- package/dist/image-ops-Dlt3T7th.js +0 -541
- package/dist/image-ops-omlvdfah.js +0 -541
- package/dist/init-Bm04RagW.js +0 -122
- package/dist/init-CaJBf4p1.js +0 -122
- package/dist/installs-C2iMRBVz.js +0 -383
- package/dist/installs-D-cPGdCw.js +0 -383
- package/dist/ipv4-Bf7NS3QU.js +0 -1964
- package/dist/ipv4-wWNs8IH_.js +0 -1964
- package/dist/lanes-CNxj3tit.js +0 -232
- package/dist/lifecycle-core-B_7XRcvF.js +0 -388
- package/dist/lifecycle-core-By83PVAK.js +0 -387
- package/dist/links-BfjHVTB_.js +0 -15
- package/dist/links-DPGe0OHw.js +0 -15
- package/dist/logging-DB6BQmhi.js +0 -15
- package/dist/logging-mcb66J0p.js +0 -15
- package/dist/login-BDCg6D0N.js +0 -61
- package/dist/login-BDfnbjnZ.js +0 -59
- package/dist/login-BqH1itcg.js +0 -61
- package/dist/login-qr-CyOw3R4r.js +0 -321
- package/dist/login-qr-D8ECtb72.js +0 -323
- package/dist/login-qr-RnR7e4Bw.js +0 -326
- package/dist/logs-cli--j89L74J.js +0 -245
- package/dist/logs-cli-DpEMg_Gq.js +0 -242
- package/dist/manager-B4OyvcxT.js +0 -3244
- package/dist/manager-Cqc1CeH7.js +0 -3246
- package/dist/manager-DUyQPFvj.js +0 -3244
- package/dist/manifest-registry-CW1zCyRF.js +0 -748
- package/dist/manifest-registry-D4lM2RdV.js +0 -748
- package/dist/markdown-tables-BT1X6jqH.js +0 -347
- package/dist/markdown-tables-DHgOK2vI.js +0 -348
- package/dist/media-THyainiE.js +0 -1342
- package/dist/memory-cli-BKocCWXM.js +0 -868
- package/dist/memory-cli-Jmma-xI_.js +0 -869
- package/dist/message-channel-dSTVVCyX.js +0 -110
- package/dist/migrate-BR6iAIjO.js +0 -157
- package/dist/migrate-D0EcMs0f.js +0 -157
- package/dist/model-selection-YcSr9CgC.js +0 -2691
- package/dist/models-1vUQBVfw.js +0 -2510
- package/dist/models-cli-BK3BwUhL.js +0 -2739
- package/dist/models-cli-DECrM8oA.js +0 -258
- package/dist/net-B5lXhYLV.js +0 -218
- package/dist/node-cli-cLHUNpPD.js +0 -1319
- package/dist/node-cli-fO7Y132S.js +0 -1322
- package/dist/node-service-BFxHJsno.js +0 -67
- package/dist/node-service-DUnan4uK.js +0 -67
- package/dist/nodes-cli-BCq35E6N.js +0 -1200
- package/dist/nodes-cli-vD7MwAKP.js +0 -1197
- package/dist/nodes-screen-1YiLkqr5.js +0 -234
- package/dist/nodes-screen-DZeD8hE5.js +0 -234
- package/dist/note-Bi8Wb8DV.js +0 -73
- package/dist/note-uiuPxhyX.js +0 -73
- package/dist/npm-registry-spec-B-XIShkB.js +0 -351
- package/dist/npm-registry-spec-za3itb5Y.js +0 -351
- package/dist/onboard-Ds6w_sWo.js +0 -1165
- package/dist/onboard-SAVx3bp4.js +0 -1166
- package/dist/onboard-channels-Cg_EkBa4.js +0 -672
- package/dist/onboard-channels-D7NbA55V.js +0 -672
- package/dist/onboard-helpers-DO_hgZb9.js +0 -365
- package/dist/onboard-helpers-_XgJgeqh.js +0 -365
- package/dist/onboarding-3hLmDd0r.js +0 -911
- package/dist/onboarding-B4LKLsbU.js +0 -910
- package/dist/orchestrator-BKzmyBWy.js +0 -357
- package/dist/orchestrator-BN3QCz2s.js +0 -357
- package/dist/outbound-BgA9hNlP.js +0 -2062
- package/dist/outbound-CjdvVhUI.js +0 -214
- package/dist/outbound-DOGe6qb2.js +0 -214
- package/dist/outbound-send-deps-Du5aBpd7.js +0 -55
- package/dist/pairing-cli-2vnyg_Nd.js +0 -118
- package/dist/pairing-cli-BH1KQtNV.js +0 -121
- package/dist/pairing-store-DJz_9Gv0.js +0 -388
- package/dist/pairing-store-DmOzxcuk.js +0 -388
- package/dist/path-env-Bu6k0jDQ.js +0 -89
- package/dist/path-env-C0zQSjw8.js +0 -89
- package/dist/paths-BTc4nk-6.js +0 -126
- package/dist/paths-BgUi2Z2G.js +0 -54
- package/dist/paths-C6VCWKo3.js +0 -238
- package/dist/paths-CCxa0o9c.js +0 -222
- package/dist/paths-CxRf2rBG.js +0 -129
- package/dist/paths-hcX1Gqg5.js +0 -129
- package/dist/pi-auth-json-B68R7q7_.js +0 -82
- package/dist/pi-auth-json-CR0jXAgq.js +0 -78
- package/dist/pi-auth-json-ZYzi3nxs.js +0 -80
- package/dist/pi-model-discovery-Cxs4pvC2.js +0 -3
- package/dist/pi-tools.policy-D81U5xy0.js +0 -200
- package/dist/pi-tools.policy-DSHkkb5b.js +0 -200
- package/dist/plugin-auto-enable-CxF4bpDN.js +0 -282
- package/dist/plugin-auto-enable-jNaAeyEh.js +0 -282
- package/dist/plugin-registry-C7XWotZG.js +0 -32
- package/dist/plugin-registry-DcUCbGax.js +0 -32
- package/dist/plugins-B362e77G.js +0 -168
- package/dist/plugins-CmSUIUNi.js +0 -38
- package/dist/plugins-cli-BsCEnoQ7.js +0 -734
- package/dist/plugins-cli-QSIsMUG7.js +0 -736
- package/dist/polls-CItfB1H8.js +0 -1343
- package/dist/ports-BVLMN1Sr.js +0 -96
- package/dist/ports-CqLSlU6Z.js +0 -317
- package/dist/ports-D94CwCrv.js +0 -344
- package/dist/ports-D_NHthOz.js +0 -96
- package/dist/program-DkJHjI0R.js +0 -176
- package/dist/program-context-DnyGM2SC.js +0 -496
- package/dist/progress-Bek_GyWS.js +0 -133
- package/dist/prompt-style-lu0clOOE.js +0 -9
- package/dist/pw-ai-BLVMuSLv.js +0 -1867
- package/dist/pw-ai-DZJWEF_f.js +0 -1865
- package/dist/pw-ai-dzf-ptcn.js +0 -1868
- package/dist/qmd-manager-Cur_Ekn0.js +0 -937
- package/dist/qmd-manager-DNAUuwjK.js +0 -938
- package/dist/qmd-manager-DepEoASu.js +0 -935
- package/dist/register.agent-CSWvzOkR.js +0 -265
- package/dist/register.agent-UeH2NXmH.js +0 -1003
- package/dist/register.anima-DOdee0dh.js +0 -193
- package/dist/register.anima-HHDWsz6r.js +0 -193
- package/dist/register.configure-CSJFxdz9.js +0 -103
- package/dist/register.configure-D84Fvcz4.js +0 -101
- package/dist/register.maintenance-B3pvNbZb.js +0 -543
- package/dist/register.maintenance-BKVOwkw6.js +0 -543
- package/dist/register.message-BAO6CPl2.js +0 -657
- package/dist/register.message-OXoOKE_6.js +0 -660
- package/dist/register.onboard-BK_ixVmD.js +0 -170
- package/dist/register.onboard-cfCaPx6j.js +0 -170
- package/dist/register.setup-BGfDnzph.js +0 -175
- package/dist/register.setup-Y-Q74M-0.js +0 -175
- package/dist/register.status-health-sessions-CT14eitH.js +0 -142
- package/dist/register.status-health-sessions-TfZMzAUn.js +0 -313
- package/dist/register.subclis-BZwdlNHC.js +0 -255
- package/dist/reply-mlsExaZm.js +0 -32212
- package/dist/reply-prefix-B0CfR4bM.js +0 -100
- package/dist/reply-prefix-w4a39ybC.js +0 -100
- package/dist/reply-qalRISe_.js +0 -32212
- package/dist/routes-CENsHJyg.js +0 -1820
- package/dist/routes-DO0HqW2e.js +0 -1820
- package/dist/rpc-C0pjNhBi.js +0 -70
- package/dist/rpc-DZ44PIXE.js +0 -70
- package/dist/run-main-BMpKw8Mp.js +0 -371
- package/dist/runtime-guard-BSUFiAQV.js +0 -60
- package/dist/sandbox-BIGfMYEI.js +0 -858
- package/dist/sandbox-DxP3IpUP.js +0 -859
- package/dist/sandbox-cli-DtLGH8sL.js +0 -461
- package/dist/sandbox-cli-_Tg7lfJ_.js +0 -458
- package/dist/security-cli-BRwgbedo.js +0 -462
- package/dist/security-cli-D3bSuyZt.js +0 -465
- package/dist/server-context-49XFFxFg.js +0 -824
- package/dist/server-context-LrlgrZzS.js +0 -824
- package/dist/server-node-events-Dm52i7NW.js +0 -231
- package/dist/server-node-events-QX523UyF.js +0 -233
- package/dist/service-BNVpYcQe.js +0 -642
- package/dist/service-D56aMXUB.js +0 -642
- package/dist/service-audit-D0X_XAB2.js +0 -488
- package/dist/service-audit-qmf6XMmP.js +0 -488
- package/dist/session-CrQQLLhx.js +0 -179
- package/dist/session-LocsOOWJ.js +0 -181
- package/dist/session-Vlce2BAT.js +0 -181
- package/dist/session-cost-usage-BwiTZuKl.js +0 -600
- package/dist/session-cost-usage-DT9YNXTJ.js +0 -600
- package/dist/sessions-BfV53TbG.js +0 -1296
- package/dist/sessions-BimpX_km.js +0 -180
- package/dist/sessions-DcXpzig0.js +0 -1296
- package/dist/sessions-Wd18dukK.js +0 -2038
- package/dist/shared-Bsr69u_7.js +0 -77
- package/dist/shared-Cgly1vPb.js +0 -66
- package/dist/shared-JOo05hST.js +0 -66
- package/dist/shared-f7dvQsi7.js +0 -77
- package/dist/skill-scanner-CkaVLABv.js +0 -263
- package/dist/skills-B-G7UHOa.js +0 -808
- package/dist/skills-B5LQx4lT.js +0 -807
- package/dist/skills-cli-DUGe2ZWW.js +0 -286
- package/dist/skills-cli-DtOk0bvK.js +0 -289
- package/dist/skills-status-Clq9ZnYu.js +0 -166
- package/dist/skills-status-JQluhU-P.js +0 -166
- package/dist/sqlite-BukcjdJa.js +0 -321
- package/dist/sqlite-CGcOZZ0C.js +0 -368
- package/dist/sqlite-Ck6f9KWc.js +0 -453
- package/dist/start--xmSFepB.js +0 -372
- package/dist/start-BdlZbqrr.js +0 -371
- package/dist/status-BgoeFm6g.js +0 -2137
- package/dist/status-BjjDrUq7.js +0 -27
- package/dist/status-Ct0DgOZ-.js +0 -2132
- package/dist/status-RA_uNmK0.js +0 -27
- package/dist/status.update-BjOH3GlS.js +0 -79
- package/dist/status.update-DLU1qBf0.js +0 -79
- package/dist/subagent-registry-9RLdKxES.js +0 -2760
- package/dist/subagent-registry-Byuex3zp.js +0 -2759
- package/dist/subagent-registry-DOBunBYS.js +0 -14
- package/dist/subsystem-Dowf8fSU.js +0 -860
- package/dist/system-cli-C5oBpzni.js +0 -79
- package/dist/system-cli-DXNKD_Id.js +0 -82
- package/dist/systemd-BSrHDyeU.js +0 -452
- package/dist/systemd-By5xdSB4.js +0 -452
- package/dist/systemd-hints-BtjL_5Rh.js +0 -36
- package/dist/systemd-hints-sJmr6cjb.js +0 -36
- package/dist/systemd-linger-CTmV2Gci.js +0 -75
- package/dist/systemd-linger-CmyqQkeC.js +0 -75
- package/dist/table-BL0lJzsm.js +0 -279
- package/dist/table-DoiRPsn0.js +0 -279
- package/dist/timeout-CswI_K-U.js +0 -232
- package/dist/tokens-C-X7wDKj.js +0 -14
- package/dist/tokens-DkvqA72p.js +0 -14
- package/dist/trash-BJLK1vMn.js +0 -23
- package/dist/trash-_x5UZ94k.js +0 -23
- package/dist/tui-BHjxDFZC.js +0 -3894
- package/dist/tui-CgOocwN8.js +0 -3894
- package/dist/tui-cli-5ANH8dE5.js +0 -47
- package/dist/tui-cli-BQ4P-JW_.js +0 -50
- package/dist/update-LFgxHHPd.js +0 -317
- package/dist/update-TxptCqk7.js +0 -317
- package/dist/update-check-CWc7YXmc.js +0 -400
- package/dist/update-check-IhlWaui6.js +0 -400
- package/dist/update-cli-PtXU62w7.js +0 -1105
- package/dist/update-cli-Va0EtETG.js +0 -1105
- package/dist/update-runner-BLeKFkiB.js +0 -894
- package/dist/update-runner-Iuzpc-_y.js +0 -894
- package/dist/usage-ApGvBLVg.js +0 -4516
- package/dist/utils-Bsw__U-F.js +0 -243
- package/dist/web-B6_Ky60G.js +0 -63
- package/dist/web-EZLQEWXY.js +0 -46842
- package/dist/web-pec8YJUX.js +0 -2203
- package/dist/webhooks-cli-BYQKTHTp.js +0 -319
- package/dist/webhooks-cli-C2_xtsUQ.js +0 -316
- package/dist/whatsapp-actions-C72VCq8f.js +0 -49
- package/dist/whatsapp-actions-Ck9Uv0Nw.js +0 -45
- package/dist/whatsapp-actions-D0reTj2k.js +0 -53
- package/dist/widearea-dns-B6ocX23x.js +0 -127
- package/dist/widearea-dns-NsEUNYwz.js +0 -127
- package/dist/workspace-Dcfoy5JJ.js +0 -649
- package/dist/ws-log-N8R5MvGE.js +0 -267
- package/dist/ws-log-gwFxPxj5.js +0 -267
- /package/dist/{auto-update-CUeF99gI.js → auto-update-CpF0fycd.js} +0 -0
- /package/dist/{auto-update-cgkp9ZTJ.js → auto-update-DNWdO7uF.js} +0 -0
- /package/dist/{brew-CVZkr0GU.js → brew-nqf_MiE4.js} +0 -0
- /package/dist/{budget-DxYQSekw.js → budget-CPedI-qW.js} +0 -0
- /package/dist/{budget-BWBp8Res.js → budget-CRpvqDRX.js} +0 -0
- /package/dist/{cli-utils-DtAxdCte.js → cli-utils-C1YHVD4o.js} +0 -0
- /package/dist/{command-options-CSbuuqHr.js → command-options-BbponVnw.js} +0 -0
- /package/dist/{command-options-Cp1tf96a.js → command-options-s0gnvXnS.js} +0 -0
- /package/dist/{constants-O8yBqCBv.js → constants-Dhb6zSIV.js} +0 -0
- /package/dist/{dangerous-tools-5ObDWy1N.js → dangerous-tools-DGTtJ_JR.js} +0 -0
- /package/dist/{dangerous-tools-Jwr7jqNw.js → dangerous-tools-DxrfTOfT.js} +0 -0
- /package/dist/{delivery-queue-B6IHz4Ry.js → delivery-queue-Bxm0nzw7.js} +0 -0
- /package/dist/{display-BDOsXu8F.js → display-Jy3UdGzA.js} +0 -0
- /package/dist/{errors-CHow2wtt.js → errors-CKaCqKga.js} +0 -0
- /package/dist/{exec-BizYYQgP.js → exec-DDmuVVNq.js} +0 -0
- /package/dist/{format-Mq6iU0_5.js → format-ByEjgyTF.js} +0 -0
- /package/dist/{format-duration-DhWzz_5b.js → format-duration-Aaj5tjJd.js} +0 -0
- /package/dist/{format-relative-C6kUHuOj.js → format-relative-79_Y1n2Y.js} +0 -0
- /package/dist/{help-format-DUBI91Ti.js → help-format-BMKzarov.js} +0 -0
- /package/dist/{helpers-eJFa4K6r.js → helpers-DpEB9Mh0.js} +0 -0
- /package/dist/{helpers-DLgbkcEn.js → helpers-FMld9sBT.js} +0 -0
- /package/dist/{input-provenance-DJBdpeKk.js → input-provenance-Cy_KnBlP.js} +0 -0
- /package/dist/{is-main-Dt9DTcH1.js → is-main-yjaVwMtJ.js} +0 -0
- /package/dist/{loader-l2OBdJ8x.js → loader-Br7Vr0zn.js} +0 -0
- /package/dist/{loader-BoYxRfcW.js → loader-CkmOrXcC.js} +0 -0
- /package/dist/{logging-BdnOSVPD.js → logging-CY-Q5cwf.js} +0 -0
- /package/dist/{message-channel-w4F2b2F6.js → message-channel-dua8OOGJ.js} +0 -0
- /package/dist/{mime-B1ZoR53M.js → mime-CBg4KybI.js} +0 -0
- /package/dist/{model-param-b-DPwyNGn8.js → model-param-b-DW9f0NN8.js} +0 -0
- /package/dist/{node-match-8XZnaid6.js → node-match-BV8bTBd4.js} +0 -0
- /package/dist/{normalize-GDK8JTNW.js → normalize-_lmlBOW9.js} +0 -0
- /package/dist/{openclaw-root-C85WMnVV.js → openclaw-root-JPvmPTf7.js} +0 -0
- /package/dist/{outbound-send-deps-ANnAhImn.js → outbound-send-deps-BfUvuWGa.js} +0 -0
- /package/dist/{parse-6-2MDhdT.js → parse-CZRwKocn.js} +0 -0
- /package/dist/{parse-log-line-Bqh1SSzC.js → parse-log-line-CvrZEK6A.js} +0 -0
- /package/dist/{parse-log-line-DUZCjXbl.js → parse-log-line-mLdat0AH.js} +0 -0
- /package/dist/{parse-port-BKB9Exlg.js → parse-port-BSOOdo7I.js} +0 -0
- /package/dist/{parse-port-DrfvwwiL.js → parse-port-Y0NK62x1.js} +0 -0
- /package/dist/{parse-timeout-Di_tcEmi.js → parse-timeout-DVPQ3n9j.js} +0 -0
- /package/dist/{paths-DcVEkYX5.js → paths-DHjlJ6cn.js} +0 -0
- /package/dist/{pi-model-discovery-DsRqYJLy.js → pi-model-discovery-DzEIEgHL.js} +0 -0
- /package/dist/{plugins-CDJw924T.js → plugins-D6PBOdkn.js} +0 -0
- /package/dist/{program-context-Bvn8046-.js → program-context-Q1hkT73c.js} +0 -0
- /package/dist/{progress-CbZ2D53A.js → progress-C9Ha1NJh.js} +0 -0
- /package/dist/{prompt-style-DKy6qQxR.js → prompt-style-DQi8j03a.js} +0 -0
- /package/dist/{prompts-BI__va99.js → prompts-BEHxUC3w.js} +0 -0
- /package/dist/{prompts-_dDWkCAz.js → prompts-CSOhuiqe.js} +0 -0
- /package/dist/{queue-D_u34pbL.js → queue-BJGo7kAB.js} +0 -0
- /package/dist/{queue-PG591iID.js → queue-DYgUbdoq.js} +0 -0
- /package/dist/{redact-ClVwO7Nn.js → redact-CyKvdFrg.js} +0 -0
- /package/dist/{registry-Bs_DJK9E.js → registry-C5MAYD4V.js} +0 -0
- /package/dist/{registry-D_zlP1U-.js → registry-CRrXXVs0.js} +0 -0
- /package/dist/{requirements-BzZxj2Wu.js → requirements-CGkxTCu4.js} +0 -0
- /package/dist/{requirements-DIW1svgA.js → requirements-CIDaOcbO.js} +0 -0
- /package/dist/{runtime-guard-DeOXA_86.js → runtime-guard-nL3Lp8T-.js} +0 -0
- /package/dist/{secret-equal-Dghy3xsA.js → secret-equal-DJpmLXlG.js} +0 -0
- /package/dist/{send-BhAfdGII.js → send-CTcxgDDU.js} +0 -0
- /package/dist/{send-ga9udK1_.js → send-DPezUR3-.js} +0 -0
- /package/dist/{send-C2t9xpXI.js → send-DZQTaG7-.js} +0 -0
- /package/dist/{send-DigO-i9j.js → send-VDff2gra.js} +0 -0
- /package/dist/{send-Dz2BDHll.js → send-bgQNV8d1.js} +0 -0
- /package/dist/{session-key-BGiG_JcT.js → session-key-CQT-NR6w.js} +0 -0
- /package/dist/{shell-argv-CAq1mLa2.js → shell-argv-n9IueeJQ.js} +0 -0
- /package/dist/{skill-scanner-Coo4QoCd.js → skill-scanner-o6NgVMD9.js} +0 -0
- /package/dist/{status-CMnlcBVc.js → status-C53kTIXF.js} +0 -0
- /package/dist/{status-tDZPwewW.js → status-CZDDA_Sy.js} +0 -0
- /package/dist/{system-run-command-X9lDJIy0.js → system-run-command-BCjUffN9.js} +0 -0
- /package/dist/{system-run-command-DGk7dwQP.js → system-run-command-CqAqKL9K.js} +0 -0
- /package/dist/{tailnet-CuiNECdL.js → tailnet-Ciwjv243.js} +0 -0
- /package/dist/{templates-CeYJjVzw.js → templates-37RKpACb.js} +0 -0
- /package/dist/{templates-I3Z0xplD.js → templates-DPalk30o.js} +0 -0
- /package/dist/{thinking-BXEswx1X.js → thinking-2hxwmvTl.js} +0 -0
- /package/dist/{transcript-events-C1hdue6u.js → transcript-events-Bp7fGnwv.js} +0 -0
- /package/dist/{transcript-tools-DuyYOkUq.js → transcript-tools-D4Lbxlka.js} +0 -0
- /package/dist/{usage-format-BAirWUSO.js → usage-format-6Uar63S0.js} +0 -0
- /package/dist/{utils-C9sj30YY.js → utils-DT8uXjFS.js} +0 -0
- /package/dist/{wsl-CqyuRvtM.js → wsl-CrPvx2kZ.js} +0 -0
- /package/dist/{wsl-ymJYvc9Q.js → wsl-UvJ5dHah.js} +0 -0
package/dist/ipv4-Bf7NS3QU.js
DELETED
|
@@ -1,1964 +0,0 @@
|
|
|
1
|
-
import { Dt as DEFAULT_PROVIDER, E as buildModelAliasIndex, Et as DEFAULT_MODEL, F as resolveConfiguredModelRef, d as listProfilesForProvider, h as ensureAuthProfileStore, j as normalizeProviderId, k as modelKey, rt as getCustomProviderApiKey, st as resolveEnvApiKey, ut as normalizeSecretInput, w as buildAllowedModelSet } from "./auth-profiles-DxI8L7bs.js";
|
|
2
|
-
import { t as formatCliCommand } from "./command-format-Clp46jkj.js";
|
|
3
|
-
import { s as ensureDir, t as CONFIG_DIR, y as resolveUserPath } from "./utils-C9sj30YY.js";
|
|
4
|
-
import { t as runCommandWithTimeout } from "./exec-BizYYQgP.js";
|
|
5
|
-
import { h as resolveSkillKey, i as loadWorkspaceSkillEntries, t as resolveSkillsInstallPreferences, x as hasBinary } from "./skills-B5LQx4lT.js";
|
|
6
|
-
import { t as buildWorkspaceSkillStatus } from "./skills-status-JQluhU-P.js";
|
|
7
|
-
import { c as fetchWithTimeout, o as fetchWithSsrFGuard } from "./media-THyainiE.js";
|
|
8
|
-
import { Yt as loadModelCatalog } from "./cli-session-Dd8DKb5a.js";
|
|
9
|
-
import { t as resolveBrewExecutable } from "./brew-CVZkr0GU.js";
|
|
10
|
-
import { o as extractArchive$1 } from "./npm-registry-spec-za3itb5Y.js";
|
|
11
|
-
import { t as scanDirectoryWithSummary } from "./skill-scanner-CkaVLABv.js";
|
|
12
|
-
import { g as resolveNodeManagerOptions, r as detectBinary } from "./onboard-helpers-DO_hgZb9.js";
|
|
13
|
-
import { n as resolveWideAreaDiscoveryDomain } from "./widearea-dns-NsEUNYwz.js";
|
|
14
|
-
import { i as promptAndConfigureVllm, o as OPENAI_CODEX_DEFAULT_MODEL } from "./auth-choice-p3SeHPj2.js";
|
|
15
|
-
import { a as normalizeAlias, r as formatTokenK } from "./shared-f7dvQsi7.js";
|
|
16
|
-
import path from "node:path";
|
|
17
|
-
import fs from "node:fs";
|
|
18
|
-
import { pipeline } from "node:stream/promises";
|
|
19
|
-
import { Readable } from "node:stream";
|
|
20
|
-
|
|
21
|
-
//#region src/infra/bonjour-discovery.ts
|
|
22
|
-
const DEFAULT_TIMEOUT_MS = 2e3;
|
|
23
|
-
const GATEWAY_SERVICE_TYPE = "_anima-gw._tcp";
|
|
24
|
-
function decodeDnsSdEscapes(value) {
|
|
25
|
-
let decoded = false;
|
|
26
|
-
const bytes = [];
|
|
27
|
-
let pending = "";
|
|
28
|
-
const flush = () => {
|
|
29
|
-
if (!pending) return;
|
|
30
|
-
bytes.push(...Buffer.from(pending, "utf8"));
|
|
31
|
-
pending = "";
|
|
32
|
-
};
|
|
33
|
-
for (let i = 0; i < value.length; i += 1) {
|
|
34
|
-
const ch = value[i] ?? "";
|
|
35
|
-
if (ch === "\\" && i + 3 < value.length) {
|
|
36
|
-
const escaped = value.slice(i + 1, i + 4);
|
|
37
|
-
if (/^[0-9]{3}$/.test(escaped)) {
|
|
38
|
-
const byte = Number.parseInt(escaped, 10);
|
|
39
|
-
if (!Number.isFinite(byte) || byte < 0 || byte > 255) {
|
|
40
|
-
pending += ch;
|
|
41
|
-
continue;
|
|
42
|
-
}
|
|
43
|
-
flush();
|
|
44
|
-
bytes.push(byte);
|
|
45
|
-
decoded = true;
|
|
46
|
-
i += 3;
|
|
47
|
-
continue;
|
|
48
|
-
}
|
|
49
|
-
}
|
|
50
|
-
pending += ch;
|
|
51
|
-
}
|
|
52
|
-
if (!decoded) return value;
|
|
53
|
-
flush();
|
|
54
|
-
return Buffer.from(bytes).toString("utf8");
|
|
55
|
-
}
|
|
56
|
-
function isTailnetIPv4(address) {
|
|
57
|
-
const parts = address.split(".");
|
|
58
|
-
if (parts.length !== 4) return false;
|
|
59
|
-
const octets = parts.map((p) => Number.parseInt(p, 10));
|
|
60
|
-
if (octets.some((n) => !Number.isFinite(n) || n < 0 || n > 255)) return false;
|
|
61
|
-
const [a, b] = octets;
|
|
62
|
-
return a === 100 && b >= 64 && b <= 127;
|
|
63
|
-
}
|
|
64
|
-
function parseDigShortLines(stdout) {
|
|
65
|
-
return stdout.split("\n").map((l) => l.trim()).filter(Boolean);
|
|
66
|
-
}
|
|
67
|
-
function parseDigTxt(stdout) {
|
|
68
|
-
const tokens = [];
|
|
69
|
-
for (const raw of stdout.split("\n")) {
|
|
70
|
-
const line = raw.trim();
|
|
71
|
-
if (!line) continue;
|
|
72
|
-
const matches = Array.from(line.matchAll(/"([^"]*)"/g), (m) => m[1] ?? "");
|
|
73
|
-
for (const m of matches) {
|
|
74
|
-
const unescaped = m.replaceAll("\\\\", "\\").replaceAll("\\\"", "\"").replaceAll("\\n", "\n");
|
|
75
|
-
tokens.push(unescaped);
|
|
76
|
-
}
|
|
77
|
-
}
|
|
78
|
-
return tokens;
|
|
79
|
-
}
|
|
80
|
-
function parseDigSrv(stdout) {
|
|
81
|
-
const line = stdout.split("\n").map((l) => l.trim()).find(Boolean);
|
|
82
|
-
if (!line) return null;
|
|
83
|
-
const parts = line.split(/\s+/).filter(Boolean);
|
|
84
|
-
if (parts.length < 4) return null;
|
|
85
|
-
const port = Number.parseInt(parts[2] ?? "", 10);
|
|
86
|
-
const hostRaw = parts[3] ?? "";
|
|
87
|
-
if (!Number.isFinite(port) || port <= 0) return null;
|
|
88
|
-
const host = hostRaw.replace(/\.$/, "");
|
|
89
|
-
if (!host) return null;
|
|
90
|
-
return {
|
|
91
|
-
host,
|
|
92
|
-
port
|
|
93
|
-
};
|
|
94
|
-
}
|
|
95
|
-
function parseTailscaleStatusIPv4s(stdout) {
|
|
96
|
-
const parsed = stdout ? JSON.parse(stdout) : {};
|
|
97
|
-
const out = [];
|
|
98
|
-
const addIps = (value) => {
|
|
99
|
-
if (!value || typeof value !== "object") return;
|
|
100
|
-
const ips = value.TailscaleIPs;
|
|
101
|
-
if (!Array.isArray(ips)) return;
|
|
102
|
-
for (const ip of ips) {
|
|
103
|
-
if (typeof ip !== "string") continue;
|
|
104
|
-
const trimmed = ip.trim();
|
|
105
|
-
if (trimmed && isTailnetIPv4(trimmed)) out.push(trimmed);
|
|
106
|
-
}
|
|
107
|
-
};
|
|
108
|
-
addIps(parsed.Self);
|
|
109
|
-
const peerObj = parsed.Peer;
|
|
110
|
-
if (peerObj && typeof peerObj === "object") for (const peer of Object.values(peerObj)) addIps(peer);
|
|
111
|
-
return [...new Set(out)];
|
|
112
|
-
}
|
|
113
|
-
function parseIntOrNull(value) {
|
|
114
|
-
if (!value) return;
|
|
115
|
-
const parsed = Number.parseInt(value, 10);
|
|
116
|
-
return Number.isFinite(parsed) ? parsed : void 0;
|
|
117
|
-
}
|
|
118
|
-
function parseTxtTokens(tokens) {
|
|
119
|
-
const txt = {};
|
|
120
|
-
for (const token of tokens) {
|
|
121
|
-
const idx = token.indexOf("=");
|
|
122
|
-
if (idx <= 0) continue;
|
|
123
|
-
const key = token.slice(0, idx).trim();
|
|
124
|
-
const value = decodeDnsSdEscapes(token.slice(idx + 1).trim());
|
|
125
|
-
if (!key) continue;
|
|
126
|
-
txt[key] = value;
|
|
127
|
-
}
|
|
128
|
-
return txt;
|
|
129
|
-
}
|
|
130
|
-
function parseDnsSdBrowse(stdout) {
|
|
131
|
-
const instances = /* @__PURE__ */ new Set();
|
|
132
|
-
for (const raw of stdout.split("\n")) {
|
|
133
|
-
const line = raw.trim();
|
|
134
|
-
if (!line || !line.includes(GATEWAY_SERVICE_TYPE)) continue;
|
|
135
|
-
if (!line.includes("Add")) continue;
|
|
136
|
-
const match = line.match(/_anima-gw\._tcp\.?\s+(.+)$/);
|
|
137
|
-
if (match?.[1]) instances.add(decodeDnsSdEscapes(match[1].trim()));
|
|
138
|
-
}
|
|
139
|
-
return Array.from(instances.values());
|
|
140
|
-
}
|
|
141
|
-
function parseDnsSdResolve(stdout, instanceName) {
|
|
142
|
-
const decodedInstanceName = decodeDnsSdEscapes(instanceName);
|
|
143
|
-
const beacon = { instanceName: decodedInstanceName };
|
|
144
|
-
let txt = {};
|
|
145
|
-
for (const raw of stdout.split("\n")) {
|
|
146
|
-
const line = raw.trim();
|
|
147
|
-
if (!line) continue;
|
|
148
|
-
if (line.includes("can be reached at")) {
|
|
149
|
-
const match = line.match(/can be reached at\s+([^\s:]+):(\d+)/i);
|
|
150
|
-
if (match?.[1]) beacon.host = match[1].replace(/\.$/, "");
|
|
151
|
-
if (match?.[2]) beacon.port = parseIntOrNull(match[2]);
|
|
152
|
-
continue;
|
|
153
|
-
}
|
|
154
|
-
if (line.startsWith("txt") || line.includes("txtvers=")) txt = parseTxtTokens(line.split(/\s+/).filter(Boolean));
|
|
155
|
-
}
|
|
156
|
-
beacon.txt = Object.keys(txt).length ? txt : void 0;
|
|
157
|
-
if (txt.displayName) beacon.displayName = decodeDnsSdEscapes(txt.displayName);
|
|
158
|
-
if (txt.lanHost) beacon.lanHost = txt.lanHost;
|
|
159
|
-
if (txt.tailnetDns) beacon.tailnetDns = txt.tailnetDns;
|
|
160
|
-
if (txt.cliPath) beacon.cliPath = txt.cliPath;
|
|
161
|
-
beacon.gatewayPort = parseIntOrNull(txt.gatewayPort);
|
|
162
|
-
beacon.sshPort = parseIntOrNull(txt.sshPort);
|
|
163
|
-
if (txt.gatewayTls) {
|
|
164
|
-
const raw = txt.gatewayTls.trim().toLowerCase();
|
|
165
|
-
beacon.gatewayTls = raw === "1" || raw === "true" || raw === "yes";
|
|
166
|
-
}
|
|
167
|
-
if (txt.gatewayTlsSha256) beacon.gatewayTlsFingerprintSha256 = txt.gatewayTlsSha256;
|
|
168
|
-
if (txt.role) beacon.role = txt.role;
|
|
169
|
-
if (txt.transport) beacon.transport = txt.transport;
|
|
170
|
-
if (!beacon.displayName) beacon.displayName = decodedInstanceName;
|
|
171
|
-
return beacon;
|
|
172
|
-
}
|
|
173
|
-
async function discoverViaDnsSd(domain, timeoutMs, run) {
|
|
174
|
-
const instances = parseDnsSdBrowse((await run([
|
|
175
|
-
"dns-sd",
|
|
176
|
-
"-B",
|
|
177
|
-
GATEWAY_SERVICE_TYPE,
|
|
178
|
-
domain
|
|
179
|
-
], { timeoutMs })).stdout);
|
|
180
|
-
const results = [];
|
|
181
|
-
for (const instance of instances) {
|
|
182
|
-
const parsed = parseDnsSdResolve((await run([
|
|
183
|
-
"dns-sd",
|
|
184
|
-
"-L",
|
|
185
|
-
instance,
|
|
186
|
-
GATEWAY_SERVICE_TYPE,
|
|
187
|
-
domain
|
|
188
|
-
], { timeoutMs })).stdout, instance);
|
|
189
|
-
if (parsed) results.push({
|
|
190
|
-
...parsed,
|
|
191
|
-
domain
|
|
192
|
-
});
|
|
193
|
-
}
|
|
194
|
-
return results;
|
|
195
|
-
}
|
|
196
|
-
async function discoverWideAreaViaTailnetDns(domain, timeoutMs, run) {
|
|
197
|
-
if (!domain || domain === "local.") return [];
|
|
198
|
-
const startedAt = Date.now();
|
|
199
|
-
const remainingMs = () => timeoutMs - (Date.now() - startedAt);
|
|
200
|
-
const tailscaleCandidates = ["tailscale", "/Applications/Tailscale.app/Contents/MacOS/Tailscale"];
|
|
201
|
-
let ips = [];
|
|
202
|
-
for (const candidate of tailscaleCandidates) try {
|
|
203
|
-
ips = parseTailscaleStatusIPv4s((await run([
|
|
204
|
-
candidate,
|
|
205
|
-
"status",
|
|
206
|
-
"--json"
|
|
207
|
-
], { timeoutMs: Math.max(1, Math.min(700, remainingMs())) })).stdout);
|
|
208
|
-
if (ips.length > 0) break;
|
|
209
|
-
} catch {}
|
|
210
|
-
if (ips.length === 0) return [];
|
|
211
|
-
if (remainingMs() <= 0) return [];
|
|
212
|
-
ips = ips.slice(0, 40);
|
|
213
|
-
const probeName = `${GATEWAY_SERVICE_TYPE}.${domain.replace(/\.$/, "")}`;
|
|
214
|
-
const concurrency = 6;
|
|
215
|
-
let nextIndex = 0;
|
|
216
|
-
let nameserver = null;
|
|
217
|
-
let ptrs = [];
|
|
218
|
-
const worker = async () => {
|
|
219
|
-
while (nameserver === null) {
|
|
220
|
-
const budget = remainingMs();
|
|
221
|
-
if (budget <= 0) return;
|
|
222
|
-
const i = nextIndex;
|
|
223
|
-
nextIndex += 1;
|
|
224
|
-
if (i >= ips.length) return;
|
|
225
|
-
const ip = ips[i] ?? "";
|
|
226
|
-
if (!ip) continue;
|
|
227
|
-
try {
|
|
228
|
-
const lines = parseDigShortLines((await run([
|
|
229
|
-
"dig",
|
|
230
|
-
"+short",
|
|
231
|
-
"+time=1",
|
|
232
|
-
"+tries=1",
|
|
233
|
-
`@${ip}`,
|
|
234
|
-
probeName,
|
|
235
|
-
"PTR"
|
|
236
|
-
], { timeoutMs: Math.max(1, Math.min(250, budget)) })).stdout);
|
|
237
|
-
if (lines.length === 0) continue;
|
|
238
|
-
nameserver = ip;
|
|
239
|
-
ptrs = lines;
|
|
240
|
-
return;
|
|
241
|
-
} catch {}
|
|
242
|
-
}
|
|
243
|
-
};
|
|
244
|
-
await Promise.all(Array.from({ length: Math.min(concurrency, ips.length) }, () => worker()));
|
|
245
|
-
if (!nameserver || ptrs.length === 0) return [];
|
|
246
|
-
if (remainingMs() <= 0) return [];
|
|
247
|
-
const nameserverArg = `@${String(nameserver)}`;
|
|
248
|
-
const results = [];
|
|
249
|
-
for (const ptr of ptrs) {
|
|
250
|
-
const budget = remainingMs();
|
|
251
|
-
if (budget <= 0) break;
|
|
252
|
-
const ptrName = ptr.trim().replace(/\.$/, "");
|
|
253
|
-
if (!ptrName) continue;
|
|
254
|
-
const instanceName = ptrName.replace(/\.?_anima-gw\._tcp\..*$/, "");
|
|
255
|
-
const srv = await run([
|
|
256
|
-
"dig",
|
|
257
|
-
"+short",
|
|
258
|
-
"+time=1",
|
|
259
|
-
"+tries=1",
|
|
260
|
-
nameserverArg,
|
|
261
|
-
ptrName,
|
|
262
|
-
"SRV"
|
|
263
|
-
], { timeoutMs: Math.max(1, Math.min(350, budget)) }).catch(() => null);
|
|
264
|
-
const srvParsed = srv ? parseDigSrv(srv.stdout) : null;
|
|
265
|
-
if (!srvParsed) continue;
|
|
266
|
-
const txtBudget = remainingMs();
|
|
267
|
-
if (txtBudget <= 0) {
|
|
268
|
-
results.push({
|
|
269
|
-
instanceName: instanceName || ptrName,
|
|
270
|
-
displayName: instanceName || ptrName,
|
|
271
|
-
domain,
|
|
272
|
-
host: srvParsed.host,
|
|
273
|
-
port: srvParsed.port
|
|
274
|
-
});
|
|
275
|
-
continue;
|
|
276
|
-
}
|
|
277
|
-
const txt = await run([
|
|
278
|
-
"dig",
|
|
279
|
-
"+short",
|
|
280
|
-
"+time=1",
|
|
281
|
-
"+tries=1",
|
|
282
|
-
nameserverArg,
|
|
283
|
-
ptrName,
|
|
284
|
-
"TXT"
|
|
285
|
-
], { timeoutMs: Math.max(1, Math.min(350, txtBudget)) }).catch(() => null);
|
|
286
|
-
const txtTokens = txt ? parseDigTxt(txt.stdout) : [];
|
|
287
|
-
const txtMap = txtTokens.length > 0 ? parseTxtTokens(txtTokens) : {};
|
|
288
|
-
const beacon = {
|
|
289
|
-
instanceName: instanceName || ptrName,
|
|
290
|
-
displayName: txtMap.displayName || instanceName || ptrName,
|
|
291
|
-
domain,
|
|
292
|
-
host: srvParsed.host,
|
|
293
|
-
port: srvParsed.port,
|
|
294
|
-
txt: Object.keys(txtMap).length ? txtMap : void 0,
|
|
295
|
-
gatewayPort: parseIntOrNull(txtMap.gatewayPort),
|
|
296
|
-
sshPort: parseIntOrNull(txtMap.sshPort),
|
|
297
|
-
tailnetDns: txtMap.tailnetDns || void 0,
|
|
298
|
-
cliPath: txtMap.cliPath || void 0
|
|
299
|
-
};
|
|
300
|
-
if (txtMap.gatewayTls) {
|
|
301
|
-
const raw = txtMap.gatewayTls.trim().toLowerCase();
|
|
302
|
-
beacon.gatewayTls = raw === "1" || raw === "true" || raw === "yes";
|
|
303
|
-
}
|
|
304
|
-
if (txtMap.gatewayTlsSha256) beacon.gatewayTlsFingerprintSha256 = txtMap.gatewayTlsSha256;
|
|
305
|
-
if (txtMap.role) beacon.role = txtMap.role;
|
|
306
|
-
if (txtMap.transport) beacon.transport = txtMap.transport;
|
|
307
|
-
results.push(beacon);
|
|
308
|
-
}
|
|
309
|
-
return results;
|
|
310
|
-
}
|
|
311
|
-
function parseAvahiBrowse(stdout) {
|
|
312
|
-
const results = [];
|
|
313
|
-
let current = null;
|
|
314
|
-
for (const raw of stdout.split("\n")) {
|
|
315
|
-
const line = raw.trimEnd();
|
|
316
|
-
if (!line) continue;
|
|
317
|
-
if (line.startsWith("=") && line.includes(GATEWAY_SERVICE_TYPE)) {
|
|
318
|
-
if (current) results.push(current);
|
|
319
|
-
const marker = ` ${GATEWAY_SERVICE_TYPE}`;
|
|
320
|
-
const idx = line.indexOf(marker);
|
|
321
|
-
const left = idx >= 0 ? line.slice(0, idx).trim() : line;
|
|
322
|
-
const parts = left.split(/\s+/);
|
|
323
|
-
const instanceName = parts.length > 3 ? parts.slice(3).join(" ") : left;
|
|
324
|
-
current = {
|
|
325
|
-
instanceName,
|
|
326
|
-
displayName: instanceName
|
|
327
|
-
};
|
|
328
|
-
continue;
|
|
329
|
-
}
|
|
330
|
-
if (!current) continue;
|
|
331
|
-
const trimmed = line.trim();
|
|
332
|
-
if (trimmed.startsWith("hostname =")) {
|
|
333
|
-
const match = trimmed.match(/hostname\s*=\s*\[([^\]]+)\]/);
|
|
334
|
-
if (match?.[1]) current.host = match[1];
|
|
335
|
-
continue;
|
|
336
|
-
}
|
|
337
|
-
if (trimmed.startsWith("port =")) {
|
|
338
|
-
const match = trimmed.match(/port\s*=\s*\[(\d+)\]/);
|
|
339
|
-
if (match?.[1]) current.port = parseIntOrNull(match[1]);
|
|
340
|
-
continue;
|
|
341
|
-
}
|
|
342
|
-
if (trimmed.startsWith("txt =")) {
|
|
343
|
-
const txt = parseTxtTokens(Array.from(trimmed.matchAll(/"([^"]*)"/g), (m) => m[1]));
|
|
344
|
-
current.txt = Object.keys(txt).length ? txt : void 0;
|
|
345
|
-
if (txt.displayName) current.displayName = txt.displayName;
|
|
346
|
-
if (txt.lanHost) current.lanHost = txt.lanHost;
|
|
347
|
-
if (txt.tailnetDns) current.tailnetDns = txt.tailnetDns;
|
|
348
|
-
if (txt.cliPath) current.cliPath = txt.cliPath;
|
|
349
|
-
current.gatewayPort = parseIntOrNull(txt.gatewayPort);
|
|
350
|
-
current.sshPort = parseIntOrNull(txt.sshPort);
|
|
351
|
-
if (txt.gatewayTls) {
|
|
352
|
-
const raw = txt.gatewayTls.trim().toLowerCase();
|
|
353
|
-
current.gatewayTls = raw === "1" || raw === "true" || raw === "yes";
|
|
354
|
-
}
|
|
355
|
-
if (txt.gatewayTlsSha256) current.gatewayTlsFingerprintSha256 = txt.gatewayTlsSha256;
|
|
356
|
-
if (txt.role) current.role = txt.role;
|
|
357
|
-
if (txt.transport) current.transport = txt.transport;
|
|
358
|
-
}
|
|
359
|
-
}
|
|
360
|
-
if (current) results.push(current);
|
|
361
|
-
return results;
|
|
362
|
-
}
|
|
363
|
-
async function discoverViaAvahi(domain, timeoutMs, run) {
|
|
364
|
-
const args = [
|
|
365
|
-
"avahi-browse",
|
|
366
|
-
"-rt",
|
|
367
|
-
GATEWAY_SERVICE_TYPE
|
|
368
|
-
];
|
|
369
|
-
if (domain && domain !== "local.") args.push("-d", domain.replace(/\.$/, ""));
|
|
370
|
-
return parseAvahiBrowse((await run(args, { timeoutMs })).stdout).map((beacon) => ({
|
|
371
|
-
...beacon,
|
|
372
|
-
domain
|
|
373
|
-
}));
|
|
374
|
-
}
|
|
375
|
-
async function discoverGatewayBeacons(opts = {}) {
|
|
376
|
-
const timeoutMs = opts.timeoutMs ?? DEFAULT_TIMEOUT_MS;
|
|
377
|
-
const platform = opts.platform ?? process.platform;
|
|
378
|
-
const run = opts.run ?? runCommandWithTimeout;
|
|
379
|
-
const wideAreaDomain = resolveWideAreaDiscoveryDomain({ configDomain: opts.wideAreaDomain });
|
|
380
|
-
const domainsRaw = Array.isArray(opts.domains) ? opts.domains : [];
|
|
381
|
-
const defaultDomains = ["local.", ...wideAreaDomain ? [wideAreaDomain] : []];
|
|
382
|
-
const domains = (domainsRaw.length > 0 ? domainsRaw : defaultDomains).map((d) => String(d).trim()).filter(Boolean).map((d) => d.endsWith(".") ? d : `${d}.`);
|
|
383
|
-
try {
|
|
384
|
-
if (platform === "darwin") {
|
|
385
|
-
const discovered = (await Promise.allSettled(domains.map(async (domain) => await discoverViaDnsSd(domain, timeoutMs, run)))).flatMap((r) => r.status === "fulfilled" ? r.value : []);
|
|
386
|
-
const wantsWideArea = wideAreaDomain ? domains.includes(wideAreaDomain) : false;
|
|
387
|
-
const hasWideArea = wideAreaDomain ? discovered.some((b) => b.domain === wideAreaDomain) : false;
|
|
388
|
-
if (wantsWideArea && !hasWideArea && wideAreaDomain) {
|
|
389
|
-
const fallback = await discoverWideAreaViaTailnetDns(wideAreaDomain, timeoutMs, run).catch(() => []);
|
|
390
|
-
return [...discovered, ...fallback];
|
|
391
|
-
}
|
|
392
|
-
return discovered;
|
|
393
|
-
}
|
|
394
|
-
if (platform === "linux") return (await Promise.allSettled(domains.map(async (domain) => await discoverViaAvahi(domain, timeoutMs, run)))).flatMap((r) => r.status === "fulfilled" ? r.value : []);
|
|
395
|
-
} catch {
|
|
396
|
-
return [];
|
|
397
|
-
}
|
|
398
|
-
return [];
|
|
399
|
-
}
|
|
400
|
-
|
|
401
|
-
//#endregion
|
|
402
|
-
//#region src/commands/model-picker.ts
|
|
403
|
-
const KEEP_VALUE = "__keep__";
|
|
404
|
-
const MANUAL_VALUE = "__manual__";
|
|
405
|
-
const VLLM_VALUE = "__vllm__";
|
|
406
|
-
const PROVIDER_FILTER_THRESHOLD = 30;
|
|
407
|
-
const HIDDEN_ROUTER_MODELS = new Set(["openrouter/auto"]);
|
|
408
|
-
function hasAuthForProvider(provider, cfg, store) {
|
|
409
|
-
if (listProfilesForProvider(store, provider).length > 0) return true;
|
|
410
|
-
if (resolveEnvApiKey(provider)) return true;
|
|
411
|
-
if (getCustomProviderApiKey(cfg, provider)) return true;
|
|
412
|
-
return false;
|
|
413
|
-
}
|
|
414
|
-
function resolveConfiguredModelRaw(cfg) {
|
|
415
|
-
const raw = cfg.agents?.defaults?.model;
|
|
416
|
-
if (typeof raw === "string") return raw.trim();
|
|
417
|
-
return raw?.primary?.trim() ?? "";
|
|
418
|
-
}
|
|
419
|
-
function resolveConfiguredModelKeys(cfg) {
|
|
420
|
-
const models = cfg.agents?.defaults?.models ?? {};
|
|
421
|
-
return Object.keys(models).map((key) => String(key ?? "").trim()).filter((key) => key.length > 0);
|
|
422
|
-
}
|
|
423
|
-
function normalizeModelKeys(values) {
|
|
424
|
-
const seen = /* @__PURE__ */ new Set();
|
|
425
|
-
const next = [];
|
|
426
|
-
for (const raw of values) {
|
|
427
|
-
const value = String(raw ?? "").trim();
|
|
428
|
-
if (!value || seen.has(value)) continue;
|
|
429
|
-
seen.add(value);
|
|
430
|
-
next.push(value);
|
|
431
|
-
}
|
|
432
|
-
return next;
|
|
433
|
-
}
|
|
434
|
-
function addModelSelectOption(params) {
|
|
435
|
-
const key = modelKey(params.entry.provider, params.entry.id);
|
|
436
|
-
if (params.seen.has(key)) return;
|
|
437
|
-
if (HIDDEN_ROUTER_MODELS.has(key)) return;
|
|
438
|
-
const hints = [];
|
|
439
|
-
if (params.entry.name && params.entry.name !== params.entry.id) hints.push(params.entry.name);
|
|
440
|
-
if (params.entry.contextWindow) hints.push(`ctx ${formatTokenK(params.entry.contextWindow)}`);
|
|
441
|
-
if (params.entry.reasoning) hints.push("reasoning");
|
|
442
|
-
const aliases = params.aliasIndex.byKey.get(key);
|
|
443
|
-
if (aliases?.length) hints.push(`alias: ${aliases.join(", ")}`);
|
|
444
|
-
if (!params.hasAuth(params.entry.provider)) hints.push("auth missing");
|
|
445
|
-
params.options.push({
|
|
446
|
-
value: key,
|
|
447
|
-
label: key,
|
|
448
|
-
hint: hints.length > 0 ? hints.join(" · ") : void 0
|
|
449
|
-
});
|
|
450
|
-
params.seen.add(key);
|
|
451
|
-
}
|
|
452
|
-
async function promptManualModel(params) {
|
|
453
|
-
const modelInput = await params.prompter.text({
|
|
454
|
-
message: params.allowBlank ? "Default model (blank to keep)" : "Default model",
|
|
455
|
-
initialValue: params.initialValue,
|
|
456
|
-
placeholder: "provider/model",
|
|
457
|
-
validate: params.allowBlank ? void 0 : (value) => value?.trim() ? void 0 : "Required"
|
|
458
|
-
});
|
|
459
|
-
const model = String(modelInput ?? "").trim();
|
|
460
|
-
if (!model) return {};
|
|
461
|
-
return { model };
|
|
462
|
-
}
|
|
463
|
-
async function promptDefaultModel(params) {
|
|
464
|
-
const cfg = params.config;
|
|
465
|
-
const allowKeep = params.allowKeep ?? true;
|
|
466
|
-
const includeManual = params.includeManual ?? true;
|
|
467
|
-
const includeVllm = params.includeVllm ?? false;
|
|
468
|
-
const ignoreAllowlist = params.ignoreAllowlist ?? false;
|
|
469
|
-
const preferredProviderRaw = params.preferredProvider?.trim();
|
|
470
|
-
const preferredProvider = preferredProviderRaw ? normalizeProviderId(preferredProviderRaw) : void 0;
|
|
471
|
-
const configuredRaw = resolveConfiguredModelRaw(cfg);
|
|
472
|
-
const resolved = resolveConfiguredModelRef({
|
|
473
|
-
cfg,
|
|
474
|
-
defaultProvider: DEFAULT_PROVIDER,
|
|
475
|
-
defaultModel: DEFAULT_MODEL
|
|
476
|
-
});
|
|
477
|
-
const resolvedKey = modelKey(resolved.provider, resolved.model);
|
|
478
|
-
const configuredKey = configuredRaw ? resolvedKey : "";
|
|
479
|
-
const catalog = await loadModelCatalog({
|
|
480
|
-
config: cfg,
|
|
481
|
-
useCache: false
|
|
482
|
-
});
|
|
483
|
-
if (catalog.length === 0) return promptManualModel({
|
|
484
|
-
prompter: params.prompter,
|
|
485
|
-
allowBlank: allowKeep,
|
|
486
|
-
initialValue: configuredRaw || resolvedKey || void 0
|
|
487
|
-
});
|
|
488
|
-
const aliasIndex = buildModelAliasIndex({
|
|
489
|
-
cfg,
|
|
490
|
-
defaultProvider: DEFAULT_PROVIDER
|
|
491
|
-
});
|
|
492
|
-
let models = catalog;
|
|
493
|
-
if (!ignoreAllowlist) {
|
|
494
|
-
const { allowedCatalog } = buildAllowedModelSet({
|
|
495
|
-
cfg,
|
|
496
|
-
catalog,
|
|
497
|
-
defaultProvider: DEFAULT_PROVIDER
|
|
498
|
-
});
|
|
499
|
-
models = allowedCatalog.length > 0 ? allowedCatalog : catalog;
|
|
500
|
-
}
|
|
501
|
-
if (models.length === 0) return promptManualModel({
|
|
502
|
-
prompter: params.prompter,
|
|
503
|
-
allowBlank: allowKeep,
|
|
504
|
-
initialValue: configuredRaw || resolvedKey || void 0
|
|
505
|
-
});
|
|
506
|
-
const providers = Array.from(new Set(models.map((entry) => entry.provider))).toSorted((a, b) => a.localeCompare(b));
|
|
507
|
-
const hasPreferredProvider = preferredProvider ? providers.includes(preferredProvider) : false;
|
|
508
|
-
if (!hasPreferredProvider && providers.length > 1 && models.length > PROVIDER_FILTER_THRESHOLD) {
|
|
509
|
-
const selection = await params.prompter.select({
|
|
510
|
-
message: "Filter models by provider",
|
|
511
|
-
options: [{
|
|
512
|
-
value: "*",
|
|
513
|
-
label: "All providers"
|
|
514
|
-
}, ...providers.map((provider) => {
|
|
515
|
-
const count = models.filter((entry) => entry.provider === provider).length;
|
|
516
|
-
return {
|
|
517
|
-
value: provider,
|
|
518
|
-
label: provider,
|
|
519
|
-
hint: `${count} model${count === 1 ? "" : "s"}`
|
|
520
|
-
};
|
|
521
|
-
})]
|
|
522
|
-
});
|
|
523
|
-
if (selection !== "*") models = models.filter((entry) => entry.provider === selection);
|
|
524
|
-
}
|
|
525
|
-
if (hasPreferredProvider && preferredProvider) models = models.filter((entry) => entry.provider === preferredProvider);
|
|
526
|
-
const agentDir = params.agentDir;
|
|
527
|
-
const authStore = ensureAuthProfileStore(agentDir, { allowKeychainPrompt: false });
|
|
528
|
-
const authCache = /* @__PURE__ */ new Map();
|
|
529
|
-
const hasAuth = (provider) => {
|
|
530
|
-
const cached = authCache.get(provider);
|
|
531
|
-
if (cached !== void 0) return cached;
|
|
532
|
-
const value = hasAuthForProvider(provider, cfg, authStore);
|
|
533
|
-
authCache.set(provider, value);
|
|
534
|
-
return value;
|
|
535
|
-
};
|
|
536
|
-
const options = [];
|
|
537
|
-
if (allowKeep) options.push({
|
|
538
|
-
value: KEEP_VALUE,
|
|
539
|
-
label: configuredRaw ? `Keep current (${configuredRaw})` : `Keep current (default: ${resolvedKey})`,
|
|
540
|
-
hint: configuredRaw && configuredRaw !== resolvedKey ? `resolves to ${resolvedKey}` : void 0
|
|
541
|
-
});
|
|
542
|
-
if (includeManual) options.push({
|
|
543
|
-
value: MANUAL_VALUE,
|
|
544
|
-
label: "Enter model manually"
|
|
545
|
-
});
|
|
546
|
-
if (includeVllm && agentDir) options.push({
|
|
547
|
-
value: VLLM_VALUE,
|
|
548
|
-
label: "vLLM (custom)",
|
|
549
|
-
hint: "Enter vLLM URL + API key + model"
|
|
550
|
-
});
|
|
551
|
-
const seen = /* @__PURE__ */ new Set();
|
|
552
|
-
for (const entry of models) addModelSelectOption({
|
|
553
|
-
entry,
|
|
554
|
-
options,
|
|
555
|
-
seen,
|
|
556
|
-
aliasIndex,
|
|
557
|
-
hasAuth
|
|
558
|
-
});
|
|
559
|
-
if (configuredKey && !seen.has(configuredKey)) options.push({
|
|
560
|
-
value: configuredKey,
|
|
561
|
-
label: configuredKey,
|
|
562
|
-
hint: "current (not in catalog)"
|
|
563
|
-
});
|
|
564
|
-
let initialValue = allowKeep ? KEEP_VALUE : configuredKey || void 0;
|
|
565
|
-
if (allowKeep && hasPreferredProvider && preferredProvider && resolved.provider !== preferredProvider) {
|
|
566
|
-
const firstModel = models[0];
|
|
567
|
-
if (firstModel) initialValue = modelKey(firstModel.provider, firstModel.id);
|
|
568
|
-
}
|
|
569
|
-
const selection = await params.prompter.select({
|
|
570
|
-
message: params.message ?? "Default model",
|
|
571
|
-
options,
|
|
572
|
-
initialValue
|
|
573
|
-
});
|
|
574
|
-
if (selection === KEEP_VALUE) return {};
|
|
575
|
-
if (selection === MANUAL_VALUE) return promptManualModel({
|
|
576
|
-
prompter: params.prompter,
|
|
577
|
-
allowBlank: false,
|
|
578
|
-
initialValue: configuredRaw || resolvedKey || void 0
|
|
579
|
-
});
|
|
580
|
-
if (selection === VLLM_VALUE) {
|
|
581
|
-
if (!agentDir) {
|
|
582
|
-
await params.prompter.note("vLLM setup requires an agent directory context.", "vLLM not available");
|
|
583
|
-
return {};
|
|
584
|
-
}
|
|
585
|
-
const { config: nextConfig, modelRef } = await promptAndConfigureVllm({
|
|
586
|
-
cfg,
|
|
587
|
-
prompter: params.prompter,
|
|
588
|
-
agentDir
|
|
589
|
-
});
|
|
590
|
-
return {
|
|
591
|
-
model: modelRef,
|
|
592
|
-
config: nextConfig
|
|
593
|
-
};
|
|
594
|
-
}
|
|
595
|
-
return { model: String(selection) };
|
|
596
|
-
}
|
|
597
|
-
async function promptModelAllowlist(params) {
|
|
598
|
-
const cfg = params.config;
|
|
599
|
-
const existingKeys = resolveConfiguredModelKeys(cfg);
|
|
600
|
-
const allowedKeys = normalizeModelKeys(params.allowedKeys ?? []);
|
|
601
|
-
const allowedKeySet = allowedKeys.length > 0 ? new Set(allowedKeys) : null;
|
|
602
|
-
const resolved = resolveConfiguredModelRef({
|
|
603
|
-
cfg,
|
|
604
|
-
defaultProvider: DEFAULT_PROVIDER,
|
|
605
|
-
defaultModel: DEFAULT_MODEL
|
|
606
|
-
});
|
|
607
|
-
const resolvedKey = modelKey(resolved.provider, resolved.model);
|
|
608
|
-
const initialSeeds = normalizeModelKeys([
|
|
609
|
-
...existingKeys,
|
|
610
|
-
resolvedKey,
|
|
611
|
-
...params.initialSelections ?? []
|
|
612
|
-
]);
|
|
613
|
-
const initialKeys = allowedKeySet ? initialSeeds.filter((key) => allowedKeySet.has(key)) : initialSeeds;
|
|
614
|
-
const catalog = await loadModelCatalog({
|
|
615
|
-
config: cfg,
|
|
616
|
-
useCache: false
|
|
617
|
-
});
|
|
618
|
-
if (catalog.length === 0 && allowedKeys.length === 0) {
|
|
619
|
-
const raw = await params.prompter.text({
|
|
620
|
-
message: params.message ?? "Allowlist models (comma-separated provider/model; blank to keep current)",
|
|
621
|
-
initialValue: existingKeys.join(", "),
|
|
622
|
-
placeholder: `${OPENAI_CODEX_DEFAULT_MODEL}, anthropic/claude-opus-4-6`
|
|
623
|
-
});
|
|
624
|
-
const parsed = String(raw ?? "").split(",").map((value) => value.trim()).filter((value) => value.length > 0);
|
|
625
|
-
if (parsed.length === 0) return {};
|
|
626
|
-
return { models: normalizeModelKeys(parsed) };
|
|
627
|
-
}
|
|
628
|
-
const aliasIndex = buildModelAliasIndex({
|
|
629
|
-
cfg,
|
|
630
|
-
defaultProvider: DEFAULT_PROVIDER
|
|
631
|
-
});
|
|
632
|
-
const authStore = ensureAuthProfileStore(params.agentDir, { allowKeychainPrompt: false });
|
|
633
|
-
const authCache = /* @__PURE__ */ new Map();
|
|
634
|
-
const hasAuth = (provider) => {
|
|
635
|
-
const cached = authCache.get(provider);
|
|
636
|
-
if (cached !== void 0) return cached;
|
|
637
|
-
const value = hasAuthForProvider(provider, cfg, authStore);
|
|
638
|
-
authCache.set(provider, value);
|
|
639
|
-
return value;
|
|
640
|
-
};
|
|
641
|
-
const options = [];
|
|
642
|
-
const seen = /* @__PURE__ */ new Set();
|
|
643
|
-
const filteredCatalog = allowedKeySet ? catalog.filter((entry) => allowedKeySet.has(modelKey(entry.provider, entry.id))) : catalog;
|
|
644
|
-
for (const entry of filteredCatalog) addModelSelectOption({
|
|
645
|
-
entry,
|
|
646
|
-
options,
|
|
647
|
-
seen,
|
|
648
|
-
aliasIndex,
|
|
649
|
-
hasAuth
|
|
650
|
-
});
|
|
651
|
-
const supplementalKeys = allowedKeySet ? allowedKeys : existingKeys;
|
|
652
|
-
for (const key of supplementalKeys) {
|
|
653
|
-
if (seen.has(key)) continue;
|
|
654
|
-
options.push({
|
|
655
|
-
value: key,
|
|
656
|
-
label: key,
|
|
657
|
-
hint: allowedKeySet ? "allowed (not in catalog)" : "configured (not in catalog)"
|
|
658
|
-
});
|
|
659
|
-
seen.add(key);
|
|
660
|
-
}
|
|
661
|
-
if (options.length === 0) return {};
|
|
662
|
-
const selected = normalizeModelKeys((await params.prompter.multiselect({
|
|
663
|
-
message: params.message ?? "Models in /model picker (multi-select)",
|
|
664
|
-
options,
|
|
665
|
-
initialValues: initialKeys.length > 0 ? initialKeys : void 0
|
|
666
|
-
})).map((value) => String(value)));
|
|
667
|
-
if (selected.length > 0) return { models: selected };
|
|
668
|
-
if (existingKeys.length === 0) return { models: [] };
|
|
669
|
-
if (!await params.prompter.confirm({
|
|
670
|
-
message: "Clear the model allowlist? (shows all models)",
|
|
671
|
-
initialValue: false
|
|
672
|
-
})) return {};
|
|
673
|
-
return { models: [] };
|
|
674
|
-
}
|
|
675
|
-
function applyPrimaryModel(cfg, model) {
|
|
676
|
-
const defaults = cfg.agents?.defaults;
|
|
677
|
-
const existingModel = defaults?.model;
|
|
678
|
-
const existingModels = defaults?.models;
|
|
679
|
-
const fallbacks = typeof existingModel === "object" && existingModel !== null && "fallbacks" in existingModel ? existingModel.fallbacks : void 0;
|
|
680
|
-
return {
|
|
681
|
-
...cfg,
|
|
682
|
-
agents: {
|
|
683
|
-
...cfg.agents,
|
|
684
|
-
defaults: {
|
|
685
|
-
...defaults,
|
|
686
|
-
model: {
|
|
687
|
-
...fallbacks ? { fallbacks } : void 0,
|
|
688
|
-
primary: model
|
|
689
|
-
},
|
|
690
|
-
models: {
|
|
691
|
-
...existingModels,
|
|
692
|
-
[model]: existingModels?.[model] ?? {}
|
|
693
|
-
}
|
|
694
|
-
}
|
|
695
|
-
}
|
|
696
|
-
};
|
|
697
|
-
}
|
|
698
|
-
function applyModelAllowlist(cfg, models) {
|
|
699
|
-
const defaults = cfg.agents?.defaults;
|
|
700
|
-
const normalized = normalizeModelKeys(models);
|
|
701
|
-
if (normalized.length === 0) {
|
|
702
|
-
if (!defaults?.models) return cfg;
|
|
703
|
-
const { models: _ignored, ...restDefaults } = defaults;
|
|
704
|
-
return {
|
|
705
|
-
...cfg,
|
|
706
|
-
agents: {
|
|
707
|
-
...cfg.agents,
|
|
708
|
-
defaults: restDefaults
|
|
709
|
-
}
|
|
710
|
-
};
|
|
711
|
-
}
|
|
712
|
-
const existingModels = defaults?.models ?? {};
|
|
713
|
-
const nextModels = {};
|
|
714
|
-
for (const key of normalized) nextModels[key] = existingModels[key] ?? {};
|
|
715
|
-
return {
|
|
716
|
-
...cfg,
|
|
717
|
-
agents: {
|
|
718
|
-
...cfg.agents,
|
|
719
|
-
defaults: {
|
|
720
|
-
...defaults,
|
|
721
|
-
models: nextModels
|
|
722
|
-
}
|
|
723
|
-
}
|
|
724
|
-
};
|
|
725
|
-
}
|
|
726
|
-
function applyModelFallbacksFromSelection(cfg, selection) {
|
|
727
|
-
const normalized = normalizeModelKeys(selection);
|
|
728
|
-
if (normalized.length <= 1) return cfg;
|
|
729
|
-
const resolved = resolveConfiguredModelRef({
|
|
730
|
-
cfg,
|
|
731
|
-
defaultProvider: DEFAULT_PROVIDER,
|
|
732
|
-
defaultModel: DEFAULT_MODEL
|
|
733
|
-
});
|
|
734
|
-
const resolvedKey = modelKey(resolved.provider, resolved.model);
|
|
735
|
-
if (!normalized.includes(resolvedKey)) return cfg;
|
|
736
|
-
const defaults = cfg.agents?.defaults;
|
|
737
|
-
const existingModel = defaults?.model;
|
|
738
|
-
const existingPrimary = typeof existingModel === "string" ? existingModel : existingModel && typeof existingModel === "object" ? existingModel.primary : void 0;
|
|
739
|
-
const fallbacks = normalized.filter((key) => key !== resolvedKey);
|
|
740
|
-
return {
|
|
741
|
-
...cfg,
|
|
742
|
-
agents: {
|
|
743
|
-
...cfg.agents,
|
|
744
|
-
defaults: {
|
|
745
|
-
...defaults,
|
|
746
|
-
model: {
|
|
747
|
-
...typeof existingModel === "object" ? existingModel : void 0,
|
|
748
|
-
primary: existingPrimary ?? resolvedKey,
|
|
749
|
-
fallbacks
|
|
750
|
-
}
|
|
751
|
-
}
|
|
752
|
-
}
|
|
753
|
-
};
|
|
754
|
-
}
|
|
755
|
-
|
|
756
|
-
//#endregion
|
|
757
|
-
//#region src/commands/onboard-custom.ts
|
|
758
|
-
const DEFAULT_OLLAMA_BASE_URL = "http://127.0.0.1:11434/v1";
|
|
759
|
-
const DEFAULT_CONTEXT_WINDOW = 4096;
|
|
760
|
-
const DEFAULT_MAX_TOKENS = 4096;
|
|
761
|
-
const VERIFY_TIMEOUT_MS = 1e4;
|
|
762
|
-
var CustomApiError = class extends Error {
|
|
763
|
-
constructor(code, message) {
|
|
764
|
-
super(message);
|
|
765
|
-
this.name = "CustomApiError";
|
|
766
|
-
this.code = code;
|
|
767
|
-
}
|
|
768
|
-
};
|
|
769
|
-
const COMPATIBILITY_OPTIONS = [
|
|
770
|
-
{
|
|
771
|
-
value: "openai",
|
|
772
|
-
label: "OpenAI-compatible",
|
|
773
|
-
hint: "Uses /chat/completions"
|
|
774
|
-
},
|
|
775
|
-
{
|
|
776
|
-
value: "anthropic",
|
|
777
|
-
label: "Anthropic-compatible",
|
|
778
|
-
hint: "Uses /messages"
|
|
779
|
-
},
|
|
780
|
-
{
|
|
781
|
-
value: "unknown",
|
|
782
|
-
label: "Unknown (detect automatically)",
|
|
783
|
-
hint: "Probes OpenAI then Anthropic endpoints"
|
|
784
|
-
}
|
|
785
|
-
];
|
|
786
|
-
function normalizeEndpointId(raw) {
|
|
787
|
-
const trimmed = raw.trim().toLowerCase();
|
|
788
|
-
if (!trimmed) return "";
|
|
789
|
-
return trimmed.replace(/[^a-z0-9-]+/g, "-").replace(/^-+|-+$/g, "");
|
|
790
|
-
}
|
|
791
|
-
function buildEndpointIdFromUrl(baseUrl) {
|
|
792
|
-
try {
|
|
793
|
-
const url = new URL(baseUrl);
|
|
794
|
-
return normalizeEndpointId(`custom-${url.hostname.replace(/[^a-z0-9]+/gi, "-").toLowerCase()}${url.port ? `-${url.port}` : ""}`) || "custom";
|
|
795
|
-
} catch {
|
|
796
|
-
return "custom";
|
|
797
|
-
}
|
|
798
|
-
}
|
|
799
|
-
function resolveUniqueEndpointId(params) {
|
|
800
|
-
const normalized = normalizeEndpointId(params.requestedId) || "custom";
|
|
801
|
-
const existing = params.providers[normalized];
|
|
802
|
-
if (!existing?.baseUrl || existing.baseUrl === params.baseUrl) return {
|
|
803
|
-
providerId: normalized,
|
|
804
|
-
renamed: false
|
|
805
|
-
};
|
|
806
|
-
let suffix = 2;
|
|
807
|
-
let candidate = `${normalized}-${suffix}`;
|
|
808
|
-
while (params.providers[candidate]) {
|
|
809
|
-
suffix += 1;
|
|
810
|
-
candidate = `${normalized}-${suffix}`;
|
|
811
|
-
}
|
|
812
|
-
return {
|
|
813
|
-
providerId: candidate,
|
|
814
|
-
renamed: true
|
|
815
|
-
};
|
|
816
|
-
}
|
|
817
|
-
function resolveAliasError(params) {
|
|
818
|
-
const trimmed = params.raw.trim();
|
|
819
|
-
if (!trimmed) return;
|
|
820
|
-
let normalized;
|
|
821
|
-
try {
|
|
822
|
-
normalized = normalizeAlias(trimmed);
|
|
823
|
-
} catch (err) {
|
|
824
|
-
return err instanceof Error ? err.message : "Alias is invalid.";
|
|
825
|
-
}
|
|
826
|
-
const aliasIndex = buildModelAliasIndex({
|
|
827
|
-
cfg: params.cfg,
|
|
828
|
-
defaultProvider: DEFAULT_PROVIDER
|
|
829
|
-
});
|
|
830
|
-
const aliasKey = normalized.toLowerCase();
|
|
831
|
-
const existing = aliasIndex.byAlias.get(aliasKey);
|
|
832
|
-
if (!existing) return;
|
|
833
|
-
const existingKey = modelKey(existing.ref.provider, existing.ref.model);
|
|
834
|
-
if (existingKey === params.modelRef) return;
|
|
835
|
-
return `Alias ${normalized} already points to ${existingKey}.`;
|
|
836
|
-
}
|
|
837
|
-
function buildOpenAiHeaders(apiKey) {
|
|
838
|
-
const headers = {};
|
|
839
|
-
if (apiKey) headers.Authorization = `Bearer ${apiKey}`;
|
|
840
|
-
return headers;
|
|
841
|
-
}
|
|
842
|
-
function buildAnthropicHeaders(apiKey) {
|
|
843
|
-
const headers = { "anthropic-version": "2023-06-01" };
|
|
844
|
-
if (apiKey) headers["x-api-key"] = apiKey;
|
|
845
|
-
return headers;
|
|
846
|
-
}
|
|
847
|
-
function formatVerificationError(error) {
|
|
848
|
-
if (!error) return "unknown error";
|
|
849
|
-
if (error instanceof Error) return error.message;
|
|
850
|
-
if (typeof error === "string") return error;
|
|
851
|
-
try {
|
|
852
|
-
return JSON.stringify(error);
|
|
853
|
-
} catch {
|
|
854
|
-
return "unknown error";
|
|
855
|
-
}
|
|
856
|
-
}
|
|
857
|
-
async function requestOpenAiVerification(params) {
|
|
858
|
-
const endpoint = new URL("chat/completions", params.baseUrl.endsWith("/") ? params.baseUrl : `${params.baseUrl}/`).href;
|
|
859
|
-
try {
|
|
860
|
-
const res = await fetchWithTimeout(endpoint, {
|
|
861
|
-
method: "POST",
|
|
862
|
-
headers: {
|
|
863
|
-
"Content-Type": "application/json",
|
|
864
|
-
...buildOpenAiHeaders(params.apiKey)
|
|
865
|
-
},
|
|
866
|
-
body: JSON.stringify({
|
|
867
|
-
model: params.modelId,
|
|
868
|
-
messages: [{
|
|
869
|
-
role: "user",
|
|
870
|
-
content: "Hi"
|
|
871
|
-
}],
|
|
872
|
-
max_tokens: 5
|
|
873
|
-
})
|
|
874
|
-
}, VERIFY_TIMEOUT_MS);
|
|
875
|
-
return {
|
|
876
|
-
ok: res.ok,
|
|
877
|
-
status: res.status
|
|
878
|
-
};
|
|
879
|
-
} catch (error) {
|
|
880
|
-
return {
|
|
881
|
-
ok: false,
|
|
882
|
-
error
|
|
883
|
-
};
|
|
884
|
-
}
|
|
885
|
-
}
|
|
886
|
-
async function requestAnthropicVerification(params) {
|
|
887
|
-
const endpoint = new URL("messages", params.baseUrl.endsWith("/") ? params.baseUrl : `${params.baseUrl}/`).href;
|
|
888
|
-
try {
|
|
889
|
-
const res = await fetchWithTimeout(endpoint, {
|
|
890
|
-
method: "POST",
|
|
891
|
-
headers: {
|
|
892
|
-
"Content-Type": "application/json",
|
|
893
|
-
...buildAnthropicHeaders(params.apiKey)
|
|
894
|
-
},
|
|
895
|
-
body: JSON.stringify({
|
|
896
|
-
model: params.modelId,
|
|
897
|
-
max_tokens: 16,
|
|
898
|
-
messages: [{
|
|
899
|
-
role: "user",
|
|
900
|
-
content: "Hi"
|
|
901
|
-
}]
|
|
902
|
-
})
|
|
903
|
-
}, VERIFY_TIMEOUT_MS);
|
|
904
|
-
return {
|
|
905
|
-
ok: res.ok,
|
|
906
|
-
status: res.status
|
|
907
|
-
};
|
|
908
|
-
} catch (error) {
|
|
909
|
-
return {
|
|
910
|
-
ok: false,
|
|
911
|
-
error
|
|
912
|
-
};
|
|
913
|
-
}
|
|
914
|
-
}
|
|
915
|
-
async function promptBaseUrlAndKey(params) {
|
|
916
|
-
const baseUrlInput = await params.prompter.text({
|
|
917
|
-
message: "API Base URL",
|
|
918
|
-
initialValue: params.initialBaseUrl ?? DEFAULT_OLLAMA_BASE_URL,
|
|
919
|
-
placeholder: "https://api.example.com/v1",
|
|
920
|
-
validate: (val) => {
|
|
921
|
-
try {
|
|
922
|
-
new URL(val);
|
|
923
|
-
return;
|
|
924
|
-
} catch {
|
|
925
|
-
return "Please enter a valid URL (e.g. http://...)";
|
|
926
|
-
}
|
|
927
|
-
}
|
|
928
|
-
});
|
|
929
|
-
const apiKeyInput = await params.prompter.text({
|
|
930
|
-
message: "API Key (leave blank if not required)",
|
|
931
|
-
placeholder: "sk-...",
|
|
932
|
-
initialValue: ""
|
|
933
|
-
});
|
|
934
|
-
return {
|
|
935
|
-
baseUrl: baseUrlInput.trim(),
|
|
936
|
-
apiKey: apiKeyInput.trim()
|
|
937
|
-
};
|
|
938
|
-
}
|
|
939
|
-
async function promptCustomApiRetryChoice(prompter) {
|
|
940
|
-
return await prompter.select({
|
|
941
|
-
message: "What would you like to change?",
|
|
942
|
-
options: [
|
|
943
|
-
{
|
|
944
|
-
value: "baseUrl",
|
|
945
|
-
label: "Change base URL"
|
|
946
|
-
},
|
|
947
|
-
{
|
|
948
|
-
value: "model",
|
|
949
|
-
label: "Change model"
|
|
950
|
-
},
|
|
951
|
-
{
|
|
952
|
-
value: "both",
|
|
953
|
-
label: "Change base URL and model"
|
|
954
|
-
}
|
|
955
|
-
]
|
|
956
|
-
});
|
|
957
|
-
}
|
|
958
|
-
async function promptCustomApiModelId(prompter) {
|
|
959
|
-
return (await prompter.text({
|
|
960
|
-
message: "Model ID",
|
|
961
|
-
placeholder: "e.g. llama3, claude-3-7-sonnet",
|
|
962
|
-
validate: (val) => val.trim() ? void 0 : "Model ID is required"
|
|
963
|
-
})).trim();
|
|
964
|
-
}
|
|
965
|
-
function resolveProviderApi(compatibility) {
|
|
966
|
-
return compatibility === "anthropic" ? "anthropic-messages" : "openai-completions";
|
|
967
|
-
}
|
|
968
|
-
function parseCustomApiCompatibility(raw) {
|
|
969
|
-
const compatibilityRaw = raw?.trim().toLowerCase();
|
|
970
|
-
if (!compatibilityRaw) return "openai";
|
|
971
|
-
if (compatibilityRaw !== "openai" && compatibilityRaw !== "anthropic") throw new CustomApiError("invalid_compatibility", "Invalid --custom-compatibility (use \"openai\" or \"anthropic\").");
|
|
972
|
-
return compatibilityRaw;
|
|
973
|
-
}
|
|
974
|
-
function resolveCustomProviderId(params) {
|
|
975
|
-
const providers = params.config.models?.providers ?? {};
|
|
976
|
-
const baseUrl = params.baseUrl.trim();
|
|
977
|
-
const explicitProviderId = params.providerId?.trim();
|
|
978
|
-
if (explicitProviderId && !normalizeEndpointId(explicitProviderId)) throw new CustomApiError("invalid_provider_id", "Custom provider ID must include letters, numbers, or hyphens.");
|
|
979
|
-
const requestedProviderId = explicitProviderId || buildEndpointIdFromUrl(baseUrl);
|
|
980
|
-
const providerIdResult = resolveUniqueEndpointId({
|
|
981
|
-
requestedId: requestedProviderId,
|
|
982
|
-
baseUrl,
|
|
983
|
-
providers
|
|
984
|
-
});
|
|
985
|
-
return {
|
|
986
|
-
providerId: providerIdResult.providerId,
|
|
987
|
-
...providerIdResult.renamed ? { providerIdRenamedFrom: normalizeEndpointId(requestedProviderId) || "custom" } : {}
|
|
988
|
-
};
|
|
989
|
-
}
|
|
990
|
-
function parseNonInteractiveCustomApiFlags(params) {
|
|
991
|
-
const baseUrl = params.baseUrl?.trim() ?? "";
|
|
992
|
-
const modelId = params.modelId?.trim() ?? "";
|
|
993
|
-
if (!baseUrl || !modelId) throw new CustomApiError("missing_required", ["Auth choice \"custom-api-key\" requires a base URL and model ID.", "Use --custom-base-url and --custom-model-id."].join("\n"));
|
|
994
|
-
const apiKey = params.apiKey?.trim();
|
|
995
|
-
const providerId = params.providerId?.trim();
|
|
996
|
-
if (providerId && !normalizeEndpointId(providerId)) throw new CustomApiError("invalid_provider_id", "Custom provider ID must include letters, numbers, or hyphens.");
|
|
997
|
-
return {
|
|
998
|
-
baseUrl,
|
|
999
|
-
modelId,
|
|
1000
|
-
compatibility: parseCustomApiCompatibility(params.compatibility),
|
|
1001
|
-
...apiKey ? { apiKey } : {},
|
|
1002
|
-
...providerId ? { providerId } : {}
|
|
1003
|
-
};
|
|
1004
|
-
}
|
|
1005
|
-
function applyCustomApiConfig(params) {
|
|
1006
|
-
const baseUrl = params.baseUrl.trim();
|
|
1007
|
-
try {
|
|
1008
|
-
new URL(baseUrl);
|
|
1009
|
-
} catch {
|
|
1010
|
-
throw new CustomApiError("invalid_base_url", "Custom provider base URL must be a valid URL.");
|
|
1011
|
-
}
|
|
1012
|
-
if (params.compatibility !== "openai" && params.compatibility !== "anthropic") throw new CustomApiError("invalid_compatibility", "Custom provider compatibility must be \"openai\" or \"anthropic\".");
|
|
1013
|
-
const modelId = params.modelId.trim();
|
|
1014
|
-
if (!modelId) throw new CustomApiError("invalid_model_id", "Custom provider model ID is required.");
|
|
1015
|
-
const providerIdResult = resolveCustomProviderId({
|
|
1016
|
-
config: params.config,
|
|
1017
|
-
baseUrl,
|
|
1018
|
-
providerId: params.providerId
|
|
1019
|
-
});
|
|
1020
|
-
const providerId = providerIdResult.providerId;
|
|
1021
|
-
const providers = params.config.models?.providers ?? {};
|
|
1022
|
-
const modelRef = modelKey(providerId, modelId);
|
|
1023
|
-
const alias = params.alias?.trim() ?? "";
|
|
1024
|
-
const aliasError = resolveAliasError({
|
|
1025
|
-
raw: alias,
|
|
1026
|
-
cfg: params.config,
|
|
1027
|
-
modelRef
|
|
1028
|
-
});
|
|
1029
|
-
if (aliasError) throw new CustomApiError("invalid_alias", aliasError);
|
|
1030
|
-
const existingProvider = providers[providerId];
|
|
1031
|
-
const existingModels = Array.isArray(existingProvider?.models) ? existingProvider.models : [];
|
|
1032
|
-
const hasModel = existingModels.some((model) => model.id === modelId);
|
|
1033
|
-
const nextModel = {
|
|
1034
|
-
id: modelId,
|
|
1035
|
-
name: `${modelId} (Custom Provider)`,
|
|
1036
|
-
contextWindow: DEFAULT_CONTEXT_WINDOW,
|
|
1037
|
-
maxTokens: DEFAULT_MAX_TOKENS,
|
|
1038
|
-
input: ["text"],
|
|
1039
|
-
cost: {
|
|
1040
|
-
input: 0,
|
|
1041
|
-
output: 0,
|
|
1042
|
-
cacheRead: 0,
|
|
1043
|
-
cacheWrite: 0
|
|
1044
|
-
},
|
|
1045
|
-
reasoning: false
|
|
1046
|
-
};
|
|
1047
|
-
const mergedModels = hasModel ? existingModels : [...existingModels, nextModel];
|
|
1048
|
-
const { apiKey: existingApiKey, ...existingProviderRest } = existingProvider ?? {};
|
|
1049
|
-
const normalizedApiKey = params.apiKey?.trim() || (existingApiKey ? existingApiKey.trim() : void 0);
|
|
1050
|
-
let config = {
|
|
1051
|
-
...params.config,
|
|
1052
|
-
models: {
|
|
1053
|
-
...params.config.models,
|
|
1054
|
-
mode: params.config.models?.mode ?? "merge",
|
|
1055
|
-
providers: {
|
|
1056
|
-
...providers,
|
|
1057
|
-
[providerId]: {
|
|
1058
|
-
...existingProviderRest,
|
|
1059
|
-
baseUrl,
|
|
1060
|
-
api: resolveProviderApi(params.compatibility),
|
|
1061
|
-
...normalizedApiKey ? { apiKey: normalizedApiKey } : {},
|
|
1062
|
-
models: mergedModels.length > 0 ? mergedModels : [nextModel]
|
|
1063
|
-
}
|
|
1064
|
-
}
|
|
1065
|
-
}
|
|
1066
|
-
};
|
|
1067
|
-
config = applyPrimaryModel(config, modelRef);
|
|
1068
|
-
if (alias) config = {
|
|
1069
|
-
...config,
|
|
1070
|
-
agents: {
|
|
1071
|
-
...config.agents,
|
|
1072
|
-
defaults: {
|
|
1073
|
-
...config.agents?.defaults,
|
|
1074
|
-
models: {
|
|
1075
|
-
...config.agents?.defaults?.models,
|
|
1076
|
-
[modelRef]: {
|
|
1077
|
-
...config.agents?.defaults?.models?.[modelRef],
|
|
1078
|
-
alias
|
|
1079
|
-
}
|
|
1080
|
-
}
|
|
1081
|
-
}
|
|
1082
|
-
}
|
|
1083
|
-
};
|
|
1084
|
-
return {
|
|
1085
|
-
config,
|
|
1086
|
-
providerId,
|
|
1087
|
-
modelId,
|
|
1088
|
-
...providerIdResult.providerIdRenamedFrom ? { providerIdRenamedFrom: providerIdResult.providerIdRenamedFrom } : {}
|
|
1089
|
-
};
|
|
1090
|
-
}
|
|
1091
|
-
async function promptCustomApiConfig(params) {
|
|
1092
|
-
const { prompter, runtime, config } = params;
|
|
1093
|
-
const baseInput = await promptBaseUrlAndKey({ prompter });
|
|
1094
|
-
let baseUrl = baseInput.baseUrl;
|
|
1095
|
-
let apiKey = baseInput.apiKey;
|
|
1096
|
-
const compatibilityChoice = await prompter.select({
|
|
1097
|
-
message: "Endpoint compatibility",
|
|
1098
|
-
options: COMPATIBILITY_OPTIONS.map((option) => ({
|
|
1099
|
-
value: option.value,
|
|
1100
|
-
label: option.label,
|
|
1101
|
-
hint: option.hint
|
|
1102
|
-
}))
|
|
1103
|
-
});
|
|
1104
|
-
let modelId = await promptCustomApiModelId(prompter);
|
|
1105
|
-
let compatibility = compatibilityChoice === "unknown" ? null : compatibilityChoice;
|
|
1106
|
-
while (true) {
|
|
1107
|
-
let verifiedFromProbe = false;
|
|
1108
|
-
if (!compatibility) {
|
|
1109
|
-
const probeSpinner = prompter.progress("Detecting endpoint type...");
|
|
1110
|
-
if ((await requestOpenAiVerification({
|
|
1111
|
-
baseUrl,
|
|
1112
|
-
apiKey,
|
|
1113
|
-
modelId
|
|
1114
|
-
})).ok) {
|
|
1115
|
-
probeSpinner.stop("Detected OpenAI-compatible endpoint.");
|
|
1116
|
-
compatibility = "openai";
|
|
1117
|
-
verifiedFromProbe = true;
|
|
1118
|
-
} else if ((await requestAnthropicVerification({
|
|
1119
|
-
baseUrl,
|
|
1120
|
-
apiKey,
|
|
1121
|
-
modelId
|
|
1122
|
-
})).ok) {
|
|
1123
|
-
probeSpinner.stop("Detected Anthropic-compatible endpoint.");
|
|
1124
|
-
compatibility = "anthropic";
|
|
1125
|
-
verifiedFromProbe = true;
|
|
1126
|
-
} else {
|
|
1127
|
-
probeSpinner.stop("Could not detect endpoint type.");
|
|
1128
|
-
await prompter.note("This endpoint did not respond to OpenAI or Anthropic style requests.", "Endpoint detection");
|
|
1129
|
-
const retryChoice = await promptCustomApiRetryChoice(prompter);
|
|
1130
|
-
if (retryChoice === "baseUrl" || retryChoice === "both") {
|
|
1131
|
-
const retryInput = await promptBaseUrlAndKey({
|
|
1132
|
-
prompter,
|
|
1133
|
-
initialBaseUrl: baseUrl
|
|
1134
|
-
});
|
|
1135
|
-
baseUrl = retryInput.baseUrl;
|
|
1136
|
-
apiKey = retryInput.apiKey;
|
|
1137
|
-
}
|
|
1138
|
-
if (retryChoice === "model" || retryChoice === "both") modelId = await promptCustomApiModelId(prompter);
|
|
1139
|
-
continue;
|
|
1140
|
-
}
|
|
1141
|
-
}
|
|
1142
|
-
if (verifiedFromProbe) break;
|
|
1143
|
-
const verifySpinner = prompter.progress("Verifying...");
|
|
1144
|
-
const result = compatibility === "anthropic" ? await requestAnthropicVerification({
|
|
1145
|
-
baseUrl,
|
|
1146
|
-
apiKey,
|
|
1147
|
-
modelId
|
|
1148
|
-
}) : await requestOpenAiVerification({
|
|
1149
|
-
baseUrl,
|
|
1150
|
-
apiKey,
|
|
1151
|
-
modelId
|
|
1152
|
-
});
|
|
1153
|
-
if (result.ok) {
|
|
1154
|
-
verifySpinner.stop("Verification successful.");
|
|
1155
|
-
break;
|
|
1156
|
-
}
|
|
1157
|
-
if (result.status !== void 0) verifySpinner.stop(`Verification failed: status ${result.status}`);
|
|
1158
|
-
else verifySpinner.stop(`Verification failed: ${formatVerificationError(result.error)}`);
|
|
1159
|
-
const retryChoice = await promptCustomApiRetryChoice(prompter);
|
|
1160
|
-
if (retryChoice === "baseUrl" || retryChoice === "both") {
|
|
1161
|
-
const retryInput = await promptBaseUrlAndKey({
|
|
1162
|
-
prompter,
|
|
1163
|
-
initialBaseUrl: baseUrl
|
|
1164
|
-
});
|
|
1165
|
-
baseUrl = retryInput.baseUrl;
|
|
1166
|
-
apiKey = retryInput.apiKey;
|
|
1167
|
-
}
|
|
1168
|
-
if (retryChoice === "model" || retryChoice === "both") modelId = await promptCustomApiModelId(prompter);
|
|
1169
|
-
if (compatibilityChoice === "unknown") compatibility = null;
|
|
1170
|
-
}
|
|
1171
|
-
const providers = config.models?.providers ?? {};
|
|
1172
|
-
const suggestedId = buildEndpointIdFromUrl(baseUrl);
|
|
1173
|
-
const providerIdInput = await prompter.text({
|
|
1174
|
-
message: "Endpoint ID",
|
|
1175
|
-
initialValue: suggestedId,
|
|
1176
|
-
placeholder: "custom",
|
|
1177
|
-
validate: (value) => {
|
|
1178
|
-
if (!normalizeEndpointId(value)) return "Endpoint ID is required.";
|
|
1179
|
-
}
|
|
1180
|
-
});
|
|
1181
|
-
const aliasInput = await prompter.text({
|
|
1182
|
-
message: "Model alias (optional)",
|
|
1183
|
-
placeholder: "e.g. local, ollama",
|
|
1184
|
-
initialValue: "",
|
|
1185
|
-
validate: (value) => {
|
|
1186
|
-
return resolveAliasError({
|
|
1187
|
-
raw: value,
|
|
1188
|
-
cfg: config,
|
|
1189
|
-
modelRef: modelKey(resolveUniqueEndpointId({
|
|
1190
|
-
requestedId: normalizeEndpointId(providerIdInput) || "custom",
|
|
1191
|
-
baseUrl,
|
|
1192
|
-
providers
|
|
1193
|
-
}).providerId, modelId)
|
|
1194
|
-
});
|
|
1195
|
-
}
|
|
1196
|
-
});
|
|
1197
|
-
const result = applyCustomApiConfig({
|
|
1198
|
-
config,
|
|
1199
|
-
baseUrl,
|
|
1200
|
-
modelId,
|
|
1201
|
-
compatibility: compatibility ?? "openai",
|
|
1202
|
-
apiKey,
|
|
1203
|
-
providerId: providerIdInput,
|
|
1204
|
-
alias: aliasInput
|
|
1205
|
-
});
|
|
1206
|
-
if (result.providerIdRenamedFrom && result.providerId) await prompter.note(`Endpoint ID "${result.providerIdRenamedFrom}" already exists for a different base URL. Using "${result.providerId}".`, "Endpoint ID");
|
|
1207
|
-
runtime.log(`Configured custom provider: ${result.providerId}/${result.modelId}`);
|
|
1208
|
-
return result;
|
|
1209
|
-
}
|
|
1210
|
-
|
|
1211
|
-
//#endregion
|
|
1212
|
-
//#region src/commands/onboard-remote.ts
|
|
1213
|
-
const DEFAULT_GATEWAY_URL = "ws://127.0.0.1:18789";
|
|
1214
|
-
function pickHost(beacon) {
|
|
1215
|
-
return beacon.host || beacon.tailnetDns || beacon.lanHost;
|
|
1216
|
-
}
|
|
1217
|
-
function buildLabel(beacon) {
|
|
1218
|
-
const host = pickHost(beacon);
|
|
1219
|
-
const port = beacon.port ?? beacon.gatewayPort ?? 18789;
|
|
1220
|
-
return `${beacon.displayName ?? beacon.instanceName} (${host ? `${host}:${port}` : "host unknown"})`;
|
|
1221
|
-
}
|
|
1222
|
-
function ensureWsUrl(value) {
|
|
1223
|
-
const trimmed = value.trim();
|
|
1224
|
-
if (!trimmed) return DEFAULT_GATEWAY_URL;
|
|
1225
|
-
return trimmed;
|
|
1226
|
-
}
|
|
1227
|
-
async function promptRemoteGatewayConfig(cfg, prompter) {
|
|
1228
|
-
let selectedBeacon = null;
|
|
1229
|
-
let suggestedUrl = cfg.gateway?.remote?.url ?? DEFAULT_GATEWAY_URL;
|
|
1230
|
-
const hasBonjourTool = await detectBinary("dns-sd") || await detectBinary("avahi-browse");
|
|
1231
|
-
const wantsDiscover = hasBonjourTool ? await prompter.confirm({
|
|
1232
|
-
message: "Discover gateway on LAN (Bonjour)?",
|
|
1233
|
-
initialValue: true
|
|
1234
|
-
}) : false;
|
|
1235
|
-
if (!hasBonjourTool) await prompter.note(["Bonjour discovery requires dns-sd (macOS) or avahi-browse (Linux).", "Docs: https://docs.anima.ai/gateway/discovery"].join("\n"), "Discovery");
|
|
1236
|
-
if (wantsDiscover) {
|
|
1237
|
-
const wideAreaDomain = resolveWideAreaDiscoveryDomain({ configDomain: cfg.discovery?.wideArea?.domain });
|
|
1238
|
-
const spin = prompter.progress("Searching for gateways…");
|
|
1239
|
-
const beacons = await discoverGatewayBeacons({
|
|
1240
|
-
timeoutMs: 2e3,
|
|
1241
|
-
wideAreaDomain
|
|
1242
|
-
});
|
|
1243
|
-
spin.stop(beacons.length > 0 ? `Found ${beacons.length} gateway(s)` : "No gateways found");
|
|
1244
|
-
if (beacons.length > 0) {
|
|
1245
|
-
const selection = await prompter.select({
|
|
1246
|
-
message: "Select gateway",
|
|
1247
|
-
options: [...beacons.map((beacon, index) => ({
|
|
1248
|
-
value: String(index),
|
|
1249
|
-
label: buildLabel(beacon)
|
|
1250
|
-
})), {
|
|
1251
|
-
value: "manual",
|
|
1252
|
-
label: "Enter URL manually"
|
|
1253
|
-
}]
|
|
1254
|
-
});
|
|
1255
|
-
if (selection !== "manual") {
|
|
1256
|
-
const idx = Number.parseInt(String(selection), 10);
|
|
1257
|
-
selectedBeacon = Number.isFinite(idx) ? beacons[idx] ?? null : null;
|
|
1258
|
-
}
|
|
1259
|
-
}
|
|
1260
|
-
}
|
|
1261
|
-
if (selectedBeacon) {
|
|
1262
|
-
const host = pickHost(selectedBeacon);
|
|
1263
|
-
const port = selectedBeacon.port ?? selectedBeacon.gatewayPort ?? 18789;
|
|
1264
|
-
if (host) if (await prompter.select({
|
|
1265
|
-
message: "Connection method",
|
|
1266
|
-
options: [{
|
|
1267
|
-
value: "direct",
|
|
1268
|
-
label: `Direct gateway WS (${host}:${port})`
|
|
1269
|
-
}, {
|
|
1270
|
-
value: "ssh",
|
|
1271
|
-
label: "SSH tunnel (loopback)"
|
|
1272
|
-
}]
|
|
1273
|
-
}) === "direct") suggestedUrl = `ws://${host}:${port}`;
|
|
1274
|
-
else {
|
|
1275
|
-
suggestedUrl = DEFAULT_GATEWAY_URL;
|
|
1276
|
-
await prompter.note([
|
|
1277
|
-
"Start a tunnel before using the CLI:",
|
|
1278
|
-
`ssh -N -L 18789:127.0.0.1:18789 <user>@${host}${selectedBeacon.sshPort ? ` -p ${selectedBeacon.sshPort}` : ""}`,
|
|
1279
|
-
"Docs: https://docs.anima.ai/gateway/remote"
|
|
1280
|
-
].join("\n"), "SSH tunnel");
|
|
1281
|
-
}
|
|
1282
|
-
}
|
|
1283
|
-
const urlInput = await prompter.text({
|
|
1284
|
-
message: "Gateway WebSocket URL",
|
|
1285
|
-
initialValue: suggestedUrl,
|
|
1286
|
-
validate: (value) => String(value).trim().startsWith("ws://") || String(value).trim().startsWith("wss://") ? void 0 : "URL must start with ws:// or wss://"
|
|
1287
|
-
});
|
|
1288
|
-
const url = ensureWsUrl(String(urlInput));
|
|
1289
|
-
const authChoice = await prompter.select({
|
|
1290
|
-
message: "Gateway auth",
|
|
1291
|
-
options: [{
|
|
1292
|
-
value: "token",
|
|
1293
|
-
label: "Token (recommended)"
|
|
1294
|
-
}, {
|
|
1295
|
-
value: "off",
|
|
1296
|
-
label: "No auth"
|
|
1297
|
-
}]
|
|
1298
|
-
});
|
|
1299
|
-
let token = cfg.gateway?.remote?.token ?? "";
|
|
1300
|
-
if (authChoice === "token") token = String(await prompter.text({
|
|
1301
|
-
message: "Gateway token",
|
|
1302
|
-
initialValue: token,
|
|
1303
|
-
validate: (value) => value?.trim() ? void 0 : "Required"
|
|
1304
|
-
})).trim();
|
|
1305
|
-
else token = "";
|
|
1306
|
-
return {
|
|
1307
|
-
...cfg,
|
|
1308
|
-
gateway: {
|
|
1309
|
-
...cfg.gateway,
|
|
1310
|
-
mode: "remote",
|
|
1311
|
-
remote: {
|
|
1312
|
-
url,
|
|
1313
|
-
token: token || void 0
|
|
1314
|
-
}
|
|
1315
|
-
}
|
|
1316
|
-
};
|
|
1317
|
-
}
|
|
1318
|
-
|
|
1319
|
-
//#endregion
|
|
1320
|
-
//#region src/agents/skills-install.ts
|
|
1321
|
-
function isNodeReadableStream(value) {
|
|
1322
|
-
return Boolean(value && typeof value.pipe === "function");
|
|
1323
|
-
}
|
|
1324
|
-
function summarizeInstallOutput(text) {
|
|
1325
|
-
const raw = text.trim();
|
|
1326
|
-
if (!raw) return;
|
|
1327
|
-
const lines = raw.split("\n").map((line) => line.trim()).filter(Boolean);
|
|
1328
|
-
if (lines.length === 0) return;
|
|
1329
|
-
const preferred = lines.find((line) => /^error\b/i.test(line)) ?? lines.find((line) => /\b(err!|error:|failed)\b/i.test(line)) ?? lines.at(-1);
|
|
1330
|
-
if (!preferred) return;
|
|
1331
|
-
const normalized = preferred.replace(/\s+/g, " ").trim();
|
|
1332
|
-
const maxLen = 200;
|
|
1333
|
-
return normalized.length > maxLen ? `${normalized.slice(0, maxLen - 1)}…` : normalized;
|
|
1334
|
-
}
|
|
1335
|
-
function formatInstallFailureMessage(result) {
|
|
1336
|
-
const code = typeof result.code === "number" ? `exit ${result.code}` : "unknown exit";
|
|
1337
|
-
const summary = summarizeInstallOutput(result.stderr) ?? summarizeInstallOutput(result.stdout);
|
|
1338
|
-
if (!summary) return `Install failed (${code})`;
|
|
1339
|
-
return `Install failed (${code}): ${summary}`;
|
|
1340
|
-
}
|
|
1341
|
-
function withWarnings(result, warnings) {
|
|
1342
|
-
if (warnings.length === 0) return result;
|
|
1343
|
-
return {
|
|
1344
|
-
...result,
|
|
1345
|
-
warnings: warnings.slice()
|
|
1346
|
-
};
|
|
1347
|
-
}
|
|
1348
|
-
function formatScanFindingDetail(rootDir, finding) {
|
|
1349
|
-
const relativePath = path.relative(rootDir, finding.file);
|
|
1350
|
-
const filePath = relativePath && relativePath !== "." && !relativePath.startsWith("..") ? relativePath : path.basename(finding.file);
|
|
1351
|
-
return `${finding.message} (${filePath}:${finding.line})`;
|
|
1352
|
-
}
|
|
1353
|
-
async function collectSkillInstallScanWarnings(entry) {
|
|
1354
|
-
const warnings = [];
|
|
1355
|
-
const skillName = entry.skill.name;
|
|
1356
|
-
const skillDir = path.resolve(entry.skill.baseDir);
|
|
1357
|
-
try {
|
|
1358
|
-
const summary = await scanDirectoryWithSummary(skillDir);
|
|
1359
|
-
if (summary.critical > 0) {
|
|
1360
|
-
const criticalDetails = summary.findings.filter((finding) => finding.severity === "critical").map((finding) => formatScanFindingDetail(skillDir, finding)).join("; ");
|
|
1361
|
-
warnings.push(`WARNING: Skill "${skillName}" contains dangerous code patterns: ${criticalDetails}`);
|
|
1362
|
-
} else if (summary.warn > 0) warnings.push(`Skill "${skillName}" has ${summary.warn} suspicious code pattern(s). Run "anima security audit --deep" for details.`);
|
|
1363
|
-
} catch (err) {
|
|
1364
|
-
warnings.push(`Skill "${skillName}" code safety scan failed (${String(err)}). Installation continues; run "anima security audit --deep" after install.`);
|
|
1365
|
-
}
|
|
1366
|
-
return warnings;
|
|
1367
|
-
}
|
|
1368
|
-
function resolveInstallId(spec, index) {
|
|
1369
|
-
return (spec.id ?? `${spec.kind}-${index}`).trim();
|
|
1370
|
-
}
|
|
1371
|
-
function findInstallSpec(entry, installId) {
|
|
1372
|
-
const specs = entry.metadata?.install ?? [];
|
|
1373
|
-
for (const [index, spec] of specs.entries()) if (resolveInstallId(spec, index) === installId) return spec;
|
|
1374
|
-
}
|
|
1375
|
-
function buildNodeInstallCommand(packageName, prefs) {
|
|
1376
|
-
switch (prefs.nodeManager) {
|
|
1377
|
-
case "pnpm": return [
|
|
1378
|
-
"pnpm",
|
|
1379
|
-
"add",
|
|
1380
|
-
"-g",
|
|
1381
|
-
"--ignore-scripts",
|
|
1382
|
-
packageName
|
|
1383
|
-
];
|
|
1384
|
-
case "yarn": return [
|
|
1385
|
-
"yarn",
|
|
1386
|
-
"global",
|
|
1387
|
-
"add",
|
|
1388
|
-
"--ignore-scripts",
|
|
1389
|
-
packageName
|
|
1390
|
-
];
|
|
1391
|
-
case "bun": return [
|
|
1392
|
-
"bun",
|
|
1393
|
-
"add",
|
|
1394
|
-
"-g",
|
|
1395
|
-
"--ignore-scripts",
|
|
1396
|
-
packageName
|
|
1397
|
-
];
|
|
1398
|
-
default: return [
|
|
1399
|
-
"npm",
|
|
1400
|
-
"install",
|
|
1401
|
-
"-g",
|
|
1402
|
-
"--ignore-scripts",
|
|
1403
|
-
packageName
|
|
1404
|
-
];
|
|
1405
|
-
}
|
|
1406
|
-
}
|
|
1407
|
-
function buildInstallCommand(spec, prefs) {
|
|
1408
|
-
switch (spec.kind) {
|
|
1409
|
-
case "brew":
|
|
1410
|
-
if (!spec.formula) return {
|
|
1411
|
-
argv: null,
|
|
1412
|
-
error: "missing brew formula"
|
|
1413
|
-
};
|
|
1414
|
-
return { argv: [
|
|
1415
|
-
"brew",
|
|
1416
|
-
"install",
|
|
1417
|
-
spec.formula
|
|
1418
|
-
] };
|
|
1419
|
-
case "node":
|
|
1420
|
-
if (!spec.package) return {
|
|
1421
|
-
argv: null,
|
|
1422
|
-
error: "missing node package"
|
|
1423
|
-
};
|
|
1424
|
-
return { argv: buildNodeInstallCommand(spec.package, prefs) };
|
|
1425
|
-
case "go":
|
|
1426
|
-
if (!spec.module) return {
|
|
1427
|
-
argv: null,
|
|
1428
|
-
error: "missing go module"
|
|
1429
|
-
};
|
|
1430
|
-
return { argv: [
|
|
1431
|
-
"go",
|
|
1432
|
-
"install",
|
|
1433
|
-
spec.module
|
|
1434
|
-
] };
|
|
1435
|
-
case "uv":
|
|
1436
|
-
if (!spec.package) return {
|
|
1437
|
-
argv: null,
|
|
1438
|
-
error: "missing uv package"
|
|
1439
|
-
};
|
|
1440
|
-
return { argv: [
|
|
1441
|
-
"uv",
|
|
1442
|
-
"tool",
|
|
1443
|
-
"install",
|
|
1444
|
-
spec.package
|
|
1445
|
-
] };
|
|
1446
|
-
case "download": return {
|
|
1447
|
-
argv: null,
|
|
1448
|
-
error: "download install handled separately"
|
|
1449
|
-
};
|
|
1450
|
-
default: return {
|
|
1451
|
-
argv: null,
|
|
1452
|
-
error: "unsupported installer"
|
|
1453
|
-
};
|
|
1454
|
-
}
|
|
1455
|
-
}
|
|
1456
|
-
function resolveDownloadTargetDir(entry, spec) {
|
|
1457
|
-
if (spec.targetDir?.trim()) return resolveUserPath(spec.targetDir);
|
|
1458
|
-
const key = resolveSkillKey(entry.skill, entry);
|
|
1459
|
-
return path.join(CONFIG_DIR, "tools", key);
|
|
1460
|
-
}
|
|
1461
|
-
function resolveArchiveType(spec, filename) {
|
|
1462
|
-
const explicit = spec.archive?.trim().toLowerCase();
|
|
1463
|
-
if (explicit) return explicit;
|
|
1464
|
-
const lower = filename.toLowerCase();
|
|
1465
|
-
if (lower.endsWith(".tar.gz") || lower.endsWith(".tgz")) return "tar.gz";
|
|
1466
|
-
if (lower.endsWith(".tar.bz2") || lower.endsWith(".tbz2")) return "tar.bz2";
|
|
1467
|
-
if (lower.endsWith(".zip")) return "zip";
|
|
1468
|
-
}
|
|
1469
|
-
function normalizeArchiveEntryPath(raw) {
|
|
1470
|
-
return raw.replaceAll("\\", "/");
|
|
1471
|
-
}
|
|
1472
|
-
function isWindowsDrivePath(p) {
|
|
1473
|
-
return /^[a-zA-Z]:[\\/]/.test(p);
|
|
1474
|
-
}
|
|
1475
|
-
function validateArchiveEntryPath(entryPath) {
|
|
1476
|
-
if (!entryPath || entryPath === "." || entryPath === "./") return;
|
|
1477
|
-
if (isWindowsDrivePath(entryPath)) throw new Error(`archive entry uses a drive path: ${entryPath}`);
|
|
1478
|
-
const normalized = path.posix.normalize(normalizeArchiveEntryPath(entryPath));
|
|
1479
|
-
if (normalized === ".." || normalized.startsWith("../")) throw new Error(`archive entry escapes targetDir: ${entryPath}`);
|
|
1480
|
-
if (path.posix.isAbsolute(normalized) || normalized.startsWith("//")) throw new Error(`archive entry is absolute: ${entryPath}`);
|
|
1481
|
-
}
|
|
1482
|
-
function resolveSafeBaseDir(rootDir) {
|
|
1483
|
-
const resolved = path.resolve(rootDir);
|
|
1484
|
-
return resolved.endsWith(path.sep) ? resolved : `${resolved}${path.sep}`;
|
|
1485
|
-
}
|
|
1486
|
-
function stripArchivePath(entryPath, stripComponents) {
|
|
1487
|
-
const raw = normalizeArchiveEntryPath(entryPath);
|
|
1488
|
-
if (!raw || raw === "." || raw === "./") return null;
|
|
1489
|
-
const parts = raw.split("/").filter((part) => part.length > 0 && part !== ".");
|
|
1490
|
-
const strip = Math.max(0, Math.floor(stripComponents));
|
|
1491
|
-
const stripped = strip === 0 ? parts.join("/") : parts.slice(strip).join("/");
|
|
1492
|
-
const result = path.posix.normalize(stripped);
|
|
1493
|
-
if (!result || result === "." || result === "./") return null;
|
|
1494
|
-
return result;
|
|
1495
|
-
}
|
|
1496
|
-
function validateExtractedPathWithinRoot(params) {
|
|
1497
|
-
const safeBase = resolveSafeBaseDir(params.rootDir);
|
|
1498
|
-
if (!path.resolve(params.rootDir, params.relPath).startsWith(safeBase)) throw new Error(`archive entry escapes targetDir: ${params.originalPath}`);
|
|
1499
|
-
}
|
|
1500
|
-
async function downloadFile(url, destPath, timeoutMs) {
|
|
1501
|
-
const { response, release } = await fetchWithSsrFGuard({
|
|
1502
|
-
url,
|
|
1503
|
-
timeoutMs: Math.max(1e3, timeoutMs)
|
|
1504
|
-
});
|
|
1505
|
-
try {
|
|
1506
|
-
if (!response.ok || !response.body) throw new Error(`Download failed (${response.status} ${response.statusText})`);
|
|
1507
|
-
await ensureDir(path.dirname(destPath));
|
|
1508
|
-
const file = fs.createWriteStream(destPath);
|
|
1509
|
-
const body = response.body;
|
|
1510
|
-
await pipeline(isNodeReadableStream(body) ? body : Readable.fromWeb(body), file);
|
|
1511
|
-
return { bytes: (await fs.promises.stat(destPath)).size };
|
|
1512
|
-
} finally {
|
|
1513
|
-
await release();
|
|
1514
|
-
}
|
|
1515
|
-
}
|
|
1516
|
-
async function extractArchive(params) {
|
|
1517
|
-
const { archivePath, archiveType, targetDir, stripComponents, timeoutMs } = params;
|
|
1518
|
-
const strip = typeof stripComponents === "number" && Number.isFinite(stripComponents) ? Math.max(0, Math.floor(stripComponents)) : 0;
|
|
1519
|
-
try {
|
|
1520
|
-
if (archiveType === "zip") {
|
|
1521
|
-
await extractArchive$1({
|
|
1522
|
-
archivePath,
|
|
1523
|
-
destDir: targetDir,
|
|
1524
|
-
timeoutMs,
|
|
1525
|
-
kind: "zip",
|
|
1526
|
-
stripComponents: strip
|
|
1527
|
-
});
|
|
1528
|
-
return {
|
|
1529
|
-
stdout: "",
|
|
1530
|
-
stderr: "",
|
|
1531
|
-
code: 0
|
|
1532
|
-
};
|
|
1533
|
-
}
|
|
1534
|
-
if (archiveType === "tar.gz") {
|
|
1535
|
-
await extractArchive$1({
|
|
1536
|
-
archivePath,
|
|
1537
|
-
destDir: targetDir,
|
|
1538
|
-
timeoutMs,
|
|
1539
|
-
kind: "tar",
|
|
1540
|
-
stripComponents: strip,
|
|
1541
|
-
tarGzip: true
|
|
1542
|
-
});
|
|
1543
|
-
return {
|
|
1544
|
-
stdout: "",
|
|
1545
|
-
stderr: "",
|
|
1546
|
-
code: 0
|
|
1547
|
-
};
|
|
1548
|
-
}
|
|
1549
|
-
if (archiveType === "tar.bz2") {
|
|
1550
|
-
if (!hasBinary("tar")) return {
|
|
1551
|
-
stdout: "",
|
|
1552
|
-
stderr: "tar not found on PATH",
|
|
1553
|
-
code: null
|
|
1554
|
-
};
|
|
1555
|
-
const listResult = await runCommandWithTimeout([
|
|
1556
|
-
"tar",
|
|
1557
|
-
"tf",
|
|
1558
|
-
archivePath
|
|
1559
|
-
], { timeoutMs });
|
|
1560
|
-
if (listResult.code !== 0) return {
|
|
1561
|
-
stdout: listResult.stdout,
|
|
1562
|
-
stderr: listResult.stderr || "tar list failed",
|
|
1563
|
-
code: listResult.code
|
|
1564
|
-
};
|
|
1565
|
-
const entries = listResult.stdout.split("\n").map((line) => line.trim()).filter(Boolean);
|
|
1566
|
-
const verboseResult = await runCommandWithTimeout([
|
|
1567
|
-
"tar",
|
|
1568
|
-
"tvf",
|
|
1569
|
-
archivePath
|
|
1570
|
-
], { timeoutMs });
|
|
1571
|
-
if (verboseResult.code !== 0) return {
|
|
1572
|
-
stdout: verboseResult.stdout,
|
|
1573
|
-
stderr: verboseResult.stderr || "tar verbose list failed",
|
|
1574
|
-
code: verboseResult.code
|
|
1575
|
-
};
|
|
1576
|
-
for (const line of verboseResult.stdout.split("\n")) {
|
|
1577
|
-
const trimmed = line.trim();
|
|
1578
|
-
if (!trimmed) continue;
|
|
1579
|
-
const typeChar = trimmed[0];
|
|
1580
|
-
if (typeChar === "l" || typeChar === "h" || trimmed.includes(" -> ")) return {
|
|
1581
|
-
stdout: verboseResult.stdout,
|
|
1582
|
-
stderr: "tar archive contains link entries; refusing to extract for safety",
|
|
1583
|
-
code: 1
|
|
1584
|
-
};
|
|
1585
|
-
}
|
|
1586
|
-
for (const entry of entries) {
|
|
1587
|
-
validateArchiveEntryPath(entry);
|
|
1588
|
-
const relPath = stripArchivePath(entry, strip);
|
|
1589
|
-
if (!relPath) continue;
|
|
1590
|
-
validateArchiveEntryPath(relPath);
|
|
1591
|
-
validateExtractedPathWithinRoot({
|
|
1592
|
-
rootDir: targetDir,
|
|
1593
|
-
relPath,
|
|
1594
|
-
originalPath: entry
|
|
1595
|
-
});
|
|
1596
|
-
}
|
|
1597
|
-
const argv = [
|
|
1598
|
-
"tar",
|
|
1599
|
-
"xf",
|
|
1600
|
-
archivePath,
|
|
1601
|
-
"-C",
|
|
1602
|
-
targetDir
|
|
1603
|
-
];
|
|
1604
|
-
if (strip > 0) argv.push("--strip-components", String(strip));
|
|
1605
|
-
return await runCommandWithTimeout(argv, { timeoutMs });
|
|
1606
|
-
}
|
|
1607
|
-
return {
|
|
1608
|
-
stdout: "",
|
|
1609
|
-
stderr: `unsupported archive type: ${archiveType}`,
|
|
1610
|
-
code: null
|
|
1611
|
-
};
|
|
1612
|
-
} catch (err) {
|
|
1613
|
-
return {
|
|
1614
|
-
stdout: "",
|
|
1615
|
-
stderr: err instanceof Error ? err.message : String(err),
|
|
1616
|
-
code: 1
|
|
1617
|
-
};
|
|
1618
|
-
}
|
|
1619
|
-
}
|
|
1620
|
-
async function installDownloadSpec(params) {
|
|
1621
|
-
const { entry, spec, timeoutMs } = params;
|
|
1622
|
-
const url = spec.url?.trim();
|
|
1623
|
-
if (!url) return {
|
|
1624
|
-
ok: false,
|
|
1625
|
-
message: "missing download url",
|
|
1626
|
-
stdout: "",
|
|
1627
|
-
stderr: "",
|
|
1628
|
-
code: null
|
|
1629
|
-
};
|
|
1630
|
-
let filename = "";
|
|
1631
|
-
try {
|
|
1632
|
-
const parsed = new URL(url);
|
|
1633
|
-
filename = path.basename(parsed.pathname);
|
|
1634
|
-
} catch {
|
|
1635
|
-
filename = path.basename(url);
|
|
1636
|
-
}
|
|
1637
|
-
if (!filename) filename = "download";
|
|
1638
|
-
const targetDir = resolveDownloadTargetDir(entry, spec);
|
|
1639
|
-
await ensureDir(targetDir);
|
|
1640
|
-
const archivePath = path.join(targetDir, filename);
|
|
1641
|
-
let downloaded = 0;
|
|
1642
|
-
try {
|
|
1643
|
-
downloaded = (await downloadFile(url, archivePath, timeoutMs)).bytes;
|
|
1644
|
-
} catch (err) {
|
|
1645
|
-
const message = err instanceof Error ? err.message : String(err);
|
|
1646
|
-
return {
|
|
1647
|
-
ok: false,
|
|
1648
|
-
message,
|
|
1649
|
-
stdout: "",
|
|
1650
|
-
stderr: message,
|
|
1651
|
-
code: null
|
|
1652
|
-
};
|
|
1653
|
-
}
|
|
1654
|
-
const archiveType = resolveArchiveType(spec, filename);
|
|
1655
|
-
if (!(spec.extract ?? Boolean(archiveType))) return {
|
|
1656
|
-
ok: true,
|
|
1657
|
-
message: `Downloaded to ${archivePath}`,
|
|
1658
|
-
stdout: `downloaded=${downloaded}`,
|
|
1659
|
-
stderr: "",
|
|
1660
|
-
code: 0
|
|
1661
|
-
};
|
|
1662
|
-
if (!archiveType) return {
|
|
1663
|
-
ok: false,
|
|
1664
|
-
message: "extract requested but archive type could not be detected",
|
|
1665
|
-
stdout: "",
|
|
1666
|
-
stderr: "",
|
|
1667
|
-
code: null
|
|
1668
|
-
};
|
|
1669
|
-
const extractResult = await extractArchive({
|
|
1670
|
-
archivePath,
|
|
1671
|
-
archiveType,
|
|
1672
|
-
targetDir,
|
|
1673
|
-
stripComponents: spec.stripComponents,
|
|
1674
|
-
timeoutMs
|
|
1675
|
-
});
|
|
1676
|
-
const success = extractResult.code === 0;
|
|
1677
|
-
return {
|
|
1678
|
-
ok: success,
|
|
1679
|
-
message: success ? `Downloaded and extracted to ${targetDir}` : formatInstallFailureMessage(extractResult),
|
|
1680
|
-
stdout: extractResult.stdout.trim(),
|
|
1681
|
-
stderr: extractResult.stderr.trim(),
|
|
1682
|
-
code: extractResult.code
|
|
1683
|
-
};
|
|
1684
|
-
}
|
|
1685
|
-
async function resolveBrewBinDir(timeoutMs, brewExe) {
|
|
1686
|
-
const exe = brewExe ?? (hasBinary("brew") ? "brew" : resolveBrewExecutable());
|
|
1687
|
-
if (!exe) return;
|
|
1688
|
-
const prefixResult = await runCommandWithTimeout([exe, "--prefix"], { timeoutMs: Math.min(timeoutMs, 3e4) });
|
|
1689
|
-
if (prefixResult.code === 0) {
|
|
1690
|
-
const prefix = prefixResult.stdout.trim();
|
|
1691
|
-
if (prefix) return path.join(prefix, "bin");
|
|
1692
|
-
}
|
|
1693
|
-
const envPrefix = process.env.HOMEBREW_PREFIX?.trim();
|
|
1694
|
-
if (envPrefix) return path.join(envPrefix, "bin");
|
|
1695
|
-
for (const candidate of ["/opt/homebrew/bin", "/usr/local/bin"]) try {
|
|
1696
|
-
if (fs.existsSync(candidate)) return candidate;
|
|
1697
|
-
} catch {}
|
|
1698
|
-
}
|
|
1699
|
-
async function installSkill(params) {
|
|
1700
|
-
const timeoutMs = Math.min(Math.max(params.timeoutMs ?? 3e5, 1e3), 9e5);
|
|
1701
|
-
const entry = loadWorkspaceSkillEntries(resolveUserPath(params.workspaceDir)).find((item) => item.skill.name === params.skillName);
|
|
1702
|
-
if (!entry) return {
|
|
1703
|
-
ok: false,
|
|
1704
|
-
message: `Skill not found: ${params.skillName}`,
|
|
1705
|
-
stdout: "",
|
|
1706
|
-
stderr: "",
|
|
1707
|
-
code: null
|
|
1708
|
-
};
|
|
1709
|
-
const spec = findInstallSpec(entry, params.installId);
|
|
1710
|
-
const warnings = await collectSkillInstallScanWarnings(entry);
|
|
1711
|
-
if (!spec) return withWarnings({
|
|
1712
|
-
ok: false,
|
|
1713
|
-
message: `Installer not found: ${params.installId}`,
|
|
1714
|
-
stdout: "",
|
|
1715
|
-
stderr: "",
|
|
1716
|
-
code: null
|
|
1717
|
-
}, warnings);
|
|
1718
|
-
if (spec.kind === "download") return withWarnings(await installDownloadSpec({
|
|
1719
|
-
entry,
|
|
1720
|
-
spec,
|
|
1721
|
-
timeoutMs
|
|
1722
|
-
}), warnings);
|
|
1723
|
-
const command = buildInstallCommand(spec, resolveSkillsInstallPreferences(params.config));
|
|
1724
|
-
if (command.error) return withWarnings({
|
|
1725
|
-
ok: false,
|
|
1726
|
-
message: command.error,
|
|
1727
|
-
stdout: "",
|
|
1728
|
-
stderr: "",
|
|
1729
|
-
code: null
|
|
1730
|
-
}, warnings);
|
|
1731
|
-
const brewExe = hasBinary("brew") ? "brew" : resolveBrewExecutable();
|
|
1732
|
-
if (spec.kind === "brew" && !brewExe) return withWarnings({
|
|
1733
|
-
ok: false,
|
|
1734
|
-
message: "brew not installed",
|
|
1735
|
-
stdout: "",
|
|
1736
|
-
stderr: "",
|
|
1737
|
-
code: null
|
|
1738
|
-
}, warnings);
|
|
1739
|
-
if (spec.kind === "uv" && !hasBinary("uv")) if (brewExe) {
|
|
1740
|
-
const brewResult = await runCommandWithTimeout([
|
|
1741
|
-
brewExe,
|
|
1742
|
-
"install",
|
|
1743
|
-
"uv"
|
|
1744
|
-
], { timeoutMs });
|
|
1745
|
-
if (brewResult.code !== 0) return withWarnings({
|
|
1746
|
-
ok: false,
|
|
1747
|
-
message: "Failed to install uv (brew)",
|
|
1748
|
-
stdout: brewResult.stdout.trim(),
|
|
1749
|
-
stderr: brewResult.stderr.trim(),
|
|
1750
|
-
code: brewResult.code
|
|
1751
|
-
}, warnings);
|
|
1752
|
-
} else return withWarnings({
|
|
1753
|
-
ok: false,
|
|
1754
|
-
message: "uv not installed (install via brew)",
|
|
1755
|
-
stdout: "",
|
|
1756
|
-
stderr: "",
|
|
1757
|
-
code: null
|
|
1758
|
-
}, warnings);
|
|
1759
|
-
if (!command.argv || command.argv.length === 0) return withWarnings({
|
|
1760
|
-
ok: false,
|
|
1761
|
-
message: "invalid install command",
|
|
1762
|
-
stdout: "",
|
|
1763
|
-
stderr: "",
|
|
1764
|
-
code: null
|
|
1765
|
-
}, warnings);
|
|
1766
|
-
if (spec.kind === "brew" && brewExe && command.argv[0] === "brew") command.argv[0] = brewExe;
|
|
1767
|
-
if (spec.kind === "go" && !hasBinary("go")) if (brewExe) {
|
|
1768
|
-
const brewResult = await runCommandWithTimeout([
|
|
1769
|
-
brewExe,
|
|
1770
|
-
"install",
|
|
1771
|
-
"go"
|
|
1772
|
-
], { timeoutMs });
|
|
1773
|
-
if (brewResult.code !== 0) return withWarnings({
|
|
1774
|
-
ok: false,
|
|
1775
|
-
message: "Failed to install go (brew)",
|
|
1776
|
-
stdout: brewResult.stdout.trim(),
|
|
1777
|
-
stderr: brewResult.stderr.trim(),
|
|
1778
|
-
code: brewResult.code
|
|
1779
|
-
}, warnings);
|
|
1780
|
-
} else return withWarnings({
|
|
1781
|
-
ok: false,
|
|
1782
|
-
message: "go not installed (install via brew)",
|
|
1783
|
-
stdout: "",
|
|
1784
|
-
stderr: "",
|
|
1785
|
-
code: null
|
|
1786
|
-
}, warnings);
|
|
1787
|
-
let env;
|
|
1788
|
-
if (spec.kind === "go" && brewExe) {
|
|
1789
|
-
const brewBin = await resolveBrewBinDir(timeoutMs, brewExe);
|
|
1790
|
-
if (brewBin) env = { GOBIN: brewBin };
|
|
1791
|
-
}
|
|
1792
|
-
const result = await (async () => {
|
|
1793
|
-
const argv = command.argv;
|
|
1794
|
-
if (!argv || argv.length === 0) return {
|
|
1795
|
-
code: null,
|
|
1796
|
-
stdout: "",
|
|
1797
|
-
stderr: "invalid install command"
|
|
1798
|
-
};
|
|
1799
|
-
try {
|
|
1800
|
-
return await runCommandWithTimeout(argv, {
|
|
1801
|
-
timeoutMs,
|
|
1802
|
-
env
|
|
1803
|
-
});
|
|
1804
|
-
} catch (err) {
|
|
1805
|
-
return {
|
|
1806
|
-
code: null,
|
|
1807
|
-
stdout: "",
|
|
1808
|
-
stderr: err instanceof Error ? err.message : String(err)
|
|
1809
|
-
};
|
|
1810
|
-
}
|
|
1811
|
-
})();
|
|
1812
|
-
const success = result.code === 0;
|
|
1813
|
-
return withWarnings({
|
|
1814
|
-
ok: success,
|
|
1815
|
-
message: success ? "Installed" : formatInstallFailureMessage(result),
|
|
1816
|
-
stdout: result.stdout.trim(),
|
|
1817
|
-
stderr: result.stderr.trim(),
|
|
1818
|
-
code: result.code
|
|
1819
|
-
}, warnings);
|
|
1820
|
-
}
|
|
1821
|
-
|
|
1822
|
-
//#endregion
|
|
1823
|
-
//#region src/commands/onboard-skills.ts
|
|
1824
|
-
function summarizeInstallFailure(message) {
|
|
1825
|
-
const cleaned = message.replace(/^Install failed(?:\s*\([^)]*\))?\s*:?\s*/i, "").trim();
|
|
1826
|
-
if (!cleaned) return;
|
|
1827
|
-
const maxLen = 140;
|
|
1828
|
-
return cleaned.length > maxLen ? `${cleaned.slice(0, maxLen - 1)}…` : cleaned;
|
|
1829
|
-
}
|
|
1830
|
-
function formatSkillHint(skill) {
|
|
1831
|
-
const desc = skill.description?.trim();
|
|
1832
|
-
const installLabel = skill.install[0]?.label?.trim();
|
|
1833
|
-
const combined = desc && installLabel ? `${desc} — ${installLabel}` : desc || installLabel;
|
|
1834
|
-
if (!combined) return "install";
|
|
1835
|
-
const maxLen = 90;
|
|
1836
|
-
return combined.length > maxLen ? `${combined.slice(0, maxLen - 1)}…` : combined;
|
|
1837
|
-
}
|
|
1838
|
-
function upsertSkillEntry(cfg, skillKey, patch) {
|
|
1839
|
-
const entries = { ...cfg.skills?.entries };
|
|
1840
|
-
entries[skillKey] = {
|
|
1841
|
-
...entries[skillKey] ?? {},
|
|
1842
|
-
...patch
|
|
1843
|
-
};
|
|
1844
|
-
return {
|
|
1845
|
-
...cfg,
|
|
1846
|
-
skills: {
|
|
1847
|
-
...cfg.skills,
|
|
1848
|
-
entries
|
|
1849
|
-
}
|
|
1850
|
-
};
|
|
1851
|
-
}
|
|
1852
|
-
async function setupSkills(cfg, workspaceDir, runtime, prompter) {
|
|
1853
|
-
const report = buildWorkspaceSkillStatus(workspaceDir, { config: cfg });
|
|
1854
|
-
const eligible = report.skills.filter((s) => s.eligible);
|
|
1855
|
-
const unsupportedOs = report.skills.filter((s) => !s.disabled && !s.blockedByAllowlist && s.missing.os.length > 0);
|
|
1856
|
-
const missing = report.skills.filter((s) => !s.eligible && !s.disabled && !s.blockedByAllowlist && s.missing.os.length === 0);
|
|
1857
|
-
const blocked = report.skills.filter((s) => s.blockedByAllowlist);
|
|
1858
|
-
await prompter.note([
|
|
1859
|
-
`Eligible: ${eligible.length}`,
|
|
1860
|
-
`Missing requirements: ${missing.length}`,
|
|
1861
|
-
`Unsupported on this OS: ${unsupportedOs.length}`,
|
|
1862
|
-
`Blocked by allowlist: ${blocked.length}`
|
|
1863
|
-
].join("\n"), "Skills status");
|
|
1864
|
-
if (!await prompter.confirm({
|
|
1865
|
-
message: "Configure skills now? (recommended)",
|
|
1866
|
-
initialValue: true
|
|
1867
|
-
})) return cfg;
|
|
1868
|
-
const installable = missing.filter((skill) => skill.install.length > 0 && skill.missing.bins.length > 0);
|
|
1869
|
-
let next = cfg;
|
|
1870
|
-
if (installable.length > 0) {
|
|
1871
|
-
const selected = (await prompter.multiselect({
|
|
1872
|
-
message: "Install missing skill dependencies",
|
|
1873
|
-
options: [{
|
|
1874
|
-
value: "__skip__",
|
|
1875
|
-
label: "Skip for now",
|
|
1876
|
-
hint: "Continue without installing dependencies"
|
|
1877
|
-
}, ...installable.map((skill) => ({
|
|
1878
|
-
value: skill.name,
|
|
1879
|
-
label: `${skill.emoji ?? "🧩"} ${skill.name}`,
|
|
1880
|
-
hint: formatSkillHint(skill)
|
|
1881
|
-
}))]
|
|
1882
|
-
})).filter((name) => name !== "__skip__");
|
|
1883
|
-
const selectedSkills = selected.map((name) => installable.find((s) => s.name === name)).filter((item) => Boolean(item));
|
|
1884
|
-
if (process.platform !== "win32" && selectedSkills.some((skill) => skill.install.some((option) => option.kind === "brew")) && !await detectBinary("brew")) {
|
|
1885
|
-
await prompter.note(["Many skill dependencies are shipped via Homebrew.", "Without brew, you'll need to build from source or download releases manually."].join("\n"), "Homebrew recommended");
|
|
1886
|
-
if (await prompter.confirm({
|
|
1887
|
-
message: "Show Homebrew install command?",
|
|
1888
|
-
initialValue: true
|
|
1889
|
-
})) await prompter.note(["Run:", "/bin/bash -c \"$(curl -fsSL https://raw.githubusercontent.com/Homebrew/install/HEAD/install.sh)\""].join("\n"), "Homebrew install");
|
|
1890
|
-
}
|
|
1891
|
-
if (selectedSkills.some((skill) => skill.install.some((option) => option.kind === "node"))) {
|
|
1892
|
-
const nodeManager = await prompter.select({
|
|
1893
|
-
message: "Preferred node manager for skill installs",
|
|
1894
|
-
options: resolveNodeManagerOptions()
|
|
1895
|
-
});
|
|
1896
|
-
next = {
|
|
1897
|
-
...next,
|
|
1898
|
-
skills: {
|
|
1899
|
-
...next.skills,
|
|
1900
|
-
install: {
|
|
1901
|
-
...next.skills?.install,
|
|
1902
|
-
nodeManager
|
|
1903
|
-
}
|
|
1904
|
-
}
|
|
1905
|
-
};
|
|
1906
|
-
}
|
|
1907
|
-
for (const name of selected) {
|
|
1908
|
-
const target = installable.find((s) => s.name === name);
|
|
1909
|
-
if (!target || target.install.length === 0) continue;
|
|
1910
|
-
const installId = target.install[0]?.id;
|
|
1911
|
-
if (!installId) continue;
|
|
1912
|
-
const spin = prompter.progress(`Installing ${name}…`);
|
|
1913
|
-
const result = await installSkill({
|
|
1914
|
-
workspaceDir,
|
|
1915
|
-
skillName: target.name,
|
|
1916
|
-
installId,
|
|
1917
|
-
config: next
|
|
1918
|
-
});
|
|
1919
|
-
const warnings = result.warnings ?? [];
|
|
1920
|
-
if (result.ok) {
|
|
1921
|
-
spin.stop(warnings.length > 0 ? `Installed ${name} (with warnings)` : `Installed ${name}`);
|
|
1922
|
-
for (const warning of warnings) runtime.log(warning);
|
|
1923
|
-
continue;
|
|
1924
|
-
}
|
|
1925
|
-
const code = result.code == null ? "" : ` (exit ${result.code})`;
|
|
1926
|
-
const detail = summarizeInstallFailure(result.message);
|
|
1927
|
-
spin.stop(`Install failed: ${name}${code}${detail ? ` — ${detail}` : ""}`);
|
|
1928
|
-
for (const warning of warnings) runtime.log(warning);
|
|
1929
|
-
if (result.stderr) runtime.log(result.stderr.trim());
|
|
1930
|
-
else if (result.stdout) runtime.log(result.stdout.trim());
|
|
1931
|
-
runtime.log(`Tip: run \`${formatCliCommand("anima doctor")}\` to review skills + requirements.`);
|
|
1932
|
-
runtime.log("Docs: https://docs.anima.ai/skills");
|
|
1933
|
-
}
|
|
1934
|
-
}
|
|
1935
|
-
for (const skill of missing) {
|
|
1936
|
-
if (!skill.primaryEnv || skill.missing.env.length === 0) continue;
|
|
1937
|
-
if (!await prompter.confirm({
|
|
1938
|
-
message: `Set ${skill.primaryEnv} for ${skill.name}?`,
|
|
1939
|
-
initialValue: false
|
|
1940
|
-
})) continue;
|
|
1941
|
-
const apiKey = String(await prompter.text({
|
|
1942
|
-
message: `Enter ${skill.primaryEnv}`,
|
|
1943
|
-
validate: (value) => value?.trim() ? void 0 : "Required"
|
|
1944
|
-
}));
|
|
1945
|
-
next = upsertSkillEntry(next, skill.skillKey, { apiKey: normalizeSecretInput(apiKey) });
|
|
1946
|
-
}
|
|
1947
|
-
return next;
|
|
1948
|
-
}
|
|
1949
|
-
|
|
1950
|
-
//#endregion
|
|
1951
|
-
//#region src/shared/net/ipv4.ts
|
|
1952
|
-
function validateIPv4AddressInput(value) {
|
|
1953
|
-
if (!value) return "IP address is required for custom bind mode";
|
|
1954
|
-
const parts = value.trim().split(".");
|
|
1955
|
-
if (parts.length !== 4) return "Invalid IPv4 address (e.g., 192.168.1.100)";
|
|
1956
|
-
if (parts.every((part) => {
|
|
1957
|
-
const n = parseInt(part, 10);
|
|
1958
|
-
return !Number.isNaN(n) && n >= 0 && n <= 255 && part === String(n);
|
|
1959
|
-
})) return;
|
|
1960
|
-
return "Invalid IPv4 address (each octet must be 0-255)";
|
|
1961
|
-
}
|
|
1962
|
-
|
|
1963
|
-
//#endregion
|
|
1964
|
-
export { CustomApiError as a, promptCustomApiConfig as c, applyModelFallbacksFromSelection as d, applyPrimaryModel as f, discoverGatewayBeacons as h, promptRemoteGatewayConfig as i, resolveCustomProviderId as l, promptModelAllowlist as m, setupSkills as n, applyCustomApiConfig as o, promptDefaultModel as p, installSkill as r, parseNonInteractiveCustomApiFlags as s, validateIPv4AddressInput as t, applyModelAllowlist as u };
|