@maudecode/talaria-web 1.18.0 → 1.19.0

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 (567) hide show
  1. package/_release.json +8 -8
  2. package/dist/api/auth-raw.js +16 -16
  3. package/dist/api/auth-raw.js.map +1 -1
  4. package/dist/api/automation-raw.d.ts +2 -2
  5. package/dist/api/automation-raw.js +32 -32
  6. package/dist/api/automation-raw.js.map +1 -1
  7. package/dist/api/automation-router.d.ts +102 -22
  8. package/dist/api/automation-router.js +15 -13
  9. package/dist/api/automation-router.js.map +1 -1
  10. package/dist/api/chat-router.d.ts +1205 -34
  11. package/dist/api/chat-router.js +158 -78
  12. package/dist/api/chat-router.js.map +1 -1
  13. package/dist/api/git-router.d.ts +2 -2
  14. package/dist/api/git-router.js +29 -29
  15. package/dist/api/git-router.js.map +1 -1
  16. package/dist/api/raw-routes.d.ts +3 -3
  17. package/dist/api/raw-routes.js +63 -61
  18. package/dist/api/raw-routes.js.map +1 -1
  19. package/dist/api/router.d.ts +6 -6
  20. package/dist/api/router.js +22 -22
  21. package/dist/api/router.js.map +1 -1
  22. package/dist/api/session-visibility.d.ts +4 -4
  23. package/dist/api/session-visibility.js +26 -16
  24. package/dist/api/session-visibility.js.map +1 -1
  25. package/dist/api/sessions-router.d.ts +1928 -124
  26. package/dist/api/sessions-router.js +177 -173
  27. package/dist/api/sessions-router.js.map +1 -1
  28. package/dist/api/settings-router.d.ts +427 -9
  29. package/dist/api/settings-router.js +48 -32
  30. package/dist/api/settings-router.js.map +1 -1
  31. package/dist/api/sse-routes.d.ts +2 -2
  32. package/dist/api/sse-routes.js +63 -63
  33. package/dist/api/sse-routes.js.map +1 -1
  34. package/dist/api/tools-raw.d.ts +5 -0
  35. package/dist/api/tools-raw.js +58 -33
  36. package/dist/api/tools-raw.js.map +1 -1
  37. package/dist/api/tools-router.d.ts +663 -91
  38. package/dist/api/tools-router.js +309 -52
  39. package/dist/api/tools-router.js.map +1 -1
  40. package/dist/api/transcribe-stream.d.ts +16 -0
  41. package/dist/api/transcribe-stream.js +172 -0
  42. package/dist/api/transcribe-stream.js.map +1 -0
  43. package/dist/app.d.ts +4 -1
  44. package/dist/app.js +66 -47
  45. package/dist/app.js.map +1 -1
  46. package/dist/auth/gate.js +10 -9
  47. package/dist/auth/gate.js.map +1 -1
  48. package/dist/auth/passkeys.d.ts +15 -14
  49. package/dist/auth/passkeys.js +89 -91
  50. package/dist/auth/passkeys.js.map +1 -1
  51. package/dist/auth/store.d.ts +17 -7
  52. package/dist/auth/store.js +93 -52
  53. package/dist/auth/store.js.map +1 -1
  54. package/dist/bin/talaria-web.js +12 -81
  55. package/dist/bin/talaria-web.js.map +1 -1
  56. package/dist/cli/ctl.js +2 -1
  57. package/dist/cli/ctl.js.map +1 -1
  58. package/dist/cli/dotenv.d.ts +5 -0
  59. package/dist/cli/dotenv.js +14 -2
  60. package/dist/cli/dotenv.js.map +1 -1
  61. package/dist/cli/launcher.js +5 -5
  62. package/dist/cli/launcher.js.map +1 -1
  63. package/dist/cli/main.d.ts +1 -0
  64. package/dist/cli/main.js +85 -0
  65. package/dist/cli/main.js.map +1 -0
  66. package/dist/cli/supervise.d.ts +2 -0
  67. package/dist/cli/supervise.js +67 -4
  68. package/dist/cli/supervise.js.map +1 -1
  69. package/dist/config/agent-config.d.ts +34 -11
  70. package/dist/config/agent-config.js +113 -58
  71. package/dist/config/agent-config.js.map +1 -1
  72. package/dist/config.d.ts +2 -0
  73. package/dist/config.js +14 -5
  74. package/dist/config.js.map +1 -1
  75. package/dist/fs/atomic.d.ts +1 -0
  76. package/dist/fs/atomic.js +4 -1
  77. package/dist/fs/atomic.js.map +1 -1
  78. package/dist/fs/stat.d.ts +1 -0
  79. package/dist/fs/stat.js +11 -0
  80. package/dist/fs/stat.js.map +1 -0
  81. package/dist/http/context.d.ts +14 -9
  82. package/dist/http/context.js +29 -20
  83. package/dist/http/context.js.map +1 -1
  84. package/dist/onboarding.d.ts +2 -2
  85. package/dist/onboarding.js +10 -8
  86. package/dist/onboarding.js.map +1 -1
  87. package/dist/profiles/profiles.d.ts +10 -4
  88. package/dist/profiles/profiles.js +77 -30
  89. package/dist/profiles/profiles.js.map +1 -1
  90. package/dist/projects.d.ts +15 -6
  91. package/dist/projects.js +55 -47
  92. package/dist/projects.js.map +1 -1
  93. package/dist/providers/catalog.d.ts +78 -12
  94. package/dist/providers/catalog.js +445 -141
  95. package/dist/providers/catalog.js.map +1 -1
  96. package/dist/providers/env-file.d.ts +10 -3
  97. package/dist/providers/env-file.js +24 -75
  98. package/dist/providers/env-file.js.map +1 -1
  99. package/dist/providers/runtime-env.d.ts +4 -2
  100. package/dist/providers/runtime-env.js +9 -6
  101. package/dist/providers/runtime-env.js.map +1 -1
  102. package/dist/providers/tables.d.ts +3 -1
  103. package/dist/providers/tables.js +4 -2
  104. package/dist/providers/tables.js.map +1 -1
  105. package/dist/redact.js +18 -9
  106. package/dist/redact.js.map +1 -1
  107. package/dist/release.d.ts +7 -0
  108. package/dist/release.js +14 -0
  109. package/dist/release.js.map +1 -1
  110. package/dist/runtime.d.ts +5 -1
  111. package/dist/runtime.js +233 -90
  112. package/dist/runtime.js.map +1 -1
  113. package/dist/server.js +10 -0
  114. package/dist/server.js.map +1 -1
  115. package/dist/sessions/anchor.d.ts +9 -3
  116. package/dist/sessions/anchor.js +28 -36
  117. package/dist/sessions/anchor.js.map +1 -1
  118. package/dist/sessions/background-events.d.ts +2 -0
  119. package/dist/sessions/background-events.js +10 -0
  120. package/dist/sessions/background-events.js.map +1 -0
  121. package/dist/sessions/background-tasks.d.ts +26 -20
  122. package/dist/sessions/background-tasks.js +88 -86
  123. package/dist/sessions/background-tasks.js.map +1 -1
  124. package/dist/sessions/background-updates.d.ts +15 -8
  125. package/dist/sessions/background-updates.js +101 -25
  126. package/dist/sessions/background-updates.js.map +1 -1
  127. package/dist/sessions/cli-sessions.d.ts +15 -5
  128. package/dist/sessions/cli-sessions.js +62 -43
  129. package/dist/sessions/cli-sessions.js.map +1 -1
  130. package/dist/sessions/completions.d.ts +30 -2
  131. package/dist/sessions/completions.js +294 -53
  132. package/dist/sessions/completions.js.map +1 -1
  133. package/dist/sessions/compress.d.ts +8 -0
  134. package/dist/sessions/compress.js +2 -2
  135. package/dist/sessions/compress.js.map +1 -1
  136. package/dist/sessions/drafts.d.ts +14 -10
  137. package/dist/sessions/drafts.js +38 -43
  138. package/dist/sessions/drafts.js.map +1 -1
  139. package/dist/sessions/gateway-sessions.d.ts +46 -0
  140. package/dist/sessions/gateway-sessions.js +378 -0
  141. package/dist/sessions/gateway-sessions.js.map +1 -0
  142. package/dist/sessions/goals.d.ts +31 -0
  143. package/dist/sessions/goals.js +75 -0
  144. package/dist/sessions/goals.js.map +1 -0
  145. package/dist/sessions/journal.d.ts +5 -79
  146. package/dist/sessions/journal.js +15 -606
  147. package/dist/sessions/journal.js.map +1 -1
  148. package/dist/sessions/list.d.ts +27 -18
  149. package/dist/sessions/list.js +133 -131
  150. package/dist/sessions/list.js.map +1 -1
  151. package/dist/sessions/merge.d.ts +68 -10
  152. package/dist/sessions/merge.js +259 -51
  153. package/dist/sessions/merge.js.map +1 -1
  154. package/dist/sessions/notices.d.ts +22 -0
  155. package/dist/sessions/notices.js +72 -0
  156. package/dist/sessions/notices.js.map +1 -0
  157. package/dist/sessions/pending.d.ts +10 -4
  158. package/dist/sessions/pending.js +83 -7
  159. package/dist/sessions/pending.js.map +1 -1
  160. package/dist/sessions/prefix-index.d.ts +82 -0
  161. package/dist/sessions/prefix-index.js +232 -0
  162. package/dist/sessions/prefix-index.js.map +1 -0
  163. package/dist/sessions/recovery.d.ts +4 -7
  164. package/dist/sessions/recovery.js +97 -281
  165. package/dist/sessions/recovery.js.map +1 -1
  166. package/dist/sessions/relay.d.ts +20 -20
  167. package/dist/sessions/relay.js +205 -127
  168. package/dist/sessions/relay.js.map +1 -1
  169. package/dist/sessions/service.d.ts +162 -59
  170. package/dist/sessions/service.js +1133 -521
  171. package/dist/sessions/service.js.map +1 -1
  172. package/dist/sessions/session.d.ts +18 -2
  173. package/dist/sessions/session.js +29 -5
  174. package/dist/sessions/session.js.map +1 -1
  175. package/dist/sessions/shares.d.ts +7 -6
  176. package/dist/sessions/shares.js +22 -45
  177. package/dist/sessions/shares.js.map +1 -1
  178. package/dist/sessions/source-kind.js +1 -0
  179. package/dist/sessions/source-kind.js.map +1 -1
  180. package/dist/sessions/state-db-identity.d.ts +18 -0
  181. package/dist/sessions/state-db-identity.js +67 -0
  182. package/dist/sessions/state-db-identity.js.map +1 -0
  183. package/dist/sessions/state-db-worker.js +3 -1
  184. package/dist/sessions/state-db-worker.js.map +1 -1
  185. package/dist/sessions/state-db.d.ts +53 -8
  186. package/dist/sessions/state-db.js +576 -50
  187. package/dist/sessions/state-db.js.map +1 -1
  188. package/dist/sessions/storage/backend.d.ts +162 -0
  189. package/dist/sessions/storage/backend.js +19 -0
  190. package/dist/sessions/storage/backend.js.map +1 -0
  191. package/dist/sessions/storage/conformance.d.ts +20 -0
  192. package/dist/sessions/storage/conformance.js +237 -0
  193. package/dist/sessions/storage/conformance.js.map +1 -0
  194. package/dist/sessions/storage/document.d.ts +16 -0
  195. package/dist/sessions/storage/document.js +44 -0
  196. package/dist/sessions/storage/document.js.map +1 -0
  197. package/dist/sessions/storage/json-documents.d.ts +23 -0
  198. package/dist/sessions/storage/json-documents.js +233 -0
  199. package/dist/sessions/storage/json-documents.js.map +1 -0
  200. package/dist/sessions/storage/json-files.d.ts +12 -0
  201. package/dist/sessions/storage/json-files.js +124 -0
  202. package/dist/sessions/storage/json-files.js.map +1 -0
  203. package/dist/sessions/storage/json-installation.d.ts +3 -0
  204. package/dist/sessions/storage/json-installation.js +31 -0
  205. package/dist/sessions/storage/json-installation.js.map +1 -0
  206. package/dist/sessions/storage/json-journal.d.ts +114 -0
  207. package/dist/sessions/storage/json-journal.js +686 -0
  208. package/dist/sessions/storage/json-journal.js.map +1 -0
  209. package/dist/sessions/storage/json-recovery.d.ts +4 -0
  210. package/dist/sessions/storage/json-recovery.js +195 -0
  211. package/dist/sessions/storage/json-recovery.js.map +1 -0
  212. package/dist/sessions/storage/json.d.ts +68 -0
  213. package/dist/sessions/storage/json.js +258 -0
  214. package/dist/sessions/storage/json.js.map +1 -0
  215. package/dist/sessions/storage/row.d.ts +6 -0
  216. package/dist/sessions/storage/row.js +49 -0
  217. package/dist/sessions/storage/row.js.map +1 -0
  218. package/dist/sessions/storage/search-text.d.ts +4 -0
  219. package/dist/sessions/storage/search-text.js +16 -0
  220. package/dist/sessions/storage/search-text.js.map +1 -0
  221. package/dist/sessions/store.d.ts +63 -73
  222. package/dist/sessions/store.js +305 -611
  223. package/dist/sessions/store.js.map +1 -1
  224. package/dist/sessions/streams.d.ts +4 -0
  225. package/dist/sessions/streams.js +9 -1
  226. package/dist/sessions/streams.js.map +1 -1
  227. package/dist/sessions/titles.js +1 -1
  228. package/dist/sessions/titles.js.map +1 -1
  229. package/dist/sessions/todo.d.ts +5 -0
  230. package/dist/sessions/todo.js +28 -21
  231. package/dist/sessions/todo.js.map +1 -1
  232. package/dist/sessions/tool-display.d.ts +5 -4
  233. package/dist/sessions/tool-display.js +22 -16
  234. package/dist/sessions/tool-display.js.map +1 -1
  235. package/dist/sessions/turn-context.d.ts +10 -1
  236. package/dist/sessions/turn-context.js +7 -4
  237. package/dist/sessions/turn-context.js.map +1 -1
  238. package/dist/sessions/turn.d.ts +87 -17
  239. package/dist/sessions/turn.js +795 -347
  240. package/dist/sessions/turn.js.map +1 -1
  241. package/dist/sessions/wakeup-pause.d.ts +8 -13
  242. package/dist/sessions/wakeup-pause.js +31 -49
  243. package/dist/sessions/wakeup-pause.js.map +1 -1
  244. package/dist/sessions/window.js +13 -12
  245. package/dist/sessions/window.js.map +1 -1
  246. package/dist/settings.d.ts +19 -7
  247. package/dist/settings.js +179 -183
  248. package/dist/settings.js.map +1 -1
  249. package/dist/sidecar/client.d.ts +17 -3
  250. package/dist/sidecar/client.js +78 -8
  251. package/dist/sidecar/client.js.map +1 -1
  252. package/dist/sidecar/discover.d.ts +2 -1
  253. package/dist/sidecar/discover.js +93 -10
  254. package/dist/sidecar/discover.js.map +1 -1
  255. package/dist/sidecar/env.d.ts +4 -0
  256. package/dist/sidecar/env.js +3 -0
  257. package/dist/sidecar/env.js.map +1 -0
  258. package/dist/sidecar/fake.js +19 -2
  259. package/dist/sidecar/fake.js.map +1 -1
  260. package/dist/test/env-file.d.ts +5 -0
  261. package/dist/test/env-file.js +88 -0
  262. package/dist/test/env-file.js.map +1 -0
  263. package/dist/test/harness.d.ts +1 -0
  264. package/dist/test/harness.js +1 -1
  265. package/dist/test/harness.js.map +1 -1
  266. package/dist/test/passkeys.d.ts +22 -0
  267. package/dist/test/passkeys.js +62 -0
  268. package/dist/test/passkeys.js.map +1 -0
  269. package/dist/test/storage.d.ts +15 -0
  270. package/dist/test/storage.js +26 -0
  271. package/dist/test/storage.js.map +1 -0
  272. package/dist/tools/commands.d.ts +6 -1
  273. package/dist/tools/commands.js +8 -2
  274. package/dist/tools/commands.js.map +1 -1
  275. package/dist/tools/connectors.d.ts +33 -0
  276. package/dist/tools/connectors.js +121 -0
  277. package/dist/tools/connectors.js.map +1 -0
  278. package/dist/tools/crons.d.ts +38 -1
  279. package/dist/tools/crons.js +82 -15
  280. package/dist/tools/crons.js.map +1 -1
  281. package/dist/tools/dashboard-plugins.d.ts +5 -5
  282. package/dist/tools/dashboard-plugins.js +14 -14
  283. package/dist/tools/dashboard-plugins.js.map +1 -1
  284. package/dist/tools/extensions.d.ts +5 -4
  285. package/dist/tools/extensions.js +213 -207
  286. package/dist/tools/extensions.js.map +1 -1
  287. package/dist/tools/gateway-restart.d.ts +62 -0
  288. package/dist/tools/gateway-restart.js +142 -0
  289. package/dist/tools/gateway-restart.js.map +1 -0
  290. package/dist/tools/health.d.ts +15 -3
  291. package/dist/tools/health.js +97 -34
  292. package/dist/tools/health.js.map +1 -1
  293. package/dist/tools/hygiene.d.ts +4 -3
  294. package/dist/tools/hygiene.js +23 -9
  295. package/dist/tools/hygiene.js.map +1 -1
  296. package/dist/tools/kanban.d.ts +4 -2
  297. package/dist/tools/kanban.js +28 -19
  298. package/dist/tools/kanban.js.map +1 -1
  299. package/dist/tools/memory-masks.d.ts +5 -0
  300. package/dist/tools/memory-masks.js +256 -0
  301. package/dist/tools/memory-masks.js.map +1 -0
  302. package/dist/tools/memory.d.ts +29 -3
  303. package/dist/tools/memory.js +69 -27
  304. package/dist/tools/memory.js.map +1 -1
  305. package/dist/tools/plugin-settings.d.ts +15 -0
  306. package/dist/tools/plugin-settings.js +90 -0
  307. package/dist/tools/plugin-settings.js.map +1 -0
  308. package/dist/tools/skills.d.ts +9 -4
  309. package/dist/tools/skills.js +44 -13
  310. package/dist/tools/skills.js.map +1 -1
  311. package/dist/tools/update-notifications.d.ts +34 -15
  312. package/dist/tools/update-notifications.js +141 -57
  313. package/dist/tools/update-notifications.js.map +1 -1
  314. package/dist/tools/update-rollback.d.ts +11 -0
  315. package/dist/tools/update-rollback.js +28 -0
  316. package/dist/tools/update-rollback.js.map +1 -0
  317. package/dist/tools/updates.d.ts +93 -33
  318. package/dist/tools/updates.js +1051 -345
  319. package/dist/tools/updates.js.map +1 -1
  320. package/dist/util.d.ts +2 -0
  321. package/dist/util.js +5 -0
  322. package/dist/util.js.map +1 -1
  323. package/dist/workspace/git.d.ts +16 -1
  324. package/dist/workspace/git.js +291 -11
  325. package/dist/workspace/git.js.map +1 -1
  326. package/dist/workspace/media.d.ts +12 -9
  327. package/dist/workspace/media.js +31 -20
  328. package/dist/workspace/media.js.map +1 -1
  329. package/dist/workspace/rollback.d.ts +2 -2
  330. package/dist/workspace/rollback.js +5 -5
  331. package/dist/workspace/rollback.js.map +1 -1
  332. package/dist/workspace/workspaces.d.ts +15 -19
  333. package/dist/workspace/workspaces.js +55 -127
  334. package/dist/workspace/workspaces.js.map +1 -1
  335. package/dist/workspace/worktrees.js +170 -32
  336. package/dist/workspace/worktrees.js.map +1 -1
  337. package/package.json +5 -3
  338. package/sidecar/agent_dependency.json +4 -4
  339. package/sidecar/agent_support.json +26 -0
  340. package/sidecar/scripts/record-fixtures.py +12 -3
  341. package/sidecar/scripts/replay_sidecar.py +8 -0
  342. package/sidecar/scripts/suite_runner.py +302 -0
  343. package/sidecar/scripts/test.sh +12 -4
  344. package/sidecar/talaria_sidecar/__init__.py +6 -1
  345. package/sidecar/talaria_sidecar/__main__.py +4 -2
  346. package/sidecar/talaria_sidecar/agent_mutation.py +975 -0
  347. package/sidecar/talaria_sidecar/agent_services.py +1053 -0
  348. package/sidecar/talaria_sidecar/dependency_sync.py +85 -0
  349. package/sidecar/talaria_sidecar/home.py +43 -1
  350. package/sidecar/talaria_sidecar/methods/__init__.py +2 -2
  351. package/sidecar/talaria_sidecar/methods/aux.py +139 -31
  352. package/sidecar/talaria_sidecar/methods/chat.py +847 -134
  353. package/sidecar/talaria_sidecar/methods/commands.py +213 -4
  354. package/sidecar/talaria_sidecar/methods/config.py +123 -4
  355. package/sidecar/talaria_sidecar/methods/connectors.py +343 -0
  356. package/sidecar/talaria_sidecar/methods/cron.py +366 -34
  357. package/sidecar/talaria_sidecar/methods/cron_execution.py +284 -0
  358. package/sidecar/talaria_sidecar/methods/gateway.py +194 -54
  359. package/sidecar/talaria_sidecar/methods/gateway_sessions.py +234 -0
  360. package/sidecar/talaria_sidecar/methods/goals.py +81 -41
  361. package/sidecar/talaria_sidecar/methods/kanban.py +80 -27
  362. package/sidecar/talaria_sidecar/methods/memory.py +84 -0
  363. package/sidecar/talaria_sidecar/methods/oauth.py +5 -2
  364. package/sidecar/talaria_sidecar/methods/process.py +160 -11
  365. package/sidecar/talaria_sidecar/methods/profiles.py +44 -6
  366. package/sidecar/talaria_sidecar/methods/providers.py +196 -26
  367. package/sidecar/talaria_sidecar/methods/runtime.py +69 -1
  368. package/sidecar/talaria_sidecar/methods/skills.py +67 -4
  369. package/sidecar/talaria_sidecar/methods/state_db.py +277 -70
  370. package/sidecar/talaria_sidecar/methods/stt.py +159 -78
  371. package/sidecar/talaria_sidecar/methods/text.py +14 -1
  372. package/sidecar/talaria_sidecar/methods/toolsets.py +49 -0
  373. package/sidecar/talaria_sidecar/methods/usage.py +113 -14
  374. package/sidecar/talaria_sidecar/methods/worktree.py +26 -19
  375. package/sidecar/talaria_sidecar/methods/write_approval.py +181 -0
  376. package/sidecar/talaria_sidecar/rpc.py +45 -4
  377. package/sidecar/talaria_sidecar/runtime.py +81 -12
  378. package/sidecar/talaria_sidecar/speed.py +35 -0
  379. package/static/dist/FILES.txt +126 -127
  380. package/static/dist/assets/AppShell-cey33v9s.js +8 -0
  381. package/static/dist/assets/ChatPage-i8wnugr7.js +18 -0
  382. package/static/dist/assets/ConnectTargets-hg19553x.js +1 -0
  383. package/static/dist/assets/ExtensionRoute-cly4apm5.js +1 -0
  384. package/static/dist/assets/Field-j8uqoigz.js +9 -0
  385. package/static/dist/assets/HubRoute-e4bgz41j.js +2 -0
  386. package/static/dist/assets/Markdown-lahuichm.js +598 -0
  387. package/static/dist/assets/RightPanel-lbo4i0fn.js +1 -0
  388. package/static/dist/assets/Select-gqatm2e0.js +1 -0
  389. package/static/dist/assets/SessionListPanel-mfqayfjh.js +1 -0
  390. package/static/dist/assets/SettingsLayout-b8980u7k.js +1 -0
  391. package/static/dist/assets/States-e7dkgtxf.js +1 -0
  392. package/static/dist/assets/Toaster-bfqqy786.js +1 -0
  393. package/static/dist/assets/_app-n1n6pfx1.js +1 -0
  394. package/static/dist/assets/{_app.ext._extensionId-gfbzpoou.js → _app.ext._extensionId-buxjxav3.js} +1 -1
  395. package/static/dist/assets/_app.index-jt8zwiu2.js +1 -0
  396. package/static/dist/assets/_app.insights-cv76ml71.js +1 -0
  397. package/static/dist/assets/_app.kanban-h6ts53j7.js +1 -0
  398. package/static/dist/assets/_app.logs-dm873z90.js +1 -0
  399. package/static/dist/assets/_app.memory-glk5y6m8.js +1 -0
  400. package/static/dist/assets/_app.profiles-ka6zpstq.js +1 -0
  401. package/static/dist/assets/{_app.session._sessionId-fn1bhde6.js → _app.session._sessionId-g2vzghvc.js} +1 -1
  402. package/static/dist/assets/_app.settings-hgjdhzcd.js +1 -0
  403. package/static/dist/assets/_app.settings._section-jf2kmhae.js +3 -0
  404. package/static/dist/assets/_app.skills-cii852yq.js +1 -0
  405. package/static/dist/assets/_app.tasks-fp9q7atm.js +1 -0
  406. package/static/dist/assets/_app.todos-dw94qzue.js +1 -0
  407. package/static/dist/assets/_app.workspaces-inyygzze.js +1 -0
  408. package/static/dist/assets/{abnfDiagram-VCTEODGH-c8kdixke.js → abnfDiagram-VCTEODGH-gjayq3ra.js} +1 -1
  409. package/static/dist/assets/architecture-7GRP2DOG-lp56972r.js +1 -0
  410. package/static/dist/assets/{architectureDiagram-5GKGNRK7-cku06x1p.js → architectureDiagram-5GKGNRK7-nwb3xovn.js} +1 -1
  411. package/static/dist/assets/archive-b1j004vn.js +1 -0
  412. package/static/dist/assets/back-g74gkozu.js +1 -0
  413. package/static/dist/assets/{blockDiagram-I7D4REHJ-jzthp1wa.js → blockDiagram-I7D4REHJ-joedghi3.js} +1 -1
  414. package/static/dist/assets/{c4Diagram-7LVT6UL2-mwr67mt8.js → c4Diagram-7LVT6UL2-hyrjrohe.js} +1 -1
  415. package/static/dist/assets/channel-es95o4y8.js +1 -0
  416. package/static/dist/assets/{chunk-4HAMMTFA-gpq1y228.js → chunk-4HAMMTFA-koouqbut.js} +1 -1
  417. package/static/dist/assets/{chunk-75Z2AOVW-ktje58c4.js → chunk-75Z2AOVW-bl4bhdnt.js} +1 -1
  418. package/static/dist/assets/{chunk-DU6HZSFF-ofajdixh.js → chunk-DU6HZSFF-gpedttsp.js} +3 -3
  419. package/static/dist/assets/{chunk-F27PBJKO-cmev85ti.js → chunk-F27PBJKO-d8xxi0zi.js} +1 -1
  420. package/static/dist/assets/{chunk-GMAD6QVW-htjgt22y.js → chunk-GMAD6QVW-jro0hl73.js} +1 -1
  421. package/static/dist/assets/{chunk-GVQU2GXP-qndvoxl7.js → chunk-GVQU2GXP-djn6gbyu.js} +1 -1
  422. package/static/dist/assets/{chunk-IMKFNOWR-e5bkd5q6.js → chunk-IMKFNOWR-vw4p5p7o.js} +1 -1
  423. package/static/dist/assets/{chunk-L3NEJ4N5-mj1155r6.js → chunk-L3NEJ4N5-n1hj77q8.js} +1 -1
  424. package/static/dist/assets/{chunk-OSK3NFVY-e7gkikcw.js → chunk-OSK3NFVY-oy0gwn2n.js} +1 -1
  425. package/static/dist/assets/{chunk-P2QGCYS3-f7t54xfm.js → chunk-P2QGCYS3-onf1hz6c.js} +1 -1
  426. package/static/dist/assets/{chunk-POPQ4Y6H-i927v9oa.js → chunk-POPQ4Y6H-m8sqn7cs.js} +1 -1
  427. package/static/dist/assets/{chunk-PWAF6VOD-m84lmnyt.js → chunk-PWAF6VOD-ek4smc8x.js} +1 -1
  428. package/static/dist/assets/{chunk-SHT3W25Y-mi0tlcu9.js → chunk-SHT3W25Y-g9gfvefo.js} +3 -3
  429. package/static/dist/assets/{chunk-SVP7TREG-dnau702j.js → chunk-SVP7TREG-f9nfv2cu.js} +1 -1
  430. package/static/dist/assets/{chunk-TICWLB2K-edem1gkg.js → chunk-TICWLB2K-bnk3m1mq.js} +1 -1
  431. package/static/dist/assets/classDiagram-ZZMXUADV-kmihoqxh.js +1 -0
  432. package/static/dist/assets/classDiagram-v2-VYDZK3BY-kmihoqxh.js +1 -0
  433. package/static/dist/assets/copied-bli9tbcx.js +1 -0
  434. package/static/dist/assets/{copy-magtofyp.js → copy-jamtd1pf.js} +1 -1
  435. package/static/dist/assets/{cynefin-OW5HDTMX-siqlulkl.js → cynefin-OW5HDTMX-f8xfdd3f.js} +1 -1
  436. package/static/dist/assets/{cynefinDiagram-5FMLGOSQ-i648tah9.js → cynefinDiagram-5FMLGOSQ-n9lb99h9.js} +1 -1
  437. package/static/dist/assets/{dagre-GXQ25YYZ-mwn6uc17.js → dagre-GXQ25YYZ-dgailddi.js} +4 -4
  438. package/static/dist/assets/{diagram-S7CK7UJ4-l8abxaes.js → diagram-S7CK7UJ4-m6aeoe7c.js} +1 -1
  439. package/static/dist/assets/{diagram-UQ7AKVKN-mekq7zgq.js → diagram-UQ7AKVKN-jall3j0x.js} +1 -1
  440. package/static/dist/assets/{diagram-VSXAHHWV-fnky6lvc.js → diagram-VSXAHHWV-hbawi7hn.js} +1 -1
  441. package/static/dist/assets/{diagram-VX7I27RA-xe6r5qfw.js → diagram-VX7I27RA-hendl2tt.js} +1 -1
  442. package/static/dist/assets/{diagram-Z3DM3KII-nq07dg7k.js → diagram-Z3DM3KII-igwc35p3.js} +1 -1
  443. package/static/dist/assets/{ebnfDiagram-PWID7BFC-c62ipm3g.js → ebnfDiagram-PWID7BFC-c64knz08.js} +1 -1
  444. package/static/dist/assets/{erDiagram-RLTQ6QDP-h39kmnzy.js → erDiagram-RLTQ6QDP-brdu9lcm.js} +1 -1
  445. package/static/dist/assets/eventmodeling-NTZA5JFV-njk1j8wl.js +1 -0
  446. package/static/dist/assets/flowDiagram-HODETNUW-nma6f0ga.js +1 -0
  447. package/static/dist/assets/folder-plus-lvt9kudb.js +1 -0
  448. package/static/dist/assets/{ganttDiagram-EL5Y4UJY-ngbsyp37.js → ganttDiagram-EL5Y4UJY-ma6jxj5i.js} +1 -1
  449. package/static/dist/assets/{gitGraph-4MIJSDKK-fr2i7caa.js → gitGraph-4MIJSDKK-naa9w6xa.js} +1 -1
  450. package/static/dist/assets/{gitGraphDiagram-WWUBYQGX-eravdti4.js → gitGraphDiagram-WWUBYQGX-hzltvsod.js} +1 -1
  451. package/static/dist/assets/{highlighted-body-KPVGNVTW-jwpop9p8.js → highlighted-body-KPVGNVTW-ghoavj8d.js} +1 -1
  452. package/static/dist/assets/host-hzm8n85n.js +1 -0
  453. package/static/dist/assets/index-drdcaqeq.css +2 -0
  454. package/static/dist/assets/index-jzm844he.js +11 -0
  455. package/static/dist/assets/{info-A6RAGUB7-h11x0dxo.js → info-A6RAGUB7-mn2ut5ko.js} +1 -1
  456. package/static/dist/assets/{infoDiagram-27XIBGKW-dfh47dw9.js → infoDiagram-27XIBGKW-h6kuqvsb.js} +1 -1
  457. package/static/dist/assets/{ishikawaDiagram-5VMMS53U-i6ypq351.js → ishikawaDiagram-5VMMS53U-e7bnwq7h.js} +1 -1
  458. package/static/dist/assets/{journeyDiagram-3NMN7TZE-lduf1z95.js → journeyDiagram-3NMN7TZE-etd1bi6p.js} +1 -1
  459. package/static/dist/assets/{kanban-definition-UXKFOSKX-e18bu4pg.js → kanban-definition-UXKFOSKX-emb1g9dz.js} +4 -4
  460. package/static/dist/assets/lazyRouteComponent-o816ytzl.js +1 -0
  461. package/static/dist/assets/{line-meizqsvn.js → line-h0ojzsvs.js} +1 -1
  462. package/static/dist/assets/link-k01ryaf9.js +1 -0
  463. package/static/dist/assets/login-bsae49ew.js +1 -0
  464. package/static/dist/assets/mermaid-HWGCJPDP-ihl34s74.js +1 -0
  465. package/static/dist/assets/{mermaid-parser.core-ntne45i9.js → mermaid-parser.core-bnre27u8.js} +3 -3
  466. package/static/dist/assets/{mindmap-definition-YA3MSWOX-27b26eok.js → mindmap-definition-YA3MSWOX-o1vathns.js} +1 -1
  467. package/static/dist/assets/onboarding-c65tysya.js +1 -0
  468. package/static/dist/assets/onboarding_model_label-gpn28uix.js +1 -0
  469. package/static/dist/assets/{packet-AYTQ26CC-l6jdka8p.js → packet-AYTQ26CC-hatq7m2e.js} +1 -1
  470. package/static/dist/assets/pcmTap.worklet-74EKjWAZ.js +1 -0
  471. package/static/dist/assets/{pegDiagram-XKGWAZYB-g1er3bxj.js → pegDiagram-XKGWAZYB-gwisz8jv.js} +1 -1
  472. package/static/dist/assets/{pie-WAS4IAKB-i0ylcrt9.js → pie-WAS4IAKB-fpftf0mk.js} +1 -1
  473. package/static/dist/assets/{pieDiagram-E7YTZNPT-fbz1e55z.js → pieDiagram-E7YTZNPT-khm1o9a6.js} +1 -1
  474. package/static/dist/assets/{quadrantDiagram-AXDQQJYC-hhue7d8o.js → quadrantDiagram-AXDQQJYC-owqc4uqn.js} +1 -1
  475. package/static/dist/assets/{radar-RG4KPBEZ-f9b70aa4.js → radar-RG4KPBEZ-cntfwjpq.js} +1 -1
  476. package/static/dist/assets/{railroad-74A4TZTK-lgsuoeda.js → railroad-74A4TZTK-a7t5eibp.js} +1 -1
  477. package/static/dist/assets/railroad-abnf-HS5TGJTU-ol8cdktf.js +1 -0
  478. package/static/dist/assets/railroad-ebnf-LZEXJU2U-i8vzd429.js +1 -0
  479. package/static/dist/assets/railroad-peg-WCYAUIDC-nw3ulewz.js +1 -0
  480. package/static/dist/assets/{railroadDiagram-O6MQD6OU-eqpy9fnz.js → railroadDiagram-O6MQD6OU-etuh0qa0.js} +1 -1
  481. package/static/dist/assets/{refresh-cw-hlwb02qv.js → refresh-cw-mqbkv2a3.js} +1 -1
  482. package/static/dist/assets/refresh-l29ljp76.js +1 -0
  483. package/static/dist/assets/{requirementDiagram-BXWQKSXE-ogf6puhi.js → requirementDiagram-BXWQKSXE-oq2ulk22.js} +1 -1
  484. package/static/dist/assets/{sankeyDiagram-P5KCCOFB-fqb8xcjf.js → sankeyDiagram-P5KCCOFB-iqc02emv.js} +1 -1
  485. package/static/dist/assets/saved-ndd4t2xb.js +1 -0
  486. package/static/dist/assets/{sequenceDiagram-WJ2MYXX4-dlcz6qjz.js → sequenceDiagram-WJ2MYXX4-i0v116q0.js} +2 -2
  487. package/static/dist/assets/settings_section_extensions_title-jhfo6o8z.js +1 -0
  488. package/static/dist/assets/share._token-c1ri0hy1.js +2 -0
  489. package/static/dist/assets/sliders-horizontal-j3jjt9tv.js +1 -0
  490. package/static/dist/assets/{stateDiagram-D77RDMKH-fyoznpcs.js → stateDiagram-D77RDMKH-dnpt1ato.js} +1 -1
  491. package/static/dist/assets/stateDiagram-v2-MP3YSRHH-bxjacpk6.js +1 -0
  492. package/static/dist/assets/{swimlanes-42K2YHIH-oefldhfy.js → swimlanes-42K2YHIH-loqbdazb.js} +1 -1
  493. package/static/dist/assets/swimlanesDiagram-VR7AAH4N-id62p9hz.js +8 -0
  494. package/static/dist/assets/{timeline-definition-24CTP7MA-b1vl2zil.js → timeline-definition-24CTP7MA-ol2hnvma.js} +1 -1
  495. package/static/dist/assets/toast-i3h34v6o.js +64 -0
  496. package/static/dist/assets/{treeView-Q6P3EWNA-f7hcci5o.js → treeView-Q6P3EWNA-idrj6iox.js} +1 -1
  497. package/static/dist/assets/{treemap-WGGIJYW6-nl85071a.js → treemap-WGGIJYW6-lzr49vv5.js} +1 -1
  498. package/static/dist/assets/untitled-oaoya4qj.js +1 -0
  499. package/static/dist/assets/useForm-nfaxgmsk.js +1 -0
  500. package/static/dist/assets/{useParams-b4dq6n4q.js → useParams-gjc70qru.js} +1 -1
  501. package/static/dist/assets/{useSearch-ipfmv3he.js → useSearch-e6ae539u.js} +1 -1
  502. package/static/dist/assets/{vennDiagram-4TSXK5OY-h5hzbk0n.js → vennDiagram-4TSXK5OY-bvwr9o2z.js} +1 -1
  503. package/static/dist/assets/{wardley-WFR3VGLG-jftvpm3e.js → wardley-WFR3VGLG-31ui8tma.js} +1 -1
  504. package/static/dist/assets/{wardleyDiagram-VM6X3IG4-hedh85ge.js → wardleyDiagram-VM6X3IG4-k5wqtx4b.js} +1 -1
  505. package/static/dist/assets/{xychartDiagram-S5SC5T6Z-e49523ab.js → xychartDiagram-S5SC5T6Z-aqbgvujg.js} +1 -1
  506. package/static/dist/index.html +1 -1
  507. package/static/dist/sw.js +1 -1
  508. package/static/dist/assets/AppShell-g3bkgnvt.js +0 -1
  509. package/static/dist/assets/ChatPage-oo7bdan6.js +0 -25
  510. package/static/dist/assets/Dialog-g355qxhp.js +0 -1
  511. package/static/dist/assets/ExtensionRoute-i2y9fvjm.js +0 -1
  512. package/static/dist/assets/HubRoute-lmkrbw47.js +0 -2
  513. package/static/dist/assets/Markdown-j4kut4j2.js +0 -598
  514. package/static/dist/assets/RightPanel-ohlsdzfl.js +0 -1
  515. package/static/dist/assets/Select-kddq75qc.js +0 -1
  516. package/static/dist/assets/SessionListPanel-lu3oy0hw.js +0 -1
  517. package/static/dist/assets/SettingsLayout-o9bv4mgb.js +0 -1
  518. package/static/dist/assets/States-eq6fe29m.js +0 -1
  519. package/static/dist/assets/Toaster-pc247u9f.js +0 -1
  520. package/static/dist/assets/_app-f8n1i0m1.js +0 -1
  521. package/static/dist/assets/_app.index-bzzv80hk.js +0 -1
  522. package/static/dist/assets/_app.insights-dzixbryi.js +0 -1
  523. package/static/dist/assets/_app.kanban-c6hep2us.js +0 -1
  524. package/static/dist/assets/_app.logs-i69qds98.js +0 -1
  525. package/static/dist/assets/_app.memory-kl4vf0gd.js +0 -1
  526. package/static/dist/assets/_app.profiles-b8zinmyp.js +0 -1
  527. package/static/dist/assets/_app.settings-cg8plwmf.js +0 -1
  528. package/static/dist/assets/_app.settings._section-bkwbi9zn.js +0 -3
  529. package/static/dist/assets/_app.skills-cs47sbvs.js +0 -1
  530. package/static/dist/assets/_app.tasks-dwvk64tc.js +0 -1
  531. package/static/dist/assets/_app.todos-c8xjm8p3.js +0 -1
  532. package/static/dist/assets/_app.workspaces-ehvd1gds.js +0 -1
  533. package/static/dist/assets/architecture-7GRP2DOG-6crvnylg.js +0 -1
  534. package/static/dist/assets/back-h7aun7ew.js +0 -1
  535. package/static/dist/assets/cancel-fhi0vcnu.js +0 -1
  536. package/static/dist/assets/channel-b2zo73z1.js +0 -1
  537. package/static/dist/assets/classDiagram-ZZMXUADV-oe99st8x.js +0 -1
  538. package/static/dist/assets/classDiagram-v2-VYDZK3BY-oe99st8x.js +0 -1
  539. package/static/dist/assets/copied-hcplv46p.js +0 -1
  540. package/static/dist/assets/endpoints-klbxod4t.js +0 -64
  541. package/static/dist/assets/eventmodeling-NTZA5JFV-obfede4u.js +0 -1
  542. package/static/dist/assets/flowDiagram-HODETNUW-kdpsp1je.js +0 -1
  543. package/static/dist/assets/host-i828xuo7.js +0 -1
  544. package/static/dist/assets/index-eh8zilnv.css +0 -2
  545. package/static/dist/assets/index-r648f4o1.js +0 -11
  546. package/static/dist/assets/lazyRouteComponent-e1y4t2i9.js +0 -1
  547. package/static/dist/assets/link-oot2yn73.js +0 -1
  548. package/static/dist/assets/login-gu28l9ou.js +0 -1
  549. package/static/dist/assets/mermaid-HWGCJPDP-mtwrj8fn.js +0 -1
  550. package/static/dist/assets/onboarding-lkphzu1s.js +0 -1
  551. package/static/dist/assets/onboarding_model_label-ftpjdwqk.js +0 -1
  552. package/static/dist/assets/railroad-abnf-HS5TGJTU-nf9d6pdx.js +0 -1
  553. package/static/dist/assets/railroad-ebnf-LZEXJU2U-f7ummkt5.js +0 -1
  554. package/static/dist/assets/railroad-peg-WCYAUIDC-oczq5tqs.js +0 -1
  555. package/static/dist/assets/refresh-abtu93ke.js +0 -1
  556. package/static/dist/assets/saved-girnabkf.js +0 -1
  557. package/static/dist/assets/settings_section_extensions_title-h14cwk6f.js +0 -1
  558. package/static/dist/assets/share._token-kl0r7ido.js +0 -2
  559. package/static/dist/assets/sliders-horizontal-n1zm34qq.js +0 -1
  560. package/static/dist/assets/sse-iwku0sjo.js +0 -1
  561. package/static/dist/assets/stateDiagram-v2-MP3YSRHH-ixhx8r46.js +0 -1
  562. package/static/dist/assets/swimlanesDiagram-VR7AAH4N-h9ersk2e.js +0 -8
  563. package/static/dist/assets/todoStore-jjr5yr78.js +0 -1
  564. package/static/dist/assets/units-kgxzxfhi.js +0 -1
  565. package/static/dist/assets/untitled-cikfjntn.js +0 -1
  566. package/static/dist/assets/useForm-kqoqg0k9.js +0 -1
  567. package/static/dist/assets/useLocale-o59tbiea.js +0 -1
