crewly 1.20.186 → 1.20.188

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 (321) hide show
  1. package/config/skills/agent/core/project-tickets/SKILL.md +3 -2
  2. package/config/skills/agent/core/project-tickets/execute.sh +4 -4
  3. package/config/skills/agent/core/project-tickets/execute.test.sh +2 -2
  4. package/config/skills/agent/core/remember/SKILL.md +1 -0
  5. package/config/skills/agent/core/remember/execute.sh +12 -0
  6. package/config/skills/agent/core/report-status/SKILL.md +7 -1
  7. package/config/skills/agent/core/report-status/execute.sh +41 -0
  8. package/config/skills/agent/core/slack-post/SKILL.md +1 -0
  9. package/config/skills/agent/core/slack-post/execute.sh +9 -2
  10. package/config/skills/team-leader/_common/lib.sh +45 -0
  11. package/config/skills/team-leader/start-agent/SKILL.md +6 -6
  12. package/config/skills/team-leader/start-agent/execute.sh +3 -12
  13. package/config/skills/team-leader/stop-agent/SKILL.md +6 -6
  14. package/config/skills/team-leader/stop-agent/execute.sh +3 -12
  15. package/dist/backend/backend/src/constants.d.ts +114 -2
  16. package/dist/backend/backend/src/constants.d.ts.map +1 -1
  17. package/dist/backend/backend/src/constants.js +114 -2
  18. package/dist/backend/backend/src/constants.js.map +1 -1
  19. package/dist/backend/backend/src/controllers/monitoring/terminal.controller.d.ts.map +1 -1
  20. package/dist/backend/backend/src/controllers/monitoring/terminal.controller.js +62 -0
  21. package/dist/backend/backend/src/controllers/monitoring/terminal.controller.js.map +1 -1
  22. package/dist/backend/backend/src/controllers/project-tickets/project-tickets.controller.d.ts +1 -1
  23. package/dist/backend/backend/src/controllers/project-tickets/project-tickets.controller.d.ts.map +1 -1
  24. package/dist/backend/backend/src/controllers/project-tickets/project-tickets.controller.js +5 -1
  25. package/dist/backend/backend/src/controllers/project-tickets/project-tickets.controller.js.map +1 -1
  26. package/dist/backend/backend/src/controllers/project-tickets/project-tickets.routes.d.ts +1 -1
  27. package/dist/backend/backend/src/controllers/project-tickets/project-tickets.routes.js +1 -1
  28. package/dist/backend/backend/src/controllers/request/open-items.controller.js +1 -1
  29. package/dist/backend/backend/src/controllers/request/open-items.controller.js.map +1 -1
  30. package/dist/backend/backend/src/controllers/slack/slack.controller.d.ts.map +1 -1
  31. package/dist/backend/backend/src/controllers/slack/slack.controller.js +4 -1
  32. package/dist/backend/backend/src/controllers/slack/slack.controller.js.map +1 -1
  33. package/dist/backend/backend/src/controllers/standing/standing.controller.d.ts +18 -1
  34. package/dist/backend/backend/src/controllers/standing/standing.controller.d.ts.map +1 -1
  35. package/dist/backend/backend/src/controllers/standing/standing.controller.js +77 -4
  36. package/dist/backend/backend/src/controllers/standing/standing.controller.js.map +1 -1
  37. package/dist/backend/backend/src/controllers/system/system.controller.d.ts +12 -0
  38. package/dist/backend/backend/src/controllers/system/system.controller.d.ts.map +1 -1
  39. package/dist/backend/backend/src/controllers/system/system.controller.js +28 -3
  40. package/dist/backend/backend/src/controllers/system/system.controller.js.map +1 -1
  41. package/dist/backend/backend/src/controllers/system/usage.controller.d.ts +46 -0
  42. package/dist/backend/backend/src/controllers/system/usage.controller.d.ts.map +1 -0
  43. package/dist/backend/backend/src/controllers/system/usage.controller.js +181 -0
  44. package/dist/backend/backend/src/controllers/system/usage.controller.js.map +1 -0
  45. package/dist/backend/backend/src/controllers/task-pool/task-pool.controller.d.ts +7 -0
  46. package/dist/backend/backend/src/controllers/task-pool/task-pool.controller.d.ts.map +1 -1
  47. package/dist/backend/backend/src/controllers/task-pool/task-pool.controller.js +64 -1
  48. package/dist/backend/backend/src/controllers/task-pool/task-pool.controller.js.map +1 -1
  49. package/dist/backend/backend/src/index.d.ts +7 -0
  50. package/dist/backend/backend/src/index.d.ts.map +1 -1
  51. package/dist/backend/backend/src/index.js +115 -1
  52. package/dist/backend/backend/src/index.js.map +1 -1
  53. package/dist/backend/backend/src/routes/modules/system.routes.d.ts.map +1 -1
  54. package/dist/backend/backend/src/routes/modules/system.routes.js +3 -0
  55. package/dist/backend/backend/src/routes/modules/system.routes.js.map +1 -1
  56. package/dist/backend/backend/src/scripts/open-items-stale-followups.d.ts +51 -0
  57. package/dist/backend/backend/src/scripts/open-items-stale-followups.d.ts.map +1 -0
  58. package/dist/backend/backend/src/scripts/open-items-stale-followups.js +142 -0
  59. package/dist/backend/backend/src/scripts/open-items-stale-followups.js.map +1 -0
  60. package/dist/backend/backend/src/services/agent/agent-registration.service.d.ts.map +1 -1
  61. package/dist/backend/backend/src/services/agent/agent-registration.service.js +32 -1
  62. package/dist/backend/backend/src/services/agent/agent-registration.service.js.map +1 -1
  63. package/dist/backend/backend/src/services/event-bus/event-bus.service.d.ts +28 -0
  64. package/dist/backend/backend/src/services/event-bus/event-bus.service.d.ts.map +1 -1
  65. package/dist/backend/backend/src/services/event-bus/event-bus.service.js +83 -2
  66. package/dist/backend/backend/src/services/event-bus/event-bus.service.js.map +1 -1
  67. package/dist/backend/backend/src/services/memory/memory.service.d.ts +14 -2
  68. package/dist/backend/backend/src/services/memory/memory.service.d.ts.map +1 -1
  69. package/dist/backend/backend/src/services/memory/memory.service.js +12 -1
  70. package/dist/backend/backend/src/services/memory/memory.service.js.map +1 -1
  71. package/dist/backend/backend/src/services/memory/project-memory.service.d.ts +18 -1
  72. package/dist/backend/backend/src/services/memory/project-memory.service.d.ts.map +1 -1
  73. package/dist/backend/backend/src/services/memory/project-memory.service.js +38 -1
  74. package/dist/backend/backend/src/services/memory/project-memory.service.js.map +1 -1
  75. package/dist/backend/backend/src/services/memory/standing-answers.service.d.ts +11 -0
  76. package/dist/backend/backend/src/services/memory/standing-answers.service.d.ts.map +1 -1
  77. package/dist/backend/backend/src/services/memory/standing-answers.service.js +40 -2
  78. package/dist/backend/backend/src/services/memory/standing-answers.service.js.map +1 -1
  79. package/dist/backend/backend/src/services/messaging/offline-agent-message.d.ts +70 -0
  80. package/dist/backend/backend/src/services/messaging/offline-agent-message.d.ts.map +1 -0
  81. package/dist/backend/backend/src/services/messaging/offline-agent-message.js +92 -0
  82. package/dist/backend/backend/src/services/messaging/offline-agent-message.js.map +1 -0
  83. package/dist/backend/backend/src/services/messaging/owner-message-watchdog.service.d.ts +7 -1
  84. package/dist/backend/backend/src/services/messaging/owner-message-watchdog.service.d.ts.map +1 -1
  85. package/dist/backend/backend/src/services/messaging/owner-message-watchdog.service.js +16 -2
  86. package/dist/backend/backend/src/services/messaging/owner-message-watchdog.service.js.map +1 -1
  87. package/dist/backend/backend/src/services/messaging/owner-message-watchdog.wiring.d.ts.map +1 -1
  88. package/dist/backend/backend/src/services/messaging/owner-message-watchdog.wiring.js +2 -0
  89. package/dist/backend/backend/src/services/messaging/owner-message-watchdog.wiring.js.map +1 -1
  90. package/dist/backend/backend/src/services/messaging/queue-processor.service.d.ts.map +1 -1
  91. package/dist/backend/backend/src/services/messaging/queue-processor.service.js +9 -1
  92. package/dist/backend/backend/src/services/messaging/queue-processor.service.js.map +1 -1
  93. package/dist/backend/backend/src/services/messaging/sub-agent-message-queue.service.d.ts +41 -1
  94. package/dist/backend/backend/src/services/messaging/sub-agent-message-queue.service.d.ts.map +1 -1
  95. package/dist/backend/backend/src/services/messaging/sub-agent-message-queue.service.js +87 -2
  96. package/dist/backend/backend/src/services/messaging/sub-agent-message-queue.service.js.map +1 -1
  97. package/dist/backend/backend/src/services/monitoring/activity-monitor.service.d.ts +30 -12
  98. package/dist/backend/backend/src/services/monitoring/activity-monitor.service.d.ts.map +1 -1
  99. package/dist/backend/backend/src/services/monitoring/activity-monitor.service.js +87 -15
  100. package/dist/backend/backend/src/services/monitoring/activity-monitor.service.js.map +1 -1
  101. package/dist/backend/backend/src/services/monitoring/antigravity-usage-sync.service.d.ts +130 -0
  102. package/dist/backend/backend/src/services/monitoring/antigravity-usage-sync.service.d.ts.map +1 -0
  103. package/dist/backend/backend/src/services/monitoring/antigravity-usage-sync.service.js +274 -0
  104. package/dist/backend/backend/src/services/monitoring/antigravity-usage-sync.service.js.map +1 -0
  105. package/dist/backend/backend/src/services/monitoring/codex-rollout-sync.service.d.ts +152 -0
  106. package/dist/backend/backend/src/services/monitoring/codex-rollout-sync.service.d.ts.map +1 -0
  107. package/dist/backend/backend/src/services/monitoring/codex-rollout-sync.service.js +311 -0
  108. package/dist/backend/backend/src/services/monitoring/codex-rollout-sync.service.js.map +1 -0
  109. package/dist/backend/backend/src/services/monitoring/token-usage.service.d.ts +78 -1
  110. package/dist/backend/backend/src/services/monitoring/token-usage.service.d.ts.map +1 -1
  111. package/dist/backend/backend/src/services/monitoring/token-usage.service.js +96 -4
  112. package/dist/backend/backend/src/services/monitoring/token-usage.service.js.map +1 -1
  113. package/dist/backend/backend/src/services/open-items/open-item-extractor.d.ts +10 -1
  114. package/dist/backend/backend/src/services/open-items/open-item-extractor.d.ts.map +1 -1
  115. package/dist/backend/backend/src/services/open-items/open-item-extractor.js +86 -5
  116. package/dist/backend/backend/src/services/open-items/open-item-extractor.js.map +1 -1
  117. package/dist/backend/backend/src/services/open-items/open-items-backfill.d.ts +2 -1
  118. package/dist/backend/backend/src/services/open-items/open-items-backfill.d.ts.map +1 -1
  119. package/dist/backend/backend/src/services/open-items/open-items-backfill.js +17 -6
  120. package/dist/backend/backend/src/services/open-items/open-items-backfill.js.map +1 -1
  121. package/dist/backend/backend/src/services/open-items/open-items.service.d.ts +62 -1
  122. package/dist/backend/backend/src/services/open-items/open-items.service.d.ts.map +1 -1
  123. package/dist/backend/backend/src/services/open-items/open-items.service.js +203 -9
  124. package/dist/backend/backend/src/services/open-items/open-items.service.js.map +1 -1
  125. package/dist/backend/backend/src/services/project-tickets/ticket-autopilot-decision.d.ts +4 -4
  126. package/dist/backend/backend/src/services/project-tickets/ticket-autopilot-decision.d.ts.map +1 -1
  127. package/dist/backend/backend/src/services/project-tickets/ticket-autopilot-decision.js +1 -1
  128. package/dist/backend/backend/src/services/project-tickets/ticket-autopilot-decision.js.map +1 -1
  129. package/dist/backend/backend/src/services/project-tickets/ticket-autopilot-messages.d.ts +4 -3
  130. package/dist/backend/backend/src/services/project-tickets/ticket-autopilot-messages.d.ts.map +1 -1
  131. package/dist/backend/backend/src/services/project-tickets/ticket-autopilot-messages.js +7 -4
  132. package/dist/backend/backend/src/services/project-tickets/ticket-autopilot-messages.js.map +1 -1
  133. package/dist/backend/backend/src/services/project-tickets/ticket-autopilot.service.d.ts +40 -9
  134. package/dist/backend/backend/src/services/project-tickets/ticket-autopilot.service.d.ts.map +1 -1
  135. package/dist/backend/backend/src/services/project-tickets/ticket-autopilot.service.js +68 -20
  136. package/dist/backend/backend/src/services/project-tickets/ticket-autopilot.service.js.map +1 -1
  137. package/dist/backend/backend/src/services/reconciler/idle-holder-surfacer.d.ts +40 -0
  138. package/dist/backend/backend/src/services/reconciler/idle-holder-surfacer.d.ts.map +1 -0
  139. package/dist/backend/backend/src/services/reconciler/idle-holder-surfacer.js +82 -0
  140. package/dist/backend/backend/src/services/reconciler/idle-holder-surfacer.js.map +1 -0
  141. package/dist/backend/backend/src/services/reconciler/reconcile-rules.d.ts +29 -0
  142. package/dist/backend/backend/src/services/reconciler/reconcile-rules.d.ts.map +1 -1
  143. package/dist/backend/backend/src/services/reconciler/reconcile-rules.js +49 -0
  144. package/dist/backend/backend/src/services/reconciler/reconcile-rules.js.map +1 -1
  145. package/dist/backend/backend/src/services/reconciler/reconciler-data-provider.d.ts.map +1 -1
  146. package/dist/backend/backend/src/services/reconciler/reconciler-data-provider.js +6 -11
  147. package/dist/backend/backend/src/services/reconciler/reconciler-data-provider.js.map +1 -1
  148. package/dist/backend/backend/src/services/reconciler/reconciler.service.d.ts +23 -0
  149. package/dist/backend/backend/src/services/reconciler/reconciler.service.d.ts.map +1 -1
  150. package/dist/backend/backend/src/services/reconciler/reconciler.service.js +55 -1
  151. package/dist/backend/backend/src/services/reconciler/reconciler.service.js.map +1 -1
  152. package/dist/backend/backend/src/services/slack/slack-agent-post.service.d.ts.map +1 -1
  153. package/dist/backend/backend/src/services/slack/slack-agent-post.service.js +10 -4
  154. package/dist/backend/backend/src/services/slack/slack-agent-post.service.js.map +1 -1
  155. package/dist/backend/backend/src/services/slack/slack-typing-placeholder.service.d.ts +13 -2
  156. package/dist/backend/backend/src/services/slack/slack-typing-placeholder.service.d.ts.map +1 -1
  157. package/dist/backend/backend/src/services/slack/slack-typing-placeholder.service.js +19 -5
  158. package/dist/backend/backend/src/services/slack/slack-typing-placeholder.service.js.map +1 -1
  159. package/dist/backend/backend/src/services/spend/spend-cap-command.d.ts +129 -0
  160. package/dist/backend/backend/src/services/spend/spend-cap-command.d.ts.map +1 -0
  161. package/dist/backend/backend/src/services/spend/spend-cap-command.js +323 -0
  162. package/dist/backend/backend/src/services/spend/spend-cap-command.js.map +1 -0
  163. package/dist/backend/backend/src/services/spend/spend-cap.gate.d.ts +60 -0
  164. package/dist/backend/backend/src/services/spend/spend-cap.gate.d.ts.map +1 -0
  165. package/dist/backend/backend/src/services/spend/spend-cap.gate.js +66 -0
  166. package/dist/backend/backend/src/services/spend/spend-cap.gate.js.map +1 -0
  167. package/dist/backend/backend/src/services/spend/spend-cap.service.d.ts +340 -0
  168. package/dist/backend/backend/src/services/spend/spend-cap.service.d.ts.map +1 -0
  169. package/dist/backend/backend/src/services/spend/spend-cap.service.js +760 -0
  170. package/dist/backend/backend/src/services/spend/spend-cap.service.js.map +1 -0
  171. package/dist/backend/backend/src/services/spend/spend-cap.store.d.ts +126 -0
  172. package/dist/backend/backend/src/services/spend/spend-cap.store.d.ts.map +1 -0
  173. package/dist/backend/backend/src/services/spend/spend-cap.store.js +141 -0
  174. package/dist/backend/backend/src/services/spend/spend-cap.store.js.map +1 -0
  175. package/dist/backend/backend/src/services/spend/spend-cap.wiring.d.ts +52 -0
  176. package/dist/backend/backend/src/services/spend/spend-cap.wiring.d.ts.map +1 -0
  177. package/dist/backend/backend/src/services/spend/spend-cap.wiring.js +112 -0
  178. package/dist/backend/backend/src/services/spend/spend-cap.wiring.js.map +1 -0
  179. package/dist/backend/backend/src/services/spend/spend-ledger.service.d.ts +145 -0
  180. package/dist/backend/backend/src/services/spend/spend-ledger.service.d.ts.map +1 -0
  181. package/dist/backend/backend/src/services/spend/spend-ledger.service.js +214 -0
  182. package/dist/backend/backend/src/services/spend/spend-ledger.service.js.map +1 -0
  183. package/dist/backend/backend/src/services/task-pool/claim-target-waker.d.ts +51 -0
  184. package/dist/backend/backend/src/services/task-pool/claim-target-waker.d.ts.map +1 -0
  185. package/dist/backend/backend/src/services/task-pool/claim-target-waker.js +43 -0
  186. package/dist/backend/backend/src/services/task-pool/claim-target-waker.js.map +1 -0
  187. package/dist/backend/backend/src/services/task-pool/task-pool.service.d.ts +38 -0
  188. package/dist/backend/backend/src/services/task-pool/task-pool.service.d.ts.map +1 -1
  189. package/dist/backend/backend/src/services/task-pool/task-pool.service.js +73 -1
  190. package/dist/backend/backend/src/services/task-pool/task-pool.service.js.map +1 -1
  191. package/dist/backend/backend/src/services/task-pool/work-item-usage.d.ts +53 -0
  192. package/dist/backend/backend/src/services/task-pool/work-item-usage.d.ts.map +1 -0
  193. package/dist/backend/backend/src/services/task-pool/work-item-usage.js +39 -0
  194. package/dist/backend/backend/src/services/task-pool/work-item-usage.js.map +1 -0
  195. package/dist/backend/backend/src/services/usage/token-format.d.ts +49 -0
  196. package/dist/backend/backend/src/services/usage/token-format.d.ts.map +1 -0
  197. package/dist/backend/backend/src/services/usage/token-format.js +81 -0
  198. package/dist/backend/backend/src/services/usage/token-format.js.map +1 -0
  199. package/dist/backend/backend/src/services/usage/usage-stats.service.d.ts +132 -0
  200. package/dist/backend/backend/src/services/usage/usage-stats.service.d.ts.map +1 -0
  201. package/dist/backend/backend/src/services/usage/usage-stats.service.js +226 -0
  202. package/dist/backend/backend/src/services/usage/usage-stats.service.js.map +1 -0
  203. package/dist/backend/backend/src/services/v3/v3-data.service.d.ts.map +1 -1
  204. package/dist/backend/backend/src/services/v3/v3-data.service.js +11 -14
  205. package/dist/backend/backend/src/services/v3/v3-data.service.js.map +1 -1
  206. package/dist/backend/backend/src/services/v3/workitem-dispatch.subscriber.d.ts +25 -0
  207. package/dist/backend/backend/src/services/v3/workitem-dispatch.subscriber.d.ts.map +1 -1
  208. package/dist/backend/backend/src/services/v3/workitem-dispatch.subscriber.js +50 -0
  209. package/dist/backend/backend/src/services/v3/workitem-dispatch.subscriber.js.map +1 -1
  210. package/dist/backend/backend/src/services/workflow/scheduler.service.d.ts +9 -1
  211. package/dist/backend/backend/src/services/workflow/scheduler.service.d.ts.map +1 -1
  212. package/dist/backend/backend/src/services/workflow/scheduler.service.js +16 -2
  213. package/dist/backend/backend/src/services/workflow/scheduler.service.js.map +1 -1
  214. package/dist/backend/backend/src/types/decision.types.d.ts +3 -1
  215. package/dist/backend/backend/src/types/decision.types.d.ts.map +1 -1
  216. package/dist/backend/backend/src/types/event-bus.types.d.ts +9 -1
  217. package/dist/backend/backend/src/types/event-bus.types.d.ts.map +1 -1
  218. package/dist/backend/backend/src/types/event-bus.types.js.map +1 -1
  219. package/dist/backend/backend/src/types/review-reason.types.d.ts +3 -1
  220. package/dist/backend/backend/src/types/review-reason.types.d.ts.map +1 -1
  221. package/dist/backend/backend/src/types/review-reason.types.js +1 -0
  222. package/dist/backend/backend/src/types/review-reason.types.js.map +1 -1
  223. package/dist/backend/backend/src/types/ticket-autopilot.types.d.ts +24 -7
  224. package/dist/backend/backend/src/types/ticket-autopilot.types.d.ts.map +1 -1
  225. package/dist/backend/backend/src/types/ticket-autopilot.types.js +29 -13
  226. package/dist/backend/backend/src/types/ticket-autopilot.types.js.map +1 -1
  227. package/dist/backend/backend/src/types/v2/open-item.types.d.ts +5 -1
  228. package/dist/backend/backend/src/types/v2/open-item.types.d.ts.map +1 -1
  229. package/dist/backend/backend/src/types/v2/open-item.types.js +1 -1
  230. package/dist/backend/backend/src/types/v2/open-item.types.js.map +1 -1
  231. package/dist/backend/build-info.json +2 -2
  232. package/dist/cli/backend/src/constants.d.ts +114 -2
  233. package/dist/cli/backend/src/constants.d.ts.map +1 -1
  234. package/dist/cli/backend/src/constants.js +114 -2
  235. package/dist/cli/backend/src/constants.js.map +1 -1
  236. package/dist/cli/backend/src/services/agent/agent-registration.service.d.ts.map +1 -1
  237. package/dist/cli/backend/src/services/agent/agent-registration.service.js +32 -1
  238. package/dist/cli/backend/src/services/agent/agent-registration.service.js.map +1 -1
  239. package/dist/cli/backend/src/services/event-bus/event-bus.service.d.ts +28 -0
  240. package/dist/cli/backend/src/services/event-bus/event-bus.service.d.ts.map +1 -1
  241. package/dist/cli/backend/src/services/event-bus/event-bus.service.js +83 -2
  242. package/dist/cli/backend/src/services/event-bus/event-bus.service.js.map +1 -1
  243. package/dist/cli/backend/src/services/memory/memory.service.d.ts +14 -2
  244. package/dist/cli/backend/src/services/memory/memory.service.d.ts.map +1 -1
  245. package/dist/cli/backend/src/services/memory/memory.service.js +12 -1
  246. package/dist/cli/backend/src/services/memory/memory.service.js.map +1 -1
  247. package/dist/cli/backend/src/services/memory/project-memory.service.d.ts +18 -1
  248. package/dist/cli/backend/src/services/memory/project-memory.service.d.ts.map +1 -1
  249. package/dist/cli/backend/src/services/memory/project-memory.service.js +38 -1
  250. package/dist/cli/backend/src/services/memory/project-memory.service.js.map +1 -1
  251. package/dist/cli/backend/src/services/memory/standing-answers.service.d.ts +11 -0
  252. package/dist/cli/backend/src/services/memory/standing-answers.service.d.ts.map +1 -1
  253. package/dist/cli/backend/src/services/memory/standing-answers.service.js +40 -2
  254. package/dist/cli/backend/src/services/memory/standing-answers.service.js.map +1 -1
  255. package/dist/cli/backend/src/services/messaging/owner-message-watchdog.service.d.ts +7 -1
  256. package/dist/cli/backend/src/services/messaging/owner-message-watchdog.service.d.ts.map +1 -1
  257. package/dist/cli/backend/src/services/messaging/owner-message-watchdog.service.js +16 -2
  258. package/dist/cli/backend/src/services/messaging/owner-message-watchdog.service.js.map +1 -1
  259. package/dist/cli/backend/src/services/messaging/queue-processor.service.d.ts.map +1 -1
  260. package/dist/cli/backend/src/services/messaging/queue-processor.service.js +9 -1
  261. package/dist/cli/backend/src/services/messaging/queue-processor.service.js.map +1 -1
  262. package/dist/cli/backend/src/services/messaging/sub-agent-message-queue.service.d.ts +41 -1
  263. package/dist/cli/backend/src/services/messaging/sub-agent-message-queue.service.d.ts.map +1 -1
  264. package/dist/cli/backend/src/services/messaging/sub-agent-message-queue.service.js +87 -2
  265. package/dist/cli/backend/src/services/messaging/sub-agent-message-queue.service.js.map +1 -1
  266. package/dist/cli/backend/src/services/monitoring/activity-monitor.service.d.ts +30 -12
  267. package/dist/cli/backend/src/services/monitoring/activity-monitor.service.d.ts.map +1 -1
  268. package/dist/cli/backend/src/services/monitoring/activity-monitor.service.js +87 -15
  269. package/dist/cli/backend/src/services/monitoring/activity-monitor.service.js.map +1 -1
  270. package/dist/cli/backend/src/services/monitoring/model-pricing.d.ts +97 -0
  271. package/dist/cli/backend/src/services/monitoring/model-pricing.d.ts.map +1 -0
  272. package/dist/cli/backend/src/services/monitoring/model-pricing.js +120 -0
  273. package/dist/cli/backend/src/services/monitoring/model-pricing.js.map +1 -0
  274. package/dist/cli/backend/src/services/monitoring/token-usage.service.d.ts +78 -1
  275. package/dist/cli/backend/src/services/monitoring/token-usage.service.d.ts.map +1 -1
  276. package/dist/cli/backend/src/services/monitoring/token-usage.service.js +96 -4
  277. package/dist/cli/backend/src/services/monitoring/token-usage.service.js.map +1 -1
  278. package/dist/cli/backend/src/services/open-items/open-item-extractor.d.ts +10 -1
  279. package/dist/cli/backend/src/services/open-items/open-item-extractor.d.ts.map +1 -1
  280. package/dist/cli/backend/src/services/open-items/open-item-extractor.js +86 -5
  281. package/dist/cli/backend/src/services/open-items/open-item-extractor.js.map +1 -1
  282. package/dist/cli/backend/src/services/slack/slack-typing-placeholder.service.d.ts +13 -2
  283. package/dist/cli/backend/src/services/slack/slack-typing-placeholder.service.d.ts.map +1 -1
  284. package/dist/cli/backend/src/services/slack/slack-typing-placeholder.service.js +19 -5
  285. package/dist/cli/backend/src/services/slack/slack-typing-placeholder.service.js.map +1 -1
  286. package/dist/cli/backend/src/services/spend/spend-cap.gate.d.ts +60 -0
  287. package/dist/cli/backend/src/services/spend/spend-cap.gate.d.ts.map +1 -0
  288. package/dist/cli/backend/src/services/spend/spend-cap.gate.js +66 -0
  289. package/dist/cli/backend/src/services/spend/spend-cap.gate.js.map +1 -0
  290. package/dist/cli/backend/src/services/task-pool/task-pool.service.d.ts +38 -0
  291. package/dist/cli/backend/src/services/task-pool/task-pool.service.d.ts.map +1 -1
  292. package/dist/cli/backend/src/services/task-pool/task-pool.service.js +73 -1
  293. package/dist/cli/backend/src/services/task-pool/task-pool.service.js.map +1 -1
  294. package/dist/cli/backend/src/services/task-pool/work-item-usage.d.ts +53 -0
  295. package/dist/cli/backend/src/services/task-pool/work-item-usage.d.ts.map +1 -0
  296. package/dist/cli/backend/src/services/task-pool/work-item-usage.js +39 -0
  297. package/dist/cli/backend/src/services/task-pool/work-item-usage.js.map +1 -0
  298. package/dist/cli/backend/src/services/usage/token-format.d.ts +49 -0
  299. package/dist/cli/backend/src/services/usage/token-format.d.ts.map +1 -0
  300. package/dist/cli/backend/src/services/usage/token-format.js +81 -0
  301. package/dist/cli/backend/src/services/usage/token-format.js.map +1 -0
  302. package/dist/cli/backend/src/services/v3/v3-data.service.d.ts.map +1 -1
  303. package/dist/cli/backend/src/services/v3/v3-data.service.js +11 -14
  304. package/dist/cli/backend/src/services/v3/v3-data.service.js.map +1 -1
  305. package/dist/cli/backend/src/types/decision.types.d.ts +3 -1
  306. package/dist/cli/backend/src/types/decision.types.d.ts.map +1 -1
  307. package/dist/cli/backend/src/types/event-bus.types.d.ts +9 -1
  308. package/dist/cli/backend/src/types/event-bus.types.d.ts.map +1 -1
  309. package/dist/cli/backend/src/types/event-bus.types.js.map +1 -1
  310. package/dist/cli/backend/src/types/ticket-autopilot.types.d.ts +24 -7
  311. package/dist/cli/backend/src/types/ticket-autopilot.types.d.ts.map +1 -1
  312. package/dist/cli/backend/src/types/ticket-autopilot.types.js +29 -13
  313. package/dist/cli/backend/src/types/ticket-autopilot.types.js.map +1 -1
  314. package/dist/cli/backend/src/types/v2/open-item.types.d.ts +5 -1
  315. package/dist/cli/backend/src/types/v2/open-item.types.d.ts.map +1 -1
  316. package/dist/cli/backend/src/types/v2/open-item.types.js +1 -1
  317. package/dist/cli/backend/src/types/v2/open-item.types.js.map +1 -1
  318. package/frontend/dist/assets/{index-a79c7852.css → index-20a67829.css} +1 -1
  319. package/frontend/dist/assets/{index-1ee8a9a2.js → index-49f50b45.js} +282 -282
  320. package/frontend/dist/index.html +2 -2
  321. package/package.json +1 -1
