@songsid/agend 2.1.12 → 2.2.0-alpha.2

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 (436) hide show
  1. package/README.md +4 -2
  2. package/README.zh-TW.md +4 -2
  3. package/dist/agent-cli.js +6 -1
  4. package/dist/agent-cli.js.map +1 -1
  5. package/dist/agent-endpoint.js +68 -12
  6. package/dist/agent-endpoint.js.map +1 -1
  7. package/dist/agent-token-header.d.ts +13 -0
  8. package/dist/agent-token-header.js +16 -0
  9. package/dist/agent-token-header.js.map +1 -0
  10. package/dist/auth/one-time-code.d.ts +19 -0
  11. package/dist/auth/one-time-code.js +49 -0
  12. package/dist/auth/one-time-code.js.map +1 -0
  13. package/dist/auth-api.d.ts +52 -0
  14. package/dist/auth-api.js +346 -0
  15. package/dist/auth-api.js.map +1 -0
  16. package/dist/backend/antigravity.js +4 -3
  17. package/dist/backend/antigravity.js.map +1 -1
  18. package/dist/backend/claude-code.d.ts +4 -0
  19. package/dist/backend/claude-code.js +97 -0
  20. package/dist/backend/claude-code.js.map +1 -1
  21. package/dist/backend/codex.js +59 -30
  22. package/dist/backend/codex.js.map +1 -1
  23. package/dist/backend/grok.js +1 -1
  24. package/dist/backend/grok.js.map +1 -1
  25. package/dist/backend/kiro-agent.d.ts +66 -0
  26. package/dist/backend/kiro-agent.js +302 -0
  27. package/dist/backend/kiro-agent.js.map +1 -0
  28. package/dist/backend/kiro-identity.d.ts +80 -0
  29. package/dist/backend/kiro-identity.js +537 -0
  30. package/dist/backend/kiro-identity.js.map +1 -0
  31. package/dist/backend/kiro-v2-store-worker.d.ts +1 -0
  32. package/dist/backend/kiro-v2-store-worker.js +87 -0
  33. package/dist/backend/kiro-v2-store-worker.js.map +1 -0
  34. package/dist/backend/kiro-v2-store.d.ts +54 -0
  35. package/dist/backend/kiro-v2-store.js +131 -0
  36. package/dist/backend/kiro-v2-store.js.map +1 -0
  37. package/dist/backend/kiro-v3-identity.d.ts +5 -0
  38. package/dist/backend/kiro-v3-identity.js +22 -0
  39. package/dist/backend/kiro-v3-identity.js.map +1 -1
  40. package/dist/backend/kiro.d.ts +90 -7
  41. package/dist/backend/kiro.js +500 -124
  42. package/dist/backend/kiro.js.map +1 -1
  43. package/dist/backend/muse.js +1 -1
  44. package/dist/backend/muse.js.map +1 -1
  45. package/dist/backend/types.d.ts +51 -3
  46. package/dist/backend/types.js.map +1 -1
  47. package/dist/cache-analysis.d.ts +92 -0
  48. package/dist/cache-analysis.js +147 -0
  49. package/dist/cache-analysis.js.map +1 -0
  50. package/dist/cache-ledger.d.ts +108 -0
  51. package/dist/cache-ledger.js +230 -0
  52. package/dist/cache-ledger.js.map +1 -0
  53. package/dist/cache-prices.d.ts +32 -0
  54. package/dist/cache-prices.js +73 -0
  55. package/dist/cache-prices.js.map +1 -0
  56. package/dist/cache-scan.d.ts +39 -0
  57. package/dist/cache-scan.js +115 -0
  58. package/dist/cache-scan.js.map +1 -0
  59. package/dist/cache-service.d.ts +115 -0
  60. package/dist/cache-service.js +417 -0
  61. package/dist/cache-service.js.map +1 -0
  62. package/dist/channel/adapters/discord.d.ts +1 -0
  63. package/dist/channel/adapters/discord.js +29 -10
  64. package/dist/channel/adapters/discord.js.map +1 -1
  65. package/dist/channel/adapters/telegram.d.ts +1 -0
  66. package/dist/channel/adapters/telegram.js +13 -1
  67. package/dist/channel/adapters/telegram.js.map +1 -1
  68. package/dist/channel/types.d.ts +9 -1
  69. package/dist/classic-channel-manager.d.ts +18 -10
  70. package/dist/classic-channel-manager.js +45 -18
  71. package/dist/classic-channel-manager.js.map +1 -1
  72. package/dist/cli-entry.d.ts +19 -0
  73. package/dist/cli-entry.js +36 -0
  74. package/dist/cli-entry.js.map +1 -0
  75. package/dist/cli.js +471 -146
  76. package/dist/cli.js.map +1 -1
  77. package/dist/command-table.d.ts +5 -3
  78. package/dist/command-table.js +29 -27
  79. package/dist/command-table.js.map +1 -1
  80. package/dist/config-validator.js +46 -0
  81. package/dist/config-validator.js.map +1 -1
  82. package/dist/config.js +12 -0
  83. package/dist/config.js.map +1 -1
  84. package/dist/connection-secrets.d.ts +6 -0
  85. package/dist/connection-secrets.js +4 -0
  86. package/dist/connection-secrets.js.map +1 -1
  87. package/dist/daemon.d.ts +95 -4
  88. package/dist/daemon.js +748 -111
  89. package/dist/daemon.js.map +1 -1
  90. package/dist/darwin-memory.d.ts +6 -1
  91. package/dist/darwin-memory.js +17 -6
  92. package/dist/darwin-memory.js.map +1 -1
  93. package/dist/delivery-consumed-watch.d.ts +85 -0
  94. package/dist/delivery-consumed-watch.js +244 -0
  95. package/dist/delivery-consumed-watch.js.map +1 -0
  96. package/dist/delivery-outbox.d.ts +61 -0
  97. package/dist/delivery-outbox.js +120 -2
  98. package/dist/delivery-outbox.js.map +1 -1
  99. package/dist/delivery-reconciliation.d.ts +14 -5
  100. package/dist/delivery-reconciliation.js +27 -4
  101. package/dist/delivery-reconciliation.js.map +1 -1
  102. package/dist/delivery-reconciliation.test.js +35 -1
  103. package/dist/delivery-reconciliation.test.js.map +1 -1
  104. package/dist/event-log.d.ts +4 -1
  105. package/dist/event-log.js +6 -3
  106. package/dist/event-log.js.map +1 -1
  107. package/dist/event-loop-watch.d.ts +28 -0
  108. package/dist/event-loop-watch.js +75 -3
  109. package/dist/event-loop-watch.js.map +1 -1
  110. package/dist/fleet-context.d.ts +22 -2
  111. package/dist/fleet-control-audit.d.ts +5 -0
  112. package/dist/fleet-control-audit.js +7 -0
  113. package/dist/fleet-control-audit.js.map +1 -1
  114. package/dist/fleet-level-config.d.ts +2 -2
  115. package/dist/fleet-level-config.js +28 -1
  116. package/dist/fleet-level-config.js.map +1 -1
  117. package/dist/fleet-manager.d.ts +339 -12
  118. package/dist/fleet-manager.js +2623 -461
  119. package/dist/fleet-manager.js.map +1 -1
  120. package/dist/full-restart.js +2 -3
  121. package/dist/full-restart.js.map +1 -1
  122. package/dist/general-knowledge/skills/persona-emoji/SKILL.md +3 -1
  123. package/dist/host-memory.d.ts +4 -0
  124. package/dist/host-memory.js.map +1 -1
  125. package/dist/install-lock.d.ts +49 -0
  126. package/dist/install-lock.js +200 -0
  127. package/dist/install-lock.js.map +1 -0
  128. package/dist/instance-config-impact.js +8 -2
  129. package/dist/instance-config-impact.js.map +1 -1
  130. package/dist/instance-lifecycle.d.ts +10 -5
  131. package/dist/instance-lifecycle.js +162 -53
  132. package/dist/instance-lifecycle.js.map +1 -1
  133. package/dist/locale.js +164 -16
  134. package/dist/locale.js.map +1 -1
  135. package/dist/login-controller.d.ts +2 -0
  136. package/dist/login-controller.js +17 -5
  137. package/dist/login-controller.js.map +1 -1
  138. package/dist/memory-pressure.d.ts +7 -8
  139. package/dist/memory-pressure.js +76 -15
  140. package/dist/memory-pressure.js.map +1 -1
  141. package/dist/monotonic-budget.d.ts +2 -0
  142. package/dist/monotonic-budget.js +28 -0
  143. package/dist/monotonic-budget.js.map +1 -0
  144. package/dist/needs-you-hub.d.ts +114 -0
  145. package/dist/needs-you-hub.js +370 -0
  146. package/dist/needs-you-hub.js.map +1 -0
  147. package/dist/needs-you-live.d.ts +116 -0
  148. package/dist/needs-you-live.js +228 -0
  149. package/dist/needs-you-live.js.map +1 -0
  150. package/dist/needs-you.d.ts +132 -0
  151. package/dist/needs-you.js +164 -0
  152. package/dist/needs-you.js.map +1 -0
  153. package/dist/node-version-guard.d.ts +30 -0
  154. package/dist/node-version-guard.js +50 -0
  155. package/dist/node-version-guard.js.map +1 -0
  156. package/dist/operator-control-paths.d.ts +4 -0
  157. package/dist/operator-control-paths.js +24 -0
  158. package/dist/operator-control-paths.js.map +1 -0
  159. package/dist/outbound-handlers.d.ts +2 -0
  160. package/dist/outbound-handlers.js +9 -2
  161. package/dist/outbound-handlers.js.map +1 -1
  162. package/dist/outbound-schemas.d.ts +5 -5
  163. package/dist/outbound-schemas.js +1 -1
  164. package/dist/outbound-schemas.js.map +1 -1
  165. package/dist/package-preimage.d.ts +26 -0
  166. package/dist/package-preimage.js +96 -0
  167. package/dist/package-preimage.js.map +1 -0
  168. package/dist/profile-control.js +4 -20
  169. package/dist/profile-control.js.map +1 -1
  170. package/dist/public-web-gateway.d.ts +18 -0
  171. package/dist/public-web-gateway.js +141 -0
  172. package/dist/public-web-gateway.js.map +1 -0
  173. package/dist/public-web-link.d.ts +53 -0
  174. package/dist/public-web-link.js +175 -0
  175. package/dist/public-web-link.js.map +1 -0
  176. package/dist/quickstart-api.d.ts +8 -1
  177. package/dist/quickstart-api.js +86 -48
  178. package/dist/quickstart-api.js.map +1 -1
  179. package/dist/quickstart.d.ts +1 -0
  180. package/dist/quickstart.js +16 -6
  181. package/dist/quickstart.js.map +1 -1
  182. package/dist/restart-guard.d.ts +52 -0
  183. package/dist/restart-guard.js +109 -0
  184. package/dist/restart-guard.js.map +1 -0
  185. package/dist/scheduler/db.d.ts +7 -1
  186. package/dist/scheduler/db.js +44 -2
  187. package/dist/scheduler/db.js.map +1 -1
  188. package/dist/scheduler/index.d.ts +1 -1
  189. package/dist/scheduler/retry-label.d.ts +11 -0
  190. package/dist/scheduler/retry-label.js +24 -0
  191. package/dist/scheduler/retry-label.js.map +1 -0
  192. package/dist/scheduler/scheduler.d.ts +55 -2
  193. package/dist/scheduler/scheduler.js +220 -8
  194. package/dist/scheduler/scheduler.js.map +1 -1
  195. package/dist/scheduler/types.d.ts +22 -0
  196. package/dist/scheduler/types.js.map +1 -1
  197. package/dist/secret-store.d.ts +5 -0
  198. package/dist/secret-store.js +20 -0
  199. package/dist/secret-store.js.map +1 -1
  200. package/dist/service-activation.d.ts +152 -0
  201. package/dist/service-activation.js +407 -0
  202. package/dist/service-activation.js.map +1 -0
  203. package/dist/service-installer.d.ts +63 -1
  204. package/dist/service-installer.js +141 -16
  205. package/dist/service-installer.js.map +1 -1
  206. package/dist/service-plan.d.ts +65 -0
  207. package/dist/service-plan.js +108 -0
  208. package/dist/service-plan.js.map +1 -0
  209. package/dist/service-restart-selection.d.ts +6 -5
  210. package/dist/service-restart-selection.js +6 -5
  211. package/dist/service-restart-selection.js.map +1 -1
  212. package/dist/settings-api.d.ts +10 -2
  213. package/dist/settings-api.js +216 -72
  214. package/dist/settings-api.js.map +1 -1
  215. package/dist/settings-baseline.d.ts +20 -0
  216. package/dist/settings-baseline.js +104 -0
  217. package/dist/settings-baseline.js.map +1 -0
  218. package/dist/settings-change.d.ts +21 -0
  219. package/dist/settings-change.js +161 -0
  220. package/dist/settings-change.js.map +1 -0
  221. package/dist/settings-confirmation.d.ts +105 -0
  222. package/dist/settings-confirmation.js +232 -0
  223. package/dist/settings-confirmation.js.map +1 -0
  224. package/dist/settings-control.d.ts +41 -0
  225. package/dist/settings-control.js +294 -0
  226. package/dist/settings-control.js.map +1 -0
  227. package/dist/settings-effect.d.ts +24 -0
  228. package/dist/settings-effect.js +169 -0
  229. package/dist/settings-effect.js.map +1 -0
  230. package/dist/settings-http-confirmation.d.ts +29 -0
  231. package/dist/settings-http-confirmation.js +123 -0
  232. package/dist/settings-http-confirmation.js.map +1 -0
  233. package/dist/settings-instance-patch.d.ts +4 -0
  234. package/dist/settings-instance-patch.js +26 -0
  235. package/dist/settings-instance-patch.js.map +1 -0
  236. package/dist/settings-request-capability.d.ts +16 -0
  237. package/dist/settings-request-capability.js +32 -0
  238. package/dist/settings-request-capability.js.map +1 -0
  239. package/dist/settings-transaction.d.ts +65 -0
  240. package/dist/settings-transaction.js +223 -0
  241. package/dist/settings-transaction.js.map +1 -0
  242. package/dist/setup-auth.d.ts +10 -18
  243. package/dist/setup-auth.js +14 -38
  244. package/dist/setup-auth.js.map +1 -1
  245. package/dist/setup-form.d.ts +1 -1
  246. package/dist/setup-form.js +75 -18
  247. package/dist/setup-form.js.map +1 -1
  248. package/dist/setup-guide.d.ts +13 -0
  249. package/dist/setup-guide.js +25 -0
  250. package/dist/setup-guide.js.map +1 -0
  251. package/dist/setup-host.d.ts +16 -0
  252. package/dist/setup-host.js +199 -35
  253. package/dist/setup-host.js.map +1 -1
  254. package/dist/setup-wizard.js +5 -1
  255. package/dist/setup-wizard.js.map +1 -1
  256. package/dist/slash-authz.d.ts +17 -3
  257. package/dist/slash-authz.js +5 -0
  258. package/dist/slash-authz.js.map +1 -1
  259. package/dist/spawn-gate.js +3 -3
  260. package/dist/spawn-gate.js.map +1 -1
  261. package/dist/sqlite-open-errors.d.ts +12 -0
  262. package/dist/sqlite-open-errors.js +13 -0
  263. package/dist/sqlite-open-errors.js.map +1 -0
  264. package/dist/statusline-watcher.d.ts +5 -0
  265. package/dist/statusline-watcher.js +2 -0
  266. package/dist/statusline-watcher.js.map +1 -1
  267. package/dist/steer-capability.d.ts +6 -0
  268. package/dist/steer-capability.js +8 -0
  269. package/dist/steer-capability.js.map +1 -1
  270. package/dist/sync-work-attribution.d.ts +14 -0
  271. package/dist/sync-work-attribution.js +43 -8
  272. package/dist/sync-work-attribution.js.map +1 -1
  273. package/dist/tips.js +10 -5
  274. package/dist/tips.js.map +1 -1
  275. package/dist/tmux-control.d.ts +57 -5
  276. package/dist/tmux-control.js +379 -61
  277. package/dist/tmux-control.js.map +1 -1
  278. package/dist/tmux-manager.d.ts +20 -6
  279. package/dist/tmux-manager.js +90 -47
  280. package/dist/tmux-manager.js.map +1 -1
  281. package/dist/tmux-read.d.ts +59 -0
  282. package/dist/tmux-read.js +213 -0
  283. package/dist/tmux-read.js.map +1 -0
  284. package/dist/topic-commands.d.ts +21 -10
  285. package/dist/topic-commands.js +205 -63
  286. package/dist/topic-commands.js.map +1 -1
  287. package/dist/transcript-delta-reader.js +2 -1
  288. package/dist/transcript-delta-reader.js.map +1 -1
  289. package/dist/tunnel/cloudflared-install.d.ts +2 -0
  290. package/dist/tunnel/cloudflared-install.js +1 -1
  291. package/dist/tunnel/cloudflared-install.js.map +1 -1
  292. package/dist/tunnel/purpose-lane.d.ts +14 -0
  293. package/dist/tunnel/purpose-lane.js +43 -0
  294. package/dist/tunnel/purpose-lane.js.map +1 -0
  295. package/dist/turn-reply-guard.d.ts +2 -0
  296. package/dist/turn-reply-guard.js +10 -1
  297. package/dist/turn-reply-guard.js.map +1 -1
  298. package/dist/types.d.ts +33 -0
  299. package/dist/ui/app.html +18 -0
  300. package/dist/ui/chat-commands.js +43 -0
  301. package/dist/ui/chat-render.js +478 -0
  302. package/dist/ui/chat-store.js +318 -0
  303. package/dist/ui/chat-strings.js +89 -0
  304. package/dist/ui/chat-thread.js +246 -0
  305. package/dist/ui/chat-tour.js +116 -0
  306. package/dist/ui/fleet-cache.js +168 -0
  307. package/dist/ui/fleet-org.js +142 -0
  308. package/dist/ui/panel-chat.js +504 -0
  309. package/dist/ui/panel-fleet.js +427 -0
  310. package/dist/ui/panel-needs.js +202 -0
  311. package/dist/ui/panel-settings.js +754 -0
  312. package/dist/ui/preview-panel.js +202 -0
  313. package/dist/ui/preview.js +270 -0
  314. package/dist/ui/settings-apply.js +239 -0
  315. package/dist/ui/settings-confirm.js +186 -0
  316. package/dist/ui/settings-dialogs.js +546 -0
  317. package/dist/ui/settings-model.js +277 -0
  318. package/dist/ui/settings-strings.js +654 -0
  319. package/dist/ui/settings-wizard.js +140 -0
  320. package/dist/ui/shared/agend-auth.js +93 -0
  321. package/dist/ui/shared/app-ctx.js +80 -0
  322. package/dist/ui/shared/app-html.js +9 -0
  323. package/dist/ui/shared/app-i18n.js +95 -0
  324. package/dist/ui/shared/app-nav.js +73 -0
  325. package/dist/ui/shared/app-needs.js +114 -0
  326. package/dist/ui/shared/app-route.js +73 -0
  327. package/dist/ui/shared/app-session.js +66 -0
  328. package/dist/ui/shared/app-shell.js +346 -0
  329. package/dist/ui/shared/app-store.js +51 -0
  330. package/dist/ui/shared/app-stream.js +201 -0
  331. package/dist/ui/shared/app.css +820 -0
  332. package/dist/ui/shared/app.js +88 -0
  333. package/dist/ui/shared/fonts/OFL.txt +92 -0
  334. package/dist/ui/shared/fonts/README.md +21 -0
  335. package/dist/ui/shared/fonts/inter.woff2 +0 -0
  336. package/dist/ui/shared/htm.module.js +1 -0
  337. package/dist/ui/shared/panel-view.js +655 -0
  338. package/dist/ui/shared/preact-hooks.module.js +2 -0
  339. package/dist/ui/shared/preact.module.js +2 -0
  340. package/dist/ui/shared/signin.js +142 -0
  341. package/dist/ui/shared/theme.js +29 -0
  342. package/dist/ui/shared/tokens.css +153 -0
  343. package/dist/ui/shared/ui-confirm.js +43 -0
  344. package/dist/ui/shared/ui-dialog.js +45 -0
  345. package/dist/ui/shared/ui-icons.js +63 -0
  346. package/dist/ui/shared/ui-menu.js +39 -0
  347. package/dist/ui/shared/ui-states.js +20 -0
  348. package/dist/ui/shared/ui-toast.js +18 -0
  349. package/dist/ui/shared/vendor/htm.LICENSE +202 -0
  350. package/dist/ui/shared/vendor/preact.LICENSE +21 -0
  351. package/dist/ui/shared/vendor/vendor.json +39 -0
  352. package/dist/ui/shared/view-strings.js +309 -0
  353. package/dist/ui/signin.html +52 -0
  354. package/dist/update-check.d.ts +6 -2
  355. package/dist/update-check.js +12 -3
  356. package/dist/update-check.js.map +1 -1
  357. package/dist/update-dispatch.d.ts +28 -0
  358. package/dist/update-dispatch.js +73 -0
  359. package/dist/update-dispatch.js.map +1 -0
  360. package/dist/update-install.d.ts +129 -0
  361. package/dist/update-install.js +262 -0
  362. package/dist/update-install.js.map +1 -0
  363. package/dist/upgrade-notices.d.ts +17 -0
  364. package/dist/upgrade-notices.js +93 -0
  365. package/dist/upgrade-notices.js.map +1 -0
  366. package/dist/usage/statusline-usage.d.ts +2 -0
  367. package/dist/usage/statusline-usage.js +14 -10
  368. package/dist/usage/statusline-usage.js.map +1 -1
  369. package/dist/view-api.d.ts +6 -1
  370. package/dist/view-api.js +62 -51
  371. package/dist/view-api.js.map +1 -1
  372. package/dist/web-api.d.ts +85 -14
  373. package/dist/web-api.js +557 -77
  374. package/dist/web-api.js.map +1 -1
  375. package/dist/web-auth.d.ts +71 -27
  376. package/dist/web-auth.js +169 -69
  377. package/dist/web-auth.js.map +1 -1
  378. package/dist/web-body.d.ts +3 -0
  379. package/dist/web-body.js +55 -0
  380. package/dist/web-body.js.map +1 -0
  381. package/dist/web-channel-echo.d.ts +9 -0
  382. package/dist/web-channel-echo.js +55 -0
  383. package/dist/web-channel-echo.js.map +1 -0
  384. package/dist/web-chat-history.d.ts +125 -0
  385. package/dist/web-chat-history.js +184 -0
  386. package/dist/web-chat-history.js.map +1 -0
  387. package/dist/web-commands.d.ts +77 -0
  388. package/dist/web-commands.js +81 -0
  389. package/dist/web-commands.js.map +1 -0
  390. package/dist/web-continuation.d.ts +7 -0
  391. package/dist/web-continuation.js +22 -0
  392. package/dist/web-continuation.js.map +1 -0
  393. package/dist/web-host-guard.d.ts +34 -0
  394. package/dist/web-host-guard.js +57 -1
  395. package/dist/web-host-guard.js.map +1 -1
  396. package/dist/web-login.d.ts +72 -0
  397. package/dist/web-login.js +132 -0
  398. package/dist/web-login.js.map +1 -0
  399. package/dist/web-org.d.ts +55 -0
  400. package/dist/web-org.js +67 -0
  401. package/dist/web-org.js.map +1 -0
  402. package/dist/web-preview.d.ts +77 -0
  403. package/dist/web-preview.js +240 -0
  404. package/dist/web-preview.js.map +1 -0
  405. package/dist/web-request-context.d.ts +10 -0
  406. package/dist/web-request-context.js +13 -0
  407. package/dist/web-request-context.js.map +1 -0
  408. package/dist/web-session.d.ts +167 -0
  409. package/dist/web-session.js +389 -0
  410. package/dist/web-session.js.map +1 -0
  411. package/dist/web-shell-routes.d.ts +59 -0
  412. package/dist/web-shell-routes.js +96 -0
  413. package/dist/web-shell-routes.js.map +1 -0
  414. package/dist/web-upload.d.ts +183 -0
  415. package/dist/web-upload.js +468 -0
  416. package/dist/web-upload.js.map +1 -0
  417. package/dist/website-tips-renderer.d.ts +2 -2
  418. package/dist/website-tips-renderer.js +3 -3
  419. package/dist/website-tips-renderer.js.map +1 -1
  420. package/launcher/agend +110 -0
  421. package/launcher/agend-agent +110 -0
  422. package/launcher/agend-agent.cjs +4 -0
  423. package/launcher/agend.cjs +4 -0
  424. package/launcher/install-admission.cjs +105 -0
  425. package/launcher/launch.cjs +64 -0
  426. package/launcher/postinstall.cjs +114 -0
  427. package/launcher/run-in-process.cjs +13 -0
  428. package/launcher/runtime-platform.cjs +86 -0
  429. package/launcher/runtime-select.cjs +217 -0
  430. package/package.json +18 -7
  431. package/scripts/preinstall-guard.cjs +55 -0
  432. package/templates/launchd.plist.ejs +2 -2
  433. package/templates/systemd.service.ejs +1 -1
  434. package/dist/ui/dashboard.html +0 -774
  435. package/dist/ui/settings.html +0 -2165
  436. package/dist/ui/view.html +0 -1139