package/dist/runtime.js CHANGED
@@ -1,6 +1,6 @@
1
1
  import { AsyncLocalStorage } from 'node:async_hooks';
2
2
  import { pinnedFetch, systemDnsLookup } from './http/pinned.js';
3
- import { mkdirSync, readFileSync } from 'node:fs';
3
+ import { mkdirSync, readdirSync, readFileSync } from 'node:fs';
4
4
  import { resolve } from 'node:path';
5
5
  import { AuthStore } from './auth/store.js';
6
6
  import { OidcService } from './auth/oidc.js';
@@ -9,6 +9,7 @@ import { PresenceLeases, RelayService } from './sessions/relay.js';
9
9
  import { CliSessionSource } from './sessions/cli-sessions.js';
10
10
  import { ClaudeCodeSessionSource, claudeCodeProjectsDir } from './sessions/claude-code.js';
11
11
  import { GatewayWatcherRegistry } from './sessions/gateway-watcher.js';
12
+ import { GatewaySessions, gatewayStreamVisible } from './sessions/gateway-sessions.js';
12
13
  import { readImportableAgentSessionRowsAsync } from './sessions/state-db.js';
13
14
  import { CompletionDrain } from './sessions/completions.js';
14
15
  import { BackgroundActivity, BackgroundTaskStore } from './sessions/background-tasks.js';