@@ -0,0 +1,311 @@
1
+ /**
2
+ * Codex Rollout Sync — records Codex CLI token usage in the shared ledger.
3
+ *
4
+ * Codex writes every conversation to `<codexHome>/sessions/YYYY/MM/DD/
5
+ * rollout-<time>-<conversation id>.jsonl`. After each model call it appends
6
+ * an `event_msg` line of type `token_count` whose `info.total_token_usage`
7
+ * is the conversation's running total (OpenAI convention: `input_tokens`
8
+ * includes `cached_input_tokens`; `output_tokens` includes reasoning) and
9
+ * `info.last_token_usage` is that one call. The model comes from the
10
+ * preceding `turn_context` line.
11
+ *
12
+ * Each pass reads only the bytes appended since the last pass (a byte
13
+ * cursor per file, persisted under CREWLY_HOME like the Claude transcript
14
+ * cursors) and records the DELTA of the running total, so a `token_count`
15
+ * line Codex repeats (it re-emits the same totals) is counted once, and a
16
+ * restart never re-counts a file.
17
+ *
18
+ * Attribution: Crewly persists each Codex agent's conversation id (learned
19
+ * from the rollout right after launch, see runtime-session-recovery) in the
20
+ * session state, so the rollout named `…-<id>.jsonl` belongs to that
21
+ * session. A cursor keeps its session after the agent moves to a fresh
22
+ * conversation, so the old file's last turns are still counted. Rollouts no
23
+ * Crewly agent owns (the owner's own Codex use) are never read.
24
+ *
25
+ * Events are stored in the ledger's "cached on top" shape (`input` = fresh
26
+ * tokens, `cachedInput` beside it, `runtime: 'codex-cli'`), the same as
27
+ * Claude transcript turns. specs/2026-10-02-spend-cap.md §Sources.
28
+ *
29
+ * @module services/monitoring/codex-rollout-sync
30
+ */
31
+ import { promises as fs } from 'fs';
32
+ import * as path from 'path';
33
+ import { CODEX_USAGE_SYNC_CONSTANTS as C, RUNTIME_TYPES } from '../../constants.js';
34
+ /**
35
+ * Read a usage block.
36
+ *
37
+ * @param u - `total_token_usage` / `last_token_usage`
38
+ * @returns Totals, or null when it is not one
39
+ */
40
+ function totalsOf(u) {
41
+ if (!u || typeof u !== 'object')
42
+ return null;
43
+ const o = u;
44
+ const num = (k) => (typeof o[k] === 'number' && Number.isFinite(o[k]) ? Math.max(0, o[k]) : 0);
45
+ const input = num('input_tokens');
46
+ const output = num('output_tokens');
47
+ const total = typeof o.total_tokens === 'number' ? num('total_tokens') : input + output;
48
+ return { input, cached: Math.min(num('cached_input_tokens'), input), output, total };
49
+ }
50
+ /**
51
+ * Turn whole JSONL lines of a rollout into usage events. Mutates `state`.
52
+ *
53
+ * - `turn_context` sets the model;
54
+ * - `token_count` with a running total records the delta since the last
55
+ * counted total (0 = a repeated line, skipped);
56
+ * - a running total that went DOWN, or the first total of a file, records
57
+ * only that call's `last_token_usage` (a resumed conversation's file may
58
+ * open with history counted elsewhere).
59
+ *
60
+ * @param text - Whole lines
61
+ * @param state - Parse state (model, last total)
62
+ * @returns Events in file order
63
+ */
64
+ export function parseCodexRolloutLines(text, state) {
65
+ const events = [];
66
+ for (const line of text.split('\n')) {
67
+ if (!line.trim())
68
+ continue;
69
+ let entry;
70
+ try {
71
+ entry = JSON.parse(line);
72
+ }
73
+ catch {
74
+ continue;
75
+ }
76
+ const payload = entry.payload;
77
+ if (!payload || typeof payload !== 'object')
78
+ continue;
79
+ if (entry.type === 'turn_context') {
80
+ if (typeof payload.model === 'string' && payload.model)
81
+ state.model = payload.model;
82
+ continue;
83
+ }
84
+ if (entry.type !== 'event_msg' || payload.type !== 'token_count')
85
+ continue;
86
+ const info = payload.info;
87
+ if (!info)
88
+ continue;
89
+ const total = totalsOf(info.total_token_usage);
90
+ const last = totalsOf(info.last_token_usage);
91
+ if (!total && !last)
92
+ continue;
93
+ let delta;
94
+ const prev = state.lastTotal;
95
+ if (total && prev && total.total >= prev.total) {
96
+ delta = {
97
+ input: Math.max(0, total.input - prev.input),
98
+ cached: Math.max(0, total.cached - prev.cached),
99
+ output: Math.max(0, total.output - prev.output),
100
+ total: total.total - prev.total,
101
+ };
102
+ }
103
+ else {
104
+ delta = last ?? total;
105
+ }
106
+ if (total)
107
+ state.lastTotal = total;
108
+ if (!delta || delta.input + delta.output <= 0)
109
+ continue;
110
+ const cached = Math.min(delta.cached, delta.input);
111
+ events.push({
112
+ timestamp: entry.timestamp || new Date().toISOString(),
113
+ model: state.model || C.DEFAULT_MODEL,
114
+ input: delta.input - cached,
115
+ cachedInput: cached,
116
+ output: delta.output,
117
+ });
118
+ }
119
+ return events;
120
+ }
121
+ /**
122
+ * Find a conversation's rollout file by id.
123
+ *
124
+ * @param codexHome - Codex home
125
+ * @param conversationId - Conversation id
126
+ * @returns Absolute path, or null
127
+ */
128
+ export async function findCodexRollout(codexHome, conversationId) {
129
+ const suffix = `-${conversationId}.jsonl`;
130
+ const stack = [path.join(codexHome, 'sessions')];
131
+ let visited = 0;
132
+ while (stack.length > 0 && visited < C.MAX_SCAN_ENTRIES) {
133
+ const dir = stack.pop();
134
+ let entries;
135
+ try {
136
+ entries = await fs.readdir(dir, { withFileTypes: true });
137
+ }
138
+ catch {
139
+ continue;
140
+ }
141
+ // Newest day directories last on the stack = visited first.
142
+ entries.sort((a, b) => a.name.localeCompare(b.name));
143
+ for (const e of entries) {
144
+ visited += 1;
145
+ if (e.isDirectory())
146
+ stack.push(path.join(dir, e.name));
147
+ else if (e.name.startsWith('rollout-') && e.name.endsWith(suffix))
148
+ return path.join(dir, e.name);
149
+ }
150
+ }
151
+ return null;
152
+ }
153
+ /**
154
+ * Polls Codex rollouts of Crewly's Codex agents and records their usage.
155
+ */
156
+ export class CodexRolloutSyncService {
157
+ deps;
158
+ cursors = new Map();
159
+ loaded = false;
160
+ running = false;
161
+ timer = null;
162
+ /** Conversation id → when a lookup last failed (ms), to avoid rescanning every pass */
163
+ missing = new Map();
164
+ /**
165
+ * @param deps - Collaborators
166
+ */
167
+ constructor(deps) {
168
+ this.deps = deps;
169
+ }
170
+ /** Run a pass now, then poll. */
171
+ async start() {
172
+ if (this.timer)
173
+ return;
174
+ await this.sync();
175
+ this.timer = setInterval(() => void this.sync(), C.SYNC_INTERVAL_MS);
176
+ this.timer.unref?.();
177
+ }
178
+ /** Stop polling. */
179
+ stop() {
180
+ if (this.timer)
181
+ clearInterval(this.timer);
182
+ this.timer = null;
183
+ }
184
+ /**
185
+ * @param filePath - Rollout path
186
+ * @returns Its cursor (tests, diagnostics)
187
+ */
188
+ getCursor(filePath) {
189
+ return this.cursors.get(filePath);
190
+ }
191
+ /**
192
+ * One pass: adopt rollouts of newly seen Codex conversations, then read
193
+ * the new tail of every known rollout.
194
+ *
195
+ * @returns What the pass recorded
196
+ */
197
+ async sync() {
198
+ const result = { filesRead: 0, eventsRecorded: 0, tokensRecorded: 0 };
199
+ if (this.running)
200
+ return result;
201
+ this.running = true;
202
+ let changed = false;
203
+ try {
204
+ if (!this.loaded)
205
+ await this.load();
206
+ const known = new Set([...this.cursors.values()].map((c) => c.conversationId));
207
+ for (const [session, info] of this.deps.sessions()) {
208
+ const id = info.claudeSessionId;
209
+ if (info.runtimeType !== RUNTIME_TYPES.CODEX_CLI || !id || known.has(id))
210
+ continue;
211
+ const failedAt = this.missing.get(id);
212
+ if (failedAt !== undefined && Date.now() - failedAt < 10 * C.SYNC_INTERVAL_MS)
213
+ continue;
214
+ const file = await findCodexRollout(this.deps.codexHome, id);
215
+ if (!file) {
216
+ this.missing.set(id, Date.now());
217
+ continue;
218
+ }
219
+ this.missing.delete(id);
220
+ this.cursors.set(file, { session, conversationId: id, offset: 0, model: '', lastTotal: null });
221
+ known.add(id);
222
+ changed = true;
223
+ }
224
+ for (const [file, cursor] of this.cursors) {
225
+ const r = await this.syncFile(file, cursor);
226
+ if (r.read) {
227
+ result.filesRead += 1;
228
+ changed = true;
229
+ }
230
+ result.eventsRecorded += r.events;
231
+ result.tokensRecorded += r.tokens;
232
+ }
233
+ if (changed)
234
+ await this.save();
235
+ if (result.eventsRecorded > 0)
236
+ this.deps.logger?.info('Synced Codex rollouts', { ...result });
237
+ }
238
+ catch (err) {
239
+ this.deps.logger?.warn('Codex rollout sync pass failed', { error: err instanceof Error ? err.message : String(err) });
240
+ }
241
+ finally {
242
+ this.running = false;
243
+ }
244
+ return result;
245
+ }
246
+ async syncFile(file, cursor) {
247
+ let size;
248
+ try {
249
+ size = (await fs.stat(file)).size;
250
+ }
251
+ catch {
252
+ return { read: false, events: 0, tokens: 0 };
253
+ }
254
+ if (size < cursor.offset) {
255
+ // Rewritten underneath us: start over (the running-total delta keeps
256
+ // already counted calls from counting twice only within one file
257
+ // generation, so drop the total too).
258
+ cursor.offset = 0;
259
+ cursor.lastTotal = null;
260
+ }
261
+ if (size === cursor.offset)
262
+ return { read: false, events: 0, tokens: 0 };
263
+ const handle = await fs.open(file, 'r');
264
+ let tail;
265
+ try {
266
+ const buf = Buffer.alloc(size - cursor.offset);
267
+ await handle.read(buf, 0, buf.length, cursor.offset);
268
+ tail = buf.toString('utf-8');
269
+ }
270
+ finally {
271
+ await handle.close();
272
+ }
273
+ const nl = tail.lastIndexOf('\n');
274
+ if (nl < 0)
275
+ return { read: false, events: 0, tokens: 0 };
276
+ const complete = tail.slice(0, nl);
277
+ const state = { model: cursor.model, lastTotal: cursor.lastTotal };
278
+ const events = parseCodexRolloutLines(complete, state);
279
+ cursor.offset += Buffer.byteLength(complete, 'utf-8') + 1;
280
+ cursor.model = state.model;
281
+ cursor.lastTotal = state.lastTotal;
282
+ let tokens = 0;
283
+ for (const e of events) {
284
+ this.deps.record(cursor.session, e);
285
+ tokens += e.input + e.cachedInput + e.output;
286
+ }
287
+ return { read: true, events: events.length, tokens };
288
+ }
289
+ async load() {
290
+ this.loaded = true;
291
+ try {
292
+ const parsed = JSON.parse(await fs.readFile(this.deps.cursorFile, 'utf-8'));
293
+ this.cursors = new Map(Object.entries(parsed));
294
+ }
295
+ catch {
296
+ this.cursors = new Map();
297
+ }
298
+ }
299
+ async save() {
300
+ const tmp = `${this.deps.cursorFile}.tmp`;
301
+ try {
302
+ await fs.mkdir(path.dirname(this.deps.cursorFile), { recursive: true });
303
+ await fs.writeFile(tmp, JSON.stringify(Object.fromEntries(this.cursors), null, 2), 'utf-8');
304
+ await fs.rename(tmp, this.deps.cursorFile);
305
+ }
306
+ catch (err) {
307
+ this.deps.logger?.warn('Could not save Codex rollout cursors', { error: err instanceof Error ? err.message : String(err) });
308
+ }
309
+ }
310
+ }
311
+ //# sourceMappingURL=codex-rollout-sync.service.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"codex-rollout-sync.service.js","sourceRoot":"","sources":["../../../../../../backend/src/services/monitoring/codex-rollout-sync.service.ts"],"names":[],"mappings":"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"}
@@ -34,6 +34,12 @@ export interface TokenUsageEvent {
34
34
  * rate) rather than read from it. Claude only; absent when unknown.
