@0xmaxma/claude-gateway 2.0.5 → 2.0.7

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 (435) hide show
  1. package/README.md +14 -1
  2. package/dist/agent/builtin-commands.js +5 -5
  3. package/dist/agent/builtin-commands.js.map +1 -1
  4. package/dist/agent/command-help.d.ts +9 -0
  5. package/dist/agent/command-help.d.ts.map +1 -0
  6. package/dist/agent/command-help.js +50 -0
  7. package/dist/agent/command-help.js.map +1 -0
  8. package/dist/agent/dreaming/index.d.ts +6 -3
  9. package/dist/agent/dreaming/index.d.ts.map +1 -1
  10. package/dist/agent/dreaming/index.js +21 -1
  11. package/dist/agent/dreaming/index.js.map +1 -1
  12. package/dist/agent/knowledge/reflection.d.ts +7 -4
  13. package/dist/agent/knowledge/reflection.d.ts.map +1 -1
  14. package/dist/agent/knowledge/reflection.js +19 -1
  15. package/dist/agent/knowledge/reflection.js.map +1 -1
  16. package/dist/agent/runner.d.ts +51 -3
  17. package/dist/agent/runner.d.ts.map +1 -1
  18. package/dist/agent/runner.js +228 -107
  19. package/dist/agent/runner.js.map +1 -1
  20. package/dist/agent/session-compaction-scheduler.d.ts +22 -0
  21. package/dist/agent/session-compaction-scheduler.d.ts.map +1 -0
  22. package/dist/agent/session-compaction-scheduler.js +40 -0
  23. package/dist/agent/session-compaction-scheduler.js.map +1 -0
  24. package/dist/agent/session-confirmations.d.ts +12 -0
  25. package/dist/agent/session-confirmations.d.ts.map +1 -0
  26. package/dist/agent/session-confirmations.js +43 -0
  27. package/dist/agent/session-confirmations.js.map +1 -0
  28. package/dist/agent/session-status.d.ts +7 -0
  29. package/dist/agent/session-status.d.ts.map +1 -0
  30. package/dist/agent/session-status.js +16 -0
  31. package/dist/agent/session-status.js.map +1 -0
  32. package/dist/agent/skill-learning/index.d.ts +5 -1
  33. package/dist/agent/skill-learning/index.d.ts.map +1 -1
  34. package/dist/agent/skill-learning/index.js +23 -1
  35. package/dist/agent/skill-learning/index.js.map +1 -1
  36. package/dist/agent/skill-learning/notifier.d.ts +2 -1
  37. package/dist/agent/skill-learning/notifier.d.ts.map +1 -1
  38. package/dist/agent/skill-learning/notifier.js +1 -0
  39. package/dist/agent/skill-learning/notifier.js.map +1 -1
  40. package/dist/api/apps-router.d.ts.map +1 -1
  41. package/dist/api/apps-router.js +1 -3
  42. package/dist/api/apps-router.js.map +1 -1
  43. package/dist/api/cron-router.d.ts +1 -1
  44. package/dist/api/cron-router.d.ts.map +1 -1
  45. package/dist/api/cron-router.js +4 -4
  46. package/dist/api/cron-router.js.map +1 -1
  47. package/dist/api/dashboard-processes.d.ts +86 -0
  48. package/dist/api/dashboard-processes.d.ts.map +1 -0
  49. package/dist/api/dashboard-processes.js +155 -0
  50. package/dist/api/dashboard-processes.js.map +1 -0
  51. package/dist/api/dashboard-sessions.d.ts +15 -0
  52. package/dist/api/dashboard-sessions.d.ts.map +1 -0
  53. package/dist/api/dashboard-sessions.js +66 -0
  54. package/dist/api/dashboard-sessions.js.map +1 -0
  55. package/dist/api/gateway-router.d.ts +3 -4
  56. package/dist/api/gateway-router.d.ts.map +1 -1
  57. package/dist/api/gateway-router.js +177 -66
  58. package/dist/api/gateway-router.js.map +1 -1
  59. package/dist/api/memory-activity.d.ts +18 -0
  60. package/dist/api/memory-activity.d.ts.map +1 -0
  61. package/dist/api/memory-activity.js +97 -0
  62. package/dist/api/memory-activity.js.map +1 -0
  63. package/dist/api/oauth-connectors-router.d.ts +1 -1
  64. package/dist/api/oauth-connectors-router.d.ts.map +1 -1
  65. package/dist/api/oauth-connectors-router.js +11 -21
  66. package/dist/api/oauth-connectors-router.js.map +1 -1
  67. package/dist/api/router.d.ts +1 -1
  68. package/dist/api/router.d.ts.map +1 -1
  69. package/dist/api/router.js +3 -9
  70. package/dist/api/router.js.map +1 -1
  71. package/dist/api/share-router.d.ts +1 -1
  72. package/dist/api/share-router.d.ts.map +1 -1
  73. package/dist/api/share-router.js +1 -1
  74. package/dist/api/share-router.js.map +1 -1
  75. package/dist/api/slack-webhook-router.js +1 -1
  76. package/dist/api/slack-webhook-router.js.map +1 -1
  77. package/dist/api/voice-router.d.ts +1 -0
  78. package/dist/api/voice-router.d.ts.map +1 -1
  79. package/dist/api/voice-router.js +7 -0
  80. package/dist/api/voice-router.js.map +1 -1
  81. package/dist/apps/agent-container-migration.d.ts +2 -0
  82. package/dist/apps/agent-container-migration.d.ts.map +1 -1
  83. package/dist/apps/agent-container-migration.js +59 -2
  84. package/dist/apps/agent-container-migration.js.map +1 -1
  85. package/dist/apps/agent-manager.d.ts +4 -2
  86. package/dist/apps/agent-manager.d.ts.map +1 -1
  87. package/dist/apps/agent-manager.js +39 -3
  88. package/dist/apps/agent-manager.js.map +1 -1
  89. package/dist/apps/installer.d.ts +4 -3
  90. package/dist/apps/installer.d.ts.map +1 -1
  91. package/dist/apps/installer.js +8 -4
  92. package/dist/apps/installer.js.map +1 -1
  93. package/dist/build-provenance.json +8 -0
  94. package/dist/cli/args.js +1 -1
  95. package/dist/cli/args.js.map +1 -1
  96. package/dist/cli/commands/app.d.ts.map +1 -1
  97. package/dist/cli/commands/app.js +39 -3
  98. package/dist/cli/commands/app.js.map +1 -1
  99. package/dist/cli/commands/doctor.d.ts.map +1 -1
  100. package/dist/cli/commands/doctor.js +6 -2
  101. package/dist/cli/commands/doctor.js.map +1 -1
  102. package/dist/cli/commands/safemode.d.ts +2 -0
  103. package/dist/cli/commands/safemode.d.ts.map +1 -0
  104. package/dist/cli/commands/safemode.js +279 -0
  105. package/dist/cli/commands/safemode.js.map +1 -0
  106. package/dist/cli/dependencies.d.ts +2 -0
  107. package/dist/cli/dependencies.d.ts.map +1 -1
  108. package/dist/cli/dependencies.js +81 -0
  109. package/dist/cli/dependencies.js.map +1 -1
  110. package/dist/cli/index.d.ts.map +1 -1
  111. package/dist/cli/index.js +11 -1
  112. package/dist/cli/index.js.map +1 -1
  113. package/dist/cli/manager.d.ts.map +1 -1
  114. package/dist/cli/manager.js +4 -1
  115. package/dist/cli/manager.js.map +1 -1
  116. package/dist/config/agent-lifecycle.d.ts +26 -0
  117. package/dist/config/agent-lifecycle.d.ts.map +1 -0
  118. package/dist/config/agent-lifecycle.js +63 -0
  119. package/dist/config/agent-lifecycle.js.map +1 -0
  120. package/dist/config/loader.d.ts.map +1 -1
  121. package/dist/config/loader.js +11 -0
  122. package/dist/config/loader.js.map +1 -1
  123. package/dist/config/reload-policy.d.ts +9 -0
  124. package/dist/config/reload-policy.d.ts.map +1 -0
  125. package/dist/config/reload-policy.js +62 -0
  126. package/dist/config/reload-policy.js.map +1 -0
  127. package/dist/config/watcher.d.ts +3 -2
  128. package/dist/config/watcher.d.ts.map +1 -1
  129. package/dist/config/watcher.js +34 -51
  130. package/dist/config/watcher.js.map +1 -1
  131. package/dist/cron/tool-schemas.d.ts +296 -0
  132. package/dist/cron/tool-schemas.d.ts.map +1 -0
  133. package/dist/cron/tool-schemas.js +122 -0
  134. package/dist/cron/tool-schemas.js.map +1 -0
  135. package/dist/index.js +141 -158
  136. package/dist/index.js.map +1 -1
  137. package/dist/orchestration/agent-tool-schemas.js +5 -5
  138. package/dist/orchestration/agent-tool-schemas.js.map +1 -1
  139. package/dist/orchestration/background-work.d.ts +9 -0
  140. package/dist/orchestration/background-work.d.ts.map +1 -0
  141. package/dist/orchestration/background-work.js +49 -0
  142. package/dist/orchestration/background-work.js.map +1 -0
  143. package/dist/orchestration/bridge.d.ts +6 -15
  144. package/dist/orchestration/bridge.d.ts.map +1 -1
  145. package/dist/orchestration/bridge.js +67 -32
  146. package/dist/orchestration/bridge.js.map +1 -1
  147. package/dist/orchestration/capabilities.d.ts.map +1 -1
  148. package/dist/orchestration/capabilities.js +18 -10
  149. package/dist/orchestration/capabilities.js.map +1 -1
  150. package/dist/orchestration/capacity.d.ts +3 -2
  151. package/dist/orchestration/capacity.d.ts.map +1 -1
  152. package/dist/orchestration/capacity.js +7 -0
  153. package/dist/orchestration/capacity.js.map +1 -1
  154. package/dist/orchestration/channel-controls.d.ts.map +1 -1
  155. package/dist/orchestration/channel-controls.js +3 -2
  156. package/dist/orchestration/channel-controls.js.map +1 -1
  157. package/dist/orchestration/cli-skills.d.ts +5 -0
  158. package/dist/orchestration/cli-skills.d.ts.map +1 -1
  159. package/dist/orchestration/compact-measurements.d.ts +21 -0
  160. package/dist/orchestration/compact-measurements.d.ts.map +1 -0
  161. package/dist/orchestration/compact-measurements.js +62 -0
  162. package/dist/orchestration/compact-measurements.js.map +1 -0
  163. package/dist/orchestration/config.d.ts +4 -0
  164. package/dist/orchestration/config.d.ts.map +1 -1
  165. package/dist/orchestration/config.js +1 -1
  166. package/dist/orchestration/config.js.map +1 -1
  167. package/dist/orchestration/container-tool-schemas.d.ts +37 -0
  168. package/dist/orchestration/container-tool-schemas.d.ts.map +1 -0
  169. package/dist/orchestration/container-tool-schemas.js +27 -0
  170. package/dist/orchestration/container-tool-schemas.js.map +1 -0
  171. package/dist/orchestration/container.d.ts.map +1 -1
  172. package/dist/orchestration/container.js +7 -0
  173. package/dist/orchestration/container.js.map +1 -1
  174. package/dist/orchestration/context-delivery.d.ts +32 -0
  175. package/dist/orchestration/context-delivery.d.ts.map +1 -0
  176. package/dist/orchestration/context-delivery.js +101 -0
  177. package/dist/orchestration/context-delivery.js.map +1 -0
  178. package/dist/orchestration/conversation-intake.d.ts +10 -6
  179. package/dist/orchestration/conversation-intake.d.ts.map +1 -1
  180. package/dist/orchestration/conversation-intake.js +22 -8
  181. package/dist/orchestration/conversation-intake.js.map +1 -1
  182. package/dist/orchestration/dashboard-charts.d.ts +32 -0
  183. package/dist/orchestration/dashboard-charts.d.ts.map +1 -0
  184. package/dist/orchestration/dashboard-charts.js +77 -0
  185. package/dist/orchestration/dashboard-charts.js.map +1 -0
  186. package/dist/orchestration/dashboard-reader-worker.js +28 -10
  187. package/dist/orchestration/dashboard-reader-worker.js.map +1 -1
  188. package/dist/orchestration/dashboard-reader.d.ts +1 -1
  189. package/dist/orchestration/dashboard-reader.d.ts.map +1 -1
  190. package/dist/orchestration/dashboard-reader.js +2 -2
  191. package/dist/orchestration/dashboard-reader.js.map +1 -1
  192. package/dist/orchestration/decision-context.d.ts +1 -1
  193. package/dist/orchestration/decision-context.d.ts.map +1 -1
  194. package/dist/orchestration/decision-context.js +3 -3
  195. package/dist/orchestration/decision-context.js.map +1 -1
  196. package/dist/orchestration/gateway-tasks/controller.d.ts +29 -0
  197. package/dist/orchestration/gateway-tasks/controller.d.ts.map +1 -0
  198. package/dist/orchestration/gateway-tasks/controller.js +139 -0
  199. package/dist/orchestration/gateway-tasks/controller.js.map +1 -0
  200. package/dist/orchestration/gateway-tasks/safemode.d.ts +19 -0
  201. package/dist/orchestration/gateway-tasks/safemode.d.ts.map +1 -0
  202. package/dist/orchestration/gateway-tasks/safemode.js +128 -0
  203. package/dist/orchestration/gateway-tasks/safemode.js.map +1 -0
  204. package/dist/orchestration/mutation-recovery.d.ts +3 -2
  205. package/dist/orchestration/mutation-recovery.d.ts.map +1 -1
  206. package/dist/orchestration/mutation-recovery.js +8 -0
  207. package/dist/orchestration/mutation-recovery.js.map +1 -1
  208. package/dist/orchestration/native-compact.d.ts +4 -1
  209. package/dist/orchestration/native-compact.d.ts.map +1 -1
  210. package/dist/orchestration/native-compact.js +6 -2
  211. package/dist/orchestration/native-compact.js.map +1 -1
  212. package/dist/orchestration/process-turn.d.ts +12 -2
  213. package/dist/orchestration/process-turn.d.ts.map +1 -1
  214. package/dist/orchestration/process-turn.js +48 -8
  215. package/dist/orchestration/process-turn.js.map +1 -1
  216. package/dist/orchestration/recovery.d.ts.map +1 -1
  217. package/dist/orchestration/recovery.js +4 -2
  218. package/dist/orchestration/recovery.js.map +1 -1
  219. package/dist/orchestration/runtime.d.ts +23 -1
  220. package/dist/orchestration/runtime.d.ts.map +1 -1
  221. package/dist/orchestration/runtime.js +191 -21
  222. package/dist/orchestration/runtime.js.map +1 -1
  223. package/dist/orchestration/session-compaction.d.ts +59 -0
  224. package/dist/orchestration/session-compaction.d.ts.map +1 -0
  225. package/dist/orchestration/session-compaction.js +212 -0
  226. package/dist/orchestration/session-compaction.js.map +1 -0
  227. package/dist/orchestration/skills.d.ts +2 -0
  228. package/dist/orchestration/skills.d.ts.map +1 -1
  229. package/dist/orchestration/skills.js +4 -3
  230. package/dist/orchestration/skills.js.map +1 -1
  231. package/dist/orchestration/task-controls.d.ts +12 -0
  232. package/dist/orchestration/task-controls.d.ts.map +1 -1
  233. package/dist/orchestration/task-controls.js +3 -1
  234. package/dist/orchestration/task-controls.js.map +1 -1
  235. package/dist/orchestration/tasks/driver.d.ts.map +1 -1
  236. package/dist/orchestration/tasks/driver.js +100 -13
  237. package/dist/orchestration/tasks/driver.js.map +1 -1
  238. package/dist/orchestration/tasks/pool.d.ts +2 -0
  239. package/dist/orchestration/tasks/pool.d.ts.map +1 -1
  240. package/dist/orchestration/tasks/pool.js +4 -0
  241. package/dist/orchestration/tasks/pool.js.map +1 -1
  242. package/dist/orchestration/tasks/scheduler.d.ts.map +1 -1
  243. package/dist/orchestration/tasks/scheduler.js +4 -0
  244. package/dist/orchestration/tasks/scheduler.js.map +1 -1
  245. package/dist/orchestration/tasks/service.d.ts +4 -0
  246. package/dist/orchestration/tasks/service.d.ts.map +1 -1
  247. package/dist/orchestration/tasks/service.js +38 -8
  248. package/dist/orchestration/tasks/service.js.map +1 -1
  249. package/dist/orchestration/token-ledger.d.ts +8 -0
  250. package/dist/orchestration/token-ledger.d.ts.map +1 -1
  251. package/dist/orchestration/token-ledger.js +7 -2
  252. package/dist/orchestration/token-ledger.js.map +1 -1
  253. package/dist/orchestration/token-usage.d.ts +3 -0
  254. package/dist/orchestration/token-usage.d.ts.map +1 -1
  255. package/dist/orchestration/token-usage.js +12 -3
  256. package/dist/orchestration/token-usage.js.map +1 -1
  257. package/dist/orchestration/types.d.ts +19 -1
  258. package/dist/orchestration/types.d.ts.map +1 -1
  259. package/dist/orchestration/types.js.map +1 -1
  260. package/dist/orchestration/worker-crons.d.ts +5 -0
  261. package/dist/orchestration/worker-crons.d.ts.map +1 -0
  262. package/dist/orchestration/worker-crons.js +84 -0
  263. package/dist/orchestration/worker-crons.js.map +1 -0
  264. package/dist/orchestration/worker-harness.d.ts +15 -0
  265. package/dist/orchestration/worker-harness.d.ts.map +1 -0
  266. package/dist/orchestration/worker-harness.js +72 -0
  267. package/dist/orchestration/worker-harness.js.map +1 -0
  268. package/dist/safemode/config.d.ts +7 -0
  269. package/dist/safemode/config.d.ts.map +1 -0
  270. package/dist/safemode/config.js +67 -0
  271. package/dist/safemode/config.js.map +1 -0
  272. package/dist/safemode/context.d.ts +7 -0
  273. package/dist/safemode/context.d.ts.map +1 -0
  274. package/dist/safemode/context.js +397 -0
  275. package/dist/safemode/context.js.map +1 -0
  276. package/dist/safemode/external-owners.d.ts +19 -0
  277. package/dist/safemode/external-owners.d.ts.map +1 -0
  278. package/dist/safemode/external-owners.js +229 -0
  279. package/dist/safemode/external-owners.js.map +1 -0
  280. package/dist/safemode/native.d.ts +38 -0
  281. package/dist/safemode/native.d.ts.map +1 -0
  282. package/dist/safemode/native.js +220 -0
  283. package/dist/safemode/native.js.map +1 -0
  284. package/dist/safemode/params.d.ts +10 -0
  285. package/dist/safemode/params.d.ts.map +1 -0
  286. package/dist/safemode/params.js +86 -0
  287. package/dist/safemode/params.js.map +1 -0
  288. package/dist/safemode/provenance.d.ts +45 -0
  289. package/dist/safemode/provenance.d.ts.map +1 -0
  290. package/dist/safemode/provenance.js +153 -0
  291. package/dist/safemode/provenance.js.map +1 -0
  292. package/dist/safemode/runner.d.ts +17 -0
  293. package/dist/safemode/runner.d.ts.map +1 -0
  294. package/dist/safemode/runner.js +398 -0
  295. package/dist/safemode/runner.js.map +1 -0
  296. package/dist/safemode/store.d.ts +56 -0
  297. package/dist/safemode/store.d.ts.map +1 -0
  298. package/dist/safemode/store.js +451 -0
  299. package/dist/safemode/store.js.map +1 -0
  300. package/dist/session/codex-auth.d.ts +37 -0
  301. package/dist/session/codex-auth.d.ts.map +1 -0
  302. package/dist/session/codex-auth.js +266 -0
  303. package/dist/session/codex-auth.js.map +1 -0
  304. package/dist/session/codex-container-runtime.d.ts +15 -0
  305. package/dist/session/codex-container-runtime.d.ts.map +1 -0
  306. package/dist/session/codex-container-runtime.js +85 -0
  307. package/dist/session/codex-container-runtime.js.map +1 -0
  308. package/dist/session/codex-context-defaults.json +5 -0
  309. package/dist/session/codex-context.d.ts +13 -0
  310. package/dist/session/codex-context.d.ts.map +1 -0
  311. package/dist/session/codex-context.js +27 -0
  312. package/dist/session/codex-context.js.map +1 -0
  313. package/dist/session/codex-extension-discovery.d.ts +21 -0
  314. package/dist/session/codex-extension-discovery.d.ts.map +1 -0
  315. package/dist/session/codex-extension-discovery.js +132 -0
  316. package/dist/session/codex-extension-discovery.js.map +1 -0
  317. package/dist/session/codex-native-mcp-client.d.ts +37 -0
  318. package/dist/session/codex-native-mcp-client.d.ts.map +1 -0
  319. package/dist/session/codex-native-mcp-client.js +164 -0
  320. package/dist/session/codex-native-mcp-client.js.map +1 -0
  321. package/dist/session/codex-policy.d.ts +6 -0
  322. package/dist/session/codex-policy.d.ts.map +1 -0
  323. package/dist/session/codex-policy.js +17 -0
  324. package/dist/session/codex-policy.js.map +1 -0
  325. package/dist/session/codex-process.d.ts +114 -0
  326. package/dist/session/codex-process.d.ts.map +1 -0
  327. package/dist/session/codex-process.js +759 -0
  328. package/dist/session/codex-process.js.map +1 -0
  329. package/dist/session/codex-runtime.d.ts +20 -0
  330. package/dist/session/codex-runtime.d.ts.map +1 -0
  331. package/dist/session/codex-runtime.js +182 -0
  332. package/dist/session/codex-runtime.js.map +1 -0
  333. package/dist/session/codex-tool-capture.d.ts +35 -0
  334. package/dist/session/codex-tool-capture.d.ts.map +1 -0
  335. package/dist/session/codex-tool-capture.js +178 -0
  336. package/dist/session/codex-tool-capture.js.map +1 -0
  337. package/dist/session/container-connectors.d.ts +10 -0
  338. package/dist/session/container-connectors.d.ts.map +1 -0
  339. package/dist/session/container-connectors.js +41 -0
  340. package/dist/session/container-connectors.js.map +1 -0
  341. package/dist/session/container-extensions.d.ts +4 -0
  342. package/dist/session/container-extensions.d.ts.map +1 -0
  343. package/dist/session/container-extensions.js +45 -0
  344. package/dist/session/container-extensions.js.map +1 -0
  345. package/dist/session/managed-connectors.d.ts +16 -0
  346. package/dist/session/managed-connectors.d.ts.map +1 -0
  347. package/dist/session/managed-connectors.js +25 -0
  348. package/dist/session/managed-connectors.js.map +1 -0
  349. package/dist/session/process-diagnostics.d.ts +14 -0
  350. package/dist/session/process-diagnostics.d.ts.map +1 -0
  351. package/dist/session/process-diagnostics.js +39 -0
  352. package/dist/session/process-diagnostics.js.map +1 -0
  353. package/dist/session/process.d.ts +4 -0
  354. package/dist/session/process.d.ts.map +1 -1
  355. package/dist/session/process.js +21 -16
  356. package/dist/session/process.js.map +1 -1
  357. package/dist/session/request-tool-capture.d.ts +1 -1
  358. package/dist/session/request-tool-capture.d.ts.map +1 -1
  359. package/dist/session/runtime-profile.d.ts +8 -0
  360. package/dist/session/runtime-profile.d.ts.map +1 -1
  361. package/dist/session/runtime-profile.js +3 -2
  362. package/dist/session/runtime-profile.js.map +1 -1
  363. package/dist/session/worker-environment.d.ts +5 -0
  364. package/dist/session/worker-environment.d.ts.map +1 -0
  365. package/dist/session/worker-environment.js +27 -0
  366. package/dist/session/worker-environment.js.map +1 -0
  367. package/dist/session/worker-extensions.d.ts +20 -0
  368. package/dist/session/worker-extensions.d.ts.map +1 -0
  369. package/dist/session/worker-extensions.js +322 -0
  370. package/dist/session/worker-extensions.js.map +1 -0
  371. package/dist/skills/loader.d.ts +2 -0
  372. package/dist/skills/loader.d.ts.map +1 -1
  373. package/dist/skills/loader.js.map +1 -1
  374. package/dist/types.d.ts +33 -0
  375. package/dist/types.d.ts.map +1 -1
  376. package/dist/ui/codex-context.d.ts +4 -0
  377. package/dist/ui/codex-context.d.ts.map +1 -0
  378. package/dist/ui/codex-context.js +15 -0
  379. package/dist/ui/codex-context.js.map +1 -0
  380. package/dist/ui/dashboard-charts.d.ts +3 -0
  381. package/dist/ui/dashboard-charts.d.ts.map +1 -0
  382. package/dist/ui/dashboard-charts.js +130 -0
  383. package/dist/ui/dashboard-charts.js.map +1 -0
  384. package/dist/ui/dashboard-client.d.ts.map +1 -1
  385. package/dist/ui/dashboard-client.js +20 -21
  386. package/dist/ui/dashboard-client.js.map +1 -1
  387. package/dist/ui/dashboard-controls.d.ts +4 -0
  388. package/dist/ui/dashboard-controls.d.ts.map +1 -0
  389. package/dist/ui/dashboard-controls.js +27 -0
  390. package/dist/ui/dashboard-controls.js.map +1 -0
  391. package/dist/ui/dashboard-presentation.d.ts +4 -1
  392. package/dist/ui/dashboard-presentation.d.ts.map +1 -1
  393. package/dist/ui/dashboard-presentation.js +13 -7
  394. package/dist/ui/dashboard-presentation.js.map +1 -1
  395. package/dist/ui/dashboard-range.d.ts +3 -3
  396. package/dist/ui/dashboard-range.d.ts.map +1 -1
  397. package/dist/ui/dashboard-range.js +21 -5
  398. package/dist/ui/dashboard-range.js.map +1 -1
  399. package/dist/ui/dashboard-theme.d.ts +3 -1
  400. package/dist/ui/dashboard-theme.d.ts.map +1 -1
  401. package/dist/ui/dashboard-theme.js +80 -3
  402. package/dist/ui/dashboard-theme.js.map +1 -1
  403. package/dist/ui/memory-activity.d.ts +4 -0
  404. package/dist/ui/memory-activity.d.ts.map +1 -0
  405. package/dist/ui/memory-activity.js +115 -0
  406. package/dist/ui/memory-activity.js.map +1 -0
  407. package/dist/ui/token-report-client.d.ts +1 -1
  408. package/dist/ui/token-report-client.d.ts.map +1 -1
  409. package/dist/ui/token-report-client.js +1 -1
  410. package/dist/ui/token-report.d.ts +4 -0
  411. package/dist/ui/token-report.d.ts.map +1 -1
  412. package/dist/ui/token-report.js +38 -23
  413. package/dist/ui/token-report.js.map +1 -1
  414. package/dist/ui/web-ui.d.ts +1 -1
  415. package/dist/ui/web-ui.d.ts.map +1 -1
  416. package/dist/ui/web-ui.js +68 -370
  417. package/dist/ui/web-ui.js.map +1 -1
  418. package/mcp/capability-catalog.ts +2 -0
  419. package/mcp/extension-catalog.ts +18 -0
  420. package/mcp/lazy-connector.ts +4 -2
  421. package/mcp/lazy-tools.test.ts +29 -0
  422. package/mcp/modules.ts +1 -0
  423. package/mcp/server.ts +2 -2
  424. package/mcp/tools/cron/module.ts +8 -114
  425. package/mcp/tools/discord/commands.ts +4 -1
  426. package/mcp/tools/safemode/module.test.ts +29 -0
  427. package/mcp/tools/telegram/receiver-server.ts +33 -39
  428. package/mcp/tools/telegram/session-browser.ts +10 -0
  429. package/mcp/tools/telegram/task-detail.ts +2 -1
  430. package/package.json +3 -2
  431. package/scripts/orchestration/audit-codex-context.cjs +83 -0
  432. package/scripts/orchestration/benchmark-worker-harnesses.cjs +112 -0
  433. package/scripts/orchestration/smoke-codex-extensions.ts +29 -0
  434. package/scripts/orchestration/smoke-codex-worker.cjs +166 -0
  435. package/scripts/orchestration/smoke-safemode-codex.cjs +66 -0