@@ -23,6 +24,7 @@ import { displayBotName, pyBool, SettingsStore } from './settings.js';
23
24
  import { AssetCache, SpaShell } from './spa.js';
24
25
  import { StartupGate } from './startup.js';
25
26
  import { SessionStore } from './sessions/store.js';
27
+ import { JsonStorage } from './sessions/storage/json.js';
26
28
  import { DraftStore } from './sessions/drafts.js';
27
29
  import { SessionEventBus } from './sessions/events.js';
28
30
  import { ShareStore } from './sessions/shares.js';
@@ -40,7 +42,6 @@ import { EscapeGrants } from './workspace/escape.js';
40
42
  import { TurnRunner } from './sessions/turn.js';
41
43
  import { SessionChannels, StreamRegistry } from './sessions/streams.js';
42
44
  import { PendingPrompts } from './sessions/pending.js';
43
- import { RunJournal } from './sessions/journal.js';
44
45
  import { StreamSlots } from './api/sse-routes.js';
45
46
  import { AgentConfig, coerceProviderCostBudgetValue, dict as asDict, parseProviderQualifiedModel } from './config/agent-config.js';
46
47
  import { ProviderCatalog } from './providers/catalog.js';
@@ -53,7 +54,8 @@ import { CronService } from './tools/crons.js';
53
54
  import { KanbanService } from './tools/kanban.js';