35
35
  */
36
36
  cacheWrite?: number;
37
+ /**
38
+ * Runtime that produced the event (`codex-cli`, `antigravity-cli`, …), set
39
+ * by the sources that know it. Absent on older events and on sources that
40
+ * only know the model; {@link runtimeOfEvent} then infers it from the model.
41
+ */
42
+ runtime?: string;
37
43
  }
38
44
  /** Optional per-event detail beyond the raw input/output counts. */
39
45
  export interface TokenUsageDetail {
@@ -49,6 +55,8 @@ export interface TokenUsageDetail {
49
55
  * any per-day or per-hour view of the data is wrong.
50
56
  */
51
57
  timestamp?: string;
58
+ /** See {@link TokenUsageEvent.runtime}. */
59
+ runtime?: string;
52
60
  }
53
61
  /**
54
62
  * Per-session token usage record containing all events and aggregates
@@ -137,6 +145,63 @@ export declare const TOKEN_COSTS: Record<string, {
137
145
  * @returns Cost in USD
138
146
  */
139
147
  export declare function calculateCost(inputTokens: number, outputTokens: number, model: string, cachedInputTokens?: number): number;
148
+ /**
149
+ * USD cost of one recorded usage event — the one cost computation every
150
+ * spend view uses (session windows, the team budget gate, the ticket
151
+ * autopilot budget, the per-agent spend cap).
152
+ *
153
+ * The ledger holds two shapes of event:
154
+ * - in-process runs (`provider/model`, e.g. DeepSeek): `cachedInput` is the
155
+ * cache-hit PART of `input`, priced with {@link TOKEN_COSTS};
156
+ * - Claude Code transcript turns: `input` is the fresh tokens only and
157
+ * `cachedInput` (cache reads + `cacheWrite`) comes on top, priced with the
158
+ * cache-aware model-pricing table. Pricing these with {@link TOKEN_COSTS}
159
+ * dropped every cached token and used sonnet rates for opus.
160
+ *
161
+ * @param event - The usage event
162
+ * @returns Cost in USD
163
+ */
164
+ export declare function eventCostUsd(event: Pick<TokenUsageEvent, 'input' | 'output' | 'model' | 'cachedInput' | 'cacheWrite'>): number;
165
+ /** The token figures of one event in the owner-facing unit (see {@link eventTokens}). */
166
+ export interface EventTokens {
167
+ /** Every input token, cached ones included */
168
+ input: number;
169
+ /** The cached part of {@link input} (cache reads + cache writes) */
170
+ cachedInput: number;
171
+ output: number;
172
+ /** {@link input} + {@link output} — what caps, boosts and budgets count */
173
+ total: number;
174
+ }
175
+ /**
176
+ * Whether an event's `cachedInput` is part of its `input` (true) or comes
177
+ * on top of it (false).
178
+ *
179
+ * - In-process runs (`provider/model`, e.g. DeepSeek) report the provider's
180
+ * prompt-token count, which includes cache hits: part of `input`.
181
+ * - Claude Code transcript turns, Codex rollouts and Antigravity record
182
+ * `input` as the fresh tokens only, with the cached ones on top.
183
+ *
184
+ * @param event - Usage event
185
+ * @returns True when cached tokens are already inside `input`
186
+ */
187
+ export declare function cachedIsPartOfInput(event: Pick<TokenUsageEvent, 'model' | 'runtime'>): boolean;
188
+ /**
189
+ * The token unit — ONE formula for every cap, boost, budget and stat:
190
+ *
191
+ * total tokens = input tokens (fresh + cached) + output tokens
192
+ *
193
+ * Cached input counts in full (it is shown separately, never left out), and
194
+ * whether an account is billed by subscription or by API makes no
195
+ * difference. specs/2026-10-02-spend-cap.md §Token unit.
196
+ *
197
+ * @param event - Usage event
198
+ * @returns Input (cached included), cached input, output, total
199
+ *
200
+ * @example
201
+ * eventTokens({ model: 'claude-opus-5-5', input: 10, cachedInput: 990, output: 50 }).total // 1050
202
+ * eventTokens({ model: 'deepseek/deepseek-chat', input: 1000, cachedInput: 990, output: 50 }).total // 1050
203
+ */
204
+ export declare function eventTokens(event: Pick<TokenUsageEvent, 'model' | 'runtime' | 'input' | 'output' | 'cachedInput'>): EventTokens;
140
205
  /**
141
206
  * Set a cost override for a session. When present, getSummary() uses this
142
207
  * instead of recalculating from events.
@@ -264,13 +329,25 @@ export declare class TokenUsageService {
264
329
  * @param sessionName - The session to query (e.g. 'crewly-orc')
265
330
  * @param since - Only return events recorded at or after this time
266
331
  * @param until - Only return events before this time (defaults to now)
267
- * @returns Aggregated input tokens, output tokens, and cost in the window
332
+ * @returns Aggregated input tokens, output tokens, and cost in the window,
333
+ * plus the token-unit figures ({@link eventTokens}): `totalTokens` (the
334
+ * unit caps and budgets count) and `cachedInputTokens`
268
335
  */
269
336
  getSessionUsageSince(sessionName: string, since: Date, until?: Date): {
270
337
  inputTokens: number;
271
338
  outputTokens: number;
272
339
  cost: number;
340
+ totalTokens: number;
341
+ cachedInputTokens: number;
273
342
  };
343
+ /**
344
+ * Visit every recorded event at or after `since` (all events when omitted).
345
+ * Read-only; used by the spend ledger for per-day / per-agent views.
346
+ *
347
+ * @param visit - Called with the session name and the event
348
+ * @param since - Lower bound (inclusive)
349
+ */
350
+ forEachEvent(visit: (sessionName: string, event: TokenUsageEvent) => void, since?: Date): void;
274
351
  /**
275
352
  * Clear all tracked token usage data.
276
353
  */
@@ -1 +1 @@
1
- {"version":3,"file":"token-usage.service.d.ts","sourceRoot":"","sources":["../../../../../../backend/src/services/monitoring/token-usage.service.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"token-usage.service.d.ts","sourceRoot":"","sources":["../../../../../../backend/src/services/monitoring/token-usage.service.ts"],"names":[],"mappings":"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"}
@@ -8,6 +8,7 @@
8
8
  */
9
9
  import { promises as fs } from 'fs';
10
10
  import * as path from 'path';
11
+ import { calculateCost as calculateCacheAwareCost, resolveRate } from './model-pricing.js';
11
12
  /** File name for persisting token usage data */
12
13
  const TOKEN_USAGE_FILE = 'token-usage.json';
13
14
  /** Interval in milliseconds between periodic flushes to disk (5 minutes) */
@@ -59,6 +60,73 @@ export function calculateCost(inputTokens, outputTokens, model, cachedInputToken
59
60
  const cached = rates.cachedInput !== undefined ? Math.min(Math.max(cachedInputTokens, 0), inputTokens) : 0;
60
61
  return (inputTokens - cached) * rates.input + cached * (rates.cachedInput ?? 0) + outputTokens * rates.output;
61
62
  }
63
+ /**
64
+ * USD cost of one recorded usage event — the one cost computation every
65
+ * spend view uses (session windows, the team budget gate, the ticket
66
+ * autopilot budget, the per-agent spend cap).
67
+ *
68
+ * The ledger holds two shapes of event:
69
+ * - in-process runs (`provider/model`, e.g. DeepSeek): `cachedInput` is the
70
+ * cache-hit PART of `input`, priced with {@link TOKEN_COSTS};
71
+ * - Claude Code transcript turns: `input` is the fresh tokens only and
72
+ * `cachedInput` (cache reads + `cacheWrite`) comes on top, priced with the
73
+ * cache-aware model-pricing table. Pricing these with {@link TOKEN_COSTS}
74
+ * dropped every cached token and used sonnet rates for opus.
75
+ *
76
+ * @param event - The usage event
77
+ * @returns Cost in USD
78
+ */
79
+ export function eventCostUsd(event) {
80
+ const model = event.model || '';
81
+ const unprefixed = model.includes('/') ? model.slice(model.indexOf('/') + 1) : model;
82
+ const legacyKey = TOKEN_COSTS[model] ? model : TOKEN_COSTS[unprefixed] ? unprefixed : null;
83
+ if (!model.includes('/') && resolveRate(model).source !== 'default') {
84
+ const write = Math.max(0, event.cacheWrite ?? 0);
85
+ const read = Math.max(0, (event.cachedInput ?? 0) - write);
86
+ return calculateCacheAwareCost({ input: event.input, output: event.output, cacheRead: read, cacheWrite: write }, model).cost;
87
+ }
88
+ return calculateCost(event.input, event.output, legacyKey ?? model, event.cachedInput ?? 0);
89
+ }
90
+ /**
91
+ * Whether an event's `cachedInput` is part of its `input` (true) or comes
92
+ * on top of it (false).
93
+ *
94
+ * - In-process runs (`provider/model`, e.g. DeepSeek) report the provider's
95
+ * prompt-token count, which includes cache hits: part of `input`.
96
+ * - Claude Code transcript turns, Codex rollouts and Antigravity record
97
+ * `input` as the fresh tokens only, with the cached ones on top.
98
+ *
99
+ * @param event - Usage event
100
+ * @returns True when cached tokens are already inside `input`
101
+ */
102
+ export function cachedIsPartOfInput(event) {
103
+ if (event.runtime)
104
+ return event.runtime === 'crewly-agent';
105
+ return (event.model || '').includes('/');
106
+ }
107
+ /**
108
+ * The token unit — ONE formula for every cap, boost, budget and stat:
109
+ *
110
+ * total tokens = input tokens (fresh + cached) + output tokens
111
+ *
112
+ * Cached input counts in full (it is shown separately, never left out), and
113
+ * whether an account is billed by subscription or by API makes no
114
+ * difference. specs/2026-10-02-spend-cap.md §Token unit.
115
+ *
116
+ * @param event - Usage event
117
+ * @returns Input (cached included), cached input, output, total
118
+ *
119
+ * @example
120
+ * eventTokens({ model: 'claude-opus-5-5', input: 10, cachedInput: 990, output: 50 }).total // 1050
121
+ * eventTokens({ model: 'deepseek/deepseek-chat', input: 1000, cachedInput: 990, output: 50 }).total // 1050
122
+ */
123
+ export function eventTokens(event) {
124
+ const raw = Math.max(0, event.input || 0);
125
+ const cached = Math.max(0, event.cachedInput || 0);
126
+ const output = Math.max(0, event.output || 0);
127
+ const input = cachedIsPartOfInput(event) ? Math.max(raw, cached) : raw + cached;
128
+ return { input, cachedInput: Math.min(cached, input), output, total: input + output };
129
+ }
62
130
  /**
63
131
  * Stores a pre-calculated cost override for a session.
64
132
  * Used when the caller has more accurate cost data (e.g., cache-aware pricing
@@ -169,6 +237,7 @@ export class TokenUsageService {
169
237
  ...(detail?.cachedInput !== undefined ? { cachedInput: detail.cachedInput } : {}),
170
238
  ...(detail?.steps !== undefined ? { steps: detail.steps } : {}),
171
239
  ...(detail?.cacheWrite ? { cacheWrite: detail.cacheWrite } : {}),
240
+ ...(detail?.runtime ? { runtime: detail.runtime } : {}),
172
241
  };
173
242
  record.events.push(event);
174
243
  record.totalInput += input;
@@ -326,17 +395,21 @@ export class TokenUsageService {
326
395
  * @param sessionName - The session to query (e.g. 'crewly-orc')
327
396
  * @param since - Only return events recorded at or after this time
328
397
  * @param until - Only return events before this time (defaults to now)
329
- * @returns Aggregated input tokens, output tokens, and cost in the window
398
+ * @returns Aggregated input tokens, output tokens, and cost in the window,
399
+ * plus the token-unit figures ({@link eventTokens}): `totalTokens` (the
400
+ * unit caps and budgets count) and `cachedInputTokens`
330
401
  */
331
402
  getSessionUsageSince(sessionName, since, until) {
332
403
  const record = this.sessions.get(sessionName);
333
404
  if (!record)
334
- return { inputTokens: 0, outputTokens: 0, cost: 0 };
405
+ return { inputTokens: 0, outputTokens: 0, cost: 0, totalTokens: 0, cachedInputTokens: 0 };
335
406
  const sinceMs = since.getTime();
336
407
  const untilMs = until ? until.getTime() : Infinity;
337
408
  let inputTokens = 0;
338
409
  let outputTokens = 0;
339
410
  let cost = 0;
411
+ let totalTokens = 0;
412
+ let cachedInputTokens = 0;
340
413
  for (const event of record.events) {
341
414
  const eventMs = new Date(event.timestamp).getTime();
342
415
  if (eventMs >= sinceMs && eventMs <= untilMs) {
@@ -345,10 +418,29 @@ export class TokenUsageService {
345
418
  // Cache-aware: a cache hit is billed at a fraction of the miss rate,
346
419
  // and the team budget gate keys on this figure — pricing every input
347
420
  // token at the miss rate would trip monthly USD caps ~40x early.
348
- cost += calculateCost(event.input, event.output, event.model, event.cachedInput ?? 0);
421
+ cost += eventCostUsd(event);
422
+ const t = eventTokens(event);
423
+ totalTokens += t.total;
424
+ cachedInputTokens += t.cachedInput;
425
+ }
426
+ }
427
+ return { inputTokens, outputTokens, cost, totalTokens, cachedInputTokens };
428
+ }
429
+ /**
430
+ * Visit every recorded event at or after `since` (all events when omitted).
431
+ * Read-only; used by the spend ledger for per-day / per-agent views.
432
+ *
433
+ * @param visit - Called with the session name and the event
434
+ * @param since - Lower bound (inclusive)
435
+ */
436
+ forEachEvent(visit, since) {
437
+ const sinceMs = since ? since.getTime() : -Infinity;
438
+ for (const record of this.sessions.values()) {
439
+ for (const event of record.events) {
440
+ if (new Date(event.timestamp).getTime() >= sinceMs)
441
+ visit(record.sessionName, event);
349
442
  }
350
443
  }
351
- return { inputTokens, outputTokens, cost };
352
444
  }
353
445
  /**
354
446
  * Clear all tracked token usage data.