activeclaw 2026.2.11 → 2026.2.13
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/CHANGELOG.md +106 -0
- package/dist/{accounts-DbzMEfKN.js → accounts-DCDeFTra.js} +2 -2
- package/dist/{accounts-C2elk6PC.js → accounts-DeqIQjo1.js} +2 -2
- package/dist/{acp-cli-CVFTdsQY.js → acp-cli-CeYI4XRd.js} +15 -16
- package/dist/{acp-cli-BpJwIyLl.js → acp-cli-rNbGXICg.js} +14 -15
- package/dist/{agent-Bz1r5O8q.js → agent-BvNJF5QL.js} +19 -15
- package/dist/{agent-22-R4bNS.js → agent-CyMxTyrG.js} +20 -16
- package/dist/{agent-scope-D8miw9q_.js → agent-scope-BIEhVP4_.js} +172 -4
- package/dist/{agent-scope-CGmuusG9.js → agent-scope-CQCus0rI.js} +3 -3
- package/dist/{agent-scope-DQuy3dwI.js → agent-scope-CsRbLH4l.js} +4 -4
- package/dist/{agent-scope-BEf5crnU.js → agent-scope-DPIFau3f.js} +5 -1
- package/dist/audio-preflight-BU8W7uxc.js +60 -0
- package/dist/audio-preflight-CGsumMzb.js +60 -0
- package/dist/audio-preflight-SLmkJI6-.js +74 -0
- package/dist/audio-preflight-jZc5mFCZ.js +71 -0
- package/dist/{audit-C4wLaF0D.js → audit-Dmww_503.js} +71 -19
- package/dist/{audit-CY-yopxa.js → audit-wPu26VMb.js} +72 -20
- package/dist/{tailscale-DU6DgqVy.js → auth-9x3lqfIY.js} +208 -3
- package/dist/{tailscale-Cu-2HNvU.js → auth-CQNl_IaI.js} +190 -3
- package/dist/{auth-health-BFKUoCwJ.js → auth-health-C4L4FGBA.js} +1 -1
- package/dist/{auth-health-d7BMZlWG.js → auth-health-j6epgQbq.js} +1 -1
- package/dist/{auth-profiles-Bv1AEm-Y.js → auth-profiles-ByNs3eEm.js} +87 -31
- package/dist/build-info.json +3 -3
- package/dist/bundled/boot-md/handler.js +28 -22
- package/dist/bundled/session-memory/handler.js +33 -22
- package/dist/{call-7yrB6v4I.js → call-DVYCIV8m.js} +5 -5
- package/dist/{call-Bek1xlgk.js → call-SolyGS1r.js} +6 -6
- package/dist/canvas-host/a2ui/.bundle.hash +1 -1
- package/dist/{channel-options-3mdYN0C_.js → channel-options-BwC2yQcR.js} +4 -4
- package/dist/{channel-options-DJ0b1m7B.js → channel-options-Cq9BVDkP.js} +12 -7
- package/dist/{channel-selection-RZimme3j.js → channel-selection-D4D6ImhN.js} +2 -2
- package/dist/{channel-selection-B9b7Kuit.js → channel-selection-MZAHm4U8.js} +2 -2
- package/dist/{channels-cli-CYbK2Dku.js → channels-cli-9Dsk9Qm7.js} +57 -53
- package/dist/{channels-cli-BFznbGOs.js → channels-cli-BJUppQll.js} +59 -55
- package/dist/{channels-status-issues-B3KkflfR.js → channels-status-issues-D7GSV1GS.js} +1 -1
- package/dist/{channels-status-issues-DQkRaZts.js → channels-status-issues-DDAWeT-6.js} +1 -1
- package/dist/{chrome-Db7w64LF.js → chrome-BfB6JdKF.js} +4 -4
- package/dist/{chrome-Dm-EgOjJ.js → chrome-Cvr-57lg.js} +6 -5
- package/dist/{chrome-CF16STk9.js → chrome-DL0avO8n.js} +2 -1
- package/dist/{chrome-yIKmOzCO.js → chrome-foEwx3lN.js} +5 -4
- package/dist/{clack-prompter-BCiBkJVr.js → clack-prompter-Bz3Mmcl-.js} +5 -5
- package/dist/{clack-prompter-DuBVnTKy.js → clack-prompter-ChCGXfyt.js} +4 -4
- package/dist/cli/daemon-cli.js +1 -1
- package/dist/{cli-Cl3PdJei.js → cli-ZR9ugUBX.js} +42 -38
- package/dist/cli-miPe4Ujz.js +93 -0
- package/dist/{client-6xKrRC-1.js → client-BrYfyoDK.js} +54 -5
- package/dist/{client-DMloFP_O.js → client-CTwXnRl7.js} +54 -5
- package/dist/{command-format-ayFsmwwz.js → command-format-Bxe0mWee.js} +1 -1
- package/dist/{command-options-BTAzyqqb.js → command-options-BvgxzPbK.js} +9 -4
- package/dist/{commands-CjEGXOZ_.js → commands-BX_OIIVR.js} +4 -4
- package/dist/{completion-cli-DrJGfJGl.js → completion-cli-CR77-jyv.js} +3 -3
- package/dist/{completion-cli-DOec3E2Z.js → completion-cli-DnjpxAag.js} +30 -30
- package/dist/{config-B00lvFac.js → config-Bdhomfei.js} +21 -7
- package/dist/{config-XBdA0ciN.js → config-BvMsmctM.js} +83 -9
- package/dist/{config-BqGVMf1y.js → config-QYrbd7x7.js} +60 -6
- package/dist/{config--NUdpACy.js → config-aFQssWKX.js} +21 -7
- package/dist/{config-guard-4kCO_rnQ.js → config-guard-CljaSxJd.js} +160 -51
- package/dist/{configure-B69emwZv.js → configure-BXLiucXo.js} +28 -25
- package/dist/{configure-sMhpLzFf.js → configure-BYPqXzGZ.js} +28 -25
- package/dist/control-auth-8Cf4WXpR.js +54 -0
- package/dist/control-auth-DBCu3qyv.js +54 -0
- package/dist/{control-service-Db_1V-KY.js → control-service-B5KnPqGP.js} +11 -5
- package/dist/{control-service-IRAmbcbN.js → control-service-DKnttEus.js} +10 -4
- package/dist/control-ui/assets/{index-CnB9IO4a.js → index-B4LPvte9.js} +369 -369
- package/dist/control-ui/assets/index-B4LPvte9.js.map +1 -0
- package/dist/control-ui/index.html +1 -1
- package/dist/{cron-cli-Cum2324v.js → cron-cli-D7BRjDv2.js} +20 -20
- package/dist/{cron-cli-DhUWcYdk.js → cron-cli-z1zk_FXQ.js} +19 -19
- package/dist/{daemon-cli-q7nkEF5-.js → daemon-cli-BDkU2ocb.js} +60 -21
- package/dist/{daemon-cli-CTC2CHci.js → daemon-cli-cNSF93-v.js} +59 -20
- package/dist/{daemon-runtime-c0uXH4Dl.js → daemon-runtime-B0tg_LsX.js} +3 -3
- package/dist/{daemon-runtime-UsK-tOty.js → daemon-runtime-Bsjeut6m.js} +3 -3
- package/dist/{deliver-hf-WKyWd.js → deliver-CIU9Npgs.js} +373 -281
- package/dist/{deliver-CT6KiDqO.js → deliver-DYYCo1G7.js} +369 -278
- package/dist/{deliver-T9d44OpZ.js → deliver-LsxKETro.js} +371 -279
- package/dist/{deliver-CPy8jYj9.js → deliver-xUU3mGHo.js} +369 -277
- package/dist/{deps-Bv1kLtwo.js → deps-QSwGcoNZ.js} +2 -2
- package/dist/{deps-DFQdAWQc.js → deps-lAAA2zYI.js} +2 -2
- package/dist/{devices-cli-Cm7U1py9.js → devices-cli-BG3-2oqt.js} +14 -14
- package/dist/{devices-cli-ZpjlfK-e.js → devices-cli-VIQtOvt_.js} +14 -14
- package/dist/{directory-cli-B14TUSJA.js → directory-cli-BCJwjVC0.js} +16 -16
- package/dist/{directory-cli-67kzd4I5.js → directory-cli-jYzZ02gk.js} +14 -14
- package/dist/{dispatcher-3ElQWGVI.js → dispatcher-DY51b-Zc.js} +2 -2
- package/dist/{dns-cli-CU-xfhTN.js → dns-cli-DHIiMJjS.js} +12 -12
- package/dist/{dns-cli-Dqj7O6Q_.js → dns-cli-pZlv87Ib.js} +11 -11
- package/dist/{docs-cli-CamBqzb5.js → docs-cli-2JDiwfzP.js} +8 -8
- package/dist/{docs-cli-Cj3L5oqB.js → docs-cli-BhkYqoIQ.js} +7 -7
- package/dist/{doctor-BV1kvbMm.js → doctor-Bf8EhNtA.js} +36 -35
- package/dist/{doctor-BJirShBi.js → doctor-sYG5V4Co.js} +34 -33
- package/dist/entry.js +56 -18
- package/dist/{env-BxRc6wWv.js → env-ONzUVAG2.js} +1 -1
- package/dist/{exec-CijMSZd9.js → exec-B8lXct-k.js} +503 -14
- package/dist/{exec-B8JKbXKW.js → exec-CACT5OAW.js} +1 -1
- package/dist/{exec-57A8Rlc8.js → exec-CJFFoM7H.js} +32 -13
- package/dist/{exec-Cv_Ofd1m.js → exec-YIosokWE.js} +1 -1
- package/dist/{exec-approvals-cli-DEzz9Iai.js → exec-approvals-cli-7LH0lwhO.js} +21 -21
- package/dist/{exec-approvals-cli-DhXj3hQX.js → exec-approvals-cli-apGnQbpj.js} +21 -21
- package/dist/extensionAPI.js +7733 -8746
- package/dist/fetch-DmiOpALK.js +274 -0
- package/dist/fetch-timeout-BEtUjM1S.js +274 -0
- package/dist/fetch-timeout-DEoXG_SF.js +274 -0
- package/dist/fetch-timeout-DTK9vxex.js +274 -0
- package/dist/{gateway-cli-D1EdIq8I.js → gateway-cli-DUdYxlZS.js} +491 -136
- package/dist/{gateway-cli-B_xDUDy2.js → gateway-cli-DbvWmE-9.js} +495 -140
- package/dist/{gateway-rpc-3B5y445n.js → gateway-rpc-BByb2Snz.js} +3 -3
- package/dist/{gateway-rpc-BoL2vinh.js → gateway-rpc-wXSCUZXj.js} +3 -3
- package/dist/{github-copilot-auth-Omqrto0J.js → github-copilot-auth-D7ewvpMd.js} +205 -17
- package/dist/{github-copilot-auth-CZxurvdz.js → github-copilot-auth-DDispnyz.js} +205 -17
- package/dist/{github-copilot-token-SLWintYd.js → github-copilot-token-Cfs0Wxr8.js} +1 -1
- package/dist/{gmail-setup-utils-BXQKsLtI.js → gmail-setup-utils-Cfns8TQx.js} +3 -3
- package/dist/{gmail-setup-utils-CHcssBOA.js → gmail-setup-utils-DJb-_5kO.js} +4 -4
- package/dist/{health-format-Dy1caGsq.js → health-format-KGPokKJH.js} +97 -42
- package/dist/{health-format-DrGFg8bx.js → health-format-LZDxu3rv.js} +95 -40
- package/dist/{help-format-DAj7l5uV.js → help-format-C48TXngO.js} +1 -1
- package/dist/{help-format-CUnac_bT.js → help-format-R5fLToDw.js} +1 -1
- package/dist/{hooks-cli-ptEf6TIM.js → hooks-cli-CT8JCRkH.js} +51 -46
- package/dist/{hooks-cli-Bhf5VRp1.js → hooks-cli-S1MKumJO.js} +49 -44
- package/dist/{hooks-status-Br-2bK2G.js → hooks-status-Cw0xD8Lt.js} +3 -3
- package/dist/{hooks-status-DNQJSa4B.js → hooks-status-D9MhwHRp.js} +3 -3
- package/dist/{image-rOFfK3PJ.js → image-Brk1sJbw.js} +10 -7
- package/dist/{image-fUwR7slg.js → image-C4Nn2p3e.js} +10 -7
- package/dist/{image-Ds4NLGPR.js → image-DgtfXMcX.js} +9 -6
- package/dist/{image-Dnnxt82I.js → image-RKwc3fsL.js} +8 -5
- package/dist/index.js +208 -97
- package/dist/{installs-CRSjQxbR.js → installs-CrLcWYHe.js} +8 -7
- package/dist/{installs-89zeUsVn.js → installs-DscWb9b9.js} +8 -7
- package/dist/{links-7M-j83As.js → links-B8LAzWwg.js} +1 -1
- package/dist/{links-C591fM9M.js → links-Eax1UO3w.js} +1 -1
- package/dist/llm-slug-generator.js +18 -19
- package/dist/{loader-wXwp4rZJ.js → loader-KjT074JR.js} +5722 -6888
- package/dist/{logging-MMRGFxGI.js → logging-BAyPwvdH.js} +1 -1
- package/dist/{logging-DuK6YXuK.js → logging-CRq4h04P.js} +2 -2
- package/dist/{login-qr-wM8BnKJh.js → login-qr-B6ZgAuIf.js} +5 -5
- package/dist/{login-qr-CPEsT6dN.js → login-qr-Bua-p0nG.js} +3 -4
- package/dist/{login-qr-CGEu5TU-.js → login-qr-CuvemJj4.js} +6 -6
- package/dist/{login-qr-DH150tTp.js → login-qr-Djr1JfIf.js} +2 -2
- package/dist/{logs-cli-ClgkHnfT.js → logs-cli-9IAV7rWY.js} +38 -22
- package/dist/{logs-cli-CmfINsOj.js → logs-cli-EiKzUFPa.js} +37 -21
- package/dist/{manager-DYo4PlVM.js → manager-BIMh_eSm.js} +7 -8
- package/dist/{manager-D6EbxDV4.js → manager-CwinWQoz.js} +5 -5
- package/dist/{manager-BbnHek5T.js → manager-DkqF1GiK.js} +9 -9
- package/dist/{manager-CcVYv0N5.js → manager-T1XfGchB.js} +8 -8
- package/dist/{manifest-registry-3It8Z8yN.js → manifest-registry-CQhdnDBZ.js} +40 -2
- package/dist/{manifest-registry-D5SiA3xq.js → manifest-registry-u0okVSkU.js} +40 -2
- package/dist/{message-channel-Cu61-7H6.js → message-channel-BLi2a6Yw.js} +1 -1
- package/dist/{message-channel-BlgPSDAh.js → message-channel-C_MmebBt.js} +1 -1
- package/dist/{model-auth-ioeR_zLX.js → model-auth-CabXIF6O.js} +116 -34
- package/dist/{model-selection-BK7DuyH8.js → model-selection-BLuqsGVB.js} +86 -30
- package/dist/{model-selection-CezC36lH.js → model-selection-C1GmkTAV.js} +84 -28
- package/dist/{models-cli-C3uGdOrd.js → models-cli-9jmDv-h3.js} +52 -48
- package/dist/{models-cli-CUIVPgXE.js → models-cli-zS9rtWz8.js} +53 -49
- package/dist/{node-cli-BxBGSuPE.js → node-cli-CrpTxTTs.js} +28 -26
- package/dist/{node-cli-CdYAsuQQ.js → node-cli-wemUMCg-.js} +28 -26
- package/dist/{node-service-u8g85nD3.js → node-service-C8DTHTMg.js} +2 -2
- package/dist/{node-service-CM5vkdIo.js → node-service-WQuEKz6W.js} +2 -2
- package/dist/{nodes-cli-By6yeCTB.js → nodes-cli-BaU2SIFw.js} +20 -20
- package/dist/{nodes-cli-BaVMTAPc.js → nodes-cli-Dx23D72n.js} +20 -20
- package/dist/{nodes-screen-Dvl_ohUY.js → nodes-screen-C0IuBqUL.js} +1 -1
- package/dist/{note-5WqioBRA.js → note-BhRSeNeu.js} +2 -2
- package/dist/{note-Ci08TSbV.js → note-hhtubr2j.js} +1 -1
- package/dist/{onboard-channels-DxXvp8og.js → onboard-channels-C501x8GI.js} +8 -8
- package/dist/{onboard-channels-CXhnVy4E.js → onboard-channels-Dxzroasd.js} +8 -8
- package/dist/{onboard-skills-CBxsRGyf.js → onboard-skills-DV0Qzvjj.js} +440 -136
- package/dist/{onboard-skills-DQwOQ6Ry.js → onboard-skills-rlBHcu3Q.js} +439 -135
- package/dist/{onboarding-Du_7qEng.js → onboarding-CN-EDLjd.js} +38 -38
- package/dist/{openclaw-root-JLDMp6ux.js → openclaw-root-1VeFrph_.js} +4 -0
- package/dist/{openclaw-root-Dw6gumSU.js → openclaw-root-BNlEap4i.js} +4 -0
- package/dist/{pairing-cli-CRQDpj8f.js → pairing-cli-CDHG4xuI.js} +15 -15
- package/dist/{pairing-cli-Cng1KFWw.js → pairing-cli-CQP34Dlx.js} +15 -15
- package/dist/{pairing-labels-Ciu3Zoxj.js → pairing-labels-B6CN0SNH.js} +1 -1
- package/dist/{pairing-labels-CWFEtSc3.js → pairing-labels-CgNHnjzT.js} +1 -1
- package/dist/{pairing-store-c-QQ2u8p.js → pairing-store-CmlRVqOz.js} +2 -2
- package/dist/{pairing-store-CgXR3ZWJ.js → pairing-store-Dp5_JGnG.js} +3 -3
- package/dist/{path-env-CXWUFfFv.js → path-env-CLvYNwtL.js} +1 -1
- package/dist/{path-env-BgLvMbz_.js → path-env-CaYUVIML.js} +2 -2
- package/dist/{paths-MnZaxqPw.js → paths-B0a4ywSO.js} +30 -5
- package/dist/{paths-Bkhd_qY8.js → paths-B49s6UZQ.js} +30 -5
- package/dist/{paths-DL6EIRTw.js → paths-D0O87MfH.js} +30 -5
- package/dist/{paths-IivnSNkP.js → paths-DLINmNFQ.js} +31 -6
- package/dist/{pi-embedded-CgPTEqlB.js → pi-embedded-Ctrt2kz0.js} +8759 -9600
- package/dist/{pi-embedded-helpers-DYH6OWft.js → pi-embedded-helpers-CMKLjW6X.js} +68 -9
- package/dist/{pi-embedded-helpers-y1_Se0yq.js → pi-embedded-helpers-CUzTc1v6.js} +241 -24
- package/dist/{pi-embedded-helpers-Bkpd4fTr.js → pi-embedded-helpers-DfwkwPYD.js} +67 -8
- package/dist/{pi-embedded-helpers-BbWRSUnc.js → pi-embedded-helpers-WDwx99UA.js} +347 -32
- package/dist/{pi-tools.policy-akYsGFiA.js → pi-tools.policy-BpsROZbz.js} +4 -4
- package/dist/{plugin-auto-enable-lZwe2yX5.js → plugin-auto-enable-Bqhc3w5n.js} +5 -5
- package/dist/{plugin-auto-enable-AOSOJ-v1.js → plugin-auto-enable-PW76g_PJ.js} +5 -5
- package/dist/plugin-sdk/agents/bash-process-registry.d.ts +1 -0
- package/dist/plugin-sdk/agents/models-config.providers.d.ts +10 -0
- package/dist/plugin-sdk/agents/pi-embedded-helpers/errors.d.ts +5 -1
- package/dist/plugin-sdk/agents/pi-embedded-helpers.d.ts +1 -1
- package/dist/plugin-sdk/agents/pi-embedded-runner/google.d.ts +1 -0
- package/dist/plugin-sdk/agents/pi-embedded-runner/run/params.d.ts +2 -0
- package/dist/plugin-sdk/agents/pi-embedded-runner/run/payloads.d.ts +1 -0
- package/dist/plugin-sdk/agents/pi-embedded-runner/run/types.d.ts +2 -0
- package/dist/plugin-sdk/agents/pi-embedded-runner/types.d.ts +15 -0
- package/dist/plugin-sdk/agents/pi-embedded-subscribe.handlers.tools.d.ts +1 -1
- package/dist/plugin-sdk/agents/pi-embedded-subscribe.handlers.types.d.ts +2 -0
- package/dist/plugin-sdk/agents/pi-embedded-subscribe.types.d.ts +2 -0
- package/dist/plugin-sdk/agents/session-tool-result-guard-wrapper.d.ts +2 -0
- package/dist/plugin-sdk/agents/session-tool-result-guard.d.ts +4 -0
- package/dist/plugin-sdk/agents/tools/agent-step.d.ts +3 -0
- package/dist/plugin-sdk/agents/tools/browser-tool.schema.d.ts +1 -1
- package/dist/plugin-sdk/agents/tools/web-search.d.ts +10 -1
- package/dist/plugin-sdk/agents/usage.d.ts +1 -0
- package/dist/plugin-sdk/auto-reply/heartbeat.d.ts +1 -1
- package/dist/plugin-sdk/auto-reply/reply/get-reply-directives.d.ts +1 -0
- package/dist/plugin-sdk/auto-reply/reply/mentions.d.ts +1 -0
- package/dist/plugin-sdk/auto-reply/reply/model-selection.d.ts +3 -0
- package/dist/plugin-sdk/auto-reply/reply/reply-reference.d.ts +1 -1
- package/dist/plugin-sdk/auto-reply/reply/session-run-accounting.d.ts +11 -0
- package/dist/plugin-sdk/auto-reply/reply/session-usage.d.ts +8 -0
- package/dist/plugin-sdk/auto-reply/types.d.ts +2 -0
- package/dist/plugin-sdk/browser/control-auth.d.ts +13 -0
- package/dist/plugin-sdk/channels/plugins/onboarding/signal.d.ts +1 -0
- package/dist/plugin-sdk/cli/prompt.d.ts +1 -0
- package/dist/plugin-sdk/commands/agent/types.d.ts +2 -0
- package/dist/plugin-sdk/commands/onboard-types.d.ts +7 -1
- package/dist/plugin-sdk/config/sessions/paths.d.ts +7 -2
- package/dist/plugin-sdk/config/types.agents.d.ts +2 -0
- package/dist/plugin-sdk/config/types.discord.d.ts +5 -0
- package/dist/plugin-sdk/config/types.gateway.d.ts +15 -0
- package/dist/plugin-sdk/config/types.hooks.d.ts +15 -0
- package/dist/plugin-sdk/config/types.memory.d.ts +2 -0
- package/dist/plugin-sdk/config/zod-schema.agents.d.ts +1 -0
- package/dist/plugin-sdk/config/zod-schema.d.ts +13 -1
- package/dist/plugin-sdk/config/zod-schema.hooks.d.ts +1 -1
- package/dist/plugin-sdk/config/zod-schema.providers-core.d.ts +9 -0
- package/dist/plugin-sdk/config/zod-schema.providers.d.ts +4 -0
- package/dist/plugin-sdk/cron/service/jobs.d.ts +8 -0
- package/dist/plugin-sdk/cron/service/state.d.ts +1 -0
- package/dist/plugin-sdk/cron/types.d.ts +2 -0
- package/dist/plugin-sdk/discord/monitor/allow-list.d.ts +15 -0
- package/dist/plugin-sdk/discord/send.types.d.ts +5 -0
- package/dist/plugin-sdk/gateway/auth.d.ts +36 -0
- package/dist/plugin-sdk/gateway/protocol/index.d.ts +0 -3
- package/dist/plugin-sdk/gateway/protocol/schema/agent.d.ts +7 -1
- package/dist/plugin-sdk/gateway/session-utils.fs.d.ts +3 -1
- package/dist/plugin-sdk/index.js +935 -660
- package/dist/plugin-sdk/infra/binaries.d.ts +3 -0
- package/dist/plugin-sdk/infra/heartbeat-active-hours.d.ts +5 -0
- package/dist/plugin-sdk/infra/heartbeat-runner.d.ts +1 -0
- package/dist/plugin-sdk/infra/net/fetch-guard.d.ts +1 -0
- package/dist/plugin-sdk/infra/net/ssrf.d.ts +1 -0
- package/dist/plugin-sdk/infra/tailscale.d.ts +34 -0
- package/dist/plugin-sdk/infra/tmp-openclaw-dir.d.ts +10 -0
- package/dist/plugin-sdk/logging/console.d.ts +1 -0
- package/dist/plugin-sdk/logging/logger.d.ts +1 -1
- package/dist/plugin-sdk/logging/state.d.ts +1 -0
- package/dist/plugin-sdk/markdown/ir.d.ts +1 -1
- package/dist/plugin-sdk/markdown/whatsapp.d.ts +14 -0
- package/dist/plugin-sdk/media/input-files.d.ts +5 -0
- package/dist/plugin-sdk/media-understanding/audio-preflight.d.ts +16 -0
- package/dist/plugin-sdk/media-understanding/types.d.ts +1 -0
- package/dist/plugin-sdk/memory/backend-config.d.ts +2 -1
- package/dist/plugin-sdk/memory/qmd-manager.d.ts +2 -0
- package/dist/plugin-sdk/memory/qmd-query-parser.d.ts +8 -0
- package/dist/plugin-sdk/process/command-queue.d.ts +16 -0
- package/dist/plugin-sdk/routing/resolve-route.d.ts +3 -1
- package/dist/plugin-sdk/security/external-content.d.ts +1 -1
- package/dist/plugin-sdk/security/secret-equal.d.ts +1 -0
- package/dist/plugin-sdk/sessions/input-provenance.d.ts +16 -0
- package/dist/plugin-sdk/signal/monitor/event-handler.types.d.ts +8 -0
- package/dist/plugin-sdk/signal/monitor/mentions.d.ts +2 -0
- package/dist/plugin-sdk/slack/monitor/commands.d.ts +5 -0
- package/dist/plugin-sdk/telegram/bot-message-context.d.ts +2 -1
- package/dist/plugin-sdk/telegram/send.d.ts +3 -0
- package/dist/plugin-sdk/web/media.d.ts +2 -0
- package/dist/{plugins-Db5BiELK.js → plugins-4Hqd1WGf.js} +3 -3
- package/dist/{plugins-CNaHNND_.js → plugins-X7d_tfTE.js} +4 -4
- package/dist/{plugins-cli-8G-hQPCu.js → plugins-cli-Bgku3EGj.js} +253 -44
- package/dist/{plugins-cli-CDiocaDE.js → plugins-cli-CVToH3if.js} +257 -48
- package/dist/{ports-BeebfNCb.js → ports-qkt29rdC.js} +2 -2
- package/dist/{program-0Cj9YxRN.js → program-Cf7lkBur.js} +82 -80
- package/dist/{progress-DIQJt9Va.js → progress-C9kngsTD.js} +1 -1
- package/dist/{progress-Da1ehW-x.js → progress-DWqhRakV.js} +1 -1
- package/dist/{prompt-style-Dc0C5HC9.js → prompt-style-BFH5D5LN.js} +1 -1
- package/dist/{prompt-style-CjQRlDx4.js → prompt-style-CIbmaxSa.js} +1 -1
- package/dist/{pw-ai-C43wv1ZF.js → pw-ai-8mdv3h-d.js} +7 -6
- package/dist/{pw-ai-COWYvUfG.js → pw-ai-CM1IsSgZ.js} +6 -6
- package/dist/{pw-ai-BxJ-KCIy.js → pw-ai-FGoRVblI.js} +5 -6
- package/dist/{pw-ai-CsvaObGM.js → pw-ai-sS1fRKW_.js} +3 -3
- package/dist/{qmd-manager-CpsjQyaZ.js → qmd-manager-C67Fc8aN.js} +79 -26
- package/dist/{qmd-manager-C9YWFeG6.js → qmd-manager-CXVbfg99.js} +81 -26
- package/dist/{qmd-manager-C02E8ixK.js → qmd-manager-RMRE8Tqt.js} +81 -26
- package/dist/{qmd-manager-BzY2LQTT.js → qmd-manager-pyc_MTIe.js} +78 -23
- package/dist/{register.subclis-DUkirdHn.js → register.subclis-C02e4zuJ.js} +29 -29
- package/dist/{reply--b7BsXGP.js → reply-DICXkh_C.js} +7289 -8455
- package/dist/{routes-DUkEKAc1.js → routes-CmOI1hIH.js} +29 -11
- package/dist/{routes-B4QQiFju.js → routes-DewK5tq2.js} +29 -12
- package/dist/{rpc-CuMtxrRT.js → rpc-DHr30euf.js} +3 -3
- package/dist/{rpc-Blt6MJ4F.js → rpc-T300F8zI.js} +3 -3
- package/dist/{run-main-XZcPA23b.js → run-main-C5wpthq1.js} +84 -82
- package/dist/runner-CY0nmVme.js +1886 -0
- package/dist/runner-Cfm5nTMc.js +1785 -0
- package/dist/runner-D_dujMod.js +1886 -0
- package/dist/runner-DrGYLH5K.js +1785 -0
- package/dist/{sandbox-Aks-9EcZ.js → sandbox-BKYnhYQH.js} +24 -17
- package/dist/{sandbox-DqUO2K83.js → sandbox-Bhjnh1Xg.js} +23 -16
- package/dist/{sandbox-cli-C99Thxi8.js → sandbox-cli-DBsAjZJN.js} +21 -21
- package/dist/{sandbox-cli-CJqRM4V6.js → sandbox-cli-rV9LtFeu.js} +21 -21
- package/dist/{security-cli-iqYLMOz3.js → security-cli-BIwJM_rs.js} +27 -27
- package/dist/{security-cli-DW3lCz-o.js → security-cli-BRjny8Yu.js} +27 -27
- package/dist/{server-context-fX4xiYRh.js → server-context-BGpGs3qd.js} +7 -7
- package/dist/{server-context-8Qt35QdF.js → server-context-Cl0U0vE3.js} +7 -7
- package/dist/{server-node-events-CHWXfb_T.js → server-node-events-CBfTbiTA.js} +48 -44
- package/dist/{server-node-events-BzrEnKLX.js → server-node-events-QCvh8EgI.js} +45 -41
- package/dist/{service-Cd4BxKuo.js → service--nPk7DvT.js} +8 -4
- package/dist/{service-DDPRbf8a.js → service-99RDXwX4.js} +8 -4
- package/dist/{service-audit-CCFxuvKs.js → service-audit-DnLmRGQt.js} +4 -4
- package/dist/{service-audit-x6jCN-6a.js → service-audit-ckBaRCVC.js} +4 -4
- package/dist/{session-cost-usage-CcCEQNuc.js → session-cost-usage-D7HuoSSD.js} +12 -10
- package/dist/{session-cost-usage-PvyVZz-g.js → session-cost-usage-D9hHANWI.js} +12 -10
- package/dist/{shared-ILguacOr.js → shared-Bs4vduG4.js} +3 -3
- package/dist/{shared-CagUDdmp.js → shared-CEY5IkwG.js} +3 -3
- package/dist/{shared-gOyV38rM.js → shared-DRohONn_.js} +4 -4
- package/dist/{shared-BDk_zC9p.js → shared-ICqOZibV.js} +4 -4
- package/dist/{skill-scanner-C_fQzVDu.js → skill-scanner-CucvxYhu.js} +1 -1
- package/dist/{skill-scanner-DrVEHfC6.js → skill-scanner-rHMtUHtP.js} +1 -1
- package/dist/{skills-D5UZZZSY.js → skills-DRjfSQT3.js} +141 -6
- package/dist/{skills-ccAgQ3Ad.js → skills-DprQj9X2.js} +142 -7
- package/dist/{skills-cli-DQilTG3n.js → skills-cli-9WO-C55s.js} +12 -12
- package/dist/{skills-cli-ggyLBtAY.js → skills-cli-B9eej-EW.js} +13 -13
- package/dist/{skills-status-BosMnzIs.js → skills-status-5U3P3YfJ.js} +3 -3
- package/dist/{skills-status-DjtPPMnY.js → skills-status-TDIgVd1K.js} +2 -2
- package/dist/{sqlite-B7FPASCO.js → sqlite-BINzs1U0.js} +2 -2
- package/dist/{sqlite-Btrgi7-j.js → sqlite-D4w5TejA.js} +3 -3
- package/dist/{sqlite-BrQ9tw8B.js → sqlite-DRRHmlug.js} +3 -3
- package/dist/{sqlite-HepBVDoX.js → sqlite-F6PGkEm1.js} +2 -2
- package/dist/{status-BByCntWS.js → status-BKGkKC_v.js} +3 -3
- package/dist/{status-Dt7RE_Yy.js → status-CiHtHdaa.js} +4 -4
- package/dist/{status-zfL4Yej7.js → status-DDWoOpeB.js} +37 -37
- package/dist/{subsystem-Bh1Y_6Uv.js → subsystem-BoExtIHo.js} +52 -17
- package/dist/{system-cli-DwuUkdkH.js → system-cli-B6lr60Io.js} +14 -14
- package/dist/{system-cli-Clqsx8U5.js → system-cli-CprW9G3h.js} +14 -14
- package/dist/{systemd-BEWwfwn0.js → systemd-C0VZriGM.js} +3 -3
- package/dist/{systemd-D6wTPnHi.js → systemd-DrmBtJ5T.js} +3 -3
- package/dist/{systemd-hints-zi4ohCOY.js → systemd-hints-DZtXiVHa.js} +1 -1
- package/dist/{systemd-linger-CDo2UbHM.js → systemd-linger-NC2kl1SC.js} +2 -2
- package/dist/{systemd-linger-BxjTrgoH.js → systemd-linger-xdn3BdPh.js} +2 -2
- package/dist/{table-DEnmtvl5.js → table-B8dx3v4v.js} +2 -2
- package/dist/{table-cCoGqLsk.js → table-CwulTLQp.js} +1 -1
- package/dist/{tool-display-DskiU8Kt.js → tool-display-CZRIDMRm.js} +2 -2
- package/dist/{tool-display-o-dDAlqF.js → tool-display-ClRud3pg.js} +2 -2
- package/dist/{tui-BdJWZdto.js → tui-CVTQn-dC.js} +14 -13
- package/dist/{tui-Bc7XUQGP.js → tui-Lu8FdrlK.js} +13 -14
- package/dist/{tui-cli-BGYh0UL0.js → tui-cli-BLpTj1X9.js} +27 -27
- package/dist/{tui-cli-D3n-O9zB.js → tui-cli-BLx5kL2I.js} +26 -26
- package/dist/{tui-formatters-CA85v4U2.js → tui-formatters-CNySEfJN.js} +6 -6
- package/dist/{tui-formatters-C3NarH24.js → tui-formatters-DePhZK3J.js} +6 -6
- package/dist/{update-JB16aPIY.js → update-DHVxMTpQ.js} +3 -3
- package/dist/{update-Ct9sqJC_.js → update-DU1geolI.js} +3 -3
- package/dist/{update-cli-wWKDS3cm.js → update-cli-C0hUvJWK.js} +89 -71
- package/dist/{update-cli-DDXp_N9B.js → update-cli-Wb1GB3rL.js} +88 -70
- package/dist/{update-runner-ChTf6O6p.js → update-runner--ixK4J3W.js} +11 -11
- package/dist/{update-runner-CmE6cHdn.js → update-runner-7Qa1T9y6.js} +10 -10
- package/dist/{utils-Dk86IbEs.js → utils-BLJAc3ZV.js} +1 -1
- package/dist/{utils-es4ygvQ-.js → utils-Cd9QdCHh.js} +1 -1
- package/dist/{webhooks-cli-CVIE9TtX.js → webhooks-cli-DgcMy7RG.js} +12 -12
- package/dist/{webhooks-cli-BmKSiQQC.js → webhooks-cli-aVzUcJY9.js} +11 -11
- package/dist/{widearea-dns-2ah0bkAj.js → widearea-dns-BaIgNEhY.js} +3 -3
- package/dist/{widearea-dns-CMIG6-74.js → widearea-dns-DzuRdwk5.js} +3 -3
- package/dist/{ws-DtDKpbLR.js → ws-CHCQHs0F.js} +1 -1
- package/dist/{ws-log-BP3z_g6Z.js → ws-log-CIXbLCka.js} +1 -1
- package/dist/{ws-log-D7MkvKhg.js → ws-log-DcQFZByi.js} +2 -2
- package/dist/{wsl-Cwo7X0Un.js → wsl-BUOkxKJu.js} +2 -2
- package/docs/assets/install-script.svg +1 -0
- package/docs/automation/hooks.md +1 -38
- package/docs/automation/webhook.md +43 -2
- package/docs/channels/discord.md +389 -381
- package/docs/channels/imessage.md +229 -218
- package/docs/channels/slack.md +294 -415
- package/docs/channels/telegram.md +401 -505
- package/docs/channels/whatsapp.md +338 -310
- package/docs/ci.md +0 -12
- package/docs/cli/hooks.md +1 -14
- package/docs/cli/index.md +6 -1
- package/docs/cli/logs.md +4 -0
- package/docs/cli/onboard.md +30 -0
- package/docs/cli/plugins.md +20 -1
- package/docs/cli/security.md +1 -0
- package/docs/concepts/memory.md +7 -4
- package/docs/concepts/session-tool.md +1 -0
- package/docs/docs.json +11 -11
- package/docs/gateway/configuration-examples.md +9 -2
- package/docs/gateway/configuration-reference.md +2329 -0
- package/docs/gateway/configuration.md +338 -3304
- package/docs/gateway/index.md +162 -238
- package/docs/gateway/openresponses-http-api.md +15 -0
- package/docs/gateway/security/index.md +3 -0
- package/docs/help/faq.md +9 -0
- package/docs/install/hetzner.md +21 -0
- package/docs/install/installer.md +20 -0
- package/docs/nodes/audio.md +19 -0
- package/docs/platforms/mac/release.md +7 -7
- package/docs/providers/glm.md +3 -3
- package/docs/providers/index.md +1 -0
- package/docs/providers/litellm.md +153 -0
- package/docs/providers/zai.md +2 -2
- package/docs/reference/templates/AGENTS.md +26 -26
- package/docs/reference/templates/HEARTBEAT.md +31 -2
- package/docs/reference/templates/SOUL.md +14 -8
- package/docs/reference/transcript-hygiene.md +18 -0
- package/docs/start/getting-started.md +5 -0
- package/docs/start/wizard-cli-automation.md +17 -0
- package/docs/start/wizard-cli-reference.md +12 -0
- package/docs/tools/browser.md +6 -0
- package/docs/zh-CN/automation/hooks.md +1 -38
- package/docs/zh-CN/cli/hooks.md +1 -14
- package/extensions/bluebubbles/package.json +1 -1
- package/extensions/bluebubbles/src/monitor.test.ts +40 -28
- package/extensions/bluebubbles/src/monitor.ts +0 -4
- package/extensions/copilot-proxy/package.json +1 -1
- package/extensions/diagnostics-otel/package.json +10 -10
- package/extensions/discord/package.json +1 -1
- package/extensions/feishu/package.json +2 -5
- package/extensions/feishu/src/bot.checkBotMentioned.test.ts +64 -0
- package/extensions/feishu/src/bot.ts +1 -1
- package/extensions/feishu/src/channel.test.ts +48 -0
- package/extensions/feishu/src/channel.ts +1 -3
- package/extensions/feishu/src/config-schema.ts +6 -0
- package/extensions/feishu/src/docx.ts +14 -4
- package/extensions/feishu/src/media.test.ts +151 -0
- package/extensions/feishu/src/media.ts +27 -13
- package/extensions/feishu/src/reply-dispatcher.test.ts +116 -0
- package/extensions/feishu/src/reply-dispatcher.ts +124 -67
- package/extensions/feishu/src/streaming-card.ts +223 -0
- package/extensions/feishu/src/targets.test.ts +16 -0
- package/extensions/feishu/src/targets.ts +1 -1
- package/extensions/google-antigravity-auth/package.json +1 -1
- package/extensions/google-gemini-cli-auth/package.json +1 -1
- package/extensions/googlechat/package.json +1 -1
- package/extensions/imessage/package.json +1 -1
- package/extensions/irc/package.json +1 -1
- package/extensions/irc/src/client.ts +1 -1
- package/extensions/line/package.json +1 -1
- package/extensions/llm-task/package.json +1 -1
- package/extensions/lobster/package.json +1 -1
- package/extensions/matrix/CHANGELOG.md +6 -0
- package/extensions/matrix/package.json +2 -2
- package/extensions/mattermost/package.json +1 -1
- package/extensions/memory-core/package.json +1 -1
- package/extensions/memory-lancedb/index.ts +6 -2
- package/extensions/memory-lancedb/package.json +2 -2
- package/extensions/minimax-portal-auth/index.ts +7 -5
- package/extensions/minimax-portal-auth/package.json +1 -1
- package/extensions/msteams/CHANGELOG.md +6 -0
- package/extensions/msteams/package.json +1 -1
- package/extensions/nextcloud-talk/package.json +1 -1
- package/extensions/nostr/CHANGELOG.md +6 -0
- package/extensions/nostr/package.json +2 -2
- package/extensions/open-prose/package.json +1 -1
- package/extensions/signal/package.json +1 -1
- package/extensions/slack/package.json +1 -1
- package/extensions/telegram/package.json +1 -1
- package/extensions/tlon/package.json +1 -1
- package/extensions/twitch/CHANGELOG.md +6 -0
- package/extensions/twitch/package.json +1 -1
- package/extensions/voice-call/CHANGELOG.md +6 -0
- package/extensions/voice-call/package.json +1 -1
- package/extensions/voice-call/src/media-stream.ts +7 -1
- package/extensions/voice-call/src/providers/twilio.test.ts +5 -3
- package/extensions/voice-call/src/providers/twilio.ts +12 -1
- package/extensions/whatsapp/package.json +1 -1
- package/extensions/zalo/CHANGELOG.md +6 -0
- package/extensions/zalo/package.json +1 -1
- package/extensions/zalouser/CHANGELOG.md +6 -0
- package/extensions/zalouser/package.json +1 -1
- package/package.json +26 -22
- package/dist/auth-BcNHFK-i.js +0 -184
- package/dist/auth-BvIPpm7G.js +0 -184
- package/dist/boolean-M-esQJt6.js +0 -30
- package/dist/bundled/soul-evil/HOOK.md +0 -71
- package/dist/bundled/soul-evil/handler.js +0 -194
- package/dist/cli-DJbWJ9aB.js +0 -89
- package/dist/config-CI7EpvlP.js +0 -15
- package/dist/control-ui/assets/index-CnB9IO4a.js.map +0 -1
- package/dist/date-time-c6HTX6IW.js +0 -187
- package/dist/frontmatter-xwTm0734.js +0 -105
- package/dist/parse-duration-De_tAQSe.js +0 -24
- package/dist/session-key-nXYQSv-a.js +0 -167
- package/dist/utils-dp_OM900.js +0 -476
- package/docs/hooks/soul-evil.md +0 -69
- package/docs/zh-CN/hooks/soul-evil.md +0 -72
- /package/dist/{archive-CXhvR9nU.js → archive-beaSfAzA.js} +0 -0
- /package/dist/{brew-BIrWdDps.js → brew-BUIxHEkn.js} +0 -0
- /package/dist/{brew-B7YK4ZoL.js → brew-ROHf0-Xp.js} +0 -0
- /package/dist/{cli-utils-PlLcDZlM.js → cli-utils-CRhVAaLV.js} +0 -0
- /package/dist/{cli-utils-R-ECs5cY.js → cli-utils-LcHOt63h.js} +0 -0
- /package/dist/{command-format-BUxhT1xL.js → command-format-qUVxzqYm.js} +0 -0
- /package/dist/{constants-CNTiY-ZN.js → constants-BvQ6S8j5.js} +0 -0
- /package/dist/{constants-DuoCkWRh.js → constants-JPeoOZnw.js} +0 -0
- /package/dist/{errors-D3tYRJWG.js → errors-B91HIDPD.js} +0 -0
- /package/dist/{errors-B0eT3jVv.js → errors-Bv81hF2P.js} +0 -0
- /package/dist/{errors-x4NYs-1P.js → errors-DjZBTJJ3.js} +0 -0
- /package/dist/{exec-approvals-DGPTjO0N.js → exec-approvals-Cb4ZLukq.js} +0 -0
- /package/dist/{exec-approvals-DhmKpiIo.js → exec-approvals-DQ8TVVmj.js} +0 -0
- /package/dist/{format-CaxeRcue.js → format-CNU-Zkrz.js} +0 -0
- /package/dist/{format-DLOJPZmo.js → format-DcfK-dwd.js} +0 -0
- /package/dist/{format-duration-Be5Z7JdJ.js → format-duration-84n6_DgO.js} +0 -0
- /package/dist/{format-duration-CEmFWLyX.js → format-duration-Bo9zNKwO.js} +0 -0
- /package/dist/{format-relative-79_Y1n2Y.js → format-relative-CZOlQ2pA.js} +0 -0
- /package/dist/{format-relative-Db7eqEu8.js → format-relative-cegC_FF5.js} +0 -0
- /package/dist/{github-copilot-token-C9IJh2Pn.js → github-copilot-token-DkiRbJdR.js} +0 -0
- /package/dist/{helpers-CQI-5xS9.js → helpers-8O7IVGO-.js} +0 -0
- /package/dist/{helpers-CRzoyyXS.js → helpers-D_jqdWkd.js} +0 -0
- /package/dist/{helpers-C89IG08W.js → helpers-HyeZXsnu.js} +0 -0
- /package/dist/{is-main-WWuz28Ip.js → is-main-BWoXGz7p.js} +0 -0
- /package/dist/{logging-BzvBIA3Y.js → logging-fywhKCmE.js} +0 -0
- /package/dist/{nodes-screen-lykd2cny.js → nodes-screen-CdCWeiwy.js} +0 -0
- /package/dist/{parse-Cjiudy6x.js → parse-Bw0oH-rT.js} +0 -0
- /package/dist/{parse-DqAvJRIf.js → parse-ioZhOtha.js} +0 -0
- /package/dist/{parse-log-line-CUrpqe1w.js → parse-log-line-BoDqomM4.js} +0 -0
- /package/dist/{parse-log-line-D2UGw0wR.js → parse-log-line-DPxH1XZx.js} +0 -0
- /package/dist/{parse-timeout-DFSPLxpY.js → parse-timeout-D1XX_zN_.js} +0 -0
- /package/dist/{parse-timeout-DV8NQQWk.js → parse-timeout-DMW-z4Iz.js} +0 -0
- /package/dist/{pi-model-discovery-CV2V1HHz.js → pi-model-discovery-DqgqUyAv.js} +0 -0
- /package/dist/{pi-model-discovery-DzFOAbQt.js → pi-model-discovery-EwKVHlZB.js} +0 -0
- /package/dist/{prompts--d-6l5Ln.js → prompts-Bg96reub.js} +0 -0
- /package/dist/{redact-DAKeu7PA.js → redact-BRsnXqwD.js} +0 -0
- /package/dist/{redact-DuEEf1p1.js → redact-Br9GfacZ.js} +0 -0
- /package/dist/{redact-BOIof271.js → redact-BrXLgslJ.js} +0 -0
- /package/dist/{status-Cv36yYdi.js → status-BRZfQbJ2.js} +0 -0
- /package/dist/{status-Drziap9H.js → status-CoAy6bEC.js} +0 -0
- /package/dist/{systemd-hints-CH4pbCFD.js → systemd-hints-CXNtLw9Q.js} +0 -0
- /package/dist/{tailnet-DGRSvYuQ.js → tailnet-DATIFSsY.js} +0 -0
- /package/dist/{transcript-events-BlIONGVn.js → transcript-events-BHS7QoRl.js} +0 -0
- /package/dist/{transcript-events-C1hdue6u.js → transcript-events-Bp7fGnwv.js} +0 -0
- /package/dist/{transcript-events-CZ8CG4ht.js → transcript-events-BtNd-j6q.js} +0 -0
- /package/dist/{usage-format-6Uar63S0.js → usage-format-C4JfTbSp.js} +0 -0
- /package/dist/{usage-format-hd37en6b.js → usage-format-CpORtVCG.js} +0 -0
|
@@ -0,0 +1,274 @@
|
|
|
1
|
+
import { c as logWarn } from "./exec-YIosokWE.js";
|
|
2
|
+
import { S as resolvePinnedHostnameWithPolicy, b as closeDispatcher, l as detectMime, u as extensionForMime, x as createPinnedDispatcher, y as SsrFBlockedError } from "./routes-CmOI1hIH.js";
|
|
3
|
+
import path from "node:path";
|
|
4
|
+
|
|
5
|
+
//#region src/infra/net/fetch-guard.ts
|
|
6
|
+
const DEFAULT_MAX_REDIRECTS = 3;
|
|
7
|
+
function isRedirectStatus(status) {
|
|
8
|
+
return status === 301 || status === 302 || status === 303 || status === 307 || status === 308;
|
|
9
|
+
}
|
|
10
|
+
function buildAbortSignal(params) {
|
|
11
|
+
const { timeoutMs, signal } = params;
|
|
12
|
+
if (!timeoutMs && !signal) return {
|
|
13
|
+
signal: void 0,
|
|
14
|
+
cleanup: () => {}
|
|
15
|
+
};
|
|
16
|
+
if (!timeoutMs) return {
|
|
17
|
+
signal,
|
|
18
|
+
cleanup: () => {}
|
|
19
|
+
};
|
|
20
|
+
const controller = new AbortController();
|
|
21
|
+
const timeoutId = setTimeout(() => controller.abort(), timeoutMs);
|
|
22
|
+
const onAbort = () => controller.abort();
|
|
23
|
+
if (signal) if (signal.aborted) controller.abort();
|
|
24
|
+
else signal.addEventListener("abort", onAbort, { once: true });
|
|
25
|
+
const cleanup = () => {
|
|
26
|
+
clearTimeout(timeoutId);
|
|
27
|
+
if (signal) signal.removeEventListener("abort", onAbort);
|
|
28
|
+
};
|
|
29
|
+
return {
|
|
30
|
+
signal: controller.signal,
|
|
31
|
+
cleanup
|
|
32
|
+
};
|
|
33
|
+
}
|
|
34
|
+
async function fetchWithSsrFGuard(params) {
|
|
35
|
+
const fetcher = params.fetchImpl ?? globalThis.fetch;
|
|
36
|
+
if (!fetcher) throw new Error("fetch is not available");
|
|
37
|
+
const maxRedirects = typeof params.maxRedirects === "number" && Number.isFinite(params.maxRedirects) ? Math.max(0, Math.floor(params.maxRedirects)) : DEFAULT_MAX_REDIRECTS;
|
|
38
|
+
const { signal, cleanup } = buildAbortSignal({
|
|
39
|
+
timeoutMs: params.timeoutMs,
|
|
40
|
+
signal: params.signal
|
|
41
|
+
});
|
|
42
|
+
let released = false;
|
|
43
|
+
const release = async (dispatcher) => {
|
|
44
|
+
if (released) return;
|
|
45
|
+
released = true;
|
|
46
|
+
cleanup();
|
|
47
|
+
await closeDispatcher(dispatcher ?? void 0);
|
|
48
|
+
};
|
|
49
|
+
const visited = /* @__PURE__ */ new Set();
|
|
50
|
+
let currentUrl = params.url;
|
|
51
|
+
let redirectCount = 0;
|
|
52
|
+
while (true) {
|
|
53
|
+
let parsedUrl;
|
|
54
|
+
try {
|
|
55
|
+
parsedUrl = new URL(currentUrl);
|
|
56
|
+
} catch {
|
|
57
|
+
await release();
|
|
58
|
+
throw new Error("Invalid URL: must be http or https");
|
|
59
|
+
}
|
|
60
|
+
if (!["http:", "https:"].includes(parsedUrl.protocol)) {
|
|
61
|
+
await release();
|
|
62
|
+
throw new Error("Invalid URL: must be http or https");
|
|
63
|
+
}
|
|
64
|
+
let dispatcher = null;
|
|
65
|
+
try {
|
|
66
|
+
const pinned = await resolvePinnedHostnameWithPolicy(parsedUrl.hostname, {
|
|
67
|
+
lookupFn: params.lookupFn,
|
|
68
|
+
policy: params.policy
|
|
69
|
+
});
|
|
70
|
+
if (params.pinDns !== false) dispatcher = createPinnedDispatcher(pinned);
|
|
71
|
+
const init = {
|
|
72
|
+
...params.init ? { ...params.init } : {},
|
|
73
|
+
redirect: "manual",
|
|
74
|
+
...dispatcher ? { dispatcher } : {},
|
|
75
|
+
...signal ? { signal } : {}
|
|
76
|
+
};
|
|
77
|
+
const response = await fetcher(parsedUrl.toString(), init);
|
|
78
|
+
if (isRedirectStatus(response.status)) {
|
|
79
|
+
const location = response.headers.get("location");
|
|
80
|
+
if (!location) {
|
|
81
|
+
await release(dispatcher);
|
|
82
|
+
throw new Error(`Redirect missing location header (${response.status})`);
|
|
83
|
+
}
|
|
84
|
+
redirectCount += 1;
|
|
85
|
+
if (redirectCount > maxRedirects) {
|
|
86
|
+
await release(dispatcher);
|
|
87
|
+
throw new Error(`Too many redirects (limit: ${maxRedirects})`);
|
|
88
|
+
}
|
|
89
|
+
const nextUrl = new URL(location, parsedUrl).toString();
|
|
90
|
+
if (visited.has(nextUrl)) {
|
|
91
|
+
await release(dispatcher);
|
|
92
|
+
throw new Error("Redirect loop detected");
|
|
93
|
+
}
|
|
94
|
+
visited.add(nextUrl);
|
|
95
|
+
response.body?.cancel();
|
|
96
|
+
await closeDispatcher(dispatcher);
|
|
97
|
+
currentUrl = nextUrl;
|
|
98
|
+
continue;
|
|
99
|
+
}
|
|
100
|
+
return {
|
|
101
|
+
response,
|
|
102
|
+
finalUrl: currentUrl,
|
|
103
|
+
release: async () => release(dispatcher)
|
|
104
|
+
};
|
|
105
|
+
} catch (err) {
|
|
106
|
+
if (err instanceof SsrFBlockedError) logWarn(`security: blocked URL fetch (${params.auditContext ?? "url-fetch"}) target=${parsedUrl.origin}${parsedUrl.pathname} reason=${err.message}`);
|
|
107
|
+
await release(dispatcher);
|
|
108
|
+
throw err;
|
|
109
|
+
}
|
|
110
|
+
}
|
|
111
|
+
}
|
|
112
|
+
|
|
113
|
+
//#endregion
|
|
114
|
+
//#region src/utils/fetch-timeout.ts
|
|
115
|
+
/**
|
|
116
|
+
* Fetch wrapper that adds timeout support via AbortController.
|
|
117
|
+
*
|
|
118
|
+
* @param url - The URL to fetch
|
|
119
|
+
* @param init - RequestInit options (headers, method, body, etc.)
|
|
120
|
+
* @param timeoutMs - Timeout in milliseconds
|
|
121
|
+
* @param fetchFn - The fetch implementation to use (defaults to global fetch)
|
|
122
|
+
* @returns The fetch Response
|
|
123
|
+
* @throws AbortError if the request times out
|
|
124
|
+
*/
|
|
125
|
+
async function fetchWithTimeout(url, init, timeoutMs, fetchFn = fetch) {
|
|
126
|
+
const controller = new AbortController();
|
|
127
|
+
const timer = setTimeout(() => controller.abort(), Math.max(1, timeoutMs));
|
|
128
|
+
try {
|
|
129
|
+
return await fetchFn(url, {
|
|
130
|
+
...init,
|
|
131
|
+
signal: controller.signal
|
|
132
|
+
});
|
|
133
|
+
} finally {
|
|
134
|
+
clearTimeout(timer);
|
|
135
|
+
}
|
|
136
|
+
}
|
|
137
|
+
|
|
138
|
+
//#endregion
|
|
139
|
+
//#region src/media/fetch.ts
|
|
140
|
+
var MediaFetchError = class extends Error {
|
|
141
|
+
constructor(code, message) {
|
|
142
|
+
super(message);
|
|
143
|
+
this.code = code;
|
|
144
|
+
this.name = "MediaFetchError";
|
|
145
|
+
}
|
|
146
|
+
};
|
|
147
|
+
function stripQuotes(value) {
|
|
148
|
+
return value.replace(/^["']|["']$/g, "");
|
|
149
|
+
}
|
|
150
|
+
function parseContentDispositionFileName(header) {
|
|
151
|
+
if (!header) return;
|
|
152
|
+
const starMatch = /filename\*\s*=\s*([^;]+)/i.exec(header);
|
|
153
|
+
if (starMatch?.[1]) {
|
|
154
|
+
const cleaned = stripQuotes(starMatch[1].trim());
|
|
155
|
+
const encoded = cleaned.split("''").slice(1).join("''") || cleaned;
|
|
156
|
+
try {
|
|
157
|
+
return path.basename(decodeURIComponent(encoded));
|
|
158
|
+
} catch {
|
|
159
|
+
return path.basename(encoded);
|
|
160
|
+
}
|
|
161
|
+
}
|
|
162
|
+
const match = /filename\s*=\s*([^;]+)/i.exec(header);
|
|
163
|
+
if (match?.[1]) return path.basename(stripQuotes(match[1].trim()));
|
|
164
|
+
}
|
|
165
|
+
async function readErrorBodySnippet(res, maxChars = 200) {
|
|
166
|
+
try {
|
|
167
|
+
const text = await res.text();
|
|
168
|
+
if (!text) return;
|
|
169
|
+
const collapsed = text.replace(/\s+/g, " ").trim();
|
|
170
|
+
if (!collapsed) return;
|
|
171
|
+
if (collapsed.length <= maxChars) return collapsed;
|
|
172
|
+
return `${collapsed.slice(0, maxChars)}…`;
|
|
173
|
+
} catch {
|
|
174
|
+
return;
|
|
175
|
+
}
|
|
176
|
+
}
|
|
177
|
+
async function fetchRemoteMedia(options) {
|
|
178
|
+
const { url, fetchImpl, filePathHint, maxBytes, maxRedirects, ssrfPolicy, lookupFn } = options;
|
|
179
|
+
let res;
|
|
180
|
+
let finalUrl = url;
|
|
181
|
+
let release = null;
|
|
182
|
+
try {
|
|
183
|
+
const result = await fetchWithSsrFGuard({
|
|
184
|
+
url,
|
|
185
|
+
fetchImpl,
|
|
186
|
+
maxRedirects,
|
|
187
|
+
policy: ssrfPolicy,
|
|
188
|
+
lookupFn
|
|
189
|
+
});
|
|
190
|
+
res = result.response;
|
|
191
|
+
finalUrl = result.finalUrl;
|
|
192
|
+
release = result.release;
|
|
193
|
+
} catch (err) {
|
|
194
|
+
throw new MediaFetchError("fetch_failed", `Failed to fetch media from ${url}: ${String(err)}`);
|
|
195
|
+
}
|
|
196
|
+
try {
|
|
197
|
+
if (!res.ok) {
|
|
198
|
+
const statusText = res.statusText ? ` ${res.statusText}` : "";
|
|
199
|
+
const redirected = finalUrl !== url ? ` (redirected to ${finalUrl})` : "";
|
|
200
|
+
let detail = `HTTP ${res.status}${statusText}`;
|
|
201
|
+
if (!res.body) detail = `HTTP ${res.status}${statusText}; empty response body`;
|
|
202
|
+
else {
|
|
203
|
+
const snippet = await readErrorBodySnippet(res);
|
|
204
|
+
if (snippet) detail += `; body: ${snippet}`;
|
|
205
|
+
}
|
|
206
|
+
throw new MediaFetchError("http_error", `Failed to fetch media from ${url}${redirected}: ${detail}`);
|
|
207
|
+
}
|
|
208
|
+
const contentLength = res.headers.get("content-length");
|
|
209
|
+
if (maxBytes && contentLength) {
|
|
210
|
+
const length = Number(contentLength);
|
|
211
|
+
if (Number.isFinite(length) && length > maxBytes) throw new MediaFetchError("max_bytes", `Failed to fetch media from ${url}: content length ${length} exceeds maxBytes ${maxBytes}`);
|
|
212
|
+
}
|
|
213
|
+
const buffer = maxBytes ? await readResponseWithLimit(res, maxBytes) : Buffer.from(await res.arrayBuffer());
|
|
214
|
+
let fileNameFromUrl;
|
|
215
|
+
try {
|
|
216
|
+
const parsed = new URL(finalUrl);
|
|
217
|
+
fileNameFromUrl = path.basename(parsed.pathname) || void 0;
|
|
218
|
+
} catch {}
|
|
219
|
+
const headerFileName = parseContentDispositionFileName(res.headers.get("content-disposition"));
|
|
220
|
+
let fileName = headerFileName || fileNameFromUrl || (filePathHint ? path.basename(filePathHint) : void 0);
|
|
221
|
+
const filePathForMime = headerFileName && path.extname(headerFileName) ? headerFileName : filePathHint ?? finalUrl;
|
|
222
|
+
const contentType = await detectMime({
|
|
223
|
+
buffer,
|
|
224
|
+
headerMime: res.headers.get("content-type"),
|
|
225
|
+
filePath: filePathForMime
|
|
226
|
+
});
|
|
227
|
+
if (fileName && !path.extname(fileName) && contentType) {
|
|
228
|
+
const ext = extensionForMime(contentType);
|
|
229
|
+
if (ext) fileName = `${fileName}${ext}`;
|
|
230
|
+
}
|
|
231
|
+
return {
|
|
232
|
+
buffer,
|
|
233
|
+
contentType: contentType ?? void 0,
|
|
234
|
+
fileName
|
|
235
|
+
};
|
|
236
|
+
} finally {
|
|
237
|
+
if (release) await release();
|
|
238
|
+
}
|
|
239
|
+
}
|
|
240
|
+
async function readResponseWithLimit(res, maxBytes) {
|
|
241
|
+
const body = res.body;
|
|
242
|
+
if (!body || typeof body.getReader !== "function") {
|
|
243
|
+
const fallback = Buffer.from(await res.arrayBuffer());
|
|
244
|
+
if (fallback.length > maxBytes) throw new MediaFetchError("max_bytes", `Failed to fetch media from ${res.url || "response"}: payload exceeds maxBytes ${maxBytes}`);
|
|
245
|
+
return fallback;
|
|
246
|
+
}
|
|
247
|
+
const reader = body.getReader();
|
|
248
|
+
const chunks = [];
|
|
249
|
+
let total = 0;
|
|
250
|
+
try {
|
|
251
|
+
while (true) {
|
|
252
|
+
const { done, value } = await reader.read();
|
|
253
|
+
if (done) break;
|
|
254
|
+
if (value?.length) {
|
|
255
|
+
total += value.length;
|
|
256
|
+
if (total > maxBytes) {
|
|
257
|
+
try {
|
|
258
|
+
await reader.cancel();
|
|
259
|
+
} catch {}
|
|
260
|
+
throw new MediaFetchError("max_bytes", `Failed to fetch media from ${res.url || "response"}: payload exceeds maxBytes ${maxBytes}`);
|
|
261
|
+
}
|
|
262
|
+
chunks.push(value);
|
|
263
|
+
}
|
|
264
|
+
}
|
|
265
|
+
} finally {
|
|
266
|
+
try {
|
|
267
|
+
reader.releaseLock();
|
|
268
|
+
} catch {}
|
|
269
|
+
}
|
|
270
|
+
return Buffer.concat(chunks.map((chunk) => Buffer.from(chunk)), total);
|
|
271
|
+
}
|
|
272
|
+
|
|
273
|
+
//#endregion
|
|
274
|
+
export { fetchWithSsrFGuard as i, fetchRemoteMedia as n, fetchWithTimeout as r, MediaFetchError as t };
|
|
@@ -0,0 +1,274 @@
|
|
|
1
|
+
import { c as logWarn } from "./exec-B8lXct-k.js";
|
|
2
|
+
import { Bt as createPinnedDispatcher, Cn as detectMime, Rt as SsrFBlockedError, Vt as resolvePinnedHostnameWithPolicy, wn as extensionForMime, zt as closeDispatcher } from "./pi-embedded-helpers-WDwx99UA.js";
|
|
3
|
+
import path from "node:path";
|
|
4
|
+
|
|
5
|
+
//#region src/infra/net/fetch-guard.ts
|
|
6
|
+
const DEFAULT_MAX_REDIRECTS = 3;
|
|
7
|
+
function isRedirectStatus(status) {
|
|
8
|
+
return status === 301 || status === 302 || status === 303 || status === 307 || status === 308;
|
|
9
|
+
}
|
|
10
|
+
function buildAbortSignal(params) {
|
|
11
|
+
const { timeoutMs, signal } = params;
|
|
12
|
+
if (!timeoutMs && !signal) return {
|
|
13
|
+
signal: void 0,
|
|
14
|
+
cleanup: () => {}
|
|
15
|
+
};
|
|
16
|
+
if (!timeoutMs) return {
|
|
17
|
+
signal,
|
|
18
|
+
cleanup: () => {}
|
|
19
|
+
};
|
|
20
|
+
const controller = new AbortController();
|
|
21
|
+
const timeoutId = setTimeout(() => controller.abort(), timeoutMs);
|
|
22
|
+
const onAbort = () => controller.abort();
|
|
23
|
+
if (signal) if (signal.aborted) controller.abort();
|
|
24
|
+
else signal.addEventListener("abort", onAbort, { once: true });
|
|
25
|
+
const cleanup = () => {
|
|
26
|
+
clearTimeout(timeoutId);
|
|
27
|
+
if (signal) signal.removeEventListener("abort", onAbort);
|
|
28
|
+
};
|
|
29
|
+
return {
|
|
30
|
+
signal: controller.signal,
|
|
31
|
+
cleanup
|
|
32
|
+
};
|
|
33
|
+
}
|
|
34
|
+
async function fetchWithSsrFGuard(params) {
|
|
35
|
+
const fetcher = params.fetchImpl ?? globalThis.fetch;
|
|
36
|
+
if (!fetcher) throw new Error("fetch is not available");
|
|
37
|
+
const maxRedirects = typeof params.maxRedirects === "number" && Number.isFinite(params.maxRedirects) ? Math.max(0, Math.floor(params.maxRedirects)) : DEFAULT_MAX_REDIRECTS;
|
|
38
|
+
const { signal, cleanup } = buildAbortSignal({
|
|
39
|
+
timeoutMs: params.timeoutMs,
|
|
40
|
+
signal: params.signal
|
|
41
|
+
});
|
|
42
|
+
let released = false;
|
|
43
|
+
const release = async (dispatcher) => {
|
|
44
|
+
if (released) return;
|
|
45
|
+
released = true;
|
|
46
|
+
cleanup();
|
|
47
|
+
await closeDispatcher(dispatcher ?? void 0);
|
|
48
|
+
};
|
|
49
|
+
const visited = /* @__PURE__ */ new Set();
|
|
50
|
+
let currentUrl = params.url;
|
|
51
|
+
let redirectCount = 0;
|
|
52
|
+
while (true) {
|
|
53
|
+
let parsedUrl;
|
|
54
|
+
try {
|
|
55
|
+
parsedUrl = new URL(currentUrl);
|
|
56
|
+
} catch {
|
|
57
|
+
await release();
|
|
58
|
+
throw new Error("Invalid URL: must be http or https");
|
|
59
|
+
}
|
|
60
|
+
if (!["http:", "https:"].includes(parsedUrl.protocol)) {
|
|
61
|
+
await release();
|
|
62
|
+
throw new Error("Invalid URL: must be http or https");
|
|
63
|
+
}
|
|
64
|
+
let dispatcher = null;
|
|
65
|
+
try {
|
|
66
|
+
const pinned = await resolvePinnedHostnameWithPolicy(parsedUrl.hostname, {
|
|
67
|
+
lookupFn: params.lookupFn,
|
|
68
|
+
policy: params.policy
|
|
69
|
+
});
|
|
70
|
+
if (params.pinDns !== false) dispatcher = createPinnedDispatcher(pinned);
|
|
71
|
+
const init = {
|
|
72
|
+
...params.init ? { ...params.init } : {},
|
|
73
|
+
redirect: "manual",
|
|
74
|
+
...dispatcher ? { dispatcher } : {},
|
|
75
|
+
...signal ? { signal } : {}
|
|
76
|
+
};
|
|
77
|
+
const response = await fetcher(parsedUrl.toString(), init);
|
|
78
|
+
if (isRedirectStatus(response.status)) {
|
|
79
|
+
const location = response.headers.get("location");
|
|
80
|
+
if (!location) {
|
|
81
|
+
await release(dispatcher);
|
|
82
|
+
throw new Error(`Redirect missing location header (${response.status})`);
|
|
83
|
+
}
|
|
84
|
+
redirectCount += 1;
|
|
85
|
+
if (redirectCount > maxRedirects) {
|
|
86
|
+
await release(dispatcher);
|
|
87
|
+
throw new Error(`Too many redirects (limit: ${maxRedirects})`);
|
|
88
|
+
}
|
|
89
|
+
const nextUrl = new URL(location, parsedUrl).toString();
|
|
90
|
+
if (visited.has(nextUrl)) {
|
|
91
|
+
await release(dispatcher);
|
|
92
|
+
throw new Error("Redirect loop detected");
|
|
93
|
+
}
|
|
94
|
+
visited.add(nextUrl);
|
|
95
|
+
response.body?.cancel();
|
|
96
|
+
await closeDispatcher(dispatcher);
|
|
97
|
+
currentUrl = nextUrl;
|
|
98
|
+
continue;
|
|
99
|
+
}
|
|
100
|
+
return {
|
|
101
|
+
response,
|
|
102
|
+
finalUrl: currentUrl,
|
|
103
|
+
release: async () => release(dispatcher)
|
|
104
|
+
};
|
|
105
|
+
} catch (err) {
|
|
106
|
+
if (err instanceof SsrFBlockedError) logWarn(`security: blocked URL fetch (${params.auditContext ?? "url-fetch"}) target=${parsedUrl.origin}${parsedUrl.pathname} reason=${err.message}`);
|
|
107
|
+
await release(dispatcher);
|
|
108
|
+
throw err;
|
|
109
|
+
}
|
|
110
|
+
}
|
|
111
|
+
}
|
|
112
|
+
|
|
113
|
+
//#endregion
|
|
114
|
+
//#region src/media/fetch.ts
|
|
115
|
+
var MediaFetchError = class extends Error {
|
|
116
|
+
constructor(code, message) {
|
|
117
|
+
super(message);
|
|
118
|
+
this.code = code;
|
|
119
|
+
this.name = "MediaFetchError";
|
|
120
|
+
}
|
|
121
|
+
};
|
|
122
|
+
function stripQuotes(value) {
|
|
123
|
+
return value.replace(/^["']|["']$/g, "");
|
|
124
|
+
}
|
|
125
|
+
function parseContentDispositionFileName(header) {
|
|
126
|
+
if (!header) return;
|
|
127
|
+
const starMatch = /filename\*\s*=\s*([^;]+)/i.exec(header);
|
|
128
|
+
if (starMatch?.[1]) {
|
|
129
|
+
const cleaned = stripQuotes(starMatch[1].trim());
|
|
130
|
+
const encoded = cleaned.split("''").slice(1).join("''") || cleaned;
|
|
131
|
+
try {
|
|
132
|
+
return path.basename(decodeURIComponent(encoded));
|
|
133
|
+
} catch {
|
|
134
|
+
return path.basename(encoded);
|
|
135
|
+
}
|
|
136
|
+
}
|
|
137
|
+
const match = /filename\s*=\s*([^;]+)/i.exec(header);
|
|
138
|
+
if (match?.[1]) return path.basename(stripQuotes(match[1].trim()));
|
|
139
|
+
}
|
|
140
|
+
async function readErrorBodySnippet(res, maxChars = 200) {
|
|
141
|
+
try {
|
|
142
|
+
const text = await res.text();
|
|
143
|
+
if (!text) return;
|
|
144
|
+
const collapsed = text.replace(/\s+/g, " ").trim();
|
|
145
|
+
if (!collapsed) return;
|
|
146
|
+
if (collapsed.length <= maxChars) return collapsed;
|
|
147
|
+
return `${collapsed.slice(0, maxChars)}…`;
|
|
148
|
+
} catch {
|
|
149
|
+
return;
|
|
150
|
+
}
|
|
151
|
+
}
|
|
152
|
+
async function fetchRemoteMedia(options) {
|
|
153
|
+
const { url, fetchImpl, filePathHint, maxBytes, maxRedirects, ssrfPolicy, lookupFn } = options;
|
|
154
|
+
let res;
|
|
155
|
+
let finalUrl = url;
|
|
156
|
+
let release = null;
|
|
157
|
+
try {
|
|
158
|
+
const result = await fetchWithSsrFGuard({
|
|
159
|
+
url,
|
|
160
|
+
fetchImpl,
|
|
161
|
+
maxRedirects,
|
|
162
|
+
policy: ssrfPolicy,
|
|
163
|
+
lookupFn
|
|
164
|
+
});
|
|
165
|
+
res = result.response;
|
|
166
|
+
finalUrl = result.finalUrl;
|
|
167
|
+
release = result.release;
|
|
168
|
+
} catch (err) {
|
|
169
|
+
throw new MediaFetchError("fetch_failed", `Failed to fetch media from ${url}: ${String(err)}`);
|
|
170
|
+
}
|
|
171
|
+
try {
|
|
172
|
+
if (!res.ok) {
|
|
173
|
+
const statusText = res.statusText ? ` ${res.statusText}` : "";
|
|
174
|
+
const redirected = finalUrl !== url ? ` (redirected to ${finalUrl})` : "";
|
|
175
|
+
let detail = `HTTP ${res.status}${statusText}`;
|
|
176
|
+
if (!res.body) detail = `HTTP ${res.status}${statusText}; empty response body`;
|
|
177
|
+
else {
|
|
178
|
+
const snippet = await readErrorBodySnippet(res);
|
|
179
|
+
if (snippet) detail += `; body: ${snippet}`;
|
|
180
|
+
}
|
|
181
|
+
throw new MediaFetchError("http_error", `Failed to fetch media from ${url}${redirected}: ${detail}`);
|
|
182
|
+
}
|
|
183
|
+
const contentLength = res.headers.get("content-length");
|
|
184
|
+
if (maxBytes && contentLength) {
|
|
185
|
+
const length = Number(contentLength);
|
|
186
|
+
if (Number.isFinite(length) && length > maxBytes) throw new MediaFetchError("max_bytes", `Failed to fetch media from ${url}: content length ${length} exceeds maxBytes ${maxBytes}`);
|
|
187
|
+
}
|
|
188
|
+
const buffer = maxBytes ? await readResponseWithLimit(res, maxBytes) : Buffer.from(await res.arrayBuffer());
|
|
189
|
+
let fileNameFromUrl;
|
|
190
|
+
try {
|
|
191
|
+
const parsed = new URL(finalUrl);
|
|
192
|
+
fileNameFromUrl = path.basename(parsed.pathname) || void 0;
|
|
193
|
+
} catch {}
|
|
194
|
+
const headerFileName = parseContentDispositionFileName(res.headers.get("content-disposition"));
|
|
195
|
+
let fileName = headerFileName || fileNameFromUrl || (filePathHint ? path.basename(filePathHint) : void 0);
|
|
196
|
+
const filePathForMime = headerFileName && path.extname(headerFileName) ? headerFileName : filePathHint ?? finalUrl;
|
|
197
|
+
const contentType = await detectMime({
|
|
198
|
+
buffer,
|
|
199
|
+
headerMime: res.headers.get("content-type"),
|
|
200
|
+
filePath: filePathForMime
|
|
201
|
+
});
|
|
202
|
+
if (fileName && !path.extname(fileName) && contentType) {
|
|
203
|
+
const ext = extensionForMime(contentType);
|
|
204
|
+
if (ext) fileName = `${fileName}${ext}`;
|
|
205
|
+
}
|
|
206
|
+
return {
|
|
207
|
+
buffer,
|
|
208
|
+
contentType: contentType ?? void 0,
|
|
209
|
+
fileName
|
|
210
|
+
};
|
|
211
|
+
} finally {
|
|
212
|
+
if (release) await release();
|
|
213
|
+
}
|
|
214
|
+
}
|
|
215
|
+
async function readResponseWithLimit(res, maxBytes) {
|
|
216
|
+
const body = res.body;
|
|
217
|
+
if (!body || typeof body.getReader !== "function") {
|
|
218
|
+
const fallback = Buffer.from(await res.arrayBuffer());
|
|
219
|
+
if (fallback.length > maxBytes) throw new MediaFetchError("max_bytes", `Failed to fetch media from ${res.url || "response"}: payload exceeds maxBytes ${maxBytes}`);
|
|
220
|
+
return fallback;
|
|
221
|
+
}
|
|
222
|
+
const reader = body.getReader();
|
|
223
|
+
const chunks = [];
|
|
224
|
+
let total = 0;
|
|
225
|
+
try {
|
|
226
|
+
while (true) {
|
|
227
|
+
const { done, value } = await reader.read();
|
|
228
|
+
if (done) break;
|
|
229
|
+
if (value?.length) {
|
|
230
|
+
total += value.length;
|
|
231
|
+
if (total > maxBytes) {
|
|
232
|
+
try {
|
|
233
|
+
await reader.cancel();
|
|
234
|
+
} catch {}
|
|
235
|
+
throw new MediaFetchError("max_bytes", `Failed to fetch media from ${res.url || "response"}: payload exceeds maxBytes ${maxBytes}`);
|
|
236
|
+
}
|
|
237
|
+
chunks.push(value);
|
|
238
|
+
}
|
|
239
|
+
}
|
|
240
|
+
} finally {
|
|
241
|
+
try {
|
|
242
|
+
reader.releaseLock();
|
|
243
|
+
} catch {}
|
|
244
|
+
}
|
|
245
|
+
return Buffer.concat(chunks.map((chunk) => Buffer.from(chunk)), total);
|
|
246
|
+
}
|
|
247
|
+
|
|
248
|
+
//#endregion
|
|
249
|
+
//#region src/utils/fetch-timeout.ts
|
|
250
|
+
/**
|
|
251
|
+
* Fetch wrapper that adds timeout support via AbortController.
|
|
252
|
+
*
|
|
253
|
+
* @param url - The URL to fetch
|
|
254
|
+
* @param init - RequestInit options (headers, method, body, etc.)
|
|
255
|
+
* @param timeoutMs - Timeout in milliseconds
|
|
256
|
+
* @param fetchFn - The fetch implementation to use (defaults to global fetch)
|
|
257
|
+
* @returns The fetch Response
|
|
258
|
+
* @throws AbortError if the request times out
|
|
259
|
+
*/
|
|
260
|
+
async function fetchWithTimeout(url, init, timeoutMs, fetchFn = fetch) {
|
|
261
|
+
const controller = new AbortController();
|
|
262
|
+
const timer = setTimeout(() => controller.abort(), Math.max(1, timeoutMs));
|
|
263
|
+
try {
|
|
264
|
+
return await fetchFn(url, {
|
|
265
|
+
...init,
|
|
266
|
+
signal: controller.signal
|
|
267
|
+
});
|
|
268
|
+
} finally {
|
|
269
|
+
clearTimeout(timer);
|
|
270
|
+
}
|
|
271
|
+
}
|
|
272
|
+
|
|
273
|
+
//#endregion
|
|
274
|
+
export { fetchWithSsrFGuard as i, MediaFetchError as n, fetchRemoteMedia as r, fetchWithTimeout as t };
|