remoteclaw 0.1.0-next.049f396 → 0.1.0-next.05abcca
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 +11 -9
- package/dist/accounts-79XhjwAj.js +32 -0
- package/dist/accounts-B1M3fOxL.js +272 -0
- package/dist/accounts-BwbvnKsW.js +205 -0
- package/dist/accounts-CIVjmTg9.js +270 -0
- package/dist/accounts-D1awQXKu.js +36 -0
- package/dist/accounts-DHkGVGUR.js +36 -0
- package/dist/accounts-P7cmIXUM.js +206 -0
- package/dist/accounts-XFgBY644.js +47 -0
- package/dist/accounts-_ZuNC5bz.js +47 -0
- package/dist/ack-reactions-BGJ9Vigf.js +621 -0
- package/dist/ack-reactions-Diu9O24z.js +621 -0
- package/dist/acp-cli-BwZ-va2P.js +1316 -0
- package/dist/acp-cli-eVKByz-j.js +1311 -0
- package/dist/active-listener--jrUO-8L.js +37 -0
- package/dist/active-listener-C7SyMcNY.js +37 -0
- package/dist/agent-BAxK2KQW.js +688 -0
- package/dist/agent-Dd5Yfhmq.js +687 -0
- package/dist/agent-helpers-5F0tdxud.js +400 -0
- package/dist/agent-helpers-Bs2nBXeI.js +400 -0
- package/dist/agent-scope-BA1HP4K6.js +114 -0
- package/dist/agent-scope-CAQLm3LP.js +116 -0
- package/dist/agents-D--9DD91.js +754 -0
- package/dist/agents.config-CmyzLYqW.js +116 -0
- package/dist/agents.config-DerBqRzk.js +116 -0
- package/dist/ansi-DtaiOnt1.js +107 -0
- package/dist/audio-ClIuKwkl.js +43 -0
- package/dist/audio-DqlIYYTb.js +43 -0
- package/dist/audit-Cn0cNCE4.js +3114 -0
- package/dist/audit-DXY4NHBC.js +3114 -0
- package/dist/auth-B-QK8JhI.js +315 -0
- package/dist/auth-C1zx1O24.js +314 -0
- package/dist/auth-DDmNYVMW.js +448 -0
- package/dist/auth-DH1wEw0w.js +448 -0
- package/dist/banner-CBWZhANO.js +294 -0
- package/dist/binaries-CYwLdubd.js +13 -0
- package/dist/bindings-DFAFatwT.js +69 -0
- package/dist/bindings-GUKIzFCp.js +69 -0
- package/dist/bonjour-discovery-AQMJqY4V.js +378 -0
- package/dist/bonjour-discovery-BLcPWHFJ.js +378 -0
- package/dist/boot/handler.js +41 -84
- package/dist/browser-cli-8Dv5ogFT.js +1690 -0
- package/dist/browser-cli-wNLo8SOy.js +1694 -0
- package/dist/build-info.json +3 -3
- package/dist/call-BTHzKFbN.js +518 -0
- package/dist/call-D_NchaCs.js +517 -0
- package/dist/canvas-host/a2ui/.bundle.hash +1 -1
- package/dist/catalog-DgpN5jxU.js +186 -0
- package/dist/catalog-k056Nh93.js +186 -0
- package/dist/channel-account-context-BHIy71Yh.js +133 -0
- package/dist/channel-account-context-DXU_-EkJ.js +133 -0
- package/dist/channel-activity-BatlvP_U.js +292 -0
- package/dist/channel-activity-BhT7NQ_v.js +94 -0
- package/dist/channel-activity-CvjEwpJz.js +94 -0
- package/dist/channel-options-BCccA2WC.js +32 -0
- package/dist/channel-options-VPR_pNyS.js +33 -0
- package/dist/channel-selection-AH6_y6RS.js +51 -0
- package/dist/channel-selection-ovohyJQZ.js +51 -0
- package/dist/channel-web-APDaQ_wp.js +2134 -0
- package/dist/channel-web-BW_YuNlT.js +2132 -0
- package/dist/channels-cli-DVsZyaU5.js +1436 -0
- package/dist/channels-cli-ubrg5vcL.js +1440 -0
- package/dist/channels-status-issues-BbYNzwLp.js +18 -0
- package/dist/channels-status-issues-DRybAijg.js +18 -0
- package/dist/chat-envelope-AJFUAuBM.js +248 -0
- package/dist/chat-envelope-BrfcPlDM.js +248 -0
- package/dist/chrome-Bv2UtAMQ.js +1732 -0
- package/dist/chrome-C6Vc_7su.js +1733 -0
- package/dist/chunk-BAMyFYtF.js +341 -0
- package/dist/chunk-BzVoFUZL.js +341 -0
- package/dist/clack-prompter-C6mBTOzE.js +122 -0
- package/dist/clack-prompter-DKcYqv3o.js +121 -0
- package/dist/cleanup-utils-Cb-leJcy.js +94 -0
- package/dist/cli/daemon-cli.js +1 -1
- package/dist/cli-Cs1n6-eD.js +135 -0
- package/dist/cli-Di3p1tLN.js +131 -0
- package/dist/client-B6h7bgbF.js +2311 -0
- package/dist/client-CMtdm9Ii.js +2311 -0
- package/dist/clipboard-A06eV_5C.js +31 -0
- package/dist/clipboard-DQBl3coj.js +31 -0
- package/dist/command-format-BiiNHkWG.js +18 -0
- package/dist/command-format-Dntg_tnC.js +32 -0
- package/dist/command-logger/handler.js +1 -1
- package/dist/command-registry-CCAvdWh2.js +215 -0
- package/dist/commands-D93TXYhv.js +41 -0
- package/dist/commands-UD7V7QC9.js +41 -0
- package/dist/commands-registry-CCbTtSSK.js +891 -0
- package/dist/commands-registry-De8JhZLG.js +890 -0
- package/dist/common-D4fL3S2m.js +156 -0
- package/dist/common-DXNisGxw.js +156 -0
- package/dist/completion-cli-CLo-r-UP.js +452 -0
- package/dist/completion-cli-D4ajG3yt.js +452 -0
- package/dist/config-BTH7fB_v.js +3345 -0
- package/dist/config-DwuBnd6D.js +3347 -0
- package/dist/config-cli-D0D1LSNt.js +243 -0
- package/dist/config-cli-tWsFNKQM.js +247 -0
- package/dist/config-guard-BcT7soTj.js +92 -0
- package/dist/config-guard-Bqak3bDc.js +75 -0
- package/dist/config-validation-CHEjSJ5K.js +18 -0
- package/dist/config-validation-CvgqLhyG.js +18 -0
- package/dist/configure-CK_0tFJG.js +889 -0
- package/dist/configure-D0z0kE-B.js +891 -0
- package/dist/constants-BBVTjb1j.js +75 -0
- package/dist/constants-PMRtHBHU.js +75 -0
- package/dist/control-auth-DrGYtMJM.js +397 -0
- package/dist/control-auth-KY4Qdr2I.js +397 -0
- package/dist/control-ui/assets/index-DdiU_ccM.css +1 -0
- package/dist/control-ui/assets/index-kVUYi64u.js +7723 -0
- package/dist/control-ui/assets/index-kVUYi64u.js.map +1 -0
- package/dist/control-ui/index.html +2 -2
- package/dist/control-ui-assets-DO1L6M0S.js +186 -0
- package/dist/control-ui-assets-S_TLo6Fs.js +186 -0
- package/dist/conversation-label-CDH4rKMG.js +36 -0
- package/dist/conversation-label-CMOfgCVl.js +36 -0
- package/dist/cron-cli-C7h_hLHu.js +495 -0
- package/dist/cron-cli-DTNg0Uvl.js +499 -0
- package/dist/daemon-cli-BlJS9zWM.js +737 -0
- package/dist/daemon-cli-Cfc1yszp.js +735 -0
- package/dist/daemon-cli.js +174 -1167
- package/dist/daemon-install-BbBLuLWg.js +60 -0
- package/dist/daemon-install-WEBvqVOj.js +56 -0
- package/dist/daemon-install-helpers-BVtPC2TK.js +504 -0
- package/dist/daemon-install-helpers-DVr51zvE.js +504 -0
- package/dist/deliver-EB272zWh.js +481 -0
- package/dist/deliver-iGD_woru.js +481 -0
- package/dist/delivery-queue-BDvalA10.js +244 -0
- package/dist/delivery-queue-BimvYz5E.js +244 -0
- package/dist/devices-cli-BXCOsNFc.js +323 -0
- package/dist/devices-cli-CHGdYfrz.js +319 -0
- package/dist/diagnostics-BzzhTQzK.js +35 -0
- package/dist/diagnostics-DILtxtcE.js +35 -0
- package/dist/directory-cli-COS40yI9.js +221 -0
- package/dist/directory-cli-Cb5j1JTC.js +225 -0
- package/dist/dispatcher-BUqxh_mA.js +174 -0
- package/dist/dispatcher-By-KZRWZ.js +173 -0
- package/dist/dm-policy-shared-BCp9_z3w.js +22 -0
- package/dist/dm-policy-shared-DgeKqjOu.js +22 -0
- package/dist/dns-cli-B8yyXB2N.js +203 -0
- package/dist/dns-cli-DAkTk-gM.js +199 -0
- package/dist/dock-B0bIIDS3.js +906 -0
- package/dist/dock-C3PzQ6CS.js +907 -0
- package/dist/doctor-completion-BXGEqLhU.js +92 -0
- package/dist/doctor-completion-D_mNzioP.js +92 -0
- package/dist/doctor-config-flow-BDDsR2J1.js +978 -0
- package/dist/doctor-config-flow-CwFFRUic.js +979 -0
- package/dist/enable-C3I9dWel.js +59 -0
- package/dist/enable-DnwKeWnR.js +59 -0
- package/dist/entry.js +75 -21
- package/dist/env-DyyqmxSM.js +60 -0
- package/dist/env-vars-CD2_baIP.js +43 -0
- package/dist/env-vars-a7S70ba7.js +43 -0
- package/dist/errors-0dfGxeYQ.js +35 -0
- package/dist/errors-C1kDByVU.js +35 -0
- package/dist/exec-CAk1dxq_.js +164 -0
- package/dist/exec-epNpA1aU.js +164 -0
- package/dist/export-html/template.css +0 -36
- package/dist/export-html/template.js +1 -32
- package/dist/extensionAPI.js +1765 -1590
- package/dist/fetch-BMQq41sB.js +281 -0
- package/dist/fetch-Cky99wYB.js +281 -0
- package/dist/fetch-D3tw4B4n.js +67 -0
- package/dist/fetch-DTsU2XnC.js +67 -0
- package/dist/fetch-Dgm9ZHFm.js +67 -0
- package/dist/file-lock-DWH0TfVu.js +107 -0
- package/dist/file-lock-DXW9h9ek.js +107 -0
- package/dist/fs-safe-BjSd07M4.js +115 -0
- package/dist/fs-safe-aWIhCWlb.js +125 -0
- package/dist/gateway-cli-C4y4H61g.js +24546 -0
- package/dist/gateway-cli-CtFr42NV.js +24550 -0
- package/dist/gateway-rpc-B92CH0D3.js +28 -0
- package/dist/gateway-rpc-DZNlWapO.js +28 -0
- package/dist/gmail-setup-utils-CKyh29_R.js +422 -0
- package/dist/gmail-setup-utils-DquflkMR.js +423 -0
- package/dist/health-BYl7T-4m.js +1417 -0
- package/dist/health-DdviISKg.js +1414 -0
- package/dist/health-format-BE5TK5bs.js +28 -0
- package/dist/heartbeat-visibility-BO3iRpB6.js +125 -0
- package/dist/heartbeat-visibility-Cwp4TrTv.js +125 -0
- package/dist/help-format-D3JhWp1E.js +17 -0
- package/dist/helpers-DAEoFkbn.js +10 -0
- package/dist/helpers-ndPQWl6m.js +10 -0
- package/dist/hook-runner-global-C1thol1d.js +527 -0
- package/dist/hooks-cli-BKS9uZ0H.js +1221 -0
- package/dist/hooks-cli-FLWcCr9q.js +1217 -0
- package/dist/host-env-security-BGibnCbS.js +106 -0
- package/dist/host-env-security-axRnIi8d.js +106 -0
- package/dist/image-ops-CX41n0v5.js +354 -0
- package/dist/image-ops-DSL3eFfQ.js +354 -0
- package/dist/import-BSFgt760.js +604 -0
- package/dist/import-Da1CHJJg.js +606 -0
- package/dist/inbound-context-BLy-G2Eq.js +68 -0
- package/dist/inbound-context-a5bzQvRt.js +68 -0
- package/dist/index.js +137 -108
- package/dist/inspect-BEpFbi0c.js +286 -0
- package/dist/inspect-BeNNpWna.js +286 -0
- package/dist/installs-CH7Qq_m_.js +319 -0
- package/dist/installs-CcM8H2YA.js +319 -0
- package/dist/ipv4-DNo9AFDu.js +46 -0
- package/dist/ipv4-VfoVR5uR.js +46 -0
- package/dist/ir-BPwP8hIc.js +972 -0
- package/dist/json-files-BI20PLIm.js +46 -0
- package/dist/lifecycle-core-5Zxqwa6V.js +476 -0
- package/dist/lifecycle-core-C1bGeLby.js +474 -0
- package/dist/links-CtGBIrG8.js +15 -0
- package/dist/loader-BoP3JA-r.js +22411 -0
- package/dist/loader-DXbpue-L.js +22414 -0
- package/dist/logger-ASsO5Nz-.js +49 -0
- package/dist/logging-Cd9y2AdQ.js +20 -0
- package/dist/logging-DRwtiLIS.js +1 -0
- package/dist/logging-fywhKCmE.js +1 -0
- package/dist/login-B2UXzgaB.js +61 -0
- package/dist/login-BEFL3xY9.js +62 -0
- package/dist/login-qr-C7wAz2fe.js +329 -0
- package/dist/login-qr-DWpUP1Ud.js +325 -0
- package/dist/logs-cli-CAcd-pXA.js +240 -0
- package/dist/logs-cli-D7Bzarht.js +236 -0
- package/dist/markdown-tables-BBNUZp4n.js +29 -0
- package/dist/markdown-tables-NgPcfXoF.js +29 -0
- package/dist/media-4-qOIjO-.js +971 -0
- package/dist/media-DTwJhAbE.js +9481 -0
- package/dist/message-action-names-BsNTjuBE.js +2520 -0
- package/dist/message-action-names-ocKcq8_3.js +2520 -0
- package/dist/message-channel-CtcVHawF.js +91 -0
- package/dist/message-channel-tuc9CdEw.js +91 -0
- package/dist/mime-CAqaK3kp.js +146 -0
- package/dist/mime-ViuhRuMM.js +146 -0
- package/dist/net-DSkFMHJ8.js +225 -0
- package/dist/net-DTqfFYzt.js +225 -0
- package/dist/node-cli-BeXU67eQ.js +1458 -0
- package/dist/node-cli-i2aCtnmM.js +1462 -0
- package/dist/node-service-RyMlWp8N.js +67 -0
- package/dist/node-service-TL9b6Qfz.js +67 -0
- package/dist/nodes-cli-CtqnXBMD.js +1346 -0
- package/dist/nodes-cli-DgQU3LrG.js +1350 -0
- package/dist/nodes-screen-B7HJugJ0.js +250 -0
- package/dist/nodes-screen-nCRd71Mk.js +250 -0
- package/dist/note-B6142LyJ.js +92 -0
- package/dist/note-D-EI0czq.js +92 -0
- package/dist/npm-registry-spec-PPyRXSpx.js +786 -0
- package/dist/npm-registry-spec-uUmDWe6v.js +786 -0
- package/dist/npm-resolution-BC1LqCm2.js +86 -0
- package/dist/npm-resolution-DhlhUmRF.js +86 -0
- package/dist/onboard-CGpC2ecw.js +647 -0
- package/dist/onboard-auth-cNtb3FTP.js +211 -0
- package/dist/onboard-auth-gwz-0mZ6.js +207 -0
- package/dist/onboard-channels-CXjJYzHC.js +2548 -0
- package/dist/onboard-channels-vtaIxYml.js +2549 -0
- package/dist/onboard-config-DOmXYEvJ.js +39 -0
- package/dist/onboard-config-JmR21VYa.js +39 -0
- package/dist/onboard-helpers-8afRV_Tm.js +364 -0
- package/dist/onboard-helpers-DTRrJLj-.js +363 -0
- package/dist/onboard-jLzfwoPx.js +649 -0
- package/dist/onboard-remote-CFkvVAYg.js +127 -0
- package/dist/onboard-remote-JfBnmK70.js +127 -0
- package/dist/onboarding-Dt0LKvZn.js +586 -0
- package/dist/onboarding-gMKlA2bP.js +588 -0
- package/dist/onboarding.finalize-BDML6Jx7.js +403 -0
- package/dist/onboarding.finalize-D850VgMA.js +405 -0
- package/dist/onboarding.gateway-config-DolBTXWT.js +196 -0
- package/dist/onboarding.gateway-config-rJkIamlG.js +202 -0
- package/dist/outbound-CPMaDtgC.js +220 -0
- package/dist/outbound-CYSuCMiW.js +221 -0
- package/dist/outbound-attachment-Ci02LXoq.js +18 -0
- package/dist/outbound-attachment-CqZ7Qc_o.js +18 -0
- package/dist/outbound-attachment-CuqWdsdV.js +18 -0
- package/dist/pairing-cli-B9JKvvST.js +126 -0
- package/dist/pairing-cli-C4HrfIHe.js +130 -0
- package/dist/pairing-labels-CBmGQ31P.js +9 -0
- package/dist/pairing-labels-D0xwC7Xb.js +9 -0
- package/dist/pairing-store-BoF0g-iN.js +459 -0
- package/dist/pairing-store-CseXj-5p.js +460 -0
- package/dist/path-env-CPZbb7me.js +89 -0
- package/dist/path-env-GTM4HXCN.js +89 -0
- package/dist/path-safety-BFE0XmGC.js +14 -0
- package/dist/path-safety-BJ8ge6Ho.js +14 -0
- package/dist/paths-DHuXVC00.js +229 -0
- package/dist/plugin-auto-enable-B_9J1XED.js +302 -0
- package/dist/plugin-auto-enable-DghjlFCL.js +301 -0
- package/dist/plugin-registry-68h2T8vi.js +33 -0
- package/dist/plugin-registry-BitdVPb4.js +33 -0
- package/dist/plugin-sdk/agents/agent-helpers.d.ts +0 -1
- package/dist/plugin-sdk/agents/agent-scope.d.ts +11 -0
- package/dist/plugin-sdk/agents/agent-types.d.ts +1 -6
- package/dist/plugin-sdk/agents/agent-utils.d.ts +0 -14
- package/dist/plugin-sdk/agents/provider-utils.d.ts +0 -1
- package/dist/plugin-sdk/agents/subagent-registry.store.d.ts +0 -1
- package/dist/plugin-sdk/agents/subagent-spawn.d.ts +0 -1
- package/dist/plugin-sdk/agents/tools/sessions-helpers.d.ts +0 -1
- package/dist/plugin-sdk/auth/constants.d.ts +15 -0
- package/dist/plugin-sdk/auth/display.d.ts +7 -0
- package/dist/plugin-sdk/auth/doctor.d.ts +8 -0
- package/dist/plugin-sdk/auth/env-injection.d.ts +38 -0
- package/dist/plugin-sdk/auth/index.d.ts +10 -0
- package/dist/plugin-sdk/auth/oauth.d.ts +13 -0
- package/dist/plugin-sdk/auth/order.d.ts +8 -0
- package/dist/plugin-sdk/auth/paths.d.ts +3 -0
- package/dist/plugin-sdk/auth/profiles.d.ts +11 -0
- package/dist/plugin-sdk/auth/provider-auth.d.ts +32 -0
- package/dist/plugin-sdk/auth/store.d.ts +7 -0
- package/dist/plugin-sdk/auth/types.d.ts +45 -0
- package/dist/plugin-sdk/auth/usage.d.ts +80 -0
- package/dist/plugin-sdk/auto-reply/reply/agent-runner-execution.d.ts +0 -1
- package/dist/plugin-sdk/auto-reply/reply/agent-runner-utils.d.ts +3 -36
- package/dist/plugin-sdk/auto-reply/reply/commands-status.d.ts +1 -7
- package/dist/plugin-sdk/auto-reply/reply/commands-subagents/shared.d.ts +1 -1
- package/dist/plugin-sdk/auto-reply/reply/commands-types.d.ts +1 -13
- package/dist/plugin-sdk/auto-reply/reply/directive-handling.levels.d.ts +1 -10
- package/dist/plugin-sdk/auto-reply/reply/directive-handling.params.d.ts +1 -11
- package/dist/plugin-sdk/auto-reply/reply/directive-handling.parse.d.ts +1 -29
- package/dist/plugin-sdk/auto-reply/reply/directive-handling.persist.d.ts +0 -3
- package/dist/plugin-sdk/auto-reply/reply/directive-handling.shared.d.ts +0 -25
- package/dist/plugin-sdk/auto-reply/reply/directives.d.ts +3 -42
- package/dist/plugin-sdk/auto-reply/reply/get-reply-directives-apply.d.ts +0 -9
- package/dist/plugin-sdk/auto-reply/reply/get-reply-directives-utils.d.ts +0 -1
- package/dist/plugin-sdk/auto-reply/reply/get-reply-directives.d.ts +1 -20
- package/dist/plugin-sdk/auto-reply/reply/get-reply-inline-actions.d.ts +1 -12
- package/dist/plugin-sdk/auto-reply/reply/get-reply-run.d.ts +1 -15
- package/dist/plugin-sdk/auto-reply/reply/queue/types.d.ts +1 -17
- package/dist/plugin-sdk/auto-reply/reply/response-prefix-template.d.ts +4 -6
- package/dist/plugin-sdk/auto-reply/reply/session-run-accounting.d.ts +0 -7
- package/dist/plugin-sdk/auto-reply/reply/session-updates.d.ts +0 -10
- package/dist/plugin-sdk/auto-reply/reply.d.ts +1 -1
- package/dist/plugin-sdk/auto-reply/status.d.ts +3 -12
- package/dist/plugin-sdk/auto-reply/templating.d.ts +0 -4
- package/dist/plugin-sdk/auto-reply/thinking.d.ts +0 -15
- package/dist/plugin-sdk/auto-reply/types.d.ts +1 -2
- package/dist/plugin-sdk/channels/dock.d.ts +1 -2
- package/dist/plugin-sdk/channels/plugins/types.adapters.d.ts +0 -6
- package/dist/plugin-sdk/channels/plugins/types.core.d.ts +1 -0
- package/dist/plugin-sdk/channels/plugins/types.d.ts +1 -1
- package/dist/plugin-sdk/channels/plugins/types.plugin.d.ts +1 -2
- package/dist/plugin-sdk/channels/voice-credentials.d.ts +26 -0
- package/dist/plugin-sdk/commands/agent/session.d.ts +1 -2
- package/dist/plugin-sdk/commands/onboard-helpers.d.ts +0 -1
- package/dist/plugin-sdk/commands/onboard-types.d.ts +2 -1
- package/dist/plugin-sdk/config/defaults.d.ts +0 -1
- package/dist/plugin-sdk/config/legacy.migrations.d.ts +2 -1
- package/dist/plugin-sdk/config/legacy.shared.d.ts +0 -9
- package/dist/plugin-sdk/config/sessions/types.d.ts +0 -17
- package/dist/plugin-sdk/config/types.agent-defaults.d.ts +28 -120
- package/dist/plugin-sdk/config/types.agents.d.ts +8 -0
- package/dist/plugin-sdk/config/types.base.d.ts +0 -1
- package/dist/plugin-sdk/config/types.messages.d.ts +1 -6
- package/dist/plugin-sdk/config/types.remoteclaw.d.ts +2 -2
- package/dist/plugin-sdk/config/types.tools.d.ts +1 -74
- package/dist/plugin-sdk/config/types.tts.d.ts +2 -1
- package/dist/plugin-sdk/config/zod-schema.agent-defaults.d.ts +9 -70
- package/dist/plugin-sdk/config/zod-schema.agent-runtime.d.ts +12 -210
- package/dist/plugin-sdk/config/zod-schema.agents.d.ts +14 -86
- package/dist/plugin-sdk/config/zod-schema.core.d.ts +6 -234
- package/dist/plugin-sdk/config/zod-schema.d.ts +111 -378
- package/dist/plugin-sdk/config/zod-schema.providers-core.d.ts +148 -160
- package/dist/plugin-sdk/config/zod-schema.providers-whatsapp.d.ts +12 -12
- package/dist/plugin-sdk/config/zod-schema.providers.d.ts +88 -96
- package/dist/plugin-sdk/config/zod-schema.session.d.ts +4 -10
- package/dist/plugin-sdk/daemon/constants.d.ts +2 -2
- package/dist/plugin-sdk/gateway/protocol/index.d.ts +10 -17
- package/dist/plugin-sdk/gateway/protocol/schema/sessions.d.ts +0 -7
- package/dist/plugin-sdk/gateway/server/ws-types.d.ts +2 -0
- package/dist/plugin-sdk/gateway/session-utils.types.d.ts +0 -3
- package/dist/plugin-sdk/index.js +722 -1283
- package/dist/plugin-sdk/infra/agent-events.d.ts +1 -1
- package/dist/plugin-sdk/infra/provider-usage.auth.d.ts +0 -1
- package/dist/plugin-sdk/infra/provider-usage.load.d.ts +0 -1
- package/dist/plugin-sdk/line/config-schema.d.ts +4 -4
- package/dist/plugin-sdk/logging/levels.d.ts +1 -1
- package/dist/plugin-sdk/middleware/auth-key-retry.d.ts +31 -0
- package/dist/plugin-sdk/middleware/channel-bridge.d.ts +4 -0
- package/dist/plugin-sdk/middleware/cli-runtime-base.d.ts +6 -0
- package/dist/plugin-sdk/middleware/error-classifier.d.ts +5 -0
- package/dist/plugin-sdk/middleware/media-capability.d.ts +21 -0
- package/dist/plugin-sdk/middleware/media-resolver.d.ts +12 -0
- package/dist/plugin-sdk/middleware/runtime-factory.d.ts +42 -0
- package/dist/plugin-sdk/middleware/runtimes/claude.d.ts +10 -0
- package/dist/plugin-sdk/middleware/runtimes/codex.d.ts +5 -0
- package/dist/plugin-sdk/middleware/runtimes/gemini.d.ts +11 -0
- package/dist/plugin-sdk/middleware/runtimes/opencode.d.ts +5 -0
- package/dist/plugin-sdk/middleware/types.d.ts +41 -1
- package/dist/plugin-sdk/plugin-sdk/index.d.ts +5 -1
- package/dist/plugin-sdk/plugins/manifest-registry.d.ts +2 -0
- package/dist/plugin-sdk/plugins/manifest.d.ts +4 -4
- package/dist/plugin-sdk/plugins/registry.d.ts +18 -0
- package/dist/plugin-sdk/plugins/types.d.ts +5 -1
- package/dist/plugin-sdk/stt/defaults.d.ts +2 -0
- package/dist/plugin-sdk/stt/preflight.d.ts +14 -0
- package/dist/plugin-sdk/stt/providers/deepgram/index.d.ts +2 -0
- package/dist/plugin-sdk/stt/providers/google/index.d.ts +2 -0
- package/dist/plugin-sdk/stt/providers/groq/index.d.ts +2 -0
- package/dist/plugin-sdk/stt/providers/index.d.ts +4 -0
- package/dist/plugin-sdk/stt/providers/mistral/index.d.ts +2 -0
- package/dist/plugin-sdk/stt/providers/openai/index.d.ts +2 -0
- package/dist/plugin-sdk/stt/stt.d.ts +27 -0
- package/dist/plugin-sdk/stt/types.d.ts +22 -0
- package/dist/plugin-sdk/terminal/palette.d.ts +2 -2
- package/dist/plugin-sdk/tts/providers/edge.d.ts +2 -0
- package/dist/plugin-sdk/tts/providers/elevenlabs.d.ts +2 -0
- package/dist/plugin-sdk/tts/providers/index.d.ts +4 -0
- package/dist/plugin-sdk/tts/providers/openai.d.ts +2 -0
- package/dist/plugin-sdk/tts/tts.d.ts +13 -5
- package/dist/plugin-sdk/tts/types.d.ts +21 -0
- package/dist/plugins-BviLFPLV.js +255 -0
- package/dist/plugins-CaudBUbl.js +254 -0
- package/dist/plugins-cli-CsLhphNr.js +803 -0
- package/dist/plugins-cli-CujSP9NS.js +807 -0
- package/dist/ports-BtuzUQHl.js +370 -0
- package/dist/ports-CMcHia07.js +96 -0
- package/dist/ports-DALdfBQy.js +96 -0
- package/dist/ports-gRBeuUtp.js +316 -0
- package/dist/preflight-Bq8rimP-.js +667 -0
- package/dist/preflight-DyYbEp9X.js +667 -0
- package/dist/program-D64vUv0b.js +250 -0
- package/dist/program-context-CTFkimUr.js +474 -0
- package/dist/progress-BcwxtM9Q.js +124 -0
- package/dist/prompt-DtWGd43j.js +21 -0
- package/dist/prompt-select-styled-GW2PexAK.js +1672 -0
- package/dist/prompt-select-styled-JOuWGHX7.js +1669 -0
- package/dist/prompt-style-BpUMhEHC.js +9 -0
- package/dist/provider-auth-B7QgxlKt.js +187 -0
- package/dist/provider-auth-j-EQvvIk.js +187 -0
- package/dist/provider-dispatcher-Bx6CaIoV.js +660 -0
- package/dist/provider-dispatcher-DhkvjhO5.js +659 -0
- package/dist/push-apns--nEiZmEN.js +711 -0
- package/dist/push-apns-BtS6B6lb.js +713 -0
- package/dist/pw-ai-BpCsXF-x.js +1908 -0
- package/dist/pw-ai-ud_Kbn5S.js +1911 -0
- package/dist/qr-cli-BCeVLGfz.js +353 -0
- package/dist/qr-cli-Crsqtw01.js +349 -0
- package/dist/redact-Ci96Gj0O.js +191 -0
- package/dist/redact-snapshot-B9nof-Pb.js +1952 -0
- package/dist/redact-snapshot-BKiS91Mj.js +1952 -0
- package/dist/register.agent-CcvOeVnL.js +292 -0
- package/dist/register.agent-azH_tdVX.js +1014 -0
- package/dist/register.configure-DAaZLjHs.js +130 -0
- package/dist/register.configure-lUl8O79m.js +135 -0
- package/dist/register.import-B83Dn36B.js +29 -0
- package/dist/register.import-wIYU2cVW.js +31 -0
- package/dist/register.maintenance-Bo-ooQDU.js +501 -0
- package/dist/register.maintenance-BwZ4OkK2.js +503 -0
- package/dist/register.message-BQhRoEQQ.js +687 -0
- package/dist/register.message-CvZKWeGb.js +691 -0
- package/dist/register.onboard---3EPh-O.js +98 -0
- package/dist/register.onboard-rsHSJUvQ.js +94 -0
- package/dist/register.setup-B0gc_lne.js +118 -0
- package/dist/register.setup-MWpb7jxL.js +114 -0
- package/dist/register.status-health-sessions-BZJ0wTSa.js +429 -0
- package/dist/register.status-health-sessions-CyrUwwtB.js +667 -0
- package/dist/register.subclis-i2d2ugaJ.js +267 -0
- package/dist/replies-BIx-MbQ7.js +136 -0
- package/dist/replies-DVU655H4.js +136 -0
- package/dist/reply-CL5VMSKN.js +12372 -0
- package/dist/reply-XKyfU3rS.js +12375 -0
- package/dist/reply-directives-DQfJ001O.js +182 -0
- package/dist/reply-directives-DfUITt7C.js +182 -0
- package/dist/reply-payloads-ZHo6kfTS.js +527 -0
- package/dist/reply-prefix-BSf3PC0x.js +37 -0
- package/dist/reply-prefix-DBTlMHLK.js +37 -0
- package/dist/resolve-route-B-_IgETc.js +249 -0
- package/dist/resolve-route-C8ZsgWDQ.js +249 -0
- package/dist/response-prefix-template-3LeqJx2X.js +134 -0
- package/dist/response-prefix-template-DBrUVx5V.js +134 -0
- package/dist/retry-CDrH81GP.js +77 -0
- package/dist/retry-Dar_7pCv.js +77 -0
- package/dist/run-main-rOudcbbs.js +308 -0
- package/dist/runtime-guard-CK80eucm.js +60 -0
- package/dist/runtime-status-CR9445g5.js +12 -0
- package/dist/runtime-status-hFVEC3wO.js +12 -0
- package/dist/secure-random-CLWSvf8A.js +44 -0
- package/dist/security-cli-B8lXw9ke.js +488 -0
- package/dist/security-cli-CRkS3VAf.js +483 -0
- package/dist/send-6g8QKfWj.js +374 -0
- package/dist/send-B5Hz1PIn.js +29 -0
- package/dist/send-B8eIlA1u.js +349 -0
- package/dist/send-BFZPQE4j.js +492 -0
- package/dist/send-BpTDvE0D.js +1779 -0
- package/dist/send-BxOrO1Wv.js +1776 -0
- package/dist/send-C6gPJu-Z.js +11 -0
- package/dist/send-C7MoKtkN.js +426 -0
- package/dist/send-CXzq2LI6.js +2245 -0
- package/dist/send-CYOZoObr.js +547 -0
- package/dist/send-CfQyIvcC.js +332 -0
- package/dist/send-DUtuuwhw.js +492 -0
- package/dist/send-DbafVwxp.js +2245 -0
- package/dist/send-DeZg8K7y.js +349 -0
- package/dist/send-DwkjxJlv.js +547 -0
- package/dist/send-iX9xbxlU.js +1178 -0
- package/dist/server-BKfCzEzd.js +206 -0
- package/dist/server-fmO4eo7K.js +202 -0
- package/dist/server-lifecycle-CgPpP10P.js +2437 -0
- package/dist/server-lifecycle-Cn8yY5MW.js +2437 -0
- package/dist/server-node-events-C-ZzSBYh.js +391 -0
- package/dist/server-node-events-DYlyfDHM.js +395 -0
- package/dist/service-C2j81L86.js +670 -0
- package/dist/service-C8a0SXHD.js +670 -0
- package/dist/session-AulYhqOb.js +170 -0
- package/dist/session-C6VKWvx6.js +170 -0
- package/dist/session-cost-usage-0Vs4hgMe.js +627 -0
- package/dist/session-cost-usage-C-DsaOfN.js +627 -0
- package/dist/session-dirs-CO1f2ArM.js +318 -0
- package/dist/session-dirs-DoboH7Oy.js +318 -0
- package/dist/session-utils-CRK8ToKG.js +621 -0
- package/dist/session-utils-DWlkmCX8.js +621 -0
- package/dist/sessions-DtqrmUJS.js +2553 -0
- package/dist/sessions-gT-4fcX-.js +245 -0
- package/dist/shell-env-DBS5su07.js +163 -0
- package/dist/shell-env-c3j5zcU9.js +163 -0
- package/dist/ssrf-8wNqPNzN.js +183 -0
- package/dist/ssrf-CJIdPXuS.js +183 -0
- package/dist/status-BI_-xpDt.js +1947 -0
- package/dist/status-PZVwjKjl.js +1943 -0
- package/dist/status.update-BmuDZ7E7.js +449 -0
- package/dist/status.update-Mf6HSRvU.js +449 -0
- package/dist/store-B7PGEdFf.js +2555 -0
- package/dist/store-CzhBjUCN.js +64 -0
- package/dist/store-YkSxKAey.js +53 -0
- package/dist/store-ZNeFv2Q7.js +64 -0
- package/dist/subagent-registry-R1DiAM4R.js +4839 -0
- package/dist/subagent-registry-xLRXC8Bg.js +4841 -0
- package/dist/subsystem-BAW_f3DI.js +1195 -0
- package/dist/subsystem-DGSHVL8I.js +1081 -0
- package/dist/system-cli-9SvRrT9D.js +77 -0
- package/dist/system-cli-yCa5Q1YM.js +73 -0
- package/dist/systemd-40Rij3QR.js +547 -0
- package/dist/systemd-5C97CSzd.js +547 -0
- package/dist/systemd-hints-3iQteJw-.js +278 -0
- package/dist/systemd-hints-CyQqHq1i.js +278 -0
- package/dist/systemd-linger-B2rPbnAi.js +75 -0
- package/dist/systemd-linger-DDvkfxH-.js +75 -0
- package/dist/table-DFx25vNb.js +279 -0
- package/dist/tables-C5fI0PmT.js +55 -0
- package/dist/tables-Cm9qvQ9D.js +55 -0
- package/dist/tables-fRe01eP1.js +55 -0
- package/dist/tailnet-Da-_9e8E.js +40 -0
- package/dist/tailnet-xt92Yaop.js +40 -0
- package/dist/tailscale-CnV0JWca.js +230 -0
- package/dist/tailscale-VkEC8dzj.js +230 -0
- package/dist/targets-C99szk_e.js +114 -0
- package/dist/targets-CPaTjbpp.js +2607 -0
- package/dist/targets-D-p4rJVS.js +650 -0
- package/dist/targets-D2OQt8-7.js +650 -0
- package/dist/targets-D94MtTiZ.js +2606 -0
- package/dist/targets-RajrXTl7.js +220 -0
- package/dist/targets-_UWmnyI9.js +53 -0
- package/dist/targets-tDrl_ioQ.js +46 -0
- package/dist/thinking-4nOZPunr.js +60 -0
- package/dist/thinking-ZfH2V9Os.js +60 -0
- package/dist/tokens-TtJJxzRr.js +21 -0
- package/dist/tool-display-Bxs_1jIn.js +785 -0
- package/dist/tool-display-D9p_Ttkq.js +785 -0
- package/dist/tool-images-9Ron321Q.js +263 -0
- package/dist/tool-images-BWhy6WRN.js +263 -0
- package/dist/trash-B5xyvBDf.js +125 -0
- package/dist/trash-BpB96kHe.js +125 -0
- package/dist/tui-Ba0uZDrg.js +3237 -0
- package/dist/tui-Biz0HqDj.js +3237 -0
- package/dist/tui-cli-C-UV6o2v.js +63 -0
- package/dist/tui-cli-Ds_bLT-h.js +67 -0
- package/dist/types.tools-BBb2rl3g.js +23 -0
- package/dist/types.tools-BDJw1yFx.js +23 -0
- package/dist/update-Barj5dsg.js +349 -0
- package/dist/update-D839Q8su.js +349 -0
- package/dist/update-cli-C0LnrpIt.js +1148 -0
- package/dist/update-cli-CUypa-T-.js +1150 -0
- package/dist/usage-BI9kergH.js +5465 -0
- package/dist/utils-DPoNpP7D.js +631 -0
- package/dist/version-3QUZW8EP.js +52 -0
- package/dist/version-CVMnqdzu.js +52 -0
- package/dist/voice-credentials-64XAMSJm.js +46 -0
- package/dist/voice-credentials-v-CQkTpD.js +46 -0
- package/dist/web-63IbbidQ.js +3051 -0
- package/dist/web-D9N764Da.js +80 -0
- package/dist/web-DUvNYLzr.js +75 -0
- package/dist/webhooks-cli-owhVNNkz.js +334 -0
- package/dist/webhooks-cli-zlvka6QD.js +330 -0
- package/dist/whatsapp-actions-8DejyRG5.js +126 -0
- package/dist/whatsapp-actions-DCzp5LKe.js +131 -0
- package/dist/widearea-dns-CQqZIeu8.js +127 -0
- package/dist/workspace-CB7pVojf.js +441 -0
- package/dist/workspace-DWEyzM0F.js +439 -0
- package/dist/zod-schema-CvFqwpNE.js +2719 -0
- package/dist/zod-schema-Y5SQgJLm.js +2719 -0
- package/extensions/matrix/src/matrix/monitor/replies.ts +0 -24
- package/extensions/mattermost/src/mattermost/monitor-helpers.ts +0 -1
- package/extensions/voice-call/index.ts +18 -1
- package/package.json +3 -4
- package/dist/accounts-7fm_KzPm.js +0 -32
- package/dist/accounts-BFy_Z3od.js +0 -272
- package/dist/accounts-BTXSfPWi.js +0 -270
- package/dist/accounts-BxGS70Do.js +0 -36
- package/dist/accounts-CNY1TGj1.js +0 -47
- package/dist/accounts-DqRQ75w3.js +0 -36
- package/dist/accounts-iODF3SK2.js +0 -47
- package/dist/ack-reactions-C1hk85VE.js +0 -446
- package/dist/ack-reactions-DRC2CiDQ.js +0 -446
- package/dist/acp-cli-DD-PD4NM.js +0 -1326
- package/dist/acp-cli-DIyRCOum.js +0 -1320
- package/dist/active-listener-VzhWW8W6.js +0 -37
- package/dist/active-listener-z0qVEcom.js +0 -37
- package/dist/agent-D2HeDFFR.js +0 -731
- package/dist/agent-Da_eZ5BP.js +0 -732
- package/dist/agent-helpers-B6VfZ9_u.js +0 -606
- package/dist/agent-helpers-CTx5KKJu.js +0 -606
- package/dist/agent-scope-BqPmD-Ax.js +0 -114
- package/dist/agent-scope-DgQzamQB.js +0 -116
- package/dist/agents-TB3QpHoo.js +0 -788
- package/dist/agents.config-BsAQTYe1.js +0 -116
- package/dist/agents.config-C9fyYfAh.js +0 -116
- package/dist/ansi-D04X81yq.js +0 -14
- package/dist/audio-DPOuhNq7.js +0 -43
- package/dist/audio-VBcVDa08.js +0 -43
- package/dist/audio-preflight-CK3EA3Dv.js +0 -69
- package/dist/audio-preflight-tdXtrutj.js +0 -64
- package/dist/audit-CJipUWDi.js +0 -3138
- package/dist/audit-COWzB9Y1.js +0 -3138
- package/dist/auth-CAczFgAO.js +0 -448
- package/dist/auth-Deh9i9Eg.js +0 -448
- package/dist/auth-profiles-BquJGKLC.js +0 -279
- package/dist/auth-profiles-D8vKiBPq.js +0 -281
- package/dist/banner-CUWBOR42.js +0 -294
- package/dist/binaries-DXW6oATV.js +0 -13
- package/dist/bindings-8YtSWb91.js +0 -69
- package/dist/bindings-l1R5LQQH.js +0 -69
- package/dist/bonjour-discovery-DdAk1VyO.js +0 -378
- package/dist/bonjour-discovery-DuhiIZZx.js +0 -378
- package/dist/browser-cli-5Q9lhGdd.js +0 -1687
- package/dist/browser-cli-D2qMeSx1.js +0 -1692
- package/dist/call-CZHVeMf1.js +0 -2828
- package/dist/call-CoMjY7ah.js +0 -2829
- package/dist/catalog-CYiAleBT.js +0 -185
- package/dist/catalog-pjPqB2hC.js +0 -185
- package/dist/channel-account-context-CvIDAtHS.js +0 -550
- package/dist/channel-account-context-q-o0pG1A.js +0 -550
- package/dist/channel-activity-BaCNOZpP.js +0 -94
- package/dist/channel-activity-Cd1JhIUj.js +0 -292
- package/dist/channel-activity-DTKGf3j5.js +0 -94
- package/dist/channel-options-8SjIcDDI.js +0 -33
- package/dist/channel-options-BtQGtMF4.js +0 -32
- package/dist/channel-selection-C4DzrynU.js +0 -51
- package/dist/channel-selection-DdfhwFuY.js +0 -51
- package/dist/channel-web-BKJSXnwf.js +0 -2136
- package/dist/channel-web-BUzvNE_A.js +0 -2134
- package/dist/channels-cli-CCXY796Z.js +0 -1421
- package/dist/channels-cli-DTfx1zFC.js +0 -1426
- package/dist/channels-status-issues-DnmuqPsi.js +0 -18
- package/dist/channels-status-issues-p1pCvTh8.js +0 -18
- package/dist/chat-envelope-DEZ-5RY8.js +0 -248
- package/dist/chat-envelope-el7Uo-Fe.js +0 -248
- package/dist/chrome-Dd4dv0Vh.js +0 -1732
- package/dist/chrome-DdNEInwI.js +0 -1733
- package/dist/chunk-CSQfUhgF.js +0 -341
- package/dist/chunk-D0Y_w4oX.js +0 -341
- package/dist/clack-prompter-B7tOxhJd.js +0 -122
- package/dist/clack-prompter-CCFnKP_1.js +0 -121
- package/dist/cleanup-utils-CqAVZz2b.js +0 -94
- package/dist/cli-BRwDPW0r.js +0 -125
- package/dist/cli-CV86F7iv.js +0 -130
- package/dist/clipboard-D7_SKHPK.js +0 -31
- package/dist/clipboard-Dzkx6Q2K.js +0 -31
- package/dist/command-format-CVfo8I5f.js +0 -18
- package/dist/command-format-DgXcqxBt.js +0 -32
- package/dist/command-registry-BvLC28b4.js +0 -215
- package/dist/commands-B49Lu-pa.js +0 -41
- package/dist/commands-DI1BCqnj.js +0 -41
- package/dist/commands-registry-Cr6SIR3n.js +0 -892
- package/dist/commands-registry-agiTEGDz.js +0 -893
- package/dist/common-CMI-qsF8.js +0 -156
- package/dist/common-DSVmydhm.js +0 -156
- package/dist/completion-cli-C7O4JU8t.js +0 -452
- package/dist/completion-cli-CQNXtEJ7.js +0 -452
- package/dist/config-ChYRSJQt.js +0 -6953
- package/dist/config-CwtWvygh.js +0 -6951
- package/dist/config-cli-Df5nJcfO.js +0 -241
- package/dist/config-cli-Dqe5O1pl.js +0 -246
- package/dist/config-guard-C6hyuH-z.js +0 -75
- package/dist/config-guard-kNMQS_tm.js +0 -97
- package/dist/config-validation-BZBaBH69.js +0 -18
- package/dist/config-validation-DkrbzCyL.js +0 -18
- package/dist/configure-CoJmCHqT.js +0 -891
- package/dist/configure-DJbojDRf.js +0 -889
- package/dist/constants-BmRFoHl0.js +0 -67
- package/dist/constants-C9WPAluB.js +0 -67
- package/dist/control-auth-7k6Cb2zH.js +0 -397
- package/dist/control-auth-DBxfkJ3g.js +0 -397
- package/dist/control-ui/assets/index-B4ZM1lW1.js +0 -7738
- package/dist/control-ui/assets/index-B4ZM1lW1.js.map +0 -1
- package/dist/control-ui/assets/index-PED72sKF.css +0 -1
- package/dist/control-ui-assets-Cx_mw4D0.js +0 -186
- package/dist/control-ui-assets-W1AUuGrO.js +0 -186
- package/dist/conversation-label-C4SDz4sT.js +0 -36
- package/dist/conversation-label-D1frnvYe.js +0 -36
- package/dist/cron-cli-BJXQKtR3.js +0 -495
- package/dist/cron-cli-CTIj0WPW.js +0 -490
- package/dist/daemon-cli-CZbHvkRG.js +0 -1197
- package/dist/daemon-cli-Cf_YKWvV.js +0 -1199
- package/dist/daemon-install-CcohRvKV.js +0 -55
- package/dist/daemon-install-DDshfT0J.js +0 -60
- package/dist/daemon-install-helpers-CFGAfRlj.js +0 -462
- package/dist/daemon-install-helpers-DIUzSFG1.js +0 -462
- package/dist/defaults-B5KStIBg.js +0 -7
- package/dist/defaults-xUAL2Z-F.js +0 -7
- package/dist/deliver-BDf2lIEK.js +0 -481
- package/dist/deliver-DvmkSwLt.js +0 -481
- package/dist/delivery-queue-Cfa9Wmxp.js +0 -244
- package/dist/delivery-queue-CxVRi4tw.js +0 -244
- package/dist/devices-cli-CRsW5WOw.js +0 -316
- package/dist/devices-cli-Crzrk5uf.js +0 -321
- package/dist/diagnostics-99iCgBUh.js +0 -46
- package/dist/diagnostics-VC0cz7kX.js +0 -46
- package/dist/directory-cli-BnoQqeOX.js +0 -222
- package/dist/directory-cli-DdBAX3AV.js +0 -217
- package/dist/dm-policy-shared-DNqPbnip.js +0 -22
- package/dist/dm-policy-shared-vCb_hnqo.js +0 -22
- package/dist/dns-cli-D410XQr9.js +0 -197
- package/dist/dns-cli-Fgg96Xkg.js +0 -202
- package/dist/dock-DXSgTbDw.js +0 -928
- package/dist/dock-FtQwUHXE.js +0 -929
- package/dist/doctor-completion-BWmtCiFR.js +0 -92
- package/dist/doctor-completion-DTM_wDxy.js +0 -92
- package/dist/doctor-config-flow-Ccna5fPs.js +0 -1934
- package/dist/doctor-config-flow-DqzrK_jh.js +0 -1933
- package/dist/enable-DcJnkzfz.js +0 -59
- package/dist/enable-ibNq4UWy.js +0 -59
- package/dist/env-DeF64iu0.js +0 -60
- package/dist/env-vars-7aZqKPhk.js +0 -93
- package/dist/env-vars-CLGbxdpL.js +0 -93
- package/dist/errors-8F-77i6m.js +0 -35
- package/dist/errors-DZ199hOo.js +0 -35
- package/dist/exec-DbKuYyM1.js +0 -164
- package/dist/exec-DkFE7lqU.js +0 -164
- package/dist/fetch-C6XKGA11.js +0 -67
- package/dist/fetch-CEDsOiql.js +0 -67
- package/dist/fetch-ePscvwi1.js +0 -67
- package/dist/file-lock-CIvloidc.js +0 -107
- package/dist/file-lock-CzBL_VIx.js +0 -107
- package/dist/fs-safe-DSwT85uK.js +0 -88
- package/dist/fs-safe-DkBhNAc3.js +0 -98
- package/dist/gateway-cli-BJooqlkO.js +0 -23747
- package/dist/gateway-cli-C2wPjxY4.js +0 -23742
- package/dist/gateway-rpc-BcT4FqJQ.js +0 -28
- package/dist/gateway-rpc-DhKAJ5EW.js +0 -28
- package/dist/gmail-setup-utils-Cnx8A5pW.js +0 -422
- package/dist/gmail-setup-utils-nkabbKOE.js +0 -423
- package/dist/health-BZX-PyP0.js +0 -1420
- package/dist/health-BgD0koJx.js +0 -1423
- package/dist/health-format-BG95OE6N.js +0 -28
- package/dist/heartbeat-visibility-DeW9EIeS.js +0 -125
- package/dist/heartbeat-visibility-DvogUlnZ.js +0 -125
- package/dist/help-format-DAxf0l_h.js +0 -17
- package/dist/helpers-R7bU5IBz.js +0 -10
- package/dist/helpers-kkeXif0Q.js +0 -10
- package/dist/hook-runner-global-cyaKukZP.js +0 -527
- package/dist/hooks-cli-DTygpzqS.js +0 -1217
- package/dist/hooks-cli-Dg853OdZ.js +0 -1222
- package/dist/host-env-security-Bms2_EMV.js +0 -92
- package/dist/host-env-security-szwfmhC4.js +0 -92
- package/dist/image-ops-Bi6JPSkD.js +0 -354
- package/dist/image-ops-DWytvdh_.js +0 -354
- package/dist/import-D8BBZQgl.js +0 -170
- package/dist/import-DQ6NI4Fz.js +0 -168
- package/dist/inbound-context-CPkkQW0i.js +0 -68
- package/dist/inbound-context-DS_kpIYI.js +0 -68
- package/dist/inbound-path-policy-Bg4gZBx-.js +0 -250
- package/dist/inbound-path-policy-sdr5Ji0k.js +0 -250
- package/dist/inspect-Dt8hogS3.js +0 -559
- package/dist/inspect-vYIL1oA0.js +0 -559
- package/dist/installs-ClX3qQmh.js +0 -325
- package/dist/installs-CxjOiLUM.js +0 -325
- package/dist/ipv4--2WXMVtE.js +0 -46
- package/dist/ipv4-CDQpx1A7.js +0 -46
- package/dist/ir-BvKdMuSP.js +0 -940
- package/dist/json-files-DzpTak5i.js +0 -46
- package/dist/links-C3soDNDH.js +0 -15
- package/dist/loader-BWZ_iRxI.js +0 -22624
- package/dist/loader-ClFP7wvS.js +0 -22621
- package/dist/local-roots-B6rSCu4U.js +0 -314
- package/dist/local-roots-v2HlOaG5.js +0 -313
- package/dist/logger-Bw3cFE5t.js +0 -49
- package/dist/logging-C-nxX2fn.js +0 -20
- package/dist/login-Cmpeb59f.js +0 -62
- package/dist/login-D1CV2eNF.js +0 -61
- package/dist/login-qr-B3tpFLRV.js +0 -327
- package/dist/login-qr-CSQzrtFX.js +0 -322
- package/dist/logs-cli-BSiUZwb2.js +0 -238
- package/dist/logs-cli-DDtoJ1Fr.js +0 -233
- package/dist/markdown-tables-PJUMrC4T.js +0 -29
- package/dist/markdown-tables-dDWBbtqd.js +0 -29
- package/dist/media-Dqv7Q0aS.js +0 -10492
- package/dist/media-DtN0R9A0.js +0 -940
- package/dist/message-action-names-Bs50Ia1g.js +0 -2521
- package/dist/message-action-names-Btd7cMvx.js +0 -2521
- package/dist/message-channel-DzJqHVZD.js +0 -91
- package/dist/message-channel-uWMAiywE.js +0 -91
- package/dist/mime-BS3jhcZE.js +0 -149
- package/dist/mime-Cxh_64P6.js +0 -149
- package/dist/net-Cg8AQeke.js +0 -225
- package/dist/net-D6D0wgcF.js +0 -225
- package/dist/node-cli-Q2-n3Fgv.js +0 -24
- package/dist/node-cli-Uf6lAntf.js +0 -24
- package/dist/nodes-cli-DVLvMgBV.js +0 -1343
- package/dist/nodes-cli-Dxf7vAKk.js +0 -1348
- package/dist/nodes-screen-BR9sYoPa.js +0 -250
- package/dist/nodes-screen-Cw7Hv7M2.js +0 -250
- package/dist/note-Dlv4NmlQ.js +0 -92
- package/dist/note-kvWV4xtw.js +0 -92
- package/dist/npm-registry-spec-0qiKawvv.js +0 -786
- package/dist/npm-registry-spec-COvUzy5J.js +0 -786
- package/dist/npm-resolution-DJnq5QBs.js +0 -86
- package/dist/npm-resolution-DVl2spoD.js +0 -86
- package/dist/onboard-BcQWYGY3.js +0 -405
- package/dist/onboard-RQ_FAMyg.js +0 -407
- package/dist/onboard-channels-CHh_BuxJ.js +0 -2547
- package/dist/onboard-channels-DXD-CK_M.js +0 -2548
- package/dist/onboard-config-BCTthQ7J.js +0 -24
- package/dist/onboard-config-y-2cgT0V.js +0 -24
- package/dist/onboard-helpers-BRMP8mup.js +0 -362
- package/dist/onboard-helpers-CUGbuZwH.js +0 -363
- package/dist/onboard-remote-D-qWujdL.js +0 -127
- package/dist/onboard-remote-o_OW-uzc.js +0 -127
- package/dist/onboarding-Bf9kVcef.js +0 -541
- package/dist/onboarding-CVlOLLp1.js +0 -543
- package/dist/onboarding.finalize-CQSt37fw.js +0 -398
- package/dist/onboarding.finalize-DggVL7Ay.js +0 -401
- package/dist/onboarding.gateway-config-BLca3Td2.js +0 -198
- package/dist/onboarding.gateway-config-C1mcOkRh.js +0 -191
- package/dist/outbound-DXXccLDS.js +0 -220
- package/dist/outbound-ZnVvUReT.js +0 -221
- package/dist/outbound-attachment-CfRb07J7.js +0 -18
- package/dist/outbound-attachment-DGXTtERK.js +0 -18
- package/dist/outbound-attachment-_jj74QBM.js +0 -18
- package/dist/pairing-cli-Bgm4fRA3.js +0 -127
- package/dist/pairing-cli-J0uGb1nU.js +0 -122
- package/dist/pairing-labels-CVm65Jkh.js +0 -9
- package/dist/pairing-labels-DD1mcvQG.js +0 -9
- package/dist/pairing-store-5qapT5-t.js +0 -460
- package/dist/pairing-store-MLceBEeL.js +0 -459
- package/dist/path-env-DR5vn3QL.js +0 -89
- package/dist/path-env-qRJbjJzj.js +0 -89
- package/dist/path-guards-CIx4hURU.js +0 -31
- package/dist/path-guards-CrQOUlsq.js +0 -31
- package/dist/path-safety-DkT9RmTG.js +0 -14
- package/dist/path-safety-juI2XbO1.js +0 -14
- package/dist/paths-BTaH3rLn.js +0 -232
- package/dist/plugin-auto-enable-BUSF117F.js +0 -301
- package/dist/plugin-auto-enable-CoDnqA0S.js +0 -302
- package/dist/plugin-registry-D2B6nbn1.js +0 -33
- package/dist/plugin-registry-fLaMC0ik.js +0 -33
- package/dist/plugin-sdk/agents/agent-helpers/thinking.d.ts +0 -5
- package/dist/plugin-sdk/agents/agent-paths.d.ts +0 -1
- package/dist/plugin-sdk/agents/auth-profiles/constants.d.ts +0 -16
- package/dist/plugin-sdk/agents/auth-profiles/display.d.ts +0 -7
- package/dist/plugin-sdk/agents/auth-profiles/doctor.d.ts +0 -8
- package/dist/plugin-sdk/agents/auth-profiles/oauth.d.ts +0 -14
- package/dist/plugin-sdk/agents/auth-profiles/paths.d.ts +0 -4
- package/dist/plugin-sdk/agents/auth-profiles/profiles.d.ts +0 -12
- package/dist/plugin-sdk/agents/auth-profiles/session-override.d.ts +0 -18
- package/dist/plugin-sdk/agents/auth-profiles/store.d.ts +0 -10
- package/dist/plugin-sdk/agents/auth-profiles/types.d.ts +0 -13
- package/dist/plugin-sdk/agents/auth-profiles.d.ts +0 -8
- package/dist/plugin-sdk/agents/defaults.d.ts +0 -3
- package/dist/plugin-sdk/agents/provider-auth.d.ts +0 -40
- package/dist/plugin-sdk/auto-reply/model-runtime.d.ts +0 -17
- package/dist/plugin-sdk/auto-reply/reply/directive-handling.auth.d.ts +0 -19
- package/dist/plugin-sdk/auto-reply/reply/elevated-allowlist-matcher.d.ts +0 -20
- package/dist/plugin-sdk/auto-reply/reply/elevated-unavailable.d.ts +0 -8
- package/dist/plugin-sdk/auto-reply/reply/reply-elevated.d.ts +0 -16
- package/dist/plugin-sdk/compat/legacy-names.d.ts +0 -8
- package/dist/plugin-sdk/config/legacy.migrations.part-1.d.ts +0 -2
- package/dist/plugin-sdk/config/legacy.migrations.part-2.d.ts +0 -2
- package/dist/plugin-sdk/config/legacy.migrations.part-3.d.ts +0 -2
- package/dist/plugin-sdk/config/model-input.d.ts +0 -9
- package/dist/plugin-sdk/config/zod-schema.agent-model.d.ts +0 -5
- package/dist/plugin-sdk/link-understanding/apply.d.ts +0 -10
- package/dist/plugin-sdk/link-understanding/defaults.d.ts +0 -2
- package/dist/plugin-sdk/link-understanding/detect.d.ts +0 -3
- package/dist/plugin-sdk/link-understanding/format.d.ts +0 -4
- package/dist/plugin-sdk/link-understanding/runner.d.ts +0 -11
- package/dist/plugin-sdk/media/input-files.d.ts +0 -95
- package/dist/plugin-sdk/media-understanding/apply.d.ts +0 -19
- package/dist/plugin-sdk/media-understanding/attachments.d.ts +0 -49
- package/dist/plugin-sdk/media-understanding/audio-preflight.d.ts +0 -16
- package/dist/plugin-sdk/media-understanding/concurrency.d.ts +0 -1
- package/dist/plugin-sdk/media-understanding/defaults.d.ts +0 -12
- package/dist/plugin-sdk/media-understanding/errors.d.ts +0 -6
- package/dist/plugin-sdk/media-understanding/format.d.ts +0 -7
- package/dist/plugin-sdk/media-understanding/fs.d.ts +0 -1
- package/dist/plugin-sdk/media-understanding/output-extract.d.ts +0 -2
- package/dist/plugin-sdk/media-understanding/providers/anthropic/index.d.ts +0 -2
- package/dist/plugin-sdk/media-understanding/providers/deepgram/index.d.ts +0 -2
- package/dist/plugin-sdk/media-understanding/providers/google/index.d.ts +0 -2
- package/dist/plugin-sdk/media-understanding/providers/google/video.d.ts +0 -3
- package/dist/plugin-sdk/media-understanding/providers/groq/index.d.ts +0 -2
- package/dist/plugin-sdk/media-understanding/providers/index.d.ts +0 -4
- package/dist/plugin-sdk/media-understanding/providers/minimax/index.d.ts +0 -2
- package/dist/plugin-sdk/media-understanding/providers/mistral/index.d.ts +0 -2
- package/dist/plugin-sdk/media-understanding/providers/moonshot/index.d.ts +0 -2
- package/dist/plugin-sdk/media-understanding/providers/moonshot/video.d.ts +0 -3
- package/dist/plugin-sdk/media-understanding/providers/openai/index.d.ts +0 -2
- package/dist/plugin-sdk/media-understanding/providers/zai/index.d.ts +0 -2
- package/dist/plugin-sdk/media-understanding/resolve.d.ts +0 -44
- package/dist/plugin-sdk/media-understanding/runner.d.ts +0 -34
- package/dist/plugin-sdk/media-understanding/runner.entries.d.ts +0 -33
- package/dist/plugin-sdk/media-understanding/scope.d.ts +0 -9
- package/dist/plugin-sdk/media-understanding/types.d.ts +0 -74
- package/dist/plugin-sdk/media-understanding/video.d.ts +0 -2
- package/dist/plugin-sdk/sessions/model-overrides.d.ts +0 -14
- package/dist/plugin-sdk/telegram/reasoning-lane-coordinator.d.ts +0 -18
- package/dist/plugin-sdk/utils/mask-api-key.d.ts +0 -1
- package/dist/plugin-sdk/utils/run-with-concurrency.d.ts +0 -11
- package/dist/plugins-CsYMlnVa.js +0 -455
- package/dist/plugins-Dhit-VHt.js +0 -453
- package/dist/plugins-cli-BwuvKtN-.js +0 -798
- package/dist/plugins-cli-D34k2VsI.js +0 -793
- package/dist/ports-DrruB2fK.js +0 -370
- package/dist/ports-GT1yV-Tg.js +0 -96
- package/dist/ports-NPqtlfp0.js +0 -316
- package/dist/ports-QMI4-F9m.js +0 -96
- package/dist/program-C5ukTU6N.js +0 -244
- package/dist/program-context-D55P0vBV.js +0 -474
- package/dist/progress-CBkSaM6z.js +0 -124
- package/dist/prompt-Bllj1dhc.js +0 -21
- package/dist/prompt-select-styled-WStiI-bz.js +0 -1647
- package/dist/prompt-select-styled-ram-aXWu.js +0 -1650
- package/dist/prompt-style-DVEm3BZW.js +0 -9
- package/dist/provider-dispatcher-epFKwpGK.js +0 -659
- package/dist/provider-dispatcher-vEBMmwZ0.js +0 -660
- package/dist/push-apns-C0LyG-WB.js +0 -713
- package/dist/push-apns-DuG95AKC.js +0 -711
- package/dist/pw-ai-TygsEDgY.js +0 -1906
- package/dist/pw-ai-eS0sIkZo.js +0 -1910
- package/dist/qr-cli-B8sYhugo.js +0 -352
- package/dist/qr-cli-yP8i4Iv1.js +0 -347
- package/dist/redact-eZq1uwNK.js +0 -191
- package/dist/redact-snapshot-gOLgfKp3.js +0 -2028
- package/dist/redact-snapshot-uT-CXbM8.js +0 -2028
- package/dist/register.agent-CSoigVGq.js +0 -1043
- package/dist/register.agent-GZLrbUPm.js +0 -286
- package/dist/register.configure-CXpiRohq.js +0 -124
- package/dist/register.configure-RaqiHe5L.js +0 -130
- package/dist/register.import-Bs-UkOs-.js +0 -27
- package/dist/register.import-DLng8g-e.js +0 -30
- package/dist/register.maintenance-B-ZLQ56Y.js +0 -494
- package/dist/register.maintenance-Bjr_SmG9.js +0 -497
- package/dist/register.message-BCQ8Vg4O.js +0 -686
- package/dist/register.message-ChhiSr7g.js +0 -681
- package/dist/register.onboard-DJCqNufv.js +0 -257
- package/dist/register.onboard-jlxjsrv6.js +0 -262
- package/dist/register.setup-C-sdixz5.js +0 -114
- package/dist/register.setup-Dwpe4ArC.js +0 -109
- package/dist/register.status-health-sessions-BWFRHBCZ.js +0 -669
- package/dist/register.status-health-sessions-D7noMz9y.js +0 -423
- package/dist/register.subclis-DFI5u4a6.js +0 -267
- package/dist/replies-Bzcj-R8d.js +0 -136
- package/dist/replies-uvTI-4lg.js +0 -136
- package/dist/reply-B9qz9Wwk.js +0 -13897
- package/dist/reply-CmGAXQKc.js +0 -13900
- package/dist/reply-directives-Be97YiyM.js +0 -182
- package/dist/reply-directives-DsLughUT.js +0 -182
- package/dist/reply-payloads-DW0YgT82.js +0 -527
- package/dist/reply-prefix-BzoT8h8o.js +0 -38
- package/dist/reply-prefix-CSaiVnkC.js +0 -38
- package/dist/resolve-route-2P40JKXk.js +0 -249
- package/dist/resolve-route-_CwEKLq6.js +0 -249
- package/dist/response-prefix-template-BAlvtSjL.js +0 -136
- package/dist/response-prefix-template-D-tls8tI.js +0 -136
- package/dist/retry-B042l5UJ.js +0 -77
- package/dist/retry-BhuXOEVR.js +0 -77
- package/dist/run-main-B-O5ZtbU.js +0 -320
- package/dist/runner-DGkTSlOS.js +0 -2294
- package/dist/runner-hs4uxAUP.js +0 -2294
- package/dist/runtime-DJNp29jv.js +0 -94
- package/dist/runtime-guard-DZ_xuCc4.js +0 -60
- package/dist/secure-random-DTcQnwrI.js +0 -44
- package/dist/security-cli-1iY1lW6F.js +0 -484
- package/dist/security-cli-BuiPPQYU.js +0 -478
- package/dist/send-3lgWtHHf.js +0 -349
- package/dist/send-6l2S1bcr.js +0 -11
- package/dist/send-9NV7sSlD.js +0 -2245
- package/dist/send-B0TcjZUD.js +0 -1778
- package/dist/send-Bb6K_10X.js +0 -2245
- package/dist/send-BzN7X1Om.js +0 -374
- package/dist/send-CLrRM0El.js +0 -426
- package/dist/send-Caz-txXK.js +0 -492
- package/dist/send-DJEr4rP6.js +0 -547
- package/dist/send-DJiDHXsu.js +0 -349
- package/dist/send-DOjg7kJj.js +0 -1775
- package/dist/send-DVXOiKT4.js +0 -1174
- package/dist/send-Dc_K995l.js +0 -547
- package/dist/send-Dh6d3CLl.js +0 -332
- package/dist/send-iPAfbiYM.js +0 -492
- package/dist/send-pwe9Gu8e.js +0 -29
- package/dist/server-B0IC-Osg.js +0 -205
- package/dist/server-MccRxMpb.js +0 -200
- package/dist/server-lifecycle-C_0CfoP7.js +0 -2437
- package/dist/server-lifecycle-IKdGw1kM.js +0 -2437
- package/dist/server-node-events-Czr2gXp_.js +0 -393
- package/dist/server-node-events-DFG6cXud.js +0 -398
- package/dist/service-Bjqii5nW.js +0 -670
- package/dist/service-fp29z5Ww.js +0 -670
- package/dist/session-DBL5nHDy.js +0 -170
- package/dist/session-cost-usage-DX09eTPU.js +0 -627
- package/dist/session-cost-usage-yYi525j3.js +0 -627
- package/dist/session-dirs-Cj5xi7zX.js +0 -947
- package/dist/session-dirs-DdF6TDsE.js +0 -947
- package/dist/session-utils-C7BtKlun.js +0 -625
- package/dist/session-utils-CLe1dano.js +0 -625
- package/dist/session-xKIW6gL2.js +0 -170
- package/dist/sessions-C65iUuN9.js +0 -2593
- package/dist/sessions-DjZ9IshB.js +0 -252
- package/dist/ssrf-Ck9HDZpv.js +0 -183
- package/dist/ssrf-m7kFIobZ.js +0 -183
- package/dist/status-C6ghjxvX.js +0 -2072
- package/dist/status-D-qTB8aZ.js +0 -2068
- package/dist/status.update-C55QM2xs.js +0 -79
- package/dist/status.update-CBmPXwYN.js +0 -79
- package/dist/store-Bjk6rTC_.js +0 -53
- package/dist/store-C3tOpizT.js +0 -64
- package/dist/store-uRA67h-o.js +0 -2595
- package/dist/store-v3P-OWhi.js +0 -64
- package/dist/subagent-registry-BTG1aAZ8.js +0 -4860
- package/dist/subagent-registry-CoclNL5c.js +0 -4858
- package/dist/subsystem-COd61u0P.js +0 -1139
- package/dist/subsystem-D9ZpRKFP.js +0 -1079
- package/dist/system-cli-C__5QOMX.js +0 -70
- package/dist/system-cli-Dr4XoVTq.js +0 -75
- package/dist/systemd-DSnlM3jX.js +0 -547
- package/dist/systemd-TfK8GuTx.js +0 -547
- package/dist/systemd-linger-Axnc1xCb.js +0 -75
- package/dist/systemd-linger-_0_-RY4v.js +0 -75
- package/dist/table-DPTzZyhu.js +0 -279
- package/dist/tables-BQ-CvUfT.js +0 -55
- package/dist/tables-D3a9iSU1.js +0 -55
- package/dist/tables-D3zdgEuK.js +0 -55
- package/dist/tailnet-CEudzG0i.js +0 -40
- package/dist/tailnet-PnMrjwGT.js +0 -40
- package/dist/tailscale-DTATQxAG.js +0 -230
- package/dist/tailscale-Dbyahx0J.js +0 -230
- package/dist/targets-B_0Y1i-1.js +0 -2173
- package/dist/targets-CMhBAn87.js +0 -120
- package/dist/targets-CTmhieRB.js +0 -650
- package/dist/targets-CcTME3bp.js +0 -46
- package/dist/targets-DfaVEd_u.js +0 -220
- package/dist/targets-DtiQgjEL.js +0 -2172
- package/dist/targets-DyybKefq.js +0 -53
- package/dist/targets-rDolm5YS.js +0 -650
- package/dist/tokens-DzFOtLlW.js +0 -21
- package/dist/tool-display-Br6mwaJc.js +0 -785
- package/dist/tool-display-sgNwLOBj.js +0 -785
- package/dist/tool-images-BNfIJ_Kj.js +0 -263
- package/dist/tool-images-kloBqxqK.js +0 -263
- package/dist/trash-DPi0aCCQ.js +0 -125
- package/dist/trash-D_Jd_yQZ.js +0 -125
- package/dist/tui-BSDCI2hh.js +0 -3392
- package/dist/tui-DT7hLOBk.js +0 -3392
- package/dist/tui-cli-DUWvLaoG.js +0 -58
- package/dist/tui-cli-Dn2iXQTO.js +0 -63
- package/dist/update-Bgl3Pk2N.js +0 -349
- package/dist/update-CFPFib4P.js +0 -349
- package/dist/update-cli-DSDSQ2Xi.js +0 -1373
- package/dist/update-cli-DYR_7NLy.js +0 -1370
- package/dist/usage-CS1zeIan.js +0 -5279
- package/dist/utils-LBKvDoPx.js +0 -631
- package/dist/web-BECD5Akw.js +0 -70
- package/dist/web-D4oENnAL.js +0 -3065
- package/dist/web-KP-TI2sO.js +0 -76
- package/dist/webhooks-cli-BqoG_i-D.js +0 -328
- package/dist/webhooks-cli-Ddu7dfdE.js +0 -333
- package/dist/whatsapp-actions-BZLIjQ8J.js +0 -122
- package/dist/whatsapp-actions-KCc1vHN5.js +0 -128
- package/dist/widearea-dns-DSoaA-eH.js +0 -127
- package/dist/workspace-4EaHHEWi.js +0 -447
- package/dist/workspace-B_1t_yq3.js +0 -449
- /package/dist/{account-lookup-0KDSp5Mj.js → account-lookup-C0ndrpt-.js} +0 -0
- /package/dist/{account-lookup-zvANGr2x.js → account-lookup-CIY_RKhi.js} +0 -0
- /package/dist/{api-BeQMq2iS.js → api-BE4ZCWWB.js} +0 -0
- /package/dist/{api-CxX8-gGz.js → api-wsk9zRVi.js} +0 -0
- /package/dist/{argv-Co-b9Zsc.js → argv-BY8EVMTP.js} +0 -0
- /package/dist/{brew-DbSbN8sD.js → brew-CmTYeZk1.js} +0 -0
- /package/dist/{brew-C4zKZsHX.js → brew-V4lMBeE3.js} +0 -0
- /package/dist/{chat-type-CYPyHAj-.js → chat-type-BP9akbag.js} +0 -0
- /package/dist/{chat-type-DKb2TlGZ.js → chat-type-CH3W-zKy.js} +0 -0
- /package/dist/{cleanup-utils-CwQvD73q.js → cleanup-utils-ZC2zvntc.js} +0 -0
- /package/dist/{cli-name-BicfmwQX.js → cli-name-BZsYSp9l.js} +0 -0
- /package/dist/{cli-name-C6rJGl18.js → cli-name-CRe5Ow_t.js} +0 -0
- /package/dist/{cli-utils-BhXbz2UF.js → cli-utils-BUOtyfnU.js} +0 -0
- /package/dist/{cli-utils-DZe_rVkZ.js → cli-utils-CGB3cBZm.js} +0 -0
- /package/dist/{client-C61M8zI3.js → client-9dK56xly.js} +0 -0
- /package/dist/{client-DdpmATKq.js → client-D-R1YdRD.js} +0 -0
- /package/dist/{command-options-C4paWSGf.js → command-options-CnHA4TzR.js} +0 -0
- /package/dist/{command-options-CA30lfLK.js → command-options-D2nN4AXX.js} +0 -0
- /package/dist/{config-eval-CjGZtLwx.js → config-eval-BQIR-wSg.js} +0 -0
- /package/dist/{config-eval-H_wlEYIG.js → config-eval-Bh82JoXK.js} +0 -0
- /package/dist/{constants-ChptG3d7.js → constants-C7j1VA2S.js} +0 -0
- /package/dist/{constants-DY6b-_Wl.js → constants-DoYLsBmv.js} +0 -0
- /package/dist/{credentials-BHWUBHMd.js → credentials-C_RoJFmK.js} +0 -0
- /package/dist/{credentials-DFsi1_e8.js → credentials-DM_Dj0m8.js} +0 -0
- /package/dist/{daemon-runtime-CMnbwryP.js → daemon-runtime-9oDBR7YW.js} +0 -0
- /package/dist/{daemon-runtime-CvqE4ysg.js → daemon-runtime-CzFI2dPw.js} +0 -0
- /package/dist/{dangerous-name-matching-BzmiLXmA.js → dangerous-name-matching-BlTBBZns.js} +0 -0
- /package/dist/{dangerous-name-matching-DaVRgwer.js → dangerous-name-matching-CSq9sJDG.js} +0 -0
- /package/dist/{dangerous-tools-BOLoCRv4.js → dangerous-tools-BRmbBvRf.js} +0 -0
- /package/dist/{dangerous-tools-Baq7Q-i6.js → dangerous-tools-D4jtl72G.js} +0 -0
- /package/dist/{fetch-timeout-DTIN7CGM.js → fetch-timeout-CytN1wiO.js} +0 -0
- /package/dist/{fetch-timeout-DoySHqfO.js → fetch-timeout-DBRRPNBi.js} +0 -0
- /package/dist/{file-identity-BxlKD8Ys.js → file-identity-CeRK5CJC.js} +0 -0
- /package/dist/{format-duration-CqUERz51.js → format-duration-B-Uv5nOi.js} +0 -0
- /package/dist/{format-duration-Ct-yiwkS.js → format-duration-D1M3Zxu6.js} +0 -0
- /package/dist/{format-relative-79_Y1n2Y.js → format-relative-Czf5fUjn.js} +0 -0
- /package/dist/{format-relative-CxLpEQOX.js → format-relative-zwkkXJvs.js} +0 -0
- /package/dist/{health-format-B_QRD8Si.js → health-format-DF54wvUU.js} +0 -0
- /package/dist/{heartbeat-wake-LGEgcXjs.js → heartbeat-wake-CvHncCjP.js} +0 -0
- /package/dist/{heartbeat-wake-Y97geucO.js → heartbeat-wake-DLxQm6-U.js} +0 -0
- /package/dist/{help-format-NNm_Ov4H.js → help-format-CJQ7APRn.js} +0 -0
- /package/dist/{helpers-BAsMXprO.js → helpers-BER76F_2.js} +0 -0
- /package/dist/{helpers-DLgbkcEn.js → helpers-n2CtWpm9.js} +0 -0
- /package/dist/{input-provenance-Bn6thJNm.js → input-provenance-gIfDn1ki.js} +0 -0
- /package/dist/{input-provenance-xUsSMOsz.js → input-provenance-wkso1o5V.js} +0 -0
- /package/dist/{ip-C9q3Oq20.js → ip-D4VG5EJO.js} +0 -0
- /package/dist/{ip-D0zgNmBV.js → ip-MwCwRA7c.js} +0 -0
- /package/dist/{is-main-DN8-sNR5.js → is-main-BmHYGRhd.js} +0 -0
- /package/dist/{json-file-B7l5-Xhr.js → json-file-BW22hGtf.js} +0 -0
- /package/dist/{json-file-ChO_R9yh.js → json-file-DwRAfAAy.js} +0 -0
- /package/dist/{json-files-CmpYSF4G.js → json-files-Dy52honG.js} +0 -0
- /package/dist/{lanes-ByWMUgrz.js → lanes-1CBKdsiR.js} +0 -0
- /package/dist/{lanes-cHJ5arWg.js → lanes-DqVYfPRG.js} +0 -0
- /package/dist/{links-Bz4V7R_p.js → links-CwTlzaPe.js} +0 -0
- /package/dist/{location-DBWCGNLq.js → location-50gaJF5Z.js} +0 -0
- /package/dist/{location-GbZ0bBRU.js → location-Qo8Ii1zo.js} +0 -0
- /package/dist/{logger-DyL5G2DO.js → logger-B8BE0PyS.js} +0 -0
- /package/dist/{logger-BWMPnILd.js → logger-CPvz-aPM.js} +0 -0
- /package/dist/{logger-GvipVDfh.js → logger-cL0D2DCr.js} +0 -0
- /package/dist/{logging-D8-Kozjc.js → logging-DTEoeoa3.js} +0 -0
- /package/dist/{mutable-allowlist-detectors-DiZDtmlZ.js → mutable-allowlist-detectors-BXE7Hr7F.js} +0 -0
- /package/dist/{mutable-allowlist-detectors-U5ThQr9V.js → mutable-allowlist-detectors-CtKavajp.js} +0 -0
- /package/dist/{parse-log-line-enq8pduH.js → parse-log-line-GisaZn5H.js} +0 -0
- /package/dist/{parse-log-line-mz9TG6ig.js → parse-log-line-ZsbwG_u7.js} +0 -0
- /package/dist/{parse-timeout-BMP8a0_a.js → parse-timeout-BpphuwYl.js} +0 -0
- /package/dist/{parse-timeout-CDkco8kd.js → parse-timeout-CE6BjmGU.js} +0 -0
- /package/dist/plugin-sdk/{agents → auth}/api-key-rotation.d.ts +0 -0
- /package/dist/plugin-sdk/{media-understanding → stt}/providers/deepgram/audio.d.ts +0 -0
- /package/dist/plugin-sdk/{media-understanding → stt}/providers/google/audio.d.ts +0 -0
- /package/dist/plugin-sdk/{media-understanding → stt}/providers/google/inline-data.d.ts +0 -0
- /package/dist/plugin-sdk/{media-understanding → stt}/providers/openai/audio.d.ts +0 -0
- /package/dist/plugin-sdk/{media-understanding → stt}/providers/shared.d.ts +0 -0
- /package/dist/{plugins-allowlist-BbTQ5Z2k.js → plugins-allowlist-A38nxBRG.js} +0 -0
- /package/dist/{plugins-allowlist-C20oaESO.js → plugins-allowlist-D2tS9tcu.js} +0 -0
- /package/dist/{polls-B0CCBDeR.js → polls-BLyT08ZI.js} +0 -0
- /package/dist/{polls-CwwHzYBM.js → polls-BmymsJEe.js} +0 -0
- /package/dist/{ports-lsof-Wteul3ju.js → ports-lsof-CDyv5GJd.js} +0 -0
- /package/dist/{process-scoped-map-CV9kDvfG.js → process-scoped-map-BCJR56ZB.js} +0 -0
- /package/dist/{process-scoped-map-PEvnG75N.js → process-scoped-map-Cb1EHPyN.js} +0 -0
- /package/dist/{program-context-jqeI5alP.js → program-context-DlXnmuB7.js} +0 -0
- /package/dist/{progress-C1kUfYL-.js → progress-DRLmcFiG.js} +0 -0
- /package/dist/{prompt-Yn2yClg1.js → prompt-BRGfic91.js} +0 -0
- /package/dist/{prompt-style-DjEYC_s-.js → prompt-style-CUuA6OCy.js} +0 -0
- /package/dist/{provider-utils-3JTMJroG.js → provider-utils-C9kBVF1f.js} +0 -0
- /package/dist/{provider-utils-FaBmofiq.js → provider-utils-DiLhkKQp.js} +0 -0
- /package/dist/{proxy-DL3MD6-P.js → proxy-BMJL0Qog.js} +0 -0
- /package/dist/{proxy-DpNv2cSV.js → proxy-D-qGA1vm.js} +0 -0
- /package/dist/{pw-ai-state-CGfLv6nV.js → pw-ai-state--TxTVwRW.js} +0 -0
- /package/dist/{pw-ai-state-Dynx20hr.js → pw-ai-state-CwXeO5d0.js} +0 -0
- /package/dist/{redact-Dx1Fue21.js → redact-BW8tobyp.js} +0 -0
- /package/dist/{redact-identifier-BTIWtaa-.js → redact-identifier-BJOQDEj0.js} +0 -0
- /package/dist/{redact-identifier-CAagcfWA.js → redact-identifier-Bv5SUUw-.js} +0 -0
- /package/dist/{remoteclaw-root-C2HV2VeC.js → remoteclaw-root-BfPjgewe.js} +0 -0
- /package/dist/{remoteclaw-root-DybYl8PL.js → remoteclaw-root-E4-hmb4E.js} +0 -0
- /package/dist/{render-CCLsW6Lz.js → render-BhKzKdV0.js} +0 -0
- /package/dist/{render-uf6PvGMV.js → render-e7fENCYH.js} +0 -0
- /package/dist/{retry-DnqPAqWp.js → retry-BWv_fy4u.js} +0 -0
- /package/dist/{runtime-guard-U-ewY_QH.js → runtime-guard-Bhx-pb8_.js} +0 -0
- /package/dist/{secret-equal-BbHdTtqY.js → secret-equal-D6AoXne1.js} +0 -0
- /package/dist/{secret-equal-CXJEZiWb.js → secret-equal-DLnUuWM3.js} +0 -0
- /package/dist/{secure-random-CS2mSdTn.js → secure-random-CJtykx_p.js} +0 -0
- /package/dist/{secure-random-_dzDDlFo.js → secure-random-CRVHgtmO.js} +0 -0
- /package/dist/{session-key-5YLnn_qf.js → session-key-BF-9YzxC.js} +0 -0
- /package/dist/{session-key-C2n-VILA.js → session-key-CgKWfjoZ.js} +0 -0
- /package/dist/{stagger-BXv_apuy.js → stagger--wvODnNe.js} +0 -0
- /package/dist/{stagger-MI9gd2rQ.js → stagger-BLmTO4cK.js} +0 -0
- /package/dist/{status-BmtCS3T1.js → status-1zVD-Clq.js} +0 -0
- /package/dist/{status-BrwHRn2B.js → status-BtRY0nXQ.js} +0 -0
- /package/dist/{strip-inbound-meta-DjKcSFaW.js → strip-inbound-meta-zmUXypSS.js} +0 -0
- /package/dist/{strip-inbound-meta-jy3bkUab.js → strip-inbound-meta-zqtN9FTK.js} +0 -0
- /package/dist/{table-C1rdyYl9.js → table-On3hkCqi.js} +0 -0
- /package/dist/{target-errors-BDpPcwh5.js → target-errors-DJVRKFcU.js} +0 -0
- /package/dist/{target-errors-DdIAPcMM.js → target-errors-GZXDqlUu.js} +0 -0
- /package/dist/{targets-C-2xwh9f.js → targets-B46m7u5J.js} +0 -0
- /package/dist/{targets-D-qLBpTA.js → targets-B_d_1z3N.js} +0 -0
- /package/dist/{targets-UncQvCVs.js → targets-D01MJGnh.js} +0 -0
- /package/dist/{targets-BMenhVHg.js → targets-D3r6Zgic.js} +0 -0
- /package/dist/{text-format-BQ3z_OXA.js → text-format-DarxU3JH.js} +0 -0
- /package/dist/{text-format-oWqzVmah.js → text-format-Ds92M9UT.js} +0 -0
- /package/dist/{tokens-B-jmvNR9.js → tokens-Dw7ZdYwT.js} +0 -0
- /package/dist/{usage-BdhBT0Vz.js → usage-BIzKZ5dT.js} +0 -0
- /package/dist/{usage-BtQcAnf6.js → usage-BvZOzIC7.js} +0 -0
- /package/dist/{usage-format-C3mNLfhI.js → usage-format-CmniSPCG.js} +0 -0
- /package/dist/{usage-format-DAaPzr_z.js → usage-format-D_KQYQ-w.js} +0 -0
- /package/dist/{widearea-dns-CsmBVbez.js → widearea-dns-D01FFYZ8.js} +0 -0
- /package/dist/{workspace-BzPeZDew.js → workspace-BJCKO8Ns.js} +0 -0
- /package/dist/{workspace-DkGLVfOl.js → workspace-BisvA9oA.js} +0 -0
- /package/dist/{wsl-B_sPlzWw.js → wsl-PDLKeX04.js} +0 -0
- /package/dist/{wsl-BCnYV9O0.js → wsl-kFaeW76c.js} +0 -0
package/dist/extensionAPI.js
CHANGED
|
@@ -13,16 +13,13 @@ import { execFileSync, spawn } from "node:child_process";
|
|
|
13
13
|
import { fileURLToPath } from "node:url";
|
|
14
14
|
import AjvPkg from "ajv";
|
|
15
15
|
import { z } from "zod";
|
|
16
|
+
import { lookup } from "node:dns";
|
|
17
|
+
import { lookup as lookup$1 } from "node:dns/promises";
|
|
18
|
+
import { Agent } from "undici";
|
|
19
|
+
import ipaddr from "ipaddr.js";
|
|
20
|
+
import { fileTypeFromBuffer } from "file-type";
|
|
16
21
|
import { createInterface } from "node:readline";
|
|
17
22
|
|
|
18
|
-
//#region src/config/model-input.ts
|
|
19
|
-
function resolveAgentModelPrimaryValue(model) {
|
|
20
|
-
if (typeof model === "string") return model.trim() || void 0;
|
|
21
|
-
if (!model || typeof model !== "object") return;
|
|
22
|
-
return model.primary?.trim() || void 0;
|
|
23
|
-
}
|
|
24
|
-
|
|
25
|
-
//#endregion
|
|
26
23
|
//#region src/infra/home-dir.ts
|
|
27
24
|
function normalize(value) {
|
|
28
25
|
const trimmed = value?.trim();
|
|
@@ -542,8 +539,8 @@ function pruneOldRollingLogs(dir) {
|
|
|
542
539
|
|
|
543
540
|
//#endregion
|
|
544
541
|
//#region src/terminal/palette.ts
|
|
545
|
-
const
|
|
546
|
-
accent: "#
|
|
542
|
+
const PALETTE = {
|
|
543
|
+
accent: "#FF5A36",
|
|
547
544
|
accentBright: "#FF7A3D",
|
|
548
545
|
accentDim: "#D14A22",
|
|
549
546
|
info: "#FF8A5B",
|
|
@@ -559,17 +556,17 @@ const hasForceColor = typeof process.env.FORCE_COLOR === "string" && process.env
|
|
|
559
556
|
const baseChalk = process.env.NO_COLOR && !hasForceColor ? new Chalk({ level: 0 }) : chalk;
|
|
560
557
|
const hex = (value) => baseChalk.hex(value);
|
|
561
558
|
const theme = {
|
|
562
|
-
accent: hex(
|
|
563
|
-
accentBright: hex(
|
|
564
|
-
accentDim: hex(
|
|
565
|
-
info: hex(
|
|
566
|
-
success: hex(
|
|
567
|
-
warn: hex(
|
|
568
|
-
error: hex(
|
|
569
|
-
muted: hex(
|
|
570
|
-
heading: baseChalk.bold.hex(
|
|
571
|
-
command: hex(
|
|
572
|
-
option: hex(
|
|
559
|
+
accent: hex(PALETTE.accent),
|
|
560
|
+
accentBright: hex(PALETTE.accentBright),
|
|
561
|
+
accentDim: hex(PALETTE.accentDim),
|
|
562
|
+
info: hex(PALETTE.info),
|
|
563
|
+
success: hex(PALETTE.success),
|
|
564
|
+
warn: hex(PALETTE.warn),
|
|
565
|
+
error: hex(PALETTE.error),
|
|
566
|
+
muted: hex(PALETTE.muted),
|
|
567
|
+
heading: baseChalk.bold.hex(PALETTE.accent),
|
|
568
|
+
command: hex(PALETTE.accentBright),
|
|
569
|
+
option: hex(PALETTE.warn)
|
|
573
570
|
};
|
|
574
571
|
|
|
575
572
|
//#endregion
|
|
@@ -578,6 +575,10 @@ let globalVerbose = false;
|
|
|
578
575
|
function isVerbose() {
|
|
579
576
|
return globalVerbose;
|
|
580
577
|
}
|
|
578
|
+
function logVerboseConsole(message) {
|
|
579
|
+
if (!globalVerbose) return;
|
|
580
|
+
console.log(theme.muted(message));
|
|
581
|
+
}
|
|
581
582
|
const success = theme.success;
|
|
582
583
|
const warn = theme.warn;
|
|
583
584
|
const info = theme.info;
|
|
@@ -636,6 +637,8 @@ function createEmptyPluginRegistry() {
|
|
|
636
637
|
typedHooks: [],
|
|
637
638
|
channels: [],
|
|
638
639
|
providers: [],
|
|
640
|
+
sttProviders: [],
|
|
641
|
+
ttsProviders: [],
|
|
639
642
|
gatewayHandlers: {},
|
|
640
643
|
httpHandlers: [],
|
|
641
644
|
httpRoutes: [],
|
|
@@ -1087,7 +1090,8 @@ function resolveAgentConfig(cfg, agentId) {
|
|
|
1087
1090
|
groupChat: entry.groupChat,
|
|
1088
1091
|
subagents: typeof entry.subagents === "object" && entry.subagents ? entry.subagents : void 0,
|
|
1089
1092
|
sandbox: entry.sandbox,
|
|
1090
|
-
tools: entry.tools
|
|
1093
|
+
tools: entry.tools,
|
|
1094
|
+
auth: entry.auth
|
|
1091
1095
|
};
|
|
1092
1096
|
}
|
|
1093
1097
|
function resolveAgentWorkspaceDir(cfg, agentId) {
|
|
@@ -1096,6 +1100,11 @@ function resolveAgentWorkspaceDir(cfg, agentId) {
|
|
|
1096
1100
|
if (configured) return stripNullBytes(resolveUserPath(configured));
|
|
1097
1101
|
throw new Error(`agent '${id}' has no workspace configured — set agents.list[].workspace in remoteclaw.json`);
|
|
1098
1102
|
}
|
|
1103
|
+
function resolveAgentWorkspaceDirOrNull(cfg, agentId) {
|
|
1104
|
+
const configured = resolveAgentConfig(cfg, normalizeAgentId(agentId))?.workspace?.trim();
|
|
1105
|
+
if (configured) return stripNullBytes(resolveUserPath(configured));
|
|
1106
|
+
return null;
|
|
1107
|
+
}
|
|
1099
1108
|
function resolveAgentDir(cfg, agentId) {
|
|
1100
1109
|
const id = normalizeAgentId(agentId);
|
|
1101
1110
|
const configured = resolveAgentConfig(cfg, id)?.agentDir?.trim();
|
|
@@ -1104,11 +1113,6 @@ function resolveAgentDir(cfg, agentId) {
|
|
|
1104
1113
|
return path.join(root, "agents", id, "agent");
|
|
1105
1114
|
}
|
|
1106
1115
|
|
|
1107
|
-
//#endregion
|
|
1108
|
-
//#region src/agents/defaults.ts
|
|
1109
|
-
const DEFAULT_PROVIDER = "anthropic";
|
|
1110
|
-
const DEFAULT_MODEL = "claude-opus-4-6";
|
|
1111
|
-
|
|
1112
1116
|
//#endregion
|
|
1113
1117
|
//#region src/agents/identity.ts
|
|
1114
1118
|
function resolveAgentIdentity(cfg, agentId) {
|
|
@@ -1716,13 +1720,12 @@ function findDuplicateAgentDirs(cfg, deps) {
|
|
|
1716
1720
|
function formatDuplicateAgentDirError(dups) {
|
|
1717
1721
|
return [
|
|
1718
1722
|
"Duplicate agentDir detected (multi-agent config).",
|
|
1719
|
-
"Each agent must have a unique agentDir; sharing it causes
|
|
1723
|
+
"Each agent must have a unique agentDir; sharing it causes session state collisions.",
|
|
1720
1724
|
"",
|
|
1721
1725
|
"Conflicts:",
|
|
1722
1726
|
...dups.map((d) => `- ${d.agentDir}: ${d.agentIds.map((id) => `"${id}"`).join(", ")}`),
|
|
1723
1727
|
"",
|
|
1724
|
-
"Fix: remove the shared agents.list[].agentDir override (or give each agent its own directory)."
|
|
1725
|
-
"If you want to share credentials, copy auth-profiles.json instead of sharing the entire agentDir."
|
|
1728
|
+
"Fix: remove the shared agents.list[].agentDir override (or give each agent its own directory)."
|
|
1726
1729
|
].join("\n");
|
|
1727
1730
|
}
|
|
1728
1731
|
|
|
@@ -2168,7 +2171,9 @@ function applyContextPruningDefaults(cfg) {
|
|
|
2168
2171
|
};
|
|
2169
2172
|
modelsMutated = true;
|
|
2170
2173
|
}
|
|
2171
|
-
const
|
|
2174
|
+
const rawModel = defaults.model;
|
|
2175
|
+
const rawPrimary = typeof rawModel === "string" ? rawModel : rawModel?.primary;
|
|
2176
|
+
const primary = resolvePrimaryModelRef(typeof rawPrimary === "string" ? rawPrimary : void 0);
|
|
2172
2177
|
if (primary) {
|
|
2173
2178
|
const parsedPrimary = parseModelRef(primary, "anthropic");
|
|
2174
2179
|
if (isAnthropicCacheRetentionTarget(parsedPrimary)) {
|
|
@@ -2201,25 +2206,6 @@ function applyContextPruningDefaults(cfg) {
|
|
|
2201
2206
|
}
|
|
2202
2207
|
};
|
|
2203
2208
|
}
|
|
2204
|
-
function applyCompactionDefaults(cfg) {
|
|
2205
|
-
const defaults = cfg.agents?.defaults;
|
|
2206
|
-
if (!defaults) return cfg;
|
|
2207
|
-
const compaction = defaults?.compaction;
|
|
2208
|
-
if (compaction?.mode) return cfg;
|
|
2209
|
-
return {
|
|
2210
|
-
...cfg,
|
|
2211
|
-
agents: {
|
|
2212
|
-
...cfg.agents,
|
|
2213
|
-
defaults: {
|
|
2214
|
-
...defaults,
|
|
2215
|
-
compaction: {
|
|
2216
|
-
...compaction,
|
|
2217
|
-
mode: "safeguard"
|
|
2218
|
-
}
|
|
2219
|
-
}
|
|
2220
|
-
}
|
|
2221
|
-
};
|
|
2222
|
-
}
|
|
2223
2209
|
|
|
2224
2210
|
//#endregion
|
|
2225
2211
|
//#region src/config/env-preserve.ts
|
|
@@ -2648,1142 +2634,189 @@ function resolveConfigIncludes(obj, configPath, resolver = defaultResolver) {
|
|
|
2648
2634
|
}
|
|
2649
2635
|
|
|
2650
2636
|
//#endregion
|
|
2651
|
-
//#region src/config/
|
|
2652
|
-
|
|
2653
|
-
|
|
2654
|
-
|
|
2655
|
-
|
|
2656
|
-
function
|
|
2657
|
-
|
|
2658
|
-
|
|
2659
|
-
|
|
2660
|
-
|
|
2661
|
-
|
|
2662
|
-
|
|
2663
|
-
|
|
2664
|
-
|
|
2637
|
+
//#region src/config/legacy.rules.ts
|
|
2638
|
+
const LEGACY_CONFIG_RULES = [];
|
|
2639
|
+
|
|
2640
|
+
//#endregion
|
|
2641
|
+
//#region src/config/legacy.ts
|
|
2642
|
+
function findLegacyConfigIssues(raw) {
|
|
2643
|
+
if (!raw || typeof raw !== "object") return [];
|
|
2644
|
+
const root = raw;
|
|
2645
|
+
const issues = [];
|
|
2646
|
+
for (const rule of LEGACY_CONFIG_RULES) {
|
|
2647
|
+
let cursor = root;
|
|
2648
|
+
for (const key of rule.path) {
|
|
2649
|
+
if (!cursor || typeof cursor !== "object") {
|
|
2650
|
+
cursor = void 0;
|
|
2651
|
+
break;
|
|
2652
|
+
}
|
|
2653
|
+
cursor = cursor[key];
|
|
2654
|
+
}
|
|
2655
|
+
if (cursor !== void 0 && (!rule.match || rule.match(cursor, root))) issues.push({
|
|
2656
|
+
path: rule.path.join("."),
|
|
2657
|
+
message: rule.message
|
|
2658
|
+
});
|
|
2659
|
+
}
|
|
2660
|
+
return issues;
|
|
2665
2661
|
}
|
|
2666
|
-
|
|
2667
|
-
|
|
2668
|
-
|
|
2669
|
-
|
|
2662
|
+
|
|
2663
|
+
//#endregion
|
|
2664
|
+
//#region src/config/merge-patch.ts
|
|
2665
|
+
function isObjectWithStringId(value) {
|
|
2666
|
+
if (!isPlainObject$2(value)) return false;
|
|
2667
|
+
return typeof value.id === "string" && value.id.length > 0;
|
|
2670
2668
|
}
|
|
2671
|
-
|
|
2672
|
-
|
|
2673
|
-
|
|
2674
|
-
|
|
2669
|
+
/**
|
|
2670
|
+
* Merge arrays of object-like entries keyed by `id`.
|
|
2671
|
+
*
|
|
2672
|
+
* Contract:
|
|
2673
|
+
* - Base array must be fully id-keyed; otherwise return undefined (caller should replace).
|
|
2674
|
+
* - Patch entries with valid id merge by id (or append when the id is new).
|
|
2675
|
+
* - Patch entries without valid id append as-is, avoiding destructive full-array replacement.
|
|
2676
|
+
*/
|
|
2677
|
+
function mergeObjectArraysById(base, patch, options) {
|
|
2678
|
+
if (!base.every(isObjectWithStringId)) return;
|
|
2679
|
+
const merged = [...base];
|
|
2680
|
+
const indexById = /* @__PURE__ */ new Map();
|
|
2681
|
+
for (const [index, entry] of merged.entries()) {
|
|
2682
|
+
if (!isObjectWithStringId(entry)) return;
|
|
2683
|
+
indexById.set(entry.id, index);
|
|
2684
|
+
}
|
|
2685
|
+
for (const patchEntry of patch) {
|
|
2686
|
+
if (!isObjectWithStringId(patchEntry)) {
|
|
2687
|
+
merged.push(structuredClone(patchEntry));
|
|
2688
|
+
continue;
|
|
2689
|
+
}
|
|
2690
|
+
const existingIndex = indexById.get(patchEntry.id);
|
|
2691
|
+
if (existingIndex === void 0) {
|
|
2692
|
+
merged.push(structuredClone(patchEntry));
|
|
2693
|
+
indexById.set(patchEntry.id, merged.length - 1);
|
|
2694
|
+
continue;
|
|
2695
|
+
}
|
|
2696
|
+
merged[existingIndex] = applyMergePatch(merged[existingIndex], patchEntry, options);
|
|
2697
|
+
}
|
|
2698
|
+
return merged;
|
|
2675
2699
|
}
|
|
2676
|
-
function
|
|
2677
|
-
|
|
2678
|
-
|
|
2679
|
-
|
|
2680
|
-
|
|
2700
|
+
function applyMergePatch(base, patch, options = {}) {
|
|
2701
|
+
if (!isPlainObject$2(patch)) return patch;
|
|
2702
|
+
const result = isPlainObject$2(base) ? { ...base } : {};
|
|
2703
|
+
for (const [key, value] of Object.entries(patch)) {
|
|
2704
|
+
if (isBlockedObjectKey(key)) continue;
|
|
2705
|
+
if (value === null) {
|
|
2706
|
+
delete result[key];
|
|
2707
|
+
continue;
|
|
2708
|
+
}
|
|
2709
|
+
if (options.mergeObjectArraysById && Array.isArray(result[key]) && Array.isArray(value)) {
|
|
2710
|
+
const mergedArray = mergeObjectArraysById(result[key], value, options);
|
|
2711
|
+
if (mergedArray) {
|
|
2712
|
+
result[key] = mergedArray;
|
|
2713
|
+
continue;
|
|
2714
|
+
}
|
|
2715
|
+
}
|
|
2716
|
+
if (isPlainObject$2(value)) {
|
|
2717
|
+
const baseValue = result[key];
|
|
2718
|
+
result[key] = applyMergePatch(isPlainObject$2(baseValue) ? baseValue : {}, value, options);
|
|
2719
|
+
continue;
|
|
2720
|
+
}
|
|
2721
|
+
result[key] = value;
|
|
2681
2722
|
}
|
|
2682
|
-
|
|
2683
|
-
if (legacy) return legacy;
|
|
2684
|
-
if (typeof params.streaming === "boolean") return params.streaming ? "partial" : "off";
|
|
2685
|
-
return "off";
|
|
2723
|
+
return result;
|
|
2686
2724
|
}
|
|
2687
|
-
|
|
2688
|
-
|
|
2689
|
-
|
|
2690
|
-
|
|
2691
|
-
|
|
2692
|
-
|
|
2693
|
-
|
|
2725
|
+
|
|
2726
|
+
//#endregion
|
|
2727
|
+
//#region src/config/normalize-paths.ts
|
|
2728
|
+
const PATH_VALUE_RE = /^~(?=$|[\\/])/;
|
|
2729
|
+
const PATH_KEY_RE = /(dir|path|paths|file|root|workspace)$/i;
|
|
2730
|
+
const PATH_LIST_KEYS = new Set(["paths", "pathPrepend"]);
|
|
2731
|
+
function normalizeStringValue(key, value) {
|
|
2732
|
+
if (!PATH_VALUE_RE.test(value.trim())) return value;
|
|
2733
|
+
if (!key) return value;
|
|
2734
|
+
if (PATH_KEY_RE.test(key) || PATH_LIST_KEYS.has(key)) return resolveUserPath(value);
|
|
2735
|
+
return value;
|
|
2694
2736
|
}
|
|
2695
|
-
function
|
|
2696
|
-
|
|
2697
|
-
if (
|
|
2698
|
-
|
|
2699
|
-
|
|
2700
|
-
|
|
2701
|
-
|
|
2737
|
+
function normalizeAny(key, value) {
|
|
2738
|
+
if (typeof value === "string") return normalizeStringValue(key, value);
|
|
2739
|
+
if (Array.isArray(value)) {
|
|
2740
|
+
const normalizeChildren = Boolean(key && PATH_LIST_KEYS.has(key));
|
|
2741
|
+
return value.map((entry) => {
|
|
2742
|
+
if (typeof entry === "string") return normalizeChildren ? normalizeStringValue(key, entry) : entry;
|
|
2743
|
+
if (Array.isArray(entry)) return normalizeAny(void 0, entry);
|
|
2744
|
+
if (isPlainObject$2(entry)) return normalizeAny(void 0, entry);
|
|
2745
|
+
return entry;
|
|
2746
|
+
});
|
|
2747
|
+
}
|
|
2748
|
+
if (!isPlainObject$2(value)) return value;
|
|
2749
|
+
for (const [childKey, childValue] of Object.entries(value)) {
|
|
2750
|
+
const next = normalizeAny(childKey, childValue);
|
|
2751
|
+
if (next !== childValue) value[childKey] = next;
|
|
2752
|
+
}
|
|
2753
|
+
return value;
|
|
2702
2754
|
}
|
|
2703
|
-
|
|
2704
|
-
|
|
2705
|
-
|
|
2706
|
-
|
|
2755
|
+
/**
|
|
2756
|
+
* Normalize "~" paths in path-ish config fields.
|
|
2757
|
+
*
|
|
2758
|
+
* Goal: accept `~/...` consistently across config file + env overrides, while
|
|
2759
|
+
* keeping the surface area small and predictable.
|
|
2760
|
+
*/
|
|
2761
|
+
function normalizeConfigPaths(cfg) {
|
|
2762
|
+
if (!cfg || typeof cfg !== "object") return cfg;
|
|
2763
|
+
normalizeAny(void 0, cfg);
|
|
2764
|
+
return cfg;
|
|
2707
2765
|
}
|
|
2708
2766
|
|
|
2709
2767
|
//#endregion
|
|
2710
|
-
//#region src/
|
|
2711
|
-
|
|
2712
|
-
|
|
2713
|
-
|
|
2714
|
-
const
|
|
2715
|
-
|
|
2716
|
-
|
|
2717
|
-
|
|
2718
|
-
|
|
2768
|
+
//#region src/config/runtime-overrides.ts
|
|
2769
|
+
let overrides = {};
|
|
2770
|
+
function mergeOverrides(base, override) {
|
|
2771
|
+
if (!isPlainObject$2(base) || !isPlainObject$2(override)) return override;
|
|
2772
|
+
const next = { ...base };
|
|
2773
|
+
for (const [key, value] of Object.entries(override)) {
|
|
2774
|
+
if (value === void 0 || isBlockedObjectKey(key)) continue;
|
|
2775
|
+
next[key] = mergeOverrides(base[key], value);
|
|
2776
|
+
}
|
|
2777
|
+
return next;
|
|
2719
2778
|
}
|
|
2720
|
-
function
|
|
2721
|
-
if (!
|
|
2722
|
-
|
|
2723
|
-
if (!trimmed) return false;
|
|
2724
|
-
if (trimmed.includes("\0")) return false;
|
|
2725
|
-
if (CONTROL_CHARS.test(trimmed)) return false;
|
|
2726
|
-
if (SHELL_METACHARS.test(trimmed)) return false;
|
|
2727
|
-
if (QUOTE_CHARS.test(trimmed)) return false;
|
|
2728
|
-
if (isLikelyPath(trimmed)) return true;
|
|
2729
|
-
if (trimmed.startsWith("-")) return false;
|
|
2730
|
-
return BARE_NAME_PATTERN.test(trimmed);
|
|
2779
|
+
function applyConfigOverrides(cfg) {
|
|
2780
|
+
if (!overrides || Object.keys(overrides).length === 0) return cfg;
|
|
2781
|
+
return mergeOverrides(cfg, overrides);
|
|
2731
2782
|
}
|
|
2732
2783
|
|
|
2733
2784
|
//#endregion
|
|
2734
|
-
//#region src/config
|
|
2735
|
-
const
|
|
2736
|
-
|
|
2737
|
-
|
|
2738
|
-
|
|
2739
|
-
|
|
2740
|
-
|
|
2741
|
-
return
|
|
2785
|
+
//#region src/plugins/config-state.ts
|
|
2786
|
+
const BUNDLED_ENABLED_BY_DEFAULT = new Set([
|
|
2787
|
+
"device-pair",
|
|
2788
|
+
"phone-control",
|
|
2789
|
+
"talk-voice"
|
|
2790
|
+
]);
|
|
2791
|
+
const normalizeList = (value) => {
|
|
2792
|
+
if (!Array.isArray(value)) return [];
|
|
2793
|
+
return value.map((entry) => typeof entry === "string" ? entry.trim() : "").filter(Boolean);
|
|
2742
2794
|
};
|
|
2743
|
-
const
|
|
2744
|
-
|
|
2745
|
-
|
|
2746
|
-
|
|
2747
|
-
if (
|
|
2748
|
-
|
|
2795
|
+
const normalizePluginEntries = (entries) => {
|
|
2796
|
+
if (!entries || typeof entries !== "object" || Array.isArray(entries)) return {};
|
|
2797
|
+
const normalized = {};
|
|
2798
|
+
for (const [key, value] of Object.entries(entries)) {
|
|
2799
|
+
if (!key.trim()) continue;
|
|
2800
|
+
if (!value || typeof value !== "object" || Array.isArray(value)) {
|
|
2801
|
+
normalized[key] = {};
|
|
2749
2802
|
continue;
|
|
2750
2803
|
}
|
|
2751
|
-
|
|
2804
|
+
const entry = value;
|
|
2805
|
+
normalized[key] = {
|
|
2806
|
+
enabled: typeof entry.enabled === "boolean" ? entry.enabled : void 0,
|
|
2807
|
+
config: "config" in entry ? entry.config : void 0
|
|
2808
|
+
};
|
|
2752
2809
|
}
|
|
2810
|
+
return normalized;
|
|
2753
2811
|
};
|
|
2754
|
-
const
|
|
2755
|
-
|
|
2756
|
-
|
|
2757
|
-
|
|
2758
|
-
|
|
2759
|
-
|
|
2760
|
-
|
|
2761
|
-
|
|
2762
|
-
if (!isSafeExecutableValue(rawExecutable)) return null;
|
|
2763
|
-
const args = command.slice(1);
|
|
2764
|
-
const timeoutSeconds = typeof transcriber?.timeoutSeconds === "number" ? transcriber?.timeoutSeconds : void 0;
|
|
2765
|
-
const result = {
|
|
2766
|
-
command: rawExecutable,
|
|
2767
|
-
type: "cli"
|
|
2768
|
-
};
|
|
2769
|
-
if (args.length > 0) result.args = args;
|
|
2770
|
-
if (timeoutSeconds !== void 0) result.timeoutSeconds = timeoutSeconds;
|
|
2771
|
-
return result;
|
|
2772
|
-
};
|
|
2773
|
-
const getAgentsList = (agents) => {
|
|
2774
|
-
const list = agents?.list;
|
|
2775
|
-
return Array.isArray(list) ? list : [];
|
|
2776
|
-
};
|
|
2777
|
-
const resolveDefaultAgentIdFromRaw = (raw) => {
|
|
2778
|
-
const list = getAgentsList(getRecord(raw.agents));
|
|
2779
|
-
const defaultEntry = list.find((entry) => isRecord(entry) && entry.default === true && typeof entry.id === "string" && entry.id.trim() !== "");
|
|
2780
|
-
if (defaultEntry) return defaultEntry.id.trim();
|
|
2781
|
-
const routing = getRecord(raw.routing);
|
|
2782
|
-
const routingDefault = typeof routing?.defaultAgentId === "string" ? routing.defaultAgentId.trim() : "";
|
|
2783
|
-
if (routingDefault) return routingDefault;
|
|
2784
|
-
const firstEntry = list.find((entry) => isRecord(entry) && typeof entry.id === "string" && entry.id.trim() !== "");
|
|
2785
|
-
if (firstEntry) return firstEntry.id.trim();
|
|
2786
|
-
return "main";
|
|
2787
|
-
};
|
|
2788
|
-
const ensureAgentEntry = (list, id) => {
|
|
2789
|
-
const normalized = id.trim();
|
|
2790
|
-
const existing = list.find((entry) => isRecord(entry) && typeof entry.id === "string" && entry.id.trim() === normalized);
|
|
2791
|
-
if (existing) return existing;
|
|
2792
|
-
const created = { id: normalized };
|
|
2793
|
-
list.push(created);
|
|
2794
|
-
return created;
|
|
2795
|
-
};
|
|
2796
|
-
|
|
2797
|
-
//#endregion
|
|
2798
|
-
//#region src/config/legacy.migrations.part-1.ts
|
|
2799
|
-
function migrateBindings(raw, changes, changeNote, mutator) {
|
|
2800
|
-
const bindings = Array.isArray(raw.bindings) ? raw.bindings : null;
|
|
2801
|
-
if (!bindings) return;
|
|
2802
|
-
let touched = false;
|
|
2803
|
-
for (const entry of bindings) {
|
|
2804
|
-
if (!isRecord(entry)) continue;
|
|
2805
|
-
const match = getRecord(entry.match);
|
|
2806
|
-
if (!match) continue;
|
|
2807
|
-
if (!mutator(match)) continue;
|
|
2808
|
-
entry.match = match;
|
|
2809
|
-
touched = true;
|
|
2810
|
-
}
|
|
2811
|
-
if (touched) {
|
|
2812
|
-
raw.bindings = bindings;
|
|
2813
|
-
changes.push(changeNote);
|
|
2814
|
-
}
|
|
2815
|
-
}
|
|
2816
|
-
function ensureDefaultGroupEntry(section) {
|
|
2817
|
-
const groups = isRecord(section.groups) ? section.groups : {};
|
|
2818
|
-
const defaultKey = "*";
|
|
2819
|
-
return {
|
|
2820
|
-
groups,
|
|
2821
|
-
entry: isRecord(groups[defaultKey]) ? groups[defaultKey] : {}
|
|
2822
|
-
};
|
|
2823
|
-
}
|
|
2824
|
-
const LEGACY_CONFIG_MIGRATIONS_PART_1 = [
|
|
2825
|
-
{
|
|
2826
|
-
id: "bindings.match.provider->bindings.match.channel",
|
|
2827
|
-
describe: "Move bindings[].match.provider to bindings[].match.channel",
|
|
2828
|
-
apply: (raw, changes) => {
|
|
2829
|
-
migrateBindings(raw, changes, "Moved bindings[].match.provider → bindings[].match.channel.", (match) => {
|
|
2830
|
-
if (typeof match.channel === "string" && match.channel.trim()) return false;
|
|
2831
|
-
const provider = typeof match.provider === "string" ? match.provider.trim() : "";
|
|
2832
|
-
if (!provider) return false;
|
|
2833
|
-
match.channel = provider;
|
|
2834
|
-
delete match.provider;
|
|
2835
|
-
return true;
|
|
2836
|
-
});
|
|
2837
|
-
}
|
|
2838
|
-
},
|
|
2839
|
-
{
|
|
2840
|
-
id: "bindings.match.accountID->bindings.match.accountId",
|
|
2841
|
-
describe: "Move bindings[].match.accountID to bindings[].match.accountId",
|
|
2842
|
-
apply: (raw, changes) => {
|
|
2843
|
-
migrateBindings(raw, changes, "Moved bindings[].match.accountID → bindings[].match.accountId.", (match) => {
|
|
2844
|
-
if (match.accountId !== void 0) return false;
|
|
2845
|
-
const accountID = typeof match.accountID === "string" ? match.accountID.trim() : match.accountID;
|
|
2846
|
-
if (!accountID) return false;
|
|
2847
|
-
match.accountId = accountID;
|
|
2848
|
-
delete match.accountID;
|
|
2849
|
-
return true;
|
|
2850
|
-
});
|
|
2851
|
-
}
|
|
2852
|
-
},
|
|
2853
|
-
{
|
|
2854
|
-
id: "session.sendPolicy.rules.match.provider->match.channel",
|
|
2855
|
-
describe: "Move session.sendPolicy.rules[].match.provider to match.channel",
|
|
2856
|
-
apply: (raw, changes) => {
|
|
2857
|
-
const session = getRecord(raw.session);
|
|
2858
|
-
if (!session) return;
|
|
2859
|
-
const sendPolicy = getRecord(session.sendPolicy);
|
|
2860
|
-
if (!sendPolicy) return;
|
|
2861
|
-
const rules = Array.isArray(sendPolicy.rules) ? sendPolicy.rules : null;
|
|
2862
|
-
if (!rules) return;
|
|
2863
|
-
let touched = false;
|
|
2864
|
-
for (const rule of rules) {
|
|
2865
|
-
if (!isRecord(rule)) continue;
|
|
2866
|
-
const match = getRecord(rule.match);
|
|
2867
|
-
if (!match) continue;
|
|
2868
|
-
if (typeof match.channel === "string" && match.channel.trim()) continue;
|
|
2869
|
-
const provider = typeof match.provider === "string" ? match.provider.trim() : "";
|
|
2870
|
-
if (!provider) continue;
|
|
2871
|
-
match.channel = provider;
|
|
2872
|
-
delete match.provider;
|
|
2873
|
-
rule.match = match;
|
|
2874
|
-
touched = true;
|
|
2875
|
-
}
|
|
2876
|
-
if (touched) {
|
|
2877
|
-
sendPolicy.rules = rules;
|
|
2878
|
-
session.sendPolicy = sendPolicy;
|
|
2879
|
-
raw.session = session;
|
|
2880
|
-
changes.push("Moved session.sendPolicy.rules[].match.provider → match.channel.");
|
|
2881
|
-
}
|
|
2882
|
-
}
|
|
2883
|
-
},
|
|
2884
|
-
{
|
|
2885
|
-
id: "messages.queue.byProvider->byChannel",
|
|
2886
|
-
describe: "Move messages.queue.byProvider to messages.queue.byChannel",
|
|
2887
|
-
apply: (raw, changes) => {
|
|
2888
|
-
const messages = getRecord(raw.messages);
|
|
2889
|
-
if (!messages) return;
|
|
2890
|
-
const queue = getRecord(messages.queue);
|
|
2891
|
-
if (!queue) return;
|
|
2892
|
-
if (queue.byProvider === void 0) return;
|
|
2893
|
-
if (queue.byChannel === void 0) {
|
|
2894
|
-
queue.byChannel = queue.byProvider;
|
|
2895
|
-
changes.push("Moved messages.queue.byProvider → messages.queue.byChannel.");
|
|
2896
|
-
} else changes.push("Removed messages.queue.byProvider (messages.queue.byChannel already set).");
|
|
2897
|
-
delete queue.byProvider;
|
|
2898
|
-
messages.queue = queue;
|
|
2899
|
-
raw.messages = messages;
|
|
2900
|
-
}
|
|
2901
|
-
},
|
|
2902
|
-
{
|
|
2903
|
-
id: "providers->channels",
|
|
2904
|
-
describe: "Move provider config sections to channels.*",
|
|
2905
|
-
apply: (raw, changes) => {
|
|
2906
|
-
const legacyEntries = [
|
|
2907
|
-
"whatsapp",
|
|
2908
|
-
"telegram",
|
|
2909
|
-
"discord",
|
|
2910
|
-
"slack",
|
|
2911
|
-
"signal",
|
|
2912
|
-
"imessage",
|
|
2913
|
-
"msteams"
|
|
2914
|
-
].filter((key) => isRecord(raw[key]));
|
|
2915
|
-
if (legacyEntries.length === 0) return;
|
|
2916
|
-
const channels = ensureRecord(raw, "channels");
|
|
2917
|
-
for (const key of legacyEntries) {
|
|
2918
|
-
const legacy = getRecord(raw[key]);
|
|
2919
|
-
if (!legacy) continue;
|
|
2920
|
-
const channelEntry = ensureRecord(channels, key);
|
|
2921
|
-
const hadEntries = Object.keys(channelEntry).length > 0;
|
|
2922
|
-
mergeMissing(channelEntry, legacy);
|
|
2923
|
-
channels[key] = channelEntry;
|
|
2924
|
-
delete raw[key];
|
|
2925
|
-
changes.push(hadEntries ? `Merged ${key} → channels.${key}.` : `Moved ${key} → channels.${key}.`);
|
|
2926
|
-
}
|
|
2927
|
-
raw.channels = channels;
|
|
2928
|
-
}
|
|
2929
|
-
},
|
|
2930
|
-
{
|
|
2931
|
-
id: "channels.streaming-keys->channels.streaming",
|
|
2932
|
-
describe: "Normalize legacy streaming keys to channels.<provider>.streaming (Telegram/Discord/Slack)",
|
|
2933
|
-
apply: (raw, changes) => {
|
|
2934
|
-
const channels = getRecord(raw.channels);
|
|
2935
|
-
if (!channels) return;
|
|
2936
|
-
const migrateProviderEntry = (params) => {
|
|
2937
|
-
const migrateCommonStreamingMode = (resolveMode) => {
|
|
2938
|
-
const hasLegacyStreamMode = params.entry.streamMode !== void 0;
|
|
2939
|
-
const legacyStreaming = params.entry.streaming;
|
|
2940
|
-
if (!hasLegacyStreamMode && typeof legacyStreaming !== "boolean") return false;
|
|
2941
|
-
const resolved = resolveMode(params.entry);
|
|
2942
|
-
params.entry.streaming = resolved;
|
|
2943
|
-
if (hasLegacyStreamMode) {
|
|
2944
|
-
delete params.entry.streamMode;
|
|
2945
|
-
changes.push(`Moved ${params.pathPrefix}.streamMode → ${params.pathPrefix}.streaming (${resolved}).`);
|
|
2946
|
-
}
|
|
2947
|
-
if (typeof legacyStreaming === "boolean") changes.push(`Normalized ${params.pathPrefix}.streaming boolean → enum (${resolved}).`);
|
|
2948
|
-
return true;
|
|
2949
|
-
};
|
|
2950
|
-
const hasLegacyStreamMode = params.entry.streamMode !== void 0;
|
|
2951
|
-
const legacyStreaming = params.entry.streaming;
|
|
2952
|
-
const legacyNativeStreaming = params.entry.nativeStreaming;
|
|
2953
|
-
if (params.provider === "telegram") {
|
|
2954
|
-
migrateCommonStreamingMode(resolveTelegramPreviewStreamMode);
|
|
2955
|
-
return;
|
|
2956
|
-
}
|
|
2957
|
-
if (params.provider === "discord") {
|
|
2958
|
-
migrateCommonStreamingMode(resolveDiscordPreviewStreamMode);
|
|
2959
|
-
return;
|
|
2960
|
-
}
|
|
2961
|
-
if (!hasLegacyStreamMode && typeof legacyStreaming !== "boolean") return;
|
|
2962
|
-
const resolvedStreaming = resolveSlackStreamingMode(params.entry);
|
|
2963
|
-
const resolvedNativeStreaming = resolveSlackNativeStreaming(params.entry);
|
|
2964
|
-
params.entry.streaming = resolvedStreaming;
|
|
2965
|
-
params.entry.nativeStreaming = resolvedNativeStreaming;
|
|
2966
|
-
if (hasLegacyStreamMode) {
|
|
2967
|
-
delete params.entry.streamMode;
|
|
2968
|
-
changes.push(`Moved ${params.pathPrefix}.streamMode → ${params.pathPrefix}.streaming (${resolvedStreaming}).`);
|
|
2969
|
-
}
|
|
2970
|
-
if (typeof legacyStreaming === "boolean") changes.push(`Moved ${params.pathPrefix}.streaming (boolean) → ${params.pathPrefix}.nativeStreaming (${resolvedNativeStreaming}).`);
|
|
2971
|
-
else if (typeof legacyNativeStreaming !== "boolean" && hasLegacyStreamMode) changes.push(`Set ${params.pathPrefix}.nativeStreaming → ${resolvedNativeStreaming}.`);
|
|
2972
|
-
};
|
|
2973
|
-
const migrateProvider = (provider) => {
|
|
2974
|
-
const providerEntry = getRecord(channels[provider]);
|
|
2975
|
-
if (!providerEntry) return;
|
|
2976
|
-
migrateProviderEntry({
|
|
2977
|
-
provider,
|
|
2978
|
-
entry: providerEntry,
|
|
2979
|
-
pathPrefix: `channels.${provider}`
|
|
2980
|
-
});
|
|
2981
|
-
const accounts = getRecord(providerEntry.accounts);
|
|
2982
|
-
if (!accounts) return;
|
|
2983
|
-
for (const [accountId, accountValue] of Object.entries(accounts)) {
|
|
2984
|
-
const account = getRecord(accountValue);
|
|
2985
|
-
if (!account) continue;
|
|
2986
|
-
migrateProviderEntry({
|
|
2987
|
-
provider,
|
|
2988
|
-
entry: account,
|
|
2989
|
-
pathPrefix: `channels.${provider}.accounts.${accountId}`
|
|
2990
|
-
});
|
|
2991
|
-
}
|
|
2992
|
-
};
|
|
2993
|
-
migrateProvider("telegram");
|
|
2994
|
-
migrateProvider("discord");
|
|
2995
|
-
migrateProvider("slack");
|
|
2996
|
-
}
|
|
2997
|
-
},
|
|
2998
|
-
{
|
|
2999
|
-
id: "routing.allowFrom->channels.whatsapp.allowFrom",
|
|
3000
|
-
describe: "Move routing.allowFrom to channels.whatsapp.allowFrom",
|
|
3001
|
-
apply: (raw, changes) => {
|
|
3002
|
-
const routing = raw.routing;
|
|
3003
|
-
if (!routing || typeof routing !== "object") return;
|
|
3004
|
-
const allowFrom = routing.allowFrom;
|
|
3005
|
-
if (allowFrom === void 0) return;
|
|
3006
|
-
const channels = getRecord(raw.channels);
|
|
3007
|
-
const whatsapp = channels ? getRecord(channels.whatsapp) : null;
|
|
3008
|
-
if (!whatsapp) {
|
|
3009
|
-
delete routing.allowFrom;
|
|
3010
|
-
if (Object.keys(routing).length === 0) delete raw.routing;
|
|
3011
|
-
changes.push("Removed routing.allowFrom (channels.whatsapp not configured).");
|
|
3012
|
-
return;
|
|
3013
|
-
}
|
|
3014
|
-
if (whatsapp.allowFrom === void 0) {
|
|
3015
|
-
whatsapp.allowFrom = allowFrom;
|
|
3016
|
-
changes.push("Moved routing.allowFrom → channels.whatsapp.allowFrom.");
|
|
3017
|
-
} else changes.push("Removed routing.allowFrom (channels.whatsapp.allowFrom already set).");
|
|
3018
|
-
delete routing.allowFrom;
|
|
3019
|
-
if (Object.keys(routing).length === 0) delete raw.routing;
|
|
3020
|
-
channels.whatsapp = whatsapp;
|
|
3021
|
-
raw.channels = channels;
|
|
3022
|
-
}
|
|
3023
|
-
},
|
|
3024
|
-
{
|
|
3025
|
-
id: "routing.groupChat.requireMention->groups.*.requireMention",
|
|
3026
|
-
describe: "Move routing.groupChat.requireMention to channels.whatsapp/telegram/imessage groups",
|
|
3027
|
-
apply: (raw, changes) => {
|
|
3028
|
-
const routing = raw.routing;
|
|
3029
|
-
if (!routing || typeof routing !== "object") return;
|
|
3030
|
-
const groupChat = routing.groupChat && typeof routing.groupChat === "object" ? routing.groupChat : null;
|
|
3031
|
-
if (!groupChat) return;
|
|
3032
|
-
const requireMention = groupChat.requireMention;
|
|
3033
|
-
if (requireMention === void 0) return;
|
|
3034
|
-
const channels = ensureRecord(raw, "channels");
|
|
3035
|
-
const applyTo = (key, options) => {
|
|
3036
|
-
if (options?.requireExisting && !isRecord(channels[key])) return;
|
|
3037
|
-
const section = channels[key] && typeof channels[key] === "object" ? channels[key] : {};
|
|
3038
|
-
const { groups, entry } = ensureDefaultGroupEntry(section);
|
|
3039
|
-
const defaultKey = "*";
|
|
3040
|
-
if (entry.requireMention === void 0) {
|
|
3041
|
-
entry.requireMention = requireMention;
|
|
3042
|
-
groups[defaultKey] = entry;
|
|
3043
|
-
section.groups = groups;
|
|
3044
|
-
channels[key] = section;
|
|
3045
|
-
changes.push(`Moved routing.groupChat.requireMention → channels.${key}.groups."*".requireMention.`);
|
|
3046
|
-
} else changes.push(`Removed routing.groupChat.requireMention (channels.${key}.groups."*" already set).`);
|
|
3047
|
-
};
|
|
3048
|
-
applyTo("whatsapp", { requireExisting: true });
|
|
3049
|
-
applyTo("telegram");
|
|
3050
|
-
applyTo("imessage");
|
|
3051
|
-
delete groupChat.requireMention;
|
|
3052
|
-
if (Object.keys(groupChat).length === 0) delete routing.groupChat;
|
|
3053
|
-
if (Object.keys(routing).length === 0) delete raw.routing;
|
|
3054
|
-
raw.channels = channels;
|
|
3055
|
-
}
|
|
3056
|
-
},
|
|
3057
|
-
{
|
|
3058
|
-
id: "gateway.token->gateway.auth.token",
|
|
3059
|
-
describe: "Move gateway.token to gateway.auth.token",
|
|
3060
|
-
apply: (raw, changes) => {
|
|
3061
|
-
const gateway = raw.gateway;
|
|
3062
|
-
if (!gateway || typeof gateway !== "object") return;
|
|
3063
|
-
const token = gateway.token;
|
|
3064
|
-
if (token === void 0) return;
|
|
3065
|
-
const gatewayObj = gateway;
|
|
3066
|
-
const auth = gatewayObj.auth && typeof gatewayObj.auth === "object" ? gatewayObj.auth : {};
|
|
3067
|
-
if (auth.token === void 0) {
|
|
3068
|
-
auth.token = token;
|
|
3069
|
-
if (!auth.mode) auth.mode = "token";
|
|
3070
|
-
changes.push("Moved gateway.token → gateway.auth.token.");
|
|
3071
|
-
} else changes.push("Removed gateway.token (gateway.auth.token already set).");
|
|
3072
|
-
delete gatewayObj.token;
|
|
3073
|
-
if (Object.keys(auth).length > 0) gatewayObj.auth = auth;
|
|
3074
|
-
raw.gateway = gatewayObj;
|
|
3075
|
-
}
|
|
3076
|
-
},
|
|
3077
|
-
{
|
|
3078
|
-
id: "telegram.requireMention->channels.telegram.groups.*.requireMention",
|
|
3079
|
-
describe: "Move telegram.requireMention to channels.telegram.groups.*.requireMention",
|
|
3080
|
-
apply: (raw, changes) => {
|
|
3081
|
-
const channels = ensureRecord(raw, "channels");
|
|
3082
|
-
const telegram = channels.telegram;
|
|
3083
|
-
if (!telegram || typeof telegram !== "object") return;
|
|
3084
|
-
const requireMention = telegram.requireMention;
|
|
3085
|
-
if (requireMention === void 0) return;
|
|
3086
|
-
const { groups, entry } = ensureDefaultGroupEntry(telegram);
|
|
3087
|
-
const defaultKey = "*";
|
|
3088
|
-
if (entry.requireMention === void 0) {
|
|
3089
|
-
entry.requireMention = requireMention;
|
|
3090
|
-
groups[defaultKey] = entry;
|
|
3091
|
-
telegram.groups = groups;
|
|
3092
|
-
changes.push("Moved telegram.requireMention → channels.telegram.groups.\"*\".requireMention.");
|
|
3093
|
-
} else changes.push("Removed telegram.requireMention (channels.telegram.groups.\"*\" already set).");
|
|
3094
|
-
delete telegram.requireMention;
|
|
3095
|
-
channels.telegram = telegram;
|
|
3096
|
-
raw.channels = channels;
|
|
3097
|
-
}
|
|
3098
|
-
}
|
|
3099
|
-
];
|
|
3100
|
-
|
|
3101
|
-
//#endregion
|
|
3102
|
-
//#region src/config/legacy.migrations.part-2.ts
|
|
3103
|
-
function applyLegacyAudioTranscriptionModel(params) {
|
|
3104
|
-
const mapped = mapLegacyAudioTranscription(params.source);
|
|
3105
|
-
if (!mapped) {
|
|
3106
|
-
params.changes.push(params.invalidMessage);
|
|
3107
|
-
return;
|
|
3108
|
-
}
|
|
3109
|
-
const mediaAudio = ensureRecord(ensureRecord(ensureRecord(params.raw, "tools"), "media"), "audio");
|
|
3110
|
-
if ((Array.isArray(mediaAudio.models) ? mediaAudio.models : []).length === 0) {
|
|
3111
|
-
mediaAudio.enabled = true;
|
|
3112
|
-
mediaAudio.models = [mapped];
|
|
3113
|
-
params.changes.push(params.movedMessage);
|
|
3114
|
-
return;
|
|
3115
|
-
}
|
|
3116
|
-
params.changes.push(params.alreadySetMessage);
|
|
3117
|
-
}
|
|
3118
|
-
const LEGACY_CONFIG_MIGRATIONS_PART_2 = [
|
|
3119
|
-
{
|
|
3120
|
-
id: "agent.model-config-v2",
|
|
3121
|
-
describe: "Migrate legacy agent.model/allowedModels/modelAliases/modelFallbacks/imageModelFallbacks to agent.models + model lists",
|
|
3122
|
-
apply: (raw, changes) => {
|
|
3123
|
-
const agentRoot = getRecord(raw.agent);
|
|
3124
|
-
const defaults = getRecord(getRecord(raw.agents)?.defaults);
|
|
3125
|
-
const agent = agentRoot ?? defaults;
|
|
3126
|
-
if (!agent) return;
|
|
3127
|
-
const label = agentRoot ? "agent" : "agents.defaults";
|
|
3128
|
-
const legacyModel = typeof agent.model === "string" ? String(agent.model) : void 0;
|
|
3129
|
-
const legacyImageModel = typeof agent.imageModel === "string" ? String(agent.imageModel) : void 0;
|
|
3130
|
-
const legacyAllowed = Array.isArray(agent.allowedModels) ? agent.allowedModels.map(String) : [];
|
|
3131
|
-
const legacyModelFallbacks = Array.isArray(agent.modelFallbacks) ? agent.modelFallbacks.map(String) : [];
|
|
3132
|
-
const legacyImageModelFallbacks = Array.isArray(agent.imageModelFallbacks) ? agent.imageModelFallbacks.map(String) : [];
|
|
3133
|
-
const legacyAliases = agent.modelAliases && typeof agent.modelAliases === "object" ? agent.modelAliases : {};
|
|
3134
|
-
if (!(legacyModel || legacyImageModel || legacyAllowed.length > 0 || legacyModelFallbacks.length > 0 || legacyImageModelFallbacks.length > 0 || Object.keys(legacyAliases).length > 0)) return;
|
|
3135
|
-
const models = agent.models && typeof agent.models === "object" ? agent.models : {};
|
|
3136
|
-
const ensureModel = (rawKey) => {
|
|
3137
|
-
if (typeof rawKey !== "string") return;
|
|
3138
|
-
const key = rawKey.trim();
|
|
3139
|
-
if (!key) return;
|
|
3140
|
-
if (!models[key]) models[key] = {};
|
|
3141
|
-
};
|
|
3142
|
-
ensureModel(legacyModel);
|
|
3143
|
-
ensureModel(legacyImageModel);
|
|
3144
|
-
for (const key of legacyAllowed) ensureModel(key);
|
|
3145
|
-
for (const key of legacyModelFallbacks) ensureModel(key);
|
|
3146
|
-
for (const key of legacyImageModelFallbacks) ensureModel(key);
|
|
3147
|
-
for (const target of Object.values(legacyAliases)) {
|
|
3148
|
-
if (typeof target !== "string") continue;
|
|
3149
|
-
ensureModel(target);
|
|
3150
|
-
}
|
|
3151
|
-
for (const [alias, targetRaw] of Object.entries(legacyAliases)) {
|
|
3152
|
-
if (typeof targetRaw !== "string") continue;
|
|
3153
|
-
const target = targetRaw.trim();
|
|
3154
|
-
if (!target) continue;
|
|
3155
|
-
const entry = models[target] && typeof models[target] === "object" ? models[target] : {};
|
|
3156
|
-
if (!("alias" in entry)) {
|
|
3157
|
-
entry.alias = alias;
|
|
3158
|
-
models[target] = entry;
|
|
3159
|
-
}
|
|
3160
|
-
}
|
|
3161
|
-
const currentModel = agent.model && typeof agent.model === "object" ? agent.model : null;
|
|
3162
|
-
if (currentModel) {
|
|
3163
|
-
if (!currentModel.primary && legacyModel) currentModel.primary = legacyModel;
|
|
3164
|
-
if (legacyModelFallbacks.length > 0 && (!Array.isArray(currentModel.fallbacks) || currentModel.fallbacks.length === 0)) currentModel.fallbacks = legacyModelFallbacks;
|
|
3165
|
-
agent.model = currentModel;
|
|
3166
|
-
} else if (legacyModel || legacyModelFallbacks.length > 0) agent.model = {
|
|
3167
|
-
primary: legacyModel,
|
|
3168
|
-
fallbacks: legacyModelFallbacks.length ? legacyModelFallbacks : []
|
|
3169
|
-
};
|
|
3170
|
-
const currentImageModel = agent.imageModel && typeof agent.imageModel === "object" ? agent.imageModel : null;
|
|
3171
|
-
if (currentImageModel) {
|
|
3172
|
-
if (!currentImageModel.primary && legacyImageModel) currentImageModel.primary = legacyImageModel;
|
|
3173
|
-
if (legacyImageModelFallbacks.length > 0 && (!Array.isArray(currentImageModel.fallbacks) || currentImageModel.fallbacks.length === 0)) currentImageModel.fallbacks = legacyImageModelFallbacks;
|
|
3174
|
-
agent.imageModel = currentImageModel;
|
|
3175
|
-
} else if (legacyImageModel || legacyImageModelFallbacks.length > 0) agent.imageModel = {
|
|
3176
|
-
primary: legacyImageModel,
|
|
3177
|
-
fallbacks: legacyImageModelFallbacks.length ? legacyImageModelFallbacks : []
|
|
3178
|
-
};
|
|
3179
|
-
agent.models = models;
|
|
3180
|
-
if (legacyModel !== void 0) changes.push(`Migrated ${label}.model string → ${label}.model.primary.`);
|
|
3181
|
-
if (legacyModelFallbacks.length > 0) changes.push(`Migrated ${label}.modelFallbacks → ${label}.model.fallbacks.`);
|
|
3182
|
-
if (legacyImageModel !== void 0) changes.push(`Migrated ${label}.imageModel string → ${label}.imageModel.primary.`);
|
|
3183
|
-
if (legacyImageModelFallbacks.length > 0) changes.push(`Migrated ${label}.imageModelFallbacks → ${label}.imageModel.fallbacks.`);
|
|
3184
|
-
if (legacyAllowed.length > 0) changes.push(`Migrated ${label}.allowedModels → ${label}.models.`);
|
|
3185
|
-
if (Object.keys(legacyAliases).length > 0) changes.push(`Migrated ${label}.modelAliases → ${label}.models.*.alias.`);
|
|
3186
|
-
delete agent.allowedModels;
|
|
3187
|
-
delete agent.modelAliases;
|
|
3188
|
-
delete agent.modelFallbacks;
|
|
3189
|
-
delete agent.imageModelFallbacks;
|
|
3190
|
-
}
|
|
3191
|
-
},
|
|
3192
|
-
{
|
|
3193
|
-
id: "routing.agents-v2",
|
|
3194
|
-
describe: "Move routing.agents/defaultAgentId to agents.list",
|
|
3195
|
-
apply: (raw, changes) => {
|
|
3196
|
-
const routing = getRecord(raw.routing);
|
|
3197
|
-
if (!routing) return;
|
|
3198
|
-
const routingAgents = getRecord(routing.agents);
|
|
3199
|
-
const agents = ensureRecord(raw, "agents");
|
|
3200
|
-
const list = getAgentsList(agents);
|
|
3201
|
-
if (routingAgents) {
|
|
3202
|
-
for (const [rawId, entryRaw] of Object.entries(routingAgents)) {
|
|
3203
|
-
const agentId = String(rawId ?? "").trim();
|
|
3204
|
-
const entry = getRecord(entryRaw);
|
|
3205
|
-
if (!agentId || !entry) continue;
|
|
3206
|
-
const target = ensureAgentEntry(list, agentId);
|
|
3207
|
-
const entryCopy = { ...entry };
|
|
3208
|
-
if ("mentionPatterns" in entryCopy) {
|
|
3209
|
-
const mentionPatterns = entryCopy.mentionPatterns;
|
|
3210
|
-
const groupChat = ensureRecord(target, "groupChat");
|
|
3211
|
-
if (groupChat.mentionPatterns === void 0) {
|
|
3212
|
-
groupChat.mentionPatterns = mentionPatterns;
|
|
3213
|
-
changes.push(`Moved routing.agents.${agentId}.mentionPatterns → agents.list (id "${agentId}").groupChat.mentionPatterns.`);
|
|
3214
|
-
} else changes.push(`Removed routing.agents.${agentId}.mentionPatterns (agents.list groupChat mentionPatterns already set).`);
|
|
3215
|
-
delete entryCopy.mentionPatterns;
|
|
3216
|
-
}
|
|
3217
|
-
const legacyGroupChat = getRecord(entryCopy.groupChat);
|
|
3218
|
-
if (legacyGroupChat) {
|
|
3219
|
-
mergeMissing(ensureRecord(target, "groupChat"), legacyGroupChat);
|
|
3220
|
-
delete entryCopy.groupChat;
|
|
3221
|
-
}
|
|
3222
|
-
const legacySandbox = getRecord(entryCopy.sandbox);
|
|
3223
|
-
if (legacySandbox) {
|
|
3224
|
-
const sandboxTools = getRecord(legacySandbox.tools);
|
|
3225
|
-
if (sandboxTools) {
|
|
3226
|
-
mergeMissing(ensureRecord(ensureRecord(ensureRecord(target, "tools"), "sandbox"), "tools"), sandboxTools);
|
|
3227
|
-
delete legacySandbox.tools;
|
|
3228
|
-
changes.push(`Moved routing.agents.${agentId}.sandbox.tools → agents.list (id "${agentId}").tools.sandbox.tools.`);
|
|
3229
|
-
}
|
|
3230
|
-
entryCopy.sandbox = legacySandbox;
|
|
3231
|
-
}
|
|
3232
|
-
mergeMissing(target, entryCopy);
|
|
3233
|
-
}
|
|
3234
|
-
delete routing.agents;
|
|
3235
|
-
changes.push("Moved routing.agents → agents.list.");
|
|
3236
|
-
}
|
|
3237
|
-
const defaultAgentId = typeof routing.defaultAgentId === "string" ? routing.defaultAgentId.trim() : "";
|
|
3238
|
-
if (defaultAgentId) {
|
|
3239
|
-
if (!list.some((entry) => isRecord(entry) && entry.default === true)) {
|
|
3240
|
-
const entry = ensureAgentEntry(list, defaultAgentId);
|
|
3241
|
-
entry.default = true;
|
|
3242
|
-
changes.push(`Moved routing.defaultAgentId → agents.list (id "${defaultAgentId}").default.`);
|
|
3243
|
-
} else changes.push("Removed routing.defaultAgentId (agents.list default already set).");
|
|
3244
|
-
delete routing.defaultAgentId;
|
|
3245
|
-
}
|
|
3246
|
-
if (list.length > 0) agents.list = list;
|
|
3247
|
-
if (Object.keys(routing).length === 0) delete raw.routing;
|
|
3248
|
-
}
|
|
3249
|
-
},
|
|
3250
|
-
{
|
|
3251
|
-
id: "routing.config-v2",
|
|
3252
|
-
describe: "Move routing bindings/groupChat/queue/agentToAgent/transcribeAudio",
|
|
3253
|
-
apply: (raw, changes) => {
|
|
3254
|
-
const routing = getRecord(raw.routing);
|
|
3255
|
-
if (!routing) return;
|
|
3256
|
-
if (routing.bindings !== void 0) {
|
|
3257
|
-
if (raw.bindings === void 0) {
|
|
3258
|
-
raw.bindings = routing.bindings;
|
|
3259
|
-
changes.push("Moved routing.bindings → bindings.");
|
|
3260
|
-
} else changes.push("Removed routing.bindings (bindings already set).");
|
|
3261
|
-
delete routing.bindings;
|
|
3262
|
-
}
|
|
3263
|
-
if (routing.agentToAgent !== void 0) {
|
|
3264
|
-
const tools = ensureRecord(raw, "tools");
|
|
3265
|
-
if (tools.agentToAgent === void 0) {
|
|
3266
|
-
tools.agentToAgent = routing.agentToAgent;
|
|
3267
|
-
changes.push("Moved routing.agentToAgent → tools.agentToAgent.");
|
|
3268
|
-
} else changes.push("Removed routing.agentToAgent (tools.agentToAgent already set).");
|
|
3269
|
-
delete routing.agentToAgent;
|
|
3270
|
-
}
|
|
3271
|
-
if (routing.queue !== void 0) {
|
|
3272
|
-
const messages = ensureRecord(raw, "messages");
|
|
3273
|
-
if (messages.queue === void 0) {
|
|
3274
|
-
messages.queue = routing.queue;
|
|
3275
|
-
changes.push("Moved routing.queue → messages.queue.");
|
|
3276
|
-
} else changes.push("Removed routing.queue (messages.queue already set).");
|
|
3277
|
-
delete routing.queue;
|
|
3278
|
-
}
|
|
3279
|
-
const groupChat = getRecord(routing.groupChat);
|
|
3280
|
-
if (groupChat) {
|
|
3281
|
-
const historyLimit = groupChat.historyLimit;
|
|
3282
|
-
if (historyLimit !== void 0) {
|
|
3283
|
-
const messagesGroup = ensureRecord(ensureRecord(raw, "messages"), "groupChat");
|
|
3284
|
-
if (messagesGroup.historyLimit === void 0) {
|
|
3285
|
-
messagesGroup.historyLimit = historyLimit;
|
|
3286
|
-
changes.push("Moved routing.groupChat.historyLimit → messages.groupChat.historyLimit.");
|
|
3287
|
-
} else changes.push("Removed routing.groupChat.historyLimit (messages.groupChat.historyLimit already set).");
|
|
3288
|
-
delete groupChat.historyLimit;
|
|
3289
|
-
}
|
|
3290
|
-
const mentionPatterns = groupChat.mentionPatterns;
|
|
3291
|
-
if (mentionPatterns !== void 0) {
|
|
3292
|
-
const messagesGroup = ensureRecord(ensureRecord(raw, "messages"), "groupChat");
|
|
3293
|
-
if (messagesGroup.mentionPatterns === void 0) {
|
|
3294
|
-
messagesGroup.mentionPatterns = mentionPatterns;
|
|
3295
|
-
changes.push("Moved routing.groupChat.mentionPatterns → messages.groupChat.mentionPatterns.");
|
|
3296
|
-
} else changes.push("Removed routing.groupChat.mentionPatterns (messages.groupChat.mentionPatterns already set).");
|
|
3297
|
-
delete groupChat.mentionPatterns;
|
|
3298
|
-
}
|
|
3299
|
-
if (Object.keys(groupChat).length === 0) delete routing.groupChat;
|
|
3300
|
-
else routing.groupChat = groupChat;
|
|
3301
|
-
}
|
|
3302
|
-
if (routing.transcribeAudio !== void 0) {
|
|
3303
|
-
applyLegacyAudioTranscriptionModel({
|
|
3304
|
-
raw,
|
|
3305
|
-
source: routing.transcribeAudio,
|
|
3306
|
-
changes,
|
|
3307
|
-
movedMessage: "Moved routing.transcribeAudio → tools.media.audio.models.",
|
|
3308
|
-
alreadySetMessage: "Removed routing.transcribeAudio (tools.media.audio.models already set).",
|
|
3309
|
-
invalidMessage: "Removed routing.transcribeAudio (invalid or empty command)."
|
|
3310
|
-
});
|
|
3311
|
-
delete routing.transcribeAudio;
|
|
3312
|
-
}
|
|
3313
|
-
if (Object.keys(routing).length === 0) delete raw.routing;
|
|
3314
|
-
}
|
|
3315
|
-
},
|
|
3316
|
-
{
|
|
3317
|
-
id: "audio.transcription-v2",
|
|
3318
|
-
describe: "Move audio.transcription to tools.media.audio.models",
|
|
3319
|
-
apply: (raw, changes) => {
|
|
3320
|
-
const audio = getRecord(raw.audio);
|
|
3321
|
-
if (audio?.transcription === void 0) return;
|
|
3322
|
-
applyLegacyAudioTranscriptionModel({
|
|
3323
|
-
raw,
|
|
3324
|
-
source: audio.transcription,
|
|
3325
|
-
changes,
|
|
3326
|
-
movedMessage: "Moved audio.transcription → tools.media.audio.models.",
|
|
3327
|
-
alreadySetMessage: "Removed audio.transcription (tools.media.audio.models already set).",
|
|
3328
|
-
invalidMessage: "Removed audio.transcription (invalid or empty command)."
|
|
3329
|
-
});
|
|
3330
|
-
delete audio.transcription;
|
|
3331
|
-
if (Object.keys(audio).length === 0) delete raw.audio;
|
|
3332
|
-
else raw.audio = audio;
|
|
3333
|
-
}
|
|
3334
|
-
}
|
|
3335
|
-
];
|
|
3336
|
-
|
|
3337
|
-
//#endregion
|
|
3338
|
-
//#region src/config/legacy.migrations.part-3.ts
|
|
3339
|
-
const LEGACY_CONFIG_MIGRATIONS_PART_3 = [
|
|
3340
|
-
{
|
|
3341
|
-
id: "auth.anthropic-claude-cli-mode-oauth",
|
|
3342
|
-
describe: "Switch anthropic:claude-cli auth profile mode to oauth",
|
|
3343
|
-
apply: (raw, changes) => {
|
|
3344
|
-
const profiles = getRecord(getRecord(raw.auth)?.profiles);
|
|
3345
|
-
if (!profiles) return;
|
|
3346
|
-
const claudeCli = getRecord(profiles["anthropic:claude-cli"]);
|
|
3347
|
-
if (!claudeCli) return;
|
|
3348
|
-
if (claudeCli.mode !== "token") return;
|
|
3349
|
-
claudeCli.mode = "oauth";
|
|
3350
|
-
changes.push("Updated auth.profiles[\"anthropic:claude-cli\"].mode → \"oauth\".");
|
|
3351
|
-
}
|
|
3352
|
-
},
|
|
3353
|
-
{
|
|
3354
|
-
id: "tools.bash->tools.exec",
|
|
3355
|
-
describe: "Move tools.bash to tools.exec",
|
|
3356
|
-
apply: (raw, changes) => {
|
|
3357
|
-
const tools = ensureRecord(raw, "tools");
|
|
3358
|
-
const bash = getRecord(tools.bash);
|
|
3359
|
-
if (!bash) return;
|
|
3360
|
-
if (tools.exec === void 0) {
|
|
3361
|
-
tools.exec = bash;
|
|
3362
|
-
changes.push("Moved tools.bash → tools.exec.");
|
|
3363
|
-
} else changes.push("Removed tools.bash (tools.exec already set).");
|
|
3364
|
-
delete tools.bash;
|
|
3365
|
-
}
|
|
3366
|
-
},
|
|
3367
|
-
{
|
|
3368
|
-
id: "messages.tts.enabled->auto",
|
|
3369
|
-
describe: "Move messages.tts.enabled to messages.tts.auto",
|
|
3370
|
-
apply: (raw, changes) => {
|
|
3371
|
-
const tts = getRecord(getRecord(raw.messages)?.tts);
|
|
3372
|
-
if (!tts) return;
|
|
3373
|
-
if (tts.auto !== void 0) {
|
|
3374
|
-
if ("enabled" in tts) {
|
|
3375
|
-
delete tts.enabled;
|
|
3376
|
-
changes.push("Removed messages.tts.enabled (messages.tts.auto already set).");
|
|
3377
|
-
}
|
|
3378
|
-
return;
|
|
3379
|
-
}
|
|
3380
|
-
if (typeof tts.enabled !== "boolean") return;
|
|
3381
|
-
tts.auto = tts.enabled ? "always" : "off";
|
|
3382
|
-
delete tts.enabled;
|
|
3383
|
-
changes.push(`Moved messages.tts.enabled → messages.tts.auto (${String(tts.auto)}).`);
|
|
3384
|
-
}
|
|
3385
|
-
},
|
|
3386
|
-
{
|
|
3387
|
-
id: "agent.defaults-v2",
|
|
3388
|
-
describe: "Move agent config to agents.defaults and tools",
|
|
3389
|
-
apply: (raw, changes) => {
|
|
3390
|
-
const agent = getRecord(raw.agent);
|
|
3391
|
-
if (!agent) return;
|
|
3392
|
-
const agents = ensureRecord(raw, "agents");
|
|
3393
|
-
const defaults = getRecord(agents.defaults) ?? {};
|
|
3394
|
-
const tools = ensureRecord(raw, "tools");
|
|
3395
|
-
const agentTools = getRecord(agent.tools);
|
|
3396
|
-
if (agentTools) {
|
|
3397
|
-
if (tools.allow === void 0 && agentTools.allow !== void 0) {
|
|
3398
|
-
tools.allow = agentTools.allow;
|
|
3399
|
-
changes.push("Moved agent.tools.allow → tools.allow.");
|
|
3400
|
-
}
|
|
3401
|
-
if (tools.deny === void 0 && agentTools.deny !== void 0) {
|
|
3402
|
-
tools.deny = agentTools.deny;
|
|
3403
|
-
changes.push("Moved agent.tools.deny → tools.deny.");
|
|
3404
|
-
}
|
|
3405
|
-
}
|
|
3406
|
-
const elevated = getRecord(agent.elevated);
|
|
3407
|
-
if (elevated) if (tools.elevated === void 0) {
|
|
3408
|
-
tools.elevated = elevated;
|
|
3409
|
-
changes.push("Moved agent.elevated → tools.elevated.");
|
|
3410
|
-
} else changes.push("Removed agent.elevated (tools.elevated already set).");
|
|
3411
|
-
const bash = getRecord(agent.bash);
|
|
3412
|
-
if (bash) if (tools.exec === void 0) {
|
|
3413
|
-
tools.exec = bash;
|
|
3414
|
-
changes.push("Moved agent.bash → tools.exec.");
|
|
3415
|
-
} else changes.push("Removed agent.bash (tools.exec already set).");
|
|
3416
|
-
const sandbox = getRecord(agent.sandbox);
|
|
3417
|
-
if (sandbox) {
|
|
3418
|
-
const sandboxTools = getRecord(sandbox.tools);
|
|
3419
|
-
if (sandboxTools) {
|
|
3420
|
-
mergeMissing(ensureRecord(ensureRecord(tools, "sandbox"), "tools"), sandboxTools);
|
|
3421
|
-
delete sandbox.tools;
|
|
3422
|
-
changes.push("Moved agent.sandbox.tools → tools.sandbox.tools.");
|
|
3423
|
-
}
|
|
3424
|
-
}
|
|
3425
|
-
const subagents = getRecord(agent.subagents);
|
|
3426
|
-
if (subagents) {
|
|
3427
|
-
const subagentTools = getRecord(subagents.tools);
|
|
3428
|
-
if (subagentTools) {
|
|
3429
|
-
mergeMissing(ensureRecord(ensureRecord(tools, "subagents"), "tools"), subagentTools);
|
|
3430
|
-
delete subagents.tools;
|
|
3431
|
-
changes.push("Moved agent.subagents.tools → tools.subagents.tools.");
|
|
3432
|
-
}
|
|
3433
|
-
}
|
|
3434
|
-
const agentCopy = structuredClone(agent);
|
|
3435
|
-
delete agentCopy.tools;
|
|
3436
|
-
delete agentCopy.elevated;
|
|
3437
|
-
delete agentCopy.bash;
|
|
3438
|
-
if (isRecord(agentCopy.sandbox)) delete agentCopy.sandbox.tools;
|
|
3439
|
-
if (isRecord(agentCopy.subagents)) delete agentCopy.subagents.tools;
|
|
3440
|
-
mergeMissing(defaults, agentCopy);
|
|
3441
|
-
agents.defaults = defaults;
|
|
3442
|
-
raw.agents = agents;
|
|
3443
|
-
delete raw.agent;
|
|
3444
|
-
changes.push("Moved agent → agents.defaults.");
|
|
3445
|
-
}
|
|
3446
|
-
},
|
|
3447
|
-
{
|
|
3448
|
-
id: "identity->agents.list",
|
|
3449
|
-
describe: "Move identity to agents.list[].identity",
|
|
3450
|
-
apply: (raw, changes) => {
|
|
3451
|
-
const identity = getRecord(raw.identity);
|
|
3452
|
-
if (!identity) return;
|
|
3453
|
-
const agents = ensureRecord(raw, "agents");
|
|
3454
|
-
const list = getAgentsList(agents);
|
|
3455
|
-
const defaultId = resolveDefaultAgentIdFromRaw(raw);
|
|
3456
|
-
const entry = ensureAgentEntry(list, defaultId);
|
|
3457
|
-
if (entry.identity === void 0) {
|
|
3458
|
-
entry.identity = identity;
|
|
3459
|
-
changes.push(`Moved identity → agents.list (id "${defaultId}").identity.`);
|
|
3460
|
-
} else changes.push("Removed identity (agents.list identity already set).");
|
|
3461
|
-
agents.list = list;
|
|
3462
|
-
raw.agents = agents;
|
|
3463
|
-
delete raw.identity;
|
|
3464
|
-
}
|
|
3465
|
-
}
|
|
3466
|
-
];
|
|
3467
|
-
|
|
3468
|
-
//#endregion
|
|
3469
|
-
//#region src/config/legacy.migrations.ts
|
|
3470
|
-
const LEGACY_CONFIG_MIGRATIONS = [
|
|
3471
|
-
...LEGACY_CONFIG_MIGRATIONS_PART_1,
|
|
3472
|
-
...LEGACY_CONFIG_MIGRATIONS_PART_2,
|
|
3473
|
-
...LEGACY_CONFIG_MIGRATIONS_PART_3
|
|
3474
|
-
];
|
|
3475
|
-
|
|
3476
|
-
//#endregion
|
|
3477
|
-
//#region src/config/legacy.rules.ts
|
|
3478
|
-
const LEGACY_CONFIG_RULES = [
|
|
3479
|
-
{
|
|
3480
|
-
path: ["whatsapp"],
|
|
3481
|
-
message: "whatsapp config moved to channels.whatsapp (auto-migrated on load)."
|
|
3482
|
-
},
|
|
3483
|
-
{
|
|
3484
|
-
path: ["telegram"],
|
|
3485
|
-
message: "telegram config moved to channels.telegram (auto-migrated on load)."
|
|
3486
|
-
},
|
|
3487
|
-
{
|
|
3488
|
-
path: ["discord"],
|
|
3489
|
-
message: "discord config moved to channels.discord (auto-migrated on load)."
|
|
3490
|
-
},
|
|
3491
|
-
{
|
|
3492
|
-
path: ["slack"],
|
|
3493
|
-
message: "slack config moved to channels.slack (auto-migrated on load)."
|
|
3494
|
-
},
|
|
3495
|
-
{
|
|
3496
|
-
path: ["signal"],
|
|
3497
|
-
message: "signal config moved to channels.signal (auto-migrated on load)."
|
|
3498
|
-
},
|
|
3499
|
-
{
|
|
3500
|
-
path: ["imessage"],
|
|
3501
|
-
message: "imessage config moved to channels.imessage (auto-migrated on load)."
|
|
3502
|
-
},
|
|
3503
|
-
{
|
|
3504
|
-
path: ["msteams"],
|
|
3505
|
-
message: "msteams config moved to channels.msteams (auto-migrated on load)."
|
|
3506
|
-
},
|
|
3507
|
-
{
|
|
3508
|
-
path: ["routing", "allowFrom"],
|
|
3509
|
-
message: "routing.allowFrom was removed; use channels.whatsapp.allowFrom instead (auto-migrated on load)."
|
|
3510
|
-
},
|
|
3511
|
-
{
|
|
3512
|
-
path: ["routing", "bindings"],
|
|
3513
|
-
message: "routing.bindings was moved; use top-level bindings instead (auto-migrated on load)."
|
|
3514
|
-
},
|
|
3515
|
-
{
|
|
3516
|
-
path: ["routing", "agents"],
|
|
3517
|
-
message: "routing.agents was moved; use agents.list instead (auto-migrated on load)."
|
|
3518
|
-
},
|
|
3519
|
-
{
|
|
3520
|
-
path: ["routing", "defaultAgentId"],
|
|
3521
|
-
message: "routing.defaultAgentId was moved; use agents.list[].default instead (auto-migrated on load)."
|
|
3522
|
-
},
|
|
3523
|
-
{
|
|
3524
|
-
path: ["routing", "agentToAgent"],
|
|
3525
|
-
message: "routing.agentToAgent was moved; use tools.agentToAgent instead (auto-migrated on load)."
|
|
3526
|
-
},
|
|
3527
|
-
{
|
|
3528
|
-
path: [
|
|
3529
|
-
"routing",
|
|
3530
|
-
"groupChat",
|
|
3531
|
-
"requireMention"
|
|
3532
|
-
],
|
|
3533
|
-
message: "routing.groupChat.requireMention was removed; use channels.whatsapp/telegram/imessage groups defaults (e.g. channels.whatsapp.groups.\"*\".requireMention) instead (auto-migrated on load)."
|
|
3534
|
-
},
|
|
3535
|
-
{
|
|
3536
|
-
path: [
|
|
3537
|
-
"routing",
|
|
3538
|
-
"groupChat",
|
|
3539
|
-
"mentionPatterns"
|
|
3540
|
-
],
|
|
3541
|
-
message: "routing.groupChat.mentionPatterns was moved; use agents.list[].groupChat.mentionPatterns or messages.groupChat.mentionPatterns instead (auto-migrated on load)."
|
|
3542
|
-
},
|
|
3543
|
-
{
|
|
3544
|
-
path: ["routing", "queue"],
|
|
3545
|
-
message: "routing.queue was moved; use messages.queue instead (auto-migrated on load)."
|
|
3546
|
-
},
|
|
3547
|
-
{
|
|
3548
|
-
path: ["routing", "transcribeAudio"],
|
|
3549
|
-
message: "routing.transcribeAudio was moved; use tools.media.audio.models instead (auto-migrated on load)."
|
|
3550
|
-
},
|
|
3551
|
-
{
|
|
3552
|
-
path: ["telegram", "requireMention"],
|
|
3553
|
-
message: "telegram.requireMention was removed; use channels.telegram.groups.\"*\".requireMention instead (auto-migrated on load)."
|
|
3554
|
-
},
|
|
3555
|
-
{
|
|
3556
|
-
path: ["identity"],
|
|
3557
|
-
message: "identity was moved; use agents.list[].identity instead (auto-migrated on load)."
|
|
3558
|
-
},
|
|
3559
|
-
{
|
|
3560
|
-
path: ["agent"],
|
|
3561
|
-
message: "agent.* was moved; use agents.defaults (and tools.* for tool/elevated/exec settings) instead (auto-migrated on load)."
|
|
3562
|
-
},
|
|
3563
|
-
{
|
|
3564
|
-
path: ["tools", "bash"],
|
|
3565
|
-
message: "tools.bash was removed; use tools.exec instead (auto-migrated on load)."
|
|
3566
|
-
},
|
|
3567
|
-
{
|
|
3568
|
-
path: ["agent", "model"],
|
|
3569
|
-
message: "agent.model string was replaced by agents.defaults.model.primary/fallbacks and agents.defaults.models (auto-migrated on load).",
|
|
3570
|
-
match: (value) => typeof value === "string"
|
|
3571
|
-
},
|
|
3572
|
-
{
|
|
3573
|
-
path: ["agent", "imageModel"],
|
|
3574
|
-
message: "agent.imageModel string was replaced by agents.defaults.imageModel.primary/fallbacks (auto-migrated on load).",
|
|
3575
|
-
match: (value) => typeof value === "string"
|
|
3576
|
-
},
|
|
3577
|
-
{
|
|
3578
|
-
path: ["agent", "allowedModels"],
|
|
3579
|
-
message: "agent.allowedModels was replaced by agents.defaults.models (auto-migrated on load)."
|
|
3580
|
-
},
|
|
3581
|
-
{
|
|
3582
|
-
path: ["agent", "modelAliases"],
|
|
3583
|
-
message: "agent.modelAliases was replaced by agents.defaults.models.*.alias (auto-migrated on load)."
|
|
3584
|
-
},
|
|
3585
|
-
{
|
|
3586
|
-
path: ["agent", "modelFallbacks"],
|
|
3587
|
-
message: "agent.modelFallbacks was replaced by agents.defaults.model.fallbacks (auto-migrated on load)."
|
|
3588
|
-
},
|
|
3589
|
-
{
|
|
3590
|
-
path: ["agent", "imageModelFallbacks"],
|
|
3591
|
-
message: "agent.imageModelFallbacks was replaced by agents.defaults.imageModel.fallbacks (auto-migrated on load)."
|
|
3592
|
-
},
|
|
3593
|
-
{
|
|
3594
|
-
path: [
|
|
3595
|
-
"messages",
|
|
3596
|
-
"tts",
|
|
3597
|
-
"enabled"
|
|
3598
|
-
],
|
|
3599
|
-
message: "messages.tts.enabled was replaced by messages.tts.auto (auto-migrated on load)."
|
|
3600
|
-
},
|
|
3601
|
-
{
|
|
3602
|
-
path: ["gateway", "token"],
|
|
3603
|
-
message: "gateway.token is ignored; use gateway.auth.token instead (auto-migrated on load)."
|
|
3604
|
-
}
|
|
3605
|
-
];
|
|
3606
|
-
|
|
3607
|
-
//#endregion
|
|
3608
|
-
//#region src/config/legacy.ts
|
|
3609
|
-
function findLegacyConfigIssues(raw) {
|
|
3610
|
-
if (!raw || typeof raw !== "object") return [];
|
|
3611
|
-
const root = raw;
|
|
3612
|
-
const issues = [];
|
|
3613
|
-
for (const rule of LEGACY_CONFIG_RULES) {
|
|
3614
|
-
let cursor = root;
|
|
3615
|
-
for (const key of rule.path) {
|
|
3616
|
-
if (!cursor || typeof cursor !== "object") {
|
|
3617
|
-
cursor = void 0;
|
|
3618
|
-
break;
|
|
3619
|
-
}
|
|
3620
|
-
cursor = cursor[key];
|
|
3621
|
-
}
|
|
3622
|
-
if (cursor !== void 0 && (!rule.match || rule.match(cursor, root))) issues.push({
|
|
3623
|
-
path: rule.path.join("."),
|
|
3624
|
-
message: rule.message
|
|
3625
|
-
});
|
|
3626
|
-
}
|
|
3627
|
-
return issues;
|
|
3628
|
-
}
|
|
3629
|
-
|
|
3630
|
-
//#endregion
|
|
3631
|
-
//#region src/config/merge-patch.ts
|
|
3632
|
-
function isObjectWithStringId(value) {
|
|
3633
|
-
if (!isPlainObject$2(value)) return false;
|
|
3634
|
-
return typeof value.id === "string" && value.id.length > 0;
|
|
3635
|
-
}
|
|
3636
|
-
/**
|
|
3637
|
-
* Merge arrays of object-like entries keyed by `id`.
|
|
3638
|
-
*
|
|
3639
|
-
* Contract:
|
|
3640
|
-
* - Base array must be fully id-keyed; otherwise return undefined (caller should replace).
|
|
3641
|
-
* - Patch entries with valid id merge by id (or append when the id is new).
|
|
3642
|
-
* - Patch entries without valid id append as-is, avoiding destructive full-array replacement.
|
|
3643
|
-
*/
|
|
3644
|
-
function mergeObjectArraysById(base, patch, options) {
|
|
3645
|
-
if (!base.every(isObjectWithStringId)) return;
|
|
3646
|
-
const merged = [...base];
|
|
3647
|
-
const indexById = /* @__PURE__ */ new Map();
|
|
3648
|
-
for (const [index, entry] of merged.entries()) {
|
|
3649
|
-
if (!isObjectWithStringId(entry)) return;
|
|
3650
|
-
indexById.set(entry.id, index);
|
|
3651
|
-
}
|
|
3652
|
-
for (const patchEntry of patch) {
|
|
3653
|
-
if (!isObjectWithStringId(patchEntry)) {
|
|
3654
|
-
merged.push(structuredClone(patchEntry));
|
|
3655
|
-
continue;
|
|
3656
|
-
}
|
|
3657
|
-
const existingIndex = indexById.get(patchEntry.id);
|
|
3658
|
-
if (existingIndex === void 0) {
|
|
3659
|
-
merged.push(structuredClone(patchEntry));
|
|
3660
|
-
indexById.set(patchEntry.id, merged.length - 1);
|
|
3661
|
-
continue;
|
|
3662
|
-
}
|
|
3663
|
-
merged[existingIndex] = applyMergePatch(merged[existingIndex], patchEntry, options);
|
|
3664
|
-
}
|
|
3665
|
-
return merged;
|
|
3666
|
-
}
|
|
3667
|
-
function applyMergePatch(base, patch, options = {}) {
|
|
3668
|
-
if (!isPlainObject$2(patch)) return patch;
|
|
3669
|
-
const result = isPlainObject$2(base) ? { ...base } : {};
|
|
3670
|
-
for (const [key, value] of Object.entries(patch)) {
|
|
3671
|
-
if (isBlockedObjectKey(key)) continue;
|
|
3672
|
-
if (value === null) {
|
|
3673
|
-
delete result[key];
|
|
3674
|
-
continue;
|
|
3675
|
-
}
|
|
3676
|
-
if (options.mergeObjectArraysById && Array.isArray(result[key]) && Array.isArray(value)) {
|
|
3677
|
-
const mergedArray = mergeObjectArraysById(result[key], value, options);
|
|
3678
|
-
if (mergedArray) {
|
|
3679
|
-
result[key] = mergedArray;
|
|
3680
|
-
continue;
|
|
3681
|
-
}
|
|
3682
|
-
}
|
|
3683
|
-
if (isPlainObject$2(value)) {
|
|
3684
|
-
const baseValue = result[key];
|
|
3685
|
-
result[key] = applyMergePatch(isPlainObject$2(baseValue) ? baseValue : {}, value, options);
|
|
3686
|
-
continue;
|
|
3687
|
-
}
|
|
3688
|
-
result[key] = value;
|
|
3689
|
-
}
|
|
3690
|
-
return result;
|
|
3691
|
-
}
|
|
3692
|
-
|
|
3693
|
-
//#endregion
|
|
3694
|
-
//#region src/config/normalize-paths.ts
|
|
3695
|
-
const PATH_VALUE_RE = /^~(?=$|[\\/])/;
|
|
3696
|
-
const PATH_KEY_RE = /(dir|path|paths|file|root|workspace)$/i;
|
|
3697
|
-
const PATH_LIST_KEYS = new Set(["paths", "pathPrepend"]);
|
|
3698
|
-
function normalizeStringValue(key, value) {
|
|
3699
|
-
if (!PATH_VALUE_RE.test(value.trim())) return value;
|
|
3700
|
-
if (!key) return value;
|
|
3701
|
-
if (PATH_KEY_RE.test(key) || PATH_LIST_KEYS.has(key)) return resolveUserPath(value);
|
|
3702
|
-
return value;
|
|
3703
|
-
}
|
|
3704
|
-
function normalizeAny(key, value) {
|
|
3705
|
-
if (typeof value === "string") return normalizeStringValue(key, value);
|
|
3706
|
-
if (Array.isArray(value)) {
|
|
3707
|
-
const normalizeChildren = Boolean(key && PATH_LIST_KEYS.has(key));
|
|
3708
|
-
return value.map((entry) => {
|
|
3709
|
-
if (typeof entry === "string") return normalizeChildren ? normalizeStringValue(key, entry) : entry;
|
|
3710
|
-
if (Array.isArray(entry)) return normalizeAny(void 0, entry);
|
|
3711
|
-
if (isPlainObject$2(entry)) return normalizeAny(void 0, entry);
|
|
3712
|
-
return entry;
|
|
3713
|
-
});
|
|
3714
|
-
}
|
|
3715
|
-
if (!isPlainObject$2(value)) return value;
|
|
3716
|
-
for (const [childKey, childValue] of Object.entries(value)) {
|
|
3717
|
-
const next = normalizeAny(childKey, childValue);
|
|
3718
|
-
if (next !== childValue) value[childKey] = next;
|
|
3719
|
-
}
|
|
3720
|
-
return value;
|
|
3721
|
-
}
|
|
3722
|
-
/**
|
|
3723
|
-
* Normalize "~" paths in path-ish config fields.
|
|
3724
|
-
*
|
|
3725
|
-
* Goal: accept `~/...` consistently across config file + env overrides, while
|
|
3726
|
-
* keeping the surface area small and predictable.
|
|
3727
|
-
*/
|
|
3728
|
-
function normalizeConfigPaths(cfg) {
|
|
3729
|
-
if (!cfg || typeof cfg !== "object") return cfg;
|
|
3730
|
-
normalizeAny(void 0, cfg);
|
|
3731
|
-
return cfg;
|
|
3732
|
-
}
|
|
3733
|
-
|
|
3734
|
-
//#endregion
|
|
3735
|
-
//#region src/config/runtime-overrides.ts
|
|
3736
|
-
let overrides = {};
|
|
3737
|
-
function mergeOverrides(base, override) {
|
|
3738
|
-
if (!isPlainObject$2(base) || !isPlainObject$2(override)) return override;
|
|
3739
|
-
const next = { ...base };
|
|
3740
|
-
for (const [key, value] of Object.entries(override)) {
|
|
3741
|
-
if (value === void 0 || isBlockedObjectKey(key)) continue;
|
|
3742
|
-
next[key] = mergeOverrides(base[key], value);
|
|
3743
|
-
}
|
|
3744
|
-
return next;
|
|
3745
|
-
}
|
|
3746
|
-
function applyConfigOverrides(cfg) {
|
|
3747
|
-
if (!overrides || Object.keys(overrides).length === 0) return cfg;
|
|
3748
|
-
return mergeOverrides(cfg, overrides);
|
|
3749
|
-
}
|
|
3750
|
-
|
|
3751
|
-
//#endregion
|
|
3752
|
-
//#region src/plugins/config-state.ts
|
|
3753
|
-
const BUNDLED_ENABLED_BY_DEFAULT = new Set([
|
|
3754
|
-
"device-pair",
|
|
3755
|
-
"phone-control",
|
|
3756
|
-
"talk-voice"
|
|
3757
|
-
]);
|
|
3758
|
-
const normalizeList = (value) => {
|
|
3759
|
-
if (!Array.isArray(value)) return [];
|
|
3760
|
-
return value.map((entry) => typeof entry === "string" ? entry.trim() : "").filter(Boolean);
|
|
3761
|
-
};
|
|
3762
|
-
const normalizePluginEntries = (entries) => {
|
|
3763
|
-
if (!entries || typeof entries !== "object" || Array.isArray(entries)) return {};
|
|
3764
|
-
const normalized = {};
|
|
3765
|
-
for (const [key, value] of Object.entries(entries)) {
|
|
3766
|
-
if (!key.trim()) continue;
|
|
3767
|
-
if (!value || typeof value !== "object" || Array.isArray(value)) {
|
|
3768
|
-
normalized[key] = {};
|
|
3769
|
-
continue;
|
|
3770
|
-
}
|
|
3771
|
-
const entry = value;
|
|
3772
|
-
normalized[key] = {
|
|
3773
|
-
enabled: typeof entry.enabled === "boolean" ? entry.enabled : void 0,
|
|
3774
|
-
config: "config" in entry ? entry.config : void 0
|
|
3775
|
-
};
|
|
3776
|
-
}
|
|
3777
|
-
return normalized;
|
|
3778
|
-
};
|
|
3779
|
-
const normalizePluginsConfig = (config) => {
|
|
3780
|
-
return {
|
|
3781
|
-
enabled: config?.enabled !== false,
|
|
3782
|
-
allow: normalizeList(config?.allow),
|
|
3783
|
-
deny: normalizeList(config?.deny),
|
|
3784
|
-
loadPaths: normalizeList(config?.load?.paths),
|
|
3785
|
-
slots: {},
|
|
3786
|
-
entries: normalizePluginEntries(config?.entries)
|
|
2812
|
+
const normalizePluginsConfig = (config) => {
|
|
2813
|
+
return {
|
|
2814
|
+
enabled: config?.enabled !== false,
|
|
2815
|
+
allow: normalizeList(config?.allow),
|
|
2816
|
+
deny: normalizeList(config?.deny),
|
|
2817
|
+
loadPaths: normalizeList(config?.load?.paths),
|
|
2818
|
+
slots: {},
|
|
2819
|
+
entries: normalizePluginEntries(config?.entries)
|
|
3787
2820
|
};
|
|
3788
2821
|
};
|
|
3789
2822
|
function resolveEnableState(id, origin, config) {
|
|
@@ -3848,27 +2881,15 @@ function resolveBundledPluginsDir() {
|
|
|
3848
2881
|
} catch {}
|
|
3849
2882
|
}
|
|
3850
2883
|
|
|
3851
|
-
//#endregion
|
|
3852
|
-
//#region src/compat/legacy-names.ts
|
|
3853
|
-
const PROJECT_NAME = "remoteclaw";
|
|
3854
|
-
const LEGACY_PROJECT_NAMES = [];
|
|
3855
|
-
const MANIFEST_KEY = PROJECT_NAME;
|
|
3856
|
-
const LEGACY_MANIFEST_KEYS = LEGACY_PROJECT_NAMES;
|
|
3857
|
-
const LEGACY_PLUGIN_MANIFEST_FILENAMES = [];
|
|
3858
|
-
|
|
3859
2884
|
//#endregion
|
|
3860
2885
|
//#region src/plugins/manifest.ts
|
|
2886
|
+
const MANIFEST_KEY = "remoteclaw";
|
|
3861
2887
|
const PLUGIN_MANIFEST_FILENAME = "remoteclaw.plugin.json";
|
|
3862
|
-
const PLUGIN_MANIFEST_FILENAMES = [PLUGIN_MANIFEST_FILENAME, ...LEGACY_PLUGIN_MANIFEST_FILENAMES];
|
|
3863
2888
|
function normalizeStringList(value) {
|
|
3864
2889
|
if (!Array.isArray(value)) return [];
|
|
3865
2890
|
return value.map((entry) => typeof entry === "string" ? entry.trim() : "").filter(Boolean);
|
|
3866
2891
|
}
|
|
3867
2892
|
function resolvePluginManifestPath(rootDir) {
|
|
3868
|
-
for (const filename of PLUGIN_MANIFEST_FILENAMES) {
|
|
3869
|
-
const candidate = path.join(rootDir, filename);
|
|
3870
|
-
if (fs.existsSync(candidate)) return candidate;
|
|
3871
|
-
}
|
|
3872
2893
|
return path.join(rootDir, PLUGIN_MANIFEST_FILENAME);
|
|
3873
2894
|
}
|
|
3874
2895
|
function loadPluginManifest(rootDir) {
|
|
@@ -3912,6 +2933,8 @@ function loadPluginManifest(rootDir) {
|
|
|
3912
2933
|
const channels = normalizeStringList(raw.channels);
|
|
3913
2934
|
const providers = normalizeStringList(raw.providers);
|
|
3914
2935
|
const skills = normalizeStringList(raw.skills);
|
|
2936
|
+
const stt = normalizeStringList(raw.stt);
|
|
2937
|
+
const tts = normalizeStringList(raw.tts);
|
|
3915
2938
|
let uiHints;
|
|
3916
2939
|
if (isRecord(raw.uiHints)) uiHints = raw.uiHints;
|
|
3917
2940
|
return {
|
|
@@ -3923,6 +2946,8 @@ function loadPluginManifest(rootDir) {
|
|
|
3923
2946
|
channels,
|
|
3924
2947
|
providers,
|
|
3925
2948
|
skills,
|
|
2949
|
+
stt,
|
|
2950
|
+
tts,
|
|
3926
2951
|
name,
|
|
3927
2952
|
description,
|
|
3928
2953
|
version,
|
|
@@ -3933,12 +2958,7 @@ function loadPluginManifest(rootDir) {
|
|
|
3933
2958
|
}
|
|
3934
2959
|
function getPackageManifestMetadata(manifest) {
|
|
3935
2960
|
if (!manifest) return;
|
|
3936
|
-
|
|
3937
|
-
if (current) return current;
|
|
3938
|
-
for (const key of LEGACY_MANIFEST_KEYS) {
|
|
3939
|
-
const legacy = manifest[key];
|
|
3940
|
-
if (legacy) return legacy;
|
|
3941
|
-
}
|
|
2961
|
+
return manifest[MANIFEST_KEY];
|
|
3942
2962
|
}
|
|
3943
2963
|
|
|
3944
2964
|
//#endregion
|
|
@@ -4428,6 +3448,8 @@ function buildRecord(params) {
|
|
|
4428
3448
|
channels: params.manifest.channels ?? [],
|
|
4429
3449
|
providers: params.manifest.providers ?? [],
|
|
4430
3450
|
skills: params.manifest.skills ?? [],
|
|
3451
|
+
stt: params.manifest.stt ?? [],
|
|
3452
|
+
tts: params.manifest.tts ?? [],
|
|
4431
3453
|
origin: params.candidate.origin,
|
|
4432
3454
|
workspaceDir: params.candidate.workspaceDir,
|
|
4433
3455
|
rootDir: params.candidate.rootDir,
|
|
@@ -4658,34 +3680,27 @@ function parseDurationMs(raw, opts) {
|
|
|
4658
3680
|
}
|
|
4659
3681
|
|
|
4660
3682
|
//#endregion
|
|
4661
|
-
//#region src/
|
|
4662
|
-
const
|
|
4663
|
-
|
|
4664
|
-
|
|
4665
|
-
|
|
4666
|
-
|
|
4667
|
-
|
|
4668
|
-
|
|
4669
|
-
|
|
4670
|
-
|
|
4671
|
-
|
|
4672
|
-
|
|
4673
|
-
|
|
4674
|
-
|
|
4675
|
-
|
|
4676
|
-
|
|
4677
|
-
|
|
4678
|
-
|
|
4679
|
-
|
|
4680
|
-
|
|
4681
|
-
|
|
4682
|
-
channel: z.string().optional(),
|
|
4683
|
-
chatType: AllowDenyChatTypeSchema,
|
|
4684
|
-
keyPrefix: z.string().optional(),
|
|
4685
|
-
rawKeyPrefix: z.string().optional()
|
|
4686
|
-
}).strict().optional()
|
|
4687
|
-
}).strict()).optional()
|
|
4688
|
-
}).strict().optional();
|
|
3683
|
+
//#region src/infra/safe-executable-value.ts
|
|
3684
|
+
const SHELL_METACHARS = /[;&|`$<>]/;
|
|
3685
|
+
const CONTROL_CHARS = /[\r\n]/;
|
|
3686
|
+
const QUOTE_CHARS = /["']/;
|
|
3687
|
+
const BARE_NAME_PATTERN = /^[A-Za-z0-9._+-]+$/;
|
|
3688
|
+
function isLikelyPath(value) {
|
|
3689
|
+
if (value.startsWith(".") || value.startsWith("~")) return true;
|
|
3690
|
+
if (value.includes("/") || value.includes("\\")) return true;
|
|
3691
|
+
return /^[A-Za-z]:[\\/]/.test(value);
|
|
3692
|
+
}
|
|
3693
|
+
function isSafeExecutableValue(value) {
|
|
3694
|
+
if (!value) return false;
|
|
3695
|
+
const trimmed = value.trim();
|
|
3696
|
+
if (!trimmed) return false;
|
|
3697
|
+
if (trimmed.includes("\0")) return false;
|
|
3698
|
+
if (CONTROL_CHARS.test(trimmed)) return false;
|
|
3699
|
+
if (SHELL_METACHARS.test(trimmed)) return false;
|
|
3700
|
+
if (QUOTE_CHARS.test(trimmed)) return false;
|
|
3701
|
+
if (isLikelyPath(trimmed)) return true;
|
|
3702
|
+
if (trimmed.startsWith("-")) return false;
|
|
3703
|
+
return BARE_NAME_PATTERN.test(trimmed);
|
|
4689
3704
|
}
|
|
4690
3705
|
|
|
4691
3706
|
//#endregion
|
|
@@ -4772,11 +3787,7 @@ const MarkdownTableModeSchema = z.enum([
|
|
|
4772
3787
|
"code"
|
|
4773
3788
|
]);
|
|
4774
3789
|
const MarkdownConfigSchema = z.object({ tables: MarkdownTableModeSchema.optional() }).strict().optional();
|
|
4775
|
-
const TtsProviderSchema = z.
|
|
4776
|
-
"elevenlabs",
|
|
4777
|
-
"openai",
|
|
4778
|
-
"edge"
|
|
4779
|
-
]);
|
|
3790
|
+
const TtsProviderSchema = z.string().min(1);
|
|
4780
3791
|
const TtsModeSchema = z.enum(["final", "all"]);
|
|
4781
3792
|
const TtsAutoSchema = z.enum([
|
|
4782
3793
|
"off",
|
|
@@ -4954,22 +3965,6 @@ const TranscribeAudioSchema = z.object({
|
|
|
4954
3965
|
}).strict().optional();
|
|
4955
3966
|
const HexColorSchema = z.string().regex(/^#?[0-9a-fA-F]{6}$/, "expected hex color (RRGGBB)");
|
|
4956
3967
|
const ExecutableTokenSchema = z.string().refine(isSafeExecutableValue, "expected safe executable name or path");
|
|
4957
|
-
const MediaUnderstandingScopeSchema = createAllowDenyChannelRulesSchema();
|
|
4958
|
-
const MediaUnderstandingCapabilitiesSchema = z.array(z.union([
|
|
4959
|
-
z.literal("image"),
|
|
4960
|
-
z.literal("audio"),
|
|
4961
|
-
z.literal("video")
|
|
4962
|
-
])).optional();
|
|
4963
|
-
const MediaUnderstandingAttachmentsSchema = z.object({
|
|
4964
|
-
mode: z.union([z.literal("first"), z.literal("all")]).optional(),
|
|
4965
|
-
maxAttachments: z.number().int().positive().optional(),
|
|
4966
|
-
prefer: z.union([
|
|
4967
|
-
z.literal("first"),
|
|
4968
|
-
z.literal("last"),
|
|
4969
|
-
z.literal("path"),
|
|
4970
|
-
z.literal("url")
|
|
4971
|
-
]).optional()
|
|
4972
|
-
}).strict().optional();
|
|
4973
3968
|
const DeepgramAudioSchema = z.object({
|
|
4974
3969
|
detectLanguage: z.boolean().optional(),
|
|
4975
3970
|
punctuate: z.boolean().optional(),
|
|
@@ -4993,7 +3988,6 @@ const MediaUnderstandingRuntimeFields = {
|
|
|
4993
3988
|
const MediaUnderstandingModelSchema = z.object({
|
|
4994
3989
|
provider: z.string().optional(),
|
|
4995
3990
|
model: z.string().optional(),
|
|
4996
|
-
capabilities: MediaUnderstandingCapabilitiesSchema,
|
|
4997
3991
|
type: z.union([z.literal("provider"), z.literal("cli")]).optional(),
|
|
4998
3992
|
command: z.string().optional(),
|
|
4999
3993
|
args: z.array(z.string()).optional(),
|
|
@@ -5005,38 +3999,23 @@ const MediaUnderstandingModelSchema = z.object({
|
|
|
5005
3999
|
}).strict().optional();
|
|
5006
4000
|
const ToolsMediaUnderstandingSchema = z.object({
|
|
5007
4001
|
enabled: z.boolean().optional(),
|
|
5008
|
-
scope: MediaUnderstandingScopeSchema,
|
|
5009
4002
|
maxBytes: z.number().int().positive().optional(),
|
|
5010
4003
|
maxChars: z.number().int().positive().optional(),
|
|
5011
4004
|
...MediaUnderstandingRuntimeFields,
|
|
5012
|
-
attachments: MediaUnderstandingAttachmentsSchema,
|
|
5013
4005
|
models: z.array(MediaUnderstandingModelSchema).optional()
|
|
5014
4006
|
}).strict().optional();
|
|
5015
|
-
const ToolsMediaSchema = z.object({
|
|
5016
|
-
models: z.array(MediaUnderstandingModelSchema).optional(),
|
|
5017
|
-
concurrency: z.number().int().positive().optional(),
|
|
5018
|
-
image: ToolsMediaUnderstandingSchema.optional(),
|
|
5019
|
-
audio: ToolsMediaUnderstandingSchema.optional(),
|
|
5020
|
-
video: ToolsMediaUnderstandingSchema.optional()
|
|
5021
|
-
}).strict().optional();
|
|
5022
|
-
const LinkModelSchema = z.object({
|
|
5023
|
-
type: z.literal("cli").optional(),
|
|
5024
|
-
command: z.string().min(1),
|
|
5025
|
-
args: z.array(z.string()).optional(),
|
|
5026
|
-
timeoutSeconds: z.number().int().positive().optional()
|
|
5027
|
-
}).strict();
|
|
5028
|
-
const ToolsLinksSchema = z.object({
|
|
5029
|
-
enabled: z.boolean().optional(),
|
|
5030
|
-
scope: MediaUnderstandingScopeSchema,
|
|
5031
|
-
maxLinks: z.number().int().positive().optional(),
|
|
5032
|
-
timeoutSeconds: z.number().int().positive().optional(),
|
|
5033
|
-
models: z.array(LinkModelSchema).optional()
|
|
5034
|
-
}).strict().optional();
|
|
4007
|
+
const ToolsMediaSchema = z.object({ audio: ToolsMediaUnderstandingSchema.optional() }).strict().optional();
|
|
5035
4008
|
const NativeCommandsSettingSchema = z.union([z.boolean(), z.literal("auto")]);
|
|
5036
4009
|
const ProviderCommandsSchema = z.object({ native: NativeCommandsSettingSchema.optional() }).strict().optional();
|
|
5037
4010
|
|
|
5038
4011
|
//#endregion
|
|
5039
4012
|
//#region src/config/zod-schema.agent-runtime.ts
|
|
4013
|
+
/** Auth profile ref: `false` (skip), single string, or string array (rotation). */
|
|
4014
|
+
const AuthFieldSchema = z.union([
|
|
4015
|
+
z.literal(false),
|
|
4016
|
+
z.string(),
|
|
4017
|
+
z.array(z.string())
|
|
4018
|
+
]).optional();
|
|
5040
4019
|
const BootSchema = z.object({
|
|
5041
4020
|
prompt: z.string().optional(),
|
|
5042
4021
|
file: z.string().optional()
|
|
@@ -5050,7 +4029,6 @@ const HeartbeatSchema = z.object({
|
|
|
5050
4029
|
}).strict().optional(),
|
|
5051
4030
|
model: z.string().optional(),
|
|
5052
4031
|
session: z.string().optional(),
|
|
5053
|
-
includeReasoning: z.boolean().optional(),
|
|
5054
4032
|
target: z.string().optional(),
|
|
5055
4033
|
to: z.string().optional(),
|
|
5056
4034
|
accountId: z.string().optional(),
|
|
@@ -5131,7 +4109,6 @@ const ToolPolicyWithProfileSchema = z.object({
|
|
|
5131
4109
|
}).strict().superRefine((value, ctx) => {
|
|
5132
4110
|
addAllowAlsoAllowConflictIssue(value, ctx, "tools.byProvider policy cannot set both allow and alsoAllow in the same scope (merge alsoAllow into allow, or remove allow and use profile + alsoAllow)");
|
|
5133
4111
|
});
|
|
5134
|
-
const ElevatedAllowFromSchema = z.record(z.string(), z.array(z.union([z.string(), z.number()]))).optional();
|
|
5135
4112
|
const ToolExecSafeBinProfileSchema = z.object({
|
|
5136
4113
|
minPositional: z.number().int().nonnegative().optional(),
|
|
5137
4114
|
maxPositional: z.number().int().nonnegative().optional(),
|
|
@@ -5180,10 +4157,6 @@ const CommonToolPolicyFields = {
|
|
|
5180
4157
|
};
|
|
5181
4158
|
const AgentToolsSchema = z.object({
|
|
5182
4159
|
...CommonToolPolicyFields,
|
|
5183
|
-
elevated: z.object({
|
|
5184
|
-
enabled: z.boolean().optional(),
|
|
5185
|
-
allowFrom: ElevatedAllowFromSchema
|
|
5186
|
-
}).strict().optional(),
|
|
5187
4160
|
exec: AgentToolExecSchema,
|
|
5188
4161
|
fs: ToolFsSchema
|
|
5189
4162
|
}).strict().superRefine((value, ctx) => {
|
|
@@ -5195,7 +4168,7 @@ const AgentEntrySchema = z.object({
|
|
|
5195
4168
|
name: z.string().optional(),
|
|
5196
4169
|
workspace: z.string().optional(),
|
|
5197
4170
|
agentDir: z.string().optional(),
|
|
5198
|
-
model:
|
|
4171
|
+
model: z.unknown().optional(),
|
|
5199
4172
|
skills: z.array(z.string()).optional(),
|
|
5200
4173
|
humanDelay: HumanDelaySchema.optional(),
|
|
5201
4174
|
heartbeat: HeartbeatSchema,
|
|
@@ -5204,19 +4177,15 @@ const AgentEntrySchema = z.object({
|
|
|
5204
4177
|
groupChat: GroupChatSchema,
|
|
5205
4178
|
subagents: z.object({
|
|
5206
4179
|
allowAgents: z.array(z.string()).optional(),
|
|
5207
|
-
model: z.
|
|
5208
|
-
primary: z.string().optional(),
|
|
5209
|
-
fallbacks: z.array(z.string()).optional()
|
|
5210
|
-
}).strict()]).optional(),
|
|
5211
|
-
thinking: z.string().optional()
|
|
4180
|
+
model: z.unknown().optional()
|
|
5212
4181
|
}).strict().optional(),
|
|
5213
4182
|
editableFiles: z.array(z.string()).optional(),
|
|
5214
|
-
tools: AgentToolsSchema
|
|
4183
|
+
tools: AgentToolsSchema,
|
|
4184
|
+
auth: AuthFieldSchema
|
|
5215
4185
|
}).strict();
|
|
5216
4186
|
const ToolsSchema = z.object({
|
|
5217
4187
|
...CommonToolPolicyFields,
|
|
5218
4188
|
media: ToolsMediaSchema,
|
|
5219
|
-
links: ToolsLinksSchema,
|
|
5220
4189
|
sessions: z.object({ visibility: z.enum([
|
|
5221
4190
|
"self",
|
|
5222
4191
|
"tree",
|
|
@@ -5240,10 +4209,6 @@ const ToolsSchema = z.object({
|
|
|
5240
4209
|
enabled: z.boolean().optional(),
|
|
5241
4210
|
allow: z.array(z.string()).optional()
|
|
5242
4211
|
}).strict().optional(),
|
|
5243
|
-
elevated: z.object({
|
|
5244
|
-
enabled: z.boolean().optional(),
|
|
5245
|
-
allowFrom: ElevatedAllowFromSchema
|
|
5246
|
-
}).strict().optional(),
|
|
5247
4212
|
exec: ToolExecSchema,
|
|
5248
4213
|
fs: ToolFsSchema,
|
|
5249
4214
|
subagents: z.object({ tools: ToolPolicySchema }).strict().optional()
|
|
@@ -5254,17 +4219,11 @@ const ToolsSchema = z.object({
|
|
|
5254
4219
|
//#endregion
|
|
5255
4220
|
//#region src/config/zod-schema.agent-defaults.ts
|
|
5256
4221
|
const AgentDefaultsSchema = z.object({
|
|
5257
|
-
model:
|
|
5258
|
-
imageModel:
|
|
5259
|
-
models: z.
|
|
5260
|
-
|
|
5261
|
-
params: z.record(z.string(), z.unknown()).optional(),
|
|
5262
|
-
streaming: z.boolean().optional()
|
|
5263
|
-
}).strict()).optional(),
|
|
4222
|
+
model: z.unknown().optional(),
|
|
4223
|
+
imageModel: z.unknown().optional(),
|
|
4224
|
+
models: z.unknown().optional(),
|
|
4225
|
+
workspace: z.string().optional(),
|
|
5264
4226
|
repoRoot: z.string().optional(),
|
|
5265
|
-
skipBootstrap: z.boolean().optional(),
|
|
5266
|
-
bootstrapMaxChars: z.number().int().positive().optional(),
|
|
5267
|
-
bootstrapTotalMaxChars: z.number().int().positive().optional(),
|
|
5268
4227
|
userTimezone: z.string().optional(),
|
|
5269
4228
|
timeFormat: z.union([
|
|
5270
4229
|
z.literal("auto"),
|
|
@@ -5275,7 +4234,7 @@ const AgentDefaultsSchema = z.object({
|
|
|
5275
4234
|
envelopeTimestamp: z.union([z.literal("on"), z.literal("off")]).optional(),
|
|
5276
4235
|
envelopeElapsed: z.union([z.literal("on"), z.literal("off")]).optional(),
|
|
5277
4236
|
contextTokens: z.number().int().positive().optional(),
|
|
5278
|
-
cliBackends: z.
|
|
4237
|
+
cliBackends: z.unknown().optional(),
|
|
5279
4238
|
contextPruning: z.object({
|
|
5280
4239
|
mode: z.union([z.literal("off"), z.literal("cache-ttl")]).optional(),
|
|
5281
4240
|
ttl: z.string().optional(),
|
|
@@ -5297,32 +4256,11 @@ const AgentDefaultsSchema = z.object({
|
|
|
5297
4256
|
placeholder: z.string().optional()
|
|
5298
4257
|
}).strict().optional()
|
|
5299
4258
|
}).strict().optional(),
|
|
5300
|
-
compaction: z.object({
|
|
5301
|
-
mode: z.union([z.literal("default"), z.literal("safeguard")]).optional(),
|
|
5302
|
-
reserveTokens: z.number().int().nonnegative().optional(),
|
|
5303
|
-
keepRecentTokens: z.number().int().positive().optional(),
|
|
5304
|
-
reserveTokensFloor: z.number().int().nonnegative().optional(),
|
|
5305
|
-
maxHistoryShare: z.number().min(.1).max(.9).optional()
|
|
5306
|
-
}).strict().optional(),
|
|
5307
|
-
thinkingDefault: z.union([
|
|
5308
|
-
z.literal("off"),
|
|
5309
|
-
z.literal("minimal"),
|
|
5310
|
-
z.literal("low"),
|
|
5311
|
-
z.literal("medium"),
|
|
5312
|
-
z.literal("high"),
|
|
5313
|
-
z.literal("xhigh")
|
|
5314
|
-
]).optional(),
|
|
5315
4259
|
verboseDefault: z.union([
|
|
5316
4260
|
z.literal("off"),
|
|
5317
4261
|
z.literal("on"),
|
|
5318
4262
|
z.literal("full")
|
|
5319
4263
|
]).optional(),
|
|
5320
|
-
elevatedDefault: z.union([
|
|
5321
|
-
z.literal("off"),
|
|
5322
|
-
z.literal("on"),
|
|
5323
|
-
z.literal("ask"),
|
|
5324
|
-
z.literal("full")
|
|
5325
|
-
]).optional(),
|
|
5326
4264
|
blockStreamingDefault: z.union([z.literal("off"), z.literal("on")]).optional(),
|
|
5327
4265
|
blockStreamingBreak: z.union([z.literal("text_end"), z.literal("message_end")]).optional(),
|
|
5328
4266
|
blockStreamingChunk: BlockStreamingChunkSchema.optional(),
|
|
@@ -5341,8 +4279,7 @@ const AgentDefaultsSchema = z.object({
|
|
|
5341
4279
|
maxSpawnDepth: z.number().int().min(1).max(5).optional().describe("Maximum nesting depth for sub-agent spawning. 1 = no nesting (default), 2 = sub-agents can spawn sub-sub-agents."),
|
|
5342
4280
|
maxChildrenPerAgent: z.number().int().min(1).max(20).optional().describe("Maximum number of active children a single agent session can spawn (default: 5)."),
|
|
5343
4281
|
archiveAfterMinutes: z.number().int().positive().optional(),
|
|
5344
|
-
model:
|
|
5345
|
-
thinking: z.string().optional(),
|
|
4282
|
+
model: z.unknown().optional(),
|
|
5346
4283
|
runTimeoutSeconds: z.number().int().min(0).optional(),
|
|
5347
4284
|
announceTimeoutMs: z.number().int().positive().optional()
|
|
5348
4285
|
}).strict().optional(),
|
|
@@ -5353,7 +4290,10 @@ const AgentDefaultsSchema = z.object({
|
|
|
5353
4290
|
z.literal("gemini"),
|
|
5354
4291
|
z.literal("codex"),
|
|
5355
4292
|
z.literal("opencode")
|
|
5356
|
-
]).optional()
|
|
4293
|
+
]).optional(),
|
|
4294
|
+
runtimeArgs: z.array(z.string()).optional(),
|
|
4295
|
+
runtimeEnv: z.record(z.string(), z.string()).optional(),
|
|
4296
|
+
auth: AuthFieldSchema
|
|
5357
4297
|
}).strict().optional();
|
|
5358
4298
|
|
|
5359
4299
|
//#endregion
|
|
@@ -5601,6 +4541,65 @@ function isValidInboundPathRootPattern(value) {
|
|
|
5601
4541
|
return segments.every((segment) => segment === WILDCARD_SEGMENT || !segment.includes("*"));
|
|
5602
4542
|
}
|
|
5603
4543
|
|
|
4544
|
+
//#endregion
|
|
4545
|
+
//#region src/config/discord-preview-streaming.ts
|
|
4546
|
+
function normalizeStreamingMode(value) {
|
|
4547
|
+
if (typeof value !== "string") return null;
|
|
4548
|
+
return value.trim().toLowerCase() || null;
|
|
4549
|
+
}
|
|
4550
|
+
function parseStreamingMode(value) {
|
|
4551
|
+
const normalized = normalizeStreamingMode(value);
|
|
4552
|
+
if (normalized === "off" || normalized === "partial" || normalized === "block" || normalized === "progress") return normalized;
|
|
4553
|
+
return null;
|
|
4554
|
+
}
|
|
4555
|
+
function parseDiscordPreviewStreamMode(value) {
|
|
4556
|
+
const parsed = parseStreamingMode(value);
|
|
4557
|
+
if (!parsed) return null;
|
|
4558
|
+
return parsed === "progress" ? "partial" : parsed;
|
|
4559
|
+
}
|
|
4560
|
+
function parseSlackLegacyDraftStreamMode(value) {
|
|
4561
|
+
const normalized = normalizeStreamingMode(value);
|
|
4562
|
+
if (normalized === "replace" || normalized === "status_final" || normalized === "append") return normalized;
|
|
4563
|
+
return null;
|
|
4564
|
+
}
|
|
4565
|
+
function mapSlackLegacyDraftStreamModeToStreaming(mode) {
|
|
4566
|
+
if (mode === "append") return "block";
|
|
4567
|
+
if (mode === "status_final") return "progress";
|
|
4568
|
+
return "partial";
|
|
4569
|
+
}
|
|
4570
|
+
function resolveTelegramPreviewStreamMode(params = {}) {
|
|
4571
|
+
const parsedStreaming = parseStreamingMode(params.streaming);
|
|
4572
|
+
if (parsedStreaming) {
|
|
4573
|
+
if (parsedStreaming === "progress") return "partial";
|
|
4574
|
+
return parsedStreaming;
|
|
4575
|
+
}
|
|
4576
|
+
const legacy = parseDiscordPreviewStreamMode(params.streamMode);
|
|
4577
|
+
if (legacy) return legacy;
|
|
4578
|
+
if (typeof params.streaming === "boolean") return params.streaming ? "partial" : "off";
|
|
4579
|
+
return "off";
|
|
4580
|
+
}
|
|
4581
|
+
function resolveDiscordPreviewStreamMode(params = {}) {
|
|
4582
|
+
const parsedStreaming = parseDiscordPreviewStreamMode(params.streaming);
|
|
4583
|
+
if (parsedStreaming) return parsedStreaming;
|
|
4584
|
+
const legacy = parseDiscordPreviewStreamMode(params.streamMode);
|
|
4585
|
+
if (legacy) return legacy;
|
|
4586
|
+
if (typeof params.streaming === "boolean") return params.streaming ? "partial" : "off";
|
|
4587
|
+
return "off";
|
|
4588
|
+
}
|
|
4589
|
+
function resolveSlackStreamingMode(params = {}) {
|
|
4590
|
+
const parsedStreaming = parseStreamingMode(params.streaming);
|
|
4591
|
+
if (parsedStreaming) return parsedStreaming;
|
|
4592
|
+
const legacyStreamMode = parseSlackLegacyDraftStreamMode(params.streamMode);
|
|
4593
|
+
if (legacyStreamMode) return mapSlackLegacyDraftStreamModeToStreaming(legacyStreamMode);
|
|
4594
|
+
if (typeof params.streaming === "boolean") return "partial";
|
|
4595
|
+
return "partial";
|
|
4596
|
+
}
|
|
4597
|
+
function resolveSlackNativeStreaming(params = {}) {
|
|
4598
|
+
if (typeof params.nativeStreaming === "boolean") return params.nativeStreaming;
|
|
4599
|
+
if (typeof params.streaming === "boolean") return params.streaming;
|
|
4600
|
+
return true;
|
|
4601
|
+
}
|
|
4602
|
+
|
|
5604
4603
|
//#endregion
|
|
5605
4604
|
//#region src/config/telegram-custom-commands.ts
|
|
5606
4605
|
const TELEGRAM_COMMAND_NAME_PATTERN = /^[a-z0-9_]{1,32}$/;
|
|
@@ -6669,6 +5668,30 @@ const ChannelsSchema = z.object({
|
|
|
6669
5668
|
msteams: MSTeamsConfigSchema.optional()
|
|
6670
5669
|
}).passthrough().optional();
|
|
6671
5670
|
|
|
5671
|
+
//#endregion
|
|
5672
|
+
//#region src/config/zod-schema.allowdeny.ts
|
|
5673
|
+
const AllowDenyActionSchema = z.union([z.literal("allow"), z.literal("deny")]);
|
|
5674
|
+
const AllowDenyChatTypeSchema = z.union([
|
|
5675
|
+
z.literal("direct"),
|
|
5676
|
+
z.literal("group"),
|
|
5677
|
+
z.literal("channel"),
|
|
5678
|
+
z.literal("dm")
|
|
5679
|
+
]).optional();
|
|
5680
|
+
function createAllowDenyChannelRulesSchema() {
|
|
5681
|
+
return z.object({
|
|
5682
|
+
default: AllowDenyActionSchema.optional(),
|
|
5683
|
+
rules: z.array(z.object({
|
|
5684
|
+
action: AllowDenyActionSchema,
|
|
5685
|
+
match: z.object({
|
|
5686
|
+
channel: z.string().optional(),
|
|
5687
|
+
chatType: AllowDenyChatTypeSchema,
|
|
5688
|
+
keyPrefix: z.string().optional(),
|
|
5689
|
+
rawKeyPrefix: z.string().optional()
|
|
5690
|
+
}).strict().optional()
|
|
5691
|
+
}).strict()).optional()
|
|
5692
|
+
}).strict().optional();
|
|
5693
|
+
}
|
|
5694
|
+
|
|
6672
5695
|
//#endregion
|
|
6673
5696
|
//#region src/config/zod-schema.session.ts
|
|
6674
5697
|
const SessionResetConfigSchema = z.object({
|
|
@@ -6807,8 +5830,6 @@ const MessagesSchema = z.object({
|
|
|
6807
5830
|
const CommandsSchema = z.object({
|
|
6808
5831
|
native: NativeCommandsSettingSchema.optional().default("auto"),
|
|
6809
5832
|
text: z.boolean().optional(),
|
|
6810
|
-
bash: z.boolean().optional(),
|
|
6811
|
-
bashForegroundMs: z.number().int().min(0).max(3e4).optional(),
|
|
6812
5833
|
config: z.boolean().optional(),
|
|
6813
5834
|
debug: z.boolean().optional(),
|
|
6814
5835
|
restart: z.boolean().optional().default(true),
|
|
@@ -6816,7 +5837,7 @@ const CommandsSchema = z.object({
|
|
|
6816
5837
|
ownerAllowFrom: z.array(z.union([z.string(), z.number()])).optional(),
|
|
6817
5838
|
ownerDisplay: z.enum(["raw", "hash"]).optional().default("raw"),
|
|
6818
5839
|
ownerDisplaySecret: z.string().optional().register(sensitive),
|
|
6819
|
-
allowFrom:
|
|
5840
|
+
allowFrom: z.record(z.string(), z.array(z.union([z.string(), z.number()]))).optional()
|
|
6820
5841
|
}).strict().optional().default(() => ({
|
|
6821
5842
|
native: "auto",
|
|
6822
5843
|
restart: true,
|
|
@@ -6913,7 +5934,7 @@ const RemoteClawSchema = z.object({
|
|
|
6913
5934
|
channel: z.union([
|
|
6914
5935
|
z.literal("stable"),
|
|
6915
5936
|
z.literal("beta"),
|
|
6916
|
-
z.literal("
|
|
5937
|
+
z.literal("next")
|
|
6917
5938
|
]).optional(),
|
|
6918
5939
|
checkOnStart: z.boolean().optional(),
|
|
6919
5940
|
auto: z.object({
|
|
@@ -7270,7 +6291,8 @@ function validateIdentityAvatar(config) {
|
|
|
7270
6291
|
});
|
|
7271
6292
|
continue;
|
|
7272
6293
|
}
|
|
7273
|
-
|
|
6294
|
+
const workspaceDir = resolveAgentWorkspaceDirOrNull(config, entry.id ?? resolveDefaultAgentId(config));
|
|
6295
|
+
if (workspaceDir != null && !isWorkspaceAvatarPath(avatar, workspaceDir)) issues.push({
|
|
7274
6296
|
path: `agents.list.${index}.identity.avatar`,
|
|
7275
6297
|
message: "identity.avatar must stay within the agent workspace."
|
|
7276
6298
|
});
|
|
@@ -7346,7 +6368,7 @@ function validateConfigObjectWithPluginsBase(raw, opts) {
|
|
|
7346
6368
|
if (registryInfo) return registryInfo;
|
|
7347
6369
|
const registry = loadPluginManifestRegistry({
|
|
7348
6370
|
config,
|
|
7349
|
-
workspaceDir:
|
|
6371
|
+
workspaceDir: resolveAgentWorkspaceDirOrNull(config, resolveDefaultAgentId(config)) ?? void 0
|
|
7350
6372
|
});
|
|
7351
6373
|
const knownIds = new Set(registry.plugins.map((record) => record.id));
|
|
7352
6374
|
const normalizedPlugins = normalizePluginsConfig(config.plugins);
|
|
@@ -7949,7 +6971,7 @@ function createConfigIO(overrides = {}) {
|
|
|
7949
6971
|
deps.logger.warn(`Config warnings:\\n${details}`);
|
|
7950
6972
|
}
|
|
7951
6973
|
warnIfConfigFromFuture(validated.config, deps.logger);
|
|
7952
|
-
const cfg = applyTalkConfigNormalization(applyModelDefaults(
|
|
6974
|
+
const cfg = applyTalkConfigNormalization(applyModelDefaults(applyContextPruningDefaults(applyAgentDefaults(applySessionDefaults(applyLoggingDefaults(applyMessageDefaults(validated.config)))))));
|
|
7953
6975
|
normalizeConfigPaths(cfg);
|
|
7954
6976
|
const duplicates = findDuplicateAgentDirs(cfg, {
|
|
7955
6977
|
env: deps.env,
|
|
@@ -8009,7 +7031,7 @@ function createConfigIO(overrides = {}) {
|
|
|
8009
7031
|
parsed: {},
|
|
8010
7032
|
resolved: {},
|
|
8011
7033
|
valid: true,
|
|
8012
|
-
config: applyTalkApiKey(applyTalkConfigNormalization(applyModelDefaults(
|
|
7034
|
+
config: applyTalkApiKey(applyTalkConfigNormalization(applyModelDefaults(applyContextPruningDefaults(applyAgentDefaults(applySessionDefaults(applyMessageDefaults({}))))))),
|
|
8013
7035
|
hash,
|
|
8014
7036
|
issues: [],
|
|
8015
7037
|
warnings: [],
|
|
@@ -9363,22 +8385,6 @@ function loadSessionStore(storePath, opts = {}) {
|
|
|
9363
8385
|
continue;
|
|
9364
8386
|
}
|
|
9365
8387
|
}
|
|
9366
|
-
for (const entry of Object.values(store)) {
|
|
9367
|
-
if (!entry || typeof entry !== "object") continue;
|
|
9368
|
-
const rec = entry;
|
|
9369
|
-
if (typeof rec.channel !== "string" && typeof rec.provider === "string") {
|
|
9370
|
-
rec.channel = rec.provider;
|
|
9371
|
-
delete rec.provider;
|
|
9372
|
-
}
|
|
9373
|
-
if (typeof rec.lastChannel !== "string" && typeof rec.lastProvider === "string") {
|
|
9374
|
-
rec.lastChannel = rec.lastProvider;
|
|
9375
|
-
delete rec.lastProvider;
|
|
9376
|
-
}
|
|
9377
|
-
if (typeof rec.groupChannel !== "string" && typeof rec.room === "string") {
|
|
9378
|
-
rec.groupChannel = rec.room;
|
|
9379
|
-
delete rec.room;
|
|
9380
|
-
} else if ("room" in rec) delete rec.room;
|
|
9381
|
-
}
|
|
9382
8388
|
if (!opts.skipCache && isSessionStoreCacheEnabled()) SESSION_STORE_CACHE.set(storePath, {
|
|
9383
8389
|
store: structuredClone(store),
|
|
9384
8390
|
loadedAt: Date.now(),
|
|
@@ -9789,273 +8795,1160 @@ async function drainSessionStoreLockQueue(storePath) {
|
|
|
9789
8795
|
drainSessionStoreLockQueue(storePath);
|
|
9790
8796
|
});
|
|
9791
8797
|
}
|
|
9792
|
-
}
|
|
9793
|
-
async function withSessionStoreLock(storePath, fn, opts = {}) {
|
|
9794
|
-
if (!storePath || typeof storePath !== "string") throw new Error(`withSessionStoreLock: storePath must be a non-empty string, got ${JSON.stringify(storePath)}`);
|
|
9795
|
-
const timeoutMs = opts.timeoutMs ?? 1e4;
|
|
9796
|
-
const staleMs = opts.staleMs ?? 3e4;
|
|
9797
|
-
opts.pollIntervalMs;
|
|
9798
|
-
const hasTimeout = timeoutMs > 0 && Number.isFinite(timeoutMs);
|
|
9799
|
-
const queue = getOrCreateLockQueue(storePath);
|
|
9800
|
-
return await new Promise((resolve, reject) => {
|
|
9801
|
-
const task = {
|
|
9802
|
-
fn: async () => await fn(),
|
|
9803
|
-
resolve: (value) => resolve(value),
|
|
9804
|
-
reject,
|
|
9805
|
-
timeoutMs: hasTimeout ? timeoutMs : void 0,
|
|
9806
|
-
staleMs
|
|
8798
|
+
}
|
|
8799
|
+
async function withSessionStoreLock(storePath, fn, opts = {}) {
|
|
8800
|
+
if (!storePath || typeof storePath !== "string") throw new Error(`withSessionStoreLock: storePath must be a non-empty string, got ${JSON.stringify(storePath)}`);
|
|
8801
|
+
const timeoutMs = opts.timeoutMs ?? 1e4;
|
|
8802
|
+
const staleMs = opts.staleMs ?? 3e4;
|
|
8803
|
+
opts.pollIntervalMs;
|
|
8804
|
+
const hasTimeout = timeoutMs > 0 && Number.isFinite(timeoutMs);
|
|
8805
|
+
const queue = getOrCreateLockQueue(storePath);
|
|
8806
|
+
return await new Promise((resolve, reject) => {
|
|
8807
|
+
const task = {
|
|
8808
|
+
fn: async () => await fn(),
|
|
8809
|
+
resolve: (value) => resolve(value),
|
|
8810
|
+
reject,
|
|
8811
|
+
timeoutMs: hasTimeout ? timeoutMs : void 0,
|
|
8812
|
+
staleMs
|
|
8813
|
+
};
|
|
8814
|
+
queue.pending.push(task);
|
|
8815
|
+
drainSessionStoreLockQueue(storePath);
|
|
8816
|
+
});
|
|
8817
|
+
}
|
|
8818
|
+
|
|
8819
|
+
//#endregion
|
|
8820
|
+
//#region src/logger.ts
|
|
8821
|
+
const subsystemPrefixRe = /^([a-z][a-z0-9-]{1,20}):\s+(.*)$/i;
|
|
8822
|
+
function splitSubsystem(message) {
|
|
8823
|
+
const match = message.match(subsystemPrefixRe);
|
|
8824
|
+
if (!match) return null;
|
|
8825
|
+
const [, subsystem, rest] = match;
|
|
8826
|
+
return {
|
|
8827
|
+
subsystem,
|
|
8828
|
+
rest
|
|
8829
|
+
};
|
|
8830
|
+
}
|
|
8831
|
+
function logWarn(message, runtime = defaultRuntime) {
|
|
8832
|
+
const parsed = runtime === defaultRuntime ? splitSubsystem(message) : null;
|
|
8833
|
+
if (parsed) {
|
|
8834
|
+
createSubsystemLogger(parsed.subsystem).warn(parsed.rest);
|
|
8835
|
+
return;
|
|
8836
|
+
}
|
|
8837
|
+
runtime.log(warn(message));
|
|
8838
|
+
getLogger().warn(message);
|
|
8839
|
+
}
|
|
8840
|
+
function logDebug(message) {
|
|
8841
|
+
getLogger().debug(message);
|
|
8842
|
+
logVerboseConsole(message);
|
|
8843
|
+
}
|
|
8844
|
+
|
|
8845
|
+
//#endregion
|
|
8846
|
+
//#region src/plugins/hook-runner-global.ts
|
|
8847
|
+
/**
|
|
8848
|
+
* Global Plugin Hook Runner
|
|
8849
|
+
*
|
|
8850
|
+
* Singleton hook runner that's initialized when plugins are loaded
|
|
8851
|
+
* and can be called from anywhere in the codebase.
|
|
8852
|
+
*/
|
|
8853
|
+
const log = createSubsystemLogger("plugins");
|
|
8854
|
+
let globalHookRunner = null;
|
|
8855
|
+
/**
|
|
8856
|
+
* Get the global hook runner.
|
|
8857
|
+
* Returns null if plugins haven't been loaded yet.
|
|
8858
|
+
*/
|
|
8859
|
+
function getGlobalHookRunner() {
|
|
8860
|
+
return globalHookRunner;
|
|
8861
|
+
}
|
|
8862
|
+
|
|
8863
|
+
//#endregion
|
|
8864
|
+
//#region src/middleware/delivery-adapter.ts
|
|
8865
|
+
const DEFAULT_CHUNK_LIMIT = 4e3;
|
|
8866
|
+
/**
|
|
8867
|
+
* Converts AgentEvent async iterable into channel-deliverable ReplyPayload chunks.
|
|
8868
|
+
*
|
|
8869
|
+
* Handles:
|
|
8870
|
+
* - Text accumulation and chunking at channel limits
|
|
8871
|
+
* - Progressive streaming via BridgeCallbacks
|
|
8872
|
+
* - Tool result formatting
|
|
8873
|
+
* - Error event formatting
|
|
8874
|
+
*/
|
|
8875
|
+
var DeliveryAdapter = class {
|
|
8876
|
+
constructor(options) {
|
|
8877
|
+
this.chunkLimit = options?.chunkLimit ?? DEFAULT_CHUNK_LIMIT;
|
|
8878
|
+
}
|
|
8879
|
+
/**
|
|
8880
|
+
* Process an event stream, invoking callbacks for real-time delivery
|
|
8881
|
+
* and returning final payloads for post-execution delivery.
|
|
8882
|
+
*
|
|
8883
|
+
* @param events - AgentEvent async iterable from runtime.execute()
|
|
8884
|
+
* @param callbacks - Optional streaming callbacks for real-time delivery
|
|
8885
|
+
* @returns Final ReplyPayload array for post-execution delivery
|
|
8886
|
+
*/
|
|
8887
|
+
async process(events, callbacks) {
|
|
8888
|
+
let textBuffer = "";
|
|
8889
|
+
const payloads = [];
|
|
8890
|
+
/** Track media delivered via streaming events to avoid duplicates from result.media. */
|
|
8891
|
+
const deliveredMediaKeys = /* @__PURE__ */ new Set();
|
|
8892
|
+
let eventCount = 0;
|
|
8893
|
+
for await (const event of events) {
|
|
8894
|
+
eventCount++;
|
|
8895
|
+
switch (event.type) {
|
|
8896
|
+
case "text":
|
|
8897
|
+
if (event.text === "") break;
|
|
8898
|
+
textBuffer += event.text;
|
|
8899
|
+
while (textBuffer.length > this.chunkLimit) {
|
|
8900
|
+
const { chunk, rest } = splitAtBoundary(textBuffer, this.chunkLimit);
|
|
8901
|
+
textBuffer = rest;
|
|
8902
|
+
const payload = { text: chunk };
|
|
8903
|
+
payloads.push(payload);
|
|
8904
|
+
await callbacks?.onPartialReply?.(payload);
|
|
8905
|
+
}
|
|
8906
|
+
break;
|
|
8907
|
+
case "media": {
|
|
8908
|
+
const mediaUrl = event.media.filePath ?? event.media.sourceUrl;
|
|
8909
|
+
if (mediaUrl) {
|
|
8910
|
+
if (textBuffer.length > 0) {
|
|
8911
|
+
const textPayload = { text: textBuffer };
|
|
8912
|
+
payloads.push(textPayload);
|
|
8913
|
+
await callbacks?.onBlockReply?.(textPayload);
|
|
8914
|
+
textBuffer = "";
|
|
8915
|
+
}
|
|
8916
|
+
deliveredMediaKeys.add(mediaUrl);
|
|
8917
|
+
const payload = { mediaUrl };
|
|
8918
|
+
payloads.push(payload);
|
|
8919
|
+
await callbacks?.onBlockReply?.(payload);
|
|
8920
|
+
}
|
|
8921
|
+
break;
|
|
8922
|
+
}
|
|
8923
|
+
case "thinking":
|
|
8924
|
+
if (event.text) callbacks?.onThinking?.({ text: event.text });
|
|
8925
|
+
break;
|
|
8926
|
+
case "tool_use": break;
|
|
8927
|
+
case "tool_result": {
|
|
8928
|
+
const payload = { text: formatToolResult(event.toolId, event.output, event.isError) };
|
|
8929
|
+
await callbacks?.onToolResult?.(payload);
|
|
8930
|
+
break;
|
|
8931
|
+
}
|
|
8932
|
+
case "error": {
|
|
8933
|
+
const payload = {
|
|
8934
|
+
text: event.code ? `[${event.code}] ${event.message}` : event.message,
|
|
8935
|
+
isError: true
|
|
8936
|
+
};
|
|
8937
|
+
payloads.push(payload);
|
|
8938
|
+
await callbacks?.onBlockReply?.(payload);
|
|
8939
|
+
break;
|
|
8940
|
+
}
|
|
8941
|
+
case "done":
|
|
8942
|
+
if (textBuffer.length > 0) {
|
|
8943
|
+
const payload = { text: textBuffer };
|
|
8944
|
+
payloads.push(payload);
|
|
8945
|
+
await callbacks?.onBlockReply?.(payload);
|
|
8946
|
+
textBuffer = "";
|
|
8947
|
+
}
|
|
8948
|
+
if (event.result.media?.length) for (const media of event.result.media) {
|
|
8949
|
+
const url = media.filePath ?? media.sourceUrl;
|
|
8950
|
+
if (url && !deliveredMediaKeys.has(url)) {
|
|
8951
|
+
const payload = { mediaUrl: url };
|
|
8952
|
+
payloads.push(payload);
|
|
8953
|
+
await callbacks?.onBlockReply?.(payload);
|
|
8954
|
+
}
|
|
8955
|
+
}
|
|
8956
|
+
break;
|
|
8957
|
+
}
|
|
8958
|
+
}
|
|
8959
|
+
if (textBuffer.length > 0) {
|
|
8960
|
+
const payload = { text: textBuffer };
|
|
8961
|
+
payloads.push(payload);
|
|
8962
|
+
}
|
|
8963
|
+
logDebug(`[delivery-adapter] processed ${eventCount} events into ${payloads.length} payloads (chunkLimit=${this.chunkLimit})`);
|
|
8964
|
+
return payloads;
|
|
8965
|
+
}
|
|
8966
|
+
};
|
|
8967
|
+
/** Format a tool result for display. */
|
|
8968
|
+
function formatToolResult(toolId, output, isError) {
|
|
8969
|
+
return `${isError ? `Tool ${toolId} error` : `Tool ${toolId} result`}: ${output}`;
|
|
8970
|
+
}
|
|
8971
|
+
/**
|
|
8972
|
+
* Split text at the nearest safe boundary before the limit.
|
|
8973
|
+
*
|
|
8974
|
+
* Preference order:
|
|
8975
|
+
* 1. Paragraph break (\n\n)
|
|
8976
|
+
* 2. Line break (\n)
|
|
8977
|
+
* 3. Word boundary (space)
|
|
8978
|
+
* 4. Hard split at limit
|
|
8979
|
+
*
|
|
8980
|
+
* Markdown-aware: preserves code fence boundaries by closing/reopening
|
|
8981
|
+
* fences at split points when a split occurs inside a fenced code block.
|
|
8982
|
+
*/
|
|
8983
|
+
function splitAtBoundary(text, limit) {
|
|
8984
|
+
const fenceInfo = findOpenCodeFence(text, limit);
|
|
8985
|
+
if (fenceInfo !== void 0) {
|
|
8986
|
+
const beforeFence = text.substring(0, fenceInfo.fenceStart);
|
|
8987
|
+
if (beforeFence.trimEnd().length > 0) {
|
|
8988
|
+
const trimmed = beforeFence.trimEnd();
|
|
8989
|
+
return {
|
|
8990
|
+
chunk: trimmed,
|
|
8991
|
+
rest: text.substring(trimmed.length).trimStart()
|
|
8992
|
+
};
|
|
8993
|
+
}
|
|
8994
|
+
const closingFence = `\n${fenceInfo.fence}`;
|
|
8995
|
+
const openingFence = `${fenceInfo.fence}\n`;
|
|
8996
|
+
const splitPoint = findSplitPoint(text, limit - closingFence.length);
|
|
8997
|
+
return {
|
|
8998
|
+
chunk: text.substring(0, splitPoint) + closingFence,
|
|
8999
|
+
rest: openingFence + text.substring(splitPoint)
|
|
9000
|
+
};
|
|
9001
|
+
}
|
|
9002
|
+
const splitPoint = findSplitPoint(text, limit);
|
|
9003
|
+
return {
|
|
9004
|
+
chunk: text.substring(0, splitPoint),
|
|
9005
|
+
rest: text.substring(splitPoint)
|
|
9006
|
+
};
|
|
9007
|
+
}
|
|
9008
|
+
/** Find the best split point within the text up to the given limit. */
|
|
9009
|
+
function findSplitPoint(text, limit) {
|
|
9010
|
+
if (limit <= 0) return Math.min(1, text.length);
|
|
9011
|
+
const searchRegion = text.substring(0, limit);
|
|
9012
|
+
const paragraphIdx = searchRegion.lastIndexOf("\n\n");
|
|
9013
|
+
if (paragraphIdx > 0) return paragraphIdx + 2;
|
|
9014
|
+
const lineIdx = searchRegion.lastIndexOf("\n");
|
|
9015
|
+
if (lineIdx > 0) return lineIdx + 1;
|
|
9016
|
+
const spaceIdx = searchRegion.lastIndexOf(" ");
|
|
9017
|
+
if (spaceIdx > 0) return spaceIdx + 1;
|
|
9018
|
+
return limit;
|
|
9019
|
+
}
|
|
9020
|
+
/**
|
|
9021
|
+
* Detect if the text has an unclosed code fence at or before the limit position.
|
|
9022
|
+
* Returns info about the open fence, or undefined if no open fence.
|
|
9023
|
+
*/
|
|
9024
|
+
function findOpenCodeFence(text, limit) {
|
|
9025
|
+
const fenceRegex = /^(`{3,}|~{3,})/gm;
|
|
9026
|
+
let openFence;
|
|
9027
|
+
let match;
|
|
9028
|
+
while ((match = fenceRegex.exec(text)) !== null) {
|
|
9029
|
+
if (match.index >= limit) break;
|
|
9030
|
+
if (openFence === void 0) openFence = {
|
|
9031
|
+
fenceStart: match.index,
|
|
9032
|
+
fence: match[1]
|
|
9033
|
+
};
|
|
9034
|
+
else if (match[1].charAt(0) === openFence.fence.charAt(0) && match[1].length >= openFence.fence.length) openFence = void 0;
|
|
9035
|
+
}
|
|
9036
|
+
return openFence;
|
|
9037
|
+
}
|
|
9038
|
+
|
|
9039
|
+
//#endregion
|
|
9040
|
+
//#region src/middleware/error-classifier.ts
|
|
9041
|
+
const retryablePatterns = [
|
|
9042
|
+
/rate.?limit/i,
|
|
9043
|
+
/429/i,
|
|
9044
|
+
/503/i,
|
|
9045
|
+
/overloaded/i,
|
|
9046
|
+
/ETIMEDOUT/i,
|
|
9047
|
+
/ECONNRESET/i,
|
|
9048
|
+
/ECONNREFUSED/i,
|
|
9049
|
+
/network/i
|
|
9050
|
+
];
|
|
9051
|
+
const contextOverflowPatterns = [
|
|
9052
|
+
/context.?length/i,
|
|
9053
|
+
/context.?window/i,
|
|
9054
|
+
/context.?overflow/i,
|
|
9055
|
+
/too many tokens/i,
|
|
9056
|
+
/maximum context/i,
|
|
9057
|
+
/token.?limit/i
|
|
9058
|
+
];
|
|
9059
|
+
const fatalAuthPatterns = [
|
|
9060
|
+
/401/i,
|
|
9061
|
+
/403/i,
|
|
9062
|
+
/unauthorized/i,
|
|
9063
|
+
/forbidden/i,
|
|
9064
|
+
/invalid.?key/i,
|
|
9065
|
+
/authentication/i
|
|
9066
|
+
];
|
|
9067
|
+
/**
|
|
9068
|
+
* Classify an error message string into an actionable category.
|
|
9069
|
+
*
|
|
9070
|
+
* Uses first-match-wins semantics across ordered pattern arrays:
|
|
9071
|
+
* 1. Retryable patterns checked first
|
|
9072
|
+
* 2. Context overflow patterns checked second
|
|
9073
|
+
* 3. Fatal auth patterns checked third
|
|
9074
|
+
* 4. Default: "fatal" for unmatched messages
|
|
9075
|
+
*
|
|
9076
|
+
* Case-insensitive matching throughout.
|
|
9077
|
+
*/
|
|
9078
|
+
function classifyError(message) {
|
|
9079
|
+
for (const pattern of retryablePatterns) if (pattern.test(message)) {
|
|
9080
|
+
logDebug(`[error-classifier] classified as retryable: ${message.slice(0, 200)}`);
|
|
9081
|
+
return "retryable";
|
|
9082
|
+
}
|
|
9083
|
+
for (const pattern of contextOverflowPatterns) if (pattern.test(message)) {
|
|
9084
|
+
logDebug(`[error-classifier] classified as context_overflow: ${message.slice(0, 200)}`);
|
|
9085
|
+
return "context_overflow";
|
|
9086
|
+
}
|
|
9087
|
+
for (const pattern of fatalAuthPatterns) if (pattern.test(message)) {
|
|
9088
|
+
logDebug(`[error-classifier] classified as fatal (auth): ${message.slice(0, 200)}`);
|
|
9089
|
+
return "fatal";
|
|
9090
|
+
}
|
|
9091
|
+
logDebug(`[error-classifier] classified as fatal (unmatched): ${message.slice(0, 200)}`);
|
|
9092
|
+
return "fatal";
|
|
9093
|
+
}
|
|
9094
|
+
|
|
9095
|
+
//#endregion
|
|
9096
|
+
//#region src/middleware/mcp-side-effects.ts
|
|
9097
|
+
async function readMcpSideEffects(filePath) {
|
|
9098
|
+
const result = {
|
|
9099
|
+
sentTexts: [],
|
|
9100
|
+
sentMediaUrls: [],
|
|
9101
|
+
sentTargets: [],
|
|
9102
|
+
cronAdds: 0
|
|
9103
|
+
};
|
|
9104
|
+
let content;
|
|
9105
|
+
try {
|
|
9106
|
+
content = await readFile(filePath, "utf-8");
|
|
9107
|
+
} catch {
|
|
9108
|
+
return result;
|
|
9109
|
+
}
|
|
9110
|
+
const lines = content.split("\n").filter(Boolean);
|
|
9111
|
+
for (const line of lines) {
|
|
9112
|
+
let record;
|
|
9113
|
+
try {
|
|
9114
|
+
record = JSON.parse(line);
|
|
9115
|
+
} catch {
|
|
9116
|
+
continue;
|
|
9117
|
+
}
|
|
9118
|
+
if (record.type === "message_sent") {
|
|
9119
|
+
result.sentTexts.push(record.text);
|
|
9120
|
+
if (record.mediaUrl) result.sentMediaUrls.push(record.mediaUrl);
|
|
9121
|
+
const target = {
|
|
9122
|
+
tool: record.tool,
|
|
9123
|
+
provider: record.provider,
|
|
9124
|
+
...record.accountId ? { accountId: record.accountId } : {},
|
|
9125
|
+
...record.to ? { to: record.to } : {}
|
|
9126
|
+
};
|
|
9127
|
+
result.sentTargets.push(target);
|
|
9128
|
+
} else if (record.type === "cron_added") result.cronAdds += 1;
|
|
9129
|
+
else if (record.type === "heartbeat_report") result.heartbeatReport = {
|
|
9130
|
+
anythingDone: record.anythingDone,
|
|
9131
|
+
summary: record.summary
|
|
9807
9132
|
};
|
|
9808
|
-
|
|
9809
|
-
|
|
9810
|
-
});
|
|
9133
|
+
}
|
|
9134
|
+
return result;
|
|
9811
9135
|
}
|
|
9812
9136
|
|
|
9813
9137
|
//#endregion
|
|
9814
|
-
//#region src/
|
|
9138
|
+
//#region src/middleware/media-capability.ts
|
|
9815
9139
|
/**
|
|
9816
|
-
*
|
|
9140
|
+
* Partition media attachments by whether the runtime accepts them.
|
|
9817
9141
|
*
|
|
9818
|
-
*
|
|
9819
|
-
*
|
|
9142
|
+
* If the runtime does not declare `mediaCapabilities` at all, all media is
|
|
9143
|
+
* treated as supported (backwards-compatible — the runtime decides what to do).
|
|
9820
9144
|
*/
|
|
9821
|
-
|
|
9822
|
-
|
|
9145
|
+
function partitionMedia(runtime, media) {
|
|
9146
|
+
const prefixes = runtime.mediaCapabilities?.acceptsInbound;
|
|
9147
|
+
if (prefixes === void 0) return {
|
|
9148
|
+
supported: media,
|
|
9149
|
+
unsupported: []
|
|
9150
|
+
};
|
|
9151
|
+
const supported = [];
|
|
9152
|
+
const unsupported = [];
|
|
9153
|
+
for (const attachment of media) if (prefixes.some((prefix) => attachment.mimeType.startsWith(prefix))) supported.push(attachment);
|
|
9154
|
+
else unsupported.push(attachment);
|
|
9155
|
+
return {
|
|
9156
|
+
supported,
|
|
9157
|
+
unsupported
|
|
9158
|
+
};
|
|
9159
|
+
}
|
|
9823
9160
|
/**
|
|
9824
|
-
*
|
|
9825
|
-
*
|
|
9161
|
+
* Format a user-facing warning for media the runtime cannot handle.
|
|
9162
|
+
*
|
|
9163
|
+
* Returns `undefined` when there are no unsupported attachments.
|
|
9826
9164
|
*/
|
|
9827
|
-
function
|
|
9828
|
-
return
|
|
9165
|
+
function formatUnsupportedMediaWarning(unsupported, runtimeName) {
|
|
9166
|
+
if (unsupported.length === 0) return;
|
|
9167
|
+
const typeSummary = summarizeMediaTypes(unsupported);
|
|
9168
|
+
const runtimeLabel = runtimeName.toLowerCase();
|
|
9169
|
+
if (unsupported.length === 1) return `\u26a0\ufe0f Your ${typeSummary} was received but the current runtime (${runtimeLabel}) doesn't support ${typeSummary} input. Its content was not included in the conversation.`;
|
|
9170
|
+
return `\u26a0\ufe0f ${unsupported.length} media attachments were received but the current runtime (${runtimeLabel}) doesn't support them: ${typeSummary}. Their content was not included in the conversation.`;
|
|
9829
9171
|
}
|
|
9830
|
-
|
|
9831
|
-
//#endregion
|
|
9832
|
-
//#region src/middleware/delivery-adapter.ts
|
|
9833
|
-
const DEFAULT_CHUNK_LIMIT = 4e3;
|
|
9834
9172
|
/**
|
|
9835
|
-
*
|
|
9173
|
+
* Produce a human-readable summary of MIME type categories.
|
|
9836
9174
|
*
|
|
9837
|
-
*
|
|
9838
|
-
*
|
|
9839
|
-
* - Progressive streaming via BridgeCallbacks
|
|
9840
|
-
* - Tool result formatting
|
|
9841
|
-
* - Error event formatting
|
|
9175
|
+
* Groups by top-level type (image, audio, video) and deduplicates.
|
|
9176
|
+
* Falls back to "media" for unknown types.
|
|
9842
9177
|
*/
|
|
9843
|
-
|
|
9844
|
-
|
|
9845
|
-
|
|
9178
|
+
function summarizeMediaTypes(attachments) {
|
|
9179
|
+
const categories = /* @__PURE__ */ new Set();
|
|
9180
|
+
for (const a of attachments) switch (a.mimeType.split("/")[0]) {
|
|
9181
|
+
case "image":
|
|
9182
|
+
categories.add("image");
|
|
9183
|
+
break;
|
|
9184
|
+
case "audio":
|
|
9185
|
+
categories.add("audio");
|
|
9186
|
+
break;
|
|
9187
|
+
case "video":
|
|
9188
|
+
categories.add("video");
|
|
9189
|
+
break;
|
|
9190
|
+
default:
|
|
9191
|
+
categories.add("media");
|
|
9192
|
+
break;
|
|
9193
|
+
}
|
|
9194
|
+
return [...categories].toSorted().join("/");
|
|
9195
|
+
}
|
|
9196
|
+
|
|
9197
|
+
//#endregion
|
|
9198
|
+
//#region src/utils/fetch-timeout.ts
|
|
9199
|
+
/**
|
|
9200
|
+
* Relay abort without forwarding the Event argument as the abort reason.
|
|
9201
|
+
* Using .bind() avoids closure scope capture (memory leak prevention).
|
|
9202
|
+
*/
|
|
9203
|
+
function relayAbort() {
|
|
9204
|
+
this.abort();
|
|
9205
|
+
}
|
|
9206
|
+
/** Returns a bound abort relay for use as an event listener. */
|
|
9207
|
+
function bindAbortRelay(controller) {
|
|
9208
|
+
return relayAbort.bind(controller);
|
|
9209
|
+
}
|
|
9210
|
+
|
|
9211
|
+
//#endregion
|
|
9212
|
+
//#region src/shared/net/ip.ts
|
|
9213
|
+
const BLOCKED_IPV4_SPECIAL_USE_RANGES = new Set([
|
|
9214
|
+
"unspecified",
|
|
9215
|
+
"broadcast",
|
|
9216
|
+
"multicast",
|
|
9217
|
+
"linkLocal",
|
|
9218
|
+
"loopback",
|
|
9219
|
+
"carrierGradeNat",
|
|
9220
|
+
"private",
|
|
9221
|
+
"reserved"
|
|
9222
|
+
]);
|
|
9223
|
+
const PRIVATE_OR_LOOPBACK_IPV4_RANGES = new Set([
|
|
9224
|
+
"loopback",
|
|
9225
|
+
"private",
|
|
9226
|
+
"linkLocal",
|
|
9227
|
+
"carrierGradeNat"
|
|
9228
|
+
]);
|
|
9229
|
+
const PRIVATE_OR_LOOPBACK_IPV6_RANGES = new Set([
|
|
9230
|
+
"unspecified",
|
|
9231
|
+
"loopback",
|
|
9232
|
+
"linkLocal",
|
|
9233
|
+
"uniqueLocal"
|
|
9234
|
+
]);
|
|
9235
|
+
const RFC2544_BENCHMARK_PREFIX = [ipaddr.IPv4.parse("198.18.0.0"), 15];
|
|
9236
|
+
const EMBEDDED_IPV4_SENTINEL_RULES = [
|
|
9237
|
+
{
|
|
9238
|
+
matches: (parts) => parts[0] === 0 && parts[1] === 0 && parts[2] === 0 && parts[3] === 0 && parts[4] === 0 && parts[5] === 0,
|
|
9239
|
+
toHextets: (parts) => [parts[6], parts[7]]
|
|
9240
|
+
},
|
|
9241
|
+
{
|
|
9242
|
+
matches: (parts) => parts[0] === 100 && parts[1] === 65435 && parts[2] === 1 && parts[3] === 0 && parts[4] === 0 && parts[5] === 0,
|
|
9243
|
+
toHextets: (parts) => [parts[6], parts[7]]
|
|
9244
|
+
},
|
|
9245
|
+
{
|
|
9246
|
+
matches: (parts) => parts[0] === 8194,
|
|
9247
|
+
toHextets: (parts) => [parts[1], parts[2]]
|
|
9248
|
+
},
|
|
9249
|
+
{
|
|
9250
|
+
matches: (parts) => parts[0] === 8193 && parts[1] === 0,
|
|
9251
|
+
toHextets: (parts) => [parts[6] ^ 65535, parts[7] ^ 65535]
|
|
9252
|
+
},
|
|
9253
|
+
{
|
|
9254
|
+
matches: (parts) => (parts[4] & 64767) === 0 && parts[5] === 24318,
|
|
9255
|
+
toHextets: (parts) => [parts[6], parts[7]]
|
|
9846
9256
|
}
|
|
9847
|
-
|
|
9848
|
-
|
|
9849
|
-
|
|
9850
|
-
|
|
9851
|
-
|
|
9852
|
-
|
|
9853
|
-
|
|
9854
|
-
|
|
9855
|
-
|
|
9856
|
-
|
|
9857
|
-
|
|
9858
|
-
|
|
9859
|
-
|
|
9860
|
-
|
|
9861
|
-
|
|
9862
|
-
|
|
9863
|
-
|
|
9864
|
-
|
|
9865
|
-
|
|
9866
|
-
|
|
9867
|
-
|
|
9868
|
-
|
|
9869
|
-
|
|
9870
|
-
|
|
9871
|
-
|
|
9872
|
-
|
|
9873
|
-
|
|
9874
|
-
|
|
9875
|
-
|
|
9876
|
-
|
|
9877
|
-
|
|
9878
|
-
|
|
9879
|
-
|
|
9880
|
-
|
|
9881
|
-
|
|
9882
|
-
|
|
9883
|
-
|
|
9884
|
-
|
|
9885
|
-
|
|
9886
|
-
|
|
9887
|
-
|
|
9888
|
-
|
|
9889
|
-
|
|
9890
|
-
|
|
9891
|
-
|
|
9892
|
-
|
|
9893
|
-
|
|
9894
|
-
|
|
9895
|
-
|
|
9896
|
-
|
|
9897
|
-
|
|
9898
|
-
|
|
9257
|
+
];
|
|
9258
|
+
function stripIpv6Brackets(value) {
|
|
9259
|
+
if (value.startsWith("[") && value.endsWith("]")) return value.slice(1, -1);
|
|
9260
|
+
return value;
|
|
9261
|
+
}
|
|
9262
|
+
function isNumericIpv4LiteralPart(value) {
|
|
9263
|
+
return /^[0-9]+$/.test(value) || /^0x[0-9a-f]+$/i.test(value);
|
|
9264
|
+
}
|
|
9265
|
+
function parseIpv6WithEmbeddedIpv4(raw) {
|
|
9266
|
+
if (!raw.includes(":") || !raw.includes(".")) return;
|
|
9267
|
+
const match = /^(.*:)([^:%]+(?:\.[^:%]+){3})(%[0-9A-Za-z]+)?$/i.exec(raw);
|
|
9268
|
+
if (!match) return;
|
|
9269
|
+
const [, prefix, embeddedIpv4, zoneSuffix = ""] = match;
|
|
9270
|
+
if (!ipaddr.IPv4.isValidFourPartDecimal(embeddedIpv4)) return;
|
|
9271
|
+
const octets = embeddedIpv4.split(".").map((part) => Number.parseInt(part, 10));
|
|
9272
|
+
const normalizedIpv6 = `${prefix}${(octets[0] << 8 | octets[1]).toString(16)}:${(octets[2] << 8 | octets[3]).toString(16)}${zoneSuffix}`;
|
|
9273
|
+
if (!ipaddr.IPv6.isValid(normalizedIpv6)) return;
|
|
9274
|
+
return ipaddr.IPv6.parse(normalizedIpv6);
|
|
9275
|
+
}
|
|
9276
|
+
function isIpv4Address(address) {
|
|
9277
|
+
return address.kind() === "ipv4";
|
|
9278
|
+
}
|
|
9279
|
+
function isIpv6Address(address) {
|
|
9280
|
+
return address.kind() === "ipv6";
|
|
9281
|
+
}
|
|
9282
|
+
function normalizeIpv4MappedAddress(address) {
|
|
9283
|
+
if (!isIpv6Address(address)) return address;
|
|
9284
|
+
if (!address.isIPv4MappedAddress()) return address;
|
|
9285
|
+
return address.toIPv4Address();
|
|
9286
|
+
}
|
|
9287
|
+
function parseCanonicalIpAddress(raw) {
|
|
9288
|
+
const trimmed = raw?.trim();
|
|
9289
|
+
if (!trimmed) return;
|
|
9290
|
+
const normalized = stripIpv6Brackets(trimmed);
|
|
9291
|
+
if (!normalized) return;
|
|
9292
|
+
if (ipaddr.IPv4.isValid(normalized)) {
|
|
9293
|
+
if (!ipaddr.IPv4.isValidFourPartDecimal(normalized)) return;
|
|
9294
|
+
return ipaddr.IPv4.parse(normalized);
|
|
9295
|
+
}
|
|
9296
|
+
if (ipaddr.IPv6.isValid(normalized)) return ipaddr.IPv6.parse(normalized);
|
|
9297
|
+
return parseIpv6WithEmbeddedIpv4(normalized);
|
|
9298
|
+
}
|
|
9299
|
+
function parseLooseIpAddress(raw) {
|
|
9300
|
+
const trimmed = raw?.trim();
|
|
9301
|
+
if (!trimmed) return;
|
|
9302
|
+
const normalized = stripIpv6Brackets(trimmed);
|
|
9303
|
+
if (!normalized) return;
|
|
9304
|
+
if (ipaddr.isValid(normalized)) return ipaddr.parse(normalized);
|
|
9305
|
+
return parseIpv6WithEmbeddedIpv4(normalized);
|
|
9306
|
+
}
|
|
9307
|
+
function isCanonicalDottedDecimalIPv4(raw) {
|
|
9308
|
+
const trimmed = raw?.trim();
|
|
9309
|
+
if (!trimmed) return false;
|
|
9310
|
+
const normalized = stripIpv6Brackets(trimmed);
|
|
9311
|
+
if (!normalized) return false;
|
|
9312
|
+
return ipaddr.IPv4.isValidFourPartDecimal(normalized);
|
|
9313
|
+
}
|
|
9314
|
+
function isLegacyIpv4Literal(raw) {
|
|
9315
|
+
const trimmed = raw?.trim();
|
|
9316
|
+
if (!trimmed) return false;
|
|
9317
|
+
const normalized = stripIpv6Brackets(trimmed);
|
|
9318
|
+
if (!normalized || normalized.includes(":")) return false;
|
|
9319
|
+
if (isCanonicalDottedDecimalIPv4(normalized)) return false;
|
|
9320
|
+
const parts = normalized.split(".");
|
|
9321
|
+
if (parts.length === 0 || parts.length > 4) return false;
|
|
9322
|
+
if (parts.some((part) => part.length === 0)) return false;
|
|
9323
|
+
if (!parts.every((part) => isNumericIpv4LiteralPart(part))) return false;
|
|
9324
|
+
return true;
|
|
9325
|
+
}
|
|
9326
|
+
function isPrivateOrLoopbackIpAddress(raw) {
|
|
9327
|
+
const parsed = parseCanonicalIpAddress(raw);
|
|
9328
|
+
if (!parsed) return false;
|
|
9329
|
+
const normalized = normalizeIpv4MappedAddress(parsed);
|
|
9330
|
+
if (isIpv4Address(normalized)) return PRIVATE_OR_LOOPBACK_IPV4_RANGES.has(normalized.range());
|
|
9331
|
+
if (PRIVATE_OR_LOOPBACK_IPV6_RANGES.has(normalized.range())) return true;
|
|
9332
|
+
return (normalized.parts[0] & 65472) === 65216;
|
|
9333
|
+
}
|
|
9334
|
+
function isBlockedSpecialUseIpv4Address(address, options = {}) {
|
|
9335
|
+
const inRfc2544BenchmarkRange = address.match(RFC2544_BENCHMARK_PREFIX);
|
|
9336
|
+
if (inRfc2544BenchmarkRange && options.allowRfc2544BenchmarkRange === true) return false;
|
|
9337
|
+
return BLOCKED_IPV4_SPECIAL_USE_RANGES.has(address.range()) || inRfc2544BenchmarkRange;
|
|
9338
|
+
}
|
|
9339
|
+
function decodeIpv4FromHextets(high, low) {
|
|
9340
|
+
const octets = [
|
|
9341
|
+
high >>> 8 & 255,
|
|
9342
|
+
high & 255,
|
|
9343
|
+
low >>> 8 & 255,
|
|
9344
|
+
low & 255
|
|
9345
|
+
];
|
|
9346
|
+
return ipaddr.IPv4.parse(octets.join("."));
|
|
9347
|
+
}
|
|
9348
|
+
function extractEmbeddedIpv4FromIpv6(address) {
|
|
9349
|
+
if (address.isIPv4MappedAddress()) return address.toIPv4Address();
|
|
9350
|
+
if (address.range() === "rfc6145") return decodeIpv4FromHextets(address.parts[6], address.parts[7]);
|
|
9351
|
+
if (address.range() === "rfc6052") return decodeIpv4FromHextets(address.parts[6], address.parts[7]);
|
|
9352
|
+
for (const rule of EMBEDDED_IPV4_SENTINEL_RULES) {
|
|
9353
|
+
if (!rule.matches(address.parts)) continue;
|
|
9354
|
+
const [high, low] = rule.toHextets(address.parts);
|
|
9355
|
+
return decodeIpv4FromHextets(high, low);
|
|
9356
|
+
}
|
|
9357
|
+
}
|
|
9358
|
+
|
|
9359
|
+
//#endregion
|
|
9360
|
+
//#region src/infra/net/hostname.ts
|
|
9361
|
+
function normalizeHostname(hostname) {
|
|
9362
|
+
const normalized = hostname.trim().toLowerCase().replace(/\.$/, "");
|
|
9363
|
+
if (normalized.startsWith("[") && normalized.endsWith("]")) return normalized.slice(1, -1);
|
|
9364
|
+
return normalized;
|
|
9365
|
+
}
|
|
9366
|
+
|
|
9367
|
+
//#endregion
|
|
9368
|
+
//#region src/infra/net/ssrf.ts
|
|
9369
|
+
var SsrFBlockedError = class extends Error {
|
|
9370
|
+
constructor(message) {
|
|
9371
|
+
super(message);
|
|
9372
|
+
this.name = "SsrFBlockedError";
|
|
9899
9373
|
}
|
|
9900
9374
|
};
|
|
9901
|
-
|
|
9902
|
-
|
|
9903
|
-
|
|
9375
|
+
const BLOCKED_HOSTNAMES = new Set([
|
|
9376
|
+
"localhost",
|
|
9377
|
+
"localhost.localdomain",
|
|
9378
|
+
"metadata.google.internal"
|
|
9379
|
+
]);
|
|
9380
|
+
function normalizeHostnameSet(values) {
|
|
9381
|
+
if (!values || values.length === 0) return /* @__PURE__ */ new Set();
|
|
9382
|
+
return new Set(values.map((value) => normalizeHostname(value)).filter(Boolean));
|
|
9904
9383
|
}
|
|
9905
|
-
|
|
9906
|
-
|
|
9907
|
-
*
|
|
9908
|
-
|
|
9909
|
-
|
|
9910
|
-
|
|
9911
|
-
|
|
9912
|
-
|
|
9913
|
-
|
|
9914
|
-
|
|
9915
|
-
|
|
9916
|
-
|
|
9917
|
-
|
|
9918
|
-
|
|
9919
|
-
|
|
9920
|
-
|
|
9921
|
-
|
|
9922
|
-
|
|
9384
|
+
function normalizeHostnameAllowlist(values) {
|
|
9385
|
+
if (!values || values.length === 0) return [];
|
|
9386
|
+
return Array.from(new Set(values.map((value) => normalizeHostname(value)).filter((value) => value !== "*" && value !== "*." && value.length > 0)));
|
|
9387
|
+
}
|
|
9388
|
+
function resolveAllowPrivateNetwork(policy) {
|
|
9389
|
+
return policy?.dangerouslyAllowPrivateNetwork === true || policy?.allowPrivateNetwork === true;
|
|
9390
|
+
}
|
|
9391
|
+
function resolveIpv4SpecialUseBlockOptions(policy) {
|
|
9392
|
+
return { allowRfc2544BenchmarkRange: policy?.allowRfc2544BenchmarkRange === true };
|
|
9393
|
+
}
|
|
9394
|
+
function isHostnameAllowedByPattern(hostname, pattern) {
|
|
9395
|
+
if (pattern.startsWith("*.")) {
|
|
9396
|
+
const suffix = pattern.slice(2);
|
|
9397
|
+
if (!suffix || hostname === suffix) return false;
|
|
9398
|
+
return hostname.endsWith(`.${suffix}`);
|
|
9399
|
+
}
|
|
9400
|
+
return hostname === pattern;
|
|
9401
|
+
}
|
|
9402
|
+
function matchesHostnameAllowlist(hostname, allowlist) {
|
|
9403
|
+
if (allowlist.length === 0) return true;
|
|
9404
|
+
return allowlist.some((pattern) => isHostnameAllowedByPattern(hostname, pattern));
|
|
9405
|
+
}
|
|
9406
|
+
function looksLikeUnsupportedIpv4Literal(address) {
|
|
9407
|
+
const parts = address.split(".");
|
|
9408
|
+
if (parts.length === 0 || parts.length > 4) return false;
|
|
9409
|
+
if (parts.some((part) => part.length === 0)) return true;
|
|
9410
|
+
return parts.every((part) => /^[0-9]+$/.test(part) || /^0x/i.test(part));
|
|
9411
|
+
}
|
|
9412
|
+
function isPrivateIpAddress(address, policy) {
|
|
9413
|
+
let normalized = address.trim().toLowerCase();
|
|
9414
|
+
if (normalized.startsWith("[") && normalized.endsWith("]")) normalized = normalized.slice(1, -1);
|
|
9415
|
+
if (!normalized) return false;
|
|
9416
|
+
const blockOptions = resolveIpv4SpecialUseBlockOptions(policy);
|
|
9417
|
+
const strictIp = parseCanonicalIpAddress(normalized);
|
|
9418
|
+
if (strictIp) {
|
|
9419
|
+
if (isIpv4Address(strictIp)) return isBlockedSpecialUseIpv4Address(strictIp, blockOptions);
|
|
9420
|
+
if (isPrivateOrLoopbackIpAddress(strictIp.toString())) return true;
|
|
9421
|
+
const embeddedIpv4 = extractEmbeddedIpv4FromIpv6(strictIp);
|
|
9422
|
+
if (embeddedIpv4) return isBlockedSpecialUseIpv4Address(embeddedIpv4, blockOptions);
|
|
9423
|
+
return false;
|
|
9424
|
+
}
|
|
9425
|
+
if (normalized.includes(":") && !parseLooseIpAddress(normalized)) return true;
|
|
9426
|
+
if (!isCanonicalDottedDecimalIPv4(normalized) && isLegacyIpv4Literal(normalized)) return true;
|
|
9427
|
+
if (looksLikeUnsupportedIpv4Literal(normalized)) return true;
|
|
9428
|
+
return false;
|
|
9429
|
+
}
|
|
9430
|
+
function isBlockedHostnameNormalized(normalized) {
|
|
9431
|
+
if (BLOCKED_HOSTNAMES.has(normalized)) return true;
|
|
9432
|
+
return normalized.endsWith(".localhost") || normalized.endsWith(".local") || normalized.endsWith(".internal");
|
|
9433
|
+
}
|
|
9434
|
+
function isBlockedHostnameOrIp(hostname, policy) {
|
|
9435
|
+
const normalized = normalizeHostname(hostname);
|
|
9436
|
+
if (!normalized) return false;
|
|
9437
|
+
return isBlockedHostnameNormalized(normalized) || isPrivateIpAddress(normalized, policy);
|
|
9438
|
+
}
|
|
9439
|
+
const BLOCKED_HOST_OR_IP_MESSAGE = "Blocked hostname or private/internal/special-use IP address";
|
|
9440
|
+
const BLOCKED_RESOLVED_IP_MESSAGE = "Blocked: resolves to private/internal/special-use IP address";
|
|
9441
|
+
function assertAllowedHostOrIpOrThrow(hostnameOrIp, policy) {
|
|
9442
|
+
if (isBlockedHostnameOrIp(hostnameOrIp, policy)) throw new SsrFBlockedError(BLOCKED_HOST_OR_IP_MESSAGE);
|
|
9443
|
+
}
|
|
9444
|
+
function assertAllowedResolvedAddressesOrThrow(results, policy) {
|
|
9445
|
+
for (const entry of results) if (isBlockedHostnameOrIp(entry.address, policy)) throw new SsrFBlockedError(BLOCKED_RESOLVED_IP_MESSAGE);
|
|
9446
|
+
}
|
|
9447
|
+
function createPinnedLookup(params) {
|
|
9448
|
+
const normalizedHost = normalizeHostname(params.hostname);
|
|
9449
|
+
const fallback = params.fallback ?? lookup;
|
|
9450
|
+
const fallbackLookup = fallback;
|
|
9451
|
+
const fallbackWithOptions = fallback;
|
|
9452
|
+
const records = params.addresses.map((address) => ({
|
|
9453
|
+
address,
|
|
9454
|
+
family: address.includes(":") ? 6 : 4
|
|
9455
|
+
}));
|
|
9456
|
+
let index = 0;
|
|
9457
|
+
return ((host, options, callback) => {
|
|
9458
|
+
const cb = typeof options === "function" ? options : callback;
|
|
9459
|
+
if (!cb) return;
|
|
9460
|
+
const normalized = normalizeHostname(host);
|
|
9461
|
+
if (!normalized || normalized !== normalizedHost) {
|
|
9462
|
+
if (typeof options === "function" || options === void 0) return fallbackLookup(host, cb);
|
|
9463
|
+
return fallbackWithOptions(host, options, cb);
|
|
9464
|
+
}
|
|
9465
|
+
const opts = typeof options === "object" && options !== null ? options : {};
|
|
9466
|
+
const requestedFamily = typeof options === "number" ? options : typeof opts.family === "number" ? opts.family : 0;
|
|
9467
|
+
const candidates = requestedFamily === 4 || requestedFamily === 6 ? records.filter((entry) => entry.family === requestedFamily) : records;
|
|
9468
|
+
const usable = candidates.length > 0 ? candidates : records;
|
|
9469
|
+
if (opts.all) {
|
|
9470
|
+
cb(null, usable);
|
|
9471
|
+
return;
|
|
9472
|
+
}
|
|
9473
|
+
const chosen = usable[index % usable.length];
|
|
9474
|
+
index += 1;
|
|
9475
|
+
cb(null, chosen.address, chosen.family);
|
|
9476
|
+
});
|
|
9477
|
+
}
|
|
9478
|
+
function dedupeAndPreferIpv4(results) {
|
|
9479
|
+
const seen = /* @__PURE__ */ new Set();
|
|
9480
|
+
const ipv4 = [];
|
|
9481
|
+
const otherFamilies = [];
|
|
9482
|
+
for (const entry of results) {
|
|
9483
|
+
if (seen.has(entry.address)) continue;
|
|
9484
|
+
seen.add(entry.address);
|
|
9485
|
+
if (entry.family === 4) {
|
|
9486
|
+
ipv4.push(entry.address);
|
|
9487
|
+
continue;
|
|
9488
|
+
}
|
|
9489
|
+
otherFamilies.push(entry.address);
|
|
9490
|
+
}
|
|
9491
|
+
return [...ipv4, ...otherFamilies];
|
|
9492
|
+
}
|
|
9493
|
+
async function resolvePinnedHostnameWithPolicy(hostname, params = {}) {
|
|
9494
|
+
const normalized = normalizeHostname(hostname);
|
|
9495
|
+
if (!normalized) throw new Error("Invalid hostname");
|
|
9496
|
+
const allowPrivateNetwork = resolveAllowPrivateNetwork(params.policy);
|
|
9497
|
+
const allowedHostnames = normalizeHostnameSet(params.policy?.allowedHostnames);
|
|
9498
|
+
const hostnameAllowlist = normalizeHostnameAllowlist(params.policy?.hostnameAllowlist);
|
|
9499
|
+
const isExplicitAllowed = allowedHostnames.has(normalized);
|
|
9500
|
+
const skipPrivateNetworkChecks = allowPrivateNetwork || isExplicitAllowed;
|
|
9501
|
+
if (!matchesHostnameAllowlist(normalized, hostnameAllowlist)) throw new SsrFBlockedError(`Blocked hostname (not in allowlist): ${hostname}`);
|
|
9502
|
+
if (!skipPrivateNetworkChecks) assertAllowedHostOrIpOrThrow(normalized, params.policy);
|
|
9503
|
+
const results = await (params.lookupFn ?? lookup$1)(normalized, { all: true });
|
|
9504
|
+
if (results.length === 0) throw new Error(`Unable to resolve hostname: ${hostname}`);
|
|
9505
|
+
if (!skipPrivateNetworkChecks) assertAllowedResolvedAddressesOrThrow(results, params.policy);
|
|
9506
|
+
const addresses = dedupeAndPreferIpv4(results);
|
|
9507
|
+
if (addresses.length === 0) throw new Error(`Unable to resolve hostname: ${hostname}`);
|
|
9508
|
+
return {
|
|
9509
|
+
hostname: normalized,
|
|
9510
|
+
addresses,
|
|
9511
|
+
lookup: createPinnedLookup({
|
|
9512
|
+
hostname: normalized,
|
|
9513
|
+
addresses
|
|
9514
|
+
})
|
|
9515
|
+
};
|
|
9516
|
+
}
|
|
9517
|
+
function createPinnedDispatcher(pinned) {
|
|
9518
|
+
return new Agent({ connect: {
|
|
9519
|
+
lookup: pinned.lookup,
|
|
9520
|
+
autoSelectFamily: true,
|
|
9521
|
+
autoSelectFamilyAttemptTimeout: 300
|
|
9522
|
+
} });
|
|
9523
|
+
}
|
|
9524
|
+
async function closeDispatcher(dispatcher) {
|
|
9525
|
+
if (!dispatcher) return;
|
|
9526
|
+
const candidate = dispatcher;
|
|
9527
|
+
try {
|
|
9528
|
+
if (typeof candidate.close === "function") {
|
|
9529
|
+
await candidate.close();
|
|
9530
|
+
return;
|
|
9531
|
+
}
|
|
9532
|
+
if (typeof candidate.destroy === "function") candidate.destroy();
|
|
9533
|
+
} catch {}
|
|
9534
|
+
}
|
|
9535
|
+
|
|
9536
|
+
//#endregion
|
|
9537
|
+
//#region src/infra/net/fetch-guard.ts
|
|
9538
|
+
const DEFAULT_MAX_REDIRECTS = 3;
|
|
9539
|
+
const CROSS_ORIGIN_REDIRECT_SENSITIVE_HEADERS = [
|
|
9540
|
+
"authorization",
|
|
9541
|
+
"proxy-authorization",
|
|
9542
|
+
"cookie",
|
|
9543
|
+
"cookie2"
|
|
9544
|
+
];
|
|
9545
|
+
function isRedirectStatus(status) {
|
|
9546
|
+
return status === 301 || status === 302 || status === 303 || status === 307 || status === 308;
|
|
9547
|
+
}
|
|
9548
|
+
function stripSensitiveHeadersForCrossOriginRedirect(init) {
|
|
9549
|
+
if (!init?.headers) return init;
|
|
9550
|
+
const headers = new Headers(init.headers);
|
|
9551
|
+
for (const header of CROSS_ORIGIN_REDIRECT_SENSITIVE_HEADERS) headers.delete(header);
|
|
9552
|
+
return {
|
|
9553
|
+
...init,
|
|
9554
|
+
headers
|
|
9555
|
+
};
|
|
9556
|
+
}
|
|
9557
|
+
function buildAbortSignal(params) {
|
|
9558
|
+
const { timeoutMs, signal } = params;
|
|
9559
|
+
if (!timeoutMs && !signal) return {
|
|
9560
|
+
signal: void 0,
|
|
9561
|
+
cleanup: () => {}
|
|
9562
|
+
};
|
|
9563
|
+
if (!timeoutMs) return {
|
|
9564
|
+
signal,
|
|
9565
|
+
cleanup: () => {}
|
|
9566
|
+
};
|
|
9567
|
+
const controller = new AbortController();
|
|
9568
|
+
const timeoutId = setTimeout(controller.abort.bind(controller), timeoutMs);
|
|
9569
|
+
const onAbort = bindAbortRelay(controller);
|
|
9570
|
+
if (signal) if (signal.aborted) controller.abort();
|
|
9571
|
+
else signal.addEventListener("abort", onAbort, { once: true });
|
|
9572
|
+
const cleanup = () => {
|
|
9573
|
+
clearTimeout(timeoutId);
|
|
9574
|
+
if (signal) signal.removeEventListener("abort", onAbort);
|
|
9575
|
+
};
|
|
9576
|
+
return {
|
|
9577
|
+
signal: controller.signal,
|
|
9578
|
+
cleanup
|
|
9579
|
+
};
|
|
9580
|
+
}
|
|
9581
|
+
async function fetchWithSsrFGuard(params) {
|
|
9582
|
+
const fetcher = params.fetchImpl ?? globalThis.fetch;
|
|
9583
|
+
if (!fetcher) throw new Error("fetch is not available");
|
|
9584
|
+
const maxRedirects = typeof params.maxRedirects === "number" && Number.isFinite(params.maxRedirects) ? Math.max(0, Math.floor(params.maxRedirects)) : DEFAULT_MAX_REDIRECTS;
|
|
9585
|
+
const { signal, cleanup } = buildAbortSignal({
|
|
9586
|
+
timeoutMs: params.timeoutMs,
|
|
9587
|
+
signal: params.signal
|
|
9588
|
+
});
|
|
9589
|
+
let released = false;
|
|
9590
|
+
const release = async (dispatcher) => {
|
|
9591
|
+
if (released) return;
|
|
9592
|
+
released = true;
|
|
9593
|
+
cleanup();
|
|
9594
|
+
await closeDispatcher(dispatcher ?? void 0);
|
|
9595
|
+
};
|
|
9596
|
+
const visited = /* @__PURE__ */ new Set();
|
|
9597
|
+
let currentUrl = params.url;
|
|
9598
|
+
let currentInit = params.init ? { ...params.init } : void 0;
|
|
9599
|
+
let redirectCount = 0;
|
|
9600
|
+
while (true) {
|
|
9601
|
+
let parsedUrl;
|
|
9602
|
+
try {
|
|
9603
|
+
parsedUrl = new URL(currentUrl);
|
|
9604
|
+
} catch {
|
|
9605
|
+
await release();
|
|
9606
|
+
throw new Error("Invalid URL: must be http or https");
|
|
9607
|
+
}
|
|
9608
|
+
if (!["http:", "https:"].includes(parsedUrl.protocol)) {
|
|
9609
|
+
await release();
|
|
9610
|
+
throw new Error("Invalid URL: must be http or https");
|
|
9611
|
+
}
|
|
9612
|
+
let dispatcher = null;
|
|
9613
|
+
try {
|
|
9614
|
+
const pinned = await resolvePinnedHostnameWithPolicy(parsedUrl.hostname, {
|
|
9615
|
+
lookupFn: params.lookupFn,
|
|
9616
|
+
policy: params.policy
|
|
9617
|
+
});
|
|
9618
|
+
if (params.pinDns !== false) dispatcher = createPinnedDispatcher(pinned);
|
|
9619
|
+
const init = {
|
|
9620
|
+
...currentInit ? { ...currentInit } : {},
|
|
9621
|
+
redirect: "manual",
|
|
9622
|
+
...dispatcher ? { dispatcher } : {},
|
|
9623
|
+
...signal ? { signal } : {}
|
|
9624
|
+
};
|
|
9625
|
+
const response = await fetcher(parsedUrl.toString(), init);
|
|
9626
|
+
if (isRedirectStatus(response.status)) {
|
|
9627
|
+
const location = response.headers.get("location");
|
|
9628
|
+
if (!location) {
|
|
9629
|
+
await release(dispatcher);
|
|
9630
|
+
throw new Error(`Redirect missing location header (${response.status})`);
|
|
9631
|
+
}
|
|
9632
|
+
redirectCount += 1;
|
|
9633
|
+
if (redirectCount > maxRedirects) {
|
|
9634
|
+
await release(dispatcher);
|
|
9635
|
+
throw new Error(`Too many redirects (limit: ${maxRedirects})`);
|
|
9636
|
+
}
|
|
9637
|
+
const nextParsedUrl = new URL(location, parsedUrl);
|
|
9638
|
+
const nextUrl = nextParsedUrl.toString();
|
|
9639
|
+
if (visited.has(nextUrl)) {
|
|
9640
|
+
await release(dispatcher);
|
|
9641
|
+
throw new Error("Redirect loop detected");
|
|
9642
|
+
}
|
|
9643
|
+
if (nextParsedUrl.origin !== parsedUrl.origin) currentInit = stripSensitiveHeadersForCrossOriginRedirect(currentInit);
|
|
9644
|
+
visited.add(nextUrl);
|
|
9645
|
+
response.body?.cancel();
|
|
9646
|
+
await closeDispatcher(dispatcher);
|
|
9647
|
+
currentUrl = nextUrl;
|
|
9648
|
+
continue;
|
|
9649
|
+
}
|
|
9923
9650
|
return {
|
|
9924
|
-
|
|
9925
|
-
|
|
9651
|
+
response,
|
|
9652
|
+
finalUrl: currentUrl,
|
|
9653
|
+
release: async () => release(dispatcher)
|
|
9926
9654
|
};
|
|
9927
|
-
}
|
|
9928
|
-
|
|
9929
|
-
|
|
9930
|
-
|
|
9931
|
-
|
|
9932
|
-
chunk: text.substring(0, splitPoint) + closingFence,
|
|
9933
|
-
rest: openingFence + text.substring(splitPoint)
|
|
9934
|
-
};
|
|
9655
|
+
} catch (err) {
|
|
9656
|
+
if (err instanceof SsrFBlockedError) logWarn(`security: blocked URL fetch (${params.auditContext ?? "url-fetch"}) target=${parsedUrl.origin}${parsedUrl.pathname} reason=${err.message}`);
|
|
9657
|
+
await release(dispatcher);
|
|
9658
|
+
throw err;
|
|
9659
|
+
}
|
|
9935
9660
|
}
|
|
9936
|
-
const splitPoint = findSplitPoint(text, limit);
|
|
9937
|
-
return {
|
|
9938
|
-
chunk: text.substring(0, splitPoint),
|
|
9939
|
-
rest: text.substring(splitPoint)
|
|
9940
|
-
};
|
|
9941
9661
|
}
|
|
9942
|
-
|
|
9943
|
-
|
|
9944
|
-
|
|
9945
|
-
|
|
9946
|
-
|
|
9947
|
-
|
|
9948
|
-
|
|
9949
|
-
|
|
9950
|
-
|
|
9951
|
-
|
|
9952
|
-
|
|
9662
|
+
|
|
9663
|
+
//#endregion
|
|
9664
|
+
//#region src/media/constants.ts
|
|
9665
|
+
const MAX_IMAGE_BYTES = 6 * 1024 * 1024;
|
|
9666
|
+
const MAX_AUDIO_BYTES = 16 * 1024 * 1024;
|
|
9667
|
+
const MAX_VIDEO_BYTES = 16 * 1024 * 1024;
|
|
9668
|
+
const MAX_DOCUMENT_BYTES = 100 * 1024 * 1024;
|
|
9669
|
+
|
|
9670
|
+
//#endregion
|
|
9671
|
+
//#region src/media/mime.ts
|
|
9672
|
+
const EXT_BY_MIME = {
|
|
9673
|
+
"image/heic": ".heic",
|
|
9674
|
+
"image/heif": ".heif",
|
|
9675
|
+
"image/jpeg": ".jpg",
|
|
9676
|
+
"image/png": ".png",
|
|
9677
|
+
"image/webp": ".webp",
|
|
9678
|
+
"image/gif": ".gif",
|
|
9679
|
+
"audio/ogg": ".ogg",
|
|
9680
|
+
"audio/mpeg": ".mp3",
|
|
9681
|
+
"audio/x-m4a": ".m4a",
|
|
9682
|
+
"audio/mp4": ".m4a",
|
|
9683
|
+
"video/mp4": ".mp4",
|
|
9684
|
+
"video/quicktime": ".mov",
|
|
9685
|
+
"application/pdf": ".pdf",
|
|
9686
|
+
"application/json": ".json",
|
|
9687
|
+
"application/zip": ".zip",
|
|
9688
|
+
"application/gzip": ".gz",
|
|
9689
|
+
"application/x-tar": ".tar",
|
|
9690
|
+
"application/x-7z-compressed": ".7z",
|
|
9691
|
+
"application/vnd.rar": ".rar",
|
|
9692
|
+
"application/msword": ".doc",
|
|
9693
|
+
"application/vnd.ms-excel": ".xls",
|
|
9694
|
+
"application/vnd.ms-powerpoint": ".ppt",
|
|
9695
|
+
"application/vnd.openxmlformats-officedocument.wordprocessingml.document": ".docx",
|
|
9696
|
+
"application/vnd.openxmlformats-officedocument.spreadsheetml.sheet": ".xlsx",
|
|
9697
|
+
"application/vnd.openxmlformats-officedocument.presentationml.presentation": ".pptx",
|
|
9698
|
+
"text/csv": ".csv",
|
|
9699
|
+
"text/plain": ".txt",
|
|
9700
|
+
"text/markdown": ".md"
|
|
9701
|
+
};
|
|
9702
|
+
const MIME_BY_EXT = {
|
|
9703
|
+
...Object.fromEntries(Object.entries(EXT_BY_MIME).map(([mime, ext]) => [ext, mime])),
|
|
9704
|
+
".jpeg": "image/jpeg"
|
|
9705
|
+
};
|
|
9706
|
+
function normalizeMimeType(mime) {
|
|
9707
|
+
if (!mime) return;
|
|
9708
|
+
return mime.split(";")[0]?.trim().toLowerCase() || void 0;
|
|
9953
9709
|
}
|
|
9954
|
-
|
|
9955
|
-
|
|
9956
|
-
|
|
9957
|
-
|
|
9958
|
-
|
|
9959
|
-
|
|
9960
|
-
let openFence;
|
|
9961
|
-
let match;
|
|
9962
|
-
while ((match = fenceRegex.exec(text)) !== null) {
|
|
9963
|
-
if (match.index >= limit) break;
|
|
9964
|
-
if (openFence === void 0) openFence = {
|
|
9965
|
-
fenceStart: match.index,
|
|
9966
|
-
fence: match[1]
|
|
9967
|
-
};
|
|
9968
|
-
else if (match[1].charAt(0) === openFence.fence.charAt(0) && match[1].length >= openFence.fence.length) openFence = void 0;
|
|
9710
|
+
async function sniffMime(buffer) {
|
|
9711
|
+
if (!buffer) return;
|
|
9712
|
+
try {
|
|
9713
|
+
return (await fileTypeFromBuffer(buffer))?.mime ?? void 0;
|
|
9714
|
+
} catch {
|
|
9715
|
+
return;
|
|
9969
9716
|
}
|
|
9970
|
-
|
|
9717
|
+
}
|
|
9718
|
+
function getFileExtension(filePath) {
|
|
9719
|
+
if (!filePath) return;
|
|
9720
|
+
try {
|
|
9721
|
+
if (/^https?:\/\//i.test(filePath)) {
|
|
9722
|
+
const url = new URL(filePath);
|
|
9723
|
+
return path.extname(url.pathname).toLowerCase() || void 0;
|
|
9724
|
+
}
|
|
9725
|
+
} catch {}
|
|
9726
|
+
return path.extname(filePath).toLowerCase() || void 0;
|
|
9727
|
+
}
|
|
9728
|
+
function detectMime(opts) {
|
|
9729
|
+
return detectMimeImpl(opts);
|
|
9730
|
+
}
|
|
9731
|
+
function isGenericMime(mime) {
|
|
9732
|
+
if (!mime) return true;
|
|
9733
|
+
const m = mime.toLowerCase();
|
|
9734
|
+
return m === "application/octet-stream" || m === "application/zip";
|
|
9735
|
+
}
|
|
9736
|
+
async function detectMimeImpl(opts) {
|
|
9737
|
+
const ext = getFileExtension(opts.filePath);
|
|
9738
|
+
const extMime = ext ? MIME_BY_EXT[ext] : void 0;
|
|
9739
|
+
const headerMime = normalizeMimeType(opts.headerMime);
|
|
9740
|
+
const sniffed = await sniffMime(opts.buffer);
|
|
9741
|
+
if (sniffed && (!isGenericMime(sniffed) || !extMime)) return sniffed;
|
|
9742
|
+
if (extMime) return extMime;
|
|
9743
|
+
if (headerMime && !isGenericMime(headerMime)) return headerMime;
|
|
9744
|
+
if (sniffed) return sniffed;
|
|
9745
|
+
if (headerMime) return headerMime;
|
|
9746
|
+
}
|
|
9747
|
+
function extensionForMime$1(mime) {
|
|
9748
|
+
const normalized = normalizeMimeType(mime);
|
|
9749
|
+
if (!normalized) return;
|
|
9750
|
+
return EXT_BY_MIME[normalized];
|
|
9971
9751
|
}
|
|
9972
9752
|
|
|
9973
9753
|
//#endregion
|
|
9974
|
-
//#region src/
|
|
9975
|
-
|
|
9976
|
-
|
|
9977
|
-
|
|
9978
|
-
|
|
9979
|
-
|
|
9980
|
-
|
|
9981
|
-
|
|
9982
|
-
|
|
9983
|
-
|
|
9984
|
-
|
|
9985
|
-
|
|
9986
|
-
|
|
9987
|
-
|
|
9988
|
-
|
|
9989
|
-
|
|
9990
|
-
|
|
9991
|
-
|
|
9992
|
-
|
|
9993
|
-
|
|
9994
|
-
|
|
9995
|
-
|
|
9996
|
-
|
|
9997
|
-
|
|
9998
|
-
|
|
9999
|
-
|
|
10000
|
-
|
|
10001
|
-
|
|
10002
|
-
|
|
10003
|
-
|
|
10004
|
-
|
|
10005
|
-
|
|
10006
|
-
|
|
10007
|
-
|
|
10008
|
-
|
|
10009
|
-
|
|
10010
|
-
|
|
10011
|
-
|
|
10012
|
-
|
|
10013
|
-
|
|
10014
|
-
|
|
10015
|
-
for (const pattern of fatalAuthPatterns) if (pattern.test(message)) return "fatal";
|
|
10016
|
-
return "fatal";
|
|
9754
|
+
//#region src/media/read-response-with-limit.ts
|
|
9755
|
+
async function readResponseWithLimit(res, maxBytes, opts) {
|
|
9756
|
+
const onOverflow = opts?.onOverflow ?? ((params) => /* @__PURE__ */ new Error(`Content too large: ${params.size} bytes (limit: ${params.maxBytes} bytes)`));
|
|
9757
|
+
const body = res.body;
|
|
9758
|
+
if (!body || typeof body.getReader !== "function") {
|
|
9759
|
+
const fallback = Buffer.from(await res.arrayBuffer());
|
|
9760
|
+
if (fallback.length > maxBytes) throw onOverflow({
|
|
9761
|
+
size: fallback.length,
|
|
9762
|
+
maxBytes,
|
|
9763
|
+
res
|
|
9764
|
+
});
|
|
9765
|
+
return fallback;
|
|
9766
|
+
}
|
|
9767
|
+
const reader = body.getReader();
|
|
9768
|
+
const chunks = [];
|
|
9769
|
+
let total = 0;
|
|
9770
|
+
try {
|
|
9771
|
+
while (true) {
|
|
9772
|
+
const { done, value } = await reader.read();
|
|
9773
|
+
if (done) break;
|
|
9774
|
+
if (value?.length) {
|
|
9775
|
+
total += value.length;
|
|
9776
|
+
if (total > maxBytes) {
|
|
9777
|
+
try {
|
|
9778
|
+
await reader.cancel();
|
|
9779
|
+
} catch {}
|
|
9780
|
+
throw onOverflow({
|
|
9781
|
+
size: total,
|
|
9782
|
+
maxBytes,
|
|
9783
|
+
res
|
|
9784
|
+
});
|
|
9785
|
+
}
|
|
9786
|
+
chunks.push(value);
|
|
9787
|
+
}
|
|
9788
|
+
}
|
|
9789
|
+
} finally {
|
|
9790
|
+
try {
|
|
9791
|
+
reader.releaseLock();
|
|
9792
|
+
} catch {}
|
|
9793
|
+
}
|
|
9794
|
+
return Buffer.concat(chunks.map((chunk) => Buffer.from(chunk)), total);
|
|
10017
9795
|
}
|
|
10018
9796
|
|
|
10019
9797
|
//#endregion
|
|
10020
|
-
//#region src/
|
|
10021
|
-
|
|
10022
|
-
|
|
10023
|
-
|
|
10024
|
-
|
|
10025
|
-
|
|
10026
|
-
|
|
10027
|
-
|
|
10028
|
-
|
|
9798
|
+
//#region src/media/fetch.ts
|
|
9799
|
+
var MediaFetchError = class extends Error {
|
|
9800
|
+
constructor(code, message) {
|
|
9801
|
+
super(message);
|
|
9802
|
+
this.code = code;
|
|
9803
|
+
this.name = "MediaFetchError";
|
|
9804
|
+
}
|
|
9805
|
+
};
|
|
9806
|
+
function stripQuotes(value) {
|
|
9807
|
+
return value.replace(/^["']|["']$/g, "");
|
|
9808
|
+
}
|
|
9809
|
+
function parseContentDispositionFileName(header) {
|
|
9810
|
+
if (!header) return;
|
|
9811
|
+
const starMatch = /filename\*\s*=\s*([^;]+)/i.exec(header);
|
|
9812
|
+
if (starMatch?.[1]) {
|
|
9813
|
+
const cleaned = stripQuotes(starMatch[1].trim());
|
|
9814
|
+
const encoded = cleaned.split("''").slice(1).join("''") || cleaned;
|
|
9815
|
+
try {
|
|
9816
|
+
return path.basename(decodeURIComponent(encoded));
|
|
9817
|
+
} catch {
|
|
9818
|
+
return path.basename(encoded);
|
|
9819
|
+
}
|
|
9820
|
+
}
|
|
9821
|
+
const match = /filename\s*=\s*([^;]+)/i.exec(header);
|
|
9822
|
+
if (match?.[1]) return path.basename(stripQuotes(match[1].trim()));
|
|
9823
|
+
}
|
|
9824
|
+
async function readErrorBodySnippet(res, maxChars = 200) {
|
|
10029
9825
|
try {
|
|
10030
|
-
|
|
9826
|
+
const text = await res.text();
|
|
9827
|
+
if (!text) return;
|
|
9828
|
+
const collapsed = text.replace(/\s+/g, " ").trim();
|
|
9829
|
+
if (!collapsed) return;
|
|
9830
|
+
if (collapsed.length <= maxChars) return collapsed;
|
|
9831
|
+
return `${collapsed.slice(0, maxChars)}…`;
|
|
10031
9832
|
} catch {
|
|
10032
|
-
return
|
|
9833
|
+
return;
|
|
10033
9834
|
}
|
|
10034
|
-
|
|
10035
|
-
|
|
10036
|
-
|
|
9835
|
+
}
|
|
9836
|
+
async function fetchRemoteMedia(options) {
|
|
9837
|
+
const { url, fetchImpl, filePathHint, maxBytes, maxRedirects, ssrfPolicy, lookupFn } = options;
|
|
9838
|
+
let res;
|
|
9839
|
+
let finalUrl = url;
|
|
9840
|
+
let release = null;
|
|
9841
|
+
try {
|
|
9842
|
+
const result = await fetchWithSsrFGuard({
|
|
9843
|
+
url,
|
|
9844
|
+
fetchImpl,
|
|
9845
|
+
maxRedirects,
|
|
9846
|
+
policy: ssrfPolicy,
|
|
9847
|
+
lookupFn
|
|
9848
|
+
});
|
|
9849
|
+
res = result.response;
|
|
9850
|
+
finalUrl = result.finalUrl;
|
|
9851
|
+
release = result.release;
|
|
9852
|
+
} catch (err) {
|
|
9853
|
+
throw new MediaFetchError("fetch_failed", `Failed to fetch media from ${url}: ${String(err)}`);
|
|
9854
|
+
}
|
|
9855
|
+
try {
|
|
9856
|
+
if (!res.ok) {
|
|
9857
|
+
const statusText = res.statusText ? ` ${res.statusText}` : "";
|
|
9858
|
+
const redirected = finalUrl !== url ? ` (redirected to ${finalUrl})` : "";
|
|
9859
|
+
let detail = `HTTP ${res.status}${statusText}`;
|
|
9860
|
+
if (!res.body) detail = `HTTP ${res.status}${statusText}; empty response body`;
|
|
9861
|
+
else {
|
|
9862
|
+
const snippet = await readErrorBodySnippet(res);
|
|
9863
|
+
if (snippet) detail += `; body: ${snippet}`;
|
|
9864
|
+
}
|
|
9865
|
+
throw new MediaFetchError("http_error", `Failed to fetch media from ${url}${redirected}: ${detail}`);
|
|
9866
|
+
}
|
|
9867
|
+
const contentLength = res.headers.get("content-length");
|
|
9868
|
+
if (maxBytes && contentLength) {
|
|
9869
|
+
const length = Number(contentLength);
|
|
9870
|
+
if (Number.isFinite(length) && length > maxBytes) throw new MediaFetchError("max_bytes", `Failed to fetch media from ${url}: content length ${length} exceeds maxBytes ${maxBytes}`);
|
|
9871
|
+
}
|
|
9872
|
+
const buffer = maxBytes ? await readResponseWithLimit(res, maxBytes, { onOverflow: ({ maxBytes, res }) => new MediaFetchError("max_bytes", `Failed to fetch media from ${res.url || url}: payload exceeds maxBytes ${maxBytes}`) }) : Buffer.from(await res.arrayBuffer());
|
|
9873
|
+
let fileNameFromUrl;
|
|
10037
9874
|
try {
|
|
10038
|
-
|
|
10039
|
-
|
|
10040
|
-
|
|
9875
|
+
const parsed = new URL(finalUrl);
|
|
9876
|
+
fileNameFromUrl = path.basename(parsed.pathname) || void 0;
|
|
9877
|
+
} catch {}
|
|
9878
|
+
const headerFileName = parseContentDispositionFileName(res.headers.get("content-disposition"));
|
|
9879
|
+
let fileName = headerFileName || fileNameFromUrl || (filePathHint ? path.basename(filePathHint) : void 0);
|
|
9880
|
+
const filePathForMime = headerFileName && path.extname(headerFileName) ? headerFileName : filePathHint ?? finalUrl;
|
|
9881
|
+
const contentType = await detectMime({
|
|
9882
|
+
buffer,
|
|
9883
|
+
headerMime: res.headers.get("content-type"),
|
|
9884
|
+
filePath: filePathForMime
|
|
9885
|
+
});
|
|
9886
|
+
if (fileName && !path.extname(fileName) && contentType) {
|
|
9887
|
+
const ext = extensionForMime$1(contentType);
|
|
9888
|
+
if (ext) fileName = `${fileName}${ext}`;
|
|
10041
9889
|
}
|
|
10042
|
-
|
|
10043
|
-
|
|
10044
|
-
|
|
10045
|
-
|
|
10046
|
-
tool: record.tool,
|
|
10047
|
-
provider: record.provider,
|
|
10048
|
-
...record.accountId ? { accountId: record.accountId } : {},
|
|
10049
|
-
...record.to ? { to: record.to } : {}
|
|
10050
|
-
};
|
|
10051
|
-
result.sentTargets.push(target);
|
|
10052
|
-
} else if (record.type === "cron_added") result.cronAdds += 1;
|
|
10053
|
-
else if (record.type === "heartbeat_report") result.heartbeatReport = {
|
|
10054
|
-
anythingDone: record.anythingDone,
|
|
10055
|
-
summary: record.summary
|
|
9890
|
+
return {
|
|
9891
|
+
buffer,
|
|
9892
|
+
contentType: contentType ?? void 0,
|
|
9893
|
+
fileName
|
|
10056
9894
|
};
|
|
9895
|
+
} finally {
|
|
9896
|
+
if (release) await release();
|
|
10057
9897
|
}
|
|
10058
|
-
|
|
9898
|
+
}
|
|
9899
|
+
|
|
9900
|
+
//#endregion
|
|
9901
|
+
//#region src/middleware/media-resolver.ts
|
|
9902
|
+
/** Max download size for inbound channel media (100 MB). */
|
|
9903
|
+
const MAX_INBOUND_MEDIA_BYTES = 100 * 1024 * 1024;
|
|
9904
|
+
/**
|
|
9905
|
+
* Resolve an array of media URLs (HTTP or local paths) into MediaAttachment
|
|
9906
|
+
* objects suitable for passing to {@link AgentRuntime.execute}.
|
|
9907
|
+
*
|
|
9908
|
+
* Remote URLs are downloaded into `tempDir` so that CLI runtimes can access
|
|
9909
|
+
* them as local files. Local paths are validated for MIME type only.
|
|
9910
|
+
*
|
|
9911
|
+
* Individual resolution failures are silently skipped — a single bad URL
|
|
9912
|
+
* should not prevent the rest of the message from being processed.
|
|
9913
|
+
*/
|
|
9914
|
+
async function resolveMediaAttachments(mediaUrls, tempDir) {
|
|
9915
|
+
const results = [];
|
|
9916
|
+
for (const [index, url] of mediaUrls.entries()) try {
|
|
9917
|
+
const attachment = await resolveOne(url, tempDir, index);
|
|
9918
|
+
if (attachment) {
|
|
9919
|
+
logDebug(`[media-resolver] resolved: url=${url} mime=${attachment.mimeType} path=${attachment.filePath}`);
|
|
9920
|
+
results.push(attachment);
|
|
9921
|
+
}
|
|
9922
|
+
} catch (err) {
|
|
9923
|
+
logDebug(`[media-resolver] failed: url=${url} error=${String(err)}`);
|
|
9924
|
+
}
|
|
9925
|
+
return results;
|
|
9926
|
+
}
|
|
9927
|
+
async function resolveOne(url, tempDir, index) {
|
|
9928
|
+
if (/^https?:\/\//i.test(url)) return downloadRemote(url, tempDir, index);
|
|
9929
|
+
return resolveLocal(url);
|
|
9930
|
+
}
|
|
9931
|
+
async function downloadRemote(url, tempDir, index) {
|
|
9932
|
+
const fetched = await fetchRemoteMedia({
|
|
9933
|
+
url,
|
|
9934
|
+
maxBytes: MAX_INBOUND_MEDIA_BYTES
|
|
9935
|
+
});
|
|
9936
|
+
const mimeType = fetched.contentType ?? "application/octet-stream";
|
|
9937
|
+
const fileName = `inbound-media-${index}${extensionForMime$1(mimeType) ?? ""}`;
|
|
9938
|
+
const filePath = join(tempDir, fileName);
|
|
9939
|
+
await writeFile(filePath, fetched.buffer);
|
|
9940
|
+
return {
|
|
9941
|
+
mimeType,
|
|
9942
|
+
filePath,
|
|
9943
|
+
sourceUrl: url,
|
|
9944
|
+
fileName: fetched.fileName ?? fileName
|
|
9945
|
+
};
|
|
9946
|
+
}
|
|
9947
|
+
async function resolveLocal(filePath) {
|
|
9948
|
+
return {
|
|
9949
|
+
mimeType: await detectMime({ filePath }) ?? "application/octet-stream",
|
|
9950
|
+
filePath
|
|
9951
|
+
};
|
|
10059
9952
|
}
|
|
10060
9953
|
|
|
10061
9954
|
//#endregion
|
|
@@ -10074,6 +9967,12 @@ var CLIRuntimeBase = class CLIRuntimeBase {
|
|
|
10074
9967
|
this.command = command;
|
|
10075
9968
|
this.timeoutMs = timeoutMs;
|
|
10076
9969
|
}
|
|
9970
|
+
/**
|
|
9971
|
+
* Construct a custom stdin payload for the subprocess.
|
|
9972
|
+
* When this returns a string, it is written to stdin instead of
|
|
9973
|
+
* the default large-prompt fallback. Subclasses may override.
|
|
9974
|
+
*/
|
|
9975
|
+
buildStdinPayload(_params) {}
|
|
10077
9976
|
/** Whether this CLI accepts prompts via stdin. Subclasses may override. */
|
|
10078
9977
|
get supportsStdinPrompt() {
|
|
10079
9978
|
return true;
|
|
@@ -10088,11 +9987,18 @@ var CLIRuntimeBase = class CLIRuntimeBase {
|
|
|
10088
9987
|
}
|
|
10089
9988
|
async *execute(params) {
|
|
10090
9989
|
const args = this.buildArgs(params);
|
|
9990
|
+
if (params.extraArgs && params.extraArgs.length > 0) args.push(...params.extraArgs);
|
|
9991
|
+
const runtimeEnv = this.buildEnv(params);
|
|
9992
|
+
const callerEnv = params.env ?? {};
|
|
10091
9993
|
const env = {
|
|
10092
9994
|
...process.env,
|
|
10093
|
-
...
|
|
10094
|
-
...
|
|
9995
|
+
...runtimeEnv,
|
|
9996
|
+
...callerEnv
|
|
10095
9997
|
};
|
|
9998
|
+
logDebug(`[agent-runtime] spawn: ${this.command} ${args.map((a) => JSON.stringify(a)).join(" ")}`);
|
|
9999
|
+
logDebug(`[agent-runtime] cwd: ${params.workingDirectory ?? process.cwd()}`);
|
|
10000
|
+
if (Object.keys(runtimeEnv).length > 0) logDebug(`[agent-runtime] runtime env keys: ${Object.keys(runtimeEnv).join(", ")}`);
|
|
10001
|
+
if (Object.keys(callerEnv).length > 0) logDebug(`[agent-runtime] caller env keys: ${Object.keys(callerEnv).join(", ")}`);
|
|
10096
10002
|
const child = spawn(this.command, args, {
|
|
10097
10003
|
cwd: params.workingDirectory,
|
|
10098
10004
|
env,
|
|
@@ -10102,9 +10008,11 @@ var CLIRuntimeBase = class CLIRuntimeBase {
|
|
|
10102
10008
|
"pipe"
|
|
10103
10009
|
]
|
|
10104
10010
|
});
|
|
10011
|
+
logDebug(`[agent-runtime] spawned pid=${child.pid}`);
|
|
10105
10012
|
const startMs = Date.now();
|
|
10106
10013
|
const stderrChunks = [];
|
|
10107
10014
|
let aborted = false;
|
|
10015
|
+
let yieldedEvents = false;
|
|
10108
10016
|
let escalationTimer;
|
|
10109
10017
|
const killWithEscalation = () => {
|
|
10110
10018
|
if (escalationTimer === void 0) escalationTimer = setTimeout(() => {
|
|
@@ -10126,6 +10034,7 @@ var CLIRuntimeBase = class CLIRuntimeBase {
|
|
|
10126
10034
|
if (watchdogTimer !== void 0) clearTimeout(watchdogTimer);
|
|
10127
10035
|
watchdogTimer = setTimeout(() => {
|
|
10128
10036
|
watchdogFired = true;
|
|
10037
|
+
logDebug(`[agent-runtime] pid=${child.pid}: watchdog timeout after ${this.timeoutMs}ms`);
|
|
10129
10038
|
killWithEscalation();
|
|
10130
10039
|
}, this.timeoutMs);
|
|
10131
10040
|
};
|
|
@@ -10165,10 +10074,18 @@ var CLIRuntimeBase = class CLIRuntimeBase {
|
|
|
10165
10074
|
});
|
|
10166
10075
|
});
|
|
10167
10076
|
});
|
|
10168
|
-
|
|
10077
|
+
const customStdin = this.buildStdinPayload(params);
|
|
10078
|
+
if (customStdin !== void 0 && child.stdin) {
|
|
10079
|
+
logDebug(`[agent-runtime] pid=${child.pid}: delivering custom stdin payload (${customStdin.length} chars)`);
|
|
10080
|
+
child.stdin.write(customStdin);
|
|
10081
|
+
} else if (this.supportsStdinPrompt && params.prompt.length > CLIRuntimeBase.STDIN_PROMPT_THRESHOLD && child.stdin) {
|
|
10082
|
+
logDebug(`[agent-runtime] pid=${child.pid}: delivering prompt via stdin (${params.prompt.length} chars)`);
|
|
10083
|
+
child.stdin.write(params.prompt);
|
|
10084
|
+
}
|
|
10169
10085
|
child.stdin?.end();
|
|
10170
10086
|
const onAbort = () => {
|
|
10171
10087
|
aborted = true;
|
|
10088
|
+
logDebug(`[agent-runtime] pid=${child.pid}: abort signal received`);
|
|
10172
10089
|
killWithEscalation();
|
|
10173
10090
|
};
|
|
10174
10091
|
if (params.abortSignal) if (params.abortSignal.aborted) {
|
|
@@ -10183,6 +10100,7 @@ var CLIRuntimeBase = class CLIRuntimeBase {
|
|
|
10183
10100
|
while (eventQueue.length > 0) {
|
|
10184
10101
|
const event = eventQueue.shift();
|
|
10185
10102
|
if (event === null || event === void 0) break;
|
|
10103
|
+
yieldedEvents = true;
|
|
10186
10104
|
yield event;
|
|
10187
10105
|
}
|
|
10188
10106
|
}
|
|
@@ -10190,9 +10108,16 @@ var CLIRuntimeBase = class CLIRuntimeBase {
|
|
|
10190
10108
|
if (watchdogTimer !== void 0) clearTimeout(watchdogTimer);
|
|
10191
10109
|
params.abortSignal?.removeEventListener("abort", onAbort);
|
|
10192
10110
|
}
|
|
10193
|
-
await exitPromise;
|
|
10111
|
+
const { code: exitCode, signal: exitSignal } = await exitPromise;
|
|
10194
10112
|
if (escalationTimer !== void 0) clearTimeout(escalationTimer);
|
|
10195
10113
|
const durationMs = Date.now() - startMs;
|
|
10114
|
+
logDebug(`[agent-runtime] pid=${child.pid}: exited code=${exitCode} signal=${exitSignal} duration=${durationMs}ms`);
|
|
10115
|
+
const stderr = stderrChunks.join("");
|
|
10116
|
+
if (stderr && (exitCode !== 0 || !yieldedEvents)) yield {
|
|
10117
|
+
type: "error",
|
|
10118
|
+
message: stderr.trim(),
|
|
10119
|
+
code: "CLI_STDERR"
|
|
10120
|
+
};
|
|
10196
10121
|
if (watchdogFired) yield {
|
|
10197
10122
|
type: "error",
|
|
10198
10123
|
message: `Watchdog timeout: no output for ${this.timeoutMs}ms`,
|
|
@@ -10210,7 +10135,8 @@ var CLIRuntimeBase = class CLIRuntimeBase {
|
|
|
10210
10135
|
sessionId: void 0,
|
|
10211
10136
|
durationMs,
|
|
10212
10137
|
usage: void 0,
|
|
10213
|
-
aborted
|
|
10138
|
+
aborted,
|
|
10139
|
+
stderr: stderr || void 0
|
|
10214
10140
|
}
|
|
10215
10141
|
};
|
|
10216
10142
|
}
|
|
@@ -10225,12 +10151,17 @@ var CLIRuntimeBase = class CLIRuntimeBase {
|
|
|
10225
10151
|
var ClaudeCliRuntime = class extends CLIRuntimeBase {
|
|
10226
10152
|
constructor() {
|
|
10227
10153
|
super("claude");
|
|
10154
|
+
this.mediaCapabilities = {
|
|
10155
|
+
acceptsInbound: ["image/"],
|
|
10156
|
+
emitsOutbound: false
|
|
10157
|
+
};
|
|
10228
10158
|
this.accumulatedText = "";
|
|
10229
10159
|
this.toolBuffer = null;
|
|
10230
10160
|
}
|
|
10231
10161
|
async *execute(params) {
|
|
10232
10162
|
this.resetState();
|
|
10233
|
-
|
|
10163
|
+
const prepared = await this.prepareMedia(params);
|
|
10164
|
+
for await (const event of super.execute(prepared)) {
|
|
10234
10165
|
if (event.type === "done") this.enrichDoneEvent(event);
|
|
10235
10166
|
yield event;
|
|
10236
10167
|
}
|
|
@@ -10244,9 +10175,34 @@ var ClaudeCliRuntime = class extends CLIRuntimeBase {
|
|
|
10244
10175
|
];
|
|
10245
10176
|
if (params.sessionId) args.push("--resume", params.sessionId);
|
|
10246
10177
|
if (params.mcpServers && Object.keys(params.mcpServers).length > 0) args.push("--mcp-config", JSON.stringify({ mcpServers: params.mcpServers }));
|
|
10247
|
-
args.push("--
|
|
10178
|
+
if (params.media?.some((m) => m.mimeType.startsWith("image/") && m.base64)) args.push("-p", "--input-format", "stream-json");
|
|
10179
|
+
else args.push("--print", params.prompt);
|
|
10248
10180
|
return args;
|
|
10249
10181
|
}
|
|
10182
|
+
buildStdinPayload(params) {
|
|
10183
|
+
const images = params.media?.filter((m) => m.mimeType.startsWith("image/") && m.base64);
|
|
10184
|
+
if (!images?.length) return;
|
|
10185
|
+
const content = images.map((img) => ({
|
|
10186
|
+
type: "image",
|
|
10187
|
+
source: {
|
|
10188
|
+
type: "base64",
|
|
10189
|
+
media_type: img.mimeType,
|
|
10190
|
+
data: img.base64
|
|
10191
|
+
}
|
|
10192
|
+
}));
|
|
10193
|
+
content.push({
|
|
10194
|
+
type: "text",
|
|
10195
|
+
text: params.prompt
|
|
10196
|
+
});
|
|
10197
|
+
const envelope = {
|
|
10198
|
+
type: "user",
|
|
10199
|
+
message: {
|
|
10200
|
+
role: "user",
|
|
10201
|
+
content
|
|
10202
|
+
}
|
|
10203
|
+
};
|
|
10204
|
+
return JSON.stringify(envelope) + "\n";
|
|
10205
|
+
}
|
|
10250
10206
|
extractEvent(line) {
|
|
10251
10207
|
const parsed = JSON.parse(line);
|
|
10252
10208
|
if (!isObject$3(parsed)) return null;
|
|
@@ -10261,6 +10217,11 @@ var ClaudeCliRuntime = class extends CLIRuntimeBase {
|
|
|
10261
10217
|
}
|
|
10262
10218
|
if (parsed.type === "result") {
|
|
10263
10219
|
this.storeResultData(parsed);
|
|
10220
|
+
if (parsed.is_error === true && typeof parsed.result === "string" && parsed.result) return {
|
|
10221
|
+
type: "error",
|
|
10222
|
+
message: parsed.result,
|
|
10223
|
+
code: "CLI_ERROR"
|
|
10224
|
+
};
|
|
10264
10225
|
return null;
|
|
10265
10226
|
}
|
|
10266
10227
|
return null;
|
|
@@ -10303,6 +10264,10 @@ var ClaudeCliRuntime = class extends CLIRuntimeBase {
|
|
|
10303
10264
|
if (this.toolBuffer) this.toolBuffer.input += delta.partial_json;
|
|
10304
10265
|
return null;
|
|
10305
10266
|
}
|
|
10267
|
+
if (delta.type === "thinking_delta" && typeof delta.thinking === "string") return {
|
|
10268
|
+
type: "thinking",
|
|
10269
|
+
text: delta.thinking
|
|
10270
|
+
};
|
|
10306
10271
|
return null;
|
|
10307
10272
|
}
|
|
10308
10273
|
handleContentBlockStop() {
|
|
@@ -10349,6 +10314,37 @@ var ClaudeCliRuntime = class extends CLIRuntimeBase {
|
|
|
10349
10314
|
if (this.resultData?.durationApiMs !== void 0) result.apiDurationMs = this.resultData.durationApiMs;
|
|
10350
10315
|
if (this.resultData?.numTurns !== void 0) result.numTurns = this.resultData.numTurns;
|
|
10351
10316
|
}
|
|
10317
|
+
/**
|
|
10318
|
+
* Read image files referenced by media attachments and populate their base64 field.
|
|
10319
|
+
* Non-image media types are filtered out (audio/video are not supported natively).
|
|
10320
|
+
*/
|
|
10321
|
+
async prepareMedia(params) {
|
|
10322
|
+
if (!params.media?.length) return params;
|
|
10323
|
+
const prepared = [];
|
|
10324
|
+
for (const attachment of params.media) {
|
|
10325
|
+
if (!attachment.mimeType.startsWith("image/")) continue;
|
|
10326
|
+
if (attachment.base64) {
|
|
10327
|
+
prepared.push(attachment);
|
|
10328
|
+
continue;
|
|
10329
|
+
}
|
|
10330
|
+
if (attachment.filePath) {
|
|
10331
|
+
try {
|
|
10332
|
+
const buffer = await readFile(attachment.filePath);
|
|
10333
|
+
prepared.push({
|
|
10334
|
+
...attachment,
|
|
10335
|
+
base64: buffer.toString("base64")
|
|
10336
|
+
});
|
|
10337
|
+
} catch {
|
|
10338
|
+
logDebug(`[claude-runtime] failed to read media file: ${attachment.filePath}`);
|
|
10339
|
+
}
|
|
10340
|
+
continue;
|
|
10341
|
+
}
|
|
10342
|
+
}
|
|
10343
|
+
return {
|
|
10344
|
+
...params,
|
|
10345
|
+
media: prepared.length > 0 ? prepared : void 0
|
|
10346
|
+
};
|
|
10347
|
+
}
|
|
10352
10348
|
resetState() {
|
|
10353
10349
|
this.currentSessionId = void 0;
|
|
10354
10350
|
this.accumulatedText = "";
|
|
@@ -10385,6 +10381,10 @@ function parseUsage(raw) {
|
|
|
10385
10381
|
var CodexCliRuntime = class extends CLIRuntimeBase {
|
|
10386
10382
|
constructor() {
|
|
10387
10383
|
super("codex");
|
|
10384
|
+
this.mediaCapabilities = {
|
|
10385
|
+
acceptsInbound: ["image/"],
|
|
10386
|
+
emitsOutbound: false
|
|
10387
|
+
};
|
|
10388
10388
|
this.accumulatedText = "";
|
|
10389
10389
|
this.lastEmittedTextLength = 0;
|
|
10390
10390
|
this.itemCounter = 0;
|
|
@@ -10413,13 +10413,17 @@ var CodexCliRuntime = class extends CLIRuntimeBase {
|
|
|
10413
10413
|
params.sessionId,
|
|
10414
10414
|
params.prompt
|
|
10415
10415
|
];
|
|
10416
|
-
|
|
10416
|
+
const args = [
|
|
10417
10417
|
"exec",
|
|
10418
10418
|
"--json",
|
|
10419
10419
|
"--color",
|
|
10420
|
-
"never"
|
|
10421
|
-
params.prompt
|
|
10420
|
+
"never"
|
|
10422
10421
|
];
|
|
10422
|
+
if (params.media) {
|
|
10423
|
+
for (const attachment of params.media) if (attachment.mimeType.startsWith("image/") && attachment.filePath) args.push("--image", attachment.filePath);
|
|
10424
|
+
}
|
|
10425
|
+
args.push(params.prompt);
|
|
10426
|
+
return args;
|
|
10423
10427
|
}
|
|
10424
10428
|
extractEvent(line) {
|
|
10425
10429
|
const parsed = JSON.parse(line);
|
|
@@ -10466,12 +10470,22 @@ var CodexCliRuntime = class extends CLIRuntimeBase {
|
|
|
10466
10470
|
case "agent_message":
|
|
10467
10471
|
this.lastEmittedTextLength = 0;
|
|
10468
10472
|
return null;
|
|
10473
|
+
case "reasoning": return null;
|
|
10469
10474
|
default: return null;
|
|
10470
10475
|
}
|
|
10471
10476
|
}
|
|
10472
10477
|
handleItemUpdated(parsed) {
|
|
10473
10478
|
const item = isObject$2(parsed.item) ? parsed.item : null;
|
|
10474
|
-
if (!item
|
|
10479
|
+
if (!item) return null;
|
|
10480
|
+
if (item.type === "reasoning") {
|
|
10481
|
+
const text = this.extractReasoningText(item);
|
|
10482
|
+
if (text) return {
|
|
10483
|
+
type: "thinking",
|
|
10484
|
+
text
|
|
10485
|
+
};
|
|
10486
|
+
return null;
|
|
10487
|
+
}
|
|
10488
|
+
if (item.type !== "agent_message") return null;
|
|
10475
10489
|
const fullText = this.extractMessageText(item);
|
|
10476
10490
|
if (fullText === void 0) return null;
|
|
10477
10491
|
const delta = fullText.substring(this.lastEmittedTextLength);
|
|
@@ -10504,6 +10518,14 @@ var CodexCliRuntime = class extends CLIRuntimeBase {
|
|
|
10504
10518
|
}
|
|
10505
10519
|
return null;
|
|
10506
10520
|
}
|
|
10521
|
+
case "reasoning": {
|
|
10522
|
+
const text = this.extractReasoningText(item);
|
|
10523
|
+
if (text) return {
|
|
10524
|
+
type: "thinking",
|
|
10525
|
+
text
|
|
10526
|
+
};
|
|
10527
|
+
return null;
|
|
10528
|
+
}
|
|
10507
10529
|
case "command_execution": {
|
|
10508
10530
|
const toolId = this.currentToolId ?? this.extractToolId(item);
|
|
10509
10531
|
this.currentToolId = void 0;
|
|
@@ -10573,6 +10595,14 @@ var CodexCliRuntime = class extends CLIRuntimeBase {
|
|
|
10573
10595
|
}
|
|
10574
10596
|
if (typeof item.text === "string") return item.text;
|
|
10575
10597
|
}
|
|
10598
|
+
extractReasoningText(item) {
|
|
10599
|
+
if (Array.isArray(item.summary)) {
|
|
10600
|
+
const textParts = [];
|
|
10601
|
+
for (const part of item.summary) if (isObject$2(part) && part.type === "summary_text" && typeof part.text === "string") textParts.push(part.text);
|
|
10602
|
+
if (textParts.length > 0) return textParts.join("");
|
|
10603
|
+
}
|
|
10604
|
+
if (typeof item.text === "string") return item.text;
|
|
10605
|
+
}
|
|
10576
10606
|
resetState() {
|
|
10577
10607
|
this.currentSessionId = void 0;
|
|
10578
10608
|
this.accumulatedText = "";
|
|
@@ -10709,6 +10739,15 @@ function isObject$2(value) {
|
|
|
10709
10739
|
var GeminiCliRuntime = class extends CLIRuntimeBase {
|
|
10710
10740
|
constructor() {
|
|
10711
10741
|
super("gemini");
|
|
10742
|
+
this.mediaCapabilities = {
|
|
10743
|
+
acceptsInbound: [
|
|
10744
|
+
"image/",
|
|
10745
|
+
"audio/",
|
|
10746
|
+
"video/",
|
|
10747
|
+
"application/pdf"
|
|
10748
|
+
],
|
|
10749
|
+
emitsOutbound: false
|
|
10750
|
+
};
|
|
10712
10751
|
this.accumulatedText = "";
|
|
10713
10752
|
}
|
|
10714
10753
|
get supportsStdinPrompt() {
|
|
@@ -10719,12 +10758,14 @@ var GeminiCliRuntime = class extends CLIRuntimeBase {
|
|
|
10719
10758
|
const mcpConfigManager = params.mcpServers && Object.keys(params.mcpServers).length > 0 ? new GeminiMcpConfigManager(params.workingDirectory, params.mcpServers) : null;
|
|
10720
10759
|
try {
|
|
10721
10760
|
await mcpConfigManager?.setup();
|
|
10722
|
-
|
|
10761
|
+
const prepared = await this.prepareMedia(params);
|
|
10762
|
+
for await (const event of super.execute(prepared)) {
|
|
10723
10763
|
if (event.type === "done") this.enrichDoneEvent(event);
|
|
10724
10764
|
yield event;
|
|
10725
10765
|
}
|
|
10726
10766
|
} finally {
|
|
10727
10767
|
await mcpConfigManager?.teardown();
|
|
10768
|
+
await this.cleanupMediaTempDir();
|
|
10728
10769
|
}
|
|
10729
10770
|
}
|
|
10730
10771
|
buildArgs(params) {
|
|
@@ -10814,10 +10855,52 @@ var GeminiCliRuntime = class extends CLIRuntimeBase {
|
|
|
10814
10855
|
if (this.resultStats.toolCalls !== void 0) result.numTurns = this.resultStats.toolCalls;
|
|
10815
10856
|
}
|
|
10816
10857
|
}
|
|
10858
|
+
/**
|
|
10859
|
+
* Save media attachments to temp files and inject `@path` references into
|
|
10860
|
+
* the prompt. Gemini CLI resolves `@path` inline references natively.
|
|
10861
|
+
*/
|
|
10862
|
+
async prepareMedia(params) {
|
|
10863
|
+
if (!params.media?.length) return params;
|
|
10864
|
+
const tempDir = join(tmpdir(), `remoteclaw-gemini-media-${randomUUID()}`);
|
|
10865
|
+
await mkdir(tempDir, { recursive: true });
|
|
10866
|
+
this.mediaTempDir = tempDir;
|
|
10867
|
+
const mediaRefs = [];
|
|
10868
|
+
for (const attachment of params.media) {
|
|
10869
|
+
const ext = extensionForMime(attachment.mimeType);
|
|
10870
|
+
const filePath = join(tempDir, `media-${mediaRefs.length}${ext}`);
|
|
10871
|
+
if (attachment.base64) {
|
|
10872
|
+
await writeFile(filePath, Buffer.from(attachment.base64, "base64"));
|
|
10873
|
+
mediaRefs.push(filePath);
|
|
10874
|
+
} else if (attachment.filePath) try {
|
|
10875
|
+
await writeFile(filePath, await readFile(attachment.filePath));
|
|
10876
|
+
mediaRefs.push(filePath);
|
|
10877
|
+
} catch {
|
|
10878
|
+
logDebug(`[gemini-runtime] failed to read media file: ${attachment.filePath}`);
|
|
10879
|
+
}
|
|
10880
|
+
}
|
|
10881
|
+
if (mediaRefs.length === 0) return params;
|
|
10882
|
+
const mediaPrefix = mediaRefs.map((ref) => `@${ref}`).join(" ");
|
|
10883
|
+
return {
|
|
10884
|
+
...params,
|
|
10885
|
+
prompt: `${mediaPrefix} ${params.prompt}`
|
|
10886
|
+
};
|
|
10887
|
+
}
|
|
10888
|
+
async cleanupMediaTempDir() {
|
|
10889
|
+
if (this.mediaTempDir) {
|
|
10890
|
+
try {
|
|
10891
|
+
await rm(this.mediaTempDir, {
|
|
10892
|
+
recursive: true,
|
|
10893
|
+
force: true
|
|
10894
|
+
});
|
|
10895
|
+
} catch {}
|
|
10896
|
+
this.mediaTempDir = void 0;
|
|
10897
|
+
}
|
|
10898
|
+
}
|
|
10817
10899
|
resetState() {
|
|
10818
10900
|
this.currentSessionId = void 0;
|
|
10819
10901
|
this.accumulatedText = "";
|
|
10820
10902
|
this.resultStats = void 0;
|
|
10903
|
+
this.mediaTempDir = void 0;
|
|
10821
10904
|
}
|
|
10822
10905
|
};
|
|
10823
10906
|
/**
|
|
@@ -10879,6 +10962,23 @@ var GeminiMcpConfigManager = class {
|
|
|
10879
10962
|
function isObject$1(value) {
|
|
10880
10963
|
return typeof value === "object" && value !== null && !Array.isArray(value);
|
|
10881
10964
|
}
|
|
10965
|
+
/** Map common MIME types to file extensions for Gemini CLI `@path` references. */
|
|
10966
|
+
function extensionForMime(mimeType) {
|
|
10967
|
+
return {
|
|
10968
|
+
"image/jpeg": ".jpg",
|
|
10969
|
+
"image/png": ".png",
|
|
10970
|
+
"image/gif": ".gif",
|
|
10971
|
+
"image/webp": ".webp",
|
|
10972
|
+
"audio/ogg": ".ogg",
|
|
10973
|
+
"audio/mpeg": ".mp3",
|
|
10974
|
+
"audio/wav": ".wav",
|
|
10975
|
+
"audio/webm": ".weba",
|
|
10976
|
+
"video/mp4": ".mp4",
|
|
10977
|
+
"video/webm": ".webm",
|
|
10978
|
+
"video/quicktime": ".mov",
|
|
10979
|
+
"application/pdf": ".pdf"
|
|
10980
|
+
}[mimeType] ?? "";
|
|
10981
|
+
}
|
|
10882
10982
|
|
|
10883
10983
|
//#endregion
|
|
10884
10984
|
//#region src/middleware/runtimes/opencode.ts
|
|
@@ -10897,6 +10997,10 @@ function isObject$1(value) {
|
|
|
10897
10997
|
var OpenCodeCliRuntime = class extends CLIRuntimeBase {
|
|
10898
10998
|
constructor() {
|
|
10899
10999
|
super("opencode");
|
|
11000
|
+
this.mediaCapabilities = {
|
|
11001
|
+
acceptsInbound: [],
|
|
11002
|
+
emitsOutbound: false
|
|
11003
|
+
};
|
|
10900
11004
|
this.accumulatedText = "";
|
|
10901
11005
|
this.pendingEvents = [];
|
|
10902
11006
|
this.toolCounter = 0;
|
|
@@ -10935,7 +11039,7 @@ var OpenCodeCliRuntime = class extends CLIRuntimeBase {
|
|
|
10935
11039
|
case "tool_use": return this.handleToolUse(data);
|
|
10936
11040
|
case "step_start": return null;
|
|
10937
11041
|
case "step_finish": return this.handleStepFinish(data);
|
|
10938
|
-
case "reasoning": return
|
|
11042
|
+
case "reasoning": return this.handleReasoning(data);
|
|
10939
11043
|
case "error": return this.handleError(data);
|
|
10940
11044
|
default: return null;
|
|
10941
11045
|
}
|
|
@@ -10981,6 +11085,14 @@ var OpenCodeCliRuntime = class extends CLIRuntimeBase {
|
|
|
10981
11085
|
message: typeof parsed.message === "string" ? parsed.message : "Unknown error"
|
|
10982
11086
|
};
|
|
10983
11087
|
}
|
|
11088
|
+
handleReasoning(parsed) {
|
|
11089
|
+
const content = typeof parsed.text === "string" ? parsed.text : typeof parsed.content === "string" ? parsed.content : "";
|
|
11090
|
+
if (!content) return null;
|
|
11091
|
+
return {
|
|
11092
|
+
type: "thinking",
|
|
11093
|
+
text: content
|
|
11094
|
+
};
|
|
11095
|
+
}
|
|
10984
11096
|
enrichDoneEvent(event) {
|
|
10985
11097
|
const { result } = event;
|
|
10986
11098
|
result.text = this.accumulatedText;
|
|
@@ -11075,12 +11187,42 @@ const SUPPORTED_PROVIDERS = [
|
|
|
11075
11187
|
"codex",
|
|
11076
11188
|
"opencode"
|
|
11077
11189
|
];
|
|
11190
|
+
const validatedCommands = /* @__PURE__ */ new Set();
|
|
11191
|
+
/**
|
|
11192
|
+
* Verify that a CLI binary exists on PATH.
|
|
11193
|
+
*
|
|
11194
|
+
* Results are cached per process lifetime so the `which` lookup runs at most
|
|
11195
|
+
* once per command.
|
|
11196
|
+
*/
|
|
11197
|
+
function validateExecutable(command) {
|
|
11198
|
+
if (validatedCommands.has(command)) {
|
|
11199
|
+
logDebug(`[runtime-factory] executable already validated: ${command}`);
|
|
11200
|
+
return;
|
|
11201
|
+
}
|
|
11202
|
+
try {
|
|
11203
|
+
execFileSync("which", [command], { stdio: "ignore" });
|
|
11204
|
+
logDebug(`[runtime-factory] executable validated: ${command}`);
|
|
11205
|
+
validatedCommands.add(command);
|
|
11206
|
+
} catch {
|
|
11207
|
+
throw new Error(`Runtime '${command}' is configured but the '${command}' binary was not found on PATH. Install it or set agents.defaults.runtime to a different provider.`);
|
|
11208
|
+
}
|
|
11209
|
+
}
|
|
11078
11210
|
function createCliRuntime(provider) {
|
|
11079
|
-
|
|
11080
|
-
|
|
11081
|
-
|
|
11082
|
-
case "
|
|
11083
|
-
|
|
11211
|
+
const normalized = provider.trim().toLowerCase();
|
|
11212
|
+
logDebug(`[runtime-factory] creating runtime: provider=${normalized}`);
|
|
11213
|
+
switch (normalized) {
|
|
11214
|
+
case "claude":
|
|
11215
|
+
validateExecutable(normalized);
|
|
11216
|
+
return new ClaudeCliRuntime();
|
|
11217
|
+
case "gemini":
|
|
11218
|
+
validateExecutable(normalized);
|
|
11219
|
+
return new GeminiCliRuntime();
|
|
11220
|
+
case "codex":
|
|
11221
|
+
validateExecutable(normalized);
|
|
11222
|
+
return new CodexCliRuntime();
|
|
11223
|
+
case "opencode":
|
|
11224
|
+
validateExecutable(normalized);
|
|
11225
|
+
return new OpenCodeCliRuntime();
|
|
11084
11226
|
default: throw new Error(`Unknown runtime provider "${provider}". Supported providers: ${SUPPORTED_PROVIDERS.join(", ")}`);
|
|
11085
11227
|
}
|
|
11086
11228
|
}
|
|
@@ -11231,6 +11373,8 @@ var ChannelBridge = class {
|
|
|
11231
11373
|
#workspaceDir;
|
|
11232
11374
|
#chunkLimit;
|
|
11233
11375
|
#mcpServerPath;
|
|
11376
|
+
#runtimeArgs;
|
|
11377
|
+
#runtimeEnv;
|
|
11234
11378
|
constructor(options) {
|
|
11235
11379
|
this.#provider = options.provider;
|
|
11236
11380
|
this.#sessionMap = options.sessionMap;
|
|
@@ -11239,6 +11383,8 @@ var ChannelBridge = class {
|
|
|
11239
11383
|
this.#workspaceDir = options.workspaceDir ?? DEFAULT_WORKSPACE_DIR;
|
|
11240
11384
|
this.#chunkLimit = options.chunkLimit;
|
|
11241
11385
|
this.#mcpServerPath = options.mcpServerPath ?? DEFAULT_MCP_SERVER_PATH;
|
|
11386
|
+
this.#runtimeArgs = options.runtimeArgs;
|
|
11387
|
+
this.#runtimeEnv = options.runtimeEnv;
|
|
11242
11388
|
}
|
|
11243
11389
|
/**
|
|
11244
11390
|
* Process an incoming channel message through the full agent execution pipeline.
|
|
@@ -11248,7 +11394,9 @@ var ChannelBridge = class {
|
|
|
11248
11394
|
*/
|
|
11249
11395
|
async handle(message, callbacks, abortSignal) {
|
|
11250
11396
|
const sessionKey = buildSessionKey(message);
|
|
11397
|
+
logDebug(`[channel-bridge] handle: channel=${message.provider} from=${message.from} channelId=${message.channelId} threadId=${message.replyToId ?? "none"} agentId=${message.agentId ?? "default"} media=${message.mediaUrls?.length ?? 0}`);
|
|
11251
11398
|
const existingSessionId = await this.#sessionMap.get(sessionKey);
|
|
11399
|
+
logDebug(`[channel-bridge] session lookup: key=${formatSessionKeyString(sessionKey)} ${existingSessionId ? `hit=${existingSessionId}` : "miss"}`);
|
|
11252
11400
|
const hookRunner = getGlobalHookRunner();
|
|
11253
11401
|
if (existingSessionId && hookRunner?.hasHooks("session_resumed")) await hookRunner.runSessionResumed({
|
|
11254
11402
|
sessionId: existingSessionId,
|
|
@@ -11275,9 +11423,10 @@ var ChannelBridge = class {
|
|
|
11275
11423
|
const sideEffectsFile = join(invocationDir, "side-effects.ndjson");
|
|
11276
11424
|
try {
|
|
11277
11425
|
const mcpServers = this.#buildMcpConfig(message, sessionKey, sideEffectsFile);
|
|
11426
|
+
logDebug(`[channel-bridge] creating runtime: provider=${this.#provider}`);
|
|
11278
11427
|
const runtime = createCliRuntime(this.#provider);
|
|
11279
11428
|
let workspaceDir = this.#workspaceDir;
|
|
11280
|
-
let
|
|
11429
|
+
let hookEnv;
|
|
11281
11430
|
const runId = randomUUID();
|
|
11282
11431
|
if (hookRunner?.hasHooks("before_runtime_spawn")) {
|
|
11283
11432
|
const spawnResult = await hookRunner.runBeforeRuntimeSpawn({
|
|
@@ -11293,9 +11442,23 @@ var ChannelBridge = class {
|
|
|
11293
11442
|
channelId: message.channelId,
|
|
11294
11443
|
runtimeName: this.#provider
|
|
11295
11444
|
});
|
|
11296
|
-
if (spawnResult?.workspaceDir)
|
|
11297
|
-
|
|
11445
|
+
if (spawnResult?.workspaceDir) {
|
|
11446
|
+
logDebug(`[channel-bridge] hook overrode workspaceDir: ${this.#workspaceDir} -> ${spawnResult.workspaceDir}`);
|
|
11447
|
+
workspaceDir = spawnResult.workspaceDir;
|
|
11448
|
+
}
|
|
11449
|
+
if (spawnResult?.env) {
|
|
11450
|
+
logDebug(`[channel-bridge] hook injected env keys: ${Object.keys(spawnResult.env).join(", ")}`);
|
|
11451
|
+
hookEnv = spawnResult.env;
|
|
11452
|
+
}
|
|
11298
11453
|
}
|
|
11454
|
+
const resolvedMedia = message.mediaUrls?.length ? await resolveMediaAttachments(message.mediaUrls, invocationDir) : void 0;
|
|
11455
|
+
if (resolvedMedia?.length) logDebug(`[channel-bridge] resolved ${resolvedMedia.length}/${message.mediaUrls.length} media attachments`);
|
|
11456
|
+
const { supported: supportedMedia, unsupported: unsupportedMedia } = resolvedMedia?.length ? partitionMedia(runtime, resolvedMedia) : {
|
|
11457
|
+
supported: [],
|
|
11458
|
+
unsupported: []
|
|
11459
|
+
};
|
|
11460
|
+
const mediaWarning = formatUnsupportedMediaWarning(unsupportedMedia, this.#provider);
|
|
11461
|
+
if (unsupportedMedia.length > 0) logDebug(`[channel-bridge] unsupported media: ${unsupportedMedia.length} attachment(s) not accepted by ${this.#provider}`);
|
|
11299
11462
|
const adapter = new DeliveryAdapter(this.#chunkLimit !== void 0 ? { chunkLimit: this.#chunkLimit } : void 0);
|
|
11300
11463
|
let runResult;
|
|
11301
11464
|
let lastError;
|
|
@@ -11303,11 +11466,16 @@ var ChannelBridge = class {
|
|
|
11303
11466
|
try {
|
|
11304
11467
|
const captured = captureResult(runtime.execute({
|
|
11305
11468
|
prompt: systemPrompt + (message.extraContext ? "\n\n" + message.extraContext : "") + "\n\n" + message.text,
|
|
11469
|
+
media: supportedMedia?.length ? supportedMedia : void 0,
|
|
11306
11470
|
sessionId: existingSessionId,
|
|
11307
11471
|
mcpServers,
|
|
11308
11472
|
abortSignal,
|
|
11309
11473
|
workingDirectory: workspaceDir,
|
|
11310
|
-
env:
|
|
11474
|
+
env: this.#runtimeEnv || hookEnv ? {
|
|
11475
|
+
...this.#runtimeEnv,
|
|
11476
|
+
...hookEnv
|
|
11477
|
+
} : void 0,
|
|
11478
|
+
extraArgs: this.#runtimeArgs
|
|
11311
11479
|
}));
|
|
11312
11480
|
payloads = await adapter.process(captured.events, callbacks);
|
|
11313
11481
|
runResult = captured.getResult();
|
|
@@ -11315,6 +11483,7 @@ var ChannelBridge = class {
|
|
|
11315
11483
|
} catch (err) {
|
|
11316
11484
|
const errMsg = String(err);
|
|
11317
11485
|
const category = classifyError(errMsg);
|
|
11486
|
+
logDebug(`[channel-bridge] runtime threw: category=${category} error=${errMsg.slice(0, 500)}`);
|
|
11318
11487
|
lastError = errMsg;
|
|
11319
11488
|
payloads = [];
|
|
11320
11489
|
runResult = {
|
|
@@ -11322,13 +11491,18 @@ var ChannelBridge = class {
|
|
|
11322
11491
|
errorSubtype: category === "context_overflow" ? "context_window" : category
|
|
11323
11492
|
};
|
|
11324
11493
|
}
|
|
11494
|
+
if (mediaWarning) payloads.unshift({ text: mediaWarning });
|
|
11325
11495
|
let mcp;
|
|
11326
11496
|
try {
|
|
11327
11497
|
mcp = await readMcpSideEffects(sideEffectsFile);
|
|
11328
11498
|
} catch {
|
|
11329
11499
|
mcp = { ...EMPTY_SIDE_EFFECTS };
|
|
11330
11500
|
}
|
|
11331
|
-
|
|
11501
|
+
logDebug(`[channel-bridge] side effects: sentTexts=${mcp.sentTexts.length} sentMedia=${mcp.sentMediaUrls.length} cronAdds=${mcp.cronAdds}`);
|
|
11502
|
+
if (runResult?.sessionId) {
|
|
11503
|
+
logDebug(`[channel-bridge] session update: key=${formatSessionKeyString(sessionKey)} sessionId=${runResult.sessionId}`);
|
|
11504
|
+
await this.#sessionMap.set(sessionKey, runResult.sessionId);
|
|
11505
|
+
}
|
|
11332
11506
|
const finalResult = runResult ?? { ...DEFAULT_RUN_RESULT };
|
|
11333
11507
|
if (hookRunner) {
|
|
11334
11508
|
const runtimeCtx = {
|
|
@@ -11356,6 +11530,7 @@ var ChannelBridge = class {
|
|
|
11356
11530
|
durationMs: finalResult.durationMs
|
|
11357
11531
|
}, runtimeCtx);
|
|
11358
11532
|
}
|
|
11533
|
+
logDebug(`[channel-bridge] complete: runId=${runId} duration=${finalResult.durationMs}ms payloads=${payloads.length} error=${lastError ?? "none"}`);
|
|
11359
11534
|
return {
|
|
11360
11535
|
payloads,
|
|
11361
11536
|
run: finalResult,
|
|
@@ -11517,4 +11692,4 @@ function resolveGatewayCredentialsFromConfig(params) {
|
|
|
11517
11692
|
}
|
|
11518
11693
|
|
|
11519
11694
|
//#endregion
|
|
11520
|
-
export { ChannelBridge,
|
|
11695
|
+
export { ChannelBridge, ensureAgentWorkspace, loadSessionStore, resolveAgentDir, resolveAgentIdentity, resolveAgentTimeoutMs, resolveAgentWorkspaceDir, resolveGatewayCredentialsFromConfig, resolveGatewayPort, resolveSessionFilePath, resolveStorePath, saveSessionStore };
|