@@ -0,0 +1,130 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.dashboardChartsClient = void 0;
4
+ exports.dashboardChartsHtml = dashboardChartsHtml;
5
+ function dashboardChartsHtml(timezone) {
6
+ const zone = timezone.replace(/[^A-Za-z0-9_+\/.-]/g, '');
7
+ return '<div id="overview-charts" class="overview-chart-grid">' + [
8
+ ['activity', 'Token activity'], ['agents', 'Tokens by agent'], ['models', 'Tokens by model'], ['reuse', 'Context reuse'],
9
+ ].map(([key, title]) => '<section class="dash-panel overview-chart-card" data-chart="' + key + '"><div class="chart-card-header"><h2>' + title + '</h2><div class="range-toggle chart-range" role="group" aria-label="' + title + ' date range">' + ['24h', '7d', '30d', '90d'].map(range => '<button type="button" data-chart-range="' + range + '" aria-pressed="' + (range === '24h') + '" title="' + (range === '24h' ? 'Today from 00:00 ' : range + ' including today · ') + zone + '">' + range + '</button>').join('') + '</div></div><p class="live-note chart-period"></p><div class="chart-content" id="chart-' + key + '"><p class="empty">Loading recorded usage…</p></div><p class="live-note chart-status" role="status"></p></section>').join('') + '</div>';
10
+ }
11
+ exports.dashboardChartsClient = String.raw `
12
+ const overviewChartRanges={activity:'24h',agents:'24h',models:'24h',reuse:'24h'};
13
+ const overviewChartSnapshots=new Map(),overviewChartInflight=new Map();
14
+ const chartColors=dashboardChartPalette;
15
+ const chartRendered=new WeakMap();
16
+ let chartPointer=null;
17
+ document.addEventListener('pointermove',event=>{chartPointer={x:event.clientX,y:event.clientY};});
18
+ document.addEventListener('pointerout',event=>{if(!event.relatedTarget)chartPointer=null;});
19
+ const chartPreferenceKey='gateway-overview-charts:'+location.pathname.replace(/\/$/,'');
20
+ try{
21
+ const saved=JSON.parse(localStorage.getItem(chartPreferenceKey)||'{}');
22
+ Object.keys(overviewChartRanges).forEach(key=>{if(['24h','7d','30d','90d'].includes(saved?.[key]))overviewChartRanges[key]=saved[key];});
23
+ }catch{}
24
+ // Restore controls before the first fetch, including when Overview is initially hidden.
25
+ Object.keys(overviewChartRanges).forEach(key=>document.querySelectorAll('[data-chart="'+key+'"] [data-chart-range]').forEach(button=>button.setAttribute('aria-pressed',String(button.dataset.chartRange===overviewChartRanges[key]))));
26
+ function chartPeriod(data){const fmt=new Intl.DateTimeFormat('en-GB',{timeZone:data.timezone,day:'numeric',month:'short'});return (data.scope==='24h'?'Today · from 00:00':fmt.format(data.since)+' – '+fmt.format(data.asOf))+' · '+data.timezone;}
27
+ function chartEmpty(){return '<p class="empty">No recorded token usage in this period.</p>';}
28
+ function chartTooltipRow(label,value,color='var(--text)',detail){
29
+ return '<span class="chart-tooltip-row"><span>'+escHtml(label)+'</span><strong style="color:'+color+'">'+escHtml(value)+(detail==null?'':' <span class="chart-tooltip-detail">('+escHtml(detail)+')</span>')+'</strong></span>';
30
+ }
31
+ function chartInputShare(value,total){return total>0?(value/total*100).toFixed(1)+'%':'—';}
32
+ function chartActivity(data,reuse=false){
33
+ const reuseLegend={read:'Reused (Cached Read)',write:'New saved (Cached write)',fresh:'New not cached (Input)'};
34
+ const series=reuse?[['read','Reused','var(--token-agent)'],['write','New · saved','var(--token-worker)'],['fresh','New · not cached','var(--token-report)']]:[['agent','Agent','var(--token-agent)'],['worker','Workers','var(--token-worker)']];
35
+ const blank=()=>Object.fromEntries(series.map(([key])=>[key,0]));
36
+ const slots=new Map();
37
+ if(data.scope==='24h')for(let i=0;i<24;i++)slots.set(String(i).padStart(2,'0'),blank());
38
+ else{
39
+ const fmt=new Intl.DateTimeFormat('en-CA',{timeZone:data.timezone,year:'numeric',month:'2-digit',day:'2-digit'});
40
+ const parts=fmt.formatToParts(data.asOf),v=k=>Number(parts.find(p=>p.type===k).value),end=Date.UTC(v('year'),v('month')-1,v('day'));
41
+ for(let i=Number(data.scope.slice(0,-1))-1;i>=0;i--)slots.set(new Date(end-i*86400000).toISOString().slice(0,10),blank());
42
+ }
43
+ data.agents.forEach(a=>a.buckets.forEach(b=>{if(slots.has(b.key)){const slot=slots.get(b.key);series.forEach(([key])=>slot[key]+=Number(b[key]||0));}}));
44
+ const values=[...slots].map(([key,value])=>({key,...value})),peak=Math.max(0,...values.flatMap(v=>series.map(([key])=>v[key])));
45
+ if(!peak)return chartEmpty();
46
+ const label=key=>data.scope==='24h'?key+':00':key.slice(8,10)+'/'+key.slice(5,7);
47
+ const points=role=>values.map((v,i)=>(i*600/(values.length-1)).toFixed(2)+','+(180-v[role]/peak*170).toFixed(2)).join(' ');
48
+ return '<div class="activity-frame"><div class="chart-y-labels"><span>'+compactNumber(peak)+'</span><span>'+compactNumber(peak/2)+'</span><span>0</span></div><div class="activity-plot"><svg viewBox="0 0 600 190" preserveAspectRatio="none" aria-label="'+(reuse?'Recorded input reuse':'Agent and worker recorded token activity')+'" role="img"><path d="M0 10H600M0 95H600M0 180H600" fill="none" stroke="var(--line)" stroke-dasharray="3 5" vector-effect="non-scaling-stroke"/>'+series.map(([role,label,color])=>'<polyline points="'+points(role)+'" fill="none" stroke="'+color+'" stroke-width="1.5" vector-effect="non-scaling-stroke"/>').join('')+'</svg><div class="chart-hit-grid" style="grid-template-columns:repeat('+values.length+',minmax(0,1fr))">'+values.map((v,i)=>'<div class="chart-hit" data-chart-point="'+escHtml(v.key)+'" tabindex="0" role="img" aria-label="'+escHtml(label(v.key)+': '+series.map(([key,label])=>label+' '+compactNumber(v[key])).join(', '))+'">'+series.map(([role,label,color])=>'<i class="chart-line-dot" style="top:'+((180-v[role]/peak*170)/190*100)+'%;left:'+((i/(values.length-1)*values.length-i)*100)+'%;--dot-color:'+color+'"></i>').join('')+'<span class="chart-popover '+(i>values.length/2?'align-right':'align-left')+'"><strong>'+label(v.key)+'</strong>'+series.map(([key,label,color])=>chartTooltipRow(label,reuse?chartInputShare(v[key],v.read+v.write+v.fresh):compactNumber(v[key]),color,reuse&&v.read+v.write+v.fresh>0?compactNumber(v[key]):undefined)).join('')+chartTooltipRow(reuse?'Total input':'Total',compactNumber(series.reduce((n,[key])=>n+v[key],0)))+'</span></div>').join('')+'</div><div class="chart-x-labels"><span>'+label(values[0].key)+'</span><span>'+label(values[Math.floor(values.length/2)].key)+'</span><span>'+label(values[values.length-1].key)+'</span></div></div></div><div class="chart-key reuse-key">'+series.map(([key,label,color])=>'<span><i style="background:'+color+'"></i>'+(reuse?reuseLegend[key]:label)+'</span>').join('')+'</div><p class="live-note">'+(reuse?'Input tokens only. Not billing savings.':'Recorded tokens, including cache. Not billing cost.')+'</p>';
49
+ }
50
+ function chartAgents(data,element){
51
+ const agents=data.agents.map(a=>({...a,total:a.agent+a.worker})).filter(a=>a.total>0).sort((a,b)=>b.total-a.total||a.id.localeCompare(b.id));
52
+ if(!agents.length)return chartEmpty();
53
+ const capacity=Math.max(2,Math.min(8,Math.floor((element.clientWidth-40)/76))),top=agents.slice(0,capacity),peak=top[0].total;
54
+ return '<div class="agent-column-plot"><div class="chart-y-labels"><span>'+compactNumber(peak)+'</span><span>'+compactNumber(peak/2)+'</span><span>0</span></div><div class="agent-columns">'+top.map(a=>'<div class="agent-column" data-chart-point="'+escHtml(a.id)+'" style="--agent-hue:'+agentHue(a.id)+'" tabindex="0" role="img" aria-label="'+escHtml(a.id+': Agent '+compactNumber(a.agent)+', workers '+compactNumber(a.worker)+', total '+compactNumber(a.total))+'"><div class="agent-bar-space"><div class="agent-bar" style="height:'+Math.max(1,a.total/peak*100)+'%"><span class="agent-bar-total">'+compactNumber(a.total)+'</span></div></div><span class="agent-bar-label" title="'+escHtml(a.id)+'"><i></i><span>'+escHtml(a.id)+'</span></span><span class="chart-popover"><strong>'+escHtml(a.id)+'</strong>'+chartTooltipRow('Agent',compactNumber(a.agent),'var(--token-agent)')+chartTooltipRow('Workers',compactNumber(a.worker),'var(--token-worker)')+chartTooltipRow('Total',compactNumber(a.total),'var(--agent-chart-color)')+'</span></div>').join('')+'</div></div><div class="chart-key"><span>Agent + worker tokens · colors match Agents below</span></div><p class="live-note">Top '+top.length+' of '+agents.length+' active agents · ranked by recorded tokens.</p>';
55
+ }
56
+ function chartModels(data){
57
+ const models=new Map();data.agents.forEach(a=>a.models.forEach(m=>models.set(m.name,(models.get(m.name)||0)+m.tokens)));
58
+ const sorted=[...models].map(([name,tokens])=>({name,tokens})).sort((a,b)=>b.tokens-a.tokens||a.name.localeCompare(b.name));
59
+ const total=sorted.reduce((n,m)=>n+m.tokens,0);if(!total)return chartEmpty();
60
+ const top=sorted.slice(0,5);if(sorted.length>5)top.push({name:'Other models ('+(sorted.length-5)+')',tokens:sorted.slice(5).reduce((n,m)=>n+m.tokens,0)});
61
+ let offset=0;const circumference=2*Math.PI*72;
62
+ const arcs=top.map((m,i)=>{const length=m.tokens/total*circumference,arc='<circle cx="100" cy="100" r="72" fill="none" stroke="'+chartColors[i]+'" stroke-width="22" stroke-dasharray="'+length+' '+(circumference-length)+'" stroke-dashoffset="'+(-offset)+'" transform="rotate(-90 100 100)" tabindex="0" data-chart-point="'+escHtml(m.name)+'" data-model-name="'+escHtml(m.name)+'" data-model-tokens="'+compactNumber(m.tokens)+'" data-model-share="'+(m.tokens/total*100).toFixed(1)+'%" aria-label="'+escHtml(m.name)+' · '+compactNumber(m.tokens)+' · '+(m.tokens/total*100).toFixed(1)+'%"></circle>';offset+=length;return arc;}).join('');
63
+ return '<div class="model-donut-layout"><div class="model-donut"><svg viewBox="0 0 200 200" role="img" aria-label="Recorded tokens by model">'+arcs+'</svg><span class="chart-popover model-tooltip" role="tooltip"></span><div class="donut-center"><strong>'+compactNumber(total)+'</strong><span>Total tokens</span></div></div><ul class="model-chart-legend">'+top.map((m,i)=>'<li><i style="background:'+chartColors[i]+'"></i><span title="'+escHtml(m.name)+'">'+escHtml(m.name)+'</span><strong>'+compactNumber(m.tokens)+'</strong><small>'+(m.tokens/total*100).toFixed(1)+'%</small></li>').join('')+'</ul></div><p class="live-note">Agent + worker tokens · includes cache reads and writes.</p>';
64
+ }
65
+ function chartReuse(data){
66
+ const day=key=>data.agents.reduce((r,a)=>{const value=a.reuseComparison?.[key];if(value)Object.keys(r).forEach(k=>r[k]+=value[k]||0);return r;},{fresh:0,write:0,read:0,missingTurns:0});
67
+ const today=day('today'),yesterday=day('yesterday');
68
+ const rate=d=>{const total=d.fresh+d.write+d.read;return total>0?100*d.read/total:null;};
69
+ const current=rate(today),previous=rate(yesterday),delta=current!==null&&previous!==null?current-previous:null;
70
+ const comparison=delta===null?'Yesterday: no measured input to compare.':(delta===0?'Unchanged':(delta>0?'Up ':'Down ')+Math.abs(delta).toFixed(1)+' percentage points')+' vs yesterday ('+previous.toFixed(1)+'%).';
71
+ return chartActivity(data,true)+'<p class="reuse-summary"><strong>'+(current===null?'—':current.toFixed(1)+'%')+'</strong> of today’s measured input reused</p><p class="live-note">'+(current===null?'No measured input today.':comparison)+' Today so far vs yesterday’s full day · '+escHtml(data.timezone)+(today.missingTurns?' · '+compactNumber(today.missingTurns)+' turns excluded today: incomplete measurements.':'')+'</p>';
72
+ }
73
+ function drawOverviewChart(key,data){
74
+ const card=document.querySelector('[data-chart="'+key+'"]'),element=card.querySelector('.chart-content');
75
+ const sameScope=element.dataset.scope===data.scope;
76
+ const html=key==='activity'?chartActivity(data):key==='agents'?chartAgents(data,element):key==='models'?chartModels(data):chartReuse(data);
77
+ card.querySelector('.chart-period').textContent=chartPeriod(data);
78
+ if(chartRendered.get(element)!==html){
79
+ const active=document.activeElement,hadFocus=element.contains(active);
80
+ const point=hadFocus&&sameScope?active.closest('[data-chart-point]')?.dataset.chartPoint:null;
81
+ element.innerHTML=html;chartRendered.set(element,html);
82
+ if(hadFocus){
83
+ const replacement=point==null?null:[...element.querySelectorAll('[data-chart-point]')].find(node=>node.dataset.chartPoint===point);
84
+ (replacement||card.querySelector('[data-chart-range="'+data.scope+'"]')).focus({preventScroll:true});
85
+ }
86
+ // A stationary pointer does not emit pointerover after replacing SVG nodes.
87
+ if(chartPointer){const hovered=document.elementFromPoint(chartPointer.x,chartPointer.y);if(hovered&&element.contains(hovered))showModelTooltip(hovered);}
88
+ }
89
+ element.dataset.scope=data.scope;
90
+ card.querySelector('.chart-status').textContent='';
91
+ }
92
+ function refreshOverviewCharts(force=false){
93
+ if(document.hidden||document.getElementById('view-overview').style.display==='none')return;
94
+ Object.keys(overviewChartRanges).forEach(key=>document.querySelectorAll('[data-chart="'+key+'"] [data-chart-range]').forEach(b=>b.setAttribute('aria-pressed',String(b.dataset.chartRange===overviewChartRanges[key]))));
95
+ [...new Set(Object.values(overviewChartRanges))].forEach(scope=>{
96
+ const old=overviewChartSnapshots.get(scope);if(!force&&old&&Date.now()-old.at<10000)return;
97
+ if(overviewChartInflight.has(scope))return;
98
+ const request=fetch(apiUrl('/dashboard/charts')+'?scope='+scope,{signal:AbortSignal.timeout(15000)}).then(async response=>{if(!response.ok)throw Error('Chart data temporarily unavailable');return response.json();}).then(data=>{
99
+ overviewChartSnapshots.set(scope,{data,at:Date.now()});Object.keys(overviewChartRanges).forEach(key=>{if(overviewChartRanges[key]===scope)drawOverviewChart(key,data);});
100
+ }).catch(()=>Object.keys(overviewChartRanges).forEach(key=>{if(overviewChartRanges[key]===scope)document.querySelector('[data-chart="'+key+'"] .chart-status').textContent='Could not refresh. Retrying automatically.';})).finally(()=>overviewChartInflight.delete(scope));
101
+ overviewChartInflight.set(scope,request);
102
+ });
103
+ }
104
+ function showModelTooltip(target){
105
+ const arc=target.closest('[data-model-name]');if(!arc)return;
106
+ const tip=arc.closest('.model-donut').querySelector('.model-tooltip');
107
+ const color=arc.getAttribute('stroke');
108
+ // Stroke comes only from our fixed chart palette, never provider metadata.
109
+ tip.innerHTML='<strong>'+escHtml(arc.dataset.modelName)+'</strong>'+chartTooltipRow('Tokens',arc.dataset.modelShare,color,arc.dataset.modelTokens);
110
+ tip.style.display='block';
111
+ }
112
+ document.addEventListener('pointerover',event=>showModelTooltip(event.target));
113
+ document.addEventListener('focusin',event=>showModelTooltip(event.target));
114
+ function hideModelTooltip(event){const arc=event.target.closest('[data-model-name]');if(arc)arc.closest('.model-donut').querySelector('.model-tooltip').style.display='none';}
115
+ document.addEventListener('pointerout',hideModelTooltip);
116
+ document.addEventListener('focusout',hideModelTooltip);
117
+ document.addEventListener('click',event=>{
118
+ const button=event.target.closest('[data-chart-range]');if(button){
119
+ const key=button.closest('[data-chart]').dataset.chart,scope=button.dataset.chartRange;overviewChartRanges[key]=scope;
120
+ try{localStorage.setItem(chartPreferenceKey,JSON.stringify(overviewChartRanges));}catch{}
121
+ const cached=overviewChartSnapshots.get(scope);if(cached)drawOverviewChart(key,cached.data);else {chartRendered.delete(document.getElementById('chart-'+key));document.getElementById('chart-'+key).innerHTML='<p class="empty">Loading recorded usage…</p>';document.querySelector('[data-chart="'+key+'"] .chart-period').textContent='';}
122
+ refreshOverviewCharts();
123
+ }else if(event.target.closest('#tab-overview'))refreshOverviewCharts();
124
+ });
125
+ document.addEventListener('DOMContentLoaded',()=>refreshOverviewCharts());
126
+ document.addEventListener('visibilitychange',()=>{if(!document.hidden)refreshOverviewCharts();});
127
+ setInterval(()=>refreshOverviewCharts(true),10000);
128
+ let chartResizeWidth=0;new ResizeObserver(entries=>{const width=Math.round(entries[0].contentRect.width);if(width===chartResizeWidth)return;chartResizeWidth=width;const snapshot=overviewChartSnapshots.get(overviewChartRanges.agents);if(snapshot)drawOverviewChart('agents',snapshot.data);}).observe(document.getElementById('chart-agents'));
129
+ `;
130
+ //# sourceMappingURL=dashboard-charts.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"dashboard-charts.js","sourceRoot":"","sources":["../../src/ui/dashboard-charts.ts"],"names":[],"mappings":";;;AAAA,kDAKC;AALD,SAAgB,mBAAmB,CAAC,QAAgB;IAClD,MAAM,IAAI,GAAC,QAAQ,CAAC,OAAO,CAAC,qBAAqB,EAAC,EAAE,CAAC,CAAC;IACtD,OAAO,wDAAwD,GAAC;QAC9D,CAAC,UAAU,EAAC,gBAAgB,CAAC,EAAC,CAAC,QAAQ,EAAC,iBAAiB,CAAC,EAAC,CAAC,QAAQ,EAAC,iBAAiB,CAAC,EAAC,CAAC,OAAO,EAAC,eAAe,CAAC;KAClH,CAAC,GAAG,CAAC,CAAC,CAAC,GAAG,EAAC,KAAK,CAAC,EAAC,EAAE,CAAA,8DAA8D,GAAC,GAAG,GAAC,uCAAuC,GAAC,KAAK,GAAC,sEAAsE,GAAC,KAAK,GAAC,eAAe,GAAC,CAAC,KAAK,EAAC,IAAI,EAAC,KAAK,EAAC,KAAK,CAAC,CAAC,GAAG,CAAC,KAAK,CAAA,EAAE,CAAA,0CAA0C,GAAC,KAAK,GAAC,kBAAkB,GAAC,CAAC,KAAK,KAAG,KAAK,CAAC,GAAC,WAAW,GAAC,CAAC,KAAK,KAAG,KAAK,CAAA,CAAC,CAAA,mBAAmB,CAAA,CAAC,CAAA,KAAK,GAAC,qBAAqB,CAAC,GAAC,IAAI,GAAC,IAAI,GAAC,KAAK,GAAC,WAAW,CAAC,CAAC,IAAI,CAAC,EAAE,CAAC,GAAC,yFAAyF,GAAC,GAAG,GAAC,oHAAoH,CAAC,CAAC,IAAI,CAAC,EAAE,CAAC,GAAC,QAAQ,CAAC;AACrrB,CAAC;AAEY,QAAA,qBAAqB,GAAC,MAAM,CAAC,GAAG,CAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;CAsH5C,CAAC"}
@@ -1 +1 @@
1
- {"version":3,"file":"dashboard-client.d.ts","sourceRoot":"","sources":["../../src/ui/dashboard-client.ts"],"names":[],"mappings":"AAEA,gFAAgF;AAChF,eAAO,MAAM,eAAe,QAoL3B,CAAC"}
1
+ {"version":3,"file":"dashboard-client.d.ts","sourceRoot":"","sources":["../../src/ui/dashboard-client.ts"],"names":[],"mappings":"AAIA,gFAAgF;AAChF,eAAO,MAAM,eAAe,QAiL3B,CAAC"}
@@ -1,10 +1,12 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
3
  exports.dashboardClient = void 0;
