@symerian/symi 3.5.3 → 3.5.5
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/dist/{agent-Bl0Wfrd4.js → agent-8EuVoCbs.js} +11 -11
- package/dist/{agent-BsRlH9Ez.js → agent-B87OYNFx.js} +9 -9
- package/dist/{agents-Ch38fapn.js → agents-CNbjbSD0.js} +11 -11
- package/dist/{audit-CcxTZUi-.js → audit-Bk6kay2Z.js} +9 -9
- package/dist/{audit-CojL8qpM.js → audit-CtrXFZb5.js} +9 -9
- package/dist/{auth-choice-CQnJ5pRD.js → auth-choice-BL4lqaJL.js} +8 -8
- package/dist/{auth-choice-O55PGflm.js → auth-choice-CB0rQByJ.js} +8 -8
- package/dist/{auth-choice-options-DfT-D0Cb.js → auth-choice-options-DmXqtnP9.js} +1 -1
- package/dist/{auth-choice-options-osb2GMd4.js → auth-choice-options-od_KpHe8.js} +1 -1
- package/dist/{auth-choice-prompt-6_u7zS1M.js → auth-choice-prompt-BnvC700A.js} +1 -1
- package/dist/{auth-choice-prompt-SCWccuw0.js → auth-choice-prompt-kt2FcieM.js} +1 -1
- package/dist/{auth-token-Dvw-1mFR.js → auth-token-DyhvQgv4.js} +1 -1
- package/dist/{auth-token-t_CY5BPB.js → auth-token-lPWiklDD.js} +1 -1
- package/dist/{banner-TDzek44y.js → banner-D-ssxnQN.js} +1 -1
- package/dist/{bonjour-discovery-BjSUj2V6.js → bonjour-discovery-CyLfNUkJ.js} +1 -1
- package/dist/{bonjour-discovery-FJyieAXp.js → bonjour-discovery-DuObXMh2.js} +1 -1
- package/dist/breakdown-B_Dhhm3K.js +753 -0
- package/dist/breakdown-Cszrv-Lf.js +753 -0
- package/dist/{browser-cli-BXH0KbhG.js → browser-cli-DGjYBquX.js} +9 -9
- package/dist/{browser-cli-UZqxfaV_.js → browser-cli-rZb2WjFF.js} +9 -9
- package/dist/build-info.json +3 -3
- package/dist/bundled/boot-md/handler.js +10 -10
- package/dist/bundled/session-memory/handler.js +9 -9
- package/dist/{call-CKm3T_ar.js → call-DKQC0JT1.js} +1 -1
- package/dist/{call-DrkOiHjS.js → call-ogggp9QZ.js} +1 -1
- package/dist/canvas-host/a2ui/.bundle.hash +1 -1
- package/dist/{channel-options-BEM8ruys.js → channel-options-DLV6zIpW.js} +2 -2
- package/dist/{channel-options-zAbgRuGY.js → channel-options-_DJXj921.js} +2 -2
- package/dist/{channels-cli-cRWPvOQD.js → channels-cli-2OTAQPvZ.js} +54 -53
- package/dist/{channels-cli-DdKnAzW9.js → channels-cli-CUsX2v-1.js} +54 -53
- package/dist/{chrome-BKUACyeO.js → chrome-3jl2ulOE.js} +8 -8
- package/dist/{chrome-zElD4rpN.js → chrome-D1eO2jfe.js} +1 -1
- package/dist/{chrome-rzK8edU7.js → chrome-DJChpTwP.js} +1 -1
- package/dist/{chrome-DPjznJQ-.js → chrome-OTJg3QKn.js} +1 -1
- package/dist/{clack-prompter-CuIw5vQW.js → clack-prompter-_kEnSVz4.js} +4 -4
- package/dist/{clack-prompter-Bc38EIYW.js → clack-prompter-v9MYo-5u.js} +4 -4
- package/dist/{cli--UhNWFtQ.js → cli-D4cMWhob.js} +36 -35
- package/dist/{cli-BJDlZfYi.js → cli-Qq7pr2SX.js} +36 -35
- package/dist/{command-registry-COpZWfkh.js → command-registry-Br9vlIL_.js} +11 -11
- package/dist/{commands-registry-DPZevjMh.js → commands-registry-BuOUfpmg.js} +31 -0
- package/dist/{commands-registry-VfAQOVZO.js → commands-registry-C2Hvwjym.js} +31 -0
- package/dist/{commands-registry-BisT2Fcd.js → commands-registry-CJPBJPlh.js} +31 -0
- package/dist/{commands-registry-DFYDtKr_.js → commands-registry-DG2kGyg5.js} +31 -0
- package/dist/{completion-cli-EltMSZer.js → completion-cli-CKLoZFMQ.js} +3 -3
- package/dist/{completion-cli-DVF5x7Kp.js → completion-cli-P5zBWNnc.js} +1 -1
- package/dist/{config-D7SS4vdk.js → config-B4jkreCN.js} +13 -2
- package/dist/{config-_DaupjQd.js → config-D7TcU4qN.js} +13 -2
- package/dist/{config-cli-kN07V9j6.js → config-cli-CcJOubCt.js} +3 -3
- package/dist/{config-cli-DaPePEIB.js → config-cli-NvqRZAqr.js} +3 -3
- package/dist/{config-guard-SNMCV6sc.js → config-guard-CLfXzB_z.js} +2 -2
- package/dist/{config-guard-CN1qhDyB.js → config-guard-D58THqAB.js} +8 -8
- package/dist/{config-validation-DS5Jr_iO.js → config-validation-DQ-lm2Qx.js} +1 -1
- package/dist/{config-validation-DGWvkKov.js → config-validation-DhsYEtLL.js} +1 -1
- package/dist/{configure-id9imsuH.js → configure-B1RJ6bi3.js} +22 -22
- package/dist/{configure-C9Z4clKW.js → configure-C7BfUqKR.js} +22 -22
- package/dist/{control-service-CJWzOFkK.js → control-service-DOGU9T2P.js} +4 -4
- package/dist/{control-service-DvK2HPC2.js → control-service-DPzhv357.js} +4 -4
- package/dist/cost-cli-C9LvOtGz.js +138 -0
- package/dist/cost-cli-CmfkZsmZ.js +133 -0
- package/dist/{cron-cli-BIIzbF-W.js → cron-cli-DtDqHIZn.js} +7 -7
- package/dist/{cron-cli-BNx0V18_.js → cron-cli-L4iwVTNV.js} +7 -7
- package/dist/{daemon-cli-CGfWQN7c.js → daemon-cli-39fFIU2G.js} +15 -15
- package/dist/{daemon-cli-DCbqVfyu.js → daemon-cli-B5TdtWCQ.js} +15 -15
- package/dist/daemon-cli.js +13 -2
- package/dist/{daemon-runtime-BD_EkuZP.js → daemon-runtime-7YBz5otm.js} +3 -3
- package/dist/{daemon-runtime-CAdn50ea.js → daemon-runtime-DaJ4Tf2a.js} +3 -3
- package/dist/{deliver-6fYMGY7T.js → deliver-0nDhDdKd.js} +2 -2
- package/dist/{deliver-DTRkeYm3.js → deliver-BiWlR84Y.js} +5 -5
- package/dist/{deliver-DB4v0Tyl.js → deliver-C81eqdrP.js} +2 -2
- package/dist/{deliver-Cjyb6h4g.js → deliver-f3cIWxXT.js} +5 -5
- package/dist/{deps-Bt6gnwqB.js → deps-D5me2CAW.js} +1 -1
- package/dist/{devices-cli-CK5iNr60.js → devices-cli-DuVhACtW.js} +4 -4
- package/dist/{devices-cli-Dg4sVTTI.js → devices-cli-Ec6d58OB.js} +4 -4
- package/dist/{diagnostics-Ee2qfR9V.js → diagnostics-BZH08r5U.js} +1 -1
- package/dist/{diagnostics-4PsqURzT.js → diagnostics-CdawaB0U.js} +1 -1
- package/dist/{directory-cli-CIX9qXWA.js → directory-cli-BQrGwwjf.js} +6 -6
- package/dist/{directory-cli-CR-4DW4i.js → directory-cli-FR_KoYon.js} +6 -6
- package/dist/{dns-cli-Cd3EpJKL.js → dns-cli-CH2QMf70.js} +4 -4
- package/dist/{dns-cli-DzE58v7c.js → dns-cli-Cua_RGWw.js} +4 -4
- package/dist/{docs-cli-DD59E5fQ.js → docs-cli-9yu6OeWj.js} +2 -2
- package/dist/{docs-cli-BcqjkjOA.js → docs-cli-DwrSCuWF.js} +2 -2
- package/dist/{doctor-completion-Dw70YhMd.js → doctor-completion-Be3Of_A2.js} +2 -2
- package/dist/{doctor-completion-Dv6aw9I2.js → doctor-completion-Dco2Lmvy.js} +2 -2
- package/dist/{doctor-config-flow-BOfsrB_o.js → doctor-config-flow-CKJlpwtv.js} +5 -5
- package/dist/{doctor-config-flow-dUAjyD2W.js → doctor-config-flow-CcwEh3WQ.js} +5 -5
- package/dist/{enable-avpl_Lwo.js → enable-BI6rQ1Fb.js} +1 -1
- package/dist/{enable-B5wvwTYB.js → enable-xfczksnk.js} +1 -1
- package/dist/entry.js +1 -1
- package/dist/{exec-approvals-cli-Cv9lE0Ov.js → exec-approvals-cli-1K1PMf0f.js} +10 -10
- package/dist/{exec-approvals-cli-CLD1HXqE.js → exec-approvals-cli-N45JsIvc.js} +10 -10
- package/dist/extensionAPI.js +8 -8
- package/dist/{gateway-cli-DF-S-bKo.js → gateway-cli-BQAh5DqM.js} +86 -85
- package/dist/{gateway-cli-C1yf0Kx4.js → gateway-cli-XV8T-ix8.js} +84 -83
- package/dist/{gateway-rpc-CBb3_pT9.js → gateway-rpc-c2_A2rwu.js} +2 -2
- package/dist/{gateway-rpc-DrcgCoEA.js → gateway-rpc-gDrdC_J6.js} +2 -2
- package/dist/{glass-ui-ws-CgTry9OG.js → glass-ui-ws-1FOCi0nn.js} +62 -61
- package/dist/{glass-ui-ws-BZJKBK5D.js → glass-ui-ws-CqGzDNV7.js} +63 -62
- package/dist/{health-B__mwl7J.js → health-B5BrlZ8G.js} +6 -6
- package/dist/{health-BJl_ZtRW.js → health-B7yvi1O9.js} +6 -6
- package/dist/{hooks-cli-B_d8Cv16.js → hooks-cli-BPa-ssdB.js} +42 -41
- package/dist/{hooks-cli-CpDJa8fo.js → hooks-cli-D7iTDry_.js} +42 -41
- package/dist/{hooks-status-CRdYwf7p.js → hooks-status-B5vDwm19.js} +1 -1
- package/dist/{hooks-status-i4MgV8tU.js → hooks-status-CQ33gaVT.js} +2 -2
- package/dist/index.js +47 -46
- package/dist/{inspect-BZEGJ1Wu.js → inspect-C3_zr-N9.js} +2 -2
- package/dist/{inspect-ChCXJY8c.js → inspect-D_lN8pwg.js} +2 -2
- package/dist/{install-safe-path-PVqsVjI9.js → install-safe-path-79R0iPyC.js} +2 -2
- package/dist/{install-safe-path-INk2Z_kc.js → install-safe-path-BBe6qFNr.js} +2 -2
- package/dist/{installs-lGgvyXAJ.js → installs-BVJQl3Tj.js} +3 -3
- package/dist/{installs-b6XWplET.js → installs-Bb1phV9x.js} +3 -3
- package/dist/{lifecycle-core-iiq9e4fE.js → lifecycle-core-DdbL6ELJ.js} +7 -7
- package/dist/{lifecycle-core-SWNKAc8k.js → lifecycle-core-O50xtu5c.js} +7 -7
- package/dist/llm-slug-generator.js +9 -9
- package/dist/{logs-cli-BGjeoamB.js → logs-cli-DvbMaSKU.js} +6 -6
- package/dist/{logs-cli-BEWpB_ac.js → logs-cli-T5v8efuM.js} +6 -6
- package/dist/{manager-rvtFoeFT.js → manager-Bt-1HGg9.js} +1 -1
- package/dist/{manager-DcZUW1bz.js → manager-CC13EPO9.js} +1 -1
- package/dist/{manager-CsxTf96V.js → manager-Ck1YSfr6.js} +1 -1
- package/dist/{manager-xeIkDkmx.js → manager-DghM7T-b.js} +1 -1
- package/dist/{memory-D8JRYEYq.js → memory-CgWOtF4K.js} +4 -4
- package/dist/{memory-cli-DZtv3G9o.js → memory-cli-DGheAg5i.js} +7 -7
- package/dist/{memory-cli-rORHUdUV.js → memory-cli-vN3fGs79.js} +7 -7
- package/dist/{memory-CeB8eMPH.js → memory-d0YI5Lr0.js} +4 -4
- package/dist/{model-catalog-MHTLXFwi.js → model-catalog-CzKsiNZA.js} +2 -2
- package/dist/{model-catalog-DQTmHZK7.js → model-catalog-IWi6-nY9.js} +2 -2
- package/dist/{model-picker-BVNI6Imm.js → model-picker-CS_h9RHv.js} +2 -2
- package/dist/{model-picker-DHLA0BEe.js → model-picker-DN-co6Oy.js} +2 -2
- package/dist/{models-D3haEpaG.js → models-CBw1pGIq.js} +17 -17
- package/dist/{models-cli-DidUOdbx.js → models-cli-BBReZHNq.js} +46 -45
- package/dist/{models-cli-DiyNuQ5w.js → models-cli-Bmh1S3iG.js} +49 -48
- package/dist/{models-config-CRnTzdFs.js → models-config-B5Xxy-c-.js} +1 -1
- package/dist/{models-config-Br7EjqgG.js → models-config-CiR_RUxw.js} +1 -1
- package/dist/{node-cli-Yqf38Nio.js → node-cli-2HDdeLgi.js} +20 -20
- package/dist/{node-cli-DnwByBU2.js → node-cli-CH1yLZuO.js} +20 -20
- package/dist/{node-service-CRSkbk2b.js → node-service-CfHbECCi.js} +2 -2
- package/dist/{node-service-E8k7BOQV.js → node-service-D44noKnR.js} +2 -2
- package/dist/{nodes-cli-BY6HrZlh.js → nodes-cli-ARs9ZPma.js} +9 -9
- package/dist/{nodes-cli-OTk4gEj-.js → nodes-cli-DIm6cMS_.js} +9 -9
- package/dist/{note-Bn5K9itM.js → note-Cltpxj6i.js} +1 -1
- package/dist/{note-DtkOgLxt.js → note-ytwb4wwn.js} +1 -1
- package/dist/{npm-registry-spec-CZCkONwR.js → npm-registry-spec-CONWlhd6.js} +1 -1
- package/dist/{npm-registry-spec-L8BUQ0nu.js → npm-registry-spec-DPqOMFd9.js} +1 -1
- package/dist/{onboard-oIJ6OEGu.js → onboard-Csj4sOF5.js} +18 -18
- package/dist/{onboard-C1PSYsJY.js → onboard-LVUmCZhX.js} +18 -18
- package/dist/{onboard-channels-DvNWHvx3.js → onboard-channels-mrSIlZDB.js} +7 -7
- package/dist/{onboard-channels-BSt89ffO.js → onboard-channels-vDtX0e0w.js} +7 -7
- package/dist/{onboard-custom-y7PsUrmE.js → onboard-custom-BCcuL4Uq.js} +2 -2
- package/dist/{onboard-custom-TvRg0dYq.js → onboard-custom-C-wfNtOM.js} +2 -2
- package/dist/{onboard-helpers-CtpOchu0.js → onboard-helpers-BKfeJ1xj.js} +4 -4
- package/dist/{onboard-helpers-HjgAKoSl.js → onboard-helpers-CCI7SimM.js} +4 -4
- package/dist/{onboard-hooks-BU0EsBMH.js → onboard-hooks-CXRw9BJY.js} +2 -2
- package/dist/{onboard-hooks-Cmy0Qz0F.js → onboard-hooks-DfDF9AU4.js} +2 -2
- package/dist/{onboard-remote-B7bM-1-l.js → onboard-remote-D4R-Yq2Q.js} +3 -3
- package/dist/{onboard-remote-B5kHPh_e.js → onboard-remote-DKXBH_lQ.js} +3 -3
- package/dist/{onboard-skills-BsPcuuer.js → onboard-skills-BPmu8XLA.js} +2 -2
- package/dist/{onboard-skills-V7pX2pkl.js → onboard-skills-jVyIFojF.js} +3 -3
- package/dist/{onboarding-Ce0PyZFq.js → onboarding-D2VmoKU1.js} +16 -16
- package/dist/{onboarding-D4SGY_zG.js → onboarding-DojADc8N.js} +16 -16
- package/dist/{onboarding.finalize-TkbmJzg5.js → onboarding.finalize-Bi1wSEtw.js} +28 -28
- package/dist/{onboarding.finalize-BDPrr9CT.js → onboarding.finalize-C4BwVw6u.js} +26 -26
- package/dist/{onboarding.gateway-config-9dgVRLeb.js → onboarding.gateway-config-B301LxTx.js} +6 -6
- package/dist/{onboarding.gateway-config-DXQhxsQS.js → onboarding.gateway-config-ChCxv8dy.js} +6 -6
- package/dist/{openai-model-default-D_rz8Pew.js → openai-model-default-CKfNKTZD.js} +1 -1
- package/dist/{openai-model-default-BkGyzajy.js → openai-model-default-ChdgeMqX.js} +1 -1
- package/dist/{outbound-send-deps-PNzbuoSX.js → outbound-send-deps-JQjmNLPx.js} +1 -1
- package/dist/{pairing-cli-WQ1MKO2B.js → pairing-cli-D7_UlTsI.js} +3 -3
- package/dist/{pairing-cli-D2zvrKTM.js → pairing-cli-UgiAsygW.js} +3 -3
- package/dist/{path-env-BHRjFlqO.js → path-env-BAyW1s3c.js} +1 -1
- package/dist/{path-env-i-ZjtVbs.js → path-env-C1hgM8gP.js} +1 -1
- package/dist/{pi-embedded-helpers-nFK_hP2q.js → pi-embedded-helpers-BBiyNXkS.js} +1 -1
- package/dist/{pi-embedded-helpers-DVolpQ34.js → pi-embedded-helpers-CDzBxa-P.js} +1 -1
- package/dist/{pi-embedded-BPuUM-gD.js → pi-embedded-zSv7VKNQ.js} +1265 -428
- package/dist/{pi-tools.policy-uHgu_nx0.js → pi-tools.policy-CU8U7--z.js} +2 -2
- package/dist/{pi-tools.policy-CTzYYKRt.js → pi-tools.policy-WaLKhqJQ.js} +2 -2
- package/dist/{plugin-auto-enable-C4b23B35.js → plugin-auto-enable-Bt2sVz8w.js} +2 -2
- package/dist/{plugin-auto-enable-BkhVwtbW.js → plugin-auto-enable-PBDcVF_-.js} +2 -2
- package/dist/{plugin-registry-CxUYRmLh.js → plugin-registry-Dq6OJ45H.js} +2 -2
- package/dist/{plugin-registry-V5jShvbP.js → plugin-registry-L1h7mxjX.js} +2 -2
- package/dist/plugin-sdk/auto-reply/reply/commands-info.d.ts +1 -0
- package/dist/plugin-sdk/auto-reply/status.d.ts +13 -0
- package/dist/plugin-sdk/config/types.models.d.ts +5 -0
- package/dist/plugin-sdk/config/zod-schema.core.d.ts +11 -0
- package/dist/plugin-sdk/config/zod-schema.d.ts +5 -0
- package/dist/plugin-sdk/cost/benchmark.d.ts +36 -0
- package/dist/plugin-sdk/cost/breakdown.d.ts +63 -0
- package/dist/plugin-sdk/cost/gpu-inference.d.ts +52 -0
- package/dist/plugin-sdk/cost/rates.d.ts +32 -0
- package/dist/plugin-sdk/cost/serving-discovery.d.ts +54 -0
- package/dist/plugin-sdk/cost/summary.d.ts +40 -0
- package/dist/plugin-sdk/index.js +19 -8
- package/dist/{plugins-cli-BthQwo7n.js → plugins-cli-BEIKMoVH.js} +43 -42
- package/dist/{plugins-cli-CMAwepRk.js → plugins-cli-C9ehLXaT.js} +43 -42
- package/dist/{program-context-BVEz8AgF.js → program-context-Bh5wzWdC.js} +48 -40
- package/dist/{program-iw_XyVhs.js → program-iTd2Dei7.js} +46 -45
- package/dist/{prompt-select-styled-CF4qV0_M.js → prompt-select-styled-CNFytCD3.js} +32 -32
- package/dist/{prompt-select-styled-D3RAY7pg.js → prompt-select-styled-fXotfbCt.js} +31 -31
- package/dist/{provider-auth-helpers-BTBjOyhO.js → provider-auth-helpers-DBrH-cce.js} +6 -6
- package/dist/{provider-auth-helpers-Dxo0v0UO.js → provider-auth-helpers-Dho1n21x.js} +6 -6
- package/dist/{push-apns-DIIbGT1M.js → push-apns-DYYY9NOE.js} +1 -1
- package/dist/{push-apns-B8Wg3Hqw.js → push-apns-DpyCFRTu.js} +1 -1
- package/dist/{pw-ai-kkF0QaDF.js → pw-ai-DBAtSFTB.js} +2 -2
- package/dist/{pw-ai-BFS9ezWe.js → pw-ai-DOAsQ5NX.js} +2 -2
- package/dist/{pw-ai-_prsAw5O.js → pw-ai-DQZa9DUQ.js} +2 -2
- package/dist/{pw-ai-D2pEVS5n.js → pw-ai-DY_6l11g.js} +2 -2
- package/dist/{qr-cli-CcAzgz_N.js → qr-cli-D2A-IU0Y.js} +1 -1
- package/dist/{qr-cli-KmGkQDBF.js → qr-cli-DHpiebkG.js} +1 -1
- package/dist/{redact-identifier-CXvHJXk9.js → redact-identifier-BOxAUdff.js} +1 -1
- package/dist/{register.agent-8XsVRuWC.js → register.agent-BYpBNbHe.js} +61 -60
- package/dist/{register.agent-D-OIszeY.js → register.agent-DceNHGi_.js} +63 -62
- package/dist/register.configure-09lIIUvq.js +131 -0
- package/dist/register.configure-UUZqL0Ck.js +135 -0
- package/dist/{register.maintenance-CBYqsXkf.js → register.maintenance-CsoEyVyl.js} +63 -62
- package/dist/{register.maintenance-CjM8sJqH.js → register.maintenance-DdX8GZpv.js} +64 -63
- package/dist/{register.message-kSIASKVK.js → register.message-CAM62MaW.js} +41 -40
- package/dist/{register.message-DnljWvZP.js → register.message-RYn7LD6-.js} +40 -39
- package/dist/{register.onboard-Vj1-Ike1.js → register.onboard-CoRtNlNa.js} +28 -28
- package/dist/{register.onboard-eDNn1pdd.js → register.onboard-DhR5o8KO.js} +28 -28
- package/dist/{register.setup-CmhspsS8.js → register.setup-CEjhFwYz.js} +28 -28
- package/dist/{register.setup-DMaoMWRD.js → register.setup-CI_RT1Wa.js} +28 -28
- package/dist/{register.status-health-sessions-CJqCoqAi.js → register.status-health-sessions-8N1xEKl7.js} +35 -35
- package/dist/{register.status-health-sessions-r3F9H8b0.js → register.status-health-sessions-DNlsQ-xt.js} +36 -36
- package/dist/{register.subclis-RqX1a2aL.js → register.subclis-D1qkm3UK.js} +37 -29
- package/dist/{replies-BYF1gbJf.js → replies-0nzkXt6o.js} +1 -1
- package/dist/{replies-B91-OngF.js → replies-C5CBlnFS.js} +1 -1
- package/dist/{replies-DAYTg6Mb.js → replies-D0FYSIJg.js} +1 -1
- package/dist/{replies-UP2sglaR.js → replies-_DV8VSSj.js} +1 -1
- package/dist/{resolve-route-Zww0Y-HJ.js → resolve-route-CnTdHVgw.js} +1 -1
- package/dist/{resolve-route-CmZ7XjmB.js → resolve-route-D0NrCHnr.js} +1 -1
- package/dist/{routes-BfeVDhod.js → routes-CPMVuvoz.js} +3 -3
- package/dist/{routes-y2Ww0pum.js → routes-DIyAmLYR.js} +3 -3
- package/dist/{rpc-DZCrGGH5.js → rpc-B2BLRS45.js} +2 -2
- package/dist/{rpc-RIkh5F9v.js → rpc-gUsL9Mqf.js} +2 -2
- package/dist/{run-main-6pE2fYXT.js → run-main-hKg6FDt6.js} +61 -60
- package/dist/{sandbox-DQdjlC-w.js → sandbox-61-kshSF.js} +5 -5
- package/dist/{sandbox-BjQ6n3zl.js → sandbox-J92UBQK8.js} +5 -5
- package/dist/{sandbox-cli-CTYAHFyM.js → sandbox-cli-D9v0jhBb.js} +8 -8
- package/dist/{sandbox-cli-C0IVf8AS.js → sandbox-cli-DJgF-r8G.js} +8 -8
- package/dist/{security-cli-B8VyQJcl.js → security-cli-CZix5cXq.js} +13 -13
- package/dist/{security-cli-D0oErb9f.js → security-cli-J9J0qvDy.js} +13 -13
- package/dist/{send-Cxu1tl56.js → send-B0jHSNMF.js} +1 -1
- package/dist/{send-Cuk_Rjss.js → send-C75uSv6p.js} +1 -1
- package/dist/{send-BBfSp-8Q.js → send-Dq252-bi.js} +1 -1
- package/dist/{server-context-BFCh7pUb.js → server-context-D-82OTsT.js} +5 -5
- package/dist/{server-context-YlgRz1wC.js → server-context-SbbjNkPL.js} +5 -5
- package/dist/{server-methods-BWCAXrQJ.js → server-methods-CXoipzKe.js} +31 -31
- package/dist/{server-methods-BxsThjMp.js → server-methods-bIWvtXlT.js} +31 -31
- package/dist/{server-node-events-AZFI44cm.js → server-node-events-BD8wnswX.js} +40 -39
- package/dist/{server-node-events-C10Bhdag.js → server-node-events-nQkNuQOx.js} +39 -38
- package/dist/{service-vsb7_8MA.js → service-BF50XyKr.js} +2 -2
- package/dist/{service-BBw78ATM.js → service-Ccv3Zi5_.js} +2 -2
- package/dist/{session-cost-usage-CqLUlh7S.js → session-cost-usage-CJWHHY-C.js} +1 -1
- package/dist/{session-cost-usage-D6Ocwmq1.js → session-cost-usage-D3mgssM_.js} +1 -1
- package/dist/{session-utils-BZnPW904.js → session-utils-Cs1jlD-q.js} +3 -3
- package/dist/{session-utils-BGw_xwXK.js → session-utils-Zpe3t68b.js} +3 -3
- package/dist/{sessions-uS7rV-lI.js → sessions-BSmT7vGX.js} +3 -3
- package/dist/{sessions-DHPf5TzB.js → sessions-Dn6VXn4p.js} +1 -1
- package/dist/{sessions-optZRB57.js → sessions-Dxf5Kjig.js} +1 -1
- package/dist/{shared-CfBMF1VB.js → shared-BJRsBGGr.js} +2 -2
- package/dist/{shared-CVXZtpIq.js → shared-BmjlTHYU.js} +2 -2
- package/dist/{shared-BucaCyaw.js → shared-Ck6cf10x.js} +1 -1
- package/dist/{shared-k1QjV3ys.js → shared-Crfo8y70.js} +1 -1
- package/dist/{skill-commands-CKm7eCw6.js → skill-commands-D0xAWG0l.js} +1 -1
- package/dist/{skill-commands-DAtpPeXi.js → skill-commands-DKkiQJxU.js} +1 -1
- package/dist/{skill-commands-BoMrW3WV.js → skill-commands-JIccKWkf.js} +1 -1
- package/dist/{skill-commands-yPirQFOb.js → skill-commands-KnANH5Qm.js} +1 -1
- package/dist/{skills-cli-CcWFIcOR.js → skills-cli-BZF5mcG5.js} +7 -7
- package/dist/{skills-cli-DcJBgk5R.js → skills-cli-C9F-zLWe.js} +3 -3
- package/dist/{skills-install-CcW780Kq.js → skills-install-QOHQrX6P.js} +4 -4
- package/dist/{skills-install-CbRsCzAG.js → skills-install-X12kifP1.js} +4 -4
- package/dist/{skills-status-CLzaY4r2.js → skills-status-6LVKpabC.js} +1 -1
- package/dist/{ssrf-q6hBiAOi.js → ssrf-BCSnhba8.js} +13 -2
- package/dist/{ssrf-oI58TMOb.js → ssrf-DNhyFMRW.js} +13 -2
- package/dist/{status-BxD8CjLr.js → status-CIZltjd7.js} +2 -2
- package/dist/{status-Cv8N2kIe.js → status-CTDVhXdb.js} +20 -20
- package/dist/{status-CZc22Lqb.js → status-CWzbgPAZ.js} +2 -2
- package/dist/{status-B5sjPQS6.js → status-Dgg3SlRY.js} +20 -20
- package/dist/{status.update-B52bM2Tg.js → status.update-CdTtmVpp.js} +2 -2
- package/dist/{status.update-Bl_ewksT.js → status.update-_3qHPt0O.js} +2 -2
- package/dist/{subagent-registry-BnHgIGX-.js → subagent-registry-DQ_BPb-T.js} +130 -40
- package/dist/{synthesis-DvfrgkQU.js → synthesis-CDd1xqI3.js} +36 -35
- package/dist/{synthesis-CBIT6Vnk.js → synthesis-CSsmBmJc.js} +9 -9
- package/dist/{synthesis-o7Zdrwxz.js → synthesis-DIqhHKjV.js} +36 -35
- package/dist/{synthesis-7UL3pCpj.js → synthesis-XbEFEFK1.js} +8 -8
- package/dist/{system-cli-BAn07VkE.js → system-cli-DB9etQxq.js} +5 -5
- package/dist/{system-cli-BTZ8T0-Z.js → system-cli-szRqg1_v.js} +5 -5
- package/dist/{systemd-DCzA-V_E.js → systemd-Dic80Qni.js} +1 -1
- package/dist/{systemd-Cmn7zMqD.js → systemd-Dtydk5-z.js} +1 -1
- package/dist/{systemd-hints-CvIqgg9d.js → systemd-hints-DmDUq9JT.js} +4 -4
- package/dist/{systemd-hints-BlGehfA3.js → systemd-hints-bP8dBJ78.js} +4 -4
- package/dist/{systemd-linger-BUWYteOW.js → systemd-linger-BBxRNFXz.js} +2 -2
- package/dist/{systemd-linger-Bj4nK9ZB.js → systemd-linger-DjoQVcOq.js} +2 -2
- package/dist/{tui-XLWiN8Hm.js → tui-CEhOf9fk.js} +6 -6
- package/dist/{tui-B6mIUNPO.js → tui-Dp58oYvX.js} +6 -6
- package/dist/{tui-cli-byFYgg3c.js → tui-cli-DFaOwBwg.js} +12 -12
- package/dist/{tui-cli-CTK5_3rU.js → tui-cli-wxh3YpaV.js} +12 -12
- package/dist/{unified-runner-DnikxMFg.js → unified-runner-Bm3r8UOg.js} +130 -40
- package/dist/{unified-runner-BVvvnjXW.js → unified-runner-DN0asRIR.js} +1263 -426
- package/dist/{update-DxY1UB0k.js → update-BDo7wxMf.js} +1 -1
- package/dist/{update-EhDcBqN1.js → update-CcacbR32.js} +1 -1
- package/dist/{update-check-pFwV6W-z.js → update-check-A86nJKtZ.js} +1 -1
- package/dist/{update-check-H0DwvuqN.js → update-check-oEbS0voJ.js} +1 -1
- package/dist/{update-cli-C8IVRiDZ.js → update-cli-CK7nw0t0.js} +74 -73
- package/dist/{update-cli-BAdPKO1o.js → update-cli-kysdsvn3.js} +73 -72
- package/dist/{update-runner-CERd2XdT.js → update-runner-CQMv-ibM.js} +3 -3
- package/dist/{update-runner-7oHPAIND.js → update-runner-DHi359Tb.js} +3 -3
- package/dist/{usage-format-_37Bn-Jb.js → usage-format-DQJz-0qd.js} +0 -1
- package/dist/{usage-format-rxT5cEAf.js → usage-format-DeczTGI-.js} +0 -1
- package/dist/{webhooks-cli-3UJupWMP.js → webhooks-cli-C3g4MxCE.js} +3 -3
- package/dist/{webhooks-cli-BFpGMNrf.js → webhooks-cli-C3uyehJS.js} +3 -3
- package/dist/{with-timeout-Bn-ltLg1.js → with-timeout-B0ZJa7f2.js} +1 -1
- package/dist/{with-timeout-EXM-FP4_.js → with-timeout-GbJ1Yzsh.js} +1 -1
- package/extensions/outlook/src/graph-mail.test.ts +76 -0
- package/extensions/outlook/src/graph-mail.ts +7 -2
- package/package.json +1 -1
- package/dist/register.configure-Bcdw9qlF.js +0 -130
- package/dist/register.configure-KE6Kvt4O.js +0 -134
- /package/dist/{agents.config-BG9fpad0.js → agents.config-Cyc_RegL.js} +0 -0
- /package/dist/{agents.config-CxrFhtC1.js → agents.config-DK6nN-Qh.js} +0 -0
- /package/dist/{argv-oa_KBmv1.js → argv-Bl0th4dq.js} +0 -0
- /package/dist/{auth-choice-legacy-DwMt7oDR.js → auth-choice-legacy-BZWIpO92.js} +0 -0
- /package/dist/{auth-choice-legacy-ZsU_kwPI.js → auth-choice-legacy-iEyARXI2.js} +0 -0
- /package/dist/{bindings-CLS_owm_.js → bindings-BAOPW5eK.js} +0 -0
- /package/dist/{bindings-BpMZcmYL.js → bindings-c7qLJdIA.js} +0 -0
- /package/dist/{brew-B3VMQVQk.js → brew-B4FH-mEH.js} +0 -0
- /package/dist/{brew-BsE_w2tW.js → brew-CI00FKf8.js} +0 -0
- /package/dist/{catalog-CriSxQMH.js → catalog-BaM8d1-T.js} +0 -0
- /package/dist/{catalog-BXxi5-YC.js → catalog-BnLcGVie.js} +0 -0
- /package/dist/{channel-selection-BiYW5XI-.js → channel-selection-BrFl0vVK.js} +0 -0
- /package/dist/{channel-selection-DF4bza2Q.js → channel-selection-DjrS6oiz.js} +0 -0
- /package/dist/{channels-status-issues-DuRF3XF3.js → channels-status-issues-BwbA2OBt.js} +0 -0
- /package/dist/{channels-status-issues-C2AVfv0-.js → channels-status-issues-iWQDGUQe.js} +0 -0
- /package/dist/{cli-utils-tNdOjVQI.js → cli-utils-CbnnSB38.js} +0 -0
- /package/dist/{clipboard-B1jgJ11s.js → clipboard-BSTxQ2tO.js} +0 -0
- /package/dist/{clipboard-Sks8Qw-6.js → clipboard-CHn5r7Kj.js} +0 -0
- /package/dist/{command-options-C2yg82U0.js → command-options-DgcCGXMQ.js} +0 -0
- /package/dist/{command-options-D_KEIae-.js → command-options-Vxb4M7Aj.js} +0 -0
- /package/dist/{consolidate-DPAffHCg.js → consolidate-BSUbtSDt.js} +0 -0
- /package/dist/{consolidate-CF6vEjPe.js → consolidate-DhoiF4n7.js} +0 -0
- /package/dist/{constants-B4wXIPMk.js → constants-BLIhifCJ.js} +0 -0
- /package/dist/{constants-ChnKXZKi.js → constants-BP_JoSwO.js} +0 -0
- /package/dist/{control-ui-assets-CkPR0Fz2.js → control-ui-assets-CnX0W3vy.js} +0 -0
- /package/dist/{control-ui-assets-BVCcPRi3.js → control-ui-assets-DfBRXG5y.js} +0 -0
- /package/dist/{delivery-queue-DqDe6994.js → delivery-queue-CIwn40ej.js} +0 -0
- /package/dist/{delivery-queue-RUd4NhRw.js → delivery-queue-duM0RT18.js} +0 -0
- /package/dist/{dm-policy-shared-DmpXsl2K.js → dm-policy-shared-BUwZ6Ajx.js} +0 -0
- /package/dist/{dm-policy-shared-ZfPtrTeh.js → dm-policy-shared-EuuPwRNE.js} +0 -0
- /package/dist/{entry-status-BqhxPFzK.js → entry-status-D0BSpWt_.js} +0 -0
- /package/dist/{format-BskCnX0I.js → format-BcXs5iuf.js} +0 -0
- /package/dist/{gmail-setup-utils-BlGvgPlF.js → gmail-setup-utils-DJgxyDTX.js} +0 -0
- /package/dist/{gmail-setup-utils-DsRU2ywQ.js → gmail-setup-utils-_TEJA4pL.js} +0 -0
- /package/dist/{health-format-CzrMGubG.js → health-format-Dp4xmTKn.js} +0 -0
- /package/dist/{health-format-C0DWlpEn.js → health-format-Li703vy6.js} +0 -0
- /package/dist/{help-format-DhRyo3Pj.js → help-format-8IYCRvx1.js} +0 -0
- /package/dist/{help-format-BjEVi4c_.js → help-format-BTNd5kFC.js} +0 -0
- /package/dist/{helpers-CcArejFh.js → helpers-BnXDQL2q.js} +0 -0
- /package/dist/{helpers-Dm_utoC3.js → helpers-CoScWBmD.js} +0 -0
- /package/dist/{helpers-DJRLZbrj.js → helpers-DGBa5iKd.js} +0 -0
- /package/dist/{helpers-DUclfUl-.js → helpers-lLtg0Hgi.js} +0 -0
- /package/dist/{ipv4--8f4a_51.js → ipv4-CCdAVmwu.js} +0 -0
- /package/dist/{ipv4-Cy7l-phR.js → ipv4-DFUXU3PT.js} +0 -0
- /package/dist/{links-D6ASL_as.js → links-B9CbwY46.js} +0 -0
- /package/dist/{links-BkFDs4sT.js → links-CQZxjjCO.js} +0 -0
- /package/dist/{logging-4WqMHwAZ.js → logging-BRejMykf.js} +0 -0
- /package/dist/{logging-iIX8duxv.js → logging-BmJ5ky59.js} +0 -0
- /package/dist/{logging-Czh4x_NQ.js → logging-CLWZ3KQI.js} +0 -0
- /package/dist/{model-D50Lt_sm.js → model-BMFj7NXy.js} +0 -0
- /package/dist/{model-param-b-CfiuLqZG.js → model-param-b-C6mMtCJr.js} +0 -0
- /package/dist/{onboard-config-BKb2QQqE.js → onboard-config-B9Iy9-4f.js} +0 -0
- /package/dist/{onboard-config-DZIbmz6s.js → onboard-config-DwsP5yz1.js} +0 -0
- /package/dist/{outbound-send-deps-BR6jeE9h.js → outbound-send-deps-DpyxnI3f.js} +0 -0
- /package/dist/{parse-log-line-CeJ1RDHv.js → parse-log-line-BQPvB6cZ.js} +0 -0
- /package/dist/{parse-log-line-DxFrnzNo.js → parse-log-line-Cg7e_EO6.js} +0 -0
- /package/dist/{parse-port-DdAxyRwV.js → parse-port-CLBKavYE.js} +0 -0
- /package/dist/{parse-port-W56FnCN_.js → parse-port-dzRz6QnZ.js} +0 -0
- /package/dist/{parse-timeout-DKY8YAUj.js → parse-timeout-CuYdP9TL.js} +0 -0
- /package/dist/{path-safety-LPRW6mO-.js → path-safety-ZDtSDPro.js} +0 -0
- /package/dist/{path-safety-grmMl9nR.js → path-safety-cWA8NpOb.js} +0 -0
- /package/dist/{plugins-allowlist-BuJjTWyS.js → plugins-allowlist-C5r7biDp.js} +0 -0
- /package/dist/{plugins-allowlist-BvQZxkGy.js → plugins-allowlist-CD4oIJNk.js} +0 -0
- /package/dist/{ports-CqKpyZSl.js → ports-BE4iY9ho.js} +0 -0
- /package/dist/{ports-BDzMH5Eu.js → ports-C2swmreL.js} +0 -0
- /package/dist/{program-context-C5Y6Svzj.js → program-context-CGKRxOBU.js} +0 -0
- /package/dist/{progress-deSwGz9x.js → progress-BOQ0hkeM.js} +0 -0
- /package/dist/{progress-B3K1UFtC.js → progress-DQTvTiEg.js} +0 -0
- /package/dist/{prompt-style-DeaIm7_1.js → prompt-style-CzRuIYtp.js} +0 -0
- /package/dist/{prompt-style-DS51QPPi.js → prompt-style-pphr4yLK.js} +0 -0
- /package/dist/{prompts-LvxbwPs6.js → prompts-B98rp78m.js} +0 -0
- /package/dist/{prompts-l_pUOv42.js → prompts-CqJkfsHC.js} +0 -0
- /package/dist/{qmd-manager-BbWeOOTD.js → qmd-manager-C6wRtPm_.js} +0 -0
- /package/dist/{qmd-manager-CYKlEJ2U.js → qmd-manager-CYEAMLE7.js} +0 -0
- /package/dist/{runtime-guard-GWXNB3ke.js → runtime-guard-Bgv3O9s4.js} +0 -0
- /package/dist/{runtime-guard-DWXoHW1Q.js → runtime-guard-ofQGcCUc.js} +0 -0
- /package/dist/{runtime-status-BqrK6ivx.js → runtime-status-B-PXkhrX.js} +0 -0
- /package/dist/{runtime-status-D4pjzLyv.js → runtime-status-Zb9OQ0VK.js} +0 -0
- /package/dist/{session-dirs-CXErIzZq.js → session-dirs-BsQ-g02q.js} +0 -0
- /package/dist/{session-dirs-DJ4qiP3r.js → session-dirs-DpiMgw4q.js} +0 -0
- /package/dist/{skill-scanner-zh2dJM3x.js → skill-scanner-D5p8L-xO.js} +0 -0
- /package/dist/{skill-scanner-Ur9nMoo4.js → skill-scanner-EhsZUzzk.js} +0 -0
- /package/dist/{stagger-DkaCfsKB.js → stagger-DQs772BN.js} +0 -0
- /package/dist/{status-Bz_-dDs6.js → status-DtyqId3v.js} +0 -0
- /package/dist/{status-CExNNC5N.js → status-dOhj12u0.js} +0 -0
- /package/dist/{system-run-command-CeR1OLFk.js → system-run-command-2oJPKfVr.js} +0 -0
- /package/dist/{system-run-command-Craglj8T.js → system-run-command-D_OmCQOL.js} +0 -0
- /package/dist/{table-xKEHbVsK.js → table-Dm8jYqmW.js} +0 -0
- /package/dist/{table-jBELNhV1.js → table-Ds5CZCyv.js} +0 -0
- /package/dist/{tool-loop-detection-D3y39HsT.js → tool-loop-detection-2Mxxm8YE.js} +0 -0
- /package/dist/{tool-loop-detection-DljhV89j.js → tool-loop-detection-Bk07vuCX.js} +0 -0
- /package/dist/{widearea-dns-C8Rsixsi.js → widearea-dns-BwIBBqZo.js} +0 -0
- /package/dist/{widearea-dns-BSrnDwJD.js → widearea-dns-DA_m7oeT.js} +0 -0
- /package/dist/{workspace-DKEYzTNc.js → workspace-DD9pYbiv.js} +0 -0
- /package/dist/{workspace-BkWAKK8O.js → workspace-Wkr6wXcS.js} +0 -0
- /package/dist/{wsl-cy5jpbkx.js → wsl-Ci3VOaSK.js} +0 -0
- /package/dist/{wsl-hSA0zCrh.js → wsl-S50RbgL8.js} +0 -0
|
@@ -8,17 +8,17 @@ import { _ as DEFAULT_PROVIDER, a as modelKey, d as resolveModelRefFromString, f
|
|
|
8
8
|
import { i as resolveAckReaction, o as resolveEffectiveMessagesConfig, r as resolveResponsePrefixTemplate, s as resolveHumanDelayConfig, t as createReplyPrefixOptions } from "./reply-prefix-i-FPYcoQ.js";
|
|
9
9
|
import { t as normalizeChatType } from "./chat-type-Acj2OK2p.js";
|
|
10
10
|
import { i as resolveSlackAccount, n as listChannelPlugins, o as resolveSlackAppToken, r as normalizeChannelId$1, s as resolveSlackBotToken, t as getChannelPlugin } from "./plugins-CZ_mYwXq.js";
|
|
11
|
-
import { S as resolveSlackChannelId, _ as resolveSlackWebClientOptions, a as sendMessageSlack, b as buildSlackBlocksFallbackText, c as getDefaultLocalRoots, d as fetchRemoteMedia, f as readResponseWithLimit, g as createSlackWebClient, h as fetchWithTimeout, i as resolveSlackThreadTs, l as loadWebMedia, m as bindAbortRelay, n as deliverReplies, o as renderMarkdownWithMarkers, p as fetchWithSsrFGuard, s as markdownToIRWithMeta, t as createSlackReplyDeliveryPlan, u as MediaFetchError, v as parseSlackBlocksInput, x as parseSlackTarget, y as validateSlackBlocksArray } from "./replies-
|
|
12
|
-
import { $ as loadSessionStore, $t as resolveToolProfilePolicy, A as formatRawAssistantErrorForUi, At as resolveMainSessionKey, B as isRateLimitAssistantError, Bt as saveMediaBuffer, C as downgradeOpenAIReasoningBlocks, Ct as resolveChannelResetConfig, D as classifyFailoverReason, Dt as DEFAULT_RESET_TRIGGERS, E as BILLING_ERROR_USER_MESSAGE, Et as resolveThreadFlag, F as isCompactionFailureError, Ft as createBrowserRouteContext, G as parseImageSizeError, Gt as resolveBrowserControlAuth, H as isTimeoutErrorMessage, Ht as resolveExistingPathsWithinRoot, I as isContextOverflowError, It as registerBrowserRoutes, J as resolveSandboxContext, Jt as collectExplicitAllowlist, K as sanitizeUserFacingText, Kt as applyOwnerOnlyToolPolicy, L as isFailoverAssistantError, Lt as resolveBrowserConfig, M as isAuthAssistantError, Mt as resolveGroupSessionKey, N as isBillingAssistantError, Nt as acquireSessionWriteLock, O as formatAssistantErrorText, Ot as resolveFreshSessionTotalTokens, P as isCloudCodeAssistFormatError, Pt as resolveSessionLockMaxHoldFromTimeout, Q as resolveAndPersistSessionFile, Qt as normalizeToolName$1, R as isFailoverErrorMessage, Rt as resolveProfile, S as extractToolResultId, St as evaluateSessionFreshness, T as isGoogleModelApi, Tt as resolveSessionResetType, U as isTransientHttpError, Ut as getBridgeAuthForPort, V as isRawApiErrorPayload, Vt as DEFAULT_UPLOAD_DIR, W as parseImageDimensionError, Wt as ensureBrowserControlAuth, X as extractDeliveryInfo, Xt as expandToolGroups, Y as resolveSandboxRuntimeStatus, Yt as expandPolicyWithPluginGroups, Z as appendAssistantMessageToSessionTranscript, Zt as mergeAlsoAllowPolicy, _ as sanitizeSessionMessagesImages, _t as INPUT_PROVENANCE_KIND_VALUES, a as normalizeChannelTargetInput, an as resolveBootstrapMaxChars, at as updateSessionStoreEntry, b as resolveImageSanitizationLimits, bt as normalizeInputProvenance, c as parseReplyDirectives, cn as getGlobalHookRunner, ct as deliveryContextFromSession, d as parseInlineDirectives$1, dt as normalizeDeliveryContext, en as stripPluginOnlyAllowlist, et as readSessionUpdatedAt, f as validateAnthropicTurns, ft as normalizeSessionDeliveryFields, g as normalizeTextForComparison, gt as extractToolCallNames, h as isMessagingToolDuplicateNormalized, ht as countToolResults, i as buildTargetResolverSignature, in as ensureSessionHeader, it as updateSessionStore, j as getApiErrorPayloadFingerprint, jt as deriveSessionMetaPatch, k as formatBillingErrorMessage, kt as canonicalizeMainSessionAlias, l as MEDIA_TOKEN_RE, ln as initializeGlobalHookRunner, lt as deliveryContextKey, m as pickFallbackThinkingLevel, mt as capArrayByJsonBytes, nn as matchesAnyGlobPattern, o as normalizeTargetForProvider, on as resolveBootstrapTotalMaxChars, ot as isCacheEnabled, p as validateGeminiTurns, pt as archiveSessionTranscripts, q as ensureSandboxWorkspaceForSession, qt as buildPluginToolGroups, r as normalizeReplyPayloadsForDelivery, rn as buildBootstrapContextFiles, rt as updateLastRoute, s as throwIfAborted, sn as sanitizeGoogleTurnOrdering, st as resolveCacheTtlMs$1, t as deliverOutboundPayloads, tn as compileGlobPatterns, tt as recordSessionMetaFromInbound, u as splitMediaFromOutput, ut as mergeDeliveryContext, v as sanitizeImageBlocks, vt as applyInputProvenanceToUserMessage, w as isAntigravityClaude, wt as resolveSessionResetPolicy, x as extractToolCallsFromAssistant, xt as resolveSessionKey, y as sanitizeToolResultImages, yt as hasInterSessionUserProvenance, z as isLikelyContextOverflowError, zt as getMediaDir } from "./deliver-
|
|
11
|
+
import { S as resolveSlackChannelId, _ as resolveSlackWebClientOptions, a as sendMessageSlack, b as buildSlackBlocksFallbackText, c as getDefaultLocalRoots, d as fetchRemoteMedia, f as readResponseWithLimit, g as createSlackWebClient, h as fetchWithTimeout, i as resolveSlackThreadTs, l as loadWebMedia, m as bindAbortRelay, n as deliverReplies, o as renderMarkdownWithMarkers, p as fetchWithSsrFGuard, s as markdownToIRWithMeta, t as createSlackReplyDeliveryPlan, u as MediaFetchError, v as parseSlackBlocksInput, x as parseSlackTarget, y as validateSlackBlocksArray } from "./replies-0nzkXt6o.js";
|
|
12
|
+
import { $ as loadSessionStore, $t as resolveToolProfilePolicy, A as formatRawAssistantErrorForUi, At as resolveMainSessionKey, B as isRateLimitAssistantError, Bt as saveMediaBuffer, C as downgradeOpenAIReasoningBlocks, Ct as resolveChannelResetConfig, D as classifyFailoverReason, Dt as DEFAULT_RESET_TRIGGERS, E as BILLING_ERROR_USER_MESSAGE, Et as resolveThreadFlag, F as isCompactionFailureError, Ft as createBrowserRouteContext, G as parseImageSizeError, Gt as resolveBrowserControlAuth, H as isTimeoutErrorMessage, Ht as resolveExistingPathsWithinRoot, I as isContextOverflowError, It as registerBrowserRoutes, J as resolveSandboxContext, Jt as collectExplicitAllowlist, K as sanitizeUserFacingText, Kt as applyOwnerOnlyToolPolicy, L as isFailoverAssistantError, Lt as resolveBrowserConfig, M as isAuthAssistantError, Mt as resolveGroupSessionKey, N as isBillingAssistantError, Nt as acquireSessionWriteLock, O as formatAssistantErrorText, Ot as resolveFreshSessionTotalTokens, P as isCloudCodeAssistFormatError, Pt as resolveSessionLockMaxHoldFromTimeout, Q as resolveAndPersistSessionFile, Qt as normalizeToolName$1, R as isFailoverErrorMessage, Rt as resolveProfile, S as extractToolResultId, St as evaluateSessionFreshness, T as isGoogleModelApi, Tt as resolveSessionResetType, U as isTransientHttpError, Ut as getBridgeAuthForPort, V as isRawApiErrorPayload, Vt as DEFAULT_UPLOAD_DIR, W as parseImageDimensionError, Wt as ensureBrowserControlAuth, X as extractDeliveryInfo, Xt as expandToolGroups, Y as resolveSandboxRuntimeStatus, Yt as expandPolicyWithPluginGroups, Z as appendAssistantMessageToSessionTranscript, Zt as mergeAlsoAllowPolicy, _ as sanitizeSessionMessagesImages, _t as INPUT_PROVENANCE_KIND_VALUES, a as normalizeChannelTargetInput, an as resolveBootstrapMaxChars, at as updateSessionStoreEntry, b as resolveImageSanitizationLimits, bt as normalizeInputProvenance, c as parseReplyDirectives, cn as getGlobalHookRunner, ct as deliveryContextFromSession, d as parseInlineDirectives$1, dt as normalizeDeliveryContext, en as stripPluginOnlyAllowlist, et as readSessionUpdatedAt, f as validateAnthropicTurns, ft as normalizeSessionDeliveryFields, g as normalizeTextForComparison, gt as extractToolCallNames, h as isMessagingToolDuplicateNormalized, ht as countToolResults, i as buildTargetResolverSignature, in as ensureSessionHeader, it as updateSessionStore, j as getApiErrorPayloadFingerprint, jt as deriveSessionMetaPatch, k as formatBillingErrorMessage, kt as canonicalizeMainSessionAlias, l as MEDIA_TOKEN_RE, ln as initializeGlobalHookRunner, lt as deliveryContextKey, m as pickFallbackThinkingLevel, mt as capArrayByJsonBytes, nn as matchesAnyGlobPattern, o as normalizeTargetForProvider, on as resolveBootstrapTotalMaxChars, ot as isCacheEnabled, p as validateGeminiTurns, pt as archiveSessionTranscripts, q as ensureSandboxWorkspaceForSession, qt as buildPluginToolGroups, r as normalizeReplyPayloadsForDelivery, rn as buildBootstrapContextFiles, rt as updateLastRoute, s as throwIfAborted, sn as sanitizeGoogleTurnOrdering, st as resolveCacheTtlMs$1, t as deliverOutboundPayloads, tn as compileGlobPatterns, tt as recordSessionMetaFromInbound, u as splitMediaFromOutput, ut as mergeDeliveryContext, v as sanitizeImageBlocks, vt as applyInputProvenanceToUserMessage, w as isAntigravityClaude, wt as resolveSessionResetPolicy, x as extractToolCallsFromAssistant, xt as resolveSessionKey, y as sanitizeToolResultImages, yt as hasInterSessionUserProvenance, z as isLikelyContextOverflowError, zt as getMediaDir } from "./deliver-f3cIWxXT.js";
|
|
13
13
|
import { a as logMessageProcessed, i as logLaneEnqueue, o as logMessageQueued, r as logLaneDequeue, s as logSessionStateChange, t as diag } from "./diagnostic-BdRnGknC.js";
|
|
14
14
|
import { n as getDiagnosticSessionState } from "./diagnostic-session-state-DpxCUzoM.js";
|
|
15
15
|
import { S as GATEWAY_CLIENT_NAMES, _ as listDeliverableMessageChannels, a as chunkText, b as GATEWAY_CLIENT_IDS, c as resolveChunkMode, d as isSafeFenceBreak, f as parseFenceSpans, g as isMarkdownCapableMessageChannel, h as isInternalMessageChannel, i as chunkMarkdownTextWithMode, l as resolveTextChunkLimit, m as isDeliverableMessageChannel, o as chunkTextWithMode, p as INTERNAL_MESSAGE_CHANNEL, r as chunkMarkdownText, t as chunkByNewline, u as findFenceSpanAt, v as normalizeMessageChannel, x as GATEWAY_CLIENT_MODES, y as resolveGatewayMessageChannel } from "./chunk-CAZujdOi.js";
|
|
16
16
|
import { _ as resolveSymiAgentDir, a as markAuthProfileFailure, c as dedupeProfileIds, d as ensureAuthProfileStore, f as resolveAuthStorePathForDisplay, g as normalizeSecretInput, i as isProfileInCooldown, l as listProfilesForProvider, m as resolveAuthProfileDisplayLabel, n as resolveAuthProfileOrder, o as markAuthProfileUsed, p as withFileLock$1, r as getSoonestCooldownExpiry, s as resolveApiKeyForProfile, u as markAuthProfileGood } from "./auth-profiles-Bt3PyWkt.js";
|
|
17
|
-
import { C as unsetConfigValueAtPath, S as setConfigValueAtPath, T as VERSION, _ as resetConfigOverrides, b as getConfigValueAtPath, c as loadConfig, d as writeConfigFile, f as validateConfigObjectWithPlugins, g as getConfigOverrides, h as validateJsonSchemaValue, i as isBlockedHostnameOrIp, l as readConfigFileSnapshot, o as normalizeHostname, p as parseDurationMs, t as SsrFBlockedError, u as resolveConfigSnapshotHash, v as setConfigOverride, w as DEFAULT_SUBAGENT_MAX_SPAWN_DEPTH, x as parseConfigPath, y as unsetConfigOverride } from "./ssrf-
|
|
17
|
+
import { C as unsetConfigValueAtPath, S as setConfigValueAtPath, T as VERSION, _ as resetConfigOverrides, b as getConfigValueAtPath, c as loadConfig, d as writeConfigFile, f as validateConfigObjectWithPlugins, g as getConfigOverrides, h as validateJsonSchemaValue, i as isBlockedHostnameOrIp, l as readConfigFileSnapshot, o as normalizeHostname, p as parseDurationMs, t as SsrFBlockedError, u as resolveConfigSnapshotHash, v as setConfigOverride, w as DEFAULT_SUBAGENT_MAX_SPAWN_DEPTH, x as parseConfigPath, y as unsetConfigOverride } from "./ssrf-BCSnhba8.js";
|
|
18
18
|
import { t as parseBooleanValue } from "./boolean-BW6OTjPi.js";
|
|
19
19
|
import { i as resolveShellEnvFallbackTimeoutMs, n as getShellPathFromLoginShell, s as isTruthyEnvValue } from "./shell-env-DgjeObDZ.js";
|
|
20
20
|
import { c as normalizePluginsConfig, f as isPathInsideWithRealpath, i as safeStatSync, l as resolveEnableState, n as discoverSymiPlugins, p as isDangerousHostEnvVarName, r as isPathInside, s as applyTestPluginDefaults, t as loadPluginManifestRegistry, u as resolveMemorySlotDecision } from "./manifest-registry-CAWGTwb5.js";
|
|
21
|
-
import { C as rawDataToString, O as DEFAULT_AI_SNAPSHOT_MAX_CHARS, T as isSecureWebSocketUrl, x as ensureChromeExtensionRelayServer } from "./chrome-
|
|
21
|
+
import { C as rawDataToString, O as DEFAULT_AI_SNAPSHOT_MAX_CHARS, T as isSecureWebSocketUrl, x as ensureChromeExtensionRelayServer } from "./chrome-3jl2ulOE.js";
|
|
22
22
|
import { n as resolveCliName, t as formatCliCommand } from "./command-format-DPd9RN2g.js";
|
|
23
23
|
import { c as assertSandboxPath, d as resolveSandboxedMediaSource, f as applySkillEnvOverrides, h as parseFrontmatterBlock, i as resolveSkillsPromptForRun, l as resolveSandboxInputPath, n as buildWorkspaceSkillSnapshot, p as applySkillEnvOverridesFromSnapshot, r as loadWorkspaceSkillEntries, s as assertMediaNotDataUrl } from "./skills-DO7WNsVJ.js";
|
|
24
24
|
import { n as redactToolDetail } from "./redact-DSOAcWMe.js";
|
|
@@ -29,12 +29,12 @@ import { n as resolveConversationLabel } from "./conversation-label-DTTqF8gH.js"
|
|
|
29
29
|
import { i as resolveSessionTranscriptPath, n as resolveSessionFilePath, o as resolveSessionTranscriptsDirForAgent, r as resolveSessionFilePathOptions, s as resolveStorePath, t as resolveDefaultSessionStorePath } from "./paths-BsT3BvfH.js";
|
|
30
30
|
import { t as emitSessionTranscriptUpdate } from "./transcript-events-ChU6IQwp.js";
|
|
31
31
|
import { n as saveJsonFile, t as loadJsonFile } from "./json-file-B7D44OOV.js";
|
|
32
|
-
import { a as parseGeminiAuth, c as resolveMemorySearchConfig, d as requireApiKey, f as resolveApiKeyForProvider, h as resolveModelAuthMode, i as resolveOllamaBaseUrl, l as getApiKeyForModel, m as resolveEnvApiKey, n as retryAsync, o as collectProviderApiKeysForExecution, p as resolveAwsSdkEnvVarName, r as probeOllamaEmbeddingModels, s as executeWithApiKeyRotation, u as getCustomProviderApiKey } from "./manager-
|
|
32
|
+
import { a as parseGeminiAuth, c as resolveMemorySearchConfig, d as requireApiKey, f as resolveApiKeyForProvider, h as resolveModelAuthMode, i as resolveOllamaBaseUrl, l as getApiKeyForModel, m as resolveEnvApiKey, n as retryAsync, o as collectProviderApiKeysForExecution, p as resolveAwsSdkEnvVarName, r as probeOllamaEmbeddingModels, s as executeWithApiKeyRotation, u as getCustomProviderApiKey } from "./manager-Bt-1HGg9.js";
|
|
33
33
|
import { r as resolveCopilotApiToken, t as DEFAULT_COPILOT_API_BASE_URL } from "./github-copilot-token-dYUr1mDQ.js";
|
|
34
34
|
import { c as normalizeExtraMemoryPaths, f as runTasksWithConcurrency, s as listMemoryFiles } from "./internal-Ce-sg7EN.js";
|
|
35
35
|
import { n as resolveMarkdownTableMode } from "./markdown-tables-jQzXAsf3.js";
|
|
36
|
-
import { a as shouldHandleTextCommands, c as resolveNativeCommandsEnabled, i as normalizeCommandBody, l as resolveNativeSkillsEnabled, n as listChatCommands, o as isCommandFlagEnabled, r as listChatCommandsForConfig, s as isRestartEnabled } from "./commands-registry-
|
|
37
|
-
import { c as getSkillsSnapshotVersion, d as createAsyncLock, f as readJsonFile$1, i as resolveSkillCommandInvocation, l as pruneExpiredPending, n as listSkillCommandsForAgents, o as getRemoteSkillEligibility, p as writeJsonAtomic, r as listSkillCommandsForWorkspace, s as ensureSkillsWatcher, t as listReservedChatSlashCommandNames, u as resolvePairingPaths } from "./skill-commands-
|
|
36
|
+
import { a as shouldHandleTextCommands, c as resolveNativeCommandsEnabled, i as normalizeCommandBody, l as resolveNativeSkillsEnabled, n as listChatCommands, o as isCommandFlagEnabled, r as listChatCommandsForConfig, s as isRestartEnabled } from "./commands-registry-DG2kGyg5.js";
|
|
37
|
+
import { c as getSkillsSnapshotVersion, d as createAsyncLock, f as readJsonFile$1, i as resolveSkillCommandInvocation, l as pruneExpiredPending, n as listSkillCommandsForAgents, o as getRemoteSkillEligibility, p as writeJsonAtomic, r as listSkillCommandsForWorkspace, s as ensureSkillsWatcher, t as listReservedChatSlashCommandNames, u as resolvePairingPaths } from "./skill-commands-D0xAWG0l.js";
|
|
38
38
|
import { r as normalizeInboundTextNewlines, t as finalizeInboundContext } from "./inbound-context-M0vxsAoa.js";
|
|
39
39
|
import { n as discoverModels, t as discoverAuthStorage } from "./pi-model-discovery-CuZX_Q4t.js";
|
|
40
40
|
import { n as resolveAgentRoute, t as buildAgentSessionKey } from "./resolve-route-0kL4oMLp.js";
|
|
@@ -53,7 +53,7 @@ import { fileURLToPath } from "node:url";
|
|
|
53
53
|
import { CURRENT_SESSION_VERSION, DefaultResourceLoader, SessionManager, SettingsManager, codingTools, createAgentSession, createEditTool, createReadTool, createWriteTool, estimateTokens, generateSummary, readTool } from "@mariozechner/pi-coding-agent";
|
|
54
54
|
import crypto, { X509Certificate, createHash, createHmac, randomBytes, randomUUID } from "node:crypto";
|
|
55
55
|
import AjvPkg from "ajv";
|
|
56
|
-
import { WebSocket } from "ws";
|
|
56
|
+
import { WebSocket as WebSocket$1 } from "ws";
|
|
57
57
|
import { Buffer as Buffer$1 } from "node:buffer";
|
|
58
58
|
import { complete, createAssistantMessageEventStream, streamSimple } from "@mariozechner/pi-ai";
|
|
59
59
|
import { BedrockClient, ListFoundationModelsCommand } from "@aws-sdk/client-bedrock";
|
|
@@ -3390,7 +3390,7 @@ async function getMemorySearchManager(params) {
|
|
|
3390
3390
|
const wrapper = new FallbackMemoryManager({
|
|
3391
3391
|
primary,
|
|
3392
3392
|
fallbackFactory: async () => {
|
|
3393
|
-
const { MemoryIndexManager } = await import("./manager-
|
|
3393
|
+
const { MemoryIndexManager } = await import("./manager-Bt-1HGg9.js").then((n) => n.t);
|
|
3394
3394
|
return await MemoryIndexManager.get(params);
|
|
3395
3395
|
}
|
|
3396
3396
|
}, () => QMD_MANAGER_CACHE.delete(cacheKey));
|
|
@@ -3403,7 +3403,7 @@ async function getMemorySearchManager(params) {
|
|
|
3403
3403
|
}
|
|
3404
3404
|
}
|
|
3405
3405
|
try {
|
|
3406
|
-
const { MemoryIndexManager } = await import("./manager-
|
|
3406
|
+
const { MemoryIndexManager } = await import("./manager-Bt-1HGg9.js").then((n) => n.t);
|
|
3407
3407
|
return { manager: await MemoryIndexManager.get(params) };
|
|
3408
3408
|
} catch (err) {
|
|
3409
3409
|
return {
|
|
@@ -5920,7 +5920,7 @@ var GatewayClient = class {
|
|
|
5920
5920
|
if (fingerprint !== expected) return /* @__PURE__ */ new Error("gateway tls fingerprint mismatch");
|
|
5921
5921
|
});
|
|
5922
5922
|
}
|
|
5923
|
-
this.ws = new WebSocket(url, wsOptions);
|
|
5923
|
+
this.ws = new WebSocket$1(url, wsOptions);
|
|
5924
5924
|
this.ws.on("open", () => {
|
|
5925
5925
|
if (url.startsWith("wss://") && this.opts.tlsFingerprint) {
|
|
5926
5926
|
const tlsError = this.validateTlsFingerprint();
|
|
@@ -6139,7 +6139,7 @@ var GatewayClient = class {
|
|
|
6139
6139
|
return null;
|
|
6140
6140
|
}
|
|
6141
6141
|
async request(method, params, opts) {
|
|
6142
|
-
if (!this.ws || this.ws.readyState !== WebSocket.OPEN) throw new Error("gateway not connected");
|
|
6142
|
+
if (!this.ws || this.ws.readyState !== WebSocket$1.OPEN) throw new Error("gateway not connected");
|
|
6143
6143
|
const id = randomUUID();
|
|
6144
6144
|
const frame = {
|
|
6145
6145
|
type: "req",
|
|
@@ -7087,7 +7087,7 @@ async function routeReply(params) {
|
|
|
7087
7087
|
const resolvedReplyToId = replyToId ?? (channelId === "slack" && threadId != null && threadId !== "" ? String(threadId) : void 0);
|
|
7088
7088
|
const resolvedThreadId = channelId === "slack" ? null : threadId ?? null;
|
|
7089
7089
|
try {
|
|
7090
|
-
const { deliverOutboundPayloads } = await import("./deliver-
|
|
7090
|
+
const { deliverOutboundPayloads } = await import("./deliver-f3cIWxXT.js").then((n) => n.n);
|
|
7091
7091
|
return {
|
|
7092
7092
|
ok: true,
|
|
7093
7093
|
messageId: (await deliverOutboundPayloads({
|
|
@@ -24404,7 +24404,6 @@ function formatTokenCount$1(value) {
|
|
|
24404
24404
|
function formatUsd(value) {
|
|
24405
24405
|
if (value === void 0 || !Number.isFinite(value)) return;
|
|
24406
24406
|
if (value >= 1) return `$${value.toFixed(2)}`;
|
|
24407
|
-
if (value >= .01) return `$${value.toFixed(2)}`;
|
|
24408
24407
|
return `$${value.toFixed(4)}`;
|
|
24409
24408
|
}
|
|
24410
24409
|
function resolveModelCostConfig(params) {
|
|
@@ -24479,13 +24478,13 @@ function resolveRuntimeLabel(args) {
|
|
|
24479
24478
|
return sessionKey !== resolveMainSessionKey({ session: { scope: args.sessionScope ?? "per-sender" } }).trim();
|
|
24480
24479
|
})() ? "docker" : sessionKey ? "direct" : "unknown"}/${sandboxMode}`;
|
|
24481
24480
|
}
|
|
24482
|
-
const formatTokens = (total, contextTokens) => {
|
|
24481
|
+
const formatTokens$1 = (total, contextTokens) => {
|
|
24483
24482
|
const ctx = contextTokens ?? null;
|
|
24484
24483
|
if (total == null) return `?/${ctx ? formatTokenCount(ctx) : "?"}`;
|
|
24485
24484
|
const pct = ctx ? Math.min(999, Math.round(total / ctx * 100)) : null;
|
|
24486
24485
|
return `${formatTokenCount(total)}/${ctx ? formatTokenCount(ctx) : "?"}${pct !== null ? ` (${pct}%)` : ""}`;
|
|
24487
24486
|
};
|
|
24488
|
-
const formatContextUsageShort = (total, contextTokens) => `Context ${formatTokens(total, contextTokens ?? null)}`;
|
|
24487
|
+
const formatContextUsageShort = (total, contextTokens) => `Context ${formatTokens$1(total, contextTokens ?? null)}`;
|
|
24489
24488
|
const formatQueueDetails = (queue) => {
|
|
24490
24489
|
if (!queue) return "";
|
|
24491
24490
|
const depth = typeof queue.depth === "number" ? `depth ${queue.depth}` : null;
|
|
@@ -24637,7 +24636,7 @@ function buildStatusMessage(args) {
|
|
|
24637
24636
|
const updatedAt = entry?.updatedAt;
|
|
24638
24637
|
const sessionLine = [`Session: ${args.sessionKey ?? "unknown"}`, typeof updatedAt === "number" ? `updated ${formatTimeAgo(now - updatedAt)}` : "no activity"].filter(Boolean).join(" • ");
|
|
24639
24638
|
const groupActivationValue = entry?.chatType === "group" || entry?.chatType === "channel" || Boolean(args.sessionKey?.includes(":group:")) || Boolean(args.sessionKey?.includes(":channel:")) ? args.groupActivation ?? entry?.groupActivation ?? "mention" : void 0;
|
|
24640
|
-
const contextLine = [`Context: ${formatTokens(totalTokens, contextTokens ?? null)}`, `🧹 Compactions: ${entry?.compactionCount ?? 0}`].filter(Boolean).join(" · ");
|
|
24639
|
+
const contextLine = [`Context: ${formatTokens$1(totalTokens, contextTokens ?? null)}`, `🧹 Compactions: ${entry?.compactionCount ?? 0}`].filter(Boolean).join(" · ");
|
|
24641
24640
|
const queueMode = args.queue?.mode ?? "unknown";
|
|
24642
24641
|
const queueDetails = formatQueueDetails(args.queue);
|
|
24643
24642
|
const verboseLabel = verboseLevel === "full" ? "verbose:full" : verboseLevel === "on" ? "verbose" : null;
|
|
@@ -24669,14 +24668,19 @@ function buildStatusMessage(args) {
|
|
|
24669
24668
|
config: args.config
|
|
24670
24669
|
}) : void 0;
|
|
24671
24670
|
const hasUsage = typeof inputTokens === "number" || typeof outputTokens === "number";
|
|
24672
|
-
const
|
|
24671
|
+
const rawCost = showCost && hasUsage ? estimateUsageCost({
|
|
24673
24672
|
usage: {
|
|
24674
24673
|
input: inputTokens ?? void 0,
|
|
24675
24674
|
output: outputTokens ?? void 0
|
|
24676
24675
|
},
|
|
24677
24676
|
cost: costConfig
|
|
24678
24677
|
}) : void 0;
|
|
24679
|
-
const
|
|
24678
|
+
const useOverride = showCost && hasUsage && typeof args.costOverrideUsd === "number" && (rawCost === void 0 || rawCost === 0);
|
|
24679
|
+
const cost = useOverride ? args.costOverrideUsd : rawCost;
|
|
24680
|
+
const baseLabel = showCost && hasUsage ? formatUsd(cost) : void 0;
|
|
24681
|
+
const tag = useOverride ? " (self-hosted)" : "";
|
|
24682
|
+
const suffix = args.costLineSuffix ? ` · ${args.costLineSuffix}` : "";
|
|
24683
|
+
const costLabel = baseLabel ? `${baseLabel}${tag}${suffix}` : void 0;
|
|
24680
24684
|
const selectedAuthLabel = selectedAuthLabelValue ? ` · 🔑 ${selectedAuthLabelValue}` : "";
|
|
24681
24685
|
const channelModelNote = (() => {
|
|
24682
24686
|
if (!args.config || !entry) return;
|
|
@@ -24721,6 +24725,8 @@ function buildStatusMessage(args) {
|
|
|
24721
24725
|
fallbackLine,
|
|
24722
24726
|
usageCostLine,
|
|
24723
24727
|
cacheLine,
|
|
24728
|
+
args.engineLine,
|
|
24729
|
+
args.hardwareLine,
|
|
24724
24730
|
`📚 ${contextLine}`,
|
|
24725
24731
|
mediaLine,
|
|
24726
24732
|
args.usageLine,
|
|
@@ -25297,6 +25303,606 @@ const handleDebugCommand = async (params, allowTextCommands) => {
|
|
|
25297
25303
|
return null;
|
|
25298
25304
|
};
|
|
25299
25305
|
|
|
25306
|
+
//#endregion
|
|
25307
|
+
//#region src/infra/session-cost-usage.ts
|
|
25308
|
+
const emptyTotals = () => ({
|
|
25309
|
+
input: 0,
|
|
25310
|
+
output: 0,
|
|
25311
|
+
cacheRead: 0,
|
|
25312
|
+
cacheWrite: 0,
|
|
25313
|
+
totalTokens: 0,
|
|
25314
|
+
totalCost: 0,
|
|
25315
|
+
inputCost: 0,
|
|
25316
|
+
outputCost: 0,
|
|
25317
|
+
cacheReadCost: 0,
|
|
25318
|
+
cacheWriteCost: 0,
|
|
25319
|
+
missingCostEntries: 0
|
|
25320
|
+
});
|
|
25321
|
+
const toFiniteNumber = (value) => {
|
|
25322
|
+
if (typeof value !== "number") return;
|
|
25323
|
+
if (!Number.isFinite(value)) return;
|
|
25324
|
+
return value;
|
|
25325
|
+
};
|
|
25326
|
+
const extractCostBreakdown = (usageRaw) => {
|
|
25327
|
+
if (!usageRaw || typeof usageRaw !== "object") return;
|
|
25328
|
+
const cost = usageRaw.cost;
|
|
25329
|
+
if (!cost) return;
|
|
25330
|
+
const total = toFiniteNumber(cost.total);
|
|
25331
|
+
if (total === void 0 || total < 0) return;
|
|
25332
|
+
return {
|
|
25333
|
+
total,
|
|
25334
|
+
input: toFiniteNumber(cost.input),
|
|
25335
|
+
output: toFiniteNumber(cost.output),
|
|
25336
|
+
cacheRead: toFiniteNumber(cost.cacheRead),
|
|
25337
|
+
cacheWrite: toFiniteNumber(cost.cacheWrite)
|
|
25338
|
+
};
|
|
25339
|
+
};
|
|
25340
|
+
const parseTimestamp = (entry) => {
|
|
25341
|
+
const raw = entry.timestamp;
|
|
25342
|
+
if (typeof raw === "string") {
|
|
25343
|
+
const parsed = new Date(raw);
|
|
25344
|
+
if (!Number.isNaN(parsed.valueOf())) return parsed;
|
|
25345
|
+
}
|
|
25346
|
+
const message = entry.message;
|
|
25347
|
+
const messageTimestamp = toFiniteNumber(message?.timestamp);
|
|
25348
|
+
if (messageTimestamp !== void 0) {
|
|
25349
|
+
const parsed = new Date(messageTimestamp);
|
|
25350
|
+
if (!Number.isNaN(parsed.valueOf())) return parsed;
|
|
25351
|
+
}
|
|
25352
|
+
};
|
|
25353
|
+
const parseTranscriptEntry = (entry) => {
|
|
25354
|
+
const message = entry.message;
|
|
25355
|
+
if (!message || typeof message !== "object") return null;
|
|
25356
|
+
const roleRaw = message.role;
|
|
25357
|
+
const role = roleRaw === "user" || roleRaw === "assistant" ? roleRaw : void 0;
|
|
25358
|
+
if (!role) return null;
|
|
25359
|
+
const usageRaw = message.usage ?? entry.usage;
|
|
25360
|
+
const usage = usageRaw ? normalizeUsage(usageRaw) ?? void 0 : void 0;
|
|
25361
|
+
const provider = (typeof message.provider === "string" ? message.provider : void 0) ?? (typeof entry.provider === "string" ? entry.provider : void 0);
|
|
25362
|
+
const model = (typeof message.model === "string" ? message.model : void 0) ?? (typeof entry.model === "string" ? entry.model : void 0);
|
|
25363
|
+
const costBreakdown = extractCostBreakdown(usageRaw);
|
|
25364
|
+
const stopReason = typeof message.stopReason === "string" ? message.stopReason : void 0;
|
|
25365
|
+
const durationMs = toFiniteNumber(message.durationMs ?? entry.durationMs);
|
|
25366
|
+
return {
|
|
25367
|
+
message,
|
|
25368
|
+
role,
|
|
25369
|
+
timestamp: parseTimestamp(entry),
|
|
25370
|
+
durationMs,
|
|
25371
|
+
usage,
|
|
25372
|
+
costTotal: costBreakdown?.total,
|
|
25373
|
+
costBreakdown,
|
|
25374
|
+
provider,
|
|
25375
|
+
model,
|
|
25376
|
+
stopReason,
|
|
25377
|
+
toolNames: extractToolCallNames(message),
|
|
25378
|
+
toolResultCounts: countToolResults(message)
|
|
25379
|
+
};
|
|
25380
|
+
};
|
|
25381
|
+
const formatDayKey = (date) => date.toLocaleDateString("en-CA", { timeZone: Intl.DateTimeFormat().resolvedOptions().timeZone });
|
|
25382
|
+
const computeLatencyStats = (values) => {
|
|
25383
|
+
if (!values.length) return;
|
|
25384
|
+
const sorted = values.toSorted((a, b) => a - b);
|
|
25385
|
+
const total = sorted.reduce((sum, v) => sum + v, 0);
|
|
25386
|
+
const count = sorted.length;
|
|
25387
|
+
const p95Index = Math.max(0, Math.ceil(count * .95) - 1);
|
|
25388
|
+
return {
|
|
25389
|
+
count,
|
|
25390
|
+
avgMs: total / count,
|
|
25391
|
+
p95Ms: sorted[p95Index] ?? sorted[count - 1],
|
|
25392
|
+
minMs: sorted[0],
|
|
25393
|
+
maxMs: sorted[count - 1]
|
|
25394
|
+
};
|
|
25395
|
+
};
|
|
25396
|
+
const applyUsageTotals = (totals, usage) => {
|
|
25397
|
+
totals.input += usage.input ?? 0;
|
|
25398
|
+
totals.output += usage.output ?? 0;
|
|
25399
|
+
totals.cacheRead += usage.cacheRead ?? 0;
|
|
25400
|
+
totals.cacheWrite += usage.cacheWrite ?? 0;
|
|
25401
|
+
const totalTokens = usage.total ?? (usage.input ?? 0) + (usage.output ?? 0) + (usage.cacheRead ?? 0) + (usage.cacheWrite ?? 0);
|
|
25402
|
+
totals.totalTokens += totalTokens;
|
|
25403
|
+
};
|
|
25404
|
+
const applyCostBreakdown = (totals, costBreakdown) => {
|
|
25405
|
+
if (costBreakdown === void 0 || costBreakdown.total === void 0) return;
|
|
25406
|
+
totals.totalCost += costBreakdown.total;
|
|
25407
|
+
totals.inputCost += costBreakdown.input ?? 0;
|
|
25408
|
+
totals.outputCost += costBreakdown.output ?? 0;
|
|
25409
|
+
totals.cacheReadCost += costBreakdown.cacheRead ?? 0;
|
|
25410
|
+
totals.cacheWriteCost += costBreakdown.cacheWrite ?? 0;
|
|
25411
|
+
};
|
|
25412
|
+
const applyCostTotal = (totals, costTotal) => {
|
|
25413
|
+
if (costTotal === void 0) {
|
|
25414
|
+
totals.missingCostEntries += 1;
|
|
25415
|
+
return;
|
|
25416
|
+
}
|
|
25417
|
+
totals.totalCost += costTotal;
|
|
25418
|
+
};
|
|
25419
|
+
async function* readJsonlRecords(filePath) {
|
|
25420
|
+
const fileStream = fs.createReadStream(filePath, { encoding: "utf-8" });
|
|
25421
|
+
const rl = readline.createInterface({
|
|
25422
|
+
input: fileStream,
|
|
25423
|
+
crlfDelay: Infinity
|
|
25424
|
+
});
|
|
25425
|
+
try {
|
|
25426
|
+
for await (const line of rl) {
|
|
25427
|
+
const trimmed = line.trim();
|
|
25428
|
+
if (!trimmed) continue;
|
|
25429
|
+
try {
|
|
25430
|
+
const parsed = JSON.parse(trimmed);
|
|
25431
|
+
if (!parsed || typeof parsed !== "object") continue;
|
|
25432
|
+
yield parsed;
|
|
25433
|
+
} catch {}
|
|
25434
|
+
}
|
|
25435
|
+
} finally {
|
|
25436
|
+
rl.close();
|
|
25437
|
+
fileStream.destroy();
|
|
25438
|
+
}
|
|
25439
|
+
}
|
|
25440
|
+
async function scanTranscriptFile(params) {
|
|
25441
|
+
for await (const parsed of readJsonlRecords(params.filePath)) {
|
|
25442
|
+
const entry = parseTranscriptEntry(parsed);
|
|
25443
|
+
if (!entry) continue;
|
|
25444
|
+
if (entry.usage && entry.costTotal === void 0) {
|
|
25445
|
+
const cost = resolveModelCostConfig({
|
|
25446
|
+
provider: entry.provider,
|
|
25447
|
+
model: entry.model,
|
|
25448
|
+
config: params.config
|
|
25449
|
+
});
|
|
25450
|
+
entry.costTotal = estimateUsageCost({
|
|
25451
|
+
usage: entry.usage,
|
|
25452
|
+
cost
|
|
25453
|
+
});
|
|
25454
|
+
}
|
|
25455
|
+
params.onEntry(entry);
|
|
25456
|
+
}
|
|
25457
|
+
}
|
|
25458
|
+
async function scanUsageFile(params) {
|
|
25459
|
+
await scanTranscriptFile({
|
|
25460
|
+
filePath: params.filePath,
|
|
25461
|
+
config: params.config,
|
|
25462
|
+
onEntry: (entry) => {
|
|
25463
|
+
if (!entry.usage) return;
|
|
25464
|
+
params.onEntry({
|
|
25465
|
+
usage: entry.usage,
|
|
25466
|
+
costTotal: entry.costTotal,
|
|
25467
|
+
costBreakdown: entry.costBreakdown,
|
|
25468
|
+
provider: entry.provider,
|
|
25469
|
+
model: entry.model,
|
|
25470
|
+
timestamp: entry.timestamp
|
|
25471
|
+
});
|
|
25472
|
+
}
|
|
25473
|
+
});
|
|
25474
|
+
}
|
|
25475
|
+
async function loadCostUsageSummary(params) {
|
|
25476
|
+
const now = /* @__PURE__ */ new Date();
|
|
25477
|
+
let sinceTime;
|
|
25478
|
+
let untilTime;
|
|
25479
|
+
if (params?.startMs !== void 0 && params?.endMs !== void 0) {
|
|
25480
|
+
sinceTime = params.startMs;
|
|
25481
|
+
untilTime = params.endMs;
|
|
25482
|
+
} else {
|
|
25483
|
+
const days = Math.max(1, Math.floor(params?.days ?? 30));
|
|
25484
|
+
const since = new Date(now);
|
|
25485
|
+
since.setDate(since.getDate() - (days - 1));
|
|
25486
|
+
sinceTime = since.getTime();
|
|
25487
|
+
untilTime = now.getTime();
|
|
25488
|
+
}
|
|
25489
|
+
const dailyMap = /* @__PURE__ */ new Map();
|
|
25490
|
+
const totals = emptyTotals();
|
|
25491
|
+
const sessionsDir = resolveSessionTranscriptsDirForAgent(params?.agentId);
|
|
25492
|
+
const entries = await fs.promises.readdir(sessionsDir, { withFileTypes: true }).catch(() => []);
|
|
25493
|
+
const files = (await Promise.all(entries.filter((entry) => entry.isFile() && entry.name.endsWith(".jsonl")).map(async (entry) => {
|
|
25494
|
+
const filePath = path.join(sessionsDir, entry.name);
|
|
25495
|
+
const stats = await fs.promises.stat(filePath).catch(() => null);
|
|
25496
|
+
if (!stats) return null;
|
|
25497
|
+
if (stats.mtimeMs < sinceTime) return null;
|
|
25498
|
+
return filePath;
|
|
25499
|
+
}))).filter((filePath) => Boolean(filePath));
|
|
25500
|
+
for (const filePath of files) await scanUsageFile({
|
|
25501
|
+
filePath,
|
|
25502
|
+
config: params?.config,
|
|
25503
|
+
onEntry: (entry) => {
|
|
25504
|
+
const ts = entry.timestamp?.getTime();
|
|
25505
|
+
if (!ts || ts < sinceTime || ts > untilTime) return;
|
|
25506
|
+
const dayKey = formatDayKey(entry.timestamp ?? now);
|
|
25507
|
+
const bucket = dailyMap.get(dayKey) ?? emptyTotals();
|
|
25508
|
+
applyUsageTotals(bucket, entry.usage);
|
|
25509
|
+
if (entry.costBreakdown?.total !== void 0) applyCostBreakdown(bucket, entry.costBreakdown);
|
|
25510
|
+
else applyCostTotal(bucket, entry.costTotal);
|
|
25511
|
+
dailyMap.set(dayKey, bucket);
|
|
25512
|
+
applyUsageTotals(totals, entry.usage);
|
|
25513
|
+
if (entry.costBreakdown?.total !== void 0) applyCostBreakdown(totals, entry.costBreakdown);
|
|
25514
|
+
else applyCostTotal(totals, entry.costTotal);
|
|
25515
|
+
}
|
|
25516
|
+
});
|
|
25517
|
+
const daily = Array.from(dailyMap.entries()).map(([date, bucket]) => Object.assign({ date }, bucket)).toSorted((a, b) => a.date.localeCompare(b.date));
|
|
25518
|
+
const days = Math.ceil((untilTime - sinceTime) / (1440 * 60 * 1e3)) + 1;
|
|
25519
|
+
return {
|
|
25520
|
+
updatedAt: Date.now(),
|
|
25521
|
+
days,
|
|
25522
|
+
daily,
|
|
25523
|
+
totals
|
|
25524
|
+
};
|
|
25525
|
+
}
|
|
25526
|
+
async function loadSessionCostSummary(params) {
|
|
25527
|
+
const sessionFile = params.sessionFile ?? (params.sessionId ? resolveSessionFilePath(params.sessionId, params.sessionEntry, { agentId: params.agentId }) : void 0);
|
|
25528
|
+
if (!sessionFile || !fs.existsSync(sessionFile)) return null;
|
|
25529
|
+
const totals = emptyTotals();
|
|
25530
|
+
let firstActivity;
|
|
25531
|
+
let lastActivity;
|
|
25532
|
+
const activityDatesSet = /* @__PURE__ */ new Set();
|
|
25533
|
+
const dailyMap = /* @__PURE__ */ new Map();
|
|
25534
|
+
const dailyMessageMap = /* @__PURE__ */ new Map();
|
|
25535
|
+
const dailyLatencyMap = /* @__PURE__ */ new Map();
|
|
25536
|
+
const dailyModelUsageMap = /* @__PURE__ */ new Map();
|
|
25537
|
+
const messageCounts = {
|
|
25538
|
+
total: 0,
|
|
25539
|
+
user: 0,
|
|
25540
|
+
assistant: 0,
|
|
25541
|
+
toolCalls: 0,
|
|
25542
|
+
toolResults: 0,
|
|
25543
|
+
errors: 0
|
|
25544
|
+
};
|
|
25545
|
+
const toolUsageMap = /* @__PURE__ */ new Map();
|
|
25546
|
+
const modelUsageMap = /* @__PURE__ */ new Map();
|
|
25547
|
+
const errorStopReasons = new Set([
|
|
25548
|
+
"error",
|
|
25549
|
+
"aborted",
|
|
25550
|
+
"timeout"
|
|
25551
|
+
]);
|
|
25552
|
+
const latencyValues = [];
|
|
25553
|
+
let lastUserTimestamp;
|
|
25554
|
+
const MAX_LATENCY_MS = 720 * 60 * 1e3;
|
|
25555
|
+
await scanTranscriptFile({
|
|
25556
|
+
filePath: sessionFile,
|
|
25557
|
+
config: params.config,
|
|
25558
|
+
onEntry: (entry) => {
|
|
25559
|
+
const ts = entry.timestamp?.getTime();
|
|
25560
|
+
if (params.startMs !== void 0 && ts !== void 0 && ts < params.startMs) return;
|
|
25561
|
+
if (params.endMs !== void 0 && ts !== void 0 && ts > params.endMs) return;
|
|
25562
|
+
if (ts !== void 0) {
|
|
25563
|
+
if (!firstActivity || ts < firstActivity) firstActivity = ts;
|
|
25564
|
+
if (!lastActivity || ts > lastActivity) lastActivity = ts;
|
|
25565
|
+
}
|
|
25566
|
+
if (entry.role === "user") {
|
|
25567
|
+
messageCounts.user += 1;
|
|
25568
|
+
messageCounts.total += 1;
|
|
25569
|
+
if (entry.timestamp) lastUserTimestamp = entry.timestamp.getTime();
|
|
25570
|
+
}
|
|
25571
|
+
if (entry.role === "assistant") {
|
|
25572
|
+
messageCounts.assistant += 1;
|
|
25573
|
+
messageCounts.total += 1;
|
|
25574
|
+
const ts = entry.timestamp?.getTime();
|
|
25575
|
+
if (ts !== void 0) {
|
|
25576
|
+
const latencyMs = entry.durationMs ?? (lastUserTimestamp !== void 0 ? Math.max(0, ts - lastUserTimestamp) : void 0);
|
|
25577
|
+
if (latencyMs !== void 0 && Number.isFinite(latencyMs) && latencyMs <= MAX_LATENCY_MS) {
|
|
25578
|
+
latencyValues.push(latencyMs);
|
|
25579
|
+
const dayKey = formatDayKey(entry.timestamp ?? new Date(ts));
|
|
25580
|
+
const dailyLatencies = dailyLatencyMap.get(dayKey) ?? [];
|
|
25581
|
+
dailyLatencies.push(latencyMs);
|
|
25582
|
+
dailyLatencyMap.set(dayKey, dailyLatencies);
|
|
25583
|
+
}
|
|
25584
|
+
}
|
|
25585
|
+
}
|
|
25586
|
+
if (entry.toolNames.length > 0) {
|
|
25587
|
+
messageCounts.toolCalls += entry.toolNames.length;
|
|
25588
|
+
for (const name of entry.toolNames) toolUsageMap.set(name, (toolUsageMap.get(name) ?? 0) + 1);
|
|
25589
|
+
}
|
|
25590
|
+
if (entry.toolResultCounts.total > 0) {
|
|
25591
|
+
messageCounts.toolResults += entry.toolResultCounts.total;
|
|
25592
|
+
messageCounts.errors += entry.toolResultCounts.errors;
|
|
25593
|
+
}
|
|
25594
|
+
if (entry.stopReason && errorStopReasons.has(entry.stopReason)) messageCounts.errors += 1;
|
|
25595
|
+
if (entry.timestamp) {
|
|
25596
|
+
const dayKey = formatDayKey(entry.timestamp);
|
|
25597
|
+
activityDatesSet.add(dayKey);
|
|
25598
|
+
const daily = dailyMessageMap.get(dayKey) ?? {
|
|
25599
|
+
date: dayKey,
|
|
25600
|
+
total: 0,
|
|
25601
|
+
user: 0,
|
|
25602
|
+
assistant: 0,
|
|
25603
|
+
toolCalls: 0,
|
|
25604
|
+
toolResults: 0,
|
|
25605
|
+
errors: 0
|
|
25606
|
+
};
|
|
25607
|
+
daily.total += entry.role === "user" || entry.role === "assistant" ? 1 : 0;
|
|
25608
|
+
if (entry.role === "user") daily.user += 1;
|
|
25609
|
+
else if (entry.role === "assistant") daily.assistant += 1;
|
|
25610
|
+
daily.toolCalls += entry.toolNames.length;
|
|
25611
|
+
daily.toolResults += entry.toolResultCounts.total;
|
|
25612
|
+
daily.errors += entry.toolResultCounts.errors;
|
|
25613
|
+
if (entry.stopReason && errorStopReasons.has(entry.stopReason)) daily.errors += 1;
|
|
25614
|
+
dailyMessageMap.set(dayKey, daily);
|
|
25615
|
+
}
|
|
25616
|
+
if (!entry.usage) return;
|
|
25617
|
+
applyUsageTotals(totals, entry.usage);
|
|
25618
|
+
if (entry.costBreakdown?.total !== void 0) applyCostBreakdown(totals, entry.costBreakdown);
|
|
25619
|
+
else applyCostTotal(totals, entry.costTotal);
|
|
25620
|
+
if (entry.timestamp) {
|
|
25621
|
+
const dayKey = formatDayKey(entry.timestamp);
|
|
25622
|
+
const entryTokens = (entry.usage.input ?? 0) + (entry.usage.output ?? 0) + (entry.usage.cacheRead ?? 0) + (entry.usage.cacheWrite ?? 0);
|
|
25623
|
+
const entryCost = entry.costBreakdown?.total ?? (entry.costBreakdown ? (entry.costBreakdown.input ?? 0) + (entry.costBreakdown.output ?? 0) + (entry.costBreakdown.cacheRead ?? 0) + (entry.costBreakdown.cacheWrite ?? 0) : entry.costTotal ?? 0);
|
|
25624
|
+
const existing = dailyMap.get(dayKey) ?? {
|
|
25625
|
+
tokens: 0,
|
|
25626
|
+
cost: 0
|
|
25627
|
+
};
|
|
25628
|
+
dailyMap.set(dayKey, {
|
|
25629
|
+
tokens: existing.tokens + entryTokens,
|
|
25630
|
+
cost: existing.cost + entryCost
|
|
25631
|
+
});
|
|
25632
|
+
if (entry.provider || entry.model) {
|
|
25633
|
+
const modelKey = `${dayKey}::${entry.provider ?? "unknown"}::${entry.model ?? "unknown"}`;
|
|
25634
|
+
const dailyModel = dailyModelUsageMap.get(modelKey) ?? {
|
|
25635
|
+
date: dayKey,
|
|
25636
|
+
provider: entry.provider,
|
|
25637
|
+
model: entry.model,
|
|
25638
|
+
tokens: 0,
|
|
25639
|
+
cost: 0,
|
|
25640
|
+
count: 0
|
|
25641
|
+
};
|
|
25642
|
+
dailyModel.tokens += entryTokens;
|
|
25643
|
+
dailyModel.cost += entryCost;
|
|
25644
|
+
dailyModel.count += 1;
|
|
25645
|
+
dailyModelUsageMap.set(modelKey, dailyModel);
|
|
25646
|
+
}
|
|
25647
|
+
}
|
|
25648
|
+
if (entry.provider || entry.model) {
|
|
25649
|
+
const key = `${entry.provider ?? "unknown"}::${entry.model ?? "unknown"}`;
|
|
25650
|
+
const existing = modelUsageMap.get(key) ?? {
|
|
25651
|
+
provider: entry.provider,
|
|
25652
|
+
model: entry.model,
|
|
25653
|
+
count: 0,
|
|
25654
|
+
totals: emptyTotals()
|
|
25655
|
+
};
|
|
25656
|
+
existing.count += 1;
|
|
25657
|
+
applyUsageTotals(existing.totals, entry.usage);
|
|
25658
|
+
if (entry.costBreakdown?.total !== void 0) applyCostBreakdown(existing.totals, entry.costBreakdown);
|
|
25659
|
+
else applyCostTotal(existing.totals, entry.costTotal);
|
|
25660
|
+
modelUsageMap.set(key, existing);
|
|
25661
|
+
}
|
|
25662
|
+
}
|
|
25663
|
+
});
|
|
25664
|
+
const dailyBreakdown = Array.from(dailyMap.entries()).map(([date, data]) => ({
|
|
25665
|
+
date,
|
|
25666
|
+
tokens: data.tokens,
|
|
25667
|
+
cost: data.cost
|
|
25668
|
+
})).toSorted((a, b) => a.date.localeCompare(b.date));
|
|
25669
|
+
const dailyMessageCounts = Array.from(dailyMessageMap.values()).toSorted((a, b) => a.date.localeCompare(b.date));
|
|
25670
|
+
const dailyLatency = Array.from(dailyLatencyMap.entries()).map(([date, values]) => {
|
|
25671
|
+
const stats = computeLatencyStats(values);
|
|
25672
|
+
if (!stats) return null;
|
|
25673
|
+
return {
|
|
25674
|
+
date,
|
|
25675
|
+
...stats
|
|
25676
|
+
};
|
|
25677
|
+
}).filter((entry) => Boolean(entry)).toSorted((a, b) => a.date.localeCompare(b.date));
|
|
25678
|
+
const dailyModelUsage = Array.from(dailyModelUsageMap.values()).toSorted((a, b) => a.date.localeCompare(b.date) || b.cost - a.cost);
|
|
25679
|
+
const toolUsage = toolUsageMap.size ? {
|
|
25680
|
+
totalCalls: Array.from(toolUsageMap.values()).reduce((sum, count) => sum + count, 0),
|
|
25681
|
+
uniqueTools: toolUsageMap.size,
|
|
25682
|
+
tools: Array.from(toolUsageMap.entries()).map(([name, count]) => ({
|
|
25683
|
+
name,
|
|
25684
|
+
count
|
|
25685
|
+
})).toSorted((a, b) => b.count - a.count)
|
|
25686
|
+
} : void 0;
|
|
25687
|
+
const modelUsage = modelUsageMap.size ? Array.from(modelUsageMap.values()).toSorted((a, b) => {
|
|
25688
|
+
const costDiff = b.totals.totalCost - a.totals.totalCost;
|
|
25689
|
+
if (costDiff !== 0) return costDiff;
|
|
25690
|
+
return b.totals.totalTokens - a.totals.totalTokens;
|
|
25691
|
+
}) : void 0;
|
|
25692
|
+
return {
|
|
25693
|
+
sessionId: params.sessionId,
|
|
25694
|
+
sessionFile,
|
|
25695
|
+
firstActivity,
|
|
25696
|
+
lastActivity,
|
|
25697
|
+
durationMs: firstActivity !== void 0 && lastActivity !== void 0 ? Math.max(0, lastActivity - firstActivity) : void 0,
|
|
25698
|
+
activityDates: Array.from(activityDatesSet).toSorted(),
|
|
25699
|
+
dailyBreakdown,
|
|
25700
|
+
dailyMessageCounts,
|
|
25701
|
+
dailyLatency: dailyLatency.length ? dailyLatency : void 0,
|
|
25702
|
+
dailyModelUsage: dailyModelUsage.length ? dailyModelUsage : void 0,
|
|
25703
|
+
messageCounts,
|
|
25704
|
+
toolUsage,
|
|
25705
|
+
modelUsage,
|
|
25706
|
+
latency: computeLatencyStats(latencyValues),
|
|
25707
|
+
...totals
|
|
25708
|
+
};
|
|
25709
|
+
}
|
|
25710
|
+
|
|
25711
|
+
//#endregion
|
|
25712
|
+
//#region src/cost/benchmark.ts
|
|
25713
|
+
/**
|
|
25714
|
+
* Claude reference rates and benchmark comparison.
|
|
25715
|
+
*
|
|
25716
|
+
* Hardcoded per-token USD rates for Claude Opus 4.7, Sonnet 4.6, and
|
|
25717
|
+
* Haiku 4.5 (per million tokens, Anthropic public list as of 2026-Q1).
|
|
25718
|
+
* Override via `models.gpuRates` is for GPU rates only — Claude rates can
|
|
25719
|
+
* be overridden via the per-model `cost: { input, output }` configuration
|
|
25720
|
+
* on the user's `anthropic` provider entry, which already exists.
|
|
25721
|
+
*
|
|
25722
|
+
* Display: pick a target tier via `agents.defaults.cost.benchmark`, default
|
|
25723
|
+
* `sonnet`. Setting `"all"` shows comparisons against all three tiers.
|
|
25724
|
+
*/
|
|
25725
|
+
/** Per-million-token USD rates, applied via `estimateUsageCost`. */
|
|
25726
|
+
const CLAUDE_RATES = {
|
|
25727
|
+
opus: {
|
|
25728
|
+
input: 15,
|
|
25729
|
+
output: 75,
|
|
25730
|
+
cacheRead: 1.5,
|
|
25731
|
+
cacheWrite: 18.75
|
|
25732
|
+
},
|
|
25733
|
+
sonnet: {
|
|
25734
|
+
input: 3,
|
|
25735
|
+
output: 15,
|
|
25736
|
+
cacheRead: .3,
|
|
25737
|
+
cacheWrite: 3.75
|
|
25738
|
+
},
|
|
25739
|
+
haiku: {
|
|
25740
|
+
input: .8,
|
|
25741
|
+
output: 4,
|
|
25742
|
+
cacheRead: .08,
|
|
25743
|
+
cacheWrite: 1
|
|
25744
|
+
}
|
|
25745
|
+
};
|
|
25746
|
+
const CLAUDE_LABEL = {
|
|
25747
|
+
opus: "Claude Opus 4.7",
|
|
25748
|
+
sonnet: "Claude Sonnet 4.6",
|
|
25749
|
+
haiku: "Claude Haiku 4.5"
|
|
25750
|
+
};
|
|
25751
|
+
function benchmarkUsage(args) {
|
|
25752
|
+
if (!args.usage) return [];
|
|
25753
|
+
const tiers = args.target === "all" ? [
|
|
25754
|
+
"opus",
|
|
25755
|
+
"sonnet",
|
|
25756
|
+
"haiku"
|
|
25757
|
+
] : [args.target];
|
|
25758
|
+
const results = [];
|
|
25759
|
+
for (const tier of tiers) {
|
|
25760
|
+
const cost = estimateUsageCost({
|
|
25761
|
+
usage: args.usage,
|
|
25762
|
+
cost: CLAUDE_RATES[tier]
|
|
25763
|
+
});
|
|
25764
|
+
if (cost === void 0) continue;
|
|
25765
|
+
results.push({
|
|
25766
|
+
tier,
|
|
25767
|
+
costUsd: cost
|
|
25768
|
+
});
|
|
25769
|
+
}
|
|
25770
|
+
return results;
|
|
25771
|
+
}
|
|
25772
|
+
function formatBenchmarkSuffix(args) {
|
|
25773
|
+
if (args.benchmarks.length === 0) return;
|
|
25774
|
+
if (args.benchmarks.length === 1) {
|
|
25775
|
+
const b = args.benchmarks[0];
|
|
25776
|
+
return formatPair(args.ourCostUsd, b);
|
|
25777
|
+
}
|
|
25778
|
+
const parts = [];
|
|
25779
|
+
for (const b of args.benchmarks) parts.push(`${shortLabel(b.tier)} $${formatCostShort(b.costUsd)}`);
|
|
25780
|
+
const cheapest = args.benchmarks.reduce((min, b) => b.costUsd < min.costUsd ? b : min);
|
|
25781
|
+
if (cheapest.costUsd > args.ourCostUsd && cheapest.costUsd > 0) {
|
|
25782
|
+
const savedPct = (cheapest.costUsd - args.ourCostUsd) / cheapest.costUsd * 100;
|
|
25783
|
+
if (savedPct >= 1) parts.push(`save ${savedPct.toFixed(0)}% vs ${shortLabel(cheapest.tier)}`);
|
|
25784
|
+
}
|
|
25785
|
+
return `vs ${parts.join(" / ")}`;
|
|
25786
|
+
}
|
|
25787
|
+
function formatPair(ourCost, b) {
|
|
25788
|
+
const benchPart = `${CLAUDE_LABEL[b.tier]} would be $${formatCostShort(b.costUsd)}`;
|
|
25789
|
+
if (b.costUsd > 0 && b.costUsd > ourCost) {
|
|
25790
|
+
const saved = (b.costUsd - ourCost) / b.costUsd * 100;
|
|
25791
|
+
if (saved >= 1) return `${benchPart} (save ${saved.toFixed(0)}%)`;
|
|
25792
|
+
} else if (b.costUsd > 0 && ourCost > b.costUsd) {
|
|
25793
|
+
const overspend = (ourCost - b.costUsd) / b.costUsd * 100;
|
|
25794
|
+
if (overspend >= 1) return `${benchPart} (+${overspend.toFixed(0)}%)`;
|
|
25795
|
+
}
|
|
25796
|
+
return benchPart;
|
|
25797
|
+
}
|
|
25798
|
+
function shortLabel(tier) {
|
|
25799
|
+
if (tier === "opus") return "Opus";
|
|
25800
|
+
if (tier === "sonnet") return "Sonnet";
|
|
25801
|
+
return "Haiku";
|
|
25802
|
+
}
|
|
25803
|
+
function formatCostShort(value) {
|
|
25804
|
+
if (value >= 1) return value.toFixed(2);
|
|
25805
|
+
return value.toFixed(4);
|
|
25806
|
+
}
|
|
25807
|
+
function isClaudeTier(value) {
|
|
25808
|
+
return value === "opus" || value === "sonnet" || value === "haiku";
|
|
25809
|
+
}
|
|
25810
|
+
function isBenchmarkTarget(value) {
|
|
25811
|
+
return isClaudeTier(value) || value === "all";
|
|
25812
|
+
}
|
|
25813
|
+
function resolveBenchmarkTarget(value) {
|
|
25814
|
+
if (typeof value === "string" && isBenchmarkTarget(value)) return value;
|
|
25815
|
+
return "sonnet";
|
|
25816
|
+
}
|
|
25817
|
+
|
|
25818
|
+
//#endregion
|
|
25819
|
+
//#region src/cost/summary.ts
|
|
25820
|
+
async function loadCostBenchmarkSummary(params) {
|
|
25821
|
+
const summary = await loadCostUsageSummary(params);
|
|
25822
|
+
const daily = summary.daily.map((day) => ({
|
|
25823
|
+
...day,
|
|
25824
|
+
benchmarkUsd: computeBenchmarkPerTier(day)
|
|
25825
|
+
}));
|
|
25826
|
+
const benchmarkTotals = computeBenchmarkPerTier(summary.totals);
|
|
25827
|
+
const savingsTotals = {
|
|
25828
|
+
opus: benchmarkTotals.opus - summary.totals.totalCost,
|
|
25829
|
+
sonnet: benchmarkTotals.sonnet - summary.totals.totalCost,
|
|
25830
|
+
haiku: benchmarkTotals.haiku - summary.totals.totalCost
|
|
25831
|
+
};
|
|
25832
|
+
return {
|
|
25833
|
+
...summary,
|
|
25834
|
+
daily,
|
|
25835
|
+
benchmarkTotals,
|
|
25836
|
+
savingsTotals
|
|
25837
|
+
};
|
|
25838
|
+
}
|
|
25839
|
+
function computeBenchmarkPerTier(totals) {
|
|
25840
|
+
const all = benchmarkUsage({
|
|
25841
|
+
usage: {
|
|
25842
|
+
input: totals.input,
|
|
25843
|
+
output: totals.output,
|
|
25844
|
+
cacheRead: totals.cacheRead,
|
|
25845
|
+
cacheWrite: totals.cacheWrite
|
|
25846
|
+
},
|
|
25847
|
+
target: "all"
|
|
25848
|
+
});
|
|
25849
|
+
const map = new Map(all.map((b) => [b.tier, b.costUsd]));
|
|
25850
|
+
return {
|
|
25851
|
+
opus: map.get("opus") ?? 0,
|
|
25852
|
+
sonnet: map.get("sonnet") ?? 0,
|
|
25853
|
+
haiku: map.get("haiku") ?? 0
|
|
25854
|
+
};
|
|
25855
|
+
}
|
|
25856
|
+
function resolveWindow(window, now = Date.now()) {
|
|
25857
|
+
const end = now;
|
|
25858
|
+
switch (window) {
|
|
25859
|
+
case "today": {
|
|
25860
|
+
const d = new Date(end);
|
|
25861
|
+
d.setHours(0, 0, 0, 0);
|
|
25862
|
+
return {
|
|
25863
|
+
startMs: d.getTime(),
|
|
25864
|
+
endMs: end
|
|
25865
|
+
};
|
|
25866
|
+
}
|
|
25867
|
+
case "week": return {
|
|
25868
|
+
startMs: end - 10080 * 6e4,
|
|
25869
|
+
endMs: end
|
|
25870
|
+
};
|
|
25871
|
+
case "month": return {
|
|
25872
|
+
startMs: end - 720 * 60 * 6e4,
|
|
25873
|
+
endMs: end
|
|
25874
|
+
};
|
|
25875
|
+
case "all": return {
|
|
25876
|
+
startMs: 0,
|
|
25877
|
+
endMs: end
|
|
25878
|
+
};
|
|
25879
|
+
}
|
|
25880
|
+
}
|
|
25881
|
+
function formatSummaryReport(summary, label) {
|
|
25882
|
+
const t = summary.totals;
|
|
25883
|
+
const b = summary.benchmarkTotals;
|
|
25884
|
+
const lines = [];
|
|
25885
|
+
if (label) lines.push(`# ${label}`);
|
|
25886
|
+
lines.push(`Tokens: ${formatTokens(t.totalTokens)} (${formatTokens(t.input)} in / ${formatTokens(t.output)} out)`);
|
|
25887
|
+
lines.push(`Spend: $${t.totalCost.toFixed(4)}`);
|
|
25888
|
+
lines.push(`Claude equivalents:`);
|
|
25889
|
+
lines.push(` Opus: $${b.opus.toFixed(4)} (saved $${(b.opus - t.totalCost).toFixed(4)})`);
|
|
25890
|
+
lines.push(` Sonnet: $${b.sonnet.toFixed(4)} (saved $${(b.sonnet - t.totalCost).toFixed(4)})`);
|
|
25891
|
+
lines.push(` Haiku: $${b.haiku.toFixed(4)} (saved $${(b.haiku - t.totalCost).toFixed(4)})`);
|
|
25892
|
+
if (summary.daily.length > 0) {
|
|
25893
|
+
lines.push("");
|
|
25894
|
+
lines.push("Daily:");
|
|
25895
|
+
for (const d of summary.daily.slice(-7)) lines.push(` ${d.date}: ${formatTokens(d.totalTokens).padStart(8)} tokens · $${d.totalCost.toFixed(4).padStart(8)} · vs Sonnet $${d.benchmarkUsd.sonnet.toFixed(4)}`);
|
|
25896
|
+
}
|
|
25897
|
+
return lines.join("\n");
|
|
25898
|
+
}
|
|
25899
|
+
function formatTokens(n) {
|
|
25900
|
+
if (!Number.isFinite(n) || n <= 0) return "0";
|
|
25901
|
+
if (n >= 1e6) return `${(n / 1e6).toFixed(1)}m`;
|
|
25902
|
+
if (n >= 1e3) return `${(n / 1e3).toFixed(n >= 1e4 ? 0 : 1)}k`;
|
|
25903
|
+
return String(Math.round(n));
|
|
25904
|
+
}
|
|
25905
|
+
|
|
25300
25906
|
//#endregion
|
|
25301
25907
|
//#region src/agents/system-prompt-report.ts
|
|
25302
25908
|
function extractBetween(input, startMarker, endMarker) {
|
|
@@ -26417,6 +27023,560 @@ async function buildExportSessionReply(params) {
|
|
|
26417
27023
|
].join("\n") };
|
|
26418
27024
|
}
|
|
26419
27025
|
|
|
27026
|
+
//#endregion
|
|
27027
|
+
//#region src/cost/rates.ts
|
|
27028
|
+
const GPU_VRAM_GB = {
|
|
27029
|
+
"a100-40gb": 40,
|
|
27030
|
+
"a100-80gb": 80,
|
|
27031
|
+
"h100-pcie": 80,
|
|
27032
|
+
"h100-sxm": 80,
|
|
27033
|
+
h200: 141,
|
|
27034
|
+
l40: 48,
|
|
27035
|
+
l40s: 48,
|
|
27036
|
+
a40: 48,
|
|
27037
|
+
a6000: 48,
|
|
27038
|
+
a5000: 24,
|
|
27039
|
+
v100: 32,
|
|
27040
|
+
mi300x: 192,
|
|
27041
|
+
"rtx-4090": 24
|
|
27042
|
+
};
|
|
27043
|
+
const GPU_LABEL = {
|
|
27044
|
+
"a100-40gb": "A100-40GB",
|
|
27045
|
+
"a100-80gb": "A100-80GB",
|
|
27046
|
+
"h100-pcie": "H100-PCIe",
|
|
27047
|
+
"h100-sxm": "H100-SXM",
|
|
27048
|
+
h200: "H200",
|
|
27049
|
+
l40: "L40",
|
|
27050
|
+
l40s: "L40S",
|
|
27051
|
+
a40: "A40",
|
|
27052
|
+
a6000: "RTX-A6000",
|
|
27053
|
+
a5000: "RTX-A5000",
|
|
27054
|
+
v100: "V100",
|
|
27055
|
+
mi300x: "MI300X",
|
|
27056
|
+
"rtx-4090": "RTX-4090"
|
|
27057
|
+
};
|
|
27058
|
+
const DEFAULT_HOURLY_RATES_USD = {
|
|
27059
|
+
"a100-40gb": 2.06,
|
|
27060
|
+
"a100-80gb": 2.21,
|
|
27061
|
+
"h100-pcie": 4.25,
|
|
27062
|
+
"h100-sxm": 4.76,
|
|
27063
|
+
h200: 6.5,
|
|
27064
|
+
l40: 1.27,
|
|
27065
|
+
l40s: 1.35,
|
|
27066
|
+
a40: .95,
|
|
27067
|
+
a6000: .96,
|
|
27068
|
+
a5000: .61,
|
|
27069
|
+
v100: .8,
|
|
27070
|
+
mi300x: 4.89,
|
|
27071
|
+
"rtx-4090": .74
|
|
27072
|
+
};
|
|
27073
|
+
/**
|
|
27074
|
+
* Rough decode (output) throughput defaults in tokens/sec for a 27-30B FP8
|
|
27075
|
+
* model on a single GPU of each type. Scales roughly inversely with model
|
|
27076
|
+
* parameter count and bytes-per-param. Used as a fallback when no live
|
|
27077
|
+
* `vllm:generation_tokens_total` delta has been observed yet.
|
|
27078
|
+
*
|
|
27079
|
+
* These are conservative published-benchmark medians; treat as ballpark.
|
|
27080
|
+
* Override via `models.gpuRates` is rate-only; throughput overrides are
|
|
27081
|
+
* Phase 4+ (not yet wired to config).
|
|
27082
|
+
*/
|
|
27083
|
+
const DEFAULT_DECODE_TPS = {
|
|
27084
|
+
"a100-40gb": 60,
|
|
27085
|
+
"a100-80gb": 80,
|
|
27086
|
+
"h100-pcie": 120,
|
|
27087
|
+
"h100-sxm": 130,
|
|
27088
|
+
h200: 160,
|
|
27089
|
+
l40: 45,
|
|
27090
|
+
l40s: 50,
|
|
27091
|
+
a40: 40,
|
|
27092
|
+
a6000: 35,
|
|
27093
|
+
a5000: 25,
|
|
27094
|
+
v100: 25,
|
|
27095
|
+
mi300x: 110,
|
|
27096
|
+
"rtx-4090": 55
|
|
27097
|
+
};
|
|
27098
|
+
/**
|
|
27099
|
+
* Prefill throughput is typically 30-60× higher than decode for a given
|
|
27100
|
+
* setup. Use 40× as a balanced midpoint.
|
|
27101
|
+
*/
|
|
27102
|
+
const PREFILL_DECODE_RATIO = 40;
|
|
27103
|
+
function resolveDefaultDecodeTps(gpuType, paramsB, bytesPerParam) {
|
|
27104
|
+
const baseline = DEFAULT_DECODE_TPS[gpuType];
|
|
27105
|
+
if (!paramsB) return baseline;
|
|
27106
|
+
const refBytes = 27;
|
|
27107
|
+
const modelBytes = paramsB * (bytesPerParam ?? 2);
|
|
27108
|
+
if (modelBytes <= 0) return baseline;
|
|
27109
|
+
const scaled = baseline * (refBytes / modelBytes);
|
|
27110
|
+
return Math.max(5, scaled);
|
|
27111
|
+
}
|
|
27112
|
+
function resolveHourlyRate(gpuType, overrides) {
|
|
27113
|
+
if (overrides && typeof overrides[gpuType] === "number" && overrides[gpuType] >= 0) return overrides[gpuType];
|
|
27114
|
+
return DEFAULT_HOURLY_RATES_USD[gpuType];
|
|
27115
|
+
}
|
|
27116
|
+
|
|
27117
|
+
//#endregion
|
|
27118
|
+
//#region src/cost/gpu-inference.ts
|
|
27119
|
+
/**
|
|
27120
|
+
* Heuristic GPU type + count inference for self-hosted serving endpoints.
|
|
27121
|
+
*
|
|
27122
|
+
* Two signals: the baseUrl hostname (often encodes "a100", "h100", etc.) and
|
|
27123
|
+
* the model id (encodes parameter count + quantization, e.g. "qwen36-27b-fp8").
|
|
27124
|
+
* Output is a confidence-tagged guess so downstream code (and the user) can
|
|
27125
|
+
* decide whether to trust the inference or override it.
|
|
27126
|
+
*
|
|
27127
|
+
* Bytes-per-parameter table:
|
|
27128
|
+
* fp32 → 4
|
|
27129
|
+
* fp16/bf16 → 2 (default when unspecified)
|
|
27130
|
+
* fp8/int8/q8 → 1
|
|
27131
|
+
* int4/q4/fp4 → 0.5
|
|
27132
|
+
*
|
|
27133
|
+
* GPU count formula:
|
|
27134
|
+
* model_bytes = params × bytes_per_param
|
|
27135
|
+
* target_util = 0.6 (40% headroom for KV cache, activations, scheduler)
|
|
27136
|
+
* count = max(1, ceil(model_bytes / (vram × target_util)))
|
|
27137
|
+
*/
|
|
27138
|
+
const URL_GPU_PATTERNS = [
|
|
27139
|
+
{
|
|
27140
|
+
re: /h200/i,
|
|
27141
|
+
type: "h200",
|
|
27142
|
+
confidence: "high"
|
|
27143
|
+
},
|
|
27144
|
+
{
|
|
27145
|
+
re: /h100[-_]?pcie/i,
|
|
27146
|
+
type: "h100-pcie",
|
|
27147
|
+
confidence: "high"
|
|
27148
|
+
},
|
|
27149
|
+
{
|
|
27150
|
+
re: /h100[-_]?sxm/i,
|
|
27151
|
+
type: "h100-sxm",
|
|
27152
|
+
confidence: "high"
|
|
27153
|
+
},
|
|
27154
|
+
{
|
|
27155
|
+
re: /h100/i,
|
|
27156
|
+
type: "h100-sxm",
|
|
27157
|
+
confidence: "medium"
|
|
27158
|
+
},
|
|
27159
|
+
{
|
|
27160
|
+
re: /a100[-_]?80/i,
|
|
27161
|
+
type: "a100-80gb",
|
|
27162
|
+
confidence: "high"
|
|
27163
|
+
},
|
|
27164
|
+
{
|
|
27165
|
+
re: /a100[-_]?40/i,
|
|
27166
|
+
type: "a100-40gb",
|
|
27167
|
+
confidence: "high"
|
|
27168
|
+
},
|
|
27169
|
+
{
|
|
27170
|
+
re: /a100/i,
|
|
27171
|
+
type: "a100-80gb",
|
|
27172
|
+
confidence: "medium"
|
|
27173
|
+
},
|
|
27174
|
+
{
|
|
27175
|
+
re: /l40s/i,
|
|
27176
|
+
type: "l40s",
|
|
27177
|
+
confidence: "high"
|
|
27178
|
+
},
|
|
27179
|
+
{
|
|
27180
|
+
re: /l40/i,
|
|
27181
|
+
type: "l40",
|
|
27182
|
+
confidence: "high"
|
|
27183
|
+
},
|
|
27184
|
+
{
|
|
27185
|
+
re: /mi300x/i,
|
|
27186
|
+
type: "mi300x",
|
|
27187
|
+
confidence: "high"
|
|
27188
|
+
},
|
|
27189
|
+
{
|
|
27190
|
+
re: /a6000/i,
|
|
27191
|
+
type: "a6000",
|
|
27192
|
+
confidence: "high"
|
|
27193
|
+
},
|
|
27194
|
+
{
|
|
27195
|
+
re: /a5000/i,
|
|
27196
|
+
type: "a5000",
|
|
27197
|
+
confidence: "high"
|
|
27198
|
+
},
|
|
27199
|
+
{
|
|
27200
|
+
re: /a40/i,
|
|
27201
|
+
type: "a40",
|
|
27202
|
+
confidence: "high"
|
|
27203
|
+
},
|
|
27204
|
+
{
|
|
27205
|
+
re: /v100/i,
|
|
27206
|
+
type: "v100",
|
|
27207
|
+
confidence: "high"
|
|
27208
|
+
},
|
|
27209
|
+
{
|
|
27210
|
+
re: /rtx[-_]?4090|gpu[-_]?4090/i,
|
|
27211
|
+
type: "rtx-4090",
|
|
27212
|
+
confidence: "high"
|
|
27213
|
+
}
|
|
27214
|
+
];
|
|
27215
|
+
function inferGpuFromUrl(baseUrl) {
|
|
27216
|
+
const url = baseUrl.toLowerCase();
|
|
27217
|
+
for (const pattern of URL_GPU_PATTERNS) {
|
|
27218
|
+
const match = url.match(pattern.re);
|
|
27219
|
+
if (match) return {
|
|
27220
|
+
gpuType: pattern.type,
|
|
27221
|
+
confidence: pattern.confidence,
|
|
27222
|
+
match: match[0]
|
|
27223
|
+
};
|
|
27224
|
+
}
|
|
27225
|
+
return { confidence: "low" };
|
|
27226
|
+
}
|
|
27227
|
+
function parseModelSize(modelId) {
|
|
27228
|
+
const id = modelId.toLowerCase();
|
|
27229
|
+
const sizeMatch = id.match(/(\d+(?:\.\d+)?)b(?:[-_./]|$)/);
|
|
27230
|
+
const paramsB = sizeMatch ? Number.parseFloat(sizeMatch[1]) : void 0;
|
|
27231
|
+
let bytesPerParam;
|
|
27232
|
+
if (/\b(fp4|q4|int4)\b/.test(id) || /[-_]q4[-_]/.test(id)) bytesPerParam = .5;
|
|
27233
|
+
else if (/\b(fp8|int8|q8|w8a8|w8a16)\b/.test(id) || /[-_]fp8[-_]?/.test(id)) bytesPerParam = 1;
|
|
27234
|
+
else if (/\b(fp16|bf16|float16|half)\b/.test(id)) bytesPerParam = 2;
|
|
27235
|
+
else if (/\b(fp32|float32)\b/.test(id)) bytesPerParam = 4;
|
|
27236
|
+
return {
|
|
27237
|
+
paramsB,
|
|
27238
|
+
bytesPerParam
|
|
27239
|
+
};
|
|
27240
|
+
}
|
|
27241
|
+
function inferGpuCount(args) {
|
|
27242
|
+
const util = args.targetUtilization ?? .6;
|
|
27243
|
+
if (!args.paramsB || !args.bytesPerParam) return 1;
|
|
27244
|
+
const modelBytes = args.paramsB * 1e9 * args.bytesPerParam;
|
|
27245
|
+
const usableVram = args.vramGb * 1e9 * util;
|
|
27246
|
+
return Math.max(1, Math.ceil(modelBytes / usableVram));
|
|
27247
|
+
}
|
|
27248
|
+
function inferGpu(args) {
|
|
27249
|
+
const reasoning = [];
|
|
27250
|
+
const overrideType = args.override?.gpuType;
|
|
27251
|
+
const overrideCount = args.override?.gpuCount;
|
|
27252
|
+
let gpuType;
|
|
27253
|
+
let confidence = "low";
|
|
27254
|
+
if (overrideType && overrideType in GPU_VRAM_GB) {
|
|
27255
|
+
gpuType = overrideType;
|
|
27256
|
+
confidence = "high";
|
|
27257
|
+
reasoning.push(`gpuType=${gpuType} from config override`);
|
|
27258
|
+
} else if (args.baseUrl) {
|
|
27259
|
+
const fromUrl = inferGpuFromUrl(args.baseUrl);
|
|
27260
|
+
if (fromUrl.gpuType) {
|
|
27261
|
+
gpuType = fromUrl.gpuType;
|
|
27262
|
+
confidence = fromUrl.confidence;
|
|
27263
|
+
reasoning.push(`gpuType=${gpuType} from URL pattern '${fromUrl.match}'`);
|
|
27264
|
+
} else reasoning.push("no GPU type pattern matched in URL");
|
|
27265
|
+
}
|
|
27266
|
+
const sized = args.modelId ? parseModelSize(args.modelId) : {};
|
|
27267
|
+
if (sized.paramsB) reasoning.push(`paramsB=${sized.paramsB} from model id '${args.modelId}'`);
|
|
27268
|
+
if (sized.bytesPerParam) reasoning.push(`bytesPerParam=${sized.bytesPerParam} from quantization marker`);
|
|
27269
|
+
else if (args.modelId) reasoning.push("no quantization marker — defaulting to bf16 (2 bytes)");
|
|
27270
|
+
let gpuCount = 1;
|
|
27271
|
+
if (typeof overrideCount === "number" && overrideCount > 0) {
|
|
27272
|
+
gpuCount = Math.floor(overrideCount);
|
|
27273
|
+
reasoning.push(`gpuCount=${gpuCount} from config override`);
|
|
27274
|
+
} else if (gpuType) {
|
|
27275
|
+
const bpp = sized.bytesPerParam ?? 2;
|
|
27276
|
+
gpuCount = inferGpuCount({
|
|
27277
|
+
paramsB: sized.paramsB,
|
|
27278
|
+
bytesPerParam: bpp,
|
|
27279
|
+
vramGb: GPU_VRAM_GB[gpuType]
|
|
27280
|
+
});
|
|
27281
|
+
if (sized.paramsB) reasoning.push(`gpuCount=${gpuCount} (model ${(sized.paramsB * bpp).toFixed(0)}GB / ${GPU_VRAM_GB[gpuType]}GB × 0.6 util)`);
|
|
27282
|
+
}
|
|
27283
|
+
return {
|
|
27284
|
+
gpuType,
|
|
27285
|
+
gpuCount,
|
|
27286
|
+
confidence,
|
|
27287
|
+
paramsB: sized.paramsB,
|
|
27288
|
+
bytesPerParam: sized.bytesPerParam,
|
|
27289
|
+
reasoning
|
|
27290
|
+
};
|
|
27291
|
+
}
|
|
27292
|
+
|
|
27293
|
+
//#endregion
|
|
27294
|
+
//#region src/cost/serving-discovery.ts
|
|
27295
|
+
const SUCCESS_TTL_MS = 6e4;
|
|
27296
|
+
const NULL_TTL_MS = 5 * 6e4;
|
|
27297
|
+
const DEFAULT_TIMEOUT_MS$1 = 4e3;
|
|
27298
|
+
const cache = /* @__PURE__ */ new Map();
|
|
27299
|
+
const previousSnapshots = /* @__PURE__ */ new Map();
|
|
27300
|
+
async function probeServingEndpoint(baseUrl, opts = {}) {
|
|
27301
|
+
const fetchImpl = opts.fetchImpl ?? globalThis.fetch;
|
|
27302
|
+
const nowFn = opts.now ?? (() => Date.now());
|
|
27303
|
+
const timeoutMs = opts.timeoutMs ?? DEFAULT_TIMEOUT_MS$1;
|
|
27304
|
+
const trimmed = baseUrl.trim().replace(/\/+$/, "");
|
|
27305
|
+
if (!trimmed) return null;
|
|
27306
|
+
const cached = cache.get(trimmed);
|
|
27307
|
+
if (cached && !opts.forceRefresh && cached.expiresAt > nowFn()) return cached.info;
|
|
27308
|
+
const rootUrl = trimmed.replace(/\/v\d+$/, "");
|
|
27309
|
+
const probeAt = nowFn();
|
|
27310
|
+
const fetchOpts = () => ({
|
|
27311
|
+
signal: AbortSignal.timeout(timeoutMs),
|
|
27312
|
+
headers: { Accept: "application/json, text/plain, */*" }
|
|
27313
|
+
});
|
|
27314
|
+
const [versionRes, modelsRes, metricsRes] = await Promise.allSettled([
|
|
27315
|
+
fetchImpl(`${rootUrl}/version`, fetchOpts()),
|
|
27316
|
+
fetchImpl(`${rootUrl}/v1/models`, fetchOpts()),
|
|
27317
|
+
fetchImpl(`${rootUrl}/metrics`, fetchOpts())
|
|
27318
|
+
]);
|
|
27319
|
+
const info = {
|
|
27320
|
+
engine: "unknown",
|
|
27321
|
+
probedAt: probeAt,
|
|
27322
|
+
baseUrl: trimmed,
|
|
27323
|
+
rootUrl
|
|
27324
|
+
};
|
|
27325
|
+
if (versionRes.status === "fulfilled" && versionRes.value.ok) try {
|
|
27326
|
+
const txt = await versionRes.value.text();
|
|
27327
|
+
try {
|
|
27328
|
+
const json = JSON.parse(txt);
|
|
27329
|
+
if (typeof json.version === "string") info.version = json.version;
|
|
27330
|
+
} catch {
|
|
27331
|
+
const stripped = txt.trim();
|
|
27332
|
+
if (stripped && stripped.length < 64 && /^[\w.\-+]+$/.test(stripped)) info.version = stripped;
|
|
27333
|
+
}
|
|
27334
|
+
} catch {}
|
|
27335
|
+
if (modelsRes.status === "fulfilled" && modelsRes.value.ok) try {
|
|
27336
|
+
const first = (await modelsRes.value.json()).data?.[0];
|
|
27337
|
+
if (first) {
|
|
27338
|
+
if (typeof first.id === "string") info.modelId = first.id;
|
|
27339
|
+
if (typeof first.max_model_len === "number") info.contextWindow = first.max_model_len;
|
|
27340
|
+
if (typeof first.owned_by === "string") {
|
|
27341
|
+
const owner = first.owned_by.toLowerCase();
|
|
27342
|
+
if (owner.includes("vllm")) info.engine = "vllm";
|
|
27343
|
+
else if (owner.includes("sglang")) info.engine = "sglang";
|
|
27344
|
+
else if (info.engine === "unknown") info.engine = "openai-compat";
|
|
27345
|
+
}
|
|
27346
|
+
}
|
|
27347
|
+
} catch {}
|
|
27348
|
+
let snapshot = { probedAt: probeAt };
|
|
27349
|
+
if (metricsRes.status === "fulfilled" && metricsRes.value.ok) try {
|
|
27350
|
+
const parsed = parsePrometheusMetrics(await metricsRes.value.text());
|
|
27351
|
+
info.kvCacheUsagePerc = parsed.kvCacheUsagePerc;
|
|
27352
|
+
info.queueDepth = parsed.queueDepth;
|
|
27353
|
+
info.numRequestsRunning = parsed.numRequestsRunning;
|
|
27354
|
+
info.cacheConfig = parsed.cacheConfig;
|
|
27355
|
+
snapshot = {
|
|
27356
|
+
probedAt: probeAt,
|
|
27357
|
+
promptTokensTotal: parsed.promptTokensTotal,
|
|
27358
|
+
generationTokensTotal: parsed.generationTokensTotal
|
|
27359
|
+
};
|
|
27360
|
+
if (info.engine === "unknown" && parsed.foundVllmPrefix) info.engine = "vllm";
|
|
27361
|
+
if (info.engine === "unknown" && parsed.foundSglangPrefix) info.engine = "sglang";
|
|
27362
|
+
} catch {}
|
|
27363
|
+
const prev = previousSnapshots.get(trimmed);
|
|
27364
|
+
if (prev && typeof prev.generationTokensTotal === "number" && typeof snapshot.generationTokensTotal === "number") {
|
|
27365
|
+
const dt = (snapshot.probedAt - prev.probedAt) / 1e3;
|
|
27366
|
+
const dToks = snapshot.generationTokensTotal - prev.generationTokensTotal;
|
|
27367
|
+
if (dt > 0 && dToks >= 0) info.observedTps = dToks / dt;
|
|
27368
|
+
}
|
|
27369
|
+
if (snapshot.generationTokensTotal !== void 0 || snapshot.promptTokensTotal !== void 0) previousSnapshots.set(trimmed, snapshot);
|
|
27370
|
+
if (!(info.version !== void 0 || info.modelId !== void 0 || info.cacheConfig !== void 0 || info.kvCacheUsagePerc !== void 0 || info.queueDepth !== void 0 || info.numRequestsRunning !== void 0)) {
|
|
27371
|
+
cache.set(trimmed, {
|
|
27372
|
+
info: null,
|
|
27373
|
+
expiresAt: nowFn() + NULL_TTL_MS
|
|
27374
|
+
});
|
|
27375
|
+
return null;
|
|
27376
|
+
}
|
|
27377
|
+
cache.set(trimmed, {
|
|
27378
|
+
info,
|
|
27379
|
+
expiresAt: nowFn() + SUCCESS_TTL_MS
|
|
27380
|
+
});
|
|
27381
|
+
return info;
|
|
27382
|
+
}
|
|
27383
|
+
function parsePrometheusMetrics(text) {
|
|
27384
|
+
const result = {
|
|
27385
|
+
foundVllmPrefix: false,
|
|
27386
|
+
foundSglangPrefix: false
|
|
27387
|
+
};
|
|
27388
|
+
const lines = text.split("\n");
|
|
27389
|
+
for (const raw of lines) {
|
|
27390
|
+
const line = raw.trim();
|
|
27391
|
+
if (!line || line.startsWith("#")) continue;
|
|
27392
|
+
if (line.startsWith("vllm:")) result.foundVllmPrefix = true;
|
|
27393
|
+
if (line.startsWith("sglang:")) result.foundSglangPrefix = true;
|
|
27394
|
+
const match = line.match(/^([^\s{]+)(\{[^}]*\})?\s+([0-9eE+\-.]+)$/);
|
|
27395
|
+
if (!match) continue;
|
|
27396
|
+
const metric = match[1];
|
|
27397
|
+
const labels = match[2];
|
|
27398
|
+
const value = Number(match[3]);
|
|
27399
|
+
if (!Number.isFinite(value)) continue;
|
|
27400
|
+
switch (metric) {
|
|
27401
|
+
case "vllm:prompt_tokens_total":
|
|
27402
|
+
result.promptTokensTotal = (result.promptTokensTotal ?? 0) + value;
|
|
27403
|
+
break;
|
|
27404
|
+
case "vllm:generation_tokens_total":
|
|
27405
|
+
result.generationTokensTotal = (result.generationTokensTotal ?? 0) + value;
|
|
27406
|
+
break;
|
|
27407
|
+
case "vllm:kv_cache_usage_perc":
|
|
27408
|
+
result.kvCacheUsagePerc = value;
|
|
27409
|
+
break;
|
|
27410
|
+
case "vllm:num_requests_waiting":
|
|
27411
|
+
if (!labels || !labels.includes("reason=")) result.queueDepth = value;
|
|
27412
|
+
break;
|
|
27413
|
+
case "vllm:num_requests_running":
|
|
27414
|
+
result.numRequestsRunning = value;
|
|
27415
|
+
break;
|
|
27416
|
+
case "vllm:cache_config_info": {
|
|
27417
|
+
if (!labels) break;
|
|
27418
|
+
const parsed = parseLabels(labels);
|
|
27419
|
+
const cfg = {};
|
|
27420
|
+
if (parsed.block_size !== void 0) cfg.blockSize = Number(parsed.block_size);
|
|
27421
|
+
if (parsed.num_gpu_blocks !== void 0) cfg.numGpuBlocks = Number(parsed.num_gpu_blocks);
|
|
27422
|
+
if (parsed.cache_dtype !== void 0) cfg.cacheDtype = parsed.cache_dtype;
|
|
27423
|
+
if (parsed.gpu_memory_utilization !== void 0) {
|
|
27424
|
+
const n = Number(parsed.gpu_memory_utilization);
|
|
27425
|
+
if (Number.isFinite(n)) cfg.gpuMemoryUtilization = n;
|
|
27426
|
+
}
|
|
27427
|
+
if (parsed.enable_prefix_caching !== void 0) cfg.enablePrefixCaching = parsed.enable_prefix_caching === "True";
|
|
27428
|
+
result.cacheConfig = cfg;
|
|
27429
|
+
break;
|
|
27430
|
+
}
|
|
27431
|
+
}
|
|
27432
|
+
}
|
|
27433
|
+
return result;
|
|
27434
|
+
}
|
|
27435
|
+
function parseLabels(rawLabels) {
|
|
27436
|
+
const inner = rawLabels.replace(/^\{/, "").replace(/\}$/, "");
|
|
27437
|
+
const out = {};
|
|
27438
|
+
const re = /(\w+)="([^"]*)"/g;
|
|
27439
|
+
let m;
|
|
27440
|
+
while ((m = re.exec(inner)) !== null) out[m[1]] = m[2];
|
|
27441
|
+
return out;
|
|
27442
|
+
}
|
|
27443
|
+
function formatEngineLine(info) {
|
|
27444
|
+
if (!info) return null;
|
|
27445
|
+
const parts = [];
|
|
27446
|
+
const engineLabel = (() => {
|
|
27447
|
+
if (info.engine === "vllm") return info.version ? `vLLM ${info.version}` : "vLLM";
|
|
27448
|
+
if (info.engine === "sglang") return info.version ? `SGLang ${info.version}` : "SGLang";
|
|
27449
|
+
if (info.engine === "openai-compat") return "OpenAI-compat";
|
|
27450
|
+
return info.version ? `engine ${info.version}` : null;
|
|
27451
|
+
})();
|
|
27452
|
+
if (engineLabel) parts.push(engineLabel);
|
|
27453
|
+
if (typeof info.observedTps === "number" && info.observedTps > .5) parts.push(`${Math.round(info.observedTps)} tps`);
|
|
27454
|
+
if (typeof info.kvCacheUsagePerc === "number") {
|
|
27455
|
+
const pct = Math.round(info.kvCacheUsagePerc * 100);
|
|
27456
|
+
if (pct > 0) parts.push(`KV ${pct}%`);
|
|
27457
|
+
}
|
|
27458
|
+
if (typeof info.queueDepth === "number" && info.queueDepth > 0) parts.push(`queue ${info.queueDepth}`);
|
|
27459
|
+
if (typeof info.numRequestsRunning === "number" && info.numRequestsRunning > 0) parts.push(`running ${info.numRequestsRunning}`);
|
|
27460
|
+
if (parts.length === 0) return null;
|
|
27461
|
+
return `🖥 ${parts.join(" · ")}`;
|
|
27462
|
+
}
|
|
27463
|
+
|
|
27464
|
+
//#endregion
|
|
27465
|
+
//#region src/cost/breakdown.ts
|
|
27466
|
+
async function buildCostBreakdown(args) {
|
|
27467
|
+
const benchmarkTarget = args.config?.models?.benchmark === "none" ? "none" : resolveBenchmarkTarget(args.config?.models?.benchmark);
|
|
27468
|
+
const breakdown = {
|
|
27469
|
+
serving: null,
|
|
27470
|
+
benchmarks: [],
|
|
27471
|
+
benchmarkTarget
|
|
27472
|
+
};
|
|
27473
|
+
if (args.baseUrl && args.baseUrl.trim()) try {
|
|
27474
|
+
breakdown.serving = await probeServingEndpoint(args.baseUrl, {
|
|
27475
|
+
timeoutMs: args.probeTimeoutMs ?? 3e3,
|
|
27476
|
+
forceRefresh: Boolean(args.forceProbeRefresh)
|
|
27477
|
+
});
|
|
27478
|
+
} catch {
|
|
27479
|
+
breakdown.serving = null;
|
|
27480
|
+
}
|
|
27481
|
+
breakdown.engineLine = formatEngineLine(breakdown.serving) ?? void 0;
|
|
27482
|
+
const modelCost = resolveModelCost(args.config, args.provider, args.modelId);
|
|
27483
|
+
const detectedModelId = breakdown.serving?.modelId ?? args.modelId;
|
|
27484
|
+
breakdown.gpu = inferGpu({
|
|
27485
|
+
baseUrl: args.baseUrl,
|
|
27486
|
+
modelId: detectedModelId,
|
|
27487
|
+
override: {
|
|
27488
|
+
gpuType: modelCost?.gpuType,
|
|
27489
|
+
gpuCount: modelCost?.gpuCount
|
|
27490
|
+
}
|
|
27491
|
+
});
|
|
27492
|
+
const overrides = args.config?.models?.gpuRates;
|
|
27493
|
+
let rate;
|
|
27494
|
+
let source;
|
|
27495
|
+
if (typeof modelCost?.hourlyRate === "number" && modelCost.hourlyRate >= 0) {
|
|
27496
|
+
rate = modelCost.hourlyRate;
|
|
27497
|
+
source = "model-override";
|
|
27498
|
+
} else if (breakdown.gpu.gpuType) {
|
|
27499
|
+
rate = resolveHourlyRate(breakdown.gpu.gpuType, overrides);
|
|
27500
|
+
if (rate !== void 0) source = overrides && breakdown.gpu.gpuType in overrides ? "config-override" : "default-table";
|
|
27501
|
+
}
|
|
27502
|
+
breakdown.hourlyRate = rate;
|
|
27503
|
+
breakdown.hourlyRateSource = source;
|
|
27504
|
+
if (breakdown.gpu?.gpuType) {
|
|
27505
|
+
const observed = breakdown.serving?.observedTps;
|
|
27506
|
+
if (typeof observed === "number" && observed > .5) {
|
|
27507
|
+
breakdown.decodeTps = observed;
|
|
27508
|
+
breakdown.prefillTps = observed * PREFILL_DECODE_RATIO;
|
|
27509
|
+
breakdown.throughputSource = "observed";
|
|
27510
|
+
} else {
|
|
27511
|
+
const decode = resolveDefaultDecodeTps(breakdown.gpu.gpuType, breakdown.gpu.paramsB, breakdown.gpu.bytesPerParam);
|
|
27512
|
+
breakdown.decodeTps = decode;
|
|
27513
|
+
breakdown.prefillTps = decode * PREFILL_DECODE_RATIO;
|
|
27514
|
+
breakdown.throughputSource = "default-table";
|
|
27515
|
+
}
|
|
27516
|
+
}
|
|
27517
|
+
if (args.usage && breakdown.hourlyRate !== void 0 && breakdown.gpu?.gpuType && breakdown.decodeTps !== void 0 && breakdown.prefillTps !== void 0) {
|
|
27518
|
+
const perSecond = breakdown.hourlyRate * breakdown.gpu.gpuCount / 3600;
|
|
27519
|
+
const inputTokens = args.usage.input ?? 0;
|
|
27520
|
+
const outputTokens = args.usage.output ?? 0;
|
|
27521
|
+
const totalCost = ((breakdown.prefillTps > 0 ? inputTokens / breakdown.prefillTps : 0) + (breakdown.decodeTps > 0 ? outputTokens / breakdown.decodeTps : 0)) * perSecond;
|
|
27522
|
+
breakdown.instanceCostUsd = totalCost;
|
|
27523
|
+
const totalTokens = inputTokens + outputTokens;
|
|
27524
|
+
if (totalTokens > 0) breakdown.perTokenAvgUsd = totalCost / totalTokens;
|
|
27525
|
+
}
|
|
27526
|
+
if (args.usage) {
|
|
27527
|
+
const costForEstimate = modelCost ? {
|
|
27528
|
+
input: modelCost.input ?? 0,
|
|
27529
|
+
output: modelCost.output ?? 0,
|
|
27530
|
+
cacheRead: modelCost.cacheRead ?? 0,
|
|
27531
|
+
cacheWrite: modelCost.cacheWrite ?? 0
|
|
27532
|
+
} : void 0;
|
|
27533
|
+
const rawCost = estimateUsageCost({
|
|
27534
|
+
usage: args.usage,
|
|
27535
|
+
cost: costForEstimate
|
|
27536
|
+
});
|
|
27537
|
+
if (typeof rawCost === "number" && rawCost > 0) breakdown.effectiveCostUsd = rawCost;
|
|
27538
|
+
else if (breakdown.instanceCostUsd !== void 0) breakdown.effectiveCostUsd = breakdown.instanceCostUsd;
|
|
27539
|
+
if (benchmarkTarget !== "none" && breakdown.effectiveCostUsd !== void 0) {
|
|
27540
|
+
breakdown.benchmarks = benchmarkUsage({
|
|
27541
|
+
usage: args.usage,
|
|
27542
|
+
target: benchmarkTarget
|
|
27543
|
+
});
|
|
27544
|
+
breakdown.costLineSuffix = formatBenchmarkSuffix({
|
|
27545
|
+
ourCostUsd: breakdown.effectiveCostUsd,
|
|
27546
|
+
benchmarks: breakdown.benchmarks
|
|
27547
|
+
});
|
|
27548
|
+
}
|
|
27549
|
+
}
|
|
27550
|
+
breakdown.hardwareLine = formatHardwareLine(breakdown);
|
|
27551
|
+
return breakdown;
|
|
27552
|
+
}
|
|
27553
|
+
function resolveModelCost(config, provider, modelId) {
|
|
27554
|
+
if (!config || !provider || !modelId) return;
|
|
27555
|
+
const providers = config.models?.providers;
|
|
27556
|
+
if (!providers) return;
|
|
27557
|
+
const providerCfg = providers[provider];
|
|
27558
|
+
if (!providerCfg?.models) return;
|
|
27559
|
+
return providerCfg.models.find((m) => m.id === modelId)?.cost;
|
|
27560
|
+
}
|
|
27561
|
+
function formatHardwareLine(breakdown) {
|
|
27562
|
+
const gpu = breakdown.gpu;
|
|
27563
|
+
if (!gpu?.gpuType) return;
|
|
27564
|
+
const label = GPU_LABEL[gpu.gpuType];
|
|
27565
|
+
const count = gpu.gpuCount;
|
|
27566
|
+
const parts = [];
|
|
27567
|
+
parts.push(`${count}× ${label}`);
|
|
27568
|
+
if (typeof breakdown.hourlyRate === "number") parts.push(`≈ $${(breakdown.hourlyRate * count).toFixed(2)}/hr`);
|
|
27569
|
+
const tag = (() => {
|
|
27570
|
+
if (breakdown.hourlyRateSource === "model-override") return "model override";
|
|
27571
|
+
if (breakdown.hourlyRateSource === "config-override") return "config override";
|
|
27572
|
+
if (gpu.confidence === "high") return "inferred";
|
|
27573
|
+
if (gpu.confidence === "medium") return "inferred · medium-conf";
|
|
27574
|
+
return "inferred · low-conf";
|
|
27575
|
+
})();
|
|
27576
|
+
parts.push(`(${tag})`);
|
|
27577
|
+
return `🧰 ${parts.join(" · ")}`;
|
|
27578
|
+
}
|
|
27579
|
+
|
|
26420
27580
|
//#endregion
|
|
26421
27581
|
//#region src/infra/provider-usage.shared.ts
|
|
26422
27582
|
const DEFAULT_TIMEOUT_MS = 5e3;
|
|
@@ -27620,6 +28780,32 @@ async function buildStatusReply(params) {
|
|
|
27620
28780
|
} catch {
|
|
27621
28781
|
usageLine = null;
|
|
27622
28782
|
}
|
|
28783
|
+
const baseUrl = cfg.models?.providers?.[provider]?.baseUrl;
|
|
28784
|
+
let engineLine;
|
|
28785
|
+
let hardwareLine;
|
|
28786
|
+
let costOverrideUsd;
|
|
28787
|
+
let costLineSuffix;
|
|
28788
|
+
try {
|
|
28789
|
+
const breakdown = await buildCostBreakdown({
|
|
28790
|
+
baseUrl,
|
|
28791
|
+
provider,
|
|
28792
|
+
modelId: model,
|
|
28793
|
+
config: cfg,
|
|
28794
|
+
usage: {
|
|
28795
|
+
input: sessionEntry?.inputTokens,
|
|
28796
|
+
output: sessionEntry?.outputTokens
|
|
28797
|
+
}
|
|
28798
|
+
});
|
|
28799
|
+
engineLine = breakdown.engineLine;
|
|
28800
|
+
hardwareLine = breakdown.hardwareLine;
|
|
28801
|
+
costOverrideUsd = breakdown.instanceCostUsd;
|
|
28802
|
+
costLineSuffix = breakdown.costLineSuffix;
|
|
28803
|
+
} catch {
|
|
28804
|
+
engineLine = void 0;
|
|
28805
|
+
hardwareLine = void 0;
|
|
28806
|
+
costOverrideUsd = void 0;
|
|
28807
|
+
costLineSuffix = void 0;
|
|
28808
|
+
}
|
|
27623
28809
|
const queueSettings = resolveQueueSettings({
|
|
27624
28810
|
cfg,
|
|
27625
28811
|
channel: command.channel,
|
|
@@ -27702,6 +28888,10 @@ async function buildStatusReply(params) {
|
|
|
27702
28888
|
showDetails: queueOverrides
|
|
27703
28889
|
},
|
|
27704
28890
|
subagentsLine,
|
|
28891
|
+
engineLine,
|
|
28892
|
+
hardwareLine,
|
|
28893
|
+
costOverrideUsd,
|
|
28894
|
+
costLineSuffix,
|
|
27705
28895
|
mediaDecisions: params.mediaDecisions,
|
|
27706
28896
|
includeTranscriptUsage: false
|
|
27707
28897
|
}) };
|
|
@@ -27802,6 +28992,27 @@ const handleStatusCommand = async (params, allowTextCommands) => {
|
|
|
27802
28992
|
})
|
|
27803
28993
|
};
|
|
27804
28994
|
};
|
|
28995
|
+
const handleCostCommand = async (params, allowTextCommands) => {
|
|
28996
|
+
if (!allowTextCommands) return null;
|
|
28997
|
+
const normalized = params.command.commandBodyNormalized;
|
|
28998
|
+
if (normalized !== "/cost" && !normalized.startsWith("/cost ")) return null;
|
|
28999
|
+
if (!params.command.isAuthorizedSender) {
|
|
29000
|
+
logVerbose(`Ignoring /cost from unauthorized sender: ${params.command.senderId || "<unknown>"}`);
|
|
29001
|
+
return { shouldContinue: false };
|
|
29002
|
+
}
|
|
29003
|
+
const arg = normalized.slice(5).trim();
|
|
29004
|
+
const window = arg === "today" || arg === "week" || arg === "month" || arg === "all" ? arg : "week";
|
|
29005
|
+
const { startMs, endMs } = resolveWindow(window);
|
|
29006
|
+
return {
|
|
29007
|
+
shouldContinue: false,
|
|
29008
|
+
reply: { text: formatSummaryReport(await loadCostBenchmarkSummary({
|
|
29009
|
+
startMs,
|
|
29010
|
+
endMs,
|
|
29011
|
+
config: params.cfg,
|
|
29012
|
+
agentId: params.agentId
|
|
29013
|
+
}), `${window.charAt(0).toUpperCase()}${window.slice(1)}`) }
|
|
29014
|
+
};
|
|
29015
|
+
};
|
|
27805
29016
|
const handleContextCommand = async (params, allowTextCommands) => {
|
|
27806
29017
|
if (!allowTextCommands) return null;
|
|
27807
29018
|
const normalized = params.command.commandBodyNormalized;
|
|
@@ -28198,411 +29409,6 @@ function scheduleGatewaySigusr1Restart(opts) {
|
|
|
28198
29409
|
};
|
|
28199
29410
|
}
|
|
28200
29411
|
|
|
28201
|
-
//#endregion
|
|
28202
|
-
//#region src/infra/session-cost-usage.ts
|
|
28203
|
-
const emptyTotals = () => ({
|
|
28204
|
-
input: 0,
|
|
28205
|
-
output: 0,
|
|
28206
|
-
cacheRead: 0,
|
|
28207
|
-
cacheWrite: 0,
|
|
28208
|
-
totalTokens: 0,
|
|
28209
|
-
totalCost: 0,
|
|
28210
|
-
inputCost: 0,
|
|
28211
|
-
outputCost: 0,
|
|
28212
|
-
cacheReadCost: 0,
|
|
28213
|
-
cacheWriteCost: 0,
|
|
28214
|
-
missingCostEntries: 0
|
|
28215
|
-
});
|
|
28216
|
-
const toFiniteNumber = (value) => {
|
|
28217
|
-
if (typeof value !== "number") return;
|
|
28218
|
-
if (!Number.isFinite(value)) return;
|
|
28219
|
-
return value;
|
|
28220
|
-
};
|
|
28221
|
-
const extractCostBreakdown = (usageRaw) => {
|
|
28222
|
-
if (!usageRaw || typeof usageRaw !== "object") return;
|
|
28223
|
-
const cost = usageRaw.cost;
|
|
28224
|
-
if (!cost) return;
|
|
28225
|
-
const total = toFiniteNumber(cost.total);
|
|
28226
|
-
if (total === void 0 || total < 0) return;
|
|
28227
|
-
return {
|
|
28228
|
-
total,
|
|
28229
|
-
input: toFiniteNumber(cost.input),
|
|
28230
|
-
output: toFiniteNumber(cost.output),
|
|
28231
|
-
cacheRead: toFiniteNumber(cost.cacheRead),
|
|
28232
|
-
cacheWrite: toFiniteNumber(cost.cacheWrite)
|
|
28233
|
-
};
|
|
28234
|
-
};
|
|
28235
|
-
const parseTimestamp = (entry) => {
|
|
28236
|
-
const raw = entry.timestamp;
|
|
28237
|
-
if (typeof raw === "string") {
|
|
28238
|
-
const parsed = new Date(raw);
|
|
28239
|
-
if (!Number.isNaN(parsed.valueOf())) return parsed;
|
|
28240
|
-
}
|
|
28241
|
-
const message = entry.message;
|
|
28242
|
-
const messageTimestamp = toFiniteNumber(message?.timestamp);
|
|
28243
|
-
if (messageTimestamp !== void 0) {
|
|
28244
|
-
const parsed = new Date(messageTimestamp);
|
|
28245
|
-
if (!Number.isNaN(parsed.valueOf())) return parsed;
|
|
28246
|
-
}
|
|
28247
|
-
};
|
|
28248
|
-
const parseTranscriptEntry = (entry) => {
|
|
28249
|
-
const message = entry.message;
|
|
28250
|
-
if (!message || typeof message !== "object") return null;
|
|
28251
|
-
const roleRaw = message.role;
|
|
28252
|
-
const role = roleRaw === "user" || roleRaw === "assistant" ? roleRaw : void 0;
|
|
28253
|
-
if (!role) return null;
|
|
28254
|
-
const usageRaw = message.usage ?? entry.usage;
|
|
28255
|
-
const usage = usageRaw ? normalizeUsage(usageRaw) ?? void 0 : void 0;
|
|
28256
|
-
const provider = (typeof message.provider === "string" ? message.provider : void 0) ?? (typeof entry.provider === "string" ? entry.provider : void 0);
|
|
28257
|
-
const model = (typeof message.model === "string" ? message.model : void 0) ?? (typeof entry.model === "string" ? entry.model : void 0);
|
|
28258
|
-
const costBreakdown = extractCostBreakdown(usageRaw);
|
|
28259
|
-
const stopReason = typeof message.stopReason === "string" ? message.stopReason : void 0;
|
|
28260
|
-
const durationMs = toFiniteNumber(message.durationMs ?? entry.durationMs);
|
|
28261
|
-
return {
|
|
28262
|
-
message,
|
|
28263
|
-
role,
|
|
28264
|
-
timestamp: parseTimestamp(entry),
|
|
28265
|
-
durationMs,
|
|
28266
|
-
usage,
|
|
28267
|
-
costTotal: costBreakdown?.total,
|
|
28268
|
-
costBreakdown,
|
|
28269
|
-
provider,
|
|
28270
|
-
model,
|
|
28271
|
-
stopReason,
|
|
28272
|
-
toolNames: extractToolCallNames(message),
|
|
28273
|
-
toolResultCounts: countToolResults(message)
|
|
28274
|
-
};
|
|
28275
|
-
};
|
|
28276
|
-
const formatDayKey = (date) => date.toLocaleDateString("en-CA", { timeZone: Intl.DateTimeFormat().resolvedOptions().timeZone });
|
|
28277
|
-
const computeLatencyStats = (values) => {
|
|
28278
|
-
if (!values.length) return;
|
|
28279
|
-
const sorted = values.toSorted((a, b) => a - b);
|
|
28280
|
-
const total = sorted.reduce((sum, v) => sum + v, 0);
|
|
28281
|
-
const count = sorted.length;
|
|
28282
|
-
const p95Index = Math.max(0, Math.ceil(count * .95) - 1);
|
|
28283
|
-
return {
|
|
28284
|
-
count,
|
|
28285
|
-
avgMs: total / count,
|
|
28286
|
-
p95Ms: sorted[p95Index] ?? sorted[count - 1],
|
|
28287
|
-
minMs: sorted[0],
|
|
28288
|
-
maxMs: sorted[count - 1]
|
|
28289
|
-
};
|
|
28290
|
-
};
|
|
28291
|
-
const applyUsageTotals = (totals, usage) => {
|
|
28292
|
-
totals.input += usage.input ?? 0;
|
|
28293
|
-
totals.output += usage.output ?? 0;
|
|
28294
|
-
totals.cacheRead += usage.cacheRead ?? 0;
|
|
28295
|
-
totals.cacheWrite += usage.cacheWrite ?? 0;
|
|
28296
|
-
const totalTokens = usage.total ?? (usage.input ?? 0) + (usage.output ?? 0) + (usage.cacheRead ?? 0) + (usage.cacheWrite ?? 0);
|
|
28297
|
-
totals.totalTokens += totalTokens;
|
|
28298
|
-
};
|
|
28299
|
-
const applyCostBreakdown = (totals, costBreakdown) => {
|
|
28300
|
-
if (costBreakdown === void 0 || costBreakdown.total === void 0) return;
|
|
28301
|
-
totals.totalCost += costBreakdown.total;
|
|
28302
|
-
totals.inputCost += costBreakdown.input ?? 0;
|
|
28303
|
-
totals.outputCost += costBreakdown.output ?? 0;
|
|
28304
|
-
totals.cacheReadCost += costBreakdown.cacheRead ?? 0;
|
|
28305
|
-
totals.cacheWriteCost += costBreakdown.cacheWrite ?? 0;
|
|
28306
|
-
};
|
|
28307
|
-
const applyCostTotal = (totals, costTotal) => {
|
|
28308
|
-
if (costTotal === void 0) {
|
|
28309
|
-
totals.missingCostEntries += 1;
|
|
28310
|
-
return;
|
|
28311
|
-
}
|
|
28312
|
-
totals.totalCost += costTotal;
|
|
28313
|
-
};
|
|
28314
|
-
async function* readJsonlRecords(filePath) {
|
|
28315
|
-
const fileStream = fs.createReadStream(filePath, { encoding: "utf-8" });
|
|
28316
|
-
const rl = readline.createInterface({
|
|
28317
|
-
input: fileStream,
|
|
28318
|
-
crlfDelay: Infinity
|
|
28319
|
-
});
|
|
28320
|
-
try {
|
|
28321
|
-
for await (const line of rl) {
|
|
28322
|
-
const trimmed = line.trim();
|
|
28323
|
-
if (!trimmed) continue;
|
|
28324
|
-
try {
|
|
28325
|
-
const parsed = JSON.parse(trimmed);
|
|
28326
|
-
if (!parsed || typeof parsed !== "object") continue;
|
|
28327
|
-
yield parsed;
|
|
28328
|
-
} catch {}
|
|
28329
|
-
}
|
|
28330
|
-
} finally {
|
|
28331
|
-
rl.close();
|
|
28332
|
-
fileStream.destroy();
|
|
28333
|
-
}
|
|
28334
|
-
}
|
|
28335
|
-
async function scanTranscriptFile(params) {
|
|
28336
|
-
for await (const parsed of readJsonlRecords(params.filePath)) {
|
|
28337
|
-
const entry = parseTranscriptEntry(parsed);
|
|
28338
|
-
if (!entry) continue;
|
|
28339
|
-
if (entry.usage && entry.costTotal === void 0) {
|
|
28340
|
-
const cost = resolveModelCostConfig({
|
|
28341
|
-
provider: entry.provider,
|
|
28342
|
-
model: entry.model,
|
|
28343
|
-
config: params.config
|
|
28344
|
-
});
|
|
28345
|
-
entry.costTotal = estimateUsageCost({
|
|
28346
|
-
usage: entry.usage,
|
|
28347
|
-
cost
|
|
28348
|
-
});
|
|
28349
|
-
}
|
|
28350
|
-
params.onEntry(entry);
|
|
28351
|
-
}
|
|
28352
|
-
}
|
|
28353
|
-
async function scanUsageFile(params) {
|
|
28354
|
-
await scanTranscriptFile({
|
|
28355
|
-
filePath: params.filePath,
|
|
28356
|
-
config: params.config,
|
|
28357
|
-
onEntry: (entry) => {
|
|
28358
|
-
if (!entry.usage) return;
|
|
28359
|
-
params.onEntry({
|
|
28360
|
-
usage: entry.usage,
|
|
28361
|
-
costTotal: entry.costTotal,
|
|
28362
|
-
costBreakdown: entry.costBreakdown,
|
|
28363
|
-
provider: entry.provider,
|
|
28364
|
-
model: entry.model,
|
|
28365
|
-
timestamp: entry.timestamp
|
|
28366
|
-
});
|
|
28367
|
-
}
|
|
28368
|
-
});
|
|
28369
|
-
}
|
|
28370
|
-
async function loadCostUsageSummary(params) {
|
|
28371
|
-
const now = /* @__PURE__ */ new Date();
|
|
28372
|
-
let sinceTime;
|
|
28373
|
-
let untilTime;
|
|
28374
|
-
if (params?.startMs !== void 0 && params?.endMs !== void 0) {
|
|
28375
|
-
sinceTime = params.startMs;
|
|
28376
|
-
untilTime = params.endMs;
|
|
28377
|
-
} else {
|
|
28378
|
-
const days = Math.max(1, Math.floor(params?.days ?? 30));
|
|
28379
|
-
const since = new Date(now);
|
|
28380
|
-
since.setDate(since.getDate() - (days - 1));
|
|
28381
|
-
sinceTime = since.getTime();
|
|
28382
|
-
untilTime = now.getTime();
|
|
28383
|
-
}
|
|
28384
|
-
const dailyMap = /* @__PURE__ */ new Map();
|
|
28385
|
-
const totals = emptyTotals();
|
|
28386
|
-
const sessionsDir = resolveSessionTranscriptsDirForAgent(params?.agentId);
|
|
28387
|
-
const entries = await fs.promises.readdir(sessionsDir, { withFileTypes: true }).catch(() => []);
|
|
28388
|
-
const files = (await Promise.all(entries.filter((entry) => entry.isFile() && entry.name.endsWith(".jsonl")).map(async (entry) => {
|
|
28389
|
-
const filePath = path.join(sessionsDir, entry.name);
|
|
28390
|
-
const stats = await fs.promises.stat(filePath).catch(() => null);
|
|
28391
|
-
if (!stats) return null;
|
|
28392
|
-
if (stats.mtimeMs < sinceTime) return null;
|
|
28393
|
-
return filePath;
|
|
28394
|
-
}))).filter((filePath) => Boolean(filePath));
|
|
28395
|
-
for (const filePath of files) await scanUsageFile({
|
|
28396
|
-
filePath,
|
|
28397
|
-
config: params?.config,
|
|
28398
|
-
onEntry: (entry) => {
|
|
28399
|
-
const ts = entry.timestamp?.getTime();
|
|
28400
|
-
if (!ts || ts < sinceTime || ts > untilTime) return;
|
|
28401
|
-
const dayKey = formatDayKey(entry.timestamp ?? now);
|
|
28402
|
-
const bucket = dailyMap.get(dayKey) ?? emptyTotals();
|
|
28403
|
-
applyUsageTotals(bucket, entry.usage);
|
|
28404
|
-
if (entry.costBreakdown?.total !== void 0) applyCostBreakdown(bucket, entry.costBreakdown);
|
|
28405
|
-
else applyCostTotal(bucket, entry.costTotal);
|
|
28406
|
-
dailyMap.set(dayKey, bucket);
|
|
28407
|
-
applyUsageTotals(totals, entry.usage);
|
|
28408
|
-
if (entry.costBreakdown?.total !== void 0) applyCostBreakdown(totals, entry.costBreakdown);
|
|
28409
|
-
else applyCostTotal(totals, entry.costTotal);
|
|
28410
|
-
}
|
|
28411
|
-
});
|
|
28412
|
-
const daily = Array.from(dailyMap.entries()).map(([date, bucket]) => Object.assign({ date }, bucket)).toSorted((a, b) => a.date.localeCompare(b.date));
|
|
28413
|
-
const days = Math.ceil((untilTime - sinceTime) / (1440 * 60 * 1e3)) + 1;
|
|
28414
|
-
return {
|
|
28415
|
-
updatedAt: Date.now(),
|
|
28416
|
-
days,
|
|
28417
|
-
daily,
|
|
28418
|
-
totals
|
|
28419
|
-
};
|
|
28420
|
-
}
|
|
28421
|
-
async function loadSessionCostSummary(params) {
|
|
28422
|
-
const sessionFile = params.sessionFile ?? (params.sessionId ? resolveSessionFilePath(params.sessionId, params.sessionEntry, { agentId: params.agentId }) : void 0);
|
|
28423
|
-
if (!sessionFile || !fs.existsSync(sessionFile)) return null;
|
|
28424
|
-
const totals = emptyTotals();
|
|
28425
|
-
let firstActivity;
|
|
28426
|
-
let lastActivity;
|
|
28427
|
-
const activityDatesSet = /* @__PURE__ */ new Set();
|
|
28428
|
-
const dailyMap = /* @__PURE__ */ new Map();
|
|
28429
|
-
const dailyMessageMap = /* @__PURE__ */ new Map();
|
|
28430
|
-
const dailyLatencyMap = /* @__PURE__ */ new Map();
|
|
28431
|
-
const dailyModelUsageMap = /* @__PURE__ */ new Map();
|
|
28432
|
-
const messageCounts = {
|
|
28433
|
-
total: 0,
|
|
28434
|
-
user: 0,
|
|
28435
|
-
assistant: 0,
|
|
28436
|
-
toolCalls: 0,
|
|
28437
|
-
toolResults: 0,
|
|
28438
|
-
errors: 0
|
|
28439
|
-
};
|
|
28440
|
-
const toolUsageMap = /* @__PURE__ */ new Map();
|
|
28441
|
-
const modelUsageMap = /* @__PURE__ */ new Map();
|
|
28442
|
-
const errorStopReasons = new Set([
|
|
28443
|
-
"error",
|
|
28444
|
-
"aborted",
|
|
28445
|
-
"timeout"
|
|
28446
|
-
]);
|
|
28447
|
-
const latencyValues = [];
|
|
28448
|
-
let lastUserTimestamp;
|
|
28449
|
-
const MAX_LATENCY_MS = 720 * 60 * 1e3;
|
|
28450
|
-
await scanTranscriptFile({
|
|
28451
|
-
filePath: sessionFile,
|
|
28452
|
-
config: params.config,
|
|
28453
|
-
onEntry: (entry) => {
|
|
28454
|
-
const ts = entry.timestamp?.getTime();
|
|
28455
|
-
if (params.startMs !== void 0 && ts !== void 0 && ts < params.startMs) return;
|
|
28456
|
-
if (params.endMs !== void 0 && ts !== void 0 && ts > params.endMs) return;
|
|
28457
|
-
if (ts !== void 0) {
|
|
28458
|
-
if (!firstActivity || ts < firstActivity) firstActivity = ts;
|
|
28459
|
-
if (!lastActivity || ts > lastActivity) lastActivity = ts;
|
|
28460
|
-
}
|
|
28461
|
-
if (entry.role === "user") {
|
|
28462
|
-
messageCounts.user += 1;
|
|
28463
|
-
messageCounts.total += 1;
|
|
28464
|
-
if (entry.timestamp) lastUserTimestamp = entry.timestamp.getTime();
|
|
28465
|
-
}
|
|
28466
|
-
if (entry.role === "assistant") {
|
|
28467
|
-
messageCounts.assistant += 1;
|
|
28468
|
-
messageCounts.total += 1;
|
|
28469
|
-
const ts = entry.timestamp?.getTime();
|
|
28470
|
-
if (ts !== void 0) {
|
|
28471
|
-
const latencyMs = entry.durationMs ?? (lastUserTimestamp !== void 0 ? Math.max(0, ts - lastUserTimestamp) : void 0);
|
|
28472
|
-
if (latencyMs !== void 0 && Number.isFinite(latencyMs) && latencyMs <= MAX_LATENCY_MS) {
|
|
28473
|
-
latencyValues.push(latencyMs);
|
|
28474
|
-
const dayKey = formatDayKey(entry.timestamp ?? new Date(ts));
|
|
28475
|
-
const dailyLatencies = dailyLatencyMap.get(dayKey) ?? [];
|
|
28476
|
-
dailyLatencies.push(latencyMs);
|
|
28477
|
-
dailyLatencyMap.set(dayKey, dailyLatencies);
|
|
28478
|
-
}
|
|
28479
|
-
}
|
|
28480
|
-
}
|
|
28481
|
-
if (entry.toolNames.length > 0) {
|
|
28482
|
-
messageCounts.toolCalls += entry.toolNames.length;
|
|
28483
|
-
for (const name of entry.toolNames) toolUsageMap.set(name, (toolUsageMap.get(name) ?? 0) + 1);
|
|
28484
|
-
}
|
|
28485
|
-
if (entry.toolResultCounts.total > 0) {
|
|
28486
|
-
messageCounts.toolResults += entry.toolResultCounts.total;
|
|
28487
|
-
messageCounts.errors += entry.toolResultCounts.errors;
|
|
28488
|
-
}
|
|
28489
|
-
if (entry.stopReason && errorStopReasons.has(entry.stopReason)) messageCounts.errors += 1;
|
|
28490
|
-
if (entry.timestamp) {
|
|
28491
|
-
const dayKey = formatDayKey(entry.timestamp);
|
|
28492
|
-
activityDatesSet.add(dayKey);
|
|
28493
|
-
const daily = dailyMessageMap.get(dayKey) ?? {
|
|
28494
|
-
date: dayKey,
|
|
28495
|
-
total: 0,
|
|
28496
|
-
user: 0,
|
|
28497
|
-
assistant: 0,
|
|
28498
|
-
toolCalls: 0,
|
|
28499
|
-
toolResults: 0,
|
|
28500
|
-
errors: 0
|
|
28501
|
-
};
|
|
28502
|
-
daily.total += entry.role === "user" || entry.role === "assistant" ? 1 : 0;
|
|
28503
|
-
if (entry.role === "user") daily.user += 1;
|
|
28504
|
-
else if (entry.role === "assistant") daily.assistant += 1;
|
|
28505
|
-
daily.toolCalls += entry.toolNames.length;
|
|
28506
|
-
daily.toolResults += entry.toolResultCounts.total;
|
|
28507
|
-
daily.errors += entry.toolResultCounts.errors;
|
|
28508
|
-
if (entry.stopReason && errorStopReasons.has(entry.stopReason)) daily.errors += 1;
|
|
28509
|
-
dailyMessageMap.set(dayKey, daily);
|
|
28510
|
-
}
|
|
28511
|
-
if (!entry.usage) return;
|
|
28512
|
-
applyUsageTotals(totals, entry.usage);
|
|
28513
|
-
if (entry.costBreakdown?.total !== void 0) applyCostBreakdown(totals, entry.costBreakdown);
|
|
28514
|
-
else applyCostTotal(totals, entry.costTotal);
|
|
28515
|
-
if (entry.timestamp) {
|
|
28516
|
-
const dayKey = formatDayKey(entry.timestamp);
|
|
28517
|
-
const entryTokens = (entry.usage.input ?? 0) + (entry.usage.output ?? 0) + (entry.usage.cacheRead ?? 0) + (entry.usage.cacheWrite ?? 0);
|
|
28518
|
-
const entryCost = entry.costBreakdown?.total ?? (entry.costBreakdown ? (entry.costBreakdown.input ?? 0) + (entry.costBreakdown.output ?? 0) + (entry.costBreakdown.cacheRead ?? 0) + (entry.costBreakdown.cacheWrite ?? 0) : entry.costTotal ?? 0);
|
|
28519
|
-
const existing = dailyMap.get(dayKey) ?? {
|
|
28520
|
-
tokens: 0,
|
|
28521
|
-
cost: 0
|
|
28522
|
-
};
|
|
28523
|
-
dailyMap.set(dayKey, {
|
|
28524
|
-
tokens: existing.tokens + entryTokens,
|
|
28525
|
-
cost: existing.cost + entryCost
|
|
28526
|
-
});
|
|
28527
|
-
if (entry.provider || entry.model) {
|
|
28528
|
-
const modelKey = `${dayKey}::${entry.provider ?? "unknown"}::${entry.model ?? "unknown"}`;
|
|
28529
|
-
const dailyModel = dailyModelUsageMap.get(modelKey) ?? {
|
|
28530
|
-
date: dayKey,
|
|
28531
|
-
provider: entry.provider,
|
|
28532
|
-
model: entry.model,
|
|
28533
|
-
tokens: 0,
|
|
28534
|
-
cost: 0,
|
|
28535
|
-
count: 0
|
|
28536
|
-
};
|
|
28537
|
-
dailyModel.tokens += entryTokens;
|
|
28538
|
-
dailyModel.cost += entryCost;
|
|
28539
|
-
dailyModel.count += 1;
|
|
28540
|
-
dailyModelUsageMap.set(modelKey, dailyModel);
|
|
28541
|
-
}
|
|
28542
|
-
}
|
|
28543
|
-
if (entry.provider || entry.model) {
|
|
28544
|
-
const key = `${entry.provider ?? "unknown"}::${entry.model ?? "unknown"}`;
|
|
28545
|
-
const existing = modelUsageMap.get(key) ?? {
|
|
28546
|
-
provider: entry.provider,
|
|
28547
|
-
model: entry.model,
|
|
28548
|
-
count: 0,
|
|
28549
|
-
totals: emptyTotals()
|
|
28550
|
-
};
|
|
28551
|
-
existing.count += 1;
|
|
28552
|
-
applyUsageTotals(existing.totals, entry.usage);
|
|
28553
|
-
if (entry.costBreakdown?.total !== void 0) applyCostBreakdown(existing.totals, entry.costBreakdown);
|
|
28554
|
-
else applyCostTotal(existing.totals, entry.costTotal);
|
|
28555
|
-
modelUsageMap.set(key, existing);
|
|
28556
|
-
}
|
|
28557
|
-
}
|
|
28558
|
-
});
|
|
28559
|
-
const dailyBreakdown = Array.from(dailyMap.entries()).map(([date, data]) => ({
|
|
28560
|
-
date,
|
|
28561
|
-
tokens: data.tokens,
|
|
28562
|
-
cost: data.cost
|
|
28563
|
-
})).toSorted((a, b) => a.date.localeCompare(b.date));
|
|
28564
|
-
const dailyMessageCounts = Array.from(dailyMessageMap.values()).toSorted((a, b) => a.date.localeCompare(b.date));
|
|
28565
|
-
const dailyLatency = Array.from(dailyLatencyMap.entries()).map(([date, values]) => {
|
|
28566
|
-
const stats = computeLatencyStats(values);
|
|
28567
|
-
if (!stats) return null;
|
|
28568
|
-
return {
|
|
28569
|
-
date,
|
|
28570
|
-
...stats
|
|
28571
|
-
};
|
|
28572
|
-
}).filter((entry) => Boolean(entry)).toSorted((a, b) => a.date.localeCompare(b.date));
|
|
28573
|
-
const dailyModelUsage = Array.from(dailyModelUsageMap.values()).toSorted((a, b) => a.date.localeCompare(b.date) || b.cost - a.cost);
|
|
28574
|
-
const toolUsage = toolUsageMap.size ? {
|
|
28575
|
-
totalCalls: Array.from(toolUsageMap.values()).reduce((sum, count) => sum + count, 0),
|
|
28576
|
-
uniqueTools: toolUsageMap.size,
|
|
28577
|
-
tools: Array.from(toolUsageMap.entries()).map(([name, count]) => ({
|
|
28578
|
-
name,
|
|
28579
|
-
count
|
|
28580
|
-
})).toSorted((a, b) => b.count - a.count)
|
|
28581
|
-
} : void 0;
|
|
28582
|
-
const modelUsage = modelUsageMap.size ? Array.from(modelUsageMap.values()).toSorted((a, b) => {
|
|
28583
|
-
const costDiff = b.totals.totalCost - a.totals.totalCost;
|
|
28584
|
-
if (costDiff !== 0) return costDiff;
|
|
28585
|
-
return b.totals.totalTokens - a.totals.totalTokens;
|
|
28586
|
-
}) : void 0;
|
|
28587
|
-
return {
|
|
28588
|
-
sessionId: params.sessionId,
|
|
28589
|
-
sessionFile,
|
|
28590
|
-
firstActivity,
|
|
28591
|
-
lastActivity,
|
|
28592
|
-
durationMs: firstActivity !== void 0 && lastActivity !== void 0 ? Math.max(0, lastActivity - firstActivity) : void 0,
|
|
28593
|
-
activityDates: Array.from(activityDatesSet).toSorted(),
|
|
28594
|
-
dailyBreakdown,
|
|
28595
|
-
dailyMessageCounts,
|
|
28596
|
-
dailyLatency: dailyLatency.length ? dailyLatency : void 0,
|
|
28597
|
-
dailyModelUsage: dailyModelUsage.length ? dailyModelUsage : void 0,
|
|
28598
|
-
messageCounts,
|
|
28599
|
-
toolUsage,
|
|
28600
|
-
modelUsage,
|
|
28601
|
-
latency: computeLatencyStats(latencyValues),
|
|
28602
|
-
...totals
|
|
28603
|
-
};
|
|
28604
|
-
}
|
|
28605
|
-
|
|
28606
29412
|
//#endregion
|
|
28607
29413
|
//#region src/auto-reply/send-policy.ts
|
|
28608
29414
|
function normalizeSendPolicyOverride(raw) {
|
|
@@ -29802,6 +30608,7 @@ async function handleCommands(params) {
|
|
|
29802
30608
|
handleHelpCommand,
|
|
29803
30609
|
handleCommandsListCommand,
|
|
29804
30610
|
handleStatusCommand,
|
|
30611
|
+
handleCostCommand,
|
|
29805
30612
|
handleAllowlistCommand,
|
|
29806
30613
|
handleApproveCommand,
|
|
29807
30614
|
handleContextCommand,
|
|
@@ -37429,6 +38236,32 @@ function createSessionStatusTool(opts) {
|
|
|
37429
38236
|
}
|
|
37430
38237
|
} catch {}
|
|
37431
38238
|
const groupActivation = resolved.entry.chatType === "group" || resolved.entry.chatType === "channel" || resolved.key.includes(":group:") || resolved.key.includes(":channel:") ? normalizeGroupActivation(resolved.entry.groupActivation) ?? "mention" : void 0;
|
|
38239
|
+
const baseUrl = cfg.models?.providers?.[providerForCard]?.baseUrl;
|
|
38240
|
+
let engineLine;
|
|
38241
|
+
let hardwareLine;
|
|
38242
|
+
let costOverrideUsd;
|
|
38243
|
+
let costLineSuffix;
|
|
38244
|
+
try {
|
|
38245
|
+
const breakdown = await buildCostBreakdown({
|
|
38246
|
+
baseUrl,
|
|
38247
|
+
provider: providerForCard,
|
|
38248
|
+
modelId: configured.model,
|
|
38249
|
+
config: cfg,
|
|
38250
|
+
usage: {
|
|
38251
|
+
input: resolved.entry.inputTokens,
|
|
38252
|
+
output: resolved.entry.outputTokens
|
|
38253
|
+
}
|
|
38254
|
+
});
|
|
38255
|
+
engineLine = breakdown.engineLine;
|
|
38256
|
+
hardwareLine = breakdown.hardwareLine;
|
|
38257
|
+
costOverrideUsd = breakdown.instanceCostUsd;
|
|
38258
|
+
costLineSuffix = breakdown.costLineSuffix;
|
|
38259
|
+
} catch {
|
|
38260
|
+
engineLine = void 0;
|
|
38261
|
+
hardwareLine = void 0;
|
|
38262
|
+
costOverrideUsd = void 0;
|
|
38263
|
+
costLineSuffix = void 0;
|
|
38264
|
+
}
|
|
37432
38265
|
const queueSettings = resolveQueueSettings({
|
|
37433
38266
|
cfg,
|
|
37434
38267
|
channel: resolved.entry.channel ?? resolved.entry.lastChannel ?? "unknown",
|
|
@@ -37474,6 +38307,10 @@ function createSessionStatusTool(opts) {
|
|
|
37474
38307
|
dropPolicy: queueSettings.dropPolicy,
|
|
37475
38308
|
showDetails: queueOverrides
|
|
37476
38309
|
},
|
|
38310
|
+
engineLine,
|
|
38311
|
+
hardwareLine,
|
|
38312
|
+
costOverrideUsd,
|
|
38313
|
+
costLineSuffix,
|
|
37477
38314
|
includeTranscriptUsage: false
|
|
37478
38315
|
});
|
|
37479
38316
|
return {
|
|
@@ -41151,7 +41988,7 @@ async function deliverSessionMaintenanceWarning(params) {
|
|
|
41151
41988
|
return;
|
|
41152
41989
|
}
|
|
41153
41990
|
try {
|
|
41154
|
-
const { deliverOutboundPayloads } = await import("./deliver-
|
|
41991
|
+
const { deliverOutboundPayloads } = await import("./deliver-f3cIWxXT.js").then((n) => n.n);
|
|
41155
41992
|
await deliverOutboundPayloads({
|
|
41156
41993
|
cfg: params.cfg,
|
|
41157
41994
|
channel,
|
|
@@ -57931,7 +58768,7 @@ function readSlackExternalArgMenuToken(raw) {
|
|
|
57931
58768
|
}
|
|
57932
58769
|
let commandsRegistry;
|
|
57933
58770
|
async function getCommandsRegistry() {
|
|
57934
|
-
if (!commandsRegistry) commandsRegistry = await import("./commands-registry-
|
|
58771
|
+
if (!commandsRegistry) commandsRegistry = await import("./commands-registry-DG2kGyg5.js").then((n) => n.t);
|
|
57935
58772
|
return commandsRegistry;
|
|
57936
58773
|
}
|
|
57937
58774
|
function encodeSlackCommandArgValue(parts) {
|
|
@@ -58334,7 +59171,7 @@ async function registerSlackMonitorSlashCommands(params) {
|
|
|
58334
59171
|
});
|
|
58335
59172
|
const deliverSlashPayloads = async (replies) => {
|
|
58336
59173
|
const [{ deliverSlackSlashReplies }, { resolveChunkMode }, { resolveMarkdownTableMode }] = await Promise.all([
|
|
58337
|
-
import("./replies-
|
|
59174
|
+
import("./replies-0nzkXt6o.js").then((n) => n.r),
|
|
58338
59175
|
import("./chunk-CAZujdOi.js").then((n) => n.s),
|
|
58339
59176
|
import("./markdown-tables-jQzXAsf3.js").then((n) => n.t)
|
|
58340
59177
|
]);
|
|
@@ -58389,7 +59226,7 @@ async function registerSlackMonitorSlashCommands(params) {
|
|
|
58389
59226
|
let nativeCommands = [];
|
|
58390
59227
|
if (nativeEnabled) {
|
|
58391
59228
|
reg = await getCommandsRegistry();
|
|
58392
|
-
const skillCommands = nativeSkillsEnabled ? (await import("./skill-commands-
|
|
59229
|
+
const skillCommands = nativeSkillsEnabled ? (await import("./skill-commands-D0xAWG0l.js").then((n) => n.a)).listSkillCommandsForAgents({ cfg }) : [];
|
|
58393
59230
|
nativeCommands = reg.listNativeCommandSpecsForConfig(cfg, {
|
|
58394
59231
|
skillCommands,
|
|
58395
59232
|
provider: "slack"
|