@@ -0,0 +1,147 @@
1
+ /**
2
+ * #1468: the prompt-cache expiry analysis — pure, over a ledger (cache-ledger.ts). For a window [from, to]:
3
+ *
4
+ * - Each gap carries the TTL of the cache it sat on, as that session last wrote it: Claude Code's own write split
5
+ * (1 hour, or 5 minutes), Codex's 30 minutes (GPT-5.6 and later). Sessions of one instance can differ.
6
+ * - An expired request: one that came after a gap longer than its TTL and had to write at least half of the context
7
+ * the previous request left cached (the cache can outlive its TTL; then nothing was lost). What it rewrote, up to
8
+ * that context, is the expiry's tokens; its cost is those tokens at the write rate minus what reading them would
9
+ * have cost, at the returning request's own price tier.
10
+ * - Keep-warm, simulated: a ping at every I = TTL − TTL/10 after a request (t + k·I, k ≥ 1, up to and including
11
+ * the moment the gap ends — floor(gap / I) of them), each reading the cached context at that context's own tier.
12
+ * Only pings whose instant falls inside the window are counted. A gap that ended in an expired request inside the
13
+ * window saves its expiry cost; any other gap only pays for its pings. After a session's last request the pings
14
+ * are pure loss, up to the moment the next session of the instance starts, or the window ends.
15
+ * - Recommendation: on when the simulated pings cost less than the expiries they prevent (by a margin), else off.
16
+ *
17
+ * Money is list price (cache-prices.ts). If any model the window touches — requests, pinged contexts, idle tails —
18
+ * is missing from the table, the whole instance is weighed in input-price units instead (write 1.25x, 1-hour write
19
+ * 2x, read 0.1x, output 5x) and shows no dollars.
20
+ */
21
+ import { ratesFor } from "./cache-prices.js";
22
+ import { GAP_BUCKETS } from "./cache-ledger.js";
23
+ export const UNITS = { input: 1, read: 0.1, write5m: 1.25, write1h: 2, write: 1.25, output: 5 };
24
+ const M = 1_000_000;
25
+ export const pingIntervalMs = (ttlSec) => Math.round(ttlSec * 900);
26
+ const writeRate = (r, ttlSec) => (ttlSec >= 3600 ? r.write1h : ttlSec <= 300 ? r.write5m : r.write);
27
+ /** Pings at t + k·I (k ≥ 1) no later than `end`, counted only where they fall inside [from, to]. */
28
+ export function pingsBetween(t, end, intervalMs, from, to) {
29
+ if (!(intervalMs > 0))
30
+ return 0;
31
+ const kMin = Math.max(1, Math.ceil((from - t) / intervalMs));
32
+ const kMax = Math.floor((Math.min(end, to) - t) / intervalMs);
33
+ return Math.max(0, kMax - kMin + 1);
34
+ }
35
+ /** The keep-warm simulation over a window's long gaps and its sessions' ends. */
36
+ export function simulate(gaps, tails, o) {
37
+ const res = { pastTtl: 0, expired: 0, rewriteTokens: 0, expiryCost: 0, pings: 0, pingCost: 0, tailPings: 0, tailCost: 0, net: 0, estimated: false };
38
+ let saved = 0;
39
+ for (const [tEnd, gap, ctx, ctxModel, ttl, model, prompt, measured, estimated] of gaps) {
40
+ if (tEnd < o.from)
41
+ continue;
42
+ const start = tEnd - Math.round(gap * 1000);
43
+ const pings = pingsBetween(start, tEnd, pingIntervalMs(ttl), o.from, o.to);
44
+ if (pings) {
45
+ res.pings += pings;
46
+ res.pingCost += pings * ctx * o.rates(ctxModel, ctx).read / M;
47
+ }
48
+ if (tEnd > o.to || !(gap > ttl))
49
+ continue;
50
+ res.pastTtl++;
51
+ const useMeasured = o.measured && measured !== null;
52
+ if (!useMeasured)
53
+ res.estimated = true;
54
+ const rewrite = useMeasured ? measured : estimated;
55
+ const lost = Math.min(rewrite, ctx);
56
+ if (ctx > 0 && lost >= ctx / 2) {
57
+ const r = o.rates(model, prompt);
58
+ const cost = lost * (writeRate(r, ttl) - r.read) / M;
59
+ res.expired++;
60
+ res.rewriteTokens += lost;
61
+ res.expiryCost += cost;
62
+ saved += cost;
63
+ }
64
+ }
65
+ for (const tail of tails) {
66
+ const n = pingsBetween(tail.t, tail.until, pingIntervalMs(tail.ttl), o.from, o.to);
67
+ if (!n)
68
+ continue;
69
+ res.tailPings += n;
70
+ res.tailCost += n * tail.ctx * o.rates(tail.model, tail.ctx).read / M;
71
+ }
72
+ res.net = saved - res.pingCost - res.tailCost;
73
+ return res;
74
+ }
75
+ /**
76
+ * Each session's end: its last request, until the next session of the instance starts (the earliest other session
77
+ * that starts at or after it — one that starts at the same instant leaves no idle time), or `to`.
78
+ */
79
+ export function sessionTails(ledger, to) {
80
+ const sessions = Object.values(ledger.files).filter((f) => f.last && f.first !== undefined).map((f) => ({ first: f.first, last: f.last }));
81
+ return sessions.map((s) => {
82
+ let until = to;
83
+ for (const o of sessions)
84
+ if (o !== s && o.first >= s.last.t && o.first < until)
85
+ until = o.first;
86
+ return { t: s.last.t, ctx: s.last.ctx, model: s.last.model, ttl: s.last.ttl, until };
87
+ });
88
+ }
89
+ /** Codex GPT-5.6 and later bill cache writes and keep a prefix 30 minutes. */
90
+ export const isOpenAiTtlModel = (model) => /^gpt-(5\.(6|[7-9])|[6-9])/.test(model);
91
+ /** Requests in a window below this are too few to say anything. */
92
+ export const MIN_REQUESTS = 3;
93
+ export function analyzeLedger(ledger, o) {
94
+ const listed = o.rates ?? ratesFor;
95
+ const inWindow = (h) => h + 3_600_000 > o.from && h <= o.to;
96
+ const tails = sessionTails(ledger, o.to);
97
+ const estimatedTotals = o.backend === "codex" && !ledger.writesSeen;
98
+ // One unit for the whole instance: dollars when every model that contributes to this window is priced — the
99
+ // window's requests, and whatever the simulation itself prices (a pinged context, an expired request, an idle tail).
100
+ // A probe run records exactly the models the simulation asks a rate for.
101
+ const requestModels = new Set();
102
+ for (const [hk, hour] of Object.entries(ledger.hours)) {
103
+ if (!inWindow(Number(hk)))
104
+ continue;
105
+ for (const mk of Object.keys(hour.m))
106
+ requestModels.add(mk.slice(0, mk.lastIndexOf("|")));
107
+ }
108
+ const touched = new Set(requestModels);
109
+ simulate(ledger.gaps, tails, { rates: (model) => { touched.add(model); return UNITS; }, from: o.from, to: o.to, measured: !estimatedTotals });
110
+ const priced = [...touched].every((m) => listed(m, 0) !== null);
111
+ const rates = (model, prompt) => (priced ? listed(model, prompt) : null) ?? UNITS;
112
+ const gapBuckets = new Array(GAP_BUCKETS).fill(0);
113
+ let requests = 0, totalCost = 0;
114
+ for (const [hk, hour] of Object.entries(ledger.hours)) {
115
+ if (!inWindow(Number(hk)))
116
+ continue;
117
+ hour.g.forEach((n, i) => { gapBuckets[i] += n; });
118
+ for (const [mk, [n, uncached, read, write5m, write1h, write, output]] of Object.entries(hour.m)) {
119
+ const bar = mk.lastIndexOf("|");
120
+ const model = mk.slice(0, bar), long = mk.slice(bar + 1) === "1";
121
+ requests += n;
122
+ const r = rates(model, long ? Number.MAX_SAFE_INTEGER : 0);
123
+ // Codex on GPT-5.6+ with no recorded writes: its uncached input is what got written (the estimate).
124
+ const uncachedRate = estimatedTotals && isOpenAiTtlModel(model) ? r.write : r.input;
125
+ totalCost += (uncached * uncachedRate + read * r.read + write5m * r.write5m + write1h * r.write1h + write * r.write + output * r.output) / M;
126
+ }
127
+ }
128
+ const sim = simulate(ledger.gaps, tails, { rates, from: o.from, to: o.to, measured: !estimatedTotals });
129
+ const latest = tails.reduce((a, t) => (!a || t.t > a.t ? t : a), null);
130
+ const ttlSec = latest ? latest.ttl : o.backend === "codex" ? 1800 : 3600;
131
+ const assumedTtl = o.backend === "codex" && [...requestModels].some((m) => !isOpenAiTtlModel(m));
132
+ let recommendation;
133
+ if (requests < MIN_REQUESTS)
134
+ recommendation = { on: false, reason: "quiet" };
135
+ else if (!sim.expired)
136
+ recommendation = { on: false, reason: "never_expired" };
137
+ else if (sim.net > 0 && sim.net >= sim.expiryCost * 0.1)
138
+ recommendation = { on: true, reason: "saves" };
139
+ else
140
+ recommendation = { on: false, reason: "costs_more", pingsPerExpiry: Math.round((sim.pings + sim.tailPings) / sim.expired) };
141
+ return {
142
+ // An estimate when anything shown used one: the totals (Codex with no recorded write), a gap's rewrite, a TTL.
143
+ requests, ttlSec, estimate: (estimatedTotals && requests > 0) || sim.estimated || assumedTtl, priced, models: [...requestModels].sort(), gapBuckets, sim,
144
+ totalCost, share: totalCost > 0 ? sim.expiryCost / totalCost : null, recommendation,
145
+ };
146
+ }
147
+ //# sourceMappingURL=cache-analysis.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"cache-analysis.js","sourceRoot":"","sources":["../src/cache-analysis.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,108 @@
1
+ /**
2
+ * #1468: what the prompt-cache analysis keeps per instance — never the transcripts themselves. Each model request a
3
+ * CLI made (a Claude assistant message, a Codex `token_count`) becomes a "turn"; the ledger folds turns into:
4
+ * - hourly totals per model and price tier (requests and tokens: uncached input, cache reads, cache writes, output)
5
+ * with the hour's histogram of gaps between consecutive requests of the same session;
6
+ * - one event per long gap (≥ GAP_EVENT_SEC): when it ended, how long it was, the context it left cached, what the
7
+ * request after it wrote to the cache — all the keep-warm simulation needs;
8
+ * - per transcript file: where reading stopped (a line start), and the session's first and last request.
9
+ * That keeps a month of a busy fleet in kilobytes per instance, and a file is read once, incrementally.
10
+ *
11
+ * Usage fields (real shapes, checked 2026-10-09):
12
+ * - Claude Code: `message.usage` { input_tokens, cache_read_input_tokens, cache_creation_input_tokens,
13
+ * cache_creation: { ephemeral_5m_input_tokens, ephemeral_1h_input_tokens }, output_tokens }. A message spans several
14
+ * lines (one per content block) carrying the same id and usage: counted once.
15
+ * - Codex (0.160): `event_msg` `token_count` with `info.last_token_usage` { input_tokens (cached included),
16
+ * cached_input_tokens, cache_write_input_tokens, output_tokens }. The write field exists but was 0 in every one of
17
+ * 38,551 real events on GPT-5.6+ models — so a write is estimated as the request's uncached input unless a real
18
+ * write count shows up. The model comes from the preceding `turn_context`.
19
+ */
20
+ import { type ScanLine } from "./cache-scan.js";
21
+ export type TranscriptKind = "claude" | "codex";
22
+ /** One model request, as the transcript records it. */
23
+ export interface Turn {
24
+ t: number;
25
+ model: string;
26
+ /** Everything the request sent: uncached input + cache reads + cache writes. */
27
+ prompt: number;
28
+ uncached: number;
29
+ read: number;
30
+ write5m: number;
31
+ write1h: number;
32
+ /** An OpenAI cache write as recorded (null: not recorded, 0 included when the field is absent). */
33
+ write: number | null;
34
+ output: number;
35
+ }
36
+ /** Gap histogram edges, seconds: ≤5 min, ≤30 min, ≤1 h, ≤2 h, ≤6 h, ≤24 h, longer. */
37
+ export declare const GAP_EDGES: readonly [300, 1800, 3600, 7200, 21600, 86400];
38
+ export declare const GAP_BUCKETS: number;
39
+ /** Gaps at least this long are kept one by one (the shortest keep-warm interval is a 5-minute TTL's 270 s). */
40
+ export declare const GAP_EVENT_SEC = 240;
41
+ export declare const KEEP_DAYS = 31;
42
+ /** [requests, uncached, read, write5m, write1h, write, output] */
43
+ export type HourTotals = [number, number, number, number, number, number, number];
44
+ export interface HourAgg {
45
+ m: Record<string, HourTotals>;
46
+ g: number[];
47
+ }
48
+ /**
49
+ * One long gap: [tEnd, gapSec, contextCached, contextModel, ttlSec, model, promptAfter, measuredWrite, estimatedWrite].
50
+ * - `contextCached`/`contextModel`: what the previous request left cached, and its model — what a ping would read.
51
+ * - `ttlSec`: the TTL of that cache as the session last wrote it (Claude's own write split; Codex's 30 minutes).
52
+ * - `measuredWrite`: what the request after the gap recorded writing (Claude always; Codex its write field, 0
53
+ * included, or null when the field is absent). `estimatedWrite`: Codex's uncached input — used only while the
54
+ * instance has never recorded a real write (the field exists but stays 0 on the CLIs seen so far).
55
+ */
56
+ export type GapEvent = [number, number, number, string, number, string, number, number | null, number];
57
+ export interface SessionPoint {
58
+ t: number;
59
+ ctx: number;
60
+ model: string;
61
+ ttl: number;
62
+ }
63
+ export interface FileCursor {
64
+ kind: TranscriptKind;
65
+ ino: number;
66
+ offset: number;
67
+ first?: number;
68
+ last?: SessionPoint;
69
+ /** Claude: the TTL the session's latest cache write used (1 h or 5 min). */
70
+ ttl?: number;
71
+ /** The file size at which only an unfinished line was left: not read again until the file grows. */
72
+ stalled?: number;
73
+ /** Codex: the model of the latest turn_context; the last cumulative total (token_count repeats itself). */
74
+ model?: string;
75
+ total?: number;
76
+ /** Claude: ids of the last messages counted (one message spans several lines). */
77
+ ids?: string[];
78
+ }
79
+ export interface Ledger {
80
+ v: 2;
81
+ files: Record<string, FileCursor>;
82
+ hours: Record<string, HourAgg>;
83
+ gaps: GapEvent[];
84
+ /** A real OpenAI cache-write count was seen (Codex): writes are then measured, not estimated. */
85
+ writesSeen?: boolean;
86
+ }
87
+ export declare function emptyLedger(): Ledger;
88
+ /** A ledger read back from disk; anything that is not one is a fresh ledger. */
89
+ export declare function reviveLedger(raw: unknown): Ledger;
90
+ export declare const hourOf: (t: number) => number;
91
+ export declare const gapBucket: (sec: number) => number;
92
+ /** The key hourly totals are kept under: the model, and whether the request paid its long-prompt row. */
93
+ export declare const modelKey: (model: string, prompt: number) => string;
94
+ /** Codex keeps a prefix 30 minutes (GPT-5.6 and later; assumed for any other Codex model, which is then an estimate). */
95
+ export declare const CODEX_TTL_SEC = 1800;
96
+ /** The TTL a Claude request's own cache writes used: its write split decides; no write leaves the session's as it was. */
97
+ export declare function claudeTtlAfter(turn: Turn, current: number | undefined): number;
98
+ /**
99
+ * Fold one turn into the ledger, in file order. Turns older than `cutoff` only move the session's last point (the
100
+ * next gap needs it); everything else is counted. Pure apart from mutating `ledger`.
101
+ */
102
+ export declare function addTurn(ledger: Ledger, file: FileCursor, turn: Turn, cutoff: number): void;
103
+ /** Drop what is older than `cutoff` (hours and gap events). */
104
+ export declare function pruneLedger(ledger: Ledger, cutoff: number): void;
105
+ /** The turn a Claude Code transcript line records, or null; a message already counted (`file.ids`) is null too. */
106
+ export declare function claudeLine(line: ScanLine, file: FileCursor): Turn | null;
107
+ /** The turn a Codex rollout line records, or null. A `turn_context` line updates the file's model. */
108
+ export declare function codexLine(line: ScanLine, file: FileCursor): Turn | null;
@@ -0,0 +1,230 @@
1
+ /**
2
+ * #1468: what the prompt-cache analysis keeps per instance — never the transcripts themselves. Each model request a
3
+ * CLI made (a Claude assistant message, a Codex `token_count`) becomes a "turn"; the ledger folds turns into:
4
+ * - hourly totals per model and price tier (requests and tokens: uncached input, cache reads, cache writes, output)
5
+ * with the hour's histogram of gaps between consecutive requests of the same session;
6
+ * - one event per long gap (≥ GAP_EVENT_SEC): when it ended, how long it was, the context it left cached, what the
7
+ * request after it wrote to the cache — all the keep-warm simulation needs;
8
+ * - per transcript file: where reading stopped (a line start), and the session's first and last request.
9
+ * That keeps a month of a busy fleet in kilobytes per instance, and a file is read once, incrementally.
10
+ *
11
+ * Usage fields (real shapes, checked 2026-10-09):
12
+ * - Claude Code: `message.usage` { input_tokens, cache_read_input_tokens, cache_creation_input_tokens,
13
+ * cache_creation: { ephemeral_5m_input_tokens, ephemeral_1h_input_tokens }, output_tokens }. A message spans several
14
+ * lines (one per content block) carrying the same id and usage: counted once.
15
+ * - Codex (0.160): `event_msg` `token_count` with `info.last_token_usage` { input_tokens (cached included),
16
+ * cached_input_tokens, cache_write_input_tokens, output_tokens }. The write field exists but was 0 in every one of
17
+ * 38,551 real events on GPT-5.6+ models — so a write is estimated as the request's uncached input unless a real
18
+ * write count shows up. The model comes from the preceding `turn_context`.
19
+ */
20
+ import { objectAt } from "./cache-scan.js";
21
+ import { isLongPrompt } from "./cache-prices.js";
22
+ /** Gap histogram edges, seconds: ≤5 min, ≤30 min, ≤1 h, ≤2 h, ≤6 h, ≤24 h, longer. */
23
+ export const GAP_EDGES = [300, 1800, 3600, 7200, 21600, 86400];
24
+ export const GAP_BUCKETS = GAP_EDGES.length + 1;
25
+ /** Gaps at least this long are kept one by one (the shortest keep-warm interval is a 5-minute TTL's 270 s). */
26
+ export const GAP_EVENT_SEC = 240;
27
+ export const KEEP_DAYS = 31;
28
+ /** A dictionary keyed by names from outside (paths, model ids): every key an own property (#1467 lesson). */
29
+ const dict = () => Object.create(null);
30
+ export function emptyLedger() { return { v: 2, files: dict(), hours: dict(), gaps: [] }; }
31
+ /** A ledger read back from disk; anything that is not one is a fresh ledger. */
32
+ export function reviveLedger(raw) {
33
+ const l = emptyLedger();
34
+ if (!raw || typeof raw !== "object" || raw.v !== 2)
35
+ return l;
36
+ const r = raw;
37
+ for (const [k, v] of Object.entries(r.files ?? {}))
38
+ if (v && typeof v.offset === "number")
39
+ l.files[k] = v;
40
+ for (const [k, v] of Object.entries(r.hours ?? {})) {
41
+ if (!v || !Array.isArray(v.g))
42
+ continue;
43
+ const m = dict();
44
+ for (const [mk, tot] of Object.entries(v.m ?? {}))
45
+ if (Array.isArray(tot) && tot.length === 7)
46
+ m[mk] = tot;
47
+ l.hours[k] = { m, g: v.g };
48
+ }
49
+ if (Array.isArray(r.gaps))
50
+ l.gaps = r.gaps.filter((g) => Array.isArray(g) && g.length === 9);
51
+ if (r.writesSeen)
52
+ l.writesSeen = true;
53
+ return l;
54
+ }
55
+ const HOUR = 3_600_000;
56
+ export const hourOf = (t) => Math.floor(t / HOUR) * HOUR;
57
+ export const gapBucket = (sec) => { let i = 0; while (i < GAP_EDGES.length && sec > GAP_EDGES[i])
58
+ i++; return i; };
59
+ /** The key hourly totals are kept under: the model, and whether the request paid its long-prompt row. */
60
+ export const modelKey = (model, prompt) => `${model}|${isLongPrompt(model, prompt) ? 1 : 0}`;
61
+ /** Codex keeps a prefix 30 minutes (GPT-5.6 and later; assumed for any other Codex model, which is then an estimate). */
62
+ export const CODEX_TTL_SEC = 1800;
63
+ const CLAUDE_DEFAULT_TTL_SEC = 3600;
64
+ /** The TTL a Claude request's own cache writes used: its write split decides; no write leaves the session's as it was. */
65
+ export function claudeTtlAfter(turn, current) {
66
+ if (turn.write1h > 0 || turn.write5m > 0)
67
+ return turn.write5m > turn.write1h ? 300 : 3600;
68
+ return current ?? CLAUDE_DEFAULT_TTL_SEC;
69
+ }
70
+ /**
71
+ * Fold one turn into the ledger, in file order. Turns older than `cutoff` only move the session's last point (the
72
+ * next gap needs it); everything else is counted. Pure apart from mutating `ledger`.
73
+ */
74
+ export function addTurn(ledger, file, turn, cutoff) {
75
+ const prev = file.last;
76
+ const ttlBefore = file.kind === "claude" ? (file.ttl ?? CLAUDE_DEFAULT_TTL_SEC) : CODEX_TTL_SEC;
77
+ if (file.kind === "claude")
78
+ file.ttl = claudeTtlAfter(turn, file.ttl);
79
+ file.first ??= turn.t;
80
+ file.last = { t: turn.t, ctx: turn.prompt + turn.output, model: turn.model, ttl: file.kind === "claude" ? file.ttl : CODEX_TTL_SEC };
81
+ if (turn.write !== null && turn.write > 0)
82
+ ledger.writesSeen = true;
83
+ if (turn.t < cutoff)
84
+ return;
85
+ const hk = String(hourOf(turn.t));
86
+ const hour = ledger.hours[hk] ??= { m: dict(), g: new Array(GAP_BUCKETS).fill(0) };
87
+ const mk = modelKey(turn.model, turn.prompt);
88
+ const tot = hour.m[mk] ??= [0, 0, 0, 0, 0, 0, 0];
89
+ tot[0] += 1;
90
+ tot[1] += turn.uncached;
91
+ tot[2] += turn.read;
92
+ tot[3] += turn.write5m;
93
+ tot[4] += turn.write1h;
94
+ tot[5] += turn.write ?? 0;
95
+ tot[6] += turn.output;
96
+ if (!prev)
97
+ return;
98
+ const gap = (turn.t - prev.t) / 1000;
99
+ if (!(gap >= 0))
100
+ return;
101
+ hour.g[gapBucket(gap)] += 1;
102
+ if (gap < GAP_EVENT_SEC)
103
+ return;
104
+ const measured = file.kind === "claude" ? turn.write5m + turn.write1h : turn.write;
105
+ const estimated = file.kind === "claude" ? turn.write5m + turn.write1h : turn.uncached + (turn.write ?? 0);
106
+ ledger.gaps.push([turn.t, gap, prev.ctx, prev.model, ttlBefore, turn.model, turn.prompt, measured, estimated]);
107
+ }
108
+ /** Drop what is older than `cutoff` (hours and gap events). */
109
+ export function pruneLedger(ledger, cutoff) {
110
+ for (const k of Object.keys(ledger.hours))
111
+ if (Number(k) + HOUR <= cutoff)
112
+ delete ledger.hours[k];
113
+ if (ledger.gaps.length && ledger.gaps[0][0] < cutoff)
114
+ ledger.gaps = ledger.gaps.filter((g) => g[0] >= cutoff);
115
+ }
116
+ // ── Reading turns out of transcript lines ──
117
+ const num = (v) => (typeof v === "number" && Number.isFinite(v) && v > 0 ? v : 0);
118
+ const CLAUDE_ID = /"id":"(msg_[A-Za-z0-9_-]{1,120})"/;
119
+ const CLAUDE_ID_G = /"id":"(msg_[A-Za-z0-9_-]{1,120})"/g;
120
+ const CLAUDE_MODEL = /"model":"([^"]{1,120})"/;
121
+ const CLAUDE_MODEL_G = /"model":"([^"]{1,120})"/g;
122
+ const TIMESTAMP = /"timestamp":"([^"]{10,40})"/g;
123
+ const lastMatch = (text, re) => { const all = [...text.matchAll(re)]; return all.length ? all[all.length - 1][1] : undefined; };
124
+ function lastUsage(text) {
125
+ const at = text.lastIndexOf("\"usage\":{");
126
+ const obj = at === -1 ? null : objectAt(text, at + "\"usage\":".length);
127
+ try {
128
+ return obj ? JSON.parse(obj) : undefined;
129
+ }
130
+ catch {
131
+ return undefined;
132
+ }
133
+ }
134
+ function claudeTurn(u, model, ts) {
135
+ if (!u || typeof model !== "string" || typeof ts !== "string")
136
+ return null;
137
+ const t = Date.parse(ts);
138
+ if (!Number.isFinite(t))
139
+ return null;
140
+ const input = num(u.input_tokens), read = num(u.cache_read_input_tokens), creation = num(u.cache_creation_input_tokens);
141
+ const split = u.cache_creation;
142
+ let write1h = num(split?.ephemeral_1h_input_tokens), write5m = num(split?.ephemeral_5m_input_tokens);
143
+ // No split recorded (older CLIs): the API's default, a 5-minute write.
144
+ if (!split && creation)
145
+ write5m = creation;
146
+ if (split && write1h + write5m !== creation)
147
+ write5m = Math.max(0, creation - write1h);
148
+ return { t, model, prompt: input + read + creation, uncached: input, read, write5m, write1h, write: null, output: num(u.output_tokens) };
149
+ }
150
+ /** The turn a Claude Code transcript line records, or null; a message already counted (`file.ids`) is null too. */
151
+ export function claudeLine(line, file) {
152
+ let id, turn = null;
153
+ if ("whole" in line) {
154
+ if (line.whole.indexOf("\"usage\"") === -1 || line.whole.indexOf("\"assistant\"") === -1)
155
+ return null;
156
+ let d;
157
+ try {
158
+ d = JSON.parse(line.whole.toString("utf8"));
159
+ }
160
+ catch {
161
+ return null;
162
+ }
163
+ if (d.type !== "assistant" || d.isSidechain === true || !d.message)
164
+ return null;
165
+ id = typeof d.message.id === "string" ? d.message.id : undefined;
166
+ if (id && file.ids?.includes(id))
167
+ return null;
168
+ turn = claudeTurn(d.message.usage, d.message.model, d.timestamp);
169
+ }
170
+ else {
171
+ // A long line, kept as its two ends. Claude writes the model and id near the start and the usage and timestamp
172
+ // near the end, but where `type` and `isSidechain` sit depends on the writer: both ends are searched alike.
173
+ const head = line.head.toString("utf8"), tail = line.tail.toString("utf8");
174
+ const either = (needle) => head.includes(needle) || tail.includes(needle);
175
+ if (!either("\"type\":\"assistant\"") || either("\"isSidechain\":true"))
176
+ return null;
177
+ id = CLAUDE_ID.exec(head)?.[1] ?? lastMatch(tail, CLAUDE_ID_G);
178
+ if (id && file.ids?.includes(id))
179
+ return null;
180
+ const usage = lastUsage(tail) ?? lastUsage(head);
181
+ const ts = lastMatch(tail, TIMESTAMP) ?? lastMatch(head, TIMESTAMP);
182
+ turn = claudeTurn(usage, CLAUDE_MODEL.exec(head)?.[1] ?? lastMatch(tail, CLAUDE_MODEL_G), ts);
183
+ }
184
+ if (turn && id)
185
+ file.ids = [...(file.ids ?? []).slice(-15), id];
186
+ return turn;
187
+ }
188
+ /** The turn a Codex rollout line records, or null. A `turn_context` line updates the file's model. */
189
+ export function codexLine(line, file) {
190
+ if (!("whole" in line))
191
+ return null; // token_count and turn_context lines are small
192
+ const w = line.whole;
193
+ const isCount = w.indexOf("\"token_count\"") !== -1;
194
+ if (!isCount && w.indexOf("\"turn_context\"") === -1)
195
+ return null;
196
+ let d;
197
+ try {
198
+ d = JSON.parse(w.toString("utf8"));
199
+ }
200
+ catch {
201
+ return null;
202
+ }
203
+ const p = d.payload;
204
+ if (!p)
205
+ return null;
206
+ if (d.type === "turn_context") {
207
+ if (typeof p.model === "string")
208
+ file.model = p.model;
209
+ return null;
210
+ }
211
+ if (d.type !== "event_msg" || p.type !== "token_count")
212
+ return null;
213
+ const info = p.info;
214
+ const u = info?.last_token_usage;
215
+ if (!u || typeof d.timestamp !== "string")
216
+ return null;
217
+ // The same usage is re-announced (a rate-limit update): the running total has not moved.
218
+ const total = num(info?.total_token_usage?.total_tokens);
219
+ if (total && file.total === total)
220
+ return null;
221
+ if (total)
222
+ file.total = total;
223
+ const t = Date.parse(d.timestamp);
224
+ if (!Number.isFinite(t))
225
+ return null;
226
+ const input = num(u.input_tokens), read = Math.min(num(u.cached_input_tokens), input);
227
+ const write = typeof u.cache_write_input_tokens === "number" ? Math.min(num(u.cache_write_input_tokens), input - read) : null;
228
+ return { t, model: file.model ?? "unknown", prompt: input, uncached: input - read - (write ?? 0), read, write5m: 0, write1h: 0, write, output: num(u.output_tokens) };
229
+ }
230
+ //# sourceMappingURL=cache-ledger.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"cache-ledger.js","sourceRoot":"","sources":["../src/cache-ledger.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,32 @@
1
+ /**
2
+ * #1468: list prices for the prompt-cache analysis — the one table, with the day it was checked against the vendors'
3
+ * own pricing pages. USD per million tokens, standard tier, global routing (no batch, fast, data-residency or
4
+ * regional uplift: AgEnD's CLIs run on subscriptions, so these are list-price equivalents, not a bill).
5
+ *
6
+ * Claude (platform.claude.com/docs/en/about-claude/pricing): a 5-minute cache write is 1.25x base input, a 1-hour
7
+ * write 2x; a cache hit is 0.1x, except 0.05x on Opus/Sonnet 5.5 and 0.025x on Fable/Mythos 5.1. Haiku 5.5 is priced
8
+ * by prompt length (over 100,000 tokens: the higher row), counting cache reads and writes.
9
+ * OpenAI (developers.openai.com/api/docs/pricing, …/guides/prompt-caching): on GPT-5.6 and later a cache write is
10
+ * 1.25x uncached input and the cache lives 30 minutes after its last write or reuse; prompts over 272K input tokens
11
+ * pay the long-context row.
12
+ */
13
+ export declare const PRICES_CHECKED = "2026-10-09";
14
+ export declare const PRICE_SOURCES: readonly ["https://platform.claude.com/docs/en/about-claude/pricing", "https://developers.openai.com/api/docs/pricing", "https://developers.openai.com/api/docs/guides/prompt-caching"];
15
+ /** USD per million tokens. `write` is the one cache-write rate an OpenAI model has; Claude has `write5m`/`write1h`. */
16
+ export interface Rates {
17
+ input: number;
18
+ read: number;
19
+ write5m: number;
20
+ write1h: number;
21
+ write: number;
22
+ output: number;
23
+ }
24
+ /**
25
+ * The table's key for a model id as a transcript records it: "claude-opus-4-5-20251101" → "claude-opus-4-5",
26
+ * "claude-opus-5-5[1m]" → "claude-opus-5-5". Exact keys only — "claude-opus-5" never prices "claude-opus-5-5".
27
+ */
28
+ export declare function priceKey(model: string | null | undefined): string | null;
29
+ /** The rates for one request of `model` with a prompt of `promptTokens`; null when the model is not in the table. */
30
+ export declare function ratesFor(model: string | null | undefined, promptTokens?: number): Rates | null;
31
+ /** Whether a prompt of this size pays the model's long-context (or over-100K) row. */
32
+ export declare function isLongPrompt(model: string | null | undefined, promptTokens: number): boolean;
@@ -0,0 +1,73 @@
1
+ /**
2
+ * #1468: list prices for the prompt-cache analysis — the one table, with the day it was checked against the vendors'
3
+ * own pricing pages. USD per million tokens, standard tier, global routing (no batch, fast, data-residency or
4
+ * regional uplift: AgEnD's CLIs run on subscriptions, so these are list-price equivalents, not a bill).
5
+ *
6
+ * Claude (platform.claude.com/docs/en/about-claude/pricing): a 5-minute cache write is 1.25x base input, a 1-hour
7
+ * write 2x; a cache hit is 0.1x, except 0.05x on Opus/Sonnet 5.5 and 0.025x on Fable/Mythos 5.1. Haiku 5.5 is priced
8
+ * by prompt length (over 100,000 tokens: the higher row), counting cache reads and writes.
9
+ * OpenAI (developers.openai.com/api/docs/pricing, …/guides/prompt-caching): on GPT-5.6 and later a cache write is
10
+ * 1.25x uncached input and the cache lives 30 minutes after its last write or reuse; prompts over 272K input tokens
11
+ * pay the long-context row.
12
+ */
13
+ export const PRICES_CHECKED = "2026-10-09";
14
+ export const PRICE_SOURCES = [
15
+ "https://platform.claude.com/docs/en/about-claude/pricing",
16
+ "https://developers.openai.com/api/docs/pricing",
17
+ "https://developers.openai.com/api/docs/guides/prompt-caching",
18
+ ];
19
+ const claude = (input, read, output) => ({ input, read, write5m: input * 1.25, write1h: input * 2, write: input * 1.25, output });
20
+ const openai = (input, read, write, output) => ({ input, read, write5m: write, write1h: write, write, output });
21
+ const TABLE = {
22
+ "claude-fable-5-1": { rates: [claude(10, 0.25, 50)] },
23
+ "claude-mythos-5-1": { rates: [claude(10, 0.25, 50)] },
24
+ "claude-fable-5": { rates: [claude(10, 1, 50)] },
25
+ "claude-mythos-5": { rates: [claude(10, 1, 50)] },
26
+ "claude-opus-5-5": { rates: [claude(4, 0.20, 20)] },
27
+ "claude-opus-5": { rates: [claude(5, 0.50, 25)] },
28
+ "claude-opus-4-8": { rates: [claude(5, 0.50, 25)] },
29
+ "claude-opus-4-7": { rates: [claude(5, 0.50, 25)] },
30
+ "claude-opus-4-6": { rates: [claude(5, 0.50, 25)] },
31
+ "claude-opus-4-5": { rates: [claude(5, 0.50, 25)] },
32
+ "claude-opus-4-1": { rates: [claude(15, 1.50, 75)] },
33
+ "claude-opus-4": { rates: [claude(15, 1.50, 75)] },
34
+ "claude-sonnet-5-5": { rates: [claude(2, 0.10, 10)] },
35
+ "claude-sonnet-5": { rates: [claude(2, 0.20, 10)] },
36
+ "claude-sonnet-4-6": { rates: [claude(3, 0.30, 15)] },
37
+ "claude-sonnet-4-5": { rates: [claude(3, 0.30, 15)] },
38
+ "claude-sonnet-4": { rates: [claude(3, 0.30, 15)] },
39
+ "claude-haiku-5-5": { rates: [claude(0.10, 0.01, 0.50), claude(0.50, 0.05, 2.50)], longOver: 100_000 },
40
+ "claude-haiku-4-5": { rates: [claude(1, 0.10, 5)] },
41
+ "gpt-6.1-sol": { rates: [openai(2, 0.10, 2.50, 10), openai(4, 0.20, 5, 15)], longOver: 272_000 },
42
+ "gpt-6-sol": { rates: [openai(2, 0.20, 2.50, 10), openai(4, 0.40, 5, 15)], longOver: 272_000 },
43
+ "gpt-6-astra": { rates: [openai(10, 1, 12.50, 50), openai(20, 2, 25, 75)], longOver: 272_000 },
44
+ "gpt-6-luna": { rates: [openai(0.10, 0.01, 0.125, 0.50), openai(0.20, 0.02, 0.25, 0.75)], longOver: 272_000 },
45
+ "gpt-5.6-sol": { rates: [openai(4, 0.40, 5, 20), openai(8, 0.80, 10, 30)], longOver: 272_000 },
46
+ "gpt-5.6-terra": { rates: [openai(2, 0.20, 2.50, 12), openai(4, 0.40, 5, 18)], longOver: 272_000 },
47
+ "gpt-5.6-luna": { rates: [openai(0.20, 0.02, 0.25, 1.20), openai(0.40, 0.04, 0.50, 1.80)], longOver: 272_000 },
48
+ };
49
+ /**
50
+ * The table's key for a model id as a transcript records it: "claude-opus-4-5-20251101" → "claude-opus-4-5",
51
+ * "claude-opus-5-5[1m]" → "claude-opus-5-5". Exact keys only — "claude-opus-5" never prices "claude-opus-5-5".
52
+ */
53
+ export function priceKey(model) {
54
+ if (typeof model !== "string")
55
+ return null;
56
+ const id = model.trim().toLowerCase().replace(/\[[^\]]*\]$/, "").replace(/-\d{8}$/, "");
57
+ return Object.prototype.hasOwnProperty.call(TABLE, id) ? id : null;
58
+ }
59
+ /** The rates for one request of `model` with a prompt of `promptTokens`; null when the model is not in the table. */
60
+ export function ratesFor(model, promptTokens = 0) {
61
+ const key = priceKey(model);
62
+ if (!key)
63
+ return null;
64
+ const row = TABLE[key];
65
+ return row.longOver !== undefined && promptTokens > row.longOver && row.rates[1] ? row.rates[1] : row.rates[0];
66
+ }
67
+ /** Whether a prompt of this size pays the model's long-context (or over-100K) row. */
68
+ export function isLongPrompt(model, promptTokens) {
69
+ const key = priceKey(model);
70
+ const row = key ? TABLE[key] : undefined;
71
+ return !!row && row.longOver !== undefined && promptTokens > row.longOver;
72
+ }
73
+ //# sourceMappingURL=cache-prices.js.map