@symerian/symi 3.5.4 → 3.5.6

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.
Files changed (413) hide show
  1. package/dist/{agent-Bl0Wfrd4.js → agent-BCszhl_7.js} +11 -11
  2. package/dist/{agent-BsRlH9Ez.js → agent-Cmx-1Tfs.js} +9 -9
  3. package/dist/{agents-Ch38fapn.js → agents-BkTzJJ83.js} +11 -11
  4. package/dist/{audit-CcxTZUi-.js → audit-Bk6kay2Z.js} +9 -9
  5. package/dist/{audit-CojL8qpM.js → audit-CtrXFZb5.js} +9 -9
  6. package/dist/{auth-choice-CQnJ5pRD.js → auth-choice-CucG4Wor.js} +8 -8
  7. package/dist/{auth-choice-O55PGflm.js → auth-choice-D-iIJjJY.js} +8 -8
  8. package/dist/{auth-choice-options-DfT-D0Cb.js → auth-choice-options-DmXqtnP9.js} +1 -1
  9. package/dist/{auth-choice-options-osb2GMd4.js → auth-choice-options-od_KpHe8.js} +1 -1
  10. package/dist/{auth-choice-prompt-6_u7zS1M.js → auth-choice-prompt-BnvC700A.js} +1 -1
  11. package/dist/{auth-choice-prompt-SCWccuw0.js → auth-choice-prompt-kt2FcieM.js} +1 -1
  12. package/dist/{auth-token-Dvw-1mFR.js → auth-token-DyhvQgv4.js} +1 -1
  13. package/dist/{auth-token-t_CY5BPB.js → auth-token-lPWiklDD.js} +1 -1
  14. package/dist/{banner-TDzek44y.js → banner-CApT91CY.js} +1 -1
  15. package/dist/{bonjour-discovery-BjSUj2V6.js → bonjour-discovery-CyLfNUkJ.js} +1 -1
  16. package/dist/{bonjour-discovery-FJyieAXp.js → bonjour-discovery-DuObXMh2.js} +1 -1
  17. package/dist/breakdown-B_Dhhm3K.js +753 -0
  18. package/dist/breakdown-Cszrv-Lf.js +753 -0
  19. package/dist/{browser-cli-BXH0KbhG.js → browser-cli-DGjYBquX.js} +9 -9
  20. package/dist/{browser-cli-UZqxfaV_.js → browser-cli-rZb2WjFF.js} +9 -9
  21. package/dist/build-info.json +3 -3
  22. package/dist/bundled/boot-md/handler.js +10 -10
  23. package/dist/bundled/session-memory/handler.js +9 -9
  24. package/dist/{call-CKm3T_ar.js → call-DKQC0JT1.js} +1 -1
  25. package/dist/{call-DrkOiHjS.js → call-ogggp9QZ.js} +1 -1
  26. package/dist/canvas-host/a2ui/.bundle.hash +1 -1
  27. package/dist/{channel-options-zAbgRuGY.js → channel-options-CdIEyHya.js} +2 -2
  28. package/dist/{channel-options-BEM8ruys.js → channel-options-DYh8mLMN.js} +2 -2
  29. package/dist/{channels-cli-cRWPvOQD.js → channels-cli-Bb18aE2b.js} +54 -53
  30. package/dist/{channels-cli-DdKnAzW9.js → channels-cli-sG9Wf2LH.js} +54 -53
  31. package/dist/{chrome-C_I81hbq.js → chrome-3jl2ulOE.js} +4 -4
  32. package/dist/{chrome-zElD4rpN.js → chrome-D1eO2jfe.js} +1 -1
  33. package/dist/{chrome-rzK8edU7.js → chrome-DJChpTwP.js} +1 -1
  34. package/dist/{chrome-BKUACyeO.js → chrome-OTJg3QKn.js} +4 -4
  35. package/dist/{clack-prompter-CuIw5vQW.js → clack-prompter-_kEnSVz4.js} +4 -4
  36. package/dist/{clack-prompter-Bc38EIYW.js → clack-prompter-v9MYo-5u.js} +4 -4
  37. package/dist/{cli-BJDlZfYi.js → cli-DEGt0Tp0.js} +36 -35
  38. package/dist/{cli--UhNWFtQ.js → cli-DtdTf-ZQ.js} +36 -35
  39. package/dist/{command-registry-COpZWfkh.js → command-registry-O155hUhR.js} +11 -11
  40. package/dist/{commands-registry-DPZevjMh.js → commands-registry-BuOUfpmg.js} +31 -0
  41. package/dist/{commands-registry-VfAQOVZO.js → commands-registry-C2Hvwjym.js} +31 -0
  42. package/dist/{commands-registry-BisT2Fcd.js → commands-registry-CJPBJPlh.js} +31 -0
  43. package/dist/{commands-registry-DFYDtKr_.js → commands-registry-DG2kGyg5.js} +31 -0
  44. package/dist/{completion-cli-EltMSZer.js → completion-cli-BaOjuoPX.js} +3 -3
  45. package/dist/{completion-cli-DVF5x7Kp.js → completion-cli-DLUKoSIx.js} +1 -1
  46. package/dist/{config-D7SS4vdk.js → config-B4jkreCN.js} +13 -2
  47. package/dist/{config-_DaupjQd.js → config-D7TcU4qN.js} +13 -2
  48. package/dist/{config-cli-DaPePEIB.js → config-cli-BuZ-L1Iw.js} +3 -3
  49. package/dist/{config-cli-kN07V9j6.js → config-cli-BxWavRxN.js} +3 -3
  50. package/dist/{config-guard-SNMCV6sc.js → config-guard-CLfXzB_z.js} +2 -2
  51. package/dist/{config-guard-CN1qhDyB.js → config-guard-D58THqAB.js} +8 -8
  52. package/dist/{config-validation-DS5Jr_iO.js → config-validation-DQ-lm2Qx.js} +1 -1
  53. package/dist/{config-validation-DGWvkKov.js → config-validation-DhsYEtLL.js} +1 -1
  54. package/dist/{configure-C9Z4clKW.js → configure-BSKWgEhS.js} +22 -22
  55. package/dist/{configure-id9imsuH.js → configure-gxAEhC9E.js} +22 -22
  56. package/dist/{control-service-CJWzOFkK.js → control-service-DOGU9T2P.js} +4 -4
  57. package/dist/{control-service-DvK2HPC2.js → control-service-DPzhv357.js} +4 -4
  58. package/dist/cost-cli-C9LvOtGz.js +138 -0
  59. package/dist/cost-cli-CmfkZsmZ.js +133 -0
  60. package/dist/{cron-cli-BIIzbF-W.js → cron-cli-DtDqHIZn.js} +7 -7
  61. package/dist/{cron-cli-BNx0V18_.js → cron-cli-L4iwVTNV.js} +7 -7
  62. package/dist/{daemon-cli-CGfWQN7c.js → daemon-cli-39fFIU2G.js} +15 -15
  63. package/dist/{daemon-cli-DCbqVfyu.js → daemon-cli-B5TdtWCQ.js} +15 -15
  64. package/dist/daemon-cli.js +13 -2
  65. package/dist/{daemon-runtime-BD_EkuZP.js → daemon-runtime-7YBz5otm.js} +3 -3
  66. package/dist/{daemon-runtime-CAdn50ea.js → daemon-runtime-DaJ4Tf2a.js} +3 -3
  67. package/dist/{deliver-6fYMGY7T.js → deliver-0nDhDdKd.js} +2 -2
  68. package/dist/{deliver-DyO3QD8O.js → deliver-BiWlR84Y.js} +5 -5
  69. package/dist/{deliver-DB4v0Tyl.js → deliver-C81eqdrP.js} +2 -2
  70. package/dist/{deliver-Cjyb6h4g.js → deliver-f3cIWxXT.js} +5 -5
  71. package/dist/{deps-Bt6gnwqB.js → deps-D5me2CAW.js} +1 -1
  72. package/dist/{devices-cli-CK5iNr60.js → devices-cli-DuVhACtW.js} +4 -4
  73. package/dist/{devices-cli-Dg4sVTTI.js → devices-cli-Ec6d58OB.js} +4 -4
  74. package/dist/{diagnostics-Ee2qfR9V.js → diagnostics-BZH08r5U.js} +1 -1
  75. package/dist/{diagnostics-4PsqURzT.js → diagnostics-CdawaB0U.js} +1 -1
  76. package/dist/{directory-cli-CIX9qXWA.js → directory-cli-BQrGwwjf.js} +6 -6
  77. package/dist/{directory-cli-CR-4DW4i.js → directory-cli-FR_KoYon.js} +6 -6
  78. package/dist/{dns-cli-Cd3EpJKL.js → dns-cli-CH2QMf70.js} +4 -4
  79. package/dist/{dns-cli-DzE58v7c.js → dns-cli-Cua_RGWw.js} +4 -4
  80. package/dist/{docs-cli-DD59E5fQ.js → docs-cli-9yu6OeWj.js} +2 -2
  81. package/dist/{docs-cli-BcqjkjOA.js → docs-cli-DwrSCuWF.js} +2 -2
  82. package/dist/{doctor-completion-Dw70YhMd.js → doctor-completion-BzfgfpBH.js} +2 -2
  83. package/dist/{doctor-completion-Dv6aw9I2.js → doctor-completion-wlBp8bv7.js} +2 -2
  84. package/dist/{doctor-config-flow-BOfsrB_o.js → doctor-config-flow-CKJlpwtv.js} +5 -5
  85. package/dist/{doctor-config-flow-dUAjyD2W.js → doctor-config-flow-CcwEh3WQ.js} +5 -5
  86. package/dist/{enable-avpl_Lwo.js → enable-BI6rQ1Fb.js} +1 -1
  87. package/dist/{enable-B5wvwTYB.js → enable-xfczksnk.js} +1 -1
  88. package/dist/entry.js +1 -1
  89. package/dist/{exec-approvals-cli-Cv9lE0Ov.js → exec-approvals-cli-1K1PMf0f.js} +10 -10
  90. package/dist/{exec-approvals-cli-CLD1HXqE.js → exec-approvals-cli-N45JsIvc.js} +10 -10
  91. package/dist/extensionAPI.js +8 -8
  92. package/dist/{gateway-cli-C1yf0Kx4.js → gateway-cli-Bz5fqsnE.js} +84 -83
  93. package/dist/{gateway-cli-DF-S-bKo.js → gateway-cli-_xNZ2L_e.js} +86 -85
  94. package/dist/{gateway-rpc-CBb3_pT9.js → gateway-rpc-c2_A2rwu.js} +2 -2
  95. package/dist/{gateway-rpc-DrcgCoEA.js → gateway-rpc-gDrdC_J6.js} +2 -2
  96. package/dist/{glass-ui-ws-CgTry9OG.js → glass-ui-ws-CbKVlQRh.js} +62 -61
  97. package/dist/{glass-ui-ws-BZJKBK5D.js → glass-ui-ws-DO8WKPIK.js} +63 -62
  98. package/dist/{health-B__mwl7J.js → health-B5BrlZ8G.js} +6 -6
  99. package/dist/{health-BJl_ZtRW.js → health-B7yvi1O9.js} +6 -6
  100. package/dist/{hooks-cli-CpDJa8fo.js → hooks-cli-CrgD2ZqP.js} +42 -41
  101. package/dist/{hooks-cli-B_d8Cv16.js → hooks-cli-mwiHuRfO.js} +42 -41
  102. package/dist/{hooks-status-CRdYwf7p.js → hooks-status-B5vDwm19.js} +1 -1
  103. package/dist/{hooks-status-i4MgV8tU.js → hooks-status-CQ33gaVT.js} +2 -2
  104. package/dist/index.js +47 -46
  105. package/dist/{inspect-BZEGJ1Wu.js → inspect-C3_zr-N9.js} +2 -2
  106. package/dist/{inspect-ChCXJY8c.js → inspect-D_lN8pwg.js} +2 -2
  107. package/dist/{install-safe-path-PVqsVjI9.js → install-safe-path-79R0iPyC.js} +2 -2
  108. package/dist/{install-safe-path-INk2Z_kc.js → install-safe-path-BBe6qFNr.js} +2 -2
  109. package/dist/{installs-lGgvyXAJ.js → installs-BVJQl3Tj.js} +3 -3
  110. package/dist/{installs-b6XWplET.js → installs-Bb1phV9x.js} +3 -3
  111. package/dist/{lifecycle-core-iiq9e4fE.js → lifecycle-core-DdbL6ELJ.js} +7 -7
  112. package/dist/{lifecycle-core-SWNKAc8k.js → lifecycle-core-O50xtu5c.js} +7 -7
  113. package/dist/llm-slug-generator.js +9 -9
  114. package/dist/{logs-cli-BGjeoamB.js → logs-cli-DvbMaSKU.js} +6 -6
  115. package/dist/{logs-cli-BEWpB_ac.js → logs-cli-T5v8efuM.js} +6 -6
  116. package/dist/{manager-xeIkDkmx.js → manager-BVPXSK-I.js} +1 -1
  117. package/dist/{manager-rvtFoeFT.js → manager-CnBU0aOR.js} +1 -1
  118. package/dist/{manager-PTSjHNVq.js → manager-CpBJ1BE6.js} +1 -1
  119. package/dist/{manager-DcZUW1bz.js → manager-CvqH_tah.js} +1 -1
  120. package/dist/{memory-D8JRYEYq.js → memory-BsGfHO_F.js} +4 -4
  121. package/dist/{memory-CeB8eMPH.js → memory-CbwmxmxW.js} +4 -4
  122. package/dist/{memory-cli-DZtv3G9o.js → memory-cli-B1dFPZw-.js} +7 -7
  123. package/dist/{memory-cli-rORHUdUV.js → memory-cli-BwQsPEFk.js} +7 -7
  124. package/dist/{model-catalog-MHTLXFwi.js → model-catalog-CzKsiNZA.js} +2 -2
  125. package/dist/{model-catalog-DQTmHZK7.js → model-catalog-IWi6-nY9.js} +2 -2
  126. package/dist/{model-picker-BVNI6Imm.js → model-picker-CS_h9RHv.js} +2 -2
  127. package/dist/{model-picker-DHLA0BEe.js → model-picker-DN-co6Oy.js} +2 -2
  128. package/dist/{models-D3haEpaG.js → models-Dm6dSSSx.js} +17 -17
  129. package/dist/{models-cli-DiyNuQ5w.js → models-cli-BA6ufqLd.js} +49 -48
  130. package/dist/{models-cli-DidUOdbx.js → models-cli-BPSrz6tf.js} +46 -45
  131. package/dist/{models-config-CRnTzdFs.js → models-config-B5Xxy-c-.js} +1 -1
  132. package/dist/{models-config-Br7EjqgG.js → models-config-CiR_RUxw.js} +1 -1
  133. package/dist/{node-cli-Yqf38Nio.js → node-cli-2HDdeLgi.js} +20 -20
  134. package/dist/{node-cli-DnwByBU2.js → node-cli-CH1yLZuO.js} +20 -20
  135. package/dist/{node-service-CRSkbk2b.js → node-service-CfHbECCi.js} +2 -2
  136. package/dist/{node-service-E8k7BOQV.js → node-service-D44noKnR.js} +2 -2
  137. package/dist/{nodes-cli-BY6HrZlh.js → nodes-cli-ARs9ZPma.js} +9 -9
  138. package/dist/{nodes-cli-OTk4gEj-.js → nodes-cli-DIm6cMS_.js} +9 -9
  139. package/dist/{note-Bn5K9itM.js → note-Cltpxj6i.js} +1 -1
  140. package/dist/{note-DtkOgLxt.js → note-ytwb4wwn.js} +1 -1
  141. package/dist/{npm-registry-spec-CZCkONwR.js → npm-registry-spec-CONWlhd6.js} +1 -1
  142. package/dist/{npm-registry-spec-L8BUQ0nu.js → npm-registry-spec-DPqOMFd9.js} +1 -1
  143. package/dist/{onboard-oIJ6OEGu.js → onboard-CjnPughY.js} +18 -18
  144. package/dist/{onboard-C1PSYsJY.js → onboard-Cmz6Rtm-.js} +18 -18
  145. package/dist/{onboard-channels-BSt89ffO.js → onboard-channels-Cozz3CQv.js} +7 -7
  146. package/dist/{onboard-channels-DvNWHvx3.js → onboard-channels-D00NAtQt.js} +7 -7
  147. package/dist/{onboard-custom-y7PsUrmE.js → onboard-custom-BCcuL4Uq.js} +2 -2
  148. package/dist/{onboard-custom-TvRg0dYq.js → onboard-custom-C-wfNtOM.js} +2 -2
  149. package/dist/{onboard-helpers-CtpOchu0.js → onboard-helpers-BKfeJ1xj.js} +4 -4
  150. package/dist/{onboard-helpers-HjgAKoSl.js → onboard-helpers-CCI7SimM.js} +4 -4
  151. package/dist/{onboard-hooks-BU0EsBMH.js → onboard-hooks-CXRw9BJY.js} +2 -2
  152. package/dist/{onboard-hooks-Cmy0Qz0F.js → onboard-hooks-DfDF9AU4.js} +2 -2
  153. package/dist/{onboard-remote-B7bM-1-l.js → onboard-remote-D4R-Yq2Q.js} +3 -3
  154. package/dist/{onboard-remote-B5kHPh_e.js → onboard-remote-DKXBH_lQ.js} +3 -3
  155. package/dist/{onboard-skills-BsPcuuer.js → onboard-skills-BPmu8XLA.js} +2 -2
  156. package/dist/{onboard-skills-V7pX2pkl.js → onboard-skills-jVyIFojF.js} +3 -3
  157. package/dist/{onboarding-D4SGY_zG.js → onboarding-BPZb40BJ.js} +16 -16
  158. package/dist/{onboarding-Ce0PyZFq.js → onboarding-BrTMOcPF.js} +16 -16
  159. package/dist/{onboarding.finalize-BDPrr9CT.js → onboarding.finalize-Bd2rGMjo.js} +26 -26
  160. package/dist/{onboarding.finalize-TkbmJzg5.js → onboarding.finalize-BiL_LXrR.js} +28 -28
  161. package/dist/{onboarding.gateway-config-9dgVRLeb.js → onboarding.gateway-config-B301LxTx.js} +6 -6
  162. package/dist/{onboarding.gateway-config-DXQhxsQS.js → onboarding.gateway-config-ChCxv8dy.js} +6 -6
  163. package/dist/{openai-model-default-D_rz8Pew.js → openai-model-default-CKfNKTZD.js} +1 -1
  164. package/dist/{openai-model-default-BkGyzajy.js → openai-model-default-ChdgeMqX.js} +1 -1
  165. package/dist/{outbound-send-deps-PNzbuoSX.js → outbound-send-deps-JQjmNLPx.js} +1 -1
  166. package/dist/{pairing-cli-WQ1MKO2B.js → pairing-cli-D7_UlTsI.js} +3 -3
  167. package/dist/{pairing-cli-D2zvrKTM.js → pairing-cli-UgiAsygW.js} +3 -3
  168. package/dist/{path-env-BHRjFlqO.js → path-env-BAyW1s3c.js} +1 -1
  169. package/dist/{path-env-i-ZjtVbs.js → path-env-C1hgM8gP.js} +1 -1
  170. package/dist/{pi-embedded-BPuUM-gD.js → pi-embedded-C9wLrFjj.js} +1439 -494
  171. package/dist/{pi-embedded-helpers-nFK_hP2q.js → pi-embedded-helpers-BBiyNXkS.js} +1 -1
  172. package/dist/{pi-embedded-helpers-DVolpQ34.js → pi-embedded-helpers-CDzBxa-P.js} +1 -1
  173. package/dist/{pi-tools.policy-uHgu_nx0.js → pi-tools.policy-CU8U7--z.js} +2 -2
  174. package/dist/{pi-tools.policy-CTzYYKRt.js → pi-tools.policy-WaLKhqJQ.js} +2 -2
  175. package/dist/{plugin-auto-enable-C4b23B35.js → plugin-auto-enable-Bt2sVz8w.js} +2 -2
  176. package/dist/{plugin-auto-enable-BkhVwtbW.js → plugin-auto-enable-PBDcVF_-.js} +2 -2
  177. package/dist/{plugin-registry-V5jShvbP.js → plugin-registry-BLoSesyj.js} +2 -2
  178. package/dist/{plugin-registry-CxUYRmLh.js → plugin-registry-CZDG8fjK.js} +2 -2
  179. package/dist/plugin-sdk/auto-reply/reply/commands-info.d.ts +1 -0
  180. package/dist/plugin-sdk/auto-reply/reply/middleware-context-warning.d.ts +22 -0
  181. package/dist/plugin-sdk/auto-reply/session-boundary-messages.d.ts +16 -3
  182. package/dist/plugin-sdk/auto-reply/status.d.ts +13 -0
  183. package/dist/plugin-sdk/config/types.models.d.ts +5 -0
  184. package/dist/plugin-sdk/config/zod-schema.core.d.ts +11 -0
  185. package/dist/plugin-sdk/config/zod-schema.d.ts +5 -0
  186. package/dist/plugin-sdk/cost/benchmark.d.ts +36 -0
  187. package/dist/plugin-sdk/cost/breakdown.d.ts +63 -0
  188. package/dist/plugin-sdk/cost/gpu-inference.d.ts +52 -0
  189. package/dist/plugin-sdk/cost/rates.d.ts +32 -0
  190. package/dist/plugin-sdk/cost/serving-discovery.d.ts +54 -0
  191. package/dist/plugin-sdk/cost/summary.d.ts +40 -0
  192. package/dist/plugin-sdk/index.js +13 -2
  193. package/dist/{plugins-cli-CMAwepRk.js → plugins-cli-2yraoR6V.js} +43 -42
  194. package/dist/{plugins-cli-BthQwo7n.js → plugins-cli-CGs9-UtO.js} +43 -42
  195. package/dist/{program-iw_XyVhs.js → program-BnKEJpZF.js} +46 -45
  196. package/dist/{program-context-BVEz8AgF.js → program-context-BvP9L_1W.js} +48 -40
  197. package/dist/{prompt-select-styled-CF4qV0_M.js → prompt-select-styled-BTF5vvv8.js} +32 -32
  198. package/dist/{prompt-select-styled-D3RAY7pg.js → prompt-select-styled-Brx330O3.js} +31 -31
  199. package/dist/{provider-auth-helpers-Dxo0v0UO.js → provider-auth-helpers-CppzYZM9.js} +6 -6
  200. package/dist/{provider-auth-helpers-BTBjOyhO.js → provider-auth-helpers-hjy3e-oS.js} +6 -6
  201. package/dist/{push-apns-B8Wg3Hqw.js → push-apns-BD2iO09c.js} +1 -1
  202. package/dist/{push-apns-DIIbGT1M.js → push-apns-DJ55TFPT.js} +1 -1
  203. package/dist/{pw-ai-kkF0QaDF.js → pw-ai-DBAtSFTB.js} +2 -2
  204. package/dist/{pw-ai-BFS9ezWe.js → pw-ai-DOAsQ5NX.js} +2 -2
  205. package/dist/{pw-ai-_prsAw5O.js → pw-ai-DQZa9DUQ.js} +2 -2
  206. package/dist/{pw-ai-Cx-Ko_FL.js → pw-ai-DY_6l11g.js} +2 -2
  207. package/dist/{qr-cli-CcAzgz_N.js → qr-cli-D2A-IU0Y.js} +1 -1
  208. package/dist/{qr-cli-KmGkQDBF.js → qr-cli-DHpiebkG.js} +1 -1
  209. package/dist/{redact-identifier-CXvHJXk9.js → redact-identifier-BOxAUdff.js} +1 -1
  210. package/dist/{register.agent-8XsVRuWC.js → register.agent-DTGvQGla.js} +61 -60
  211. package/dist/{register.agent-D-OIszeY.js → register.agent-Dz_P7PxO.js} +63 -62
  212. package/dist/register.configure-CrgU3FzU.js +131 -0
  213. package/dist/register.configure-D9w7Tm9e.js +135 -0
  214. package/dist/{register.maintenance-CjM8sJqH.js → register.maintenance-CqvrXPF7.js} +64 -63
  215. package/dist/{register.maintenance-CBYqsXkf.js → register.maintenance-d5xHdDgu.js} +63 -62
  216. package/dist/{register.message-DnljWvZP.js → register.message-C0tqgEor.js} +40 -39
  217. package/dist/{register.message-kSIASKVK.js → register.message-DNMCxaAD.js} +41 -40
  218. package/dist/{register.onboard-Vj1-Ike1.js → register.onboard--eJVfJGa.js} +28 -28
  219. package/dist/{register.onboard-eDNn1pdd.js → register.onboard-dkAvGraV.js} +28 -28
  220. package/dist/{register.setup-DMaoMWRD.js → register.setup-CgufX-6c.js} +28 -28
  221. package/dist/{register.setup-CmhspsS8.js → register.setup-Dwh0ylCS.js} +28 -28
  222. package/dist/{register.status-health-sessions-r3F9H8b0.js → register.status-health-sessions-BeAm7HAq.js} +36 -36
  223. package/dist/{register.status-health-sessions-CJqCoqAi.js → register.status-health-sessions-D6BRCFg_.js} +35 -35
  224. package/dist/{register.subclis-RqX1a2aL.js → register.subclis-Hb2xSHBy.js} +37 -29
  225. package/dist/{replies-BYF1gbJf.js → replies-0nzkXt6o.js} +1 -1
  226. package/dist/{replies-B91-OngF.js → replies-C5CBlnFS.js} +1 -1
  227. package/dist/{replies-DAYTg6Mb.js → replies-D0FYSIJg.js} +1 -1
  228. package/dist/{replies-UP2sglaR.js → replies-_DV8VSSj.js} +1 -1
  229. package/dist/{resolve-route-Zww0Y-HJ.js → resolve-route-CnTdHVgw.js} +1 -1
  230. package/dist/{resolve-route-CmZ7XjmB.js → resolve-route-D0NrCHnr.js} +1 -1
  231. package/dist/{routes-BfeVDhod.js → routes-CPMVuvoz.js} +3 -3
  232. package/dist/{routes-y2Ww0pum.js → routes-DIyAmLYR.js} +3 -3
  233. package/dist/{rpc-DZCrGGH5.js → rpc-B2BLRS45.js} +2 -2
  234. package/dist/{rpc-RIkh5F9v.js → rpc-gUsL9Mqf.js} +2 -2
  235. package/dist/{run-main-6pE2fYXT.js → run-main-B_NTFmz1.js} +61 -60
  236. package/dist/{sandbox-DQdjlC-w.js → sandbox-61-kshSF.js} +5 -5
  237. package/dist/{sandbox-BjQ6n3zl.js → sandbox-J92UBQK8.js} +5 -5
  238. package/dist/{sandbox-cli-CTYAHFyM.js → sandbox-cli-D9v0jhBb.js} +8 -8
  239. package/dist/{sandbox-cli-C0IVf8AS.js → sandbox-cli-DJgF-r8G.js} +8 -8
  240. package/dist/{security-cli-B8VyQJcl.js → security-cli-CZix5cXq.js} +13 -13
  241. package/dist/{security-cli-D0oErb9f.js → security-cli-J9J0qvDy.js} +13 -13
  242. package/dist/{send-Cxu1tl56.js → send-B0jHSNMF.js} +1 -1
  243. package/dist/{send-Cuk_Rjss.js → send-C75uSv6p.js} +1 -1
  244. package/dist/{send-BBfSp-8Q.js → send-Dq252-bi.js} +1 -1
  245. package/dist/{server-context-BFCh7pUb.js → server-context-D-82OTsT.js} +5 -5
  246. package/dist/{server-context-YlgRz1wC.js → server-context-SbbjNkPL.js} +5 -5
  247. package/dist/{server-methods-BxsThjMp.js → server-methods-CFWjtx32.js} +31 -31
  248. package/dist/{server-methods-BWCAXrQJ.js → server-methods-Cz_-FX5B.js} +31 -31
  249. package/dist/{server-node-events-AZFI44cm.js → server-node-events-BiMD-Sik.js} +40 -39
  250. package/dist/{server-node-events-C10Bhdag.js → server-node-events-UJ4Hwcsf.js} +39 -38
  251. package/dist/{service-vsb7_8MA.js → service-BF50XyKr.js} +2 -2
  252. package/dist/{service-BBw78ATM.js → service-Ccv3Zi5_.js} +2 -2
  253. package/dist/{session-cost-usage-CqLUlh7S.js → session-cost-usage-CJWHHY-C.js} +1 -1
  254. package/dist/{session-cost-usage-D6Ocwmq1.js → session-cost-usage-D3mgssM_.js} +1 -1
  255. package/dist/{session-utils-BZnPW904.js → session-utils-Cs1jlD-q.js} +3 -3
  256. package/dist/{session-utils-BGw_xwXK.js → session-utils-Zpe3t68b.js} +3 -3
  257. package/dist/{sessions-uS7rV-lI.js → sessions-BSmT7vGX.js} +3 -3
  258. package/dist/{sessions-DHPf5TzB.js → sessions-Dn6VXn4p.js} +1 -1
  259. package/dist/{sessions-optZRB57.js → sessions-Dxf5Kjig.js} +1 -1
  260. package/dist/{shared-CfBMF1VB.js → shared-BJRsBGGr.js} +2 -2
  261. package/dist/{shared-CVXZtpIq.js → shared-BmjlTHYU.js} +2 -2
  262. package/dist/{shared-BucaCyaw.js → shared-Ck6cf10x.js} +1 -1
  263. package/dist/{shared-k1QjV3ys.js → shared-Crfo8y70.js} +1 -1
  264. package/dist/{skill-commands-CKm7eCw6.js → skill-commands-D0xAWG0l.js} +1 -1
  265. package/dist/{skill-commands-DAtpPeXi.js → skill-commands-DKkiQJxU.js} +1 -1
  266. package/dist/{skill-commands-BoMrW3WV.js → skill-commands-JIccKWkf.js} +1 -1
  267. package/dist/{skill-commands-yPirQFOb.js → skill-commands-KnANH5Qm.js} +1 -1
  268. package/dist/{skills-cli-CcWFIcOR.js → skills-cli-BZF5mcG5.js} +7 -7
  269. package/dist/{skills-cli-DcJBgk5R.js → skills-cli-C9F-zLWe.js} +3 -3
  270. package/dist/{skills-install-CcW780Kq.js → skills-install-QOHQrX6P.js} +4 -4
  271. package/dist/{skills-install-CbRsCzAG.js → skills-install-X12kifP1.js} +4 -4
  272. package/dist/{skills-status-CLzaY4r2.js → skills-status-6LVKpabC.js} +1 -1
  273. package/dist/{ssrf-q6hBiAOi.js → ssrf-BCSnhba8.js} +13 -2
  274. package/dist/{ssrf-oI58TMOb.js → ssrf-DNhyFMRW.js} +13 -2
  275. package/dist/{status-BxD8CjLr.js → status-BGUaaSHe.js} +2 -2
  276. package/dist/{status-B5sjPQS6.js → status-Bp48-ySL.js} +20 -20
  277. package/dist/{status-CZc22Lqb.js → status-CObdh7-H.js} +2 -2
  278. package/dist/{status-Cv8N2kIe.js → status-FX0BMcCb.js} +20 -20
  279. package/dist/{status.update-B52bM2Tg.js → status.update-CdTtmVpp.js} +2 -2
  280. package/dist/{status.update-Bl_ewksT.js → status.update-_3qHPt0O.js} +2 -2
  281. package/dist/{subagent-registry-BnHgIGX-.js → subagent-registry-ChDWDl_p.js} +304 -106
  282. package/dist/{synthesis-fD8J2vag.js → synthesis-CmQvOHg6.js} +9 -9
  283. package/dist/{synthesis-7UL3pCpj.js → synthesis-DIkOQnhF.js} +8 -8
  284. package/dist/{synthesis-DvfrgkQU.js → synthesis-DdP6tbyk.js} +36 -35
  285. package/dist/{synthesis-o7Zdrwxz.js → synthesis-m6WCyI41.js} +36 -35
  286. package/dist/{system-cli-BAn07VkE.js → system-cli-DB9etQxq.js} +5 -5
  287. package/dist/{system-cli-BTZ8T0-Z.js → system-cli-szRqg1_v.js} +5 -5
  288. package/dist/{systemd-DCzA-V_E.js → systemd-Dic80Qni.js} +1 -1
  289. package/dist/{systemd-Cmn7zMqD.js → systemd-Dtydk5-z.js} +1 -1
  290. package/dist/{systemd-hints-CvIqgg9d.js → systemd-hints-DmDUq9JT.js} +4 -4
  291. package/dist/{systemd-hints-BlGehfA3.js → systemd-hints-bP8dBJ78.js} +4 -4
  292. package/dist/{systemd-linger-BUWYteOW.js → systemd-linger-BBxRNFXz.js} +2 -2
  293. package/dist/{systemd-linger-Bj4nK9ZB.js → systemd-linger-DjoQVcOq.js} +2 -2
  294. package/dist/{tui-XLWiN8Hm.js → tui-CEhOf9fk.js} +6 -6
  295. package/dist/{tui-B6mIUNPO.js → tui-Dp58oYvX.js} +6 -6
  296. package/dist/{tui-cli-byFYgg3c.js → tui-cli-DFaOwBwg.js} +12 -12
  297. package/dist/{tui-cli-CTK5_3rU.js → tui-cli-wxh3YpaV.js} +12 -12
  298. package/dist/{unified-runner-BIiKFnNF.js → unified-runner-Cu3lGa3A.js} +1440 -495
  299. package/dist/{unified-runner-DnikxMFg.js → unified-runner-DL-sfvGT.js} +305 -107
  300. package/dist/{update-DxY1UB0k.js → update-BDo7wxMf.js} +1 -1
  301. package/dist/{update-EhDcBqN1.js → update-CcacbR32.js} +1 -1
  302. package/dist/{update-check-pFwV6W-z.js → update-check-A86nJKtZ.js} +1 -1
  303. package/dist/{update-check-H0DwvuqN.js → update-check-oEbS0voJ.js} +1 -1
  304. package/dist/{update-cli-BAdPKO1o.js → update-cli-DAKoU0Wn.js} +73 -72
  305. package/dist/{update-cli-C8IVRiDZ.js → update-cli-gEBRNrm2.js} +74 -73
  306. package/dist/{update-runner-CERd2XdT.js → update-runner-CQMv-ibM.js} +3 -3
  307. package/dist/{update-runner-7oHPAIND.js → update-runner-DHi359Tb.js} +3 -3
  308. package/dist/{usage-format-_37Bn-Jb.js → usage-format-DQJz-0qd.js} +0 -1
  309. package/dist/{usage-format-rxT5cEAf.js → usage-format-DeczTGI-.js} +0 -1
  310. package/dist/{webhooks-cli-3UJupWMP.js → webhooks-cli-C3g4MxCE.js} +3 -3
  311. package/dist/{webhooks-cli-BFpGMNrf.js → webhooks-cli-C3uyehJS.js} +3 -3
  312. package/dist/{with-timeout-Bn-ltLg1.js → with-timeout-B0ZJa7f2.js} +1 -1
  313. package/dist/{with-timeout-EXM-FP4_.js → with-timeout-GbJ1Yzsh.js} +1 -1
  314. package/package.json +1 -1
  315. package/dist/register.configure-Bcdw9qlF.js +0 -130
  316. package/dist/register.configure-KE6Kvt4O.js +0 -134
  317. /package/dist/{agents.config-BG9fpad0.js → agents.config-Cyc_RegL.js} +0 -0
  318. /package/dist/{agents.config-CxrFhtC1.js → agents.config-DK6nN-Qh.js} +0 -0
  319. /package/dist/{argv-oa_KBmv1.js → argv-Bl0th4dq.js} +0 -0
  320. /package/dist/{auth-choice-legacy-DwMt7oDR.js → auth-choice-legacy-BZWIpO92.js} +0 -0
  321. /package/dist/{auth-choice-legacy-ZsU_kwPI.js → auth-choice-legacy-iEyARXI2.js} +0 -0
  322. /package/dist/{bindings-CLS_owm_.js → bindings-BAOPW5eK.js} +0 -0
  323. /package/dist/{bindings-BpMZcmYL.js → bindings-c7qLJdIA.js} +0 -0
  324. /package/dist/{brew-B3VMQVQk.js → brew-B4FH-mEH.js} +0 -0
  325. /package/dist/{brew-BsE_w2tW.js → brew-CI00FKf8.js} +0 -0
  326. /package/dist/{catalog-CriSxQMH.js → catalog-BaM8d1-T.js} +0 -0
  327. /package/dist/{catalog-BXxi5-YC.js → catalog-BnLcGVie.js} +0 -0
  328. /package/dist/{channel-selection-BiYW5XI-.js → channel-selection-BrFl0vVK.js} +0 -0
  329. /package/dist/{channel-selection-DF4bza2Q.js → channel-selection-DjrS6oiz.js} +0 -0
  330. /package/dist/{channels-status-issues-DuRF3XF3.js → channels-status-issues-BwbA2OBt.js} +0 -0
  331. /package/dist/{channels-status-issues-C2AVfv0-.js → channels-status-issues-iWQDGUQe.js} +0 -0
  332. /package/dist/{cli-utils-tNdOjVQI.js → cli-utils-CbnnSB38.js} +0 -0
  333. /package/dist/{clipboard-B1jgJ11s.js → clipboard-BSTxQ2tO.js} +0 -0
  334. /package/dist/{clipboard-Sks8Qw-6.js → clipboard-CHn5r7Kj.js} +0 -0
  335. /package/dist/{command-options-C2yg82U0.js → command-options-DgcCGXMQ.js} +0 -0
  336. /package/dist/{command-options-D_KEIae-.js → command-options-Vxb4M7Aj.js} +0 -0
  337. /package/dist/{consolidate-DPAffHCg.js → consolidate-BSUbtSDt.js} +0 -0
  338. /package/dist/{consolidate-CF6vEjPe.js → consolidate-DhoiF4n7.js} +0 -0
  339. /package/dist/{constants-B4wXIPMk.js → constants-BLIhifCJ.js} +0 -0
  340. /package/dist/{constants-ChnKXZKi.js → constants-BP_JoSwO.js} +0 -0
  341. /package/dist/{control-ui-assets-CkPR0Fz2.js → control-ui-assets-CnX0W3vy.js} +0 -0
  342. /package/dist/{control-ui-assets-BVCcPRi3.js → control-ui-assets-DfBRXG5y.js} +0 -0
  343. /package/dist/{delivery-queue-DqDe6994.js → delivery-queue-CIwn40ej.js} +0 -0
  344. /package/dist/{delivery-queue-RUd4NhRw.js → delivery-queue-duM0RT18.js} +0 -0
  345. /package/dist/{dm-policy-shared-DmpXsl2K.js → dm-policy-shared-BUwZ6Ajx.js} +0 -0
  346. /package/dist/{dm-policy-shared-ZfPtrTeh.js → dm-policy-shared-EuuPwRNE.js} +0 -0
  347. /package/dist/{entry-status-BqhxPFzK.js → entry-status-D0BSpWt_.js} +0 -0
  348. /package/dist/{format-BskCnX0I.js → format-BcXs5iuf.js} +0 -0
  349. /package/dist/{gmail-setup-utils-BlGvgPlF.js → gmail-setup-utils-DJgxyDTX.js} +0 -0
  350. /package/dist/{gmail-setup-utils-DsRU2ywQ.js → gmail-setup-utils-_TEJA4pL.js} +0 -0
  351. /package/dist/{health-format-CzrMGubG.js → health-format-Dp4xmTKn.js} +0 -0
  352. /package/dist/{health-format-C0DWlpEn.js → health-format-Li703vy6.js} +0 -0
  353. /package/dist/{help-format-DhRyo3Pj.js → help-format-8IYCRvx1.js} +0 -0
  354. /package/dist/{help-format-BjEVi4c_.js → help-format-BTNd5kFC.js} +0 -0
  355. /package/dist/{helpers-CcArejFh.js → helpers-BnXDQL2q.js} +0 -0
  356. /package/dist/{helpers-Dm_utoC3.js → helpers-CoScWBmD.js} +0 -0
  357. /package/dist/{helpers-DJRLZbrj.js → helpers-DGBa5iKd.js} +0 -0
  358. /package/dist/{helpers-DUclfUl-.js → helpers-lLtg0Hgi.js} +0 -0
  359. /package/dist/{ipv4--8f4a_51.js → ipv4-CCdAVmwu.js} +0 -0
  360. /package/dist/{ipv4-Cy7l-phR.js → ipv4-DFUXU3PT.js} +0 -0
  361. /package/dist/{links-D6ASL_as.js → links-B9CbwY46.js} +0 -0
  362. /package/dist/{links-BkFDs4sT.js → links-CQZxjjCO.js} +0 -0
  363. /package/dist/{logging-4WqMHwAZ.js → logging-BRejMykf.js} +0 -0
  364. /package/dist/{logging-iIX8duxv.js → logging-BmJ5ky59.js} +0 -0
  365. /package/dist/{logging-Czh4x_NQ.js → logging-CLWZ3KQI.js} +0 -0
  366. /package/dist/{model-D50Lt_sm.js → model-BMFj7NXy.js} +0 -0
  367. /package/dist/{model-param-b-CfiuLqZG.js → model-param-b-C6mMtCJr.js} +0 -0
  368. /package/dist/{onboard-config-BKb2QQqE.js → onboard-config-B9Iy9-4f.js} +0 -0
  369. /package/dist/{onboard-config-DZIbmz6s.js → onboard-config-DwsP5yz1.js} +0 -0
  370. /package/dist/{outbound-send-deps-BR6jeE9h.js → outbound-send-deps-DpyxnI3f.js} +0 -0
  371. /package/dist/{parse-log-line-CeJ1RDHv.js → parse-log-line-BQPvB6cZ.js} +0 -0
  372. /package/dist/{parse-log-line-DxFrnzNo.js → parse-log-line-Cg7e_EO6.js} +0 -0
  373. /package/dist/{parse-port-DdAxyRwV.js → parse-port-CLBKavYE.js} +0 -0
  374. /package/dist/{parse-port-W56FnCN_.js → parse-port-dzRz6QnZ.js} +0 -0
  375. /package/dist/{parse-timeout-DKY8YAUj.js → parse-timeout-CuYdP9TL.js} +0 -0
  376. /package/dist/{path-safety-LPRW6mO-.js → path-safety-ZDtSDPro.js} +0 -0
  377. /package/dist/{path-safety-grmMl9nR.js → path-safety-cWA8NpOb.js} +0 -0
  378. /package/dist/{plugins-allowlist-BuJjTWyS.js → plugins-allowlist-C5r7biDp.js} +0 -0
  379. /package/dist/{plugins-allowlist-BvQZxkGy.js → plugins-allowlist-CD4oIJNk.js} +0 -0
  380. /package/dist/{ports-CqKpyZSl.js → ports-BE4iY9ho.js} +0 -0
  381. /package/dist/{ports-BDzMH5Eu.js → ports-C2swmreL.js} +0 -0
  382. /package/dist/{program-context-C5Y6Svzj.js → program-context-CGKRxOBU.js} +0 -0
  383. /package/dist/{progress-deSwGz9x.js → progress-BOQ0hkeM.js} +0 -0
  384. /package/dist/{progress-B3K1UFtC.js → progress-DQTvTiEg.js} +0 -0
  385. /package/dist/{prompt-style-DeaIm7_1.js → prompt-style-CzRuIYtp.js} +0 -0
  386. /package/dist/{prompt-style-DS51QPPi.js → prompt-style-pphr4yLK.js} +0 -0
  387. /package/dist/{prompts-LvxbwPs6.js → prompts-B98rp78m.js} +0 -0
  388. /package/dist/{prompts-l_pUOv42.js → prompts-CqJkfsHC.js} +0 -0
  389. /package/dist/{qmd-manager-BbWeOOTD.js → qmd-manager-C6wRtPm_.js} +0 -0
  390. /package/dist/{qmd-manager-CYKlEJ2U.js → qmd-manager-CYEAMLE7.js} +0 -0
  391. /package/dist/{runtime-guard-GWXNB3ke.js → runtime-guard-Bgv3O9s4.js} +0 -0
  392. /package/dist/{runtime-guard-DWXoHW1Q.js → runtime-guard-ofQGcCUc.js} +0 -0
  393. /package/dist/{runtime-status-BqrK6ivx.js → runtime-status-B-PXkhrX.js} +0 -0
  394. /package/dist/{runtime-status-D4pjzLyv.js → runtime-status-Zb9OQ0VK.js} +0 -0
  395. /package/dist/{session-dirs-CXErIzZq.js → session-dirs-BsQ-g02q.js} +0 -0
  396. /package/dist/{session-dirs-DJ4qiP3r.js → session-dirs-DpiMgw4q.js} +0 -0
  397. /package/dist/{skill-scanner-zh2dJM3x.js → skill-scanner-D5p8L-xO.js} +0 -0
  398. /package/dist/{skill-scanner-Ur9nMoo4.js → skill-scanner-EhsZUzzk.js} +0 -0
  399. /package/dist/{stagger-DkaCfsKB.js → stagger-DQs772BN.js} +0 -0
  400. /package/dist/{status-Bz_-dDs6.js → status-DtyqId3v.js} +0 -0
  401. /package/dist/{status-CExNNC5N.js → status-dOhj12u0.js} +0 -0
  402. /package/dist/{system-run-command-CeR1OLFk.js → system-run-command-2oJPKfVr.js} +0 -0
  403. /package/dist/{system-run-command-Craglj8T.js → system-run-command-D_OmCQOL.js} +0 -0
  404. /package/dist/{table-xKEHbVsK.js → table-Dm8jYqmW.js} +0 -0
  405. /package/dist/{table-jBELNhV1.js → table-Ds5CZCyv.js} +0 -0
  406. /package/dist/{tool-loop-detection-D3y39HsT.js → tool-loop-detection-2Mxxm8YE.js} +0 -0
  407. /package/dist/{tool-loop-detection-DljhV89j.js → tool-loop-detection-Bk07vuCX.js} +0 -0
  408. /package/dist/{widearea-dns-C8Rsixsi.js → widearea-dns-BwIBBqZo.js} +0 -0
  409. /package/dist/{widearea-dns-BSrnDwJD.js → widearea-dns-DA_m7oeT.js} +0 -0
  410. /package/dist/{workspace-DKEYzTNc.js → workspace-DD9pYbiv.js} +0 -0
  411. /package/dist/{workspace-BkWAKK8O.js → workspace-Wkr6wXcS.js} +0 -0
  412. /package/dist/{wsl-cy5jpbkx.js → wsl-Ci3VOaSK.js} +0 -0
  413. /package/dist/{wsl-hSA0zCrh.js → wsl-S50RbgL8.js} +0 -0