4
+ const codex_context_1 = require("./codex-context");
5
+ const dashboard_charts_1 = require("./dashboard-charts");
4
6
  const dashboard_range_1 = require("./dashboard-range");
5
7
  const dashboard_presentation_1 = require("./dashboard-presentation");
6
8
  /** Browser controller: no provider keys or model-generated HTML are trusted. */
7
- exports.dashboardClient = dashboard_presentation_1.dashboardPresentationClient + dashboard_range_1.dashboardRange.toString() + ';' + dashboard_range_1.dashboardSince.toString() + ';' + String.raw `
9
+ exports.dashboardClient = codex_context_1.codexContextHtml.toString() + ';' + dashboard_presentation_1.dashboardPresentationClient + dashboard_range_1.dashboardRange.toString() + ';' + dashboard_range_1.dashboardSince.toString() + ';' + dashboard_charts_1.dashboardChartsClient + String.raw `
8
10
  let dashboardData = null, dashboardOffset = 0, dashboardBusy = false, dashboardSearch = '', dashboardAgent = '', dashboardScope = '24h';
9
11
  const dashboardStateKey='gateway-dashboard-view:'+location.pathname.replace(/\/$/,'');
10
12
  let savedDashboardState={};
@@ -34,6 +36,7 @@ function dashboardRows() {
34
36
  (dashboardData?.agents||[]).forEach(a=>(a.sessions||[]).forEach(s=>rows.push({a,s})));
35
37
  return rows.filter(({a,s})=>(!dashboardAgent||a.id===dashboardAgent)&&(!dashboardSearch||[a.id,s.sessionId,s.chatId,s.source,s.model].join(' ').toLowerCase().includes(dashboardSearch.toLowerCase()))).sort((x,y)=>(Number(y.s.updatedAt||y.s.spawnedAt)||0)-(Number(x.s.updatedAt||x.s.spawnedAt)||0)||String(x.s.sessionId).localeCompare(String(y.s.sessionId)));
36
38
  }
