@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
@@ -38,11 +38,13 @@ var __importDefault = (this && this.__importDefault) || function (mod) {
38
38
  Object.defineProperty(exports, "__esModule", { value: true });
39
39
  exports.GatewayRouter = void 0;
40
40
  exports.resolveBindHost = resolveBindHost;
41
+ const dashboard_processes_1 = require("./dashboard-processes");
42
+ const dashboard_sessions_1 = require("./dashboard-sessions");
43
+ const memory_activity_1 = require("./memory-activity");
41
44
  const dashboard_range_1 = require("../ui/dashboard-range");
42
45
  const dashboard_reader_1 = require("../orchestration/dashboard-reader");
43
46
  const express_1 = __importDefault(require("express"));
44
47
  const http = __importStar(require("node:http"));
45
- const child_process_1 = require("child_process");
46
48
  const crypto = __importStar(require("crypto"));
47
49
  const fs = __importStar(require("fs"));
48
50
  const os = __importStar(require("os"));
@@ -231,6 +233,7 @@ class RateLimiter {
231
233
  }
232
234
  class GatewayRouter {
233
235
  constructor(agents, configs, schedulers, gatewayConfig, cronManager, configPath, appsRegistry, appInstaller, appRegistryClient) {
236
+ var _a, _b;
234
237
  this.dashboardReader = new dashboard_reader_1.DashboardReader();
235
238
  this.dashboardStreams = new Set();
236
239
  // ─── App proxy ──────────────────────────────────────────────────────────
@@ -244,10 +247,6 @@ class GatewayRouter {
244
247
  /** Short-lived WS auth tickets: ticket → { agentId, sessionId, expiresAt }. One-time use. */
245
248
  this.ptyStreamTickets = new Map();
246
249
  this.ticketPruner = null;
247
- /** Dashboard session tokens (DASH_SESSION_TTL_MS). Issued at POST /dashboard/login
248
- * and carried by the HttpOnly `dash_session` cookie — never embedded in the HTML,
249
- * so no token is exposed to view-source/XSS. token → expiresAt. */
250
- this.dashboardTokens = new Map();
251
250
  /** Failed-login throttle for /dashboard/login, keyed by client IP.
252
251
  * ip → { count, resetAt }. Blocks brute-forcing configured API keys. */
253
252
  this.loginAttempts = new Map();
@@ -265,8 +264,13 @@ class GatewayRouter {
265
264
  this.agents = agents;
266
265
  this.configs = configs;
267
266
  this.gatewayConfig = gatewayConfig;
267
+ if (gatewayConfig) {
268
+ (_a = gatewayConfig.gateway).api ?? (_a.api = { keys: [] });
269
+ (_b = gatewayConfig.gateway.api).keys ?? (_b.keys = []);
270
+ }
268
271
  this.cronManager = cronManager;
269
272
  this.configPath = configPath;
273
+ this.dashboardSessions = new dashboard_sessions_1.DashboardSessions(configPath ? path.join(path.dirname(configPath), 'dashboard-sessions.db') : undefined);
270
274
  this.appsRegistry = appsRegistry;
271
275
  this.appInstaller = appInstaller;
272
276
  this.appRegistryClient = appRegistryClient;
@@ -318,8 +322,12 @@ class GatewayRouter {
318
322
  const token = parseCookies(req.headers['cookie'])[DASH_SESSION_COOKIE];
319
323
  if (!token)
320
324
  return false;
321
- const exp = this.dashboardTokens.get(token) ?? 0;
322
- return exp > Date.now();
325
+ try {
326
+ return this.dashboardSessions.valid(token, this.apiKeys);
327
+ }
328
+ catch {
329
+ return false;
330
+ } // Unreadable/corrupt auth storage must never grant access.
323
331
  }
324
332
  /**
325
333
  * Gate a dashboard-adjacent endpoint: accept an admin API key OR a live
@@ -620,8 +628,8 @@ class GatewayRouter {
620
628
  path.join(os.homedir(), '.claude-gateway', 'shares.db');
621
629
  const store = new share_store_1.ShareStore(dbPath);
622
630
  this.app.use((0, share_router_1.createSharesPublicRouter)(store, this.agentsRoot()));
623
- if (this.gatewayConfig?.gateway?.api?.keys?.length) {
624
- const publicUrl = (0, url_1.normalizePublicUrl)(this.gatewayConfig?.gateway?.publicUrl) ?? undefined;
631
+ if (this.gatewayConfig?.gateway?.api?.keys) {
632
+ const publicUrl = () => (0, url_1.normalizePublicUrl)(this.gatewayConfig?.gateway?.publicUrl) ?? undefined;
625
633
  this.app.use('/api', (0, share_router_1.createSharesPrivateRouter)(store, this.gatewayConfig.gateway.api.keys, this.agentsRoot(), publicUrl));
626
634
  }
627
635
  }
@@ -661,29 +669,29 @@ class GatewayRouter {
661
669
  res.json({ ticket, expiresAt: new Date(expiresAt).toISOString() });
662
670
  });
663
671
  // Mount API router after body parser so req.body is populated
664
- if (this.gatewayConfig?.gateway?.api?.keys?.length) {
665
- const apiRouter = (0, router_1.createApiRouter)(this.agents, this.configs, this.gatewayConfig.gateway.api.keys, this.configPath, this.gatewayConfig.gateway.models);
672
+ if (this.gatewayConfig?.gateway?.api?.keys) {
673
+ const apiRouter = (0, router_1.createApiRouter)(this.agents, this.configs, this.gatewayConfig.gateway.api.keys, this.configPath, () => this.gatewayConfig?.gateway.models);
666
674
  this.app.use('/api', apiRouter);
667
675
  this.voiceApi = new voice_router_1.VoiceApi(this.agents, this.configs, this.gatewayConfig.gateway.api.keys);
668
676
  this.app.use('/api', this.voiceApi.router);
669
677
  }
670
678
  // Mount workspace file routes
671
- if (this.gatewayConfig?.gateway?.api?.keys?.length) {
679
+ if (this.gatewayConfig?.gateway?.api?.keys) {
672
680
  const workspaceRouter = (0, workspace_router_1.createWorkspaceRouter)(this.configs, this.gatewayConfig.gateway.api.keys);
673
681
  this.app.use('/api', workspaceRouter);
674
682
  }
675
683
  // Mount skills routes
676
- if (this.gatewayConfig?.gateway?.api?.keys?.length) {
684
+ if (this.gatewayConfig?.gateway?.api?.keys) {
677
685
  const skillsRouter = (0, skills_router_1.createSkillsRouter)(this.configs, this.gatewayConfig.gateway.api.keys, this.agents, this.gatewayConfig);
678
686
  this.app.use('/api', skillsRouter);
679
687
  }
680
688
  // Mount package update routes (admin-only)
681
- if (this.gatewayConfig?.gateway?.api?.keys?.length) {
689
+ if (this.gatewayConfig?.gateway?.api?.keys) {
682
690
  const packagesRouter = (0, packages_1.createPackagesRouter)(this.gatewayConfig.gateway.api.keys);
683
691
  this.app.use('/api', packagesRouter);
684
692
  }
685
693
  // Mount connector management routes (connector definitions + secret store + config wiring)
686
- if (this.gatewayConfig?.gateway?.api?.keys?.length) {
694
+ if (this.gatewayConfig?.gateway?.api?.keys) {
687
695
  const connectorsRouter = (0, connectors_router_1.createConnectorsRouter)(this.gatewayConfig.gateway.api.keys, this.configPath, this.agents, this.customConnectorsStore);
688
696
  this.app.use('/api', connectorsRouter);
689
697
  // Admin-gated "start an OAuth sign-in" endpoint for gateway-owned
@@ -695,17 +703,15 @@ class GatewayRouter {
695
703
  // Public (no auth) — this is what the OAuth provider redirects the end
696
704
  // user's own browser to after they sign in. Mounted at the app root, not
697
705
  // under /api, mirroring the /app/:name/:portName proxy below.
698
- this.app.use((0, oauth_connectors_router_1.createOauthCallbackRouter)(this.customConnectorsStore, undefined, typeof this.gatewayConfig?.gateway?.oauthReturnUrl === 'string'
699
- ? this.gatewayConfig.gateway.oauthReturnUrl
700
- : undefined, this.agents));
706
+ this.app.use((0, oauth_connectors_router_1.createOauthCallbackRouter)(this.customConnectorsStore, undefined, () => this.gatewayConfig?.gateway.oauthReturnUrl, this.agents));
701
707
  // Mount cron manager routes with same API key auth as agent router
702
708
  if (this.cronManager) {
703
- const cronRouter = (0, cron_router_1.createCronRouter)(this.cronManager, this.gatewayConfig?.gateway?.api?.keys, new Set(this.configs.keys()));
709
+ const cronRouter = (0, cron_router_1.createCronRouter)(this.cronManager, this.gatewayConfig?.gateway?.api?.keys, () => new Set(this.configs.keys()));
704
710
  this.app.use('/api', cronRouter);
705
711
  }
706
712
  // Mount the route manifest endpoint (GET /api/v1/_meta/routes) — serves the
707
713
  // registry populated by the converted routers above, for CLI cross-checking.
708
- if (this.gatewayConfig?.gateway?.api?.keys?.length) {
714
+ if (this.gatewayConfig?.gateway?.api?.keys) {
709
715
  const metaRouter = (0, meta_router_1.createMetaRouter)(this.gatewayConfig.gateway.api.keys);
710
716
  this.app.use('/api', metaRouter);
711
717
  }
@@ -713,7 +719,7 @@ class GatewayRouter {
713
719
  if (this.appsRegistry &&
714
720
  this.appInstaller &&
715
721
  this.appRegistryClient &&
716
- this.gatewayConfig?.gateway?.api?.keys?.length) {
722
+ this.gatewayConfig?.gateway?.api?.keys) {
717
723
  const appsRouter = (0, apps_router_1.createAppsRouter)(this.appsRegistry, this.appInstaller, this.appRegistryClient, this.gatewayConfig.gateway.api.keys);
718
724
  this.app.use('/api', appsRouter);
719
725
  }
@@ -815,10 +821,10 @@ class GatewayRouter {
815
821
  delete require.cache[webUiPath];
816
822
  // eslint-disable-next-line @typescript-eslint/no-require-imports
817
823
  const { generateDashboardHtml: fresh } = require('../ui/web-ui');
818
- res.send(fresh());
824
+ res.send(fresh(this.gatewayConfig?.gateway?.timezone));
819
825
  }
820
826
  else {
821
- res.send((0, web_ui_1.generateDashboardHtml)());
827
+ res.send((0, web_ui_1.generateDashboardHtml)(this.gatewayConfig?.gateway?.timezone));
822
828
  }
823
829
  });
824
830
  // Reports expose cross-agent usage/tool inventories: the same admin gate as status.
@@ -857,7 +863,7 @@ class GatewayRouter {
857
863
  }
858
864
  try {
859
865
  const source = runner.getDashboardSource?.();
860
- let report = source ? await this.dashboardReader.read('report', source.filename, { workspace: source.workspace, sessionId, offset, since: (0, dashboard_range_1.dashboardSince)(req.query.scope ?? (reportPath === '/token-report' ? 'all' : '24h')), historyFilename: source.historyFilename }) : await runner.getTokenReport(sessionId);
866
+ let report = source ? await this.dashboardReader.read('report', source.filename, { workspace: source.workspace, sessionId, offset, since: (0, dashboard_range_1.dashboardSince)(req.query.scope ?? (reportPath === '/token-report' ? 'all' : '24h'), Date.now(), this.gatewayConfig?.gateway?.timezone), historyFilename: source.historyFilename }) : await runner.getTokenReport(sessionId);
861
867
  if (!report) {
862
868
  res.status(404).json({ error: 'No recorded session token report' });
863
869
  return;
@@ -869,7 +875,7 @@ class GatewayRouter {
869
875
  if (reportPath === '/token-report')
870
876
  res.json(report);
871
877
  else
872
- res.type('html').send((0, token_report_1.generateTokenReportHtml)(agentId, { ...report, scope: (0, dashboard_range_1.dashboardRange)(req.query.scope), sessionStatus: runner.agentSessionLiveStatus?.(sessionId) ?? 'stopped' }));
878
+ res.type('html').send((0, token_report_1.generateTokenReportHtml)(agentId, { ...report, timezone: this.gatewayConfig?.gateway?.timezone, scope: (0, dashboard_range_1.dashboardRange)(req.query.scope), sessionStatus: runner.agentSessionLiveStatus?.(sessionId) ?? 'stopped' }));
873
879
  }
874
880
  catch {
875
881
  res.status(500).json({ error: 'Unable to load session token report' });
@@ -892,7 +898,7 @@ class GatewayRouter {
892
898
  return;
893
899
  }
894
900
  try {
895
- const detail = await this.dashboardReader.read('session', source.filename, { sessionId, offset, since: (0, dashboard_range_1.dashboardSince)(req.query.scope), historyFilename: source.historyFilename });
901
+ const detail = await this.dashboardReader.read('session', source.filename, { sessionId, offset, since: (0, dashboard_range_1.dashboardSince)(req.query.scope, Date.now(), this.gatewayConfig?.gateway?.timezone), historyFilename: source.historyFilename });
896
902
  if (!detail) {
897
903
  res.status(404).json({ error: 'Session not found' });
898
904
  return;
@@ -923,7 +929,7 @@ class GatewayRouter {
923
929
  return;
924
930
  }
925
931
  try {
926
- const task = await this.dashboardReader.read('task', source.filename, { sessionId, taskId, offset, since: (0, dashboard_range_1.dashboardSince)(req.query.scope) });
932
+ const task = await this.dashboardReader.read('task', source.filename, { sessionId, taskId, offset, since: (0, dashboard_range_1.dashboardSince)(req.query.scope, Date.now(), this.gatewayConfig?.gateway?.timezone) });
927
933
  if (!task) {
928
934
  res.status(404).json({ error: 'Task not found in this session' });
929
935
  return;
@@ -959,49 +965,57 @@ class GatewayRouter {
959
965
  }
960
966
  // Success: clear this IP's failure window.
961
967
  this.loginAttempts.delete(this.clientIp(req));
962
- const token = crypto.randomBytes(32).toString('hex');
963
- this.dashboardTokens.set(token, Date.now() + DASH_SESSION_TTL_MS);
968
+ let token;
969
+ try {
970
+ token = this.dashboardSessions.issue(key, DASH_SESSION_TTL_MS);
971
+ }
972
+ catch {
973
+ res.status(503).json({ error: 'Dashboard session storage is unavailable.' });
974
+ return;
975
+ }
964
976
  res.setHeader('Set-Cookie', this.buildSessionCookie(req, token, DASH_SESSION_TTL_MS));
965
977
  res.json({ ok: true });
966
978
  });
967
979
  // Dashboard logout — revoke the session token and clear the cookie.
968
980
  this.app.post('/dashboard/logout', (req, res) => {
969
981
  const token = parseCookies(req.headers['cookie'])[DASH_SESSION_COOKIE];
970
- if (token)
971
- this.dashboardTokens.delete(token);
982
+ try {
983
+ if (token)
984
+ this.dashboardSessions.revoke(token);
985
+ }
986
+ catch {
987
+ res.status(503).json({ error: 'Could not revoke the dashboard session. Please try again.' });
988
+ return;
989
+ }
972
990
  res.setHeader('Set-Cookie', this.buildSessionCookie(req, '', 0));
973
991
  res.json({ ok: true });
974
992
  });
975
- // Process tree endpoint returns raw ps data for dashboard.
976
- // Async exec + 3s cache: avoids blocking the event loop on every dashboard poll.
977
- this.app.get('/processes', (req, res) => {
993
+ // Authenticated, cached, single-flight process inventory. No raw command lines.
994
+ this.app.get('/processes', async (req, res) => {
978
995
  if (!this.requireDashOrApiKey(req, res))
979
996
  return;
980
- const now = Date.now();
981
- if (this.processesCache && now - this.processesCache.ts < GatewayRouter.PROCESSES_CACHE_TTL_MS) {
982
- res.json({ processes: this.processesCache.data, numCpus: GatewayRouter.NUM_CPUS });
983
- return;
997
+ try {
998
+ if (!this.processesCache || Date.now() - this.processesCache.ts >= GatewayRouter.PROCESSES_CACHE_TTL_MS) {
999
+ if (!this.processesPending) {
1000
+ const owners = [{ pid: process.pid, group: 'gateway' }];
1001
+ for (const runner of this.agents.values())
1002
+ owners.push(...(runner.getProcessOwners?.() ?? []));
1003
+ const apps = new Map();
1004
+ for (const [id, config] of this.configs)
1005
+ if (config.type === 'app-agent' && config.container) {
1006
+ apps.set(config.container, [...(apps.get(config.container) ?? []), id]);
1007
+ }
1008
+ this.processesPending = (0, dashboard_processes_1.collectDashboardProcesses)(owners, [...apps].map(([name, agentIds]) => ({ name, agentIds })))
1009
+ .then(data => { this.processesCache = { data, ts: Date.now() }; return data; })
1010
+ .finally(() => { this.processesPending = undefined; });
1011
+ }
1012
+ await this.processesPending;
1013
+ }
1014
+ res.json({ ...this.processesCache.data, numCpus: GatewayRouter.NUM_CPUS });
1015
+ }
1016
+ catch {
1017
+ res.status(503).json({ error: 'Process inspection unavailable' });
984
1018
  }
985
- (0, child_process_1.exec)("ps -eo pid,ppid,stat,%cpu,%mem,rss,args --no-headers 2>/dev/null | grep -E 'claude|bun.*gateway|bun.*mcp|bun.*receiver|node.*dist/' | grep -v grep | grep -v vscode", { encoding: 'utf8', timeout: 5000 }, (err, stdout) => {
986
- if (err)
987
- process.stderr.write(`[processes] ps error: ${err.message}\n`);
988
- const processes = (stdout ?? '').trim().split('\n').filter(Boolean).map((line) => {
989
- const m = line.trim().match(/^(\d+)\s+(\d+)\s+(\S+)\s+([\d.]+)\s+([\d.]+)\s+(\d+)\s+(.+)$/);
990
- if (!m)
991
- return null;
992
- return {
993
- pid: parseInt(m[1]),
994
- ppid: parseInt(m[2]),
995
- stat: m[3],
996
- cpu: parseFloat(m[4]),
997
- mem: parseFloat(m[5]),
998
- rssKb: parseInt(m[6]),
999
- args: m[7].trim(),
1000
- };
1001
- }).filter(Boolean);
1002
- this.processesCache = { data: processes, ts: Date.now() };
1003
- res.json({ processes, numCpus: GatewayRouter.NUM_CPUS });
1004
- });
1005
1019
  });
1006
1020
  // Knowledge Base graph — a memory-wiki as a {nodes, edges} model for the
1007
1021
  // dashboard's "Knowledge base" tab. Computed ON DEMAND from *.md notes (does
@@ -1161,6 +1175,66 @@ class GatewayRouter {
1161
1175
  res.status(500).json({ error: 'Failed to list knowledge sources' });
1162
1176
  }
1163
1177
  });
1178
+ let memorySnapshot;
1179
+ let memorySnapshotUntil = 0;
1180
+ this.app.get('/dashboard/memory-activity', async (req, res) => {
1181
+ if (!this.requireDashOrApiKey(req, res))
1182
+ return;
1183
+ res.setHeader('Cache-Control', 'no-store');
1184
+ const { agentId, kind, status, id, scope, completedOnly } = req.query, page = Number(req.query.page ?? 0);
1185
+ if (!Number.isSafeInteger(page) || page < 0 || page > 1000000 ||
1186
+ [agentId, kind, status, id, scope].some(v => v !== undefined && (typeof v !== 'string' || v.length > 256)) ||
1187
+ (completedOnly !== undefined && completedOnly !== 'true' && completedOnly !== 'false') ||
1188
+ (kind !== undefined && !['all', 'memory_dream', 'session_compaction'].includes(String(kind))) ||
1189
+ (status !== undefined && !String(status).split(',').every(s => ['all', 'none', 'pending', 'running', 'completed', 'failed', 'partial_failure', 'interrupted', 'skipped'].includes(s))) ||
1190
+ (scope !== undefined && !['24h', '7d', '30d', '90d', 'all'].includes(String(scope)))) {
1191
+ res.status(400).json({ error: 'Invalid activity filters' });
1192
+ return;
1193
+ }
1194
+ if (agentId && !this.agents.has(String(agentId))) {
1195
+ res.status(404).json({ error: 'Unknown agent' });
1196
+ return;
1197
+ }
1198
+ try {
1199
+ if (!memorySnapshot || Date.now() >= memorySnapshotUntil) {
1200
+ memorySnapshotUntil = Infinity;
1201
+ const snapshot = (0, memory_activity_1.readMemoryActivity)(this.agents, this.agentsRoot(), (filename, agentId) => this.dashboardReader.read('compaction', filename, { agentId })).then(data => { if (memorySnapshot === snapshot)
1202
+ memorySnapshotUntil = Date.now() + 5000; return data; }, error => { if (memorySnapshot === snapshot)
1203
+ memorySnapshot = undefined; throw error; });
1204
+ memorySnapshot = snapshot;
1205
+ }
1206
+ const data = await memorySnapshot;
1207
+ if (id) {
1208
+ let run = data.runs.find(r => r.id === id && r.agent === agentId);
1209
+ if (!run) {
1210
+ res.status(404).json({ error: 'Activity not found' });
1211
+ return;
1212
+ }
1213
+ const source = this.agents.get(String(agentId))?.getDashboardSource?.();
1214
+ if (run.kind === 'session_compaction' && source)
1215
+ run = await this.dashboardReader.read('compaction', source.filename, { agentId, runId: id });
1216
+ if (!run) {
1217
+ res.status(404).json({ error: 'Activity not found' });
1218
+ return;
1219
+ }
1220
+ if (completedOnly === 'true' && run.kind === 'session_compaction') {
1221
+ run = { ...run, items: (run.items ?? []).filter((item) => item.status === 'completed'), itemCount: run.completedSessions };
1222
+ }
1223
+ res.json({ run });
1224
+ return;
1225
+ }
1226
+ const timezone = this.gatewayConfig?.gateway?.timezone || 'UTC';
1227
+ const since = (0, dashboard_range_1.dashboardSince)(scope, Date.now(), timezone);
1228
+ const runs = data.runs.filter(r => (completedOnly !== 'true' || r.kind !== 'session_compaction' || r.completedSessions > 0 || (r.items ?? []).some((i) => i.status === 'completed')) && (!agentId || r.agent === agentId) && (!kind || kind === 'all' || r.kind === kind) && (!status || status === 'all' || String(status).split(',').includes(r.status)) && r.startedAt >= since);
1229
+ res.json({ timezone, since, runs: runs.slice(page * 25, page * 25 + 25).map(memory_activity_1.activitySummary), total: runs.length, page, pageSize: 25,
1230
+ agents: data.agents, schedules: data.schedules.filter(s => !agentId || s.agent === agentId), unavailable: data.unavailable,
1231
+ counts: { compactedSessions: runs.reduce((n, r) => n + (r.completedSessions ?? r.items?.filter((i) => i.status === 'completed').length ?? 0), 0), measuredReduction: runs.reduce((n, r) => n + ((0, memory_activity_1.activitySummary)(r).measuredReduction ?? 0), 0), measuredSessions: runs.reduce((n, r) => n + ((0, memory_activity_1.activitySummary)(r).measuredSessions ?? 0), 0), runs: runs.length, pendingProposals: runs.reduce((n, r) => n + (r.pendingProposals ?? 0), 0), failed: runs.filter(r => ['failed', 'partial_failure', 'interrupted'].includes(r.status)).length },
1232
+ historyLimit: 100 });
1233
+ }
1234
+ catch {
1235
+ res.status(503).json({ error: 'Memory activity temporarily unavailable' });
1236
+ }
1237
+ });
1164
1238
  // Nightly dreaming report — parses every agent's `.dreaming/` audit trail
1165
1239
  // (DREAMS.md + promotions.jsonl) into newest-first runs for the dashboard's
1166
1240
  // "Nightly dreaming" tab. Auth: dashboard session cookie OR API key. Payload is
@@ -1175,7 +1249,7 @@ class GatewayRouter {
1175
1249
  const runs = [];
1176
1250
  const agents = [];
1177
1251
  for (const id of this.agents.keys()) {
1178
- const dir = path.join(root, id, 'workspace', audit_1.DREAMING_DIR);
1252
+ const dir = path.join(this.agents.get(id)?.workspacePath ?? path.join(root, id, 'workspace'), audit_1.DREAMING_DIR);
1179
1253
  let dreams;
1180
1254
  try {
1181
1255
  dreams = fs.readFileSync(path.join(dir, 'DREAMS.md'), 'utf8');
@@ -1231,6 +1305,7 @@ class GatewayRouter {
1231
1305
  this.app.post('/knowledge/dreams/apply', (req, res) => {
1232
1306
  if (!this.requireDashOrApiKey(req, res))
1233
1307
  return;
1308
+ memorySnapshot = undefined;
1234
1309
  try {
1235
1310
  const body = (req.body ?? {});
1236
1311
  const agentId = typeof body.agentId === 'string' ? body.agentId : '';
@@ -1254,7 +1329,7 @@ class GatewayRouter {
1254
1329
  }
1255
1330
  indexes = body.indexes;
1256
1331
  }
1257
- const workspaceDir = path.join(this.agentsRoot(), agentId, 'workspace');
1332
+ const workspaceDir = this.agents.get(agentId)?.workspacePath ?? path.join(this.agentsRoot(), agentId, 'workspace');
1258
1333
  const budget = (0, workspace_loader_1.resolveMemoryBudget)({
1259
1334
  ...this.gatewayConfig?.gateway?.memory,
1260
1335
  ...this.configs.get(agentId)?.memory,
@@ -1337,7 +1412,7 @@ class GatewayRouter {
1337
1412
  const source = runner.getDashboardSource?.();
1338
1413
  const legacySessions = runner.getSessionsSummary();
1339
1414
  const liveSessionIds = new Set(runner.liveSessionIds?.() ?? []);
1340
- const orchestration = source ? (source.enabled ? await this.dashboardReader.read('summary', source.filename, { ...source, offset, since: (0, dashboard_range_1.dashboardSince)(scope), legacyIds: legacySessions.map(s => s.sessionId) }) : undefined) : runner.getOrchestrationSummary?.();
1415
+ const orchestration = source ? (source.enabled ? await this.dashboardReader.read('summary', source.filename, { ...source, timezone: this.gatewayConfig?.gateway?.timezone, offset, since: (0, dashboard_range_1.dashboardSince)(scope, Date.now(), this.gatewayConfig?.gateway?.timezone), legacyIds: legacySessions.map(s => s.sessionId) }) : undefined) : runner.getOrchestrationSummary?.();
1341
1416
  const managedSessions = (orchestration?.sessions ?? []).map((s) => ({
1342
1417
  ...s,
1343
1418
  // Live liveness from the runner's in-memory map: the DB-derived status
@@ -1347,7 +1422,7 @@ class GatewayRouter {
1347
1422
  ...(runner.isSessionCompacting?.(s.sessionId) ? { status: 'compacting', isRunning: true } : {}),
1348
1423
  }));
1349
1424
  const managedIds = new Set([...managedSessions.map((s) => s.sessionId), ...(orchestration?.managedLegacyIds ?? [])]);
1350
- const sessions = [...legacySessions.filter(s => !managedIds.has(s.sessionId) && (!(0, dashboard_range_1.dashboardSince)(scope) || Number(s.updatedAt || s.spawnedAt || 0) >= (0, dashboard_range_1.dashboardSince)(scope))), ...managedSessions].map((s) => ({
1425
+ const sessions = [...legacySessions.filter(s => !managedIds.has(s.sessionId) && (!(0, dashboard_range_1.dashboardSince)(scope, Date.now(), this.gatewayConfig?.gateway?.timezone) || Number(s.updatedAt || s.spawnedAt || 0) >= (0, dashboard_range_1.dashboardSince)(scope, Date.now(), this.gatewayConfig?.gateway?.timezone))), ...managedSessions].map((s) => ({
1351
1426
  ...s,
1352
1427
  hasPtyStream: pty_stream_registry_1.ptyStreamRegistry.hasSockets(s.sessionId),
1353
1428
  }));
@@ -1383,6 +1458,34 @@ class GatewayRouter {
1383
1458
  watchers: (0, factory_1.getWatcherHealth)(),
1384
1459
  };
1385
1460
  };
1461
+ this.app.get('/dashboard/charts', async (req, res) => {
1462
+ if (!this.requireDashOrApiKey(req, res))
1463
+ return;
1464
+ res.setHeader('Cache-Control', 'no-store');
1465
+ const scope = req.query.scope ?? '24h';
1466
+ if (typeof scope !== 'string' || !['24h', '7d', '30d', '90d'].includes(scope)) {
1467
+ res.status(400).json({ error: 'Invalid chart range' });
1468
+ return;
1469
+ }
1470
+ const timezone = this.gatewayConfig?.gateway?.timezone || 'UTC';
1471
+ // Stable snapshot timestamp coalesces all four cards and concurrent browsers.
1472
+ const now = Math.floor(Date.now() / 10000) * 10000;
1473
+ try {
1474
+ const agents = [];
1475
+ for (const [id, runner] of this.agents) {
1476
+ const source = runner.getDashboardSource?.();
1477
+ if (!source?.enabled)
1478
+ continue;
1479
+ const usage = await this.dashboardReader.read('charts', source.filename, { scope, timezone, now });
1480
+ if (usage)
1481
+ agents.push({ id, ...usage });
1482
+ }
1483
+ res.json({ scope, timezone, asOf: now, since: (0, dashboard_range_1.dashboardSince)(scope, now, timezone), agents });
1484
+ }
1485
+ catch {
1486
+ res.status(503).json({ error: 'Chart data temporarily unavailable' });
1487
+ }
1488
+ });
1386
1489
  this.app.get('/status', async (req, res) => {
1387
1490
  if (!this.requireDashOrApiKey(req, res))
1388
1491
  return;
@@ -1510,10 +1613,10 @@ class GatewayRouter {
1510
1613
  if (v.expiresAt < now)
1511
1614
  this.ptyStreamTickets.delete(k);
1512
1615
  }
1513
- for (const [k, exp] of this.dashboardTokens) {
1514
- if (exp < now)
1515
- this.dashboardTokens.delete(k);
1616
+ try {
1617
+ this.dashboardSessions.prune();
1516
1618
  }
1619
+ catch { /* Login reports unavailable storage; auth fails closed. */ }
1517
1620
  for (const [ip, rec] of this.loginAttempts) {
1518
1621
  if (rec.resetAt < now)
1519
1622
  this.loginAttempts.delete(ip);
@@ -1655,6 +1758,7 @@ class GatewayRouter {
1655
1758
  await this.voiceApi?.close();
1656
1759
  if (this.ticketPruner)
1657
1760
  clearInterval(this.ticketPruner);
1761
+ this.dashboardSessions.close();
1658
1762
  // Terminate live WebSocket clients first. The dashboard PTY viewer holds these
1659
1763
  // open indefinitely; without an explicit terminate, server.close() below would
1660
1764
  // wait forever for them to drain (the "Ctrl+C twice" hang).
@@ -1712,7 +1816,14 @@ class GatewayRouter {
1712
1816
  if (!this.gatewayConfig?.gateway?.api?.keys)
1713
1817
  return;
1714
1818
  const keys = this.gatewayConfig.gateway.api.keys;
1715
- keys.splice(0, keys.length, ...newKeys);
1819
+ const next = structuredClone(newKeys);
1820
+ if (JSON.stringify(keys) === JSON.stringify(next))
1821
+ return;
1822
+ keys.splice(0, keys.length, ...next);
1823
+ this.ptyStreamTickets.clear();
1824
+ for (const client of this.wss?.clients ?? [])
1825
+ client.close(1008, 'Authorization changed');
1826
+ this.voiceApi?.invalidateAuthorization();
1716
1827
  }
1717
1828
  /**
1718
1829
  * Return per-agent stats.