54
55
  import { DashboardPlugins } from './tools/dashboard-plugins.js';
55
56
  import { ExtensionService } from './tools/extensions.js';
56
- import { dashboardStatus } from './tools/health.js';
57
+ import { dashboardStatus, gatewayRestartBlockers } from './tools/health.js';
58
+ import { GatewayRestartQueue, restartGateway } from './tools/gateway-restart.js';
57
59
  import { TerminalRegistry } from './tools/terminal.js';
58
60
  export function packageVersion() {
59
61
  try {
@@ -63,40 +65,44 @@ export function packageVersion() {
63
65
  return undefined;
64
66
  }
65
67
  }
66
- export function createDeps(opts) {
68
+ export async function createDeps(opts) {
67
69
  const log = opts.log ?? ((line) => { console.log(line); });
68
70
  const config = loadConfig(opts);
69
71
  const env = config.env;
70
72
  mkdirSync(config.stateDir, { recursive: true });
71
73
  mkdirSync(config.sessionDir, { recursive: true });
72
- const settings = new SettingsStore({ file: config.settingsFile, env, stateDir: config.stateDir, defaultWorkspace: config.defaultWorkspace, botName: config.botName, log });
73
74
  const now = opts.now ?? (() => Date.now() / 1000);
74
- const passkeys = new PasskeyStore(config.stateDir, now);
75
+ const storage = opts.storage?.(config) ?? createStorage(config, now, (name) => profileHome(name));
76
+ const settings = new SettingsStore({ documents: storage.documents, env, stateDir: config.stateDir, defaultWorkspace: config.defaultWorkspace, botName: config.botName, log });
77
+ await settings.load();
78
+ const passkeys = new PasskeyStore(storage.documents, now);
75
79
  // Resolved below once the sidecar-backed config store exists; the auth store reads it lazily.
76
80
  let oidc = null;
77
81
  let operatorConfigPeek = () => null;
78
82
  const auth = new AuthStore({
79
- stateDir: config.stateDir, env, settings, log, now,
80
- passkeysEnabled: () => passkeys.available(),
83
+ documents: storage.documents, env, settings, log, now,
84
+ passkeysEnabled: async () => (await passkeys.available()),
81
85
  oidcEnabled: () => oidc?.enabledSync() ?? false,
82
86
  oidcAvailable: () => oidc?.availableSync() ?? false,
83
87
  oidcProbe: () => oidc?.resolve() ?? Promise.resolve(),
84
88
  passkeyConfigFlag: () => { const cfg = operatorConfigPeek(); return cfg === null ? null : cfg.webui_passkey_enabled; },
85
89
  });
90
+ await auth.initialize();
86
91
  settings.hooks = {
87
- hashPassword: (pw) => auth.hashPassword(pw),
92
+ hashPassword: async (pw) => (await auth.hashPassword(pw)),
88
93
  onPasswordChanged: () => { auth.invalidatePasswordHashCache(); },
89
94
  };
90
- settings.applyStartupWorkspace();
95
+ await settings.applyStartupWorkspace();
91
96
  config.defaultWorkspace = settings.defaultWorkspace;
92
97
  const release = loadReleaseInfo({ webRoot: config.webRoot });
93
98
  const stampedRelease = loadReleaseInfo({ webRoot: config.webRoot }, { verifyCheckout: false });
94
99
  const runningSourceRevision = checkoutRevision(config.webRoot);
95
100
  // Container images bake `TALARIA_WEB_VERSION` (Python `api/_version.py`) because .git is not shipped.
96
101
  const version = opts.version ?? detectWebuiVersion(release, config.webRoot, (env.TALARIA_WEB_VERSION ?? '').trim() || packageVersion());
97
- const updateNotifications = new UpdateNotificationStore(config.stateDir, () => new Date(now() * 1000));
102
+ const updateNotifications = new UpdateNotificationStore(storage.documents, () => new Date(now() * 1000));
103
+ await updateNotifications.initialize();
98
104
  const verifiedRunningVersion = /^web-(?:exp-)?v\d+\.\d+\.\d+$/.test(version) ? version : null;
99
- updateNotifications.reconcileInterruptedUpdates(runningSourceRevision ?? release.sourceRevision, verifiedRunningVersion);
105
+ await updateNotifications.reconcileInterruptedUpdates(runningSourceRevision ?? release.sourceRevision, verifiedRunningVersion);
100
106
  const home = opts.home ?? config.homeDir;
101
107
  const PROFILE_RE = /^[a-z0-9][a-z0-9_-]{0,63}$/;
102
108
  // Python `init_profile_state` + `switch_profile(process_wide=False)`: the sticky `~/.hermes/active_profile` is
@@ -128,7 +134,7 @@ export function createDeps(opts) {
128
134
  if (profile && !isRootProfile(profile))
129
135
  return profile.charAt(0).toUpperCase() + profile.slice(1);
130
136
  try {
131
- return displayBotName(settings.load().bot_name);
137
+ return displayBotName(settings.peek().bot_name);
132
138
  }
133
139
  catch {
134
140
  return displayBotName(null);
@@ -147,6 +153,20 @@ export function createDeps(opts) {
147
153
  throw new ProfileError(escapedProfileMessage(name), 400);
148
154
  return contained;
149
155
  };
156
+ const agentHomes = () => {
157
+ if (isolatedProfileMode())
158
+ return [baseHome];
159
+ let names;
160
+ try {
161
+ names = readdirSync(join(baseHome, 'profiles'));
162
+ }
163
+ catch (error) {
164
+ if (error.code !== 'ENOENT')
165
+ throw error;
166
+ names = [];
167
+ }
168
+ return [...new Set([baseHome, ...names.filter((name) => PROFILE_RE.test(name)).map(profileHome)])];
169
+ };
150
170
  const attachmentRoot = () => {
151
171
  const override = (env.HERMES_WEBUI_ATTACHMENT_DIR ?? '').trim();
152
172
  return resolvePathLikePython(override ? override.replace(/^~(?=$|\/)/, home) : join(config.stateDir, 'attachments'));
@@ -168,12 +188,12 @@ export function createDeps(opts) {
168
188
  return [typeof d === 'string' ? d.trim() : '', typeof p === 'string' && p ? p : null];
169
189
  };
170
190
  const events = new SessionEventBus(isRootProfile);
171
- const drafts = new DraftStore(config.sessionDir);
172
- const registry = new StreamRegistry();
191
+ const drafts = new DraftStore(storage.documents);
192
+ const registry = new StreamRegistry((id) => gatewayStreamVisible(id, profileHome(activeProfile())));
173
193
  const activeStreamIds = registry.liveIds;
174
194
  const runningCronJobs = new Map();
175
195
  const workspaces = new WorkspaceRegistry({
176
- stateDir: config.stateDir,
196
+ documents: storage.documents,
177
197
  defaultWorkspace: () => config.defaultWorkspace,
178
198
  profileHome,
179
199
  activeProfile,
@@ -192,34 +212,34 @@ export function createDeps(opts) {
192
212
  return Number.isFinite(raw) && raw >= 1 ? raw : 100;
193
213
  };
194
214
  const store = new SessionStore({
195
- sessionDir: config.sessionDir,
215
+ storage,
196
216
  drafts,
197
217
  events,
198
218
  // Python `_profile_default_model_state`: the profile's own config.yaml model, else the global default. The provider
199
219
  // always comes with its model, so a provider-only profile never pairs with another profile's model.
200
- defaults: (profile) => {
220
+ defaults: async (profile) => {
201
221
  let [model, provider] = profileDefaultModel(profile);
202
222
  if (!model) {
203
- const s = settings.load();
223
+ const s = settings.peek();
204
224
  model = typeof s.default_model === 'string' ? s.default_model : '';
205
225
  provider = model && typeof s.default_model_provider === 'string' && s.default_model_provider ? s.default_model_provider : null;
206
226
  }
207
227
  const [bare, modelProvider] = parseProviderQualifiedModel(model) ?? [model || null, provider];
208
- return { workspace: workspaces.lastWorkspace(profile), model: bare, modelProvider };
228
+ return { workspace: (await workspaces.lastWorkspace(profile)), model: bare, modelProvider };
209
229
  },
210
230
  activeStreamIds: () => activeStreamIds,
211
231
  now,
212
232
  log,
213
233
  cacheMax,
214
- onDeleted: (sid) => { backgroundStore.evict(sid); },
234
+ onDeleted: async (sid) => { (await backgroundStore.delete(sid)); },
215
235
  });
216
- const projects = new ProjectStore(resolve(config.stateDir, 'projects.json'), () => store.readIndexEntries(), isRootProfile);
217
- const shares = new ShareStore(resolve(config.stateDir, 'shares'), now);
236
+ const projects = new ProjectStore(storage.documents, async () => (await store.readIndexEntries()), isRootProfile);
237
+ const shares = new ShareStore(storage.documents, now);
218
238
  const yoloSessions = new Set();
219
239
  const attachmentDir = (sid) => join(attachmentRoot(), (sid || 'session').replace(/[^\w.-]/g, '_').slice(0, 120));
220
- const cliSessions = new CliSessionSource({ store, profileHome, lastWorkspace: (p) => workspaces.lastWorkspace(p), backgroundProjectId: (kind, p) => projects.ensureSystemProject(kind, p, { create: kind === 'webhook' || projects.hasUserProjects(p) }), now, log });
240
+ const cliSessions = new CliSessionSource({ store, profileHome, profilesMatch, lastWorkspace: async (p) => (await workspaces.lastWorkspace(p)), backgroundProjectId: async (kind, p) => (await projects.ensureSystemProject(kind, p, { create: kind === 'webhook' || (await projects.hasUserProjects(p)) })), now, log });
221
241
  const gatewayWatchers = new GatewayWatcherRegistry({ profileHome, now, log, ...(opts.gatewayPollMs !== undefined ? { pollIntervalMs: opts.gatewayPollMs } : {}) });
222
- const journal = new RunJournal(config.sessionDir, env);
242
+ const journal = storage.journals;
223
243
  const contextLengths = new Map();
224
244
  const contextInflight = new Map();
225
245
  const contextKey = (model, provider, profile) => (model?.trim() ? `${profileHome(profile ?? activeProfile())}\0${provider?.trim() ?? ''}\0${model.trim()}` : null);
@@ -259,11 +279,11 @@ export function createDeps(opts) {
259
279
  profileOps.delete(key);
260
280
  };
261
281
  };
262
- const mediaActiveWorkspace = () => {
282
+ const mediaActiveWorkspace = async () => {
263
283
  if (!workspaces.profileSupportsLocalIo(null))
264
284
  return null;
265
285
  try {
266
- const ws = resolvePathLikePython(workspaces.lastWorkspace(activeProfile()));
286
+ const ws = resolvePathLikePython((await workspaces.lastWorkspace(activeProfile())));
267
287
  return statSync(ws).isDirectory() ? ws : null;
268
288
  }
269
289
  catch {
@@ -275,39 +295,49 @@ export function createDeps(opts) {
275
295
  const mediaAccess = { home: config.homeDir, hermesHome: config.hermesHome, extraRoots: env.MEDIA_ALLOWED_ROOTS ?? '', activeWorkspace: mediaActiveWorkspace, policy: mediaPolicy };
276
296
  // TAL-259: record when this server started stamping deliberate shrinks; older backups go to manual review.
277
297
  try {
278
- recoveryStampingSince(config.stateDir);
298
+ await recoveryStampingSince(storage.documents);
279
299
  }
280
300
  catch (error) {
281
301
  log(`[webui] WARNING: could not record recovery_stamping_since: ${error.message}`);
282
302
  }
283
303
  const sessions = new SessionService({
284
- recoveryStampingSince: () => recoveryStampingSince(config.stateDir),
304
+ recoveryStampingSince: async () => await recoveryStampingSince(storage.documents),
285
305
  sidecar: () => sidecar,
286
306
  media: { access: mediaAccess, localIo: (profile) => workspaces.profileSupportsLocalIo(profile) },
287
307
  profileActivity,
288
308
  profileDeleting: (profile) => profiles.isDeleting(profile),
289
- backgroundReceipts: (sid) => background.receipts(sid),
309
+ backgroundReceipts: async (sid) => (await background.receipts(sid)),
310
+ backgroundPending: async (sid) => (await completions.pendingDelegations(sid)),
290
311
  journal,
291
- clearRelayCompletions: (sid, profile) => { relay.clearDeleted(sid, profile); },
312
+ clearRelayCompletions: async (sid, profile) => { (await relay.clearDeleted(sid, profile)); },
292
313
  store,
293
- cliSessions: (profile, o) => cliSessions.read(profile, o),
294
- cliSessionsSync: (profile, o) => cliSessions.readSync(profile, o),
314
+ cliSessions: async (profile, o) => (await cliSessions.read(profile, o)),
315
+ cliSessionsSync: async (profile, o) => (await cliSessions.readSync(profile, o)),
295
316
  claudeCode: new ClaudeCodeSessionSource(() => claudeCodeProjectsDir(env, home)),
296
317
  profileHome,
297
318
  // The commit runs detached from the request, so it is registered as profile activity until it settles: profile
298
319
  // deletion must not remove the memory files the cached Agent is still writing.
299
- commitSessionMemory: (sid) => {
320
+ commitSessionMemory: async (sid) => {
300
321
  if (!sidecar)
301
322
  return;
323
+ const callerProfile = activeProfile();
324
+ // Reserve deletion protection before the asynchronous lookup knows which profile owns the session.
325
+ let release = profileActivity('*');
302
326
  let profile = null;
303
327
  try {
304
- profile = store.get(sid, { metadataOnly: true }).profile ?? null;
328
+ profile = (await store.get(sid, { metadataOnly: true })).profile ?? null;
305
329
  }
306
330
  catch {
307
331
  profile = null;
308
332
  }
309
- const release = profileActivity(profile);
310
- void Promise.resolve().then(() => sidecar.call('chat.commit_memory', { profile_home: profileHome(profile ?? activeProfile()), session_id: sid }))
333
+ const targetProfile = profile ?? callerProfile;
334
+ const releaseOwner = profileActivity(targetProfile);
335
+ release();
336
+ release = releaseOwner;
337
+ void Promise.resolve().then(async () => {
338
+ await sessions.assertWritable(sid, targetProfile);
339
+ return sidecar.call('chat.commit_memory', { profile_home: profileHome(targetProfile), session_id: sid });
340
+ })
311
341
  .catch((error) => { log(`[webui] memory commit for ${sid} failed: ${error.message}`); })
312
342
  .finally(release);
313
343
  },
@@ -330,12 +360,12 @@ export function createDeps(opts) {
330
360
  profilesMatch,
331
361
  assistantName,
332
362
  redactEnabled: () => { try {
333
- return settings.load().api_redact_enabled !== false;
363
+ return settings.peek().api_redact_enabled !== false;
334
364
  }
335
365
  catch {
336
366
  return true;
337
367
  } },
338
- pinnedSessionsLimit: () => { const v = settings.load().pinned_sessions_limit; return typeof v === 'number' && v >= 1 ? v : 3; },
368
+ pinnedSessionsLimit: () => { const v = settings.peek().pinned_sessions_limit; return typeof v === 'number' && v >= 1 ? v : 3; },
339
369
  // Chat runtime (checkpoint 6) replaces these with live stream and cron state.
340
370
  runtime: {
341
371
  activeStreamIds,
@@ -354,13 +384,20 @@ export function createDeps(opts) {
354
384
  activeRunStream: (sid) => registry.activeRunStreamForSession(sid),
355
385
  journalDegraded: (streamId) => registry.degradedJournals.has(streamId),
356
386
  pendingSteers: (streamId) => turns.pendingSteers(streamId),
357
- evictAgent: (sid, endSession) => { if (sidecar)
387
+ runStatus: (streamId) => turns.runStatus(streamId),
388
+ compressionStartedAt: (streamId) => turns.compressionStartedAt(streamId),
389
+ automaticTurnsHeld: async (sid) => (await turns.automaticTurnsHeld(sid)),
390
+ sessionNotices: (sid) => turns.sessionNotices(sid),
391
+ sessionGoal: (sid) => turns.sessionGoal(sid),
392
+ evictAgent: async (sid, endSession) => { if (sidecar && (!endSession || !(await sessions.readOnlyReason(sid))))
358
393
  sidecar.call('chat.evict_agent', endSession ? { session_id: sid, clear_session: true } : { session_id: sid }).catch(() => undefined); },
359
394
  closeTerminal: (sid) => { deps.terminals.close(sid); },
360
395
  deleteCliSession: async (profile, sid) => {
361
396
  if (!sidecar)
362
- return false;
363
- return (await sidecar.call('state_db.delete_cli_session', { profile_home: profileHome(profile ?? activeProfile()), session_id: sid })).ok;
397
+ return { ok: false };
398
+ const targetProfile = profile ?? activeProfile();
399
+ await sessions.assertWritable(sid, targetProfile);
400
+ return await sidecar.call('state_db.delete_cli_session', { profile_home: profileHome(targetProfile), session_id: sid, include_compression_lineage: true });
364
401
  },
365
402
  },
366
403
  attachmentDir,
@@ -368,11 +405,13 @@ export function createDeps(opts) {
368
405
  home,
369
406
  // Python `_sync_session_title_to_state_db`: with `sync_to_insights` on, the state.db row follows a rename.
370
407
  syncTitle: async (session, manual) => {
371
- if (!sidecar || !pyBool(settings.load().sync_to_insights))
408
+ if (!sidecar || !pyBool(settings.peek().sync_to_insights))
372
409
  return;
373
410
  // Awaited by callers: the rename/regenerate response and the title stream's teardown follow the state.db write.
374
411
  try {
375
- await sidecar.call('state_db.sync_title', { profile_home: profileHome(session.profile ?? activeProfile()), session_id: session.session_id, title: session.title, manual: manual === true });
412
+ const targetProfile = session.profile ?? activeProfile();
413
+ sessions.assertWritable(session, targetProfile);
414
+ await sidecar.call('state_db.sync_title', { profile_home: profileHome(targetProfile), session_id: session.session_id, title: session.title, manual: manual === true });
376
415
  }
377
416
  catch (error) {
378
417
  log(`[webui] state.db title sync failed for ${session.session_id}: ${error.message}`);
@@ -417,25 +456,21 @@ export function createDeps(opts) {
417
456
  // A working-tree mutation refuses while a run is active anywhere it would change files.
418
457
  const git = new GitRunner({ env, activeRunIn: (path) => [...registry.activeRuns.values()].some((run) => Boolean(run.workspace) && pathsOverlap(run.workspace, path)) });
419
458
  const rollback = new RollbackStore({
420
- sidecar: () => sidecar, profileHome: () => profileHome(activeProfile()), knownWorkspaces: () => workspaces.load(activeProfile()).map((w) => w.path),
459
+ sidecar: () => sidecar, profileHome: () => profileHome(activeProfile()), knownWorkspaces: async () => (await workspaces.load(activeProfile())).map((w) => w.path),
421
460
  // A run whose session cannot be read counts as one in the profile: refusing is the safe answer.
422
461
  activeRunInProfile: (home) => [...registry.activeRuns.values()].some((run) => {
423
- try {
424
- return profileHome(store.get(run.session_id, { metadataOnly: true }).profile ?? activeProfile()) === home;
425
- }
426
- catch {
427
- return true;
428
- }
462
+ const session = store.sessions.get(run.session_id);
463
+ return !session || profileHome(session.profile ?? activeProfile()) === home;
429
464
  }),
430
465
  });
431
466
  const uploads = new UploadInbox(attachmentRoot);
432
467
  const channels = new SessionChannels();
433
468
  const pending = new PendingPrompts(events, now);
434
469
  // TAL-372: one durable record per piece of background work; a change refreshes every client showing the session.
435
- const backgroundStore = new BackgroundTaskStore(config.sessionDir, now, (sid) => {
470
+ const backgroundStore = new BackgroundTaskStore(storage.documents, now, async (sid) => {
436
471
  let profile = null;
437
472
  try {
438
- profile = store.get(sid, { metadataOnly: true, promote: false, cacheOnMiss: false }).profile;
473
+ profile = (await store.get(sid, { metadataOnly: true, promote: false, cacheOnMiss: false })).profile;
439
474
  }
440
475
  catch {
441
476
  profile = null;
@@ -450,7 +485,7 @@ export function createDeps(opts) {
450
485
  const relay = new RelayService({
451
486
  registry, pending, store, presence: new PresenceLeases(now), profileHome, profilesMatch, fetch: () => lazyFetch, now, log,
452
487
  agentSessions: (profile) => readImportableAgentSessionRowsAsync(join(profileHome(profile), 'state.db')),
453
- stateDir: config.stateDir, env, canonicalProfile: (p) => (isRootProfile(p) ? 'default' : p), addListener: (listener) => events.addListener(listener),
488
+ documents: storage.documents, env, canonicalProfile: (p) => (isRootProfile(p) ? 'default' : p), addListener: (listener) => events.addListener(listener),
454
489
  });
455
490
  const turns = new TurnRunner({
456
491
  store,
@@ -465,11 +500,13 @@ export function createDeps(opts) {
465
500
  syncTitle: (session) => sessions.deps.syncTitle(session),
466
501
  // Python `sync_session_usage` after a settled turn: with `sync_to_insights` on, the state.db row carries the usage.
467
502
  syncUsage: async (session, model) => {
468
- if (!sidecar || !pyBool(settings.load().sync_to_insights))
503
+ if (!sidecar || !pyBool(settings.peek().sync_to_insights))
469
504
  return;
470
505
  try {
506
+ const targetProfile = session.profile ?? activeProfile();
507
+ sessions.assertWritable(session, targetProfile);
471
508
  await sidecar.call('state_db.sync_usage', {
472
- profile_home: profileHome(session.profile ?? activeProfile()), session_id: session.session_id,
509
+ profile_home: profileHome(targetProfile), session_id: session.session_id,
473
510
  input_tokens: session.input_tokens || 0, output_tokens: session.output_tokens || 0, estimated_cost: typeof session.estimated_cost === 'number' ? session.estimated_cost : null,
474
511
  cache_read_tokens: session.cache_read_tokens || 0, cache_write_tokens: session.cache_write_tokens || 0,
475
512
  model, title: session.title, message_count: session.messages.length,
@@ -486,8 +523,10 @@ export function createDeps(opts) {
486
523
  catch {
487
524
  return null;
488
525
  } },
526
+ personalities: (profile) => agentConfig.agentPersonalities(profileHome(profile ?? activeProfile())),
527
+ providerLabel: (profile, provider) => catalog.providerLabel(profileHome(profile ?? activeProfile()), provider),
489
528
  titleRefreshEvery: () => { try {
490
- const every = Number(settings.load().auto_title_refresh_every);
529
+ const every = Number(settings.peek().auto_title_refresh_every);
491
530
  return Number.isInteger(every) && every > 0 ? every : 0;
492
531
  }
493
532
  catch {
@@ -507,7 +546,7 @@ export function createDeps(opts) {
507
546
  now,
508
547
  log,
509
548
  redactEnabled: () => { try {
510
- return settings.load().api_redact_enabled !== false;
549
+ return settings.peek().api_redact_enabled !== false;
511
550
  }
512
551
  catch {
513
552
  return true;
@@ -518,7 +557,7 @@ export function createDeps(opts) {
518
557
  });
519
558
  // Services read `deps.fetch` lazily so tests can swap the outbound HTTP client after boot.
520
559
  const lazyFetch = (input, init) => deps.fetch(input, init);
521
- const catalog = new ProviderCatalog({ sidecar: () => sidecar, config: agentConfig, env, now, log, costBudget: () => coerceProviderCostBudgetValue(settings.load().provider_cost_budget), quotaThresholds: (profile) => settings.quotaThresholds(profile), isRootProfileHome: (h) => resolvePathLikePython(h) === resolvePathLikePython(config.hermesHome), stateDir: config.stateDir });
560
+ const catalog = new ProviderCatalog({ sidecar: () => sidecar, config: agentConfig, env, now, log, costBudget: () => coerceProviderCostBudgetValue(settings.peek().provider_cost_budget), quotaThresholds: async (profile) => (await settings.quotaThresholds(profile)), isRootProfileHome: (h) => resolvePathLikePython(h) === resolvePathLikePython(config.hermesHome), documents: storage.documents });
522
561
  const agentStatus = () => {
523
562
  const describe = sidecar?.describe ?? null;
524
563
  const found = Boolean(describe?.agent_dir);
@@ -532,7 +571,7 @@ export function createDeps(opts) {
532
571
  isolatedProfileMode,
533
572
  isolatedProfileName,
534
573
  config: agentConfig,
535
- defaultWorkspace: (profile) => workspaces.profileDefaultWorkspace(profile),
574
+ defaultWorkspace: async (profile) => (await workspaces.profileDefaultWorkspace(profile)),
536
575
  models: (h) => catalog.models(h),
537
576
  streamsActive: () => activeStreamIds.size > 0,
538
577
  profileRunsActive: (name) => {
@@ -548,23 +587,22 @@ export function createDeps(opts) {
548
587
  }
549
588
  for (const sessionId of sessionIds) {
550
589
  let profile = null;
551
- try {
552
- profile = store.get(sessionId, { metadataOnly: true }).profile ?? null;
553
- }
554
- catch {
555
- continue;
556
- }
590
+ const session = store.sessions.get(sessionId);
591
+ if (!session)
592
+ return true;
593
+ profile = session.profile ?? null;
557
594
  if (profiles.isRootProfile(profile ?? 'default') ? profiles.isRootProfile(name) : profile === name)
558
595
  return true;
559
596
  }
560
597
  for (const [profile, count] of profileOps)
561
- if (count > 0 && (profiles.isRootProfile(profile) ? profiles.isRootProfile(name) : profile === name))
598
+ if (count > 0 && (profile === '*' || (profiles.isRootProfile(profile) ? profiles.isRootProfile(name) : profile === name)))
562
599
  return true;
563
600
  return false;
564
601
  },
565
- tombstoneFile: join(config.stateDir, 'deleted-profiles.json'),
602
+ documents: storage.documents,
566
603
  log,
567
604
  }, now);
605
+ await profiles.initialize();
568
606
  rootAlias = (name) => profiles.isRootProfile(name);
569
607
  const onboarding = new Onboarding({
570
608
  settings,
@@ -575,7 +613,7 @@ export function createDeps(opts) {
575
613
  sidecar: () => sidecar,
576
614
  agentStatus,
577
615
  isAuthEnabled: () => auth.isAuthEnabled(),
578
- workspaces: () => ({ items: workspaces.load(activeProfile()), last: workspaces.lastWorkspace(activeProfile()) }),
616
+ workspaces: async () => ({ items: (await workspaces.load(activeProfile())), last: (await workspaces.lastWorkspace(activeProfile())) }),
579
617
  models: (h) => catalog.models(h),
580
618
  defaultWorkspace: () => config.defaultWorkspace,
581
619
  defaultModel: () => (env.HERMES_WEBUI_DEFAULT_MODEL ?? '').trim(),
@@ -625,14 +663,12 @@ export function createDeps(opts) {
625
663
  },
626
664
  };
627
665
  };
628
- completions = new CompletionDrain({ sidecar: () => sidecar, configPath: (home) => agentConfig.path(home), baseHome, profileHome: (p) => profileHome(p ?? activeProfile()), activeProfile, store, channels, registry, startTurn: async (session, prompt) => {
666
+ completions = new CompletionDrain({ documents: storage.documents, sidecar: () => sidecar, configPath: (home) => agentConfig.path(home), readConfig: (home) => agentConfig.read(home), env, baseHome, profileHome: (p) => profileHome(p ?? activeProfile()), activeProfile, store, channels, registry, isReadOnly: async (session) => (await sessions.isReadOnly(session)), startTurn: async (session, prompt, completionKeys, backgroundUpdate) => {
629
667
  // TAL-577: a wakeup passes the user-turn admission; a stale runtime answers a retryable 409, which defers it on a retry timer.
630
668
  // TAL-542: its model repair reads the cached catalog only (Python `prefer_cached_catalog`), never waiting on a build.
631
669
  try {
632
670
  await ensureAgentRuntimeCurrent(sidecar);
633
- const workspace = sessions.turnWorkspace(session);
634
- const [model, modelProvider] = sessions.turnModel(session);
635
- return turns.start(session, { msg: prompt, attachments: [], workspace, model, modelProvider, source: 'process_wakeup' });
671
+ return (await turns.startServerTurn(session, { msg: prompt, source: 'process_wakeup', completionKeys, backgroundUpdate }));
636
672
  }
637
673
  catch (error) {
638
674
  if (error instanceof HttpFailure)
@@ -657,6 +693,8 @@ export function createDeps(opts) {
657
693
  catch {
658
694
  return false;
659
695
  } };
696
+ sessions.owner = new GatewaySessions({ service: sessions, sidecar: () => sidecar, registry, journal, events,
697
+ profileHome, activeProfile, redactEnabled: sessions.deps.redactEnabled, now, log });
660
698
  const deps = {
661
699
  config,
662
700
  settings,
@@ -675,7 +713,7 @@ export function createDeps(opts) {
675
713
  requestScope,
676
714
  isRootProfile,
677
715
  assistantName,
678
- onboardingCompleted: () => truthy(env.HERMES_WEBUI_SKIP_ONBOARDING) || Boolean(settings.load().onboarding_completed),
716
+ onboardingCompleted: () => truthy(env.HERMES_WEBUI_SKIP_ONBOARDING) || Boolean(settings.peek().onboarding_completed),
679
717
  health: () => ({ sessions: store.sessions.size, activeStreams: activeStreamIds.size, activeRuns: registry.activeRuns.size, runs: [...registry.activeRuns.values()].map((r) => ({ phase: r.phase, started_at: r.started_at })), lastRunFinishedAt: registry.lastRunFinishedAt }),
680
718
  sessions,
681
719
  sessionStore: store,
@@ -721,11 +759,11 @@ export function createDeps(opts) {
721
759
  oidc,
722
760
  passkeys,
723
761
  nativeOidcLimiter: new WindowLimiter(60, 10, now),
724
- clearPasskeys: () => { passkeys.clear(); },
762
+ clearPasskeys: async () => { (await passkeys.clear()); },
725
763
  skills: new SkillsService({ sidecar: () => sidecar, config: agentConfig, log }),
726
764
  mcp: new McpService({ sidecar: () => sidecar, config: agentConfig, health: mcpHealth }),
727
765
  completions,
728
- hygiene: new HygieneTicker({ env, stateDir: config.stateDir, port: () => config.port, journal, activeJournalPaths: () => turns.activeJournalPaths(), now, log, sweeps: [() => { completions.sweep(); }] }),
766
+ hygiene: new HygieneTicker({ env, stateDir: config.stateDir, port: () => config.port, journal, now, log, sweeps: [() => { completions.sweep(); }, async () => { (await turns.sweep()); }] }),
729
767
  mcpHealth,
730
768
  nowSeconds: now,
731
769
  // Python `_webui_runtime_payload`: the four owner sections with their `available` flags.
@@ -744,12 +782,14 @@ export function createDeps(opts) {
744
782
  requestShutdown: () => { setTimeout(() => { process.kill(process.pid, 'SIGINT'); }, 300).unref(); },
745
783
  // Embedded shells are separate process groups that would outlive the worker: terminate and reap them on both exits.
746
784
  // A running retention sweep stops before the exit, like on shutdown.
747
- requestRestart: () => { void waitUntilRestartSafe(restartBlockers, { log }).then(() => deps.hygiene.stop()).then(() => auth.flushPersistence()).then(() => { deps.terminals.closeAll({ immediate: true }); purgeAgentPycache(); process.exit(RESTART_EXIT_CODE); }); },
785
+ requestRestart: () => { void waitUntilRestartSafe(restartBlockers, { log }).then(() => deps.gatewayRestarts.quiesce()).then(() => deps.hygiene.stop()).then(() => auth.flushPersistence()).then(() => store.close()).then(() => { deps.terminals.closeAll({ immediate: true }); purgeAgentPycache(); process.exit(RESTART_EXIT_CODE); }); },
748
786
  updates: null,
749
787
  updateNotifications,
788
+ gatewayRestarts: null,
750
789
  cspLimiter: new WindowLimiter(60, 100, now),
751
790
  clientEventLimiter: new WindowLimiter(60, 30, now),
752
791
  ttsLimiter: new WindowLimiter(2, 1, now),
792
+ profileActivity,
753
793
  fetch: opts.fetch ?? fetch,
754
794
  dnsLookup: systemDnsLookup,
755
795
  pinnedFetch,
@@ -762,10 +802,11 @@ export function createDeps(opts) {
762
802
  log,
763
803
  publishSessionsChanged: (reason, profile) => { events.publish(reason, { profile }); },
764
804
  runningJobs: runningCronJobs,
805
+ updateInProgress: () => deps.updates.blocksNewWork(),
765
806
  modelOptionFor: async (home, model, provider) => { await catalog.warmModelOptions(home); return catalog.modelOptionFor(home, model, provider); },
766
807
  }),
767
808
  kanban: new KanbanService({ sidecar: () => sidecar, config: agentConfig }),
768
- extensions: new ExtensionService({ env, stateDir: config.stateDir, isAuthEnabled: () => auth.isAuthEnabled(), fetch: lazyFetch, log }),
809
+ extensions: new ExtensionService({ documents: storage.documents, env, stateDir: config.stateDir, isAuthEnabled: () => auth.isAuthEnabled(), fetch: lazyFetch, log }),
769
810
  dashboardPlugins: new DashboardPlugins({ env, hermesHome: config.hermesHome, settings }),
770
811
  terminals,
771
812
  commitMessage: async (session, systemPrompt, userPrompt) => {
@@ -790,6 +831,8 @@ export function createDeps(opts) {
790
831
  };
791
832
  const purgeAgentPycache = () => { const dir = sidecar?.describe?.agent_dir; if (dir)
792
833
  purgePycache(dir); };
834
+ let recoveredAgentRevision = null;
835
+ let pendingRuntimeRecovery = null;
793
836
  deps.updates = new UpdateService({
794
837
  webRoot: config.webRoot,
795
838
  getJson: githubJson(lazyFetch, env),
@@ -805,22 +848,105 @@ export function createDeps(opts) {
805
848
  return deps.version;
806
849
  },
807
850
  agentDir: () => sidecar?.describe?.agent_dir ?? null,
808
- channel: () => normalizeChannel(settings.load().update_channel),
809
- agentChannel: () => normalizeChannel(settings.load().agent_update_channel),
810
- includeAgent: () => !pyBool(settings.load().ignore_agent_updates),
811
- autoApply: () => settings.load().check_for_updates !== false && settings.load().auto_apply_updates === true,
812
- checkEnabled: () => !truthy(env.HERMES_WEBUI_TEST_NETWORK_BLOCK) && settings.load().check_for_updates !== false,
813
- autoNotification: {
814
- begin: () => updateNotifications.begin({ owner: '*', profile: 'default', serverOwner: true }, 'webui').id,
815
- transition: (id, phase, expectedIdentity, verifiedIdentity, detail) => { updateNotifications.transition(id, phase, expectedIdentity, verifiedIdentity, detail); },
851
+ agentHomes,
852
+ ...(sidecar?.onHandshake ? { onAgentReconnect: (listener) => sidecar.onHandshake(listener) } : {}),
853
+ recoverAgent: async (probe = false, signal) => {
854
+ if (!sidecar)
855
+ throw new Error('Hermes Agent sidecar is unavailable for recovery.');
856
+ if (sidecar.status === 'starting' || sidecar.status === 'restarting' || sidecar.status === 'stopped')
857
+ throw new Error('Agent recovery is waiting for its sidecar connection.');
858
+ let result = await sidecar.call('runtime.agent_recovery', { probe }, { ...(signal ? { signal } : {}), timeoutMs: 660_000 });
859
+ if (signal?.aborted)
860
+ throw new Error('Agent recovery was cancelled.');
861
+ if (!probe && result.local_restore && result.revision)
862
+ recoveredAgentRevision = result.revision;
863
+ if (probe) {
864
+ if (pendingRuntimeRecovery?.fingerprint === result.fingerprint && restartBlockers().restart_blocked
865
+ && (sidecar.describe?.agent_revision !== recoveredAgentRevision || !sidecar.describe?.compatible)) {
866
+ return { ...result, waiting_for_idle: true, detail: 'Agent recovery is waiting for active Web work to finish before refreshing its runtime.' };
867
+ }
868
+ return result;
869
+ }
870
+ if (!result.ok || (result.owed && !result.runtime_pending))
871
+ return result;
872
+ if (result.revision)
873
+ recoveredAgentRevision = result.revision;
874
+ if (result.runtime_pending)
875
+ pendingRuntimeRecovery = result;
876
+ const runtime = await sidecar.call('runtime.status', {}, { ...(signal ? { signal } : {}), timeoutMs: 5000 });
877
+ if (signal?.aborted)
878
+ throw new Error('Agent recovery was cancelled.');
879
+ if (recoveredAgentRevision && (runtime.agent_revision !== recoveredAgentRevision || !runtime.compatible)) {
880
+ if (restartBlockers().restart_blocked)
881
+ return { ...result, waiting_for_idle: true, detail: 'Agent recovery is waiting for active Web work to finish before refreshing its runtime.' };
882
+ if (['ready', 'incompatible'].includes(sidecar.status))
883
+ sidecar.recycle('Verified retained Agent recovery requires the current interpreter and source');
884
+ throw new Error('Agent services recovered; waiting for the current sidecar runtime to become ready.');
885
+ }
886
+ if (result.runtime_pending && recoveredAgentRevision)
887
+ result = await sidecar.call('runtime.agent_recovery', { complete_revision: recoveredAgentRevision }, { ...(signal ? { signal } : {}), timeoutMs: 660_000 });
888
+ if (signal?.aborted || !result.ok || result.owed)
889
+ throw new Error(result.detail || 'Agent recovery remains recorded until loaded readiness is verified.');
890
+ await sidecar.call('runtime.ensure_current', {}, { ...(signal ? { signal } : {}), timeoutMs: 5000 });
891
+ if (signal?.aborted)
892
+ throw new Error('Agent recovery was cancelled.');
893
+ if (!runtime.compatible || runtime.stale)
894
+ throw new Error('Agent recovery has no matching loaded runtime evidence; admission remains closed.');
895
+ catalog.invalidate(undefined, undefined, { preserveConfirmed: true });
896
+ recoveredAgentRevision = null;
897
+ pendingRuntimeRecovery = null;
898
+ return result;
816
899
  },
817
- blockers: restartBlockers,
818
- scheduleRestart: () => { setTimeout(() => { void waitUntilRestartSafe(restartBlockers, { maxWaitMs: Infinity, log }).then(() => { deps.requestRestart(); }); }, 2000).unref(); },
819
- gatewayRestart: async () => {
900
+ recoveryChanged: (state) => updateNotifications.agentRecovery(state),
901
+ hasPendingRecovery: () => updateNotifications.hasPendingAgentRecovery(),
902
+ agentMutation: async (path, revision, mutate, consent) => {
820
903
  if (!sidecar)
821
904
  throw new Error('Hermes Agent sidecar is unavailable');
822
- return sidecar.call('gateway.restart', { profile_home: profileHome(activeProfile()) }, { timeoutMs: 300_000 });
905
+ const begin = await sidecar.call('runtime.agent_mutation', { action: 'begin', agent_dir: path, revision, homes: agentHomes(), ...(consent?.mutationIntent ? { intent: consent.mutationIntent } : {}), ...(consent?.refreshToken ? { refresh_token: consent.refreshToken } : {}) }, { timeoutMs: 330_000 });
906
+ if (begin.refresh_confirmation)
907
+ return { ok: false, refresh_confirmation: begin.refresh_confirmation, message: begin.detail };
908
+ if (!begin.ok || !begin.token)
909
+ throw new Error(begin.detail || 'Agent writer quiescence was not verified.');
910
+ const token = begin.token;
911
+ const leasedGit = async (args, cwd, timeoutMs = 10_000) => {
912
+ if (resolve(cwd) !== resolve(path))
913
+ throw new Error('Agent writer lease cannot mutate another checkout.');
914
+ const result = await sidecar.call('runtime.agent_mutation', { action: 'git', agent_dir: path, token, args, timeout_ms: timeoutMs }, { timeoutMs: 330_000 });
915
+ return { ok: result.ok, out: result.detail };
916
+ };
917
+ let result;
918
+ try {
919
+ result = await mutate(leasedGit, () => sidecar.call('runtime.agent_mutation', { action: 'sync', agent_dir: path, token }, { timeoutMs: 330_000 }));
920
+ }
921
+ catch (error) {
922
+ try {
923
+ await sidecar.call('runtime.agent_mutation', { action: 'finish', agent_dir: path, token }, { timeoutMs: 330_000 });
924
+ }
925
+ catch { /* The native pause journal retains any unverified recovery obligation. */ }
926
+ throw error;
927
+ }
928
+ const resumed = await sidecar.call('runtime.agent_mutation', { action: 'finish', agent_dir: path, token }, { timeoutMs: 330_000 });
929
+ return resumed.ok ? { ...result, ...(result.gateway_restart === 'waiting_for_idle' ? { gateway_restart: 'resumed' } : {}) }
930
+ : { ...result, ok: false, restart_scheduled: false, message: resumed.detail || 'Agent writer resume remains unverified; its recovery obligation is retained.' };
931
+ },
932
+ agentSync: async (agentDir) => {
933
+ if (!sidecar)
934
+ throw new Error('Hermes Agent sidecar is unavailable');
935
+ return sidecar.call('runtime.sync_dependencies', { agent_dir: agentDir }, { timeoutMs: 330_000 });
823
936
  },
937
+ channel: () => normalizeChannel(settings.peek().update_channel),
938
+ agentChannel: () => normalizeChannel(settings.peek().agent_update_channel),
939
+ includeAgent: () => !pyBool(settings.peek().ignore_agent_updates),
940
+ summarizeAutomatically: () => settings.peek().check_for_updates !== false && settings.peek().summarize_updates_automatically !== false,
941
+ autoApply: () => settings.peek().check_for_updates !== false && settings.peek().auto_apply_updates === true,
942
+ checkEnabled: () => !truthy(env.HERMES_WEBUI_TEST_NETWORK_BLOCK) && settings.peek().check_for_updates !== false,
943
+ autoNotification: {
944
+ begin: async () => (await updateNotifications.begin({ owner: '*', profile: 'default', serverOwner: true }, 'webui')).id,
945
+ transition: async (id, phase, expectedIdentity, verifiedIdentity, detail) => { (await updateNotifications.transition(id, phase, expectedIdentity, verifiedIdentity, detail)); },
946
+ },
947
+ blockers: restartBlockers,
948
+ scheduleRestart: () => { setTimeout(() => { void waitUntilRestartSafe(restartBlockers, { maxWaitMs: Infinity, log }).then(() => { deps.requestRestart(); }); }, 2000).unref(); },
949
+ gatewayRestarting: () => deps.gatewayRestarts.restarting(),
824
950
  llm: async (system, user) => {
825
951
  if (!sidecar)
826
952
  return '';
@@ -829,6 +955,17 @@ export function createDeps(opts) {
829
955
  },
830
956
  log,
831
957
  });
958
+ deps.gatewayRestarts = new GatewayRestartQueue({
959
+ notifications: updateNotifications,
960
+ blockers: (profile) => gatewayRestartBlockers(config.hermesHome, profileHome(profile), now()),
961
+ updating: () => deps.updates.blocksNewWork(),
962
+ restart: async (profile) => {
963
+ if (!sidecar)
964
+ throw new Error('Hermes Agent sidecar is unavailable');
965
+ return restartGateway(sidecar, profileHome(profile));
966
+ },
967
+ log,
968
+ });
832
969
  return deps;
833
970
  }
834
971
  /** Python `_read_active_profile_file`: the sticky profile name, or `default` when absent, unreadable, or malformed. */
@@ -841,4 +978,10 @@ function readActiveProfileFile(hermesHome, pattern) {
841
978
  return 'default';
842
979
  }
843
980
  }
981
+ export function createStorage(config, now = () => Date.now() / 1000, profileHome = (name) => name === 'default' ? config.hermesHome : join(config.hermesHome, 'profiles', name)) {
982
+ if (config.storage !== 'json')
983
+ throw new Error(`Unknown TALARIA_STORAGE=${JSON.stringify(config.storage)}; supported backends: json`);
984
+ const storage = new JsonStorage({ directory: config.sessionDir, stateDir: config.stateDir, profileHome, env: config.env, now, stampingSince: async () => (await recoveryStampingSince(storage.documents)) });
985
+ return storage;
986
+ }
844
987
  //# sourceMappingURL=runtime.js.map