@@ -9,12 +9,12 @@ import { _ as resolveAuthProfileDisplayLabel, a as markAuthProfileFailure, c as
9
9
  import { n as resolveCliName, t as formatCliCommand } from "./command-format-BrrHNE8r.js";
10
10
  import { _ as DEFAULT_MODEL, c as normalizeProviderId, d as resolveDefaultModelForAgent, f as resolveModelRefFromString, g as DEFAULT_CONTEXT_TOKENS, h as getProviderAdapter, i as findNormalizedProviderValue, m as resolveThinkingDefault, n as buildConfiguredAllowlistKeys, o as modelKey, p as resolveSubagentSpawnModelSelection, r as buildModelAliasIndex, s as normalizeModelRef$1, t as buildAllowedModelSet, u as resolveConfiguredModelRef, v as DEFAULT_PROVIDER } from "./model-selection-BqshlIZc.js";
11
11
  import { n as saveJsonFile, t as loadJsonFile } from "./json-file-CZ3ssFR9.js";
12
- import { $ as resolveSandboxContext, $t as resolveBrowserControlAuth, A as isGoogleModelApi, At as resolveSessionResetPolicy, B as isCompactionFailureError, Bt as resolveGroupSessionKey, C as sanitizeImageBlocks, Ct as INPUT_PROVENANCE_KIND_VALUES, D as extractToolResultId, Dt as resolveSessionKey, E as extractToolCallsFromAssistant, Et as normalizeInputProvenance, F as formatRawAssistantErrorForUi, Ft as canonicalizeMainSessionAlias, G as isRateLimitAssistantError, Gt as resolveBrowserConfig, H as isFailoverAssistantError, Ht as resolveSessionLockMaxHoldFromTimeout, I as getApiErrorPayloadFingerprint, J as isTransientHttpError, Jt as saveMediaBuffer, K as isRawApiErrorPayload, Kt as resolveProfile, L as isAuthAssistantError, M as classifyFailoverReason, Mt as resolveThreadFlag, N as formatAssistantErrorText, Nt as DEFAULT_RESET_TRIGGERS, O as downgradeOpenAIReasoningBlocks, Ot as evaluateSessionFreshness, P as formatBillingErrorMessage, Pt as resolveFreshSessionTotalTokens, Q as ensureSandboxWorkspaceForSession, Qt as ensureBrowserControlAuth, R as isBillingAssistantError, Rt as resolveMainSessionKey, S as sanitizeSessionMessagesImages, St as extractToolCallNames, T as resolveImageSanitizationLimits, Tt as hasInterSessionUserProvenance, U as isFailoverErrorMessage, Ut as createBrowserRouteContext, V as isContextOverflowError, Vt as acquireSessionWriteLock, W as isLikelyContextOverflowError, Wt as registerBrowserRoutes, X as parseImageSizeError, Xt as resolveExistingPathsWithinRoot, Y as parseImageDimensionError, Yt as DEFAULT_UPLOAD_DIR, Z as sanitizeUserFacingText, Zt as getBridgeAuthForPort, _ as validateAnthropicTurns, _t as normalizeSessionDeliveryFields, an as mergeAlsoAllowPolicy, at as loadSessionStore, b as isMessagingToolDuplicateNormalized, bt as capArrayByJsonBytes, c as normalizeChannelTargetInput, cn as stripPluginOnlyAllowlist, ct as updateLastRoute, d as parseReplyDirectives, dn as buildBootstrapContextFiles, dt as isCacheEnabled, en as applyOwnerOnlyToolPolicy, et as resolveSandboxRuntimeStatus, f as MEDIA_TOKEN_RE, fn as ensureSessionHeader, ft as resolveCacheTtlMs$1, g as initializeGlobalHookRunner, gt as normalizeDeliveryContext, h as getGlobalHookRunner, hn as sanitizeGoogleTurnOrdering, ht as mergeDeliveryContext, in as expandToolGroups, it as resolveAndPersistSessionFile, j as BILLING_ERROR_USER_MESSAGE, jt as resolveSessionResetType, k as isAntigravityClaude, kt as resolveChannelResetConfig, l as normalizeTargetForProvider, ln as compileGlobPatterns, lt as updateSessionStore, m as parseInlineDirectives$1, mn as resolveBootstrapTotalMaxChars, mt as deliveryContextKey, nn as collectExplicitAllowlist, o as normalizeReplyPayloadsForDelivery, on as normalizeToolName$1, ot as readSessionUpdatedAt, p as splitMediaFromOutput, pn as resolveBootstrapMaxChars, pt as deliveryContextFromSession, q as isTimeoutErrorMessage, qt as getMediaDir, rn as expandPolicyWithPluginGroups, rt as appendAssistantMessageToSessionTranscript, s as buildTargetResolverSignature, sn as resolveToolProfilePolicy, st as recordSessionMetaFromInbound, t as deliverOutboundPayloads, tn as buildPluginToolGroups, tt as extractDeliveryInfo, u as throwIfAborted, un as matchesAnyGlobPattern, ut as updateSessionStoreEntry, v as validateGeminiTurns, w as sanitizeToolResultImages, wt as applyInputProvenanceToUserMessage, x as normalizeTextForComparison, xt as countToolResults, y as pickFallbackThinkingLevel, yt as archiveSessionTranscripts, z as isCloudCodeAssistFormatError, zt as deriveSessionMetaPatch } from "./deliver-DyO3QD8O.js";
13
- 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-oI58TMOb.js";
12
+ import { $ as resolveSandboxContext, $t as resolveBrowserControlAuth, A as isGoogleModelApi, At as resolveSessionResetPolicy, B as isCompactionFailureError, Bt as resolveGroupSessionKey, C as sanitizeImageBlocks, Ct as INPUT_PROVENANCE_KIND_VALUES, D as extractToolResultId, Dt as resolveSessionKey, E as extractToolCallsFromAssistant, Et as normalizeInputProvenance, F as formatRawAssistantErrorForUi, Ft as canonicalizeMainSessionAlias, G as isRateLimitAssistantError, Gt as resolveBrowserConfig, H as isFailoverAssistantError, Ht as resolveSessionLockMaxHoldFromTimeout, I as getApiErrorPayloadFingerprint, J as isTransientHttpError, Jt as saveMediaBuffer, K as isRawApiErrorPayload, Kt as resolveProfile, L as isAuthAssistantError, M as classifyFailoverReason, Mt as resolveThreadFlag, N as formatAssistantErrorText, Nt as DEFAULT_RESET_TRIGGERS, O as downgradeOpenAIReasoningBlocks, Ot as evaluateSessionFreshness, P as formatBillingErrorMessage, Pt as resolveFreshSessionTotalTokens, Q as ensureSandboxWorkspaceForSession, Qt as ensureBrowserControlAuth, R as isBillingAssistantError, Rt as resolveMainSessionKey, S as sanitizeSessionMessagesImages, St as extractToolCallNames, T as resolveImageSanitizationLimits, Tt as hasInterSessionUserProvenance, U as isFailoverErrorMessage, Ut as createBrowserRouteContext, V as isContextOverflowError, Vt as acquireSessionWriteLock, W as isLikelyContextOverflowError, Wt as registerBrowserRoutes, X as parseImageSizeError, Xt as resolveExistingPathsWithinRoot, Y as parseImageDimensionError, Yt as DEFAULT_UPLOAD_DIR, Z as sanitizeUserFacingText, Zt as getBridgeAuthForPort, _ as validateAnthropicTurns, _t as normalizeSessionDeliveryFields, an as mergeAlsoAllowPolicy, at as loadSessionStore, b as isMessagingToolDuplicateNormalized, bt as capArrayByJsonBytes, c as normalizeChannelTargetInput, cn as stripPluginOnlyAllowlist, ct as updateLastRoute, d as parseReplyDirectives, dn as buildBootstrapContextFiles, dt as isCacheEnabled, en as applyOwnerOnlyToolPolicy, et as resolveSandboxRuntimeStatus, f as MEDIA_TOKEN_RE, fn as ensureSessionHeader, ft as resolveCacheTtlMs$1, g as initializeGlobalHookRunner, gt as normalizeDeliveryContext, h as getGlobalHookRunner, hn as sanitizeGoogleTurnOrdering, ht as mergeDeliveryContext, in as expandToolGroups, it as resolveAndPersistSessionFile, j as BILLING_ERROR_USER_MESSAGE, jt as resolveSessionResetType, k as isAntigravityClaude, kt as resolveChannelResetConfig, l as normalizeTargetForProvider, ln as compileGlobPatterns, lt as updateSessionStore, m as parseInlineDirectives$1, mn as resolveBootstrapTotalMaxChars, mt as deliveryContextKey, nn as collectExplicitAllowlist, o as normalizeReplyPayloadsForDelivery, on as normalizeToolName$1, ot as readSessionUpdatedAt, p as splitMediaFromOutput, pn as resolveBootstrapMaxChars, pt as deliveryContextFromSession, q as isTimeoutErrorMessage, qt as getMediaDir, rn as expandPolicyWithPluginGroups, rt as appendAssistantMessageToSessionTranscript, s as buildTargetResolverSignature, sn as resolveToolProfilePolicy, st as recordSessionMetaFromInbound, t as deliverOutboundPayloads, tn as buildPluginToolGroups, tt as extractDeliveryInfo, u as throwIfAborted, un as matchesAnyGlobPattern, ut as updateSessionStoreEntry, v as validateGeminiTurns, w as sanitizeToolResultImages, wt as applyInputProvenanceToUserMessage, x as normalizeTextForComparison, xt as countToolResults, y as pickFallbackThinkingLevel, yt as archiveSessionTranscripts, z as isCloudCodeAssistFormatError, zt as deriveSessionMetaPatch } from "./deliver-BiWlR84Y.js";
13
+ 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-DNhyFMRW.js";
14
14
  import { t as parseBooleanValue } from "./boolean-BsqeuxE6.js";
15
15
  import { i as resolveShellEnvFallbackTimeoutMs, n as getShellPathFromLoginShell, s as isTruthyEnvValue } from "./shell-env-B1lDWz4t.js";
16
16
  import { a as applyTestPluginDefaults, c as resolveMemorySlotDecision, d as isDangerousHostEnvVarName, i as safeStatSync, n as discoverSymiPlugins, o as normalizePluginsConfig, r as isPathInside, s as resolveEnableState, t as loadPluginManifestRegistry, u as isPathInsideWithRealpath } from "./manifest-registry-BGJu2aC-.js";
17
- import { C as rawDataToString, O as DEFAULT_AI_SNAPSHOT_MAX_CHARS, T as isSecureWebSocketUrl, x as ensureChromeExtensionRelayServer } from "./chrome-C_I81hbq.js";
17
+ import { C as rawDataToString, O as DEFAULT_AI_SNAPSHOT_MAX_CHARS, T as isSecureWebSocketUrl, x as ensureChromeExtensionRelayServer } from "./chrome-OTJg3QKn.js";
18
18
  import { l as parseFrontmatterBlock } from "./frontmatter-CJEX1BrH.js";
19
19
  import { c as assertSandboxPath, d as resolveSandboxedMediaSource, f as applySkillEnvOverrides, i as resolveSkillsPromptForRun, l as resolveSandboxInputPath, n as buildWorkspaceSkillSnapshot, p as applySkillEnvOverridesFromSnapshot, r as loadWorkspaceSkillEntries, s as assertMediaNotDataUrl } from "./skills-Dm4gX4Tl.js";
20
20
  import { n as redactToolDetail } from "./redact-CSGZUFxa.js";
@@ -25,24 +25,24 @@ import { C as GATEWAY_CLIENT_MODES, S as GATEWAY_CLIENT_IDS, _ as isMarkdownCapa
25
25
  import { t as normalizeChatType } from "./chat-type-CE6cJOyt.js";
26
26
  import { n as resolveConversationLabel } from "./conversation-label-BVa8JTl2.js";
27
27
  import { i as resolveSlackAccount, n as listChannelPlugins, o as resolveSlackAppToken, r as normalizeChannelId$1, s as resolveSlackBotToken, t as getChannelPlugin } from "./plugins-B06cTFHC.js";
28
- import { _ as validateSlackBlocksArray, a as markdownToIRWithMeta, b as resolveSlackChannelId, c as MediaFetchError, d as fetchWithSsrFGuard, f as bindAbortRelay, g as parseSlackBlocksInput, h as resolveSlackWebClientOptions, i as renderMarkdownWithMarkers, l as fetchRemoteMedia, m as createSlackWebClient, o as getDefaultLocalRoots, p as fetchWithTimeout, s as loadWebMedia, t as sendMessageSlack, u as readResponseWithLimit, v as buildSlackBlocksFallbackText, y as parseSlackTarget } from "./send-Cuk_Rjss.js";
28
+ import { _ as validateSlackBlocksArray, a as markdownToIRWithMeta, b as resolveSlackChannelId, c as MediaFetchError, d as fetchWithSsrFGuard, f as bindAbortRelay, g as parseSlackBlocksInput, h as resolveSlackWebClientOptions, i as renderMarkdownWithMarkers, l as fetchRemoteMedia, m as createSlackWebClient, o as getDefaultLocalRoots, p as fetchWithTimeout, s as loadWebMedia, t as sendMessageSlack, u as readResponseWithLimit, v as buildSlackBlocksFallbackText, y as parseSlackTarget } from "./send-C75uSv6p.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 isSilentReplyText, t as SILENT_REPLY_TOKEN } from "./tokens-D_vCJSzF.js";
32
32
  import { a as logMessageProcessed, i as logLaneEnqueue, o as logMessageQueued, r as logLaneDequeue, s as logSessionStateChange, t as diag } from "./diagnostic-BALvP9wI.js";
33
33
  import { n as getDiagnosticSessionState } from "./diagnostic-session-state-BDfanaOY.js";
34
- 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-PTSjHNVq.js";
34
+ 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-CpBJ1BE6.js";
35
35
  import { r as resolveCopilotApiToken, t as DEFAULT_COPILOT_API_BASE_URL } from "./github-copilot-token-uhEBNQfj.js";
36
36
  import { t as ensurePiAuthJsonFromAuthProfiles } from "./pi-auth-json-DCGR3yfh.js";
37
37
  import { a as resolveEffectiveMessagesConfig, i as resolveAckReaction, o as resolveHumanDelayConfig, r as resolveResponsePrefixTemplate, t as createReplyPrefixOptions } from "./reply-prefix-D0NzzC4I.js";
38
38
  import { c as normalizeExtraMemoryPaths, f as runTasksWithConcurrency, s as listMemoryFiles } from "./internal-BYHsj5p6.js";
39
39
  import { n as resolveMarkdownTableMode } from "./markdown-tables-CGqX2WvO.js";
40
- 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-DPZevjMh.js";
41
- 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-BoMrW3WV.js";
40
+ 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-BuOUfpmg.js";
41
+ 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-JIccKWkf.js";
42
42
  import { r as normalizeInboundTextNewlines, t as finalizeInboundContext } from "./inbound-context-DZqZj2qH.js";
43
43
  import { n as discoverModels, t as discoverAuthStorage } from "./pi-model-discovery-Rgm3jE5N.js";
44
44
  import { n as resolveAgentRoute, t as buildAgentSessionKey } from "./resolve-route-CDsQda0z.js";
45
- import { i as resolveSlackThreadTs, n as deliverReplies, t as createSlackReplyDeliveryPlan } from "./replies-DAYTg6Mb.js";
45
+ import { i as resolveSlackThreadTs, n as deliverReplies, t as createSlackReplyDeliveryPlan } from "./replies-D0FYSIJg.js";
46
46
  import { createRequire } from "node:module";
47
47
  import * as path$1 from "node:path";
48
48
  import path from "node:path";
@@ -58,7 +58,7 @@ import crypto, { X509Certificate, createHash, createHmac, randomBytes, randomUUI
58
58
  import { complete, createAssistantMessageEventStream, streamSimple } from "@mariozechner/pi-ai";
59
59
  import AjvPkg from "ajv";
60
60
  import { CURRENT_SESSION_VERSION, DefaultResourceLoader, SessionManager, SettingsManager, codingTools, createAgentSession, createEditTool, createReadTool, createWriteTool, estimateTokens, generateSummary, readTool } from "@mariozechner/pi-coding-agent";
61
- import { WebSocket as WebSocket$1 } from "ws";
61
+ import { WebSocket } from "ws";
62
62
  import { Buffer as Buffer$1 } from "node:buffer";
63
63
  import { BedrockClient, ListFoundationModelsCommand } from "@aws-sdk/client-bedrock";
64
64
  import { createJiti } from "jiti";
@@ -4460,7 +4460,7 @@ async function getMemorySearchManager(params) {
4460
4460
  const wrapper = new FallbackMemoryManager({
4461
4461
  primary,
4462
4462
  fallbackFactory: async () => {
4463
- const { MemoryIndexManager } = await import("./manager-PTSjHNVq.js").then((n) => n.t);
4463
+ const { MemoryIndexManager } = await import("./manager-CpBJ1BE6.js").then((n) => n.t);
4464
4464
  return await MemoryIndexManager.get(params);
4465
4465
  }
4466
4466
  }, () => QMD_MANAGER_CACHE.delete(cacheKey));
@@ -4473,7 +4473,7 @@ async function getMemorySearchManager(params) {
4473
4473
  }
4474
4474
  }
4475
4475
  try {
4476
- const { MemoryIndexManager } = await import("./manager-PTSjHNVq.js").then((n) => n.t);
4476
+ const { MemoryIndexManager } = await import("./manager-CpBJ1BE6.js").then((n) => n.t);
4477
4477
  return { manager: await MemoryIndexManager.get(params) };
4478
4478
  } catch (err) {
4479
4479
  return {
@@ -9621,7 +9621,7 @@ var GatewayClient = class {
9621
9621
  if (fingerprint !== expected) return /* @__PURE__ */ new Error("gateway tls fingerprint mismatch");
9622
9622
  });
9623
9623
  }
9624
- this.ws = new WebSocket$1(url, wsOptions);
9624
+ this.ws = new WebSocket(url, wsOptions);
9625
9625
  this.ws.on("open", () => {
9626
9626
  if (url.startsWith("wss://") && this.opts.tlsFingerprint) {
9627
9627
  const tlsError = this.validateTlsFingerprint();
@@ -9840,7 +9840,7 @@ var GatewayClient = class {
9840
9840
  return null;
9841
9841
  }
9842
9842
  async request(method, params, opts) {
9843
- if (!this.ws || this.ws.readyState !== WebSocket$1.OPEN) throw new Error("gateway not connected");
9843
+ if (!this.ws || this.ws.readyState !== WebSocket.OPEN) throw new Error("gateway not connected");
9844
9844
  const id = randomUUID();
9845
9845
  const frame = {
9846
9846
  type: "req",
@@ -10801,7 +10801,7 @@ async function routeReply(params) {
10801
10801
  const resolvedReplyToId = replyToId ?? (channelId === "slack" && threadId != null && threadId !== "" ? String(threadId) : void 0);
10802
10802
  const resolvedThreadId = channelId === "slack" ? null : threadId ?? null;
10803
10803
  try {
10804
- const { deliverOutboundPayloads } = await import("./deliver-DyO3QD8O.js").then((n) => n.n);
10804
+ const { deliverOutboundPayloads } = await import("./deliver-BiWlR84Y.js").then((n) => n.n);
10805
10805
  return {
10806
10806
  ok: true,
10807
10807
  messageId: (await deliverOutboundPayloads({
@@ -19778,13 +19778,21 @@ async function applyMediaUnderstanding(params) {
19778
19778
  * Soft warning appended when context usage crosses the threshold.
19779
19779
  * Fires once per session (tracked via `SessionEntry.contextWarningSent`).
19780
19780
  */
19781
- const SESSION_CONTEXT_WARNING_MESSAGE = "📋 Heads up — this session is approaching the context limit. Start a new session for best results. Past sessions stay in history and can be revisited there.";
19781
+ const SESSION_CONTEXT_WARNING_MESSAGE = "📋 Heads up — this session is approaching the context limit. Symi will compact older context automatically when usage reaches 90%.";
19782
19782
  /**
19783
- * Hard limit message returned when the model API rejects the turn for
19784
- * context-too-long or role-ordering reasons, and on every subsequent
19785
- * turn until the user starts a new session.
19783
+ * Inline status emitted by Symi before running compaction proactively
19784
+ * at the 90% threshold. Followed by the agent's actual response in the
19785
+ * same turn.
19786
19786
  */
19787
- const SESSION_OVERFLOW_MESSAGE = "📋 This session has reached the context limit. Please start a new session — your full conversation is saved in history and can be revisited there.";
19787
+ const SESSION_COMPACTING_MESSAGE = "📋 Context limit reached for this session. Compacting older context and continuing…";
19788
+ /**
19789
+ * Returned when compaction can't recover enough budget to continue —
19790
+ * either because the proactive compaction at 90% failed, or because a
19791
+ * single user message overshot the window in one turn and the reactive
19792
+ * fallback compaction also failed. Same message also short-circuits
19793
+ * subsequent turns until /reset or /new.
19794
+ */
19795
+ const SESSION_COMPACTION_FAILED_MESSAGE = "📋 Couldn't compact this session further. Please /reset or /new to continue — your full conversation is saved in history.";
19788
19796
 
19789
19797
  //#endregion
19790
19798
  //#region src/sessions/level-overrides.ts
@@ -28056,7 +28064,6 @@ function formatTokenCount$1(value) {
28056
28064
  function formatUsd(value) {
28057
28065
  if (value === void 0 || !Number.isFinite(value)) return;
28058
28066
  if (value >= 1) return `$${value.toFixed(2)}`;
28059
- if (value >= .01) return `$${value.toFixed(2)}`;
28060
28067
  return `$${value.toFixed(4)}`;
28061
28068
  }
28062
28069
  function resolveModelCostConfig(params) {
@@ -28131,13 +28138,13 @@ function resolveRuntimeLabel(args) {
28131
28138
  return sessionKey !== resolveMainSessionKey({ session: { scope: args.sessionScope ?? "per-sender" } }).trim();
28132
28139
  })() ? "docker" : sessionKey ? "direct" : "unknown"}/${sandboxMode}`;
28133
28140
  }
28134
- const formatTokens = (total, contextTokens) => {
28141
+ const formatTokens$1 = (total, contextTokens) => {
28135
28142
  const ctx = contextTokens ?? null;
28136
28143
  if (total == null) return `?/${ctx ? formatTokenCount(ctx) : "?"}`;
28137
28144
  const pct = ctx ? Math.min(999, Math.round(total / ctx * 100)) : null;
28138
28145
  return `${formatTokenCount(total)}/${ctx ? formatTokenCount(ctx) : "?"}${pct !== null ? ` (${pct}%)` : ""}`;
28139
28146
  };
28140
- const formatContextUsageShort = (total, contextTokens) => `Context ${formatTokens(total, contextTokens ?? null)}`;
28147
+ const formatContextUsageShort = (total, contextTokens) => `Context ${formatTokens$1(total, contextTokens ?? null)}`;
28141
28148
  const formatQueueDetails = (queue) => {
28142
28149
  if (!queue) return "";
28143
28150
  const depth = typeof queue.depth === "number" ? `depth ${queue.depth}` : null;
@@ -28289,7 +28296,7 @@ function buildStatusMessage(args) {
28289
28296
  const updatedAt = entry?.updatedAt;
28290
28297
  const sessionLine = [`Session: ${args.sessionKey ?? "unknown"}`, typeof updatedAt === "number" ? `updated ${formatTimeAgo(now - updatedAt)}` : "no activity"].filter(Boolean).join(" • ");
28291
28298
  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;
28292
- const contextLine = [`Context: ${formatTokens(totalTokens, contextTokens ?? null)}`, `🧹 Compactions: ${entry?.compactionCount ?? 0}`].filter(Boolean).join(" · ");
28299
+ const contextLine = [`Context: ${formatTokens$1(totalTokens, contextTokens ?? null)}`, `🧹 Compactions: ${entry?.compactionCount ?? 0}`].filter(Boolean).join(" · ");
28293
28300
  const queueMode = args.queue?.mode ?? "unknown";
28294
28301
  const queueDetails = formatQueueDetails(args.queue);
28295
28302
  const verboseLabel = verboseLevel === "full" ? "verbose:full" : verboseLevel === "on" ? "verbose" : null;
@@ -28321,14 +28328,19 @@ function buildStatusMessage(args) {
28321
28328
  config: args.config
28322
28329
  }) : void 0;
28323
28330
  const hasUsage = typeof inputTokens === "number" || typeof outputTokens === "number";
28324
- const cost = showCost && hasUsage ? estimateUsageCost({
28331
+ const rawCost = showCost && hasUsage ? estimateUsageCost({
28325
28332
  usage: {
28326
28333
  input: inputTokens ?? void 0,
28327
28334
  output: outputTokens ?? void 0
28328
28335
  },
28329
28336
  cost: costConfig
28330
28337
  }) : void 0;
28331
- const costLabel = showCost && hasUsage ? formatUsd(cost) : void 0;
28338
+ const useOverride = showCost && hasUsage && typeof args.costOverrideUsd === "number" && (rawCost === void 0 || rawCost === 0);
28339
+ const cost = useOverride ? args.costOverrideUsd : rawCost;
28340
+ const baseLabel = showCost && hasUsage ? formatUsd(cost) : void 0;
28341
+ const tag = useOverride ? " (self-hosted)" : "";
28342
+ const suffix = args.costLineSuffix ? ` · ${args.costLineSuffix}` : "";
28343
+ const costLabel = baseLabel ? `${baseLabel}${tag}${suffix}` : void 0;
28332
28344
  const selectedAuthLabel = selectedAuthLabelValue ? ` · 🔑 ${selectedAuthLabelValue}` : "";
28333
28345
  const channelModelNote = (() => {
28334
28346
  if (!args.config || !entry) return;
@@ -28373,6 +28385,8 @@ function buildStatusMessage(args) {
28373
28385
  fallbackLine,
28374
28386
  usageCostLine,
28375
28387
  cacheLine,
28388
+ args.engineLine,
28389
+ args.hardwareLine,
28376
28390
  `📚 ${contextLine}`,
28377
28391
  mediaLine,
28378
28392
  args.usageLine,
@@ -28949,6 +28963,606 @@ const handleDebugCommand = async (params, allowTextCommands) => {
28949
28963
  return null;
28950
28964
  };
28951
28965
 
28966
+ //#endregion
28967
+ //#region src/infra/session-cost-usage.ts
28968
+ const emptyTotals = () => ({
28969
+ input: 0,
28970
+ output: 0,
28971
+ cacheRead: 0,
28972
+ cacheWrite: 0,
28973
+ totalTokens: 0,
28974
+ totalCost: 0,
28975
+ inputCost: 0,
28976
+ outputCost: 0,
28977
+ cacheReadCost: 0,
28978
+ cacheWriteCost: 0,
28979
+ missingCostEntries: 0
28980
+ });
28981
+ const toFiniteNumber = (value) => {
28982
+ if (typeof value !== "number") return;
28983
+ if (!Number.isFinite(value)) return;
28984
+ return value;
28985
+ };
28986
+ const extractCostBreakdown = (usageRaw) => {
28987
+ if (!usageRaw || typeof usageRaw !== "object") return;
28988
+ const cost = usageRaw.cost;
28989
+ if (!cost) return;
28990
+ const total = toFiniteNumber(cost.total);
28991
+ if (total === void 0 || total < 0) return;
28992
+ return {
28993
+ total,
28994
+ input: toFiniteNumber(cost.input),
28995
+ output: toFiniteNumber(cost.output),
28996
+ cacheRead: toFiniteNumber(cost.cacheRead),
28997
+ cacheWrite: toFiniteNumber(cost.cacheWrite)
28998
+ };
28999
+ };
29000
+ const parseTimestamp = (entry) => {
29001
+ const raw = entry.timestamp;
29002
+ if (typeof raw === "string") {
29003
+ const parsed = new Date(raw);
29004
+ if (!Number.isNaN(parsed.valueOf())) return parsed;
29005
+ }
29006
+ const message = entry.message;
29007
+ const messageTimestamp = toFiniteNumber(message?.timestamp);
29008
+ if (messageTimestamp !== void 0) {
29009
+ const parsed = new Date(messageTimestamp);
29010
+ if (!Number.isNaN(parsed.valueOf())) return parsed;
29011
+ }
29012
+ };
29013
+ const parseTranscriptEntry = (entry) => {
29014
+ const message = entry.message;
29015
+ if (!message || typeof message !== "object") return null;
29016
+ const roleRaw = message.role;
29017
+ const role = roleRaw === "user" || roleRaw === "assistant" ? roleRaw : void 0;
29018
+ if (!role) return null;
29019
+ const usageRaw = message.usage ?? entry.usage;
29020
+ const usage = usageRaw ? normalizeUsage(usageRaw) ?? void 0 : void 0;
29021
+ const provider = (typeof message.provider === "string" ? message.provider : void 0) ?? (typeof entry.provider === "string" ? entry.provider : void 0);
29022
+ const model = (typeof message.model === "string" ? message.model : void 0) ?? (typeof entry.model === "string" ? entry.model : void 0);
29023
+ const costBreakdown = extractCostBreakdown(usageRaw);
29024
+ const stopReason = typeof message.stopReason === "string" ? message.stopReason : void 0;
29025
+ const durationMs = toFiniteNumber(message.durationMs ?? entry.durationMs);
29026
+ return {
29027
+ message,
29028
+ role,
29029
+ timestamp: parseTimestamp(entry),
29030
+ durationMs,
29031
+ usage,
29032
+ costTotal: costBreakdown?.total,
29033
+ costBreakdown,
29034
+ provider,
29035
+ model,
29036
+ stopReason,
29037
+ toolNames: extractToolCallNames(message),
29038
+ toolResultCounts: countToolResults(message)
29039
+ };
29040
+ };
29041
+ const formatDayKey = (date) => date.toLocaleDateString("en-CA", { timeZone: Intl.DateTimeFormat().resolvedOptions().timeZone });
29042
+ const computeLatencyStats = (values) => {
29043
+ if (!values.length) return;
29044
+ const sorted = values.toSorted((a, b) => a - b);
29045
+ const total = sorted.reduce((sum, v) => sum + v, 0);
29046
+ const count = sorted.length;
29047
+ const p95Index = Math.max(0, Math.ceil(count * .95) - 1);
29048
+ return {
29049
+ count,
29050
+ avgMs: total / count,
29051
+ p95Ms: sorted[p95Index] ?? sorted[count - 1],
29052
+ minMs: sorted[0],
29053
+ maxMs: sorted[count - 1]
29054
+ };
29055
+ };
29056
+ const applyUsageTotals = (totals, usage) => {
29057
+ totals.input += usage.input ?? 0;
29058
+ totals.output += usage.output ?? 0;
29059
+ totals.cacheRead += usage.cacheRead ?? 0;
29060
+ totals.cacheWrite += usage.cacheWrite ?? 0;
29061
+ const totalTokens = usage.total ?? (usage.input ?? 0) + (usage.output ?? 0) + (usage.cacheRead ?? 0) + (usage.cacheWrite ?? 0);
29062
+ totals.totalTokens += totalTokens;
29063
+ };
29064
+ const applyCostBreakdown = (totals, costBreakdown) => {
29065
+ if (costBreakdown === void 0 || costBreakdown.total === void 0) return;
29066
+ totals.totalCost += costBreakdown.total;
29067
+ totals.inputCost += costBreakdown.input ?? 0;
29068
+ totals.outputCost += costBreakdown.output ?? 0;
29069
+ totals.cacheReadCost += costBreakdown.cacheRead ?? 0;
29070
+ totals.cacheWriteCost += costBreakdown.cacheWrite ?? 0;
29071
+ };
29072
+ const applyCostTotal = (totals, costTotal) => {
29073
+ if (costTotal === void 0) {
29074
+ totals.missingCostEntries += 1;
29075
+ return;
29076
+ }
29077
+ totals.totalCost += costTotal;
29078
+ };
29079
+ async function* readJsonlRecords(filePath) {
29080
+ const fileStream = fs.createReadStream(filePath, { encoding: "utf-8" });
29081
+ const rl = readline.createInterface({
29082
+ input: fileStream,
29083
+ crlfDelay: Infinity
29084
+ });
29085
+ try {
29086
+ for await (const line of rl) {
29087
+ const trimmed = line.trim();
29088
+ if (!trimmed) continue;
29089
+ try {
29090
+ const parsed = JSON.parse(trimmed);
29091
+ if (!parsed || typeof parsed !== "object") continue;
29092
+ yield parsed;
29093
+ } catch {}
29094
+ }
29095
+ } finally {
29096
+ rl.close();
29097
+ fileStream.destroy();
29098
+ }
29099
+ }
29100
+ async function scanTranscriptFile(params) {
29101
+ for await (const parsed of readJsonlRecords(params.filePath)) {
29102
+ const entry = parseTranscriptEntry(parsed);
29103
+ if (!entry) continue;
29104
+ if (entry.usage && entry.costTotal === void 0) {
29105
+ const cost = resolveModelCostConfig({
29106
+ provider: entry.provider,
29107
+ model: entry.model,
29108
+ config: params.config
29109
+ });
29110
+ entry.costTotal = estimateUsageCost({
29111
+ usage: entry.usage,
29112
+ cost
29113
+ });
29114
+ }
29115
+ params.onEntry(entry);
29116
+ }
29117
+ }
29118
+ async function scanUsageFile(params) {
29119
+ await scanTranscriptFile({
29120
+ filePath: params.filePath,
29121
+ config: params.config,
29122
+ onEntry: (entry) => {
29123
+ if (!entry.usage) return;
29124
+ params.onEntry({
29125
+ usage: entry.usage,
29126
+ costTotal: entry.costTotal,
29127
+ costBreakdown: entry.costBreakdown,
29128
+ provider: entry.provider,
29129
+ model: entry.model,
29130
+ timestamp: entry.timestamp
29131
+ });
29132
+ }
29133
+ });
29134
+ }
29135
+ async function loadCostUsageSummary(params) {
29136
+ const now = /* @__PURE__ */ new Date();
29137
+ let sinceTime;
29138
+ let untilTime;
29139
+ if (params?.startMs !== void 0 && params?.endMs !== void 0) {
29140
+ sinceTime = params.startMs;
29141
+ untilTime = params.endMs;
29142
+ } else {
29143
+ const days = Math.max(1, Math.floor(params?.days ?? 30));
29144
+ const since = new Date(now);
29145
+ since.setDate(since.getDate() - (days - 1));
29146
+ sinceTime = since.getTime();
29147
+ untilTime = now.getTime();
29148
+ }
29149
+ const dailyMap = /* @__PURE__ */ new Map();
29150
+ const totals = emptyTotals();
29151
+ const sessionsDir = resolveSessionTranscriptsDirForAgent(params?.agentId);
29152
+ const entries = await fs.promises.readdir(sessionsDir, { withFileTypes: true }).catch(() => []);
29153
+ const files = (await Promise.all(entries.filter((entry) => entry.isFile() && entry.name.endsWith(".jsonl")).map(async (entry) => {
29154
+ const filePath = path.join(sessionsDir, entry.name);
29155
+ const stats = await fs.promises.stat(filePath).catch(() => null);
29156
+ if (!stats) return null;
29157
+ if (stats.mtimeMs < sinceTime) return null;
29158
+ return filePath;
29159
+ }))).filter((filePath) => Boolean(filePath));
29160
+ for (const filePath of files) await scanUsageFile({
29161
+ filePath,
29162
+ config: params?.config,
29163
+ onEntry: (entry) => {
29164
+ const ts = entry.timestamp?.getTime();
29165
+ if (!ts || ts < sinceTime || ts > untilTime) return;
29166
+ const dayKey = formatDayKey(entry.timestamp ?? now);
29167
+ const bucket = dailyMap.get(dayKey) ?? emptyTotals();
29168
+ applyUsageTotals(bucket, entry.usage);
29169
+ if (entry.costBreakdown?.total !== void 0) applyCostBreakdown(bucket, entry.costBreakdown);
29170
+ else applyCostTotal(bucket, entry.costTotal);
29171
+ dailyMap.set(dayKey, bucket);
29172
+ applyUsageTotals(totals, entry.usage);
29173
+ if (entry.costBreakdown?.total !== void 0) applyCostBreakdown(totals, entry.costBreakdown);
29174
+ else applyCostTotal(totals, entry.costTotal);
29175
+ }
29176
+ });
29177
+ const daily = Array.from(dailyMap.entries()).map(([date, bucket]) => Object.assign({ date }, bucket)).toSorted((a, b) => a.date.localeCompare(b.date));
29178
+ const days = Math.ceil((untilTime - sinceTime) / (1440 * 60 * 1e3)) + 1;
29179
+ return {
29180
+ updatedAt: Date.now(),
29181
+ days,
29182
+ daily,
29183
+ totals
29184
+ };
29185
+ }
29186
+ async function loadSessionCostSummary(params) {
29187
+ const sessionFile = params.sessionFile ?? (params.sessionId ? resolveSessionFilePath(params.sessionId, params.sessionEntry, { agentId: params.agentId }) : void 0);
29188
+ if (!sessionFile || !fs.existsSync(sessionFile)) return null;
29189
+ const totals = emptyTotals();
29190
+ let firstActivity;
29191
+ let lastActivity;
29192
+ const activityDatesSet = /* @__PURE__ */ new Set();
29193
+ const dailyMap = /* @__PURE__ */ new Map();
29194
+ const dailyMessageMap = /* @__PURE__ */ new Map();
29195
+ const dailyLatencyMap = /* @__PURE__ */ new Map();
29196
+ const dailyModelUsageMap = /* @__PURE__ */ new Map();
29197
+ const messageCounts = {
29198
+ total: 0,
29199
+ user: 0,
29200
+ assistant: 0,
29201
+ toolCalls: 0,
29202
+ toolResults: 0,
29203
+ errors: 0
29204
+ };
29205
+ const toolUsageMap = /* @__PURE__ */ new Map();
29206
+ const modelUsageMap = /* @__PURE__ */ new Map();
29207
+ const errorStopReasons = new Set([
29208
+ "error",
29209
+ "aborted",
29210
+ "timeout"
29211
+ ]);
29212
+ const latencyValues = [];
29213
+ let lastUserTimestamp;
29214
+ const MAX_LATENCY_MS = 720 * 60 * 1e3;
29215
+ await scanTranscriptFile({
29216
+ filePath: sessionFile,
29217
+ config: params.config,
29218
+ onEntry: (entry) => {
29219
+ const ts = entry.timestamp?.getTime();
29220
+ if (params.startMs !== void 0 && ts !== void 0 && ts < params.startMs) return;
29221
+ if (params.endMs !== void 0 && ts !== void 0 && ts > params.endMs) return;
29222
+ if (ts !== void 0) {
29223
+ if (!firstActivity || ts < firstActivity) firstActivity = ts;
29224
+ if (!lastActivity || ts > lastActivity) lastActivity = ts;
29225
+ }
29226
+ if (entry.role === "user") {
29227
+ messageCounts.user += 1;
29228
+ messageCounts.total += 1;
29229
+ if (entry.timestamp) lastUserTimestamp = entry.timestamp.getTime();
29230
+ }
29231
+ if (entry.role === "assistant") {
29232
+ messageCounts.assistant += 1;
29233
+ messageCounts.total += 1;
29234
+ const ts = entry.timestamp?.getTime();
29235
+ if (ts !== void 0) {
29236
+ const latencyMs = entry.durationMs ?? (lastUserTimestamp !== void 0 ? Math.max(0, ts - lastUserTimestamp) : void 0);
29237
+ if (latencyMs !== void 0 && Number.isFinite(latencyMs) && latencyMs <= MAX_LATENCY_MS) {
29238
+ latencyValues.push(latencyMs);
29239
+ const dayKey = formatDayKey(entry.timestamp ?? new Date(ts));
29240
+ const dailyLatencies = dailyLatencyMap.get(dayKey) ?? [];
29241
+ dailyLatencies.push(latencyMs);
29242
+ dailyLatencyMap.set(dayKey, dailyLatencies);
29243
+ }
29244
+ }
29245
+ }
29246
+ if (entry.toolNames.length > 0) {
29247
+ messageCounts.toolCalls += entry.toolNames.length;
29248
+ for (const name of entry.toolNames) toolUsageMap.set(name, (toolUsageMap.get(name) ?? 0) + 1);
29249
+ }
29250
+ if (entry.toolResultCounts.total > 0) {
29251
+ messageCounts.toolResults += entry.toolResultCounts.total;
29252
+ messageCounts.errors += entry.toolResultCounts.errors;
29253
+ }
29254
+ if (entry.stopReason && errorStopReasons.has(entry.stopReason)) messageCounts.errors += 1;
29255
+ if (entry.timestamp) {
29256
+ const dayKey = formatDayKey(entry.timestamp);
29257
+ activityDatesSet.add(dayKey);
29258
+ const daily = dailyMessageMap.get(dayKey) ?? {
29259
+ date: dayKey,
29260
+ total: 0,
29261
+ user: 0,
29262
+ assistant: 0,
29263
+ toolCalls: 0,
29264
+ toolResults: 0,
29265
+ errors: 0
29266
+ };
29267
+ daily.total += entry.role === "user" || entry.role === "assistant" ? 1 : 0;
29268
+ if (entry.role === "user") daily.user += 1;
29269
+ else if (entry.role === "assistant") daily.assistant += 1;
29270
+ daily.toolCalls += entry.toolNames.length;
29271
+ daily.toolResults += entry.toolResultCounts.total;
29272
+ daily.errors += entry.toolResultCounts.errors;
29273
+ if (entry.stopReason && errorStopReasons.has(entry.stopReason)) daily.errors += 1;
29274
+ dailyMessageMap.set(dayKey, daily);
29275
+ }
29276
+ if (!entry.usage) return;
29277
+ applyUsageTotals(totals, entry.usage);
29278
+ if (entry.costBreakdown?.total !== void 0) applyCostBreakdown(totals, entry.costBreakdown);
29279
+ else applyCostTotal(totals, entry.costTotal);
29280
+ if (entry.timestamp) {
29281
+ const dayKey = formatDayKey(entry.timestamp);
29282
+ const entryTokens = (entry.usage.input ?? 0) + (entry.usage.output ?? 0) + (entry.usage.cacheRead ?? 0) + (entry.usage.cacheWrite ?? 0);
29283
+ 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);
29284
+ const existing = dailyMap.get(dayKey) ?? {
29285
+ tokens: 0,
29286
+ cost: 0
29287
+ };
29288
+ dailyMap.set(dayKey, {
29289
+ tokens: existing.tokens + entryTokens,
29290
+ cost: existing.cost + entryCost
29291
+ });
29292
+ if (entry.provider || entry.model) {
29293
+ const modelKey = `${dayKey}::${entry.provider ?? "unknown"}::${entry.model ?? "unknown"}`;
29294
+ const dailyModel = dailyModelUsageMap.get(modelKey) ?? {
29295
+ date: dayKey,
29296
+ provider: entry.provider,
29297
+ model: entry.model,
29298
+ tokens: 0,
29299
+ cost: 0,
29300
+ count: 0
29301
+ };
29302
+ dailyModel.tokens += entryTokens;
29303
+ dailyModel.cost += entryCost;
29304
+ dailyModel.count += 1;
29305
+ dailyModelUsageMap.set(modelKey, dailyModel);
29306
+ }
29307
+ }
29308
+ if (entry.provider || entry.model) {
29309
+ const key = `${entry.provider ?? "unknown"}::${entry.model ?? "unknown"}`;
29310
+ const existing = modelUsageMap.get(key) ?? {
29311
+ provider: entry.provider,
29312
+ model: entry.model,
29313
+ count: 0,
29314
+ totals: emptyTotals()
29315
+ };
29316
+ existing.count += 1;
29317
+ applyUsageTotals(existing.totals, entry.usage);
29318
+ if (entry.costBreakdown?.total !== void 0) applyCostBreakdown(existing.totals, entry.costBreakdown);
29319
+ else applyCostTotal(existing.totals, entry.costTotal);
29320
+ modelUsageMap.set(key, existing);
29321
+ }
29322
+ }
29323
+ });
29324
+ const dailyBreakdown = Array.from(dailyMap.entries()).map(([date, data]) => ({
29325
+ date,
29326
+ tokens: data.tokens,
29327
+ cost: data.cost
29328
+ })).toSorted((a, b) => a.date.localeCompare(b.date));
29329
+ const dailyMessageCounts = Array.from(dailyMessageMap.values()).toSorted((a, b) => a.date.localeCompare(b.date));
29330
+ const dailyLatency = Array.from(dailyLatencyMap.entries()).map(([date, values]) => {
29331
+ const stats = computeLatencyStats(values);
29332
+ if (!stats) return null;
29333
+ return {
29334
+ date,
29335
+ ...stats
29336
+ };
29337
+ }).filter((entry) => Boolean(entry)).toSorted((a, b) => a.date.localeCompare(b.date));
29338
+ const dailyModelUsage = Array.from(dailyModelUsageMap.values()).toSorted((a, b) => a.date.localeCompare(b.date) || b.cost - a.cost);
29339
+ const toolUsage = toolUsageMap.size ? {
29340
+ totalCalls: Array.from(toolUsageMap.values()).reduce((sum, count) => sum + count, 0),
29341
+ uniqueTools: toolUsageMap.size,
29342
+ tools: Array.from(toolUsageMap.entries()).map(([name, count]) => ({
29343
+ name,
29344
+ count
29345
+ })).toSorted((a, b) => b.count - a.count)
29346
+ } : void 0;
29347
+ const modelUsage = modelUsageMap.size ? Array.from(modelUsageMap.values()).toSorted((a, b) => {
29348
+ const costDiff = b.totals.totalCost - a.totals.totalCost;
29349
+ if (costDiff !== 0) return costDiff;
29350
+ return b.totals.totalTokens - a.totals.totalTokens;
29351
+ }) : void 0;
29352
+ return {
29353
+ sessionId: params.sessionId,
29354
+ sessionFile,
29355
+ firstActivity,
29356
+ lastActivity,
29357
+ durationMs: firstActivity !== void 0 && lastActivity !== void 0 ? Math.max(0, lastActivity - firstActivity) : void 0,
29358
+ activityDates: Array.from(activityDatesSet).toSorted(),
29359
+ dailyBreakdown,
29360
+ dailyMessageCounts,
29361
+ dailyLatency: dailyLatency.length ? dailyLatency : void 0,
29362
+ dailyModelUsage: dailyModelUsage.length ? dailyModelUsage : void 0,
29363
+ messageCounts,
29364
+ toolUsage,
29365
+ modelUsage,
29366
+ latency: computeLatencyStats(latencyValues),
29367
+ ...totals
29368
+ };
29369
+ }
29370
+
29371
+ //#endregion
29372
+ //#region src/cost/benchmark.ts
29373
+ /**
29374
+ * Claude reference rates and benchmark comparison.
29375
+ *
29376
+ * Hardcoded per-token USD rates for Claude Opus 4.7, Sonnet 4.6, and
29377
+ * Haiku 4.5 (per million tokens, Anthropic public list as of 2026-Q1).
29378
+ * Override via `models.gpuRates` is for GPU rates only — Claude rates can
29379
+ * be overridden via the per-model `cost: { input, output }` configuration
29380
+ * on the user's `anthropic` provider entry, which already exists.
29381
+ *
29382
+ * Display: pick a target tier via `agents.defaults.cost.benchmark`, default
29383
+ * `sonnet`. Setting `"all"` shows comparisons against all three tiers.
29384
+ */
29385
+ /** Per-million-token USD rates, applied via `estimateUsageCost`. */
29386
+ const CLAUDE_RATES = {
29387
+ opus: {
29388
+ input: 15,
29389
+ output: 75,
29390
+ cacheRead: 1.5,
29391
+ cacheWrite: 18.75
29392
+ },
29393
+ sonnet: {
29394
+ input: 3,
29395
+ output: 15,
29396
+ cacheRead: .3,
29397
+ cacheWrite: 3.75
29398
+ },
29399
+ haiku: {
29400
+ input: .8,
29401
+ output: 4,
29402
+ cacheRead: .08,
29403
+ cacheWrite: 1
29404
+ }
29405
+ };
29406
+ const CLAUDE_LABEL = {
29407
+ opus: "Claude Opus 4.7",
29408
+ sonnet: "Claude Sonnet 4.6",
29409
+ haiku: "Claude Haiku 4.5"
29410
+ };
29411
+ function benchmarkUsage(args) {
29412
+ if (!args.usage) return [];
29413
+ const tiers = args.target === "all" ? [
29414
+ "opus",
29415
+ "sonnet",
29416
+ "haiku"
29417
+ ] : [args.target];
29418
+ const results = [];
29419
+ for (const tier of tiers) {
29420
+ const cost = estimateUsageCost({
29421
+ usage: args.usage,
29422
+ cost: CLAUDE_RATES[tier]
29423
+ });
29424
+ if (cost === void 0) continue;
29425
+ results.push({
29426
+ tier,
29427
+ costUsd: cost
29428
+ });
29429
+ }
29430
+ return results;
29431
+ }
29432
+ function formatBenchmarkSuffix(args) {
29433
+ if (args.benchmarks.length === 0) return;
29434
+ if (args.benchmarks.length === 1) {
29435
+ const b = args.benchmarks[0];
29436
+ return formatPair(args.ourCostUsd, b);
29437
+ }
29438
+ const parts = [];
29439
+ for (const b of args.benchmarks) parts.push(`${shortLabel(b.tier)} $${formatCostShort(b.costUsd)}`);
29440
+ const cheapest = args.benchmarks.reduce((min, b) => b.costUsd < min.costUsd ? b : min);
29441
+ if (cheapest.costUsd > args.ourCostUsd && cheapest.costUsd > 0) {
29442
+ const savedPct = (cheapest.costUsd - args.ourCostUsd) / cheapest.costUsd * 100;
29443
+ if (savedPct >= 1) parts.push(`save ${savedPct.toFixed(0)}% vs ${shortLabel(cheapest.tier)}`);
29444
+ }
29445
+ return `vs ${parts.join(" / ")}`;
29446
+ }
29447
+ function formatPair(ourCost, b) {
29448
+ const benchPart = `${CLAUDE_LABEL[b.tier]} would be $${formatCostShort(b.costUsd)}`;
29449
+ if (b.costUsd > 0 && b.costUsd > ourCost) {
29450
+ const saved = (b.costUsd - ourCost) / b.costUsd * 100;
29451
+ if (saved >= 1) return `${benchPart} (save ${saved.toFixed(0)}%)`;
29452
+ } else if (b.costUsd > 0 && ourCost > b.costUsd) {
29453
+ const overspend = (ourCost - b.costUsd) / b.costUsd * 100;
29454
+ if (overspend >= 1) return `${benchPart} (+${overspend.toFixed(0)}%)`;
29455
+ }
29456
+ return benchPart;
29457
+ }
29458
+ function shortLabel(tier) {
29459
+ if (tier === "opus") return "Opus";
29460
+ if (tier === "sonnet") return "Sonnet";
29461
+ return "Haiku";
29462
+ }
29463
+ function formatCostShort(value) {
29464
+ if (value >= 1) return value.toFixed(2);
29465
+ return value.toFixed(4);
29466
+ }
29467
+ function isClaudeTier(value) {
29468
+ return value === "opus" || value === "sonnet" || value === "haiku";
29469
+ }
29470
+ function isBenchmarkTarget(value) {
29471
+ return isClaudeTier(value) || value === "all";
29472
+ }
29473
+ function resolveBenchmarkTarget(value) {
29474
+ if (typeof value === "string" && isBenchmarkTarget(value)) return value;
29475
+ return "sonnet";
29476
+ }
29477
+
29478
+ //#endregion
29479
+ //#region src/cost/summary.ts
29480
+ async function loadCostBenchmarkSummary(params) {
29481
+ const summary = await loadCostUsageSummary(params);
29482
+ const daily = summary.daily.map((day) => ({
29483
+ ...day,
29484
+ benchmarkUsd: computeBenchmarkPerTier(day)
29485
+ }));
29486
+ const benchmarkTotals = computeBenchmarkPerTier(summary.totals);
29487
+ const savingsTotals = {
29488
+ opus: benchmarkTotals.opus - summary.totals.totalCost,
29489
+ sonnet: benchmarkTotals.sonnet - summary.totals.totalCost,
29490
+ haiku: benchmarkTotals.haiku - summary.totals.totalCost
29491
+ };
29492
+ return {
29493
+ ...summary,
29494
+ daily,
29495
+ benchmarkTotals,
29496
+ savingsTotals
29497
+ };
29498
+ }
29499
+ function computeBenchmarkPerTier(totals) {
29500
+ const all = benchmarkUsage({
29501
+ usage: {
29502
+ input: totals.input,
29503
+ output: totals.output,
29504
+ cacheRead: totals.cacheRead,
29505
+ cacheWrite: totals.cacheWrite
29506
+ },
29507
+ target: "all"
29508
+ });
29509
+ const map = new Map(all.map((b) => [b.tier, b.costUsd]));
29510
+ return {
29511
+ opus: map.get("opus") ?? 0,
29512
+ sonnet: map.get("sonnet") ?? 0,
29513
+ haiku: map.get("haiku") ?? 0
29514
+ };
29515
+ }
29516
+ function resolveWindow(window, now = Date.now()) {
29517
+ const end = now;
29518
+ switch (window) {
29519
+ case "today": {
29520
+ const d = new Date(end);
29521
+ d.setHours(0, 0, 0, 0);
29522
+ return {
29523
+ startMs: d.getTime(),
29524
+ endMs: end
29525
+ };
29526
+ }
29527
+ case "week": return {
29528
+ startMs: end - 10080 * 6e4,
29529
+ endMs: end
29530
+ };
29531
+ case "month": return {
29532
+ startMs: end - 720 * 60 * 6e4,
29533
+ endMs: end
29534
+ };
29535
+ case "all": return {
29536
+ startMs: 0,
29537
+ endMs: end
29538
+ };
29539
+ }
29540
+ }
29541
+ function formatSummaryReport(summary, label) {
29542
+ const t = summary.totals;
29543
+ const b = summary.benchmarkTotals;
29544
+ const lines = [];
29545
+ if (label) lines.push(`# ${label}`);
29546
+ lines.push(`Tokens: ${formatTokens(t.totalTokens)} (${formatTokens(t.input)} in / ${formatTokens(t.output)} out)`);
29547
+ lines.push(`Spend: $${t.totalCost.toFixed(4)}`);
29548
+ lines.push(`Claude equivalents:`);
29549
+ lines.push(` Opus: $${b.opus.toFixed(4)} (saved $${(b.opus - t.totalCost).toFixed(4)})`);
29550
+ lines.push(` Sonnet: $${b.sonnet.toFixed(4)} (saved $${(b.sonnet - t.totalCost).toFixed(4)})`);
29551
+ lines.push(` Haiku: $${b.haiku.toFixed(4)} (saved $${(b.haiku - t.totalCost).toFixed(4)})`);
29552
+ if (summary.daily.length > 0) {
29553
+ lines.push("");
29554
+ lines.push("Daily:");
29555
+ 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)}`);
29556
+ }
29557
+ return lines.join("\n");
29558
+ }
29559
+ function formatTokens(n) {
29560
+ if (!Number.isFinite(n) || n <= 0) return "0";
29561
+ if (n >= 1e6) return `${(n / 1e6).toFixed(1)}m`;
29562
+ if (n >= 1e3) return `${(n / 1e3).toFixed(n >= 1e4 ? 0 : 1)}k`;
29563
+ return String(Math.round(n));
29564
+ }
29565
+
28952
29566
  //#endregion
28953
29567
  //#region src/agents/system-prompt-report.ts
28954
29568
  function extractBetween(input, startMarker, endMarker) {
@@ -29517,6 +30131,560 @@ async function buildExportSessionReply(params) {
29517
30131
  ].join("\n") };
29518
30132
  }
29519
30133
 
30134
+ //#endregion
30135
+ //#region src/cost/rates.ts
30136
+ const GPU_VRAM_GB = {
30137
+ "a100-40gb": 40,
30138
+ "a100-80gb": 80,
30139
+ "h100-pcie": 80,
30140
+ "h100-sxm": 80,
30141
+ h200: 141,
30142
+ l40: 48,
30143
+ l40s: 48,
30144
+ a40: 48,
30145
+ a6000: 48,
30146
+ a5000: 24,
30147
+ v100: 32,
30148
+ mi300x: 192,
30149
+ "rtx-4090": 24
30150
+ };
30151
+ const GPU_LABEL = {
30152
+ "a100-40gb": "A100-40GB",
30153
+ "a100-80gb": "A100-80GB",
30154
+ "h100-pcie": "H100-PCIe",
30155
+ "h100-sxm": "H100-SXM",
30156
+ h200: "H200",
30157
+ l40: "L40",
30158
+ l40s: "L40S",
30159
+ a40: "A40",
30160
+ a6000: "RTX-A6000",
30161
+ a5000: "RTX-A5000",
30162
+ v100: "V100",
30163
+ mi300x: "MI300X",
30164
+ "rtx-4090": "RTX-4090"
30165
+ };
30166
+ const DEFAULT_HOURLY_RATES_USD = {
30167
+ "a100-40gb": 2.06,
30168
+ "a100-80gb": 2.21,
30169
+ "h100-pcie": 4.25,
30170
+ "h100-sxm": 4.76,
30171
+ h200: 6.5,
30172
+ l40: 1.27,
30173
+ l40s: 1.35,
30174
+ a40: .95,
30175
+ a6000: .96,
30176
+ a5000: .61,
30177
+ v100: .8,
30178
+ mi300x: 4.89,
30179
+ "rtx-4090": .74
30180
+ };
30181
+ /**
30182
+ * Rough decode (output) throughput defaults in tokens/sec for a 27-30B FP8
30183
+ * model on a single GPU of each type. Scales roughly inversely with model
30184
+ * parameter count and bytes-per-param. Used as a fallback when no live
30185
+ * `vllm:generation_tokens_total` delta has been observed yet.
30186
+ *
30187
+ * These are conservative published-benchmark medians; treat as ballpark.
30188
+ * Override via `models.gpuRates` is rate-only; throughput overrides are
30189
+ * Phase 4+ (not yet wired to config).
30190
+ */
30191
+ const DEFAULT_DECODE_TPS = {
30192
+ "a100-40gb": 60,
30193
+ "a100-80gb": 80,
30194
+ "h100-pcie": 120,
30195
+ "h100-sxm": 130,
30196
+ h200: 160,
30197
+ l40: 45,
30198
+ l40s: 50,
30199
+ a40: 40,
30200
+ a6000: 35,
30201
+ a5000: 25,
30202
+ v100: 25,
30203
+ mi300x: 110,
30204
+ "rtx-4090": 55
30205
+ };
30206
+ /**
30207
+ * Prefill throughput is typically 30-60× higher than decode for a given
30208
+ * setup. Use 40× as a balanced midpoint.
30209
+ */
30210
+ const PREFILL_DECODE_RATIO = 40;
30211
+ function resolveDefaultDecodeTps(gpuType, paramsB, bytesPerParam) {
30212
+ const baseline = DEFAULT_DECODE_TPS[gpuType];
30213
+ if (!paramsB) return baseline;
30214
+ const refBytes = 27;
30215
+ const modelBytes = paramsB * (bytesPerParam ?? 2);
30216
+ if (modelBytes <= 0) return baseline;
30217
+ const scaled = baseline * (refBytes / modelBytes);
30218
+ return Math.max(5, scaled);
30219
+ }
30220
+ function resolveHourlyRate(gpuType, overrides) {
30221
+ if (overrides && typeof overrides[gpuType] === "number" && overrides[gpuType] >= 0) return overrides[gpuType];
30222
+ return DEFAULT_HOURLY_RATES_USD[gpuType];
30223
+ }
30224
+
30225
+ //#endregion
30226
+ //#region src/cost/gpu-inference.ts
30227
+ /**
30228
+ * Heuristic GPU type + count inference for self-hosted serving endpoints.
30229
+ *
30230
+ * Two signals: the baseUrl hostname (often encodes "a100", "h100", etc.) and
30231
+ * the model id (encodes parameter count + quantization, e.g. "qwen36-27b-fp8").
30232
+ * Output is a confidence-tagged guess so downstream code (and the user) can
30233
+ * decide whether to trust the inference or override it.
30234
+ *
30235
+ * Bytes-per-parameter table:
30236
+ * fp32 → 4
30237
+ * fp16/bf16 → 2 (default when unspecified)
30238
+ * fp8/int8/q8 → 1
30239
+ * int4/q4/fp4 → 0.5
30240
+ *
30241
+ * GPU count formula:
30242
+ * model_bytes = params × bytes_per_param
30243
+ * target_util = 0.6 (40% headroom for KV cache, activations, scheduler)
30244
+ * count = max(1, ceil(model_bytes / (vram × target_util)))
30245
+ */
30246
+ const URL_GPU_PATTERNS = [
30247
+ {
30248
+ re: /h200/i,
30249
+ type: "h200",
30250
+ confidence: "high"
30251
+ },
30252
+ {
30253
+ re: /h100[-_]?pcie/i,
30254
+ type: "h100-pcie",
30255
+ confidence: "high"
30256
+ },
30257
+ {
30258
+ re: /h100[-_]?sxm/i,
30259
+ type: "h100-sxm",
30260
+ confidence: "high"
30261
+ },
30262
+ {
30263
+ re: /h100/i,
30264
+ type: "h100-sxm",
30265
+ confidence: "medium"
30266
+ },
30267
+ {
30268
+ re: /a100[-_]?80/i,
30269
+ type: "a100-80gb",
30270
+ confidence: "high"
30271
+ },
30272
+ {
30273
+ re: /a100[-_]?40/i,
30274
+ type: "a100-40gb",
30275
+ confidence: "high"
30276
+ },
30277
+ {
30278
+ re: /a100/i,
30279
+ type: "a100-80gb",
30280
+ confidence: "medium"
30281
+ },
30282
+ {
30283
+ re: /l40s/i,
30284
+ type: "l40s",
30285
+ confidence: "high"
30286
+ },
30287
+ {
30288
+ re: /l40/i,
30289
+ type: "l40",
30290
+ confidence: "high"
30291
+ },
30292
+ {
30293
+ re: /mi300x/i,
30294
+ type: "mi300x",
30295
+ confidence: "high"
30296
+ },
30297
+ {
30298
+ re: /a6000/i,
30299
+ type: "a6000",
30300
+ confidence: "high"
30301
+ },
30302
+ {
30303
+ re: /a5000/i,
30304
+ type: "a5000",
30305
+ confidence: "high"
30306
+ },
30307
+ {
30308
+ re: /a40/i,
30309
+ type: "a40",
30310
+ confidence: "high"
30311
+ },
30312
+ {
30313
+ re: /v100/i,
30314
+ type: "v100",
30315
+ confidence: "high"
30316
+ },
30317
+ {
30318
+ re: /rtx[-_]?4090|gpu[-_]?4090/i,
30319
+ type: "rtx-4090",
30320
+ confidence: "high"
30321
+ }
30322
+ ];
30323
+ function inferGpuFromUrl(baseUrl) {
30324
+ const url = baseUrl.toLowerCase();
30325
+ for (const pattern of URL_GPU_PATTERNS) {
30326
+ const match = url.match(pattern.re);
30327
+ if (match) return {
30328
+ gpuType: pattern.type,
30329
+ confidence: pattern.confidence,
30330
+ match: match[0]
30331
+ };
30332
+ }
30333
+ return { confidence: "low" };
30334
+ }
30335
+ function parseModelSize(modelId) {
30336
+ const id = modelId.toLowerCase();
30337
+ const sizeMatch = id.match(/(\d+(?:\.\d+)?)b(?:[-_./]|$)/);
30338
+ const paramsB = sizeMatch ? Number.parseFloat(sizeMatch[1]) : void 0;
30339
+ let bytesPerParam;
30340
+ if (/\b(fp4|q4|int4)\b/.test(id) || /[-_]q4[-_]/.test(id)) bytesPerParam = .5;
30341
+ else if (/\b(fp8|int8|q8|w8a8|w8a16)\b/.test(id) || /[-_]fp8[-_]?/.test(id)) bytesPerParam = 1;
30342
+ else if (/\b(fp16|bf16|float16|half)\b/.test(id)) bytesPerParam = 2;
30343
+ else if (/\b(fp32|float32)\b/.test(id)) bytesPerParam = 4;
30344
+ return {
30345
+ paramsB,
30346
+ bytesPerParam
30347
+ };
30348
+ }
30349
+ function inferGpuCount(args) {
30350
+ const util = args.targetUtilization ?? .6;
30351
+ if (!args.paramsB || !args.bytesPerParam) return 1;
30352
+ const modelBytes = args.paramsB * 1e9 * args.bytesPerParam;
30353
+ const usableVram = args.vramGb * 1e9 * util;
30354
+ return Math.max(1, Math.ceil(modelBytes / usableVram));
30355
+ }
30356
+ function inferGpu(args) {
30357
+ const reasoning = [];
30358
+ const overrideType = args.override?.gpuType;
30359
+ const overrideCount = args.override?.gpuCount;
30360
+ let gpuType;
30361
+ let confidence = "low";
30362
+ if (overrideType && overrideType in GPU_VRAM_GB) {
30363
+ gpuType = overrideType;
30364
+ confidence = "high";
30365
+ reasoning.push(`gpuType=${gpuType} from config override`);
30366
+ } else if (args.baseUrl) {
30367
+ const fromUrl = inferGpuFromUrl(args.baseUrl);
30368
+ if (fromUrl.gpuType) {
30369
+ gpuType = fromUrl.gpuType;
30370
+ confidence = fromUrl.confidence;
30371
+ reasoning.push(`gpuType=${gpuType} from URL pattern '${fromUrl.match}'`);
30372
+ } else reasoning.push("no GPU type pattern matched in URL");
30373
+ }
30374
+ const sized = args.modelId ? parseModelSize(args.modelId) : {};
30375
+ if (sized.paramsB) reasoning.push(`paramsB=${sized.paramsB} from model id '${args.modelId}'`);
30376
+ if (sized.bytesPerParam) reasoning.push(`bytesPerParam=${sized.bytesPerParam} from quantization marker`);
30377
+ else if (args.modelId) reasoning.push("no quantization marker — defaulting to bf16 (2 bytes)");
30378
+ let gpuCount = 1;
30379
+ if (typeof overrideCount === "number" && overrideCount > 0) {
30380
+ gpuCount = Math.floor(overrideCount);
30381
+ reasoning.push(`gpuCount=${gpuCount} from config override`);
30382
+ } else if (gpuType) {
30383
+ const bpp = sized.bytesPerParam ?? 2;
30384
+ gpuCount = inferGpuCount({
30385
+ paramsB: sized.paramsB,
30386
+ bytesPerParam: bpp,
30387
+ vramGb: GPU_VRAM_GB[gpuType]
30388
+ });
30389
+ if (sized.paramsB) reasoning.push(`gpuCount=${gpuCount} (model ${(sized.paramsB * bpp).toFixed(0)}GB / ${GPU_VRAM_GB[gpuType]}GB × 0.6 util)`);
30390
+ }
30391
+ return {
30392
+ gpuType,
30393
+ gpuCount,
30394
+ confidence,
30395
+ paramsB: sized.paramsB,
30396
+ bytesPerParam: sized.bytesPerParam,
30397
+ reasoning
30398
+ };
30399
+ }
30400
+
30401
+ //#endregion
30402
+ //#region src/cost/serving-discovery.ts
30403
+ const SUCCESS_TTL_MS = 6e4;
30404
+ const NULL_TTL_MS = 5 * 6e4;
30405
+ const DEFAULT_TIMEOUT_MS$1 = 4e3;
30406
+ const cache = /* @__PURE__ */ new Map();
30407
+ const previousSnapshots = /* @__PURE__ */ new Map();
30408
+ async function probeServingEndpoint(baseUrl, opts = {}) {
30409
+ const fetchImpl = opts.fetchImpl ?? globalThis.fetch;
30410
+ const nowFn = opts.now ?? (() => Date.now());
30411
+ const timeoutMs = opts.timeoutMs ?? DEFAULT_TIMEOUT_MS$1;
30412
+ const trimmed = baseUrl.trim().replace(/\/+$/, "");
30413
+ if (!trimmed) return null;
30414
+ const cached = cache.get(trimmed);
30415
+ if (cached && !opts.forceRefresh && cached.expiresAt > nowFn()) return cached.info;
30416
+ const rootUrl = trimmed.replace(/\/v\d+$/, "");
30417
+ const probeAt = nowFn();
30418
+ const fetchOpts = () => ({
30419
+ signal: AbortSignal.timeout(timeoutMs),
30420
+ headers: { Accept: "application/json, text/plain, */*" }
30421
+ });
30422
+ const [versionRes, modelsRes, metricsRes] = await Promise.allSettled([
30423
+ fetchImpl(`${rootUrl}/version`, fetchOpts()),
30424
+ fetchImpl(`${rootUrl}/v1/models`, fetchOpts()),
30425
+ fetchImpl(`${rootUrl}/metrics`, fetchOpts())
30426
+ ]);
30427
+ const info = {
30428
+ engine: "unknown",
30429
+ probedAt: probeAt,
30430
+ baseUrl: trimmed,
30431
+ rootUrl
30432
+ };
30433
+ if (versionRes.status === "fulfilled" && versionRes.value.ok) try {
30434
+ const txt = await versionRes.value.text();
30435
+ try {
30436
+ const json = JSON.parse(txt);
30437
+ if (typeof json.version === "string") info.version = json.version;
30438
+ } catch {
30439
+ const stripped = txt.trim();
30440
+ if (stripped && stripped.length < 64 && /^[\w.\-+]+$/.test(stripped)) info.version = stripped;
30441
+ }
30442
+ } catch {}
30443
+ if (modelsRes.status === "fulfilled" && modelsRes.value.ok) try {
30444
+ const first = (await modelsRes.value.json()).data?.[0];
30445
+ if (first) {
30446
+ if (typeof first.id === "string") info.modelId = first.id;
30447
+ if (typeof first.max_model_len === "number") info.contextWindow = first.max_model_len;
30448
+ if (typeof first.owned_by === "string") {
30449
+ const owner = first.owned_by.toLowerCase();
30450
+ if (owner.includes("vllm")) info.engine = "vllm";
30451
+ else if (owner.includes("sglang")) info.engine = "sglang";
30452
+ else if (info.engine === "unknown") info.engine = "openai-compat";
30453
+ }
30454
+ }
30455
+ } catch {}
30456
+ let snapshot = { probedAt: probeAt };
30457
+ if (metricsRes.status === "fulfilled" && metricsRes.value.ok) try {
30458
+ const parsed = parsePrometheusMetrics(await metricsRes.value.text());
30459
+ info.kvCacheUsagePerc = parsed.kvCacheUsagePerc;
30460
+ info.queueDepth = parsed.queueDepth;
30461
+ info.numRequestsRunning = parsed.numRequestsRunning;
30462
+ info.cacheConfig = parsed.cacheConfig;
30463
+ snapshot = {
30464
+ probedAt: probeAt,
30465
+ promptTokensTotal: parsed.promptTokensTotal,
30466
+ generationTokensTotal: parsed.generationTokensTotal
30467
+ };
30468
+ if (info.engine === "unknown" && parsed.foundVllmPrefix) info.engine = "vllm";
30469
+ if (info.engine === "unknown" && parsed.foundSglangPrefix) info.engine = "sglang";
30470
+ } catch {}
30471
+ const prev = previousSnapshots.get(trimmed);
30472
+ if (prev && typeof prev.generationTokensTotal === "number" && typeof snapshot.generationTokensTotal === "number") {
30473
+ const dt = (snapshot.probedAt - prev.probedAt) / 1e3;
30474
+ const dToks = snapshot.generationTokensTotal - prev.generationTokensTotal;
30475
+ if (dt > 0 && dToks >= 0) info.observedTps = dToks / dt;
30476
+ }
30477
+ if (snapshot.generationTokensTotal !== void 0 || snapshot.promptTokensTotal !== void 0) previousSnapshots.set(trimmed, snapshot);
30478
+ 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)) {
30479
+ cache.set(trimmed, {
30480
+ info: null,
30481
+ expiresAt: nowFn() + NULL_TTL_MS
30482
+ });
30483
+ return null;
30484
+ }
30485
+ cache.set(trimmed, {
30486
+ info,
30487
+ expiresAt: nowFn() + SUCCESS_TTL_MS
30488
+ });
30489
+ return info;
30490
+ }
30491
+ function parsePrometheusMetrics(text) {
30492
+ const result = {
30493
+ foundVllmPrefix: false,
30494
+ foundSglangPrefix: false
30495
+ };
30496
+ const lines = text.split("\n");
30497
+ for (const raw of lines) {
30498
+ const line = raw.trim();
30499
+ if (!line || line.startsWith("#")) continue;
30500
+ if (line.startsWith("vllm:")) result.foundVllmPrefix = true;
30501
+ if (line.startsWith("sglang:")) result.foundSglangPrefix = true;
30502
+ const match = line.match(/^([^\s{]+)(\{[^}]*\})?\s+([0-9eE+\-.]+)$/);
30503
+ if (!match) continue;
30504
+ const metric = match[1];
30505
+ const labels = match[2];
30506
+ const value = Number(match[3]);
30507
+ if (!Number.isFinite(value)) continue;
30508
+ switch (metric) {
30509
+ case "vllm:prompt_tokens_total":
30510
+ result.promptTokensTotal = (result.promptTokensTotal ?? 0) + value;
30511
+ break;
30512
+ case "vllm:generation_tokens_total":
30513
+ result.generationTokensTotal = (result.generationTokensTotal ?? 0) + value;
30514
+ break;
30515
+ case "vllm:kv_cache_usage_perc":
30516
+ result.kvCacheUsagePerc = value;
30517
+ break;
30518
+ case "vllm:num_requests_waiting":
30519
+ if (!labels || !labels.includes("reason=")) result.queueDepth = value;
30520
+ break;
30521
+ case "vllm:num_requests_running":
30522
+ result.numRequestsRunning = value;
30523
+ break;
30524
+ case "vllm:cache_config_info": {
30525
+ if (!labels) break;
30526
+ const parsed = parseLabels(labels);
30527
+ const cfg = {};
30528
+ if (parsed.block_size !== void 0) cfg.blockSize = Number(parsed.block_size);
30529
+ if (parsed.num_gpu_blocks !== void 0) cfg.numGpuBlocks = Number(parsed.num_gpu_blocks);
30530
+ if (parsed.cache_dtype !== void 0) cfg.cacheDtype = parsed.cache_dtype;
30531
+ if (parsed.gpu_memory_utilization !== void 0) {
30532
+ const n = Number(parsed.gpu_memory_utilization);
30533
+ if (Number.isFinite(n)) cfg.gpuMemoryUtilization = n;
30534
+ }
30535
+ if (parsed.enable_prefix_caching !== void 0) cfg.enablePrefixCaching = parsed.enable_prefix_caching === "True";
30536
+ result.cacheConfig = cfg;
30537
+ break;
30538
+ }
30539
+ }
30540
+ }
30541
+ return result;
30542
+ }
30543
+ function parseLabels(rawLabels) {
30544
+ const inner = rawLabels.replace(/^\{/, "").replace(/\}$/, "");
30545
+ const out = {};
30546
+ const re = /(\w+)="([^"]*)"/g;
30547
+ let m;
30548
+ while ((m = re.exec(inner)) !== null) out[m[1]] = m[2];
30549
+ return out;
30550
+ }
30551
+ function formatEngineLine(info) {
30552
+ if (!info) return null;
30553
+ const parts = [];
30554
+ const engineLabel = (() => {
30555
+ if (info.engine === "vllm") return info.version ? `vLLM ${info.version}` : "vLLM";
30556
+ if (info.engine === "sglang") return info.version ? `SGLang ${info.version}` : "SGLang";
30557
+ if (info.engine === "openai-compat") return "OpenAI-compat";
30558
+ return info.version ? `engine ${info.version}` : null;
30559
+ })();
30560
+ if (engineLabel) parts.push(engineLabel);
30561
+ if (typeof info.observedTps === "number" && info.observedTps > .5) parts.push(`${Math.round(info.observedTps)} tps`);
30562
+ if (typeof info.kvCacheUsagePerc === "number") {
30563
+ const pct = Math.round(info.kvCacheUsagePerc * 100);
30564
+ if (pct > 0) parts.push(`KV ${pct}%`);
30565
+ }
30566
+ if (typeof info.queueDepth === "number" && info.queueDepth > 0) parts.push(`queue ${info.queueDepth}`);
30567
+ if (typeof info.numRequestsRunning === "number" && info.numRequestsRunning > 0) parts.push(`running ${info.numRequestsRunning}`);
30568
+ if (parts.length === 0) return null;
30569
+ return `🖥 ${parts.join(" · ")}`;
30570
+ }
30571
+
30572
+ //#endregion
30573
+ //#region src/cost/breakdown.ts
30574
+ async function buildCostBreakdown(args) {
30575
+ const benchmarkTarget = args.config?.models?.benchmark === "none" ? "none" : resolveBenchmarkTarget(args.config?.models?.benchmark);
30576
+ const breakdown = {
30577
+ serving: null,
30578
+ benchmarks: [],
30579
+ benchmarkTarget
30580
+ };
30581
+ if (args.baseUrl && args.baseUrl.trim()) try {
30582
+ breakdown.serving = await probeServingEndpoint(args.baseUrl, {
30583
+ timeoutMs: args.probeTimeoutMs ?? 3e3,
30584
+ forceRefresh: Boolean(args.forceProbeRefresh)
30585
+ });
30586
+ } catch {
30587
+ breakdown.serving = null;
30588
+ }
30589
+ breakdown.engineLine = formatEngineLine(breakdown.serving) ?? void 0;
30590
+ const modelCost = resolveModelCost(args.config, args.provider, args.modelId);
30591
+ const detectedModelId = breakdown.serving?.modelId ?? args.modelId;
30592
+ breakdown.gpu = inferGpu({
30593
+ baseUrl: args.baseUrl,
30594
+ modelId: detectedModelId,
30595
+ override: {
30596
+ gpuType: modelCost?.gpuType,
30597
+ gpuCount: modelCost?.gpuCount
30598
+ }
30599
+ });
30600
+ const overrides = args.config?.models?.gpuRates;
30601
+ let rate;
30602
+ let source;
30603
+ if (typeof modelCost?.hourlyRate === "number" && modelCost.hourlyRate >= 0) {
30604
+ rate = modelCost.hourlyRate;
30605
+ source = "model-override";
30606
+ } else if (breakdown.gpu.gpuType) {
30607
+ rate = resolveHourlyRate(breakdown.gpu.gpuType, overrides);
30608
+ if (rate !== void 0) source = overrides && breakdown.gpu.gpuType in overrides ? "config-override" : "default-table";
30609
+ }
30610
+ breakdown.hourlyRate = rate;
30611
+ breakdown.hourlyRateSource = source;
30612
+ if (breakdown.gpu?.gpuType) {
30613
+ const observed = breakdown.serving?.observedTps;
30614
+ if (typeof observed === "number" && observed > .5) {
30615
+ breakdown.decodeTps = observed;
30616
+ breakdown.prefillTps = observed * PREFILL_DECODE_RATIO;
30617
+ breakdown.throughputSource = "observed";
30618
+ } else {
30619
+ const decode = resolveDefaultDecodeTps(breakdown.gpu.gpuType, breakdown.gpu.paramsB, breakdown.gpu.bytesPerParam);
30620
+ breakdown.decodeTps = decode;
30621
+ breakdown.prefillTps = decode * PREFILL_DECODE_RATIO;
30622
+ breakdown.throughputSource = "default-table";
30623
+ }
30624
+ }
30625
+ if (args.usage && breakdown.hourlyRate !== void 0 && breakdown.gpu?.gpuType && breakdown.decodeTps !== void 0 && breakdown.prefillTps !== void 0) {
30626
+ const perSecond = breakdown.hourlyRate * breakdown.gpu.gpuCount / 3600;
30627
+ const inputTokens = args.usage.input ?? 0;
30628
+ const outputTokens = args.usage.output ?? 0;
30629
+ const totalCost = ((breakdown.prefillTps > 0 ? inputTokens / breakdown.prefillTps : 0) + (breakdown.decodeTps > 0 ? outputTokens / breakdown.decodeTps : 0)) * perSecond;
30630
+ breakdown.instanceCostUsd = totalCost;
30631
+ const totalTokens = inputTokens + outputTokens;
30632
+ if (totalTokens > 0) breakdown.perTokenAvgUsd = totalCost / totalTokens;
30633
+ }
30634
+ if (args.usage) {
30635
+ const costForEstimate = modelCost ? {
30636
+ input: modelCost.input ?? 0,
30637
+ output: modelCost.output ?? 0,
30638
+ cacheRead: modelCost.cacheRead ?? 0,
30639
+ cacheWrite: modelCost.cacheWrite ?? 0
30640
+ } : void 0;
30641
+ const rawCost = estimateUsageCost({
30642
+ usage: args.usage,
30643
+ cost: costForEstimate
30644
+ });
30645
+ if (typeof rawCost === "number" && rawCost > 0) breakdown.effectiveCostUsd = rawCost;
30646
+ else if (breakdown.instanceCostUsd !== void 0) breakdown.effectiveCostUsd = breakdown.instanceCostUsd;
30647
+ if (benchmarkTarget !== "none" && breakdown.effectiveCostUsd !== void 0) {
30648
+ breakdown.benchmarks = benchmarkUsage({
30649
+ usage: args.usage,
30650
+ target: benchmarkTarget
30651
+ });
30652
+ breakdown.costLineSuffix = formatBenchmarkSuffix({
30653
+ ourCostUsd: breakdown.effectiveCostUsd,
30654
+ benchmarks: breakdown.benchmarks
30655
+ });
30656
+ }
30657
+ }
30658
+ breakdown.hardwareLine = formatHardwareLine(breakdown);
30659
+ return breakdown;
30660
+ }
30661
+ function resolveModelCost(config, provider, modelId) {
30662
+ if (!config || !provider || !modelId) return;
30663
+ const providers = config.models?.providers;
30664
+ if (!providers) return;
30665
+ const providerCfg = providers[provider];
30666
+ if (!providerCfg?.models) return;
30667
+ return providerCfg.models.find((m) => m.id === modelId)?.cost;
30668
+ }
30669
+ function formatHardwareLine(breakdown) {
30670
+ const gpu = breakdown.gpu;
30671
+ if (!gpu?.gpuType) return;
30672
+ const label = GPU_LABEL[gpu.gpuType];
30673
+ const count = gpu.gpuCount;
30674
+ const parts = [];
30675
+ parts.push(`${count}× ${label}`);
30676
+ if (typeof breakdown.hourlyRate === "number") parts.push(`≈ $${(breakdown.hourlyRate * count).toFixed(2)}/hr`);
30677
+ const tag = (() => {
30678
+ if (breakdown.hourlyRateSource === "model-override") return "model override";
30679
+ if (breakdown.hourlyRateSource === "config-override") return "config override";
30680
+ if (gpu.confidence === "high") return "inferred";
30681
+ if (gpu.confidence === "medium") return "inferred · medium-conf";
30682
+ return "inferred · low-conf";
30683
+ })();
30684
+ parts.push(`(${tag})`);
30685
+ return `🧰 ${parts.join(" · ")}`;
30686
+ }
30687
+
29520
30688
  //#endregion
29521
30689
  //#region src/infra/provider-usage.shared.ts
29522
30690
  const DEFAULT_TIMEOUT_MS = 5e3;
@@ -30720,6 +31888,32 @@ async function buildStatusReply(params) {
30720
31888
  } catch {
30721
31889
  usageLine = null;
30722
31890
  }
31891
+ const baseUrl = cfg.models?.providers?.[provider]?.baseUrl;
31892
+ let engineLine;
31893
+ let hardwareLine;
31894
+ let costOverrideUsd;
31895
+ let costLineSuffix;
31896
+ try {
31897
+ const breakdown = await buildCostBreakdown({
31898
+ baseUrl,
31899
+ provider,
31900
+ modelId: model,
31901
+ config: cfg,
31902
+ usage: {
31903
+ input: sessionEntry?.inputTokens,
31904
+ output: sessionEntry?.outputTokens
31905
+ }
31906
+ });
31907
+ engineLine = breakdown.engineLine;
31908
+ hardwareLine = breakdown.hardwareLine;
31909
+ costOverrideUsd = breakdown.instanceCostUsd;
31910
+ costLineSuffix = breakdown.costLineSuffix;
31911
+ } catch {
31912
+ engineLine = void 0;
31913
+ hardwareLine = void 0;
31914
+ costOverrideUsd = void 0;
31915
+ costLineSuffix = void 0;
31916
+ }
30723
31917
  const queueSettings = resolveQueueSettings({
30724
31918
  cfg,
30725
31919
  channel: command.channel,
@@ -30802,6 +31996,10 @@ async function buildStatusReply(params) {
30802
31996
  showDetails: queueOverrides
30803
31997
  },
30804
31998
  subagentsLine,
31999
+ engineLine,
32000
+ hardwareLine,
32001
+ costOverrideUsd,
32002
+ costLineSuffix,
30805
32003
  mediaDecisions: params.mediaDecisions,
30806
32004
  includeTranscriptUsage: false
30807
32005
  }) };
@@ -30902,6 +32100,27 @@ const handleStatusCommand = async (params, allowTextCommands) => {
30902
32100
  })
30903
32101
  };
30904
32102
  };
32103
+ const handleCostCommand = async (params, allowTextCommands) => {
32104
+ if (!allowTextCommands) return null;
32105
+ const normalized = params.command.commandBodyNormalized;
32106
+ if (normalized !== "/cost" && !normalized.startsWith("/cost ")) return null;
32107
+ if (!params.command.isAuthorizedSender) {
32108
+ logVerbose(`Ignoring /cost from unauthorized sender: ${params.command.senderId || "<unknown>"}`);
32109
+ return { shouldContinue: false };
32110
+ }
32111
+ const arg = normalized.slice(5).trim();
32112
+ const window = arg === "today" || arg === "week" || arg === "month" || arg === "all" ? arg : "week";
32113
+ const { startMs, endMs } = resolveWindow(window);
32114
+ return {
32115
+ shouldContinue: false,
32116
+ reply: { text: formatSummaryReport(await loadCostBenchmarkSummary({
32117
+ startMs,
32118
+ endMs,
32119
+ config: params.cfg,
32120
+ agentId: params.agentId
32121
+ }), `${window.charAt(0).toUpperCase()}${window.slice(1)}`) }
32122
+ };
32123
+ };
30905
32124
  const handleContextCommand = async (params, allowTextCommands) => {
30906
32125
  if (!allowTextCommands) return null;
30907
32126
  const normalized = params.command.commandBodyNormalized;
@@ -31298,411 +32517,6 @@ function scheduleGatewaySigusr1Restart(opts) {
31298
32517
  };
31299
32518
  }
31300
32519
 
31301
- //#endregion
31302
- //#region src/infra/session-cost-usage.ts
31303
- const emptyTotals = () => ({
31304
- input: 0,
31305
- output: 0,
31306
- cacheRead: 0,
31307
- cacheWrite: 0,
31308
- totalTokens: 0,
31309
- totalCost: 0,
31310
- inputCost: 0,
31311
- outputCost: 0,
31312
- cacheReadCost: 0,
31313
- cacheWriteCost: 0,
31314
- missingCostEntries: 0
31315
- });
31316
- const toFiniteNumber = (value) => {
31317
- if (typeof value !== "number") return;
31318
- if (!Number.isFinite(value)) return;
31319
- return value;
31320
- };
31321
- const extractCostBreakdown = (usageRaw) => {
31322
- if (!usageRaw || typeof usageRaw !== "object") return;
31323
- const cost = usageRaw.cost;
31324
- if (!cost) return;
31325
- const total = toFiniteNumber(cost.total);
31326
- if (total === void 0 || total < 0) return;
31327
- return {
31328
- total,
31329
- input: toFiniteNumber(cost.input),
31330
- output: toFiniteNumber(cost.output),
31331
- cacheRead: toFiniteNumber(cost.cacheRead),
31332
- cacheWrite: toFiniteNumber(cost.cacheWrite)
31333
- };
31334
- };
31335
- const parseTimestamp = (entry) => {
31336
- const raw = entry.timestamp;
31337
- if (typeof raw === "string") {
31338
- const parsed = new Date(raw);
31339
- if (!Number.isNaN(parsed.valueOf())) return parsed;
31340
- }
31341
- const message = entry.message;
31342
- const messageTimestamp = toFiniteNumber(message?.timestamp);
31343
- if (messageTimestamp !== void 0) {
31344
- const parsed = new Date(messageTimestamp);
31345
- if (!Number.isNaN(parsed.valueOf())) return parsed;
31346
- }
31347
- };
31348
- const parseTranscriptEntry = (entry) => {
31349
- const message = entry.message;
31350
- if (!message || typeof message !== "object") return null;
31351
- const roleRaw = message.role;
31352
- const role = roleRaw === "user" || roleRaw === "assistant" ? roleRaw : void 0;
31353
- if (!role) return null;
31354
- const usageRaw = message.usage ?? entry.usage;
31355
- const usage = usageRaw ? normalizeUsage(usageRaw) ?? void 0 : void 0;
31356
- const provider = (typeof message.provider === "string" ? message.provider : void 0) ?? (typeof entry.provider === "string" ? entry.provider : void 0);
31357
- const model = (typeof message.model === "string" ? message.model : void 0) ?? (typeof entry.model === "string" ? entry.model : void 0);
31358
- const costBreakdown = extractCostBreakdown(usageRaw);
31359
- const stopReason = typeof message.stopReason === "string" ? message.stopReason : void 0;
31360
- const durationMs = toFiniteNumber(message.durationMs ?? entry.durationMs);
31361
- return {
31362
- message,
31363
- role,
31364
- timestamp: parseTimestamp(entry),
31365
- durationMs,
31366
- usage,
31367
- costTotal: costBreakdown?.total,
31368
- costBreakdown,
31369
- provider,
31370
- model,
31371
- stopReason,
31372
- toolNames: extractToolCallNames(message),
31373
- toolResultCounts: countToolResults(message)
31374
- };
31375
- };
31376
- const formatDayKey = (date) => date.toLocaleDateString("en-CA", { timeZone: Intl.DateTimeFormat().resolvedOptions().timeZone });
31377
- const computeLatencyStats = (values) => {
31378
- if (!values.length) return;
31379
- const sorted = values.toSorted((a, b) => a - b);
31380
- const total = sorted.reduce((sum, v) => sum + v, 0);
31381
- const count = sorted.length;
31382
- const p95Index = Math.max(0, Math.ceil(count * .95) - 1);
31383
- return {
31384
- count,
31385
- avgMs: total / count,
31386
- p95Ms: sorted[p95Index] ?? sorted[count - 1],
31387
- minMs: sorted[0],
31388
- maxMs: sorted[count - 1]
31389
- };
31390
- };
31391
- const applyUsageTotals = (totals, usage) => {
31392
- totals.input += usage.input ?? 0;
31393
- totals.output += usage.output ?? 0;
31394
- totals.cacheRead += usage.cacheRead ?? 0;
31395
- totals.cacheWrite += usage.cacheWrite ?? 0;
31396
- const totalTokens = usage.total ?? (usage.input ?? 0) + (usage.output ?? 0) + (usage.cacheRead ?? 0) + (usage.cacheWrite ?? 0);
31397
- totals.totalTokens += totalTokens;
31398
- };
31399
- const applyCostBreakdown = (totals, costBreakdown) => {
31400
- if (costBreakdown === void 0 || costBreakdown.total === void 0) return;
31401
- totals.totalCost += costBreakdown.total;
31402
- totals.inputCost += costBreakdown.input ?? 0;
31403
- totals.outputCost += costBreakdown.output ?? 0;
31404
- totals.cacheReadCost += costBreakdown.cacheRead ?? 0;
31405
- totals.cacheWriteCost += costBreakdown.cacheWrite ?? 0;
31406
- };
31407
- const applyCostTotal = (totals, costTotal) => {
31408
- if (costTotal === void 0) {
31409
- totals.missingCostEntries += 1;
31410
- return;
31411
- }
31412
- totals.totalCost += costTotal;
31413
- };
31414
- async function* readJsonlRecords(filePath) {
31415
- const fileStream = fs.createReadStream(filePath, { encoding: "utf-8" });
31416
- const rl = readline.createInterface({
31417
- input: fileStream,
31418
- crlfDelay: Infinity
31419
- });
31420
- try {
31421
- for await (const line of rl) {
31422
- const trimmed = line.trim();
31423
- if (!trimmed) continue;
31424
- try {
31425
- const parsed = JSON.parse(trimmed);
31426
- if (!parsed || typeof parsed !== "object") continue;
31427
- yield parsed;
31428
- } catch {}
31429
- }
31430
- } finally {
31431
- rl.close();
31432
- fileStream.destroy();
31433
- }
31434
- }
31435
- async function scanTranscriptFile(params) {
31436
- for await (const parsed of readJsonlRecords(params.filePath)) {
31437
- const entry = parseTranscriptEntry(parsed);
31438
- if (!entry) continue;
31439
- if (entry.usage && entry.costTotal === void 0) {
31440
- const cost = resolveModelCostConfig({
31441
- provider: entry.provider,
31442
- model: entry.model,
31443
- config: params.config
31444
- });
31445
- entry.costTotal = estimateUsageCost({
31446
- usage: entry.usage,
31447
- cost
31448
- });
31449
- }
31450
- params.onEntry(entry);
31451
- }
31452
- }
31453
- async function scanUsageFile(params) {
31454
- await scanTranscriptFile({
31455
- filePath: params.filePath,
31456
- config: params.config,
31457
- onEntry: (entry) => {
31458
- if (!entry.usage) return;
31459
- params.onEntry({
31460
- usage: entry.usage,
31461
- costTotal: entry.costTotal,
31462
- costBreakdown: entry.costBreakdown,
31463
- provider: entry.provider,
31464
- model: entry.model,
31465
- timestamp: entry.timestamp
31466
- });
31467
- }
31468
- });
31469
- }
31470
- async function loadCostUsageSummary(params) {
31471
- const now = /* @__PURE__ */ new Date();
31472
- let sinceTime;
31473
- let untilTime;
31474
- if (params?.startMs !== void 0 && params?.endMs !== void 0) {
31475
- sinceTime = params.startMs;
31476
- untilTime = params.endMs;
31477
- } else {
31478
- const days = Math.max(1, Math.floor(params?.days ?? 30));
31479
- const since = new Date(now);
31480
- since.setDate(since.getDate() - (days - 1));
31481
- sinceTime = since.getTime();
31482
- untilTime = now.getTime();
31483
- }
31484
- const dailyMap = /* @__PURE__ */ new Map();
31485
- const totals = emptyTotals();
31486
- const sessionsDir = resolveSessionTranscriptsDirForAgent(params?.agentId);
31487
- const entries = await fs.promises.readdir(sessionsDir, { withFileTypes: true }).catch(() => []);
31488
- const files = (await Promise.all(entries.filter((entry) => entry.isFile() && entry.name.endsWith(".jsonl")).map(async (entry) => {
31489
- const filePath = path.join(sessionsDir, entry.name);
31490
- const stats = await fs.promises.stat(filePath).catch(() => null);
31491
- if (!stats) return null;
31492
- if (stats.mtimeMs < sinceTime) return null;
31493
- return filePath;
31494
- }))).filter((filePath) => Boolean(filePath));
31495
- for (const filePath of files) await scanUsageFile({
31496
- filePath,
31497
- config: params?.config,
31498
- onEntry: (entry) => {
31499
- const ts = entry.timestamp?.getTime();
31500
- if (!ts || ts < sinceTime || ts > untilTime) return;
31501
- const dayKey = formatDayKey(entry.timestamp ?? now);
31502
- const bucket = dailyMap.get(dayKey) ?? emptyTotals();
31503
- applyUsageTotals(bucket, entry.usage);
31504
- if (entry.costBreakdown?.total !== void 0) applyCostBreakdown(bucket, entry.costBreakdown);
31505
- else applyCostTotal(bucket, entry.costTotal);
31506
- dailyMap.set(dayKey, bucket);
31507
- applyUsageTotals(totals, entry.usage);
31508
- if (entry.costBreakdown?.total !== void 0) applyCostBreakdown(totals, entry.costBreakdown);
31509
- else applyCostTotal(totals, entry.costTotal);
31510
- }
31511
- });
31512
- const daily = Array.from(dailyMap.entries()).map(([date, bucket]) => Object.assign({ date }, bucket)).toSorted((a, b) => a.date.localeCompare(b.date));
31513
- const days = Math.ceil((untilTime - sinceTime) / (1440 * 60 * 1e3)) + 1;
31514
- return {
31515
- updatedAt: Date.now(),
31516
- days,
31517
- daily,
31518
- totals
31519
- };
31520
- }
31521
- async function loadSessionCostSummary(params) {
31522
- const sessionFile = params.sessionFile ?? (params.sessionId ? resolveSessionFilePath(params.sessionId, params.sessionEntry, { agentId: params.agentId }) : void 0);
31523
- if (!sessionFile || !fs.existsSync(sessionFile)) return null;
31524
- const totals = emptyTotals();
31525
- let firstActivity;
31526
- let lastActivity;
31527
- const activityDatesSet = /* @__PURE__ */ new Set();
31528
- const dailyMap = /* @__PURE__ */ new Map();
31529
- const dailyMessageMap = /* @__PURE__ */ new Map();
31530
- const dailyLatencyMap = /* @__PURE__ */ new Map();
31531
- const dailyModelUsageMap = /* @__PURE__ */ new Map();
31532
- const messageCounts = {
31533
- total: 0,
31534
- user: 0,
31535
- assistant: 0,
31536
- toolCalls: 0,
31537
- toolResults: 0,
31538
- errors: 0
31539
- };
31540
- const toolUsageMap = /* @__PURE__ */ new Map();
31541
- const modelUsageMap = /* @__PURE__ */ new Map();
31542
- const errorStopReasons = new Set([
31543
- "error",
31544
- "aborted",
31545
- "timeout"
31546
- ]);
31547
- const latencyValues = [];
31548
- let lastUserTimestamp;
31549
- const MAX_LATENCY_MS = 720 * 60 * 1e3;
31550
- await scanTranscriptFile({
31551
- filePath: sessionFile,
31552
- config: params.config,
31553
- onEntry: (entry) => {
31554
- const ts = entry.timestamp?.getTime();
31555
- if (params.startMs !== void 0 && ts !== void 0 && ts < params.startMs) return;
31556
- if (params.endMs !== void 0 && ts !== void 0 && ts > params.endMs) return;
31557
- if (ts !== void 0) {
31558
- if (!firstActivity || ts < firstActivity) firstActivity = ts;
31559
- if (!lastActivity || ts > lastActivity) lastActivity = ts;
31560
- }
31561
- if (entry.role === "user") {
31562
- messageCounts.user += 1;
31563
- messageCounts.total += 1;
31564
- if (entry.timestamp) lastUserTimestamp = entry.timestamp.getTime();
31565
- }
31566
- if (entry.role === "assistant") {
31567
- messageCounts.assistant += 1;
31568
- messageCounts.total += 1;
31569
- const ts = entry.timestamp?.getTime();
31570
- if (ts !== void 0) {
31571
- const latencyMs = entry.durationMs ?? (lastUserTimestamp !== void 0 ? Math.max(0, ts - lastUserTimestamp) : void 0);
31572
- if (latencyMs !== void 0 && Number.isFinite(latencyMs) && latencyMs <= MAX_LATENCY_MS) {
31573
- latencyValues.push(latencyMs);
31574
- const dayKey = formatDayKey(entry.timestamp ?? new Date(ts));
31575
- const dailyLatencies = dailyLatencyMap.get(dayKey) ?? [];
31576
- dailyLatencies.push(latencyMs);
31577
- dailyLatencyMap.set(dayKey, dailyLatencies);
31578
- }
31579
- }
31580
- }
31581
- if (entry.toolNames.length > 0) {
31582
- messageCounts.toolCalls += entry.toolNames.length;
31583
- for (const name of entry.toolNames) toolUsageMap.set(name, (toolUsageMap.get(name) ?? 0) + 1);
31584
- }
31585
- if (entry.toolResultCounts.total > 0) {
31586
- messageCounts.toolResults += entry.toolResultCounts.total;
31587
- messageCounts.errors += entry.toolResultCounts.errors;
31588
- }
31589
- if (entry.stopReason && errorStopReasons.has(entry.stopReason)) messageCounts.errors += 1;
31590
- if (entry.timestamp) {
31591
- const dayKey = formatDayKey(entry.timestamp);
31592
- activityDatesSet.add(dayKey);
31593
- const daily = dailyMessageMap.get(dayKey) ?? {
31594
- date: dayKey,
31595
- total: 0,
31596
- user: 0,
31597
- assistant: 0,
31598
- toolCalls: 0,
31599
- toolResults: 0,
31600
- errors: 0
31601
- };
31602
- daily.total += entry.role === "user" || entry.role === "assistant" ? 1 : 0;
31603
- if (entry.role === "user") daily.user += 1;
31604
- else if (entry.role === "assistant") daily.assistant += 1;
31605
- daily.toolCalls += entry.toolNames.length;
31606
- daily.toolResults += entry.toolResultCounts.total;
31607
- daily.errors += entry.toolResultCounts.errors;
31608
- if (entry.stopReason && errorStopReasons.has(entry.stopReason)) daily.errors += 1;
31609
- dailyMessageMap.set(dayKey, daily);
31610
- }
31611
- if (!entry.usage) return;
31612
- applyUsageTotals(totals, entry.usage);
31613
- if (entry.costBreakdown?.total !== void 0) applyCostBreakdown(totals, entry.costBreakdown);
31614
- else applyCostTotal(totals, entry.costTotal);
31615
- if (entry.timestamp) {
31616
- const dayKey = formatDayKey(entry.timestamp);
31617
- const entryTokens = (entry.usage.input ?? 0) + (entry.usage.output ?? 0) + (entry.usage.cacheRead ?? 0) + (entry.usage.cacheWrite ?? 0);
31618
- 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);
31619
- const existing = dailyMap.get(dayKey) ?? {
31620
- tokens: 0,
31621
- cost: 0
31622
- };
31623
- dailyMap.set(dayKey, {
31624
- tokens: existing.tokens + entryTokens,
31625
- cost: existing.cost + entryCost
31626
- });
31627
- if (entry.provider || entry.model) {
31628
- const modelKey = `${dayKey}::${entry.provider ?? "unknown"}::${entry.model ?? "unknown"}`;
31629
- const dailyModel = dailyModelUsageMap.get(modelKey) ?? {
31630
- date: dayKey,
31631
- provider: entry.provider,
31632
- model: entry.model,
31633
- tokens: 0,
31634
- cost: 0,
31635
- count: 0
31636
- };
31637
- dailyModel.tokens += entryTokens;
31638
- dailyModel.cost += entryCost;
31639
- dailyModel.count += 1;
31640
- dailyModelUsageMap.set(modelKey, dailyModel);
31641
- }
31642
- }
31643
- if (entry.provider || entry.model) {
31644
- const key = `${entry.provider ?? "unknown"}::${entry.model ?? "unknown"}`;
31645
- const existing = modelUsageMap.get(key) ?? {
31646
- provider: entry.provider,
31647
- model: entry.model,
31648
- count: 0,
31649
- totals: emptyTotals()
31650
- };
31651
- existing.count += 1;
31652
- applyUsageTotals(existing.totals, entry.usage);
31653
- if (entry.costBreakdown?.total !== void 0) applyCostBreakdown(existing.totals, entry.costBreakdown);
31654
- else applyCostTotal(existing.totals, entry.costTotal);
31655
- modelUsageMap.set(key, existing);
31656
- }
31657
- }
31658
- });
31659
- const dailyBreakdown = Array.from(dailyMap.entries()).map(([date, data]) => ({
31660
- date,
31661
- tokens: data.tokens,
31662
- cost: data.cost
31663
- })).toSorted((a, b) => a.date.localeCompare(b.date));
31664
- const dailyMessageCounts = Array.from(dailyMessageMap.values()).toSorted((a, b) => a.date.localeCompare(b.date));
31665
- const dailyLatency = Array.from(dailyLatencyMap.entries()).map(([date, values]) => {
31666
- const stats = computeLatencyStats(values);
31667
- if (!stats) return null;
31668
- return {
31669
- date,
31670
- ...stats
31671
- };
31672
- }).filter((entry) => Boolean(entry)).toSorted((a, b) => a.date.localeCompare(b.date));
31673
- const dailyModelUsage = Array.from(dailyModelUsageMap.values()).toSorted((a, b) => a.date.localeCompare(b.date) || b.cost - a.cost);
31674
- const toolUsage = toolUsageMap.size ? {
31675
- totalCalls: Array.from(toolUsageMap.values()).reduce((sum, count) => sum + count, 0),
31676
- uniqueTools: toolUsageMap.size,
31677
- tools: Array.from(toolUsageMap.entries()).map(([name, count]) => ({
31678
- name,
31679
- count
31680
- })).toSorted((a, b) => b.count - a.count)
31681
- } : void 0;
31682
- const modelUsage = modelUsageMap.size ? Array.from(modelUsageMap.values()).toSorted((a, b) => {
31683
- const costDiff = b.totals.totalCost - a.totals.totalCost;
31684
- if (costDiff !== 0) return costDiff;
31685
- return b.totals.totalTokens - a.totals.totalTokens;
31686
- }) : void 0;
31687
- return {
31688
- sessionId: params.sessionId,
31689
- sessionFile,
31690
- firstActivity,
31691
- lastActivity,
31692
- durationMs: firstActivity !== void 0 && lastActivity !== void 0 ? Math.max(0, lastActivity - firstActivity) : void 0,
31693
- activityDates: Array.from(activityDatesSet).toSorted(),
31694
- dailyBreakdown,
31695
- dailyMessageCounts,
31696
- dailyLatency: dailyLatency.length ? dailyLatency : void 0,
31697
- dailyModelUsage: dailyModelUsage.length ? dailyModelUsage : void 0,
31698
- messageCounts,
31699
- toolUsage,
31700
- modelUsage,
31701
- latency: computeLatencyStats(latencyValues),
31702
- ...totals
31703
- };
31704
- }
31705
-
31706
32520
  //#endregion
31707
32521
  //#region src/auto-reply/send-policy.ts
31708
32522
  function normalizeSendPolicyOverride(raw) {
@@ -32902,6 +33716,7 @@ async function handleCommands(params) {
32902
33716
  handleHelpCommand,
32903
33717
  handleCommandsListCommand,
32904
33718
  handleStatusCommand,
33719
+ handleCostCommand,
32905
33720
  handleAllowlistCommand,
32906
33721
  handleApproveCommand,
32907
33722
  handleContextCommand,
@@ -40147,6 +40962,32 @@ function createSessionStatusTool(opts) {
40147
40962
  }
40148
40963
  } catch {}
40149
40964
  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;
40965
+ const baseUrl = cfg.models?.providers?.[providerForCard]?.baseUrl;
40966
+ let engineLine;
40967
+ let hardwareLine;
40968
+ let costOverrideUsd;
40969
+ let costLineSuffix;
40970
+ try {
40971
+ const breakdown = await buildCostBreakdown({
40972
+ baseUrl,
40973
+ provider: providerForCard,
40974
+ modelId: configured.model,
40975
+ config: cfg,
40976
+ usage: {
40977
+ input: resolved.entry.inputTokens,
40978
+ output: resolved.entry.outputTokens
40979
+ }
40980
+ });
40981
+ engineLine = breakdown.engineLine;
40982
+ hardwareLine = breakdown.hardwareLine;
40983
+ costOverrideUsd = breakdown.instanceCostUsd;
40984
+ costLineSuffix = breakdown.costLineSuffix;
40985
+ } catch {
40986
+ engineLine = void 0;
40987
+ hardwareLine = void 0;
40988
+ costOverrideUsd = void 0;
40989
+ costLineSuffix = void 0;
40990
+ }
40150
40991
  const queueSettings = resolveQueueSettings({
40151
40992
  cfg,
40152
40993
  channel: resolved.entry.channel ?? resolved.entry.lastChannel ?? "unknown",
@@ -40192,6 +41033,10 @@ function createSessionStatusTool(opts) {
40192
41033
  dropPolicy: queueSettings.dropPolicy,
40193
41034
  showDetails: queueOverrides
40194
41035
  },
41036
+ engineLine,
41037
+ hardwareLine,
41038
+ costOverrideUsd,
41039
+ costLineSuffix,
40195
41040
  includeTranscriptUsage: false
40196
41041
  });
40197
41042
  return {
@@ -43475,6 +44320,86 @@ async function handleInlineActions(params) {
43475
44320
  };
43476
44321
  }
43477
44322
 
44323
+ //#endregion
44324
+ //#region src/auto-reply/reply/middleware-context-warning.ts
44325
+ /** Threshold (fraction of context window) that triggers the soft warning. */
44326
+ const CONTEXT_WARNING_THRESHOLD = .85;
44327
+ /**
44328
+ * Threshold that triggers proactive compaction in `prepareReplyTurn`.
44329
+ * Higher than the soft warning so the user sees the heads-up first;
44330
+ * compaction runs the next turn the threshold is observed.
44331
+ */
44332
+ const CONTEXT_PROACTIVE_COMPACT_THRESHOLD = .9;
44333
+ /**
44334
+ * Pure decision for "should `prepareReplyTurn` run proactive compaction
44335
+ * before the next turn?" — extracted so the trigger logic is unit-testable
44336
+ * without mocking the rest of the prep pipeline.
44337
+ *
44338
+ * Returns true ONLY when:
44339
+ * - we have a session id (otherwise compaction has no target),
44340
+ * - we have a positive context window,
44341
+ * - we have a positive cumulative usage from the previous turn,
44342
+ * - usage / window ≥ CONTEXT_PROACTIVE_COMPACT_THRESHOLD.
44343
+ */
44344
+ function shouldProactivelyCompact(args) {
44345
+ if (!args.sessionId) return false;
44346
+ if (!args.contextTokens || args.contextTokens <= 0) return false;
44347
+ const usage = args.totalTokens ?? 0;
44348
+ if (usage <= 0) return false;
44349
+ return usage / args.contextTokens >= CONTEXT_PROACTIVE_COMPACT_THRESHOLD;
44350
+ }
44351
+ /**
44352
+ * Read the model's context-window size, falling back to the global
44353
+ * default when the model isn't in the registry yet.
44354
+ */
44355
+ function resolveContextWindow(modelId) {
44356
+ const fromRegistry = lookupContextTokens(modelId);
44357
+ if (fromRegistry && fromRegistry > 0) return fromRegistry;
44358
+ return DEFAULT_CONTEXT_TOKENS;
44359
+ }
44360
+ /**
44361
+ * After-turn hook that surfaces a one-time soft warning when usage
44362
+ * crosses the context threshold. Mutates the result text to append
44363
+ * the warning when triggered, and persists `contextWarningSent: true`
44364
+ * on the session entry so the warning doesn't fire again.
44365
+ */
44366
+ function withContextUsageWarning() {
44367
+ return (next) => async (params) => {
44368
+ const result = await next(params);
44369
+ if (result.outbound.action === "drop") return result;
44370
+ if (!params.sessionKey) return result;
44371
+ const usage = result.rawResult.meta.agentMeta?.usage?.total ?? 0;
44372
+ if (usage <= 0) return result;
44373
+ if (usage / resolveContextWindow(params.modelId ?? result.modelId) < CONTEXT_WARNING_THRESHOLD) return result;
44374
+ const agentId = resolveAgentIdFromSessionKey(params.sessionKey);
44375
+ const storePath = resolveStorePath(params.config.session?.store, { agentId });
44376
+ let alreadyWarned = false;
44377
+ try {
44378
+ await updateSessionStoreEntry({
44379
+ storePath,
44380
+ sessionKey: params.sessionKey,
44381
+ update: async (entry) => {
44382
+ if (entry.contextWarningSent === true) {
44383
+ alreadyWarned = true;
44384
+ return null;
44385
+ }
44386
+ return { contextWarningSent: true };
44387
+ }
44388
+ });
44389
+ } catch (err) {
44390
+ logVerbose(`context-warning: failed to persist contextWarningSent flag for ${params.sessionKey}: ${String(err)}`);
44391
+ return result;
44392
+ }
44393
+ if (alreadyWarned) return result;
44394
+ const trimmedText = result.text.trimEnd();
44395
+ const separator = trimmedText ? "\n\n" : "";
44396
+ return {
44397
+ ...result,
44398
+ text: `${trimmedText}${separator}${SESSION_CONTEXT_WARNING_MESSAGE}`
44399
+ };
44400
+ };
44401
+ }
44402
+
43478
44403
  //#endregion
43479
44404
  //#region src/auto-reply/reply/session-reset-model.ts
43480
44405
  function splitBody(body) {
@@ -43644,7 +44569,7 @@ async function deliverSessionMaintenanceWarning(params) {
43644
44569
  return;
43645
44570
  }
43646
44571
  try {
43647
- const { deliverOutboundPayloads } = await import("./deliver-DyO3QD8O.js").then((n) => n.n);
44572
+ const { deliverOutboundPayloads } = await import("./deliver-BiWlR84Y.js").then((n) => n.n);
43648
44573
  await deliverOutboundPayloads({
43649
44574
  cfg: params.cfg,
43650
44575
  channel,
@@ -44371,7 +45296,7 @@ async function prepareReplyTurn(ctx, opts, configOverride) {
44371
45296
  typing.cleanup();
44372
45297
  return {
44373
45298
  kind: "early-reply",
44374
- reply: { text: SESSION_OVERFLOW_MESSAGE }
45299
+ reply: { text: SESSION_COMPACTION_FAILED_MESSAGE }
44375
45300
  };
44376
45301
  }
44377
45302
  await applyResetModelOverride({
@@ -44484,6 +45409,82 @@ async function prepareReplyTurn(ctx, opts, configOverride) {
44484
45409
  };
44485
45410
  directives = inlineActionResult.directives;
44486
45411
  abortedLastRun = inlineActionResult.abortedLastRun ?? abortedLastRun;
45412
+ if (shouldProactivelyCompact({
45413
+ totalTokens: sessionEntry.totalTokens,
45414
+ contextTokens,
45415
+ sessionId: sessionEntry.sessionId
45416
+ })) {
45417
+ if (resolvedOpts?.onBlockReply) try {
45418
+ await resolvedOpts.onBlockReply({ text: SESSION_COMPACTING_MESSAGE });
45419
+ } catch (err) {
45420
+ logVerbose(`proactive-compact: inline status delivery failed: ${String(err)}`);
45421
+ }
45422
+ if (isEmbeddedPiRunActive(sessionEntry.sessionId)) {
45423
+ abortEmbeddedPiRun(sessionEntry.sessionId);
45424
+ await waitForEmbeddedPiRunEnd(sessionEntry.sessionId, 15e3);
45425
+ }
45426
+ let compactResult;
45427
+ try {
45428
+ compactResult = await compactEmbeddedPiSession({
45429
+ sessionId: sessionEntry.sessionId,
45430
+ sessionKey,
45431
+ messageChannel: command.channel,
45432
+ groupId: sessionEntry.groupId,
45433
+ groupChannel: sessionEntry.groupChannel,
45434
+ groupSpace: sessionEntry.space,
45435
+ spawnedBy: sessionEntry.spawnedBy,
45436
+ sessionFile: resolveSessionFilePath(sessionEntry.sessionId, sessionEntry, resolveSessionFilePathOptions({
45437
+ agentId,
45438
+ storePath
45439
+ })),
45440
+ workspaceDir,
45441
+ agentDir,
45442
+ config: cfg,
45443
+ skillsSnapshot: sessionEntry.skillsSnapshot,
45444
+ provider,
45445
+ model,
45446
+ thinkLevel: resolvedThinkLevel,
45447
+ reasoningLevel: resolvedReasoningLevel,
45448
+ trigger: "overflow",
45449
+ senderIsOwner: command.senderIsOwner,
45450
+ ownerNumbers: command.ownerList.length > 0 ? command.ownerList : void 0
45451
+ });
45452
+ } catch (err) {
45453
+ logVerbose(`proactive-compact: compactor threw for ${sessionKey}: ${String(err)}`);
45454
+ compactResult = {
45455
+ ok: false,
45456
+ compacted: false,
45457
+ reason: String(err)
45458
+ };
45459
+ }
45460
+ if (compactResult.ok && compactResult.compacted) await incrementCompactionCount({
45461
+ sessionEntry,
45462
+ sessionStore,
45463
+ sessionKey,
45464
+ storePath,
45465
+ tokensAfter: compactResult.result?.tokensAfter
45466
+ });
45467
+ else {
45468
+ logVerbose(`proactive-compact: failed for ${sessionKey} (${compactResult.reason ?? "unknown"})`);
45469
+ if (storePath) try {
45470
+ await updateSessionStoreEntry({
45471
+ storePath,
45472
+ sessionKey,
45473
+ update: async (entry) => {
45474
+ if (entry.endedReason === "context_overflow") return null;
45475
+ return { endedReason: "context_overflow" };
45476
+ }
45477
+ });
45478
+ } catch (err) {
45479
+ logVerbose(`proactive-compact: failed to mark session sealed: ${String(err)}`);
45480
+ }
45481
+ typing.cleanup();
45482
+ return {
45483
+ kind: "early-reply",
45484
+ reply: { text: SESSION_COMPACTION_FAILED_MESSAGE }
45485
+ };
45486
+ }
45487
+ }
44487
45488
  await stageSandboxMedia({
44488
45489
  ctx,
44489
45490
  sessionCtx,
@@ -44912,8 +45913,8 @@ function extractErrorMessage(err) {
44912
45913
  function buildBoundaryResult(params) {
44913
45914
  const profile = resolveModelProfile(params.provider && params.modelId ? `${params.provider}/${params.modelId}` : "", params.config.models?.profiles);
44914
45915
  return {
44915
- text: SESSION_OVERFLOW_MESSAGE,
44916
- rawText: SESSION_OVERFLOW_MESSAGE,
45916
+ text: SESSION_COMPACTION_FAILED_MESSAGE,
45917
+ rawText: SESSION_COMPACTION_FAILED_MESSAGE,
44917
45918
  outbound: {
44918
45919
  action: "deliver",
44919
45920
  reason: "deliver"
@@ -44924,7 +45925,7 @@ function buildBoundaryResult(params) {
44924
45925
  profile,
44925
45926
  didSendViaMessagingTool: false,
44926
45927
  rawResult: {
44927
- payloads: [{ text: SESSION_OVERFLOW_MESSAGE }],
45928
+ payloads: [{ text: SESSION_COMPACTION_FAILED_MESSAGE }],
44928
45929
  meta: {
44929
45930
  durationMs: Date.now() - params.startTime,
44930
45931
  agentMeta: {
@@ -44983,62 +45984,6 @@ function withContextOverflowRecovery() {
44983
45984
  };
44984
45985
  }
44985
45986
 
44986
- //#endregion
44987
- //#region src/auto-reply/reply/middleware-context-warning.ts
44988
- /** Threshold (fraction of context window) that triggers the soft warning. */
44989
- const CONTEXT_WARNING_THRESHOLD = .85;
44990
- /**
44991
- * Read the model's context-window size, falling back to the global
44992
- * default when the model isn't in the registry yet.
44993
- */
44994
- function resolveContextWindow(modelId) {
44995
- const fromRegistry = lookupContextTokens(modelId);
44996
- if (fromRegistry && fromRegistry > 0) return fromRegistry;
44997
- return DEFAULT_CONTEXT_TOKENS;
44998
- }
44999
- /**
45000
- * After-turn hook that surfaces a one-time soft warning when usage
45001
- * crosses the context threshold. Mutates the result text to append
45002
- * the warning when triggered, and persists `contextWarningSent: true`
45003
- * on the session entry so the warning doesn't fire again.
45004
- */
45005
- function withContextUsageWarning() {
45006
- return (next) => async (params) => {
45007
- const result = await next(params);
45008
- if (result.outbound.action === "drop") return result;
45009
- if (!params.sessionKey) return result;
45010
- const usage = result.rawResult.meta.agentMeta?.usage?.total ?? 0;
45011
- if (usage <= 0) return result;
45012
- if (usage / resolveContextWindow(params.modelId ?? result.modelId) < CONTEXT_WARNING_THRESHOLD) return result;
45013
- const agentId = resolveAgentIdFromSessionKey(params.sessionKey);
45014
- const storePath = resolveStorePath(params.config.session?.store, { agentId });
45015
- let alreadyWarned = false;
45016
- try {
45017
- await updateSessionStoreEntry({
45018
- storePath,
45019
- sessionKey: params.sessionKey,
45020
- update: async (entry) => {
45021
- if (entry.contextWarningSent === true) {
45022
- alreadyWarned = true;
45023
- return null;
45024
- }
45025
- return { contextWarningSent: true };
45026
- }
45027
- });
45028
- } catch (err) {
45029
- logVerbose(`context-warning: failed to persist contextWarningSent flag for ${params.sessionKey}: ${String(err)}`);
45030
- return result;
45031
- }
45032
- if (alreadyWarned) return result;
45033
- const trimmedText = result.text.trimEnd();
45034
- const separator = trimmedText ? "\n\n" : "";
45035
- return {
45036
- ...result,
45037
- text: `${trimmedText}${separator}${SESSION_CONTEXT_WARNING_MESSAGE}`
45038
- };
45039
- };
45040
- }
45041
-
45042
45987
  //#endregion
45043
45988
  //#region src/auto-reply/reply/middleware-diagnostic-logging.ts
45044
45989
  function deriveChannel(ctx) {
@@ -50218,7 +51163,7 @@ function readSlackExternalArgMenuToken(raw) {
50218
51163
  }
50219
51164
  let commandsRegistry;
50220
51165
  async function getCommandsRegistry() {
50221
- if (!commandsRegistry) commandsRegistry = await import("./commands-registry-DPZevjMh.js").then((n) => n.t);
51166
+ if (!commandsRegistry) commandsRegistry = await import("./commands-registry-BuOUfpmg.js").then((n) => n.t);
50222
51167
  return commandsRegistry;
50223
51168
  }
50224
51169
  function encodeSlackCommandArgValue(parts) {
@@ -50621,7 +51566,7 @@ async function registerSlackMonitorSlashCommands(params) {
50621
51566
  });
50622
51567
  const deliverSlashPayloads = async (replies) => {
50623
51568
  const [{ deliverSlackSlashReplies }, { resolveChunkMode }, { resolveMarkdownTableMode }] = await Promise.all([
50624
- import("./replies-DAYTg6Mb.js").then((n) => n.r),
51569
+ import("./replies-D0FYSIJg.js").then((n) => n.r),
50625
51570
  import("./chunk-BkYIP_hB.js").then((n) => n.s),
50626
51571
  import("./markdown-tables-CGqX2WvO.js").then((n) => n.t)
50627
51572
  ]);
@@ -50676,7 +51621,7 @@ async function registerSlackMonitorSlashCommands(params) {
50676
51621
  let nativeCommands = [];
50677
51622
  if (nativeEnabled) {
50678
51623
  reg = await getCommandsRegistry();
50679
- const skillCommands = nativeSkillsEnabled ? (await import("./skill-commands-BoMrW3WV.js").then((n) => n.a)).listSkillCommandsForAgents({ cfg }) : [];
51624
+ const skillCommands = nativeSkillsEnabled ? (await import("./skill-commands-JIccKWkf.js").then((n) => n.a)).listSkillCommandsForAgents({ cfg }) : [];
50680
51625
  nativeCommands = reg.listNativeCommandSpecsForConfig(cfg, {
50681
51626
  skillCommands,
50682
51627
  provider: "slack"
@@ -60884,7 +61829,7 @@ async function runEmbeddedPiAgent(params) {
60884
61829
  error: err
60885
61830
  });
60886
61831
  }
60887
- const MAX_OVERFLOW_COMPACTION_ATTEMPTS = 3;
61832
+ const MAX_OVERFLOW_COMPACTION_ATTEMPTS = 1;
60888
61833
  const MAX_RUN_LOOP_ITERATIONS = resolveMaxRunRetryIterations(profileCandidates.length);
60889
61834
  let overflowCompactionAttempts = 0;
60890
61835
  let toolResultTruncationAttempted = false;