39
+ function gatewayTaskLabel(t){return t.gatewayTarget?'<small class="ts">Gateway-managed · '+dashText(t.gatewayTarget.adapter==='safemode'?'Safemode':t.gatewayTarget.adapter)+' · '+dashText(t.gatewayTarget.name)+'</small>':'<small class="ts">Worker task</small>';}
37
40
  function dashboardTaskRows(){return dashboardRows().flatMap(({a,s})=>(s.tasks||[]).map(t=>({a,s,t}))).sort((x,y)=>Number(y.t.updatedAt)-Number(x.t.updatedAt)||x.t.taskId.localeCompare(y.t.taskId));}
38
41
  function dashText(value){return escHtml(value==null?'—':String(value));}
39
42
  function dashCount(value){return compactNumber(value);}
@@ -47,7 +50,7 @@ function dashReportUrl(a,s){return apiUrl('/dashboard/token-report')+'?agentId='
47
50
  function dashOpenAttrs(a,s,t){return ' data-dash-agent="'+escHtml(a)+'" data-dash-session="'+escHtml(s)+'"'+(t?' data-dash-task="'+escHtml(t)+'"':'');}
48
51
  function dashId(value){return value?'<span class="short-id" title="'+dashText(value)+'">'+dashText(String(value))+'</span>':'<span class="muted">Not assigned</span>';}
49
52
  function dashTable(headers,rows){
50
- const widths=headers[0]==='Agent / Channel'?[170,285,190,140,150,130,175]:headers[0]==='Task / Agent'?[300,140,290,120,120,145,200]:headers[0]==='Agent / Session'?[240,150,150,150,160,180]:[320,180,140];
53
+ const widths=headers[0]==='Agent / Channel'?[170,285,190,140,150,130,175]:headers[0]==='Task / Agent'?[260,120,260,95,95,110,150]:headers[0]==='Agent / Session'?[240,150,150,150,160,180]:[320,180,140];
51
54
  return '<div class="table-wrap"><table class="data-table" style="min-width:'+widths.reduce((a,b)=>a+b,0)+'px"><colgroup>'+widths.map(w=>'<col style="width:'+w+'px">').join('')+'</colgroup><thead><tr>'+headers.map(h=>'<th>'+h+'</th>').join('')+'</tr></thead><tbody>'+(rows.length?rows.join(''):'<tr><td colspan="'+headers.length+'" class="empty">No records in this scope.</td></tr>')+'</tbody></table></div>';
52
55
  }
53
56
  function renderDashboard(data){
@@ -61,18 +64,14 @@ function renderDashboard(data){
61
64
  const stats=[['Recorded sessions',sessions],['Work in progress',taskCount(['running','starting','queued','interrupting','cancel_requested'])],['Waiting for a decision',taskCount(['waiting_input'])],['Loaded agents',agents.length]];
62
65
  document.getElementById('overview-stats').innerHTML=stats.map(([label,n])=>'<div class="dash-stat"><span>'+label+'</span><strong>'+dashCount(n)+'</strong></div>').join('');
63
66
  const attention=agents.flatMap(a=>(a.orchestration?.attention||[]).map(t=>({a,s:{sessionId:t.sessionId},t})));
64
- document.getElementById('overview-attention').innerHTML=attention.length?dashTable(['Task','Agent','Status'],attention.slice(0,8).map(({a,s,t})=>'<tr'+dashOpenAttrs(a.id,s.sessionId,t.taskId)+' tabindex="0" aria-expanded="false"><td>'+dashText(t.title)+'</td><td>'+agentBadge(a.id)+'</td><td>'+dashStatus(t.state)+'</td></tr>')):'<p class="muted">No tasks are waiting for a decision or reconciliation.</p>';
65
- const hourly=Array.from({length:24},()=>({agent:0,worker:0}));let hasUsage=false;
66
- agents.forEach(a=>(a.orchestration?.usageToday||[]).forEach(r=>{if(hourly[r.hour]&&['agent','worker'].includes(r.role)){hourly[r.hour][r.role]+=Number(r.tokens||0);hasUsage=true;}}));
67
- const peak=Math.max(1,...hourly.flatMap(h=>[h.agent,h.worker]));
68
- const points=role=>hourly.map((h,i)=>(i*600/23).toFixed(1)+','+(160-h[role]/peak*140).toFixed(1)).join(' ');
69
- document.getElementById('overview-chart').innerHTML=hasUsage?'<svg viewBox="0 0 600 180" role="img" aria-label="Recorded token activity today in UTC" style="width:100%;height:180px"><path d="M0 20H600M0 90H600M0 160H600" fill="none" stroke="var(--line)" stroke-dasharray="4 5"/><polyline points="'+points('worker')+'" fill="none" stroke="var(--accent)" stroke-width="2"/><polyline points="'+points('agent')+'" fill="none" stroke="var(--blue)" stroke-width="2"/></svg><div class="row between muted small"><span>00:00 UTC</span><span>12:00</span><span>23:00 UTC</span></div>':'<p class="empty">No recorded token usage today.</p>';
67
+ document.getElementById('overview-attention-panel').hidden=!attention.length;
68
+ document.getElementById('overview-attention').innerHTML=attention.length?dashTable(['Task','Agent','Status'],attention.slice(0,8).map(({a,s,t})=>'<tr'+dashOpenAttrs(a.id,s.sessionId,t.taskId)+' tabindex="0" aria-expanded="false"><td>'+dashText(t.title)+gatewayTaskLabel(t)+'</td><td>'+agentBadge(a.id)+'</td><td>'+dashStatus(t.state)+'</td></tr>')):'<p class="muted">No tasks are waiting for a decision or reconciliation.</p>';
70
69
  const sessionRows=rows.map(({a,s})=>'<tr class="session-row"'+(s.orchestration?dashOpenAttrs(a.id,s.sessionId):'')+' tabindex="0" aria-expanded="false" data-row-key="'+escHtml(a.id+':'+s.sessionId)+'"><td>'+agentBadge(a.id)+'<br>'+channelBadge(s.source)+'</td><td><span class="session-id">'+dashText(s.sessionId)+'</span><br><small class="ts">Chat '+dashText(s.chatId)+'</small></td><td><span class="cell-clip" title="'+dashText(s.model)+'">'+dashText(s.model||'—')+'</span></td><td>'+dashStatus(sessionDisplayStatus(s))+'</td><td>'+ (s.orchestration?dashCount(s.tokenSummary?.agentTokens)+' / '+dashCount(s.tokenSummary?.totalTokens):dashCount(s.tokens))+'<br><small class="ts">'+(s.orchestration?'Agent / total · recorded only':'Legacy process tokens')+'</small></td><td class="dash-tools">'+toolInventory(s.loadedTools,s.usedTools,s.contextTools)+'</td><td>'+ (s.orchestration?'<a class="btn-stream" target="_blank" rel="noopener" href="'+escHtml(dashReportUrl(a.id,s.sessionId))+'">View token report ↗</a>':'')+(s.hasPtyStream&&s.isRunning&&s.mode==='pty-shell'?'<button class="btn-stream" data-agent-id="'+escHtml(a.id)+'" data-session-id="'+escHtml(s.sessionId)+'">Terminal</button>':'')+'</td></tr>');
71
70
  document.getElementById('session-results').innerHTML=dashTable(['Agent / Channel','Session / Chat','Model','Status','Tokens','Tools','Inspect'],sessionRows);
72
- const taskRows=tasks.map(({a,s,t})=>'<tr'+dashOpenAttrs(a.id,s.sessionId,t.taskId)+' tabindex="0" aria-expanded="false" data-row-key="'+escHtml(a.id+':'+t.taskId)+'"><td><strong class="dash-task-title">'+dashText(t.title)+'</strong><small class="ts">'+agentBadge(a.id)+' · '+dashId(t.taskId)+'<br>'+channelBadge(s.source)+'</small></td><td>'+dashStatus(t.state)+'</td><td class="session-id">'+dashId(t.workerSessionId)+'<br><small class="ts">Attempt '+dashId(t.attemptId)+'</small></td><td>'+dashCount(t.tokenSummary?.totalTokens)+'<br><small class="ts">Latest attempt</small></td><td>'+dashCount(t.tokenSummary?.allAttemptsTokens)+'<br><small class="ts">All recorded attempts</small></td><td class="dash-tools">'+toolInventory(t.loadedTools,t.usedTools,t.contextTools)+'</td><td><span class="cell-clip" title="'+dashText(t.lastTool?.name)+'">'+dashText(t.lastTool?.name||'No recorded tool')+'</span>'+'<br><small class="ts">'+(t.lastTool?.at?dashText(new Date(t.lastTool.at).toLocaleString()):'')+'</small></td></tr>');
73
- document.getElementById('task-results').innerHTML=dashTable(['Task / Agent','Status','Worker session / Attempt','Latest tokens','Task tokens','Latest attempt tools','Latest activity'],taskRows);
71
+ const taskRows=tasks.map(({a,s,t})=>'<tr'+dashOpenAttrs(a.id,s.sessionId,t.taskId)+' tabindex="0" aria-expanded="false" data-row-key="'+escHtml(a.id+':'+t.taskId)+'"><td><strong class="dash-task-title">'+dashText(t.title)+'</strong>'+gatewayTaskLabel(t)+'<small class="ts">'+agentBadge(a.id)+' · '+dashId(t.taskId)+'<br>'+channelBadge(s.source)+'</small></td><td>'+dashStatus(t.state)+'</td><td class="session-id">'+dashId(t.gatewayTarget?.sessionId||t.workerSessionId)+'<br><small class="ts">Attempt '+dashId(t.attemptId)+'</small></td><td>'+dashCount(t.tokenSummary?.totalTokens)+'<br><small class="ts">Latest attempt</small></td><td>'+dashCount(t.tokenSummary?.allAttemptsTokens)+'<br><small class="ts">All recorded attempts</small></td><td class="dash-tools">'+(t.gatewayTarget?'—':toolInventory(t.loadedTools,t.usedTools,t.contextTools,t.harness))+'</td><td><span class="cell-clip" title="'+dashText(t.lastTool?.name)+'">'+dashText(t.lastTool?.name||'No recorded tool')+'</span>'+'<br><small class="ts">'+(t.lastTool?.at?dashText(new Date(t.lastTool.at).toLocaleString('en-GB',{timeZone:dashboardTimezone})):'')+'</small></td></tr>');
72
+ document.getElementById('task-results').innerHTML=dashTable(['Task / Agent','Status','Session / Attempt','Latest tokens','Task tokens','Latest attempt tools','Latest activity'],taskRows);
74
73
  const recentWork=agents.flatMap(a=>(a.orchestration?.recentWork||[]).map(t=>({a,s:{sessionId:t.sessionId},t}))).sort((x,y)=>Number(y.t.updatedAt)-Number(x.t.updatedAt)||x.t.taskId.localeCompare(y.t.taskId));
75
- document.getElementById('overview-tasks').innerHTML=dashTable(['Task','Agent','Status'],recentWork.slice(0,6).map(({a,s,t})=>'<tr'+dashOpenAttrs(a.id,s.sessionId,t.taskId)+' tabindex="0" aria-expanded="false"><td>'+dashText(t.title)+'</td><td>'+agentBadge(a.id)+'</td><td>'+dashStatus(t.state)+'</td></tr>'));
74
+ document.getElementById('overview-tasks').innerHTML=dashTable(['Task','Agent','Status'],recentWork.slice(0,6).map(({a,s,t})=>'<tr'+dashOpenAttrs(a.id,s.sessionId,t.taskId)+' tabindex="0" aria-expanded="false"><td>'+dashText(t.title)+gatewayTaskLabel(t)+'</td><td>'+agentBadge(a.id)+'</td><td>'+dashStatus(t.state)+'</td></tr>'));
76
75
  document.getElementById('usage-results').innerHTML=dashTable(['Agent / Session','Channel','Agent tokens','Worker tokens','Total tokens','Report'],rows.filter(({s})=>s.orchestration).map(({a,s})=>'<tr'+dashOpenAttrs(a.id,s.sessionId)+' tabindex="0" aria-expanded="false"><td>'+agentBadge(a.id)+'<br>'+dashId(s.sessionId)+'</td><td>'+channelBadge(s.source)+'</td><td>'+dashCount(s.tokenSummary?.agentTokens)+'</td><td>'+dashCount(s.tokenSummary?.workerTokens)+'</td><td>'+dashCount(s.tokenSummary?.totalTokens)+'</td><td><a class="btn-stream" target="_blank" rel="noopener" href="'+escHtml(dashReportUrl(a.id,s.sessionId))+'">View token report ↗</a></td></tr>'));
77
76
 
78
77
  const max=Math.max(0,...agents.map(a=>Number(a.orchestration?.pagination?.total||0)));
@@ -84,7 +83,7 @@ function renderDashboard(data){
84
83
  if(select.dataset.signature!==signature){select.innerHTML='<option value="">All agents</option>'+agents.map(a=>'<option value="'+escHtml(a.id)+'">'+dashText(a.id)+'</option>').join('');select.value=dashboardAgent;select.dataset.signature=signature;}
85
84
  restoreDashboardDetails();
86
85
  for(const record of [...dashboardExpanded.values()])void dashDetail(record.agentId,record.sessionId,record.taskId,record.offset);
87
- document.getElementById('tasks-scope').textContent='Tasks for sessions on the current page. Up to 100 recent tasks per session; open the session to inspect all recorded worker attempts in its token report.';
86
+ document.getElementById('tasks-scope').textContent='Worker and Gateway-managed tasks for sessions on the current page. Up to 100 recent tasks per session. Open a row for its execution details and result; token reports contain measured agent and worker turns.';
88
87
  }
89
88
  async function dashDetail(agentId,sessionId,taskId,offset=0){
90
89
  const key=[agentId,sessionId,taskId||''].join(':');
@@ -100,16 +99,17 @@ async function dashDetail(agentId,sessionId,taskId,offset=0){
100
99
  if(response.status===401){onUnauthorized();return;}
101
100
  if(!response.ok)throw Error('Details unavailable (HTTP '+response.status+').');
102
101
  const detail=await response.json();if(dashboardExpanded.get(key)!==record)return;
103
- let body='<h1>'+dashText(taskId?detail.snapshot.title:'Session details')+'</h1><p class="muted">'+agentBadge(agentId)+' · <span class="session-id">'+dashText(sessionId)+'</span></p><p class="live-note">Recorded snapshot · '+new Date().toLocaleTimeString()+'</p><a class="btn-stream" href="'+escHtml(dashReportUrl(agentId,sessionId))+'" target="_blank" rel="noopener">Open full token report ↗</a>';
102
+ let body='<h1>'+dashText(taskId?detail.snapshot.title:'Session details')+'</h1><p class="muted">'+agentBadge(agentId)+' · <span class="session-id">'+dashText(sessionId)+'</span></p><p class="live-note">Recorded snapshot · '+new Date().toLocaleTimeString('en-GB',{timeZone:dashboardTimezone})+'</p><a class="btn-stream" href="'+escHtml(dashReportUrl(agentId,sessionId))+'" target="_blank" rel="noopener">Open full token report ↗</a>';
104
103
  if(taskId){
105
104
  body+='<h2>Task</h2>'+dashStatus(detail.snapshot.state)+'<pre>'+dashText(detail.instructions||'No assignment text recorded for this task.')+'</pre>';
105
+ if(detail.snapshot.gatewayTarget)body+='<dl><dt>Type</dt><dd>Gateway-managed task</dd><dt>Target</dt><dd>'+dashText(detail.snapshot.gatewayTarget.adapter==='safemode'?'Safemode':detail.snapshot.gatewayTarget.adapter)+' · '+dashText(detail.snapshot.gatewayTarget.name)+'</dd><dt>Native session</dt><dd>'+dashText(detail.snapshot.gatewayTarget.sessionId)+'</dd><dt>Request</dt><dd>'+dashText(detail.snapshot.gatewayDispatch?.requestId)+'</dd></dl><p class="muted">Existing external session. No model worker is created; its tokens and tools are not measured as worker usage.</p>';
106
106
  if(detail.snapshot.result)body+='<h2>Latest result</h2><pre>'+dashText(detail.snapshot.result.summary||JSON.stringify(detail.snapshot.result,null,2))+'</pre>';
107
- body+='<h2>Worker attempts</h2><p class="muted">'+detail.totalAttempts+' attempts · displaying '+(offset+1)+'–'+Math.min(offset+25,detail.totalAttempts)+'</p>';
108
- body+=detail.attempts.map(a=>'<section class="detail-block"><h3>Attempt '+dashText(a.generation)+' · '+dashText(a.state)+'</h3><dl><dt>Attempt ID</dt><dd>'+dashText(a.attemptId)+'</dd><dt>Worker ID</dt><dd>'+dashText(a.workerId)+'</dd><dt>Worker session</dt><dd>'+dashText(a.sessionId)+'</dd><dt>Model</dt><dd>'+dashText(a.metrics?.model)+'</dd><dt>Recorded tokens</dt><dd>'+dashCount(a.metrics?.usage?.totalTokens)+'</dd></dl>'+toolInventory(a.metrics?.loadedTools,a.metrics?.usedTools,a.metrics?.contextTools)+(a.metrics?.contextTools?'<h3>Loaded tools</h3>'+toolNameList(a.metrics.contextTools):'')+'<h3>Used tools</h3>'+toolNameList(a.metrics?.usedTools)+'<h3>Latest recorded events</h3>'+a.events.map(e=>'<section class="detail-block"><h3>'+dashText(new Date(e.at).toLocaleString())+' · '+dashText(e.type)+'</h3><pre>'+dashText(JSON.stringify(e.payload,null,2))+'</pre></section>').join('')+'</section>').join('');
107
+ body+='<h2>'+(detail.snapshot.gatewayTarget?'Gateway-managed requests':'Worker attempts')+'</h2><p class="muted">'+detail.totalAttempts+(detail.snapshot.gatewayTarget?' requests':' attempts')+' · displaying '+(detail.totalAttempts?offset+1:0)+'–'+Math.min(offset+25,detail.totalAttempts)+'</p>';
108
+ body+=detail.attempts.map(a=>detail.snapshot.gatewayTarget?'<section class="detail-block"><h3>Request '+dashText(a.generation)+' · '+dashText(a.state)+'</h3><dl><dt>Attempt ID</dt><dd>'+dashText(a.attemptId)+'</dd><dt>Native session</dt><dd>'+dashText(a.sessionId)+'</dd></dl>'+(a.failure?'<pre>'+dashText(a.failure.code+': '+a.failure.message)+'</pre>':'')+'</section>':'<section class="detail-block"><h3>Attempt '+dashText(a.generation)+' · '+dashText(a.state)+'</h3><dl><dt>Attempt ID</dt><dd>'+dashText(a.attemptId)+'</dd><dt>Worker ID</dt><dd>'+dashText(a.workerId)+'</dd><dt>Worker session</dt><dd>'+dashText(a.sessionId)+'</dd><dt>Harness</dt><dd>'+dashText(a.harness==='codex'?'Codex':a.harness==='claude'?'Claude Code':null)+'</dd><dt>Model</dt><dd>'+dashText(a.harnessModel||a.metrics?.model)+'</dd><dt>Recorded tokens</dt><dd>'+dashCount(a.metrics?.usage?.totalTokens)+'</dd></dl>'+codexContextHtml(a.metrics?.contextWindow)+toolInventory(a.metrics?.loadedTools,a.metrics?.usedTools,a.metrics?.contextTools,a.harness)+(a.metrics?.contextTools?'<h3>Loaded tools</h3>'+toolNameList(a.metrics.contextTools):'')+'<h3>Used tools</h3>'+toolNameList(a.metrics?.usedTools,a.harness)+'<h3>Latest recorded events</h3>'+a.events.map(e=>'<section class="detail-block"><h3>'+dashText(new Date(e.at).toLocaleString('en-GB',{timeZone:dashboardTimezone}))+' · '+dashText(e.type)+'</h3><pre>'+dashText(JSON.stringify(e.payload,null,2))+'</pre></section>').join('')+'</section>').join('');
109
109
  if(offset>0)body+='<button data-attempt-page="'+Math.max(0,offset-25)+'">Newer attempts</button>';
110
110
  if(offset+25<detail.totalAttempts)body+='<button data-attempt-page="'+(offset+25)+'">Older attempts</button>';
111
111
  }else{
112
- body+='<h2>Session</h2><dl><dt>Channel</dt><dd>'+channelBadge(detail.session?.source)+'</dd><dt>Chat</dt><dd>'+dashText(detail.session?.chatId)+'</dd><dt>Created</dt><dd>'+dashText(detail.session?.createdAt?new Date(detail.session.createdAt).toLocaleString():null)+'</dd></dl>';
112
+ body+='<h2>Session</h2><dl><dt>Channel</dt><dd>'+channelBadge(detail.session?.source)+'</dd><dt>Chat</dt><dd>'+dashText(detail.session?.chatId)+'</dd><dt>Created</dt><dd>'+dashText(detail.session?.createdAt?new Date(detail.session.createdAt).toLocaleString('en-GB',{timeZone:dashboardTimezone}):null)+'</dd></dl>';
113
113
  var uBy=detail.usageByRole||[];
114
114
  var uAgent=uBy.find(function(u){return u.role==='agent';}),uWorker=uBy.find(function(u){return u.role==='worker';});
115
115
  var cachedLineFor=function(u){if(!u)return '';var read=Number(u.cacheReadTokens||0),base=Number(u.inputTokens||0)+read+Number(u.cacheCreationTokens||0);return '<span class="card-cached">Cached: <b>'+(base?(read/base*100).toFixed(2):'0.00')+'%</b></span>';};
@@ -118,8 +118,8 @@ async function dashDetail(agentId,sessionId,taskId,offset=0){
118
118
  var detailActivity=detail.activityStatus||'';
119
119
  var cwStopped=detailActivity==='stopped';
120
120
  body+='<div class="dash-grid session-token-totals"><div class="dash-stat box-context"><span>Context window</span><strong>'+(cwStopped?'-':(cw?dashCount(cw.used)+' / '+(cw.total==null?'—':windowCap(cw.total)):'—'))+'</strong>'+((!cwStopped&&cw&&cw.model)?'<span class="card-cached">Model: '+escHtml(cw.model)+'</span>':'')+'</div><div class="dash-stat box-agent"><span>Agent tokens</span><strong>'+dashCount(detail.totals.agentTokens)+'</strong>'+cachedLineFor(uAgent)+'</div><div class="dash-stat box-worker"><span>Worker tokens</span><strong>'+dashCount(detail.totals.workerTokens)+'</strong>'+cachedLineFor(uWorker)+'</div></div><p class="live-note">Recorded turns only. Missing measurements are shown as —, not zero. Token volume is not billing cost.</p>';
121
- body+='<details class="detail-block turn-disclosure session-tasks" data-detail-turn="section:tasks"><summary>Tasks ('+dashCount(detail.totalTasks)+')</summary><div class="dash-mini-list">'+(detail.tasks||[]).map(t=>'<div class="session-task-row"><span class="session-task-title">'+dashText(t.title)+'</span>'+dashStatus(t.state)+'</div>').join('')+(!detail.tasks?.length?'<p class="muted">No tasks recorded.</p>':'')+'</div></details><h2>Turns & worker attempts</h2>';
122
- body+=detail.turns.map(t=>'<details class="detail-block turn-disclosure" data-detail-turn="'+dashText(t.id)+'"><summary>'+dashText(t.role)+' · '+dashText(t.category)+' · '+dashText(new Date(t.startedAt).toLocaleString())+' · '+dashCount(t.usage?.totalTokens)+' tokens</summary><p class="live-note">'+dashText(t.id)+' · '+dashText(t.model)+' · '+dashText(t.state)+'</p>'+(t.taskId?'<p>Task '+dashText(t.taskId)+'</p>':'')+toolInventory(t.loadedTools,t.usedTools,t.contextTools)+(t.contextTools?'<h3>Loaded tools</h3>'+toolNameList(t.contextTools):'')+'<h3>Used tools</h3>'+toolNameList(t.usedTools)+(t.inputTexts||[]).map(text=>'<pre>'+dashText(text)+'</pre>').join('')+(t.responseText?'<h3>Response / result</h3><pre>'+dashText(t.responseText)+'</pre>':'')+'</details>').join('');
121
+ body+='<details class="detail-block turn-disclosure session-tasks" data-detail-turn="section:tasks"><summary>Tasks ('+dashCount(detail.totalTasks)+')</summary><div class="dash-mini-list">'+(detail.tasks||[]).map(t=>'<div class="session-task-row"><span class="session-task-title">'+dashText(t.title)+gatewayTaskLabel(t)+'</span>'+dashStatus(t.state)+'</div>').join('')+(!detail.tasks?.length?'<p class="muted">No tasks recorded.</p>':'')+'</div></details><h2>Turns & worker attempts</h2>';
122
+ body+=detail.turns.map(t=>'<details class="detail-block turn-disclosure" data-detail-turn="'+dashText(t.id)+'"><summary>'+dashText(t.role)+' · '+dashText(t.category)+' · '+dashText(new Date(t.startedAt).toLocaleString('en-GB',{timeZone:dashboardTimezone}))+' · '+dashCount(t.usage?.totalTokens)+' tokens</summary><p class="live-note">'+dashText(t.id)+' · '+dashText(t.model)+' · '+dashText(t.state)+'</p>'+(t.role==='worker'?'<p>Harness: '+dashText(t.harness==='codex'?'Codex':t.harness==='claude'?'Claude Code':null)+'</p>':'')+(t.taskId?'<p>Task '+dashText(t.taskId)+'</p>':'')+codexContextHtml(t.contextWindow)+(t.gatewayTarget?'—':toolInventory(t.loadedTools,t.usedTools,t.contextTools,t.harness))+(t.contextTools?'<h3>Loaded tools</h3>'+toolNameList(t.contextTools):'')+'<h3>Used tools</h3>'+toolNameList(t.usedTools,t.harness)+(t.inputTexts||[]).map(text=>'<pre>'+dashText(text)+'</pre>').join('')+(t.responseText?'<h3>Response / result</h3><pre>'+dashText(t.responseText)+'</pre>':'')+'</details>').join('');
123
123
  if(!detail.turns.length)body+='<p class="empty">No instrumented turns recorded on this page.</p>';
124
124
  if(offset>0)body+='<button data-session-page="'+Math.max(0,offset-50)+'">Previous records</button>';
125
125
  if(offset+50<Math.max(detail.totalTasks||0,detail.pagination?.total||0))body+='<button data-session-page="'+(offset+50)+'">Next records</button>';
@@ -130,10 +130,10 @@ async function dashDetail(agentId,sessionId,taskId,offset=0){
130
130
  function restoreDashboardDetails(){
131
131
  const record=[...dashboardExpanded.values()][0];
132
132
  const back=document.getElementById('dash-drawer-back'),panel=document.getElementById('dash-drawer');
133
- back.classList.toggle('open',Boolean(record));document.body.style.overflow=record?'hidden':'';
133
+ back.classList.toggle('open',Boolean(record));document.body.style.overflow=record||document.getElementById('memory-back')?.classList.contains('open')?'hidden':'';
134
134
  document.querySelectorAll('tr[data-dash-agent]').forEach(row=>row.setAttribute('aria-expanded',String(Boolean(record&&row.dataset.dashAgent===record.agentId&&row.dataset.dashSession===record.sessionId&&(row.dataset.dashTask||'')===(record.taskId||'')))));
135
135
  if(!record){panel.innerHTML='';delete panel.dataset.html;return;}
136
- const html='<button data-dash-close aria-label="Close details">Close ×</button>'+record.html;
136
+ const html=dashboardCloseButton('dash')+record.html;
137
137
  if(panel.dataset.html!==html){
138
138
  const scroll=panel.scrollTop,focused=panel.contains(document.activeElement),closeFocused=document.activeElement?.hasAttribute('data-dash-close');
139
139
  const sameDetail=panel.dataset.agent===record.agentId&&panel.dataset.session===record.sessionId&&panel.dataset.task===(record.taskId||'');
@@ -161,7 +161,6 @@ document.addEventListener('click',function(e){
161
161
  updateSidebarToggle();
162
162
  }
163
163
  if(e.target.closest('.tab')){const view=e.target.closest('.tab').dataset.view;document.querySelector('.dash-filter').hidden=['view-overview','view-kb','view-system'].includes(view);document.getElementById('dash-search').hidden=view==='view-dreams';document.getElementById('dash-agent-filter').hidden=view==='view-dreams';document.querySelector('.dash-pager').hidden=['view-overview','view-kb','view-dreams','view-system'].includes(view);document.body.classList.remove('menuopen');updateSidebarToggle();document.getElementById('dash-current-view').textContent=e.target.closest('.tab').textContent.trim();if(e.target.closest('.tab').dataset.view==='view-system')refreshProcesses();}
164
- if(e.target.closest('#dash-theme')){const root=document.documentElement;root.dataset.theme=root.dataset.theme==='dark'?'light':'dark';}
165
164
  });
166
165
  document.addEventListener('keydown',function(e){
167
166
  if(e.target.id==='sidebar-brand'&&(e.key==='Enter'||e.key===' ')){e.preventDefault();e.target.click();return;}
@@ -1 +1 @@
1
- {"version":3,"file":"dashboard-client.js","sourceRoot":"","sources":["../../src/ui/dashboard-client.ts"],"names":[],"mappings":";;;AAAA,uDAAmE;AACnE,qEAAuE;AACvE,gFAAgF;AACnE,QAAA,eAAe,GAAG,oDAA2B,GAAG,gCAAc,CAAC,QAAQ,EAAE,GAAC,GAAG,GAAC,gCAAc,CAAC,QAAQ,EAAE,GAAC,GAAG,GAAE,MAAM,CAAC,GAAG,CAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;CAoLnI,CAAC"}
1
+ {"version":3,"file":"dashboard-client.js","sourceRoot":"","sources":["../../src/ui/dashboard-client.ts"],"names":[],"mappings":";;;AAAA,mDAAmD;AACnD,yDAA2D;AAC3D,uDAAmE;AACnE,qEAAuE;AACvE,gFAAgF;AACnE,QAAA,eAAe,GAAG,gCAAgB,CAAC,QAAQ,EAAE,GAAC,GAAG,GAAC,oDAA2B,GAAG,gCAAc,CAAC,QAAQ,EAAE,GAAC,GAAG,GAAC,gCAAc,CAAC,QAAQ,EAAE,GAAC,GAAG,GAAE,wCAAqB,GAAG,MAAM,CAAC,GAAG,CAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;CAiL3L,CAAC"}
@@ -0,0 +1,4 @@
1
+ /** Shared controls for dashboard pages and standalone reports. */
2
+ export declare function themeButtonHtml(id: 'dash-theme' | 'report-theme'): string;
3
+ export declare const dashboardControlsClient: string;
4
+ //# sourceMappingURL=dashboard-controls.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"dashboard-controls.d.ts","sourceRoot":"","sources":["../../src/ui/dashboard-controls.ts"],"names":[],"mappings":"AAAA,kEAAkE;AAClE,wBAAgB,eAAe,CAAC,EAAE,EAAE,YAAY,GAAG,cAAc,GAAG,MAAM,CAEzE;AACD,eAAO,MAAM,uBAAuB,QAiBnC,CAAC"}
@@ -0,0 +1,27 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.dashboardControlsClient = void 0;
4
+ exports.themeButtonHtml = themeButtonHtml;
5
+ /** Shared controls for dashboard pages and standalone reports. */
6
+ function themeButtonHtml(id) {
7
+ return `<button type="button" class="theme-toggle" id="${id}" data-theme-toggle aria-label="Switch to dark theme" title="Switch to dark theme"><svg class="theme-moon" width="18" height="18" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.7" aria-hidden="true"><path d="M20.5 13A8.5 8.5 0 0 1 11 3.5 8.5 8.5 0 1 0 20.5 13Z"/></svg><svg class="theme-sun" width="18" height="18" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.7" aria-hidden="true"><circle cx="12" cy="12" r="4"/><path d="M12 2v2m0 16v2M2 12h2m16 0h2M5 5l1.5 1.5m11 11L19 19M5 19l1.5-1.5m11-11L19 5"/></svg></button>`;
8
+ }
9
+ exports.dashboardControlsClient = String.raw `
10
+ function dashboardCloseButton(action){
11
+ return '<div class="drawer-actions"><button type="button" class="drawer-close" data-'+action+'-close aria-label="Close details">Close ×</button></div>';
12
+ }
13
+ (function(){
14
+ const key='gateway-dashboard-theme';
15
+ function apply(theme){
16
+ document.documentElement.dataset.theme=theme;
17
+ document.querySelectorAll('[data-theme-toggle]').forEach(button=>{const label=theme==='dark'?'Switch to light theme':'Switch to dark theme';button.setAttribute('aria-label',label);button.title=label;});
18
+ }
19
+ try{const saved=localStorage.getItem(key);apply(saved==='dark'?'dark':'light');}catch{apply(document.documentElement.dataset.theme||'light');}
20
+ document.addEventListener('click',event=>{
21
+ if(!event.target.closest('[data-theme-toggle]'))return;
22
+ const theme=document.documentElement.dataset.theme==='dark'?'light':'dark';apply(theme);try{localStorage.setItem(key,theme);}catch{}
23
+ });
24
+ window.addEventListener('storage',event=>{if(event.key===key)apply(event.newValue==='dark'?'dark':'light');});
25
+ })();
26
+ `;
27
+ //# sourceMappingURL=dashboard-controls.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"dashboard-controls.js","sourceRoot":"","sources":["../../src/ui/dashboard-controls.ts"],"names":[],"mappings":";;;AACA,0CAEC;AAHD,kEAAkE;AAClE,SAAgB,eAAe,CAAC,EAAiC;IAC/D,OAAO,kDAAkD,EAAE,sjBAAsjB,CAAC;AACpnB,CAAC;AACY,QAAA,uBAAuB,GAAG,MAAM,CAAC,GAAG,CAAA;;;;;;;;;;;;;;;;;CAiBhD,CAAC"}
@@ -1,9 +1,12 @@
1
+ /** Chart palette shared with the Context bootstrap report. */
2
+ export declare const dashboardChartPalette: string[];
1
3
  /** Shared display-only formatting; stored values and identifiers remain unchanged. */
2
4
  export declare function compactNumber(value: unknown): string;
3
5
  export declare function dashboardEscape(value: unknown): string;
6
+ export declare function agentHue(value: string): number;
4
7
  export declare function agentBadge(value: string): string;
5
8
  export declare function channelBadge(value: string): string;
6
9
  export declare function taskStatusBadge(value: string): string;
7
- export declare function toolNameList(names: string[] | null | undefined): string;
10
+ export declare function toolNameList(names: string[] | null | undefined, harness?: string): string;
8
11
  export declare const dashboardPresentationClient: string;
9
12
  //# sourceMappingURL=dashboard-presentation.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"dashboard-presentation.d.ts","sourceRoot":"","sources":["../../src/ui/dashboard-presentation.ts"],"names":[],"mappings":"AAAA,sFAAsF;AACtF,wBAAgB,aAAa,CAAC,KAAK,EAAE,OAAO,GAAG,MAAM,CAMpD;AAKD,wBAAgB,eAAe,CAAC,KAAK,EAAE,OAAO,GAAG,MAAM,CAEtD;AACD,wBAAgB,UAAU,CAAC,KAAK,EAAE,MAAM,GAAG,MAAM,CAGhD;AACD,wBAAgB,YAAY,CAAC,KAAK,EAAE,MAAM,GAAG,MAAM,CAKlD;AACD,wBAAgB,eAAe,CAAC,KAAK,EAAE,MAAM,GAAG,MAAM,CAKrD;AACD,wBAAgB,YAAY,CAAC,KAAK,EAAE,MAAM,EAAE,GAAG,IAAI,GAAG,SAAS,GAAG,MAAM,CAIvE;AACD,eAAO,MAAM,2BAA2B,QAAsO,CAAC"}
1
+ {"version":3,"file":"dashboard-presentation.d.ts","sourceRoot":"","sources":["../../src/ui/dashboard-presentation.ts"],"names":[],"mappings":"AAAA,8DAA8D;AAC9D,eAAO,MAAM,qBAAqB,UAAsG,CAAC;AACzI,sFAAsF;AACtF,wBAAgB,aAAa,CAAC,KAAK,EAAE,OAAO,GAAG,MAAM,CAMpD;AAKD,wBAAgB,eAAe,CAAC,KAAK,EAAE,OAAO,GAAG,MAAM,CAEtD;AACD,wBAAgB,QAAQ,CAAC,KAAK,EAAE,MAAM,GAAG,MAAM,CAG9C;AACD,wBAAgB,UAAU,CAAC,KAAK,EAAE,MAAM,GAAG,MAAM,CAEhD;AACD,wBAAgB,YAAY,CAAC,KAAK,EAAE,MAAM,GAAG,MAAM,CAKlD;AACD,wBAAgB,eAAe,CAAC,KAAK,EAAE,MAAM,GAAG,MAAM,CAKrD;AACD,wBAAgB,YAAY,CAAC,KAAK,EAAE,MAAM,EAAE,GAAG,IAAI,GAAG,SAAS,EAAE,OAAO,CAAC,EAAE,MAAM,GAAG,MAAM,CAIzF;AACD,eAAO,MAAM,2BAA2B,QAAuU,CAAC"}
@@ -1,12 +1,15 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
- exports.dashboardPresentationClient = void 0;
3
+ exports.dashboardPresentationClient = exports.dashboardChartPalette = void 0;
4
4
  exports.compactNumber = compactNumber;
5
5
  exports.dashboardEscape = dashboardEscape;
6
+ exports.agentHue = agentHue;
6
7
  exports.agentBadge = agentBadge;
7
8
  exports.channelBadge = channelBadge;
8
9
  exports.taskStatusBadge = taskStatusBadge;
9
10
  exports.toolNameList = toolNameList;
11
+ /** Chart palette shared with the Context bootstrap report. */
12
+ exports.dashboardChartPalette = ['#e98524', '#8e65d1', '#258fca', '#cf528b', '#359986', '#c19527', '#5c78d2', '#b66645', '#77843f', '#986499'];
10
13
  /** Shared display-only formatting; stored values and identifiers remain unchanged. */
11
14
  function compactNumber(value) {
12
15
  if (value == null)
@@ -27,11 +30,14 @@ const channelIcons = { "telegram": "<svg role=\"img\" viewBox=\"0 0 24 24\" xmln
27
30
  function dashboardEscape(value) {
28
31
  return String(value ?? '').replace(/[&<>"']/g, c => ({ '&': '&amp;', '<': '&lt;', '>': '&gt;', '"': '&quot;', "'": '&#39;' }[c]));
29
32
  }
30
- function agentBadge(value) {
33
+ function agentHue(value) {
31
34
  let hash = 0;
32
35
  for (const ch of value)
33
36
  hash = (hash * 31 + ch.charCodeAt(0)) >>> 0;
34
- return '<span class="identity-badge" style="--agent-hue:' + (hash % 360) + '" title="' + dashboardEscape(value) + '">' + dashboardEscape(value) + '</span>';
37
+ return hash % 360;
38
+ }
39
+ function agentBadge(value) {
40
+ return '<span class="identity-badge" style="--agent-hue:' + agentHue(value) + '" title="' + dashboardEscape(value) + '">' + dashboardEscape(value) + '</span>';
35
41
  }
36
42
  function channelBadge(value) {
37
43
  const key = String(value || 'unknown').toLowerCase();
@@ -41,16 +47,16 @@ function channelBadge(value) {
41
47
  }
42
48
  function taskStatusBadge(value) {
43
49
  const state = String(value || 'unknown');
44
- const colors = { running: '#e07a1e', working: '#e07a1e', thinking: '#d6459b', completed: '#24834a', succeeded: '#24834a', success: '#24834a', failed: '#c73946', queued: '#a16c11', starting: '#4d63c9', recovering: '#188b80', ended: '#607244', waiting_input: '#ba681c', needs_reconciliation: '#b345a4', cancel_requested: '#8c603c', interrupting: '#9e4d76', interrupted: '#7c6352', cancelled: '#657080', stopped: '#65605a', idle: '#287fc2', compacting: '#7655bd', unknown: '#737373' };
50
+ const colors = { pending: '#a16c11', skipped: '#657080', accepted: '#24834a', partial_failure: '#c73946', running: '#e07a1e', working: '#e07a1e', thinking: '#d6459b', completed: '#24834a', succeeded: '#24834a', success: '#24834a', failed: '#c73946', queued: '#a16c11', starting: '#4d63c9', recovering: '#188b80', ended: '#607244', waiting_input: '#ba681c', needs_reconciliation: '#b345a4', cancel_requested: '#8c603c', interrupting: '#9e4d76', interrupted: '#7c6352', cancelled: '#657080', stopped: '#65605a', idle: '#287fc2', compacting: '#7655bd', unknown: '#737373' };
45
51
  const color = colors[state] || '#737373';
46
52
  return '<span class="badge status-badge" style="--status-color:' + color + '">' + dashboardEscape(state.replace(/_/g, ' ').replace(/^./, c => c.toUpperCase())) + '</span>';
47
53
  }
48
- function toolNameList(names) {
54
+ function toolNameList(names, harness) {
49
55
  if (!Array.isArray(names))
50
56
  return '<p class="muted">—</p>';
51
57
  if (!names.length)
52
58
  return '<p class="muted">None</p>';
53
- return '<ul class="tool-name-list">' + [...new Set(names)].sort().map(name => '<li><code>' + dashboardEscape(name) + '</code></li>').join('') + '</ul>';
59
+ return '<ul class="tool-name-list">' + [...new Set(names)].sort().map(name => '<li><code>' + dashboardEscape(harness === 'codex' && name === 'Bash' ? 'Shell' : name) + '</code></li>').join('') + '</ul>';
54
60
  }
55
- exports.dashboardPresentationClient = compactNumber.toString() + ';' + 'const channelIcons=' + JSON.stringify(channelIcons) + ';' + dashboardEscape.toString() + ';' + agentBadge.toString() + ';' + channelBadge.toString() + ';' + taskStatusBadge.toString() + ';' + toolNameList.toString() + ';';
61
+ exports.dashboardPresentationClient = 'const dashboardChartPalette=' + JSON.stringify(exports.dashboardChartPalette) + ';' + compactNumber.toString() + ';' + 'const channelIcons=' + JSON.stringify(channelIcons) + ';' + dashboardEscape.toString() + ';' + agentHue.toString() + ';' + agentBadge.toString() + ';' + channelBadge.toString() + ';' + taskStatusBadge.toString() + ';' + toolNameList.toString() + ';';
56
62
  //# sourceMappingURL=dashboard-presentation.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"dashboard-presentation.js","sourceRoot":"","sources":["../../src/ui/dashboard-presentation.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"dashboard-presentation.js","sourceRoot":"","sources":["../../src/ui/dashboard-presentation.ts"],"names":[],"mappings":"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"}
@@ -1,5 +1,5 @@
1
- /** Calendar windows include today, starting at 00:00 UTC. */
1
+ /** Calendar windows include today, starting at 00:00 in the configured timezone (UTC by default). */
2
2
  export declare function dashboardRange(value: unknown): string;
3
- export declare function dashboardSince(value: unknown, now?: number): number;
4
- export declare function rangeButtons(id: string, selected: string): string;
3
+ export declare function dashboardSince(value: unknown, now?: number, timezone?: string): number;
4
+ export declare function rangeButtons(id: string, selected: string, timezone?: string): string;
5
5
  //# sourceMappingURL=dashboard-range.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"dashboard-range.d.ts","sourceRoot":"","sources":["../../src/ui/dashboard-range.ts"],"names":[],"mappings":"AAAA,6DAA6D;AAC7D,wBAAgB,cAAc,CAAC,KAAK,EAAE,OAAO,GAAG,MAAM,CAErD;AACD,wBAAgB,cAAc,CAAC,KAAK,EAAE,OAAO,EAAE,GAAG,SAAa,GAAG,MAAM,CAKvE;AACD,wBAAgB,YAAY,CAAC,EAAE,EAAE,MAAM,EAAE,QAAQ,EAAE,MAAM,GAAG,MAAM,CAEjE"}
1
+ {"version":3,"file":"dashboard-range.d.ts","sourceRoot":"","sources":["../../src/ui/dashboard-range.ts"],"names":[],"mappings":"AAAA,qGAAqG;AACrG,wBAAgB,cAAc,CAAC,KAAK,EAAE,OAAO,GAAG,MAAM,CAErD;AACD,wBAAgB,cAAc,CAAC,KAAK,EAAE,OAAO,EAAE,GAAG,SAAa,EAAE,QAAQ,SAAQ,GAAG,MAAM,CAmBzF;AACD,wBAAgB,YAAY,CAAC,EAAE,EAAE,MAAM,EAAE,QAAQ,EAAE,MAAM,EAAE,QAAQ,SAAQ,GAAG,MAAM,CAGnF"}
@@ -3,18 +3,34 @@ Object.defineProperty(exports, "__esModule", { value: true });
3
3
  exports.dashboardRange = dashboardRange;
4
4
  exports.dashboardSince = dashboardSince;
5
5
  exports.rangeButtons = rangeButtons;
6
- /** Calendar windows include today, starting at 00:00 UTC. */
6
+ /** Calendar windows include today, starting at 00:00 in the configured timezone (UTC by default). */
7
7
  function dashboardRange(value) {
8
8
  return typeof value === 'string' && ['24h', '7d', '30d', '90d', 'all'].includes(value) ? value : '24h';
9
9
  }
10
- function dashboardSince(value, now = Date.now()) {
10
+ function dashboardSince(value, now = Date.now(), timezone = 'UTC') {
11
11
  const range = dashboardRange(value);
12
12
  if (range === 'all')
13
13
  return 0;
14
14
  const days = range === '24h' ? 1 : Number(range.slice(0, -1));
15
- return Math.floor(now / 86400000) * 86400000 - (days - 1) * 86400000;
15
+ const parts = new Intl.DateTimeFormat('en-CA', { timeZone: timezone, year: 'numeric', month: '2-digit', day: '2-digit' }).formatToParts(now);
16
+ const part = (name) => Number(parts.find(p => p.type === name).value);
17
+ const target = Date.UTC(part('year'), part('month') - 1, part('day') - (days - 1));
18
+ // Resolve midnight in the configured zone, including changes in UTC offset.
19
+ let instant = target;
20
+ const clock = new Intl.DateTimeFormat('en-GB', { timeZone: timezone, year: 'numeric', month: '2-digit', day: '2-digit', hour: '2-digit', minute: '2-digit', second: '2-digit', hourCycle: 'h23' });
21
+ for (let i = 0; i < 4; i++) {
22
+ const values = clock.formatToParts(instant);
23
+ const v = (name) => Number(values.find(p => p.type === name).value);
24
+ const local = Date.UTC(v('year'), v('month') - 1, v('day'), v('hour'), v('minute'), v('second'));
25
+ const next = instant + target - local;
26
+ if (next === instant)
27
+ break;
28
+ instant = next;
29
+ }
30
+ return instant;
16
31
  }
17
- function rangeButtons(id, selected) {
18
- return '<div id="' + id + '" class="range-toggle" role="group" aria-label="Date range, from midnight UTC">' + ['24h', '7d', '30d', '90d', 'all'].map(value => '<button type="button" data-range="' + value + '" aria-pressed="' + (value === selected) + '" title="' + (value === '24h' ? 'Today from 00:00 UTC' : value === 'all' ? 'All recorded history' : value + ' including today, from 00:00 UTC') + '">' + value + '</button>').join('') + '</div>';
32
+ function rangeButtons(id, selected, timezone = 'UTC') {
33
+ timezone = timezone.replace(/[^A-Za-z0-9_+\/.-]/g, '');
34
+ return '<div id="' + id + '" class="range-toggle" role="group" aria-label="Date range, from midnight ' + timezone + '">' + ['24h', '7d', '30d', '90d', 'all'].map(value => '<button type="button" data-range="' + value + '" aria-pressed="' + (value === selected) + '" title="' + (value === '24h' ? 'Today from 00:00 ' + timezone : value === 'all' ? 'All recorded history' : value + ' including today, from 00:00 ' + timezone) + '">' + value + '</button>').join('') + '</div>';
19
35
  }
20
36
  //# sourceMappingURL=dashboard-range.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"dashboard-range.js","sourceRoot":"","sources":["../../src/ui/dashboard-range.ts"],"names":[],"mappings":";;AACA,wCAEC;AACD,wCAKC;AACD,oCAEC;AAZD,6DAA6D;AAC7D,SAAgB,cAAc,CAAC,KAAc;IAC5C,OAAO,OAAO,KAAK,KAAK,QAAQ,IAAI,CAAC,KAAK,EAAC,IAAI,EAAC,KAAK,EAAC,KAAK,EAAC,KAAK,CAAC,CAAC,QAAQ,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC,CAAC,KAAK,CAAC;AACpG,CAAC;AACD,SAAgB,cAAc,CAAC,KAAc,EAAE,GAAG,GAAG,IAAI,CAAC,GAAG,EAAE;IAC9D,MAAM,KAAK,GAAG,cAAc,CAAC,KAAK,CAAC,CAAC;IACpC,IAAI,KAAK,KAAK,KAAK;QAAE,OAAO,CAAC,CAAC;IAC9B,MAAM,IAAI,GAAG,KAAK,KAAK,KAAK,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,MAAM,CAAC,KAAK,CAAC,KAAK,CAAC,CAAC,EAAC,CAAC,CAAC,CAAC,CAAC,CAAC;IAC7D,OAAO,IAAI,CAAC,KAAK,CAAC,GAAG,GAAG,QAAQ,CAAC,GAAG,QAAQ,GAAG,CAAC,IAAI,GAAG,CAAC,CAAC,GAAG,QAAQ,CAAC;AACtE,CAAC;AACD,SAAgB,YAAY,CAAC,EAAU,EAAE,QAAgB;IACxD,OAAO,WAAW,GAAC,EAAE,GAAC,iFAAiF,GAAC,CAAC,KAAK,EAAC,IAAI,EAAC,KAAK,EAAC,KAAK,EAAC,KAAK,CAAC,CAAC,GAAG,CAAC,KAAK,CAAA,EAAE,CAAA,oCAAoC,GAAC,KAAK,GAAC,kBAAkB,GAAC,CAAC,KAAK,KAAG,QAAQ,CAAC,GAAC,WAAW,GAAC,CAAC,KAAK,KAAG,KAAK,CAAA,CAAC,CAAA,sBAAsB,CAAA,CAAC,CAAA,KAAK,KAAG,KAAK,CAAA,CAAC,CAAA,sBAAsB,CAAA,CAAC,CAAA,KAAK,GAAC,kCAAkC,CAAC,GAAC,IAAI,GAAC,KAAK,GAAC,WAAW,CAAC,CAAC,IAAI,CAAC,EAAE,CAAC,GAAC,QAAQ,CAAC;AAC/Y,CAAC"}
1
+ {"version":3,"file":"dashboard-range.js","sourceRoot":"","sources":["../../src/ui/dashboard-range.ts"],"names":[],"mappings":"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"}