@maudecode/talaria-web 1.18.0 → 1.20.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 (774) 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 +93 -38
  6. package/dist/api/automation-raw.js.map +1 -1
  7. package/dist/api/automation-router.d.ts +99 -17
  8. package/dist/api/automation-router.js +22 -14
  9. package/dist/api/automation-router.js.map +1 -1
  10. package/dist/api/chat-router.d.ts +1433 -37
  11. package/dist/api/chat-router.js +205 -90
  12. package/dist/api/chat-router.js.map +1 -1
  13. package/dist/api/git-router.d.ts +6 -2
  14. package/dist/api/git-router.js +30 -30
  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 +76 -62
  18. package/dist/api/raw-routes.js.map +1 -1
  19. package/dist/api/router.d.ts +5 -5
  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 +2635 -151
  26. package/dist/api/sessions-router.js +193 -177
  27. package/dist/api/sessions-router.js.map +1 -1
  28. package/dist/api/settings-router.d.ts +450 -11
  29. package/dist/api/settings-router.js +102 -49
  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 +102 -80
  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 +963 -109
  38. package/dist/api/tools-router.js +426 -72
  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 +80 -57
  45. package/dist/app.js.map +1 -1
  46. package/dist/auth/crypto.d.ts +3 -0
  47. package/dist/auth/crypto.js +18 -0
  48. package/dist/auth/crypto.js.map +1 -1
  49. package/dist/auth/gate.js +14 -9
  50. package/dist/auth/gate.js.map +1 -1
  51. package/dist/auth/passkeys.d.ts +15 -14
  52. package/dist/auth/passkeys.js +89 -91
  53. package/dist/auth/passkeys.js.map +1 -1
  54. package/dist/auth/store.d.ts +17 -7
  55. package/dist/auth/store.js +93 -52
  56. package/dist/auth/store.js.map +1 -1
  57. package/dist/bin/talaria-web.js +12 -81
  58. package/dist/bin/talaria-web.js.map +1 -1
  59. package/dist/cli/ctl.js +8 -2
  60. package/dist/cli/ctl.js.map +1 -1
  61. package/dist/cli/dotenv.d.ts +5 -0
  62. package/dist/cli/dotenv.js +14 -2
  63. package/dist/cli/dotenv.js.map +1 -1
  64. package/dist/cli/launcher.js +5 -5
  65. package/dist/cli/launcher.js.map +1 -1
  66. package/dist/cli/main.d.ts +1 -0
  67. package/dist/cli/main.js +90 -0
  68. package/dist/cli/main.js.map +1 -0
  69. package/dist/cli/supervise.d.ts +24 -0
  70. package/dist/cli/supervise.js +147 -6
  71. package/dist/cli/supervise.js.map +1 -1
  72. package/dist/config/agent-config.d.ts +37 -11
  73. package/dist/config/agent-config.js +146 -64
  74. package/dist/config/agent-config.js.map +1 -1
  75. package/dist/config.d.ts +2 -0
  76. package/dist/config.js +14 -5
  77. package/dist/config.js.map +1 -1
  78. package/dist/fs/atomic.d.ts +4 -0
  79. package/dist/fs/atomic.js +19 -2
  80. package/dist/fs/atomic.js.map +1 -1
  81. package/dist/fs/stat.d.ts +7 -0
  82. package/dist/fs/stat.js +27 -0
  83. package/dist/fs/stat.js.map +1 -0
  84. package/dist/http/context.d.ts +28 -9
  85. package/dist/http/context.js +77 -25
  86. package/dist/http/context.js.map +1 -1
  87. package/dist/onboarding.d.ts +2 -2
  88. package/dist/onboarding.js +10 -8
  89. package/dist/onboarding.js.map +1 -1
  90. package/dist/profiles/profiles.d.ts +12 -4
  91. package/dist/profiles/profiles.js +78 -30
  92. package/dist/profiles/profiles.js.map +1 -1
  93. package/dist/projects.d.ts +15 -6
  94. package/dist/projects.js +55 -47
  95. package/dist/projects.js.map +1 -1
  96. package/dist/providers/catalog.d.ts +85 -14
  97. package/dist/providers/catalog.js +502 -146
  98. package/dist/providers/catalog.js.map +1 -1
  99. package/dist/providers/env-file.d.ts +10 -3
  100. package/dist/providers/env-file.js +24 -75
  101. package/dist/providers/env-file.js.map +1 -1
  102. package/dist/providers/runtime-env.d.ts +4 -2
  103. package/dist/providers/runtime-env.js +9 -6
  104. package/dist/providers/runtime-env.js.map +1 -1
  105. package/dist/providers/tables.d.ts +3 -1
  106. package/dist/providers/tables.js +4 -2
  107. package/dist/providers/tables.js.map +1 -1
  108. package/dist/redact.js +56 -23
  109. package/dist/redact.js.map +1 -1
  110. package/dist/release.d.ts +7 -0
  111. package/dist/release.js +19 -3
  112. package/dist/release.js.map +1 -1
  113. package/dist/runtime.d.ts +5 -1
  114. package/dist/runtime.js +303 -96
  115. package/dist/runtime.js.map +1 -1
  116. package/dist/server.js +31 -18
  117. package/dist/server.js.map +1 -1
  118. package/dist/sessions/anchor.d.ts +11 -4
  119. package/dist/sessions/anchor.js +33 -37
  120. package/dist/sessions/anchor.js.map +1 -1
  121. package/dist/sessions/background-events.d.ts +2 -0
  122. package/dist/sessions/background-events.js +10 -0
  123. package/dist/sessions/background-events.js.map +1 -0
  124. package/dist/sessions/background-tasks.d.ts +49 -23
  125. package/dist/sessions/background-tasks.js +161 -89
  126. package/dist/sessions/background-tasks.js.map +1 -1
  127. package/dist/sessions/background-updates.d.ts +15 -8
  128. package/dist/sessions/background-updates.js +101 -25
  129. package/dist/sessions/background-updates.js.map +1 -1
  130. package/dist/sessions/cli-sessions.d.ts +23 -6
  131. package/dist/sessions/cli-sessions.js +84 -84
  132. package/dist/sessions/cli-sessions.js.map +1 -1
  133. package/dist/sessions/completions.d.ts +38 -2
  134. package/dist/sessions/completions.js +348 -77
  135. package/dist/sessions/completions.js.map +1 -1
  136. package/dist/sessions/compress.d.ts +8 -0
  137. package/dist/sessions/compress.js +2 -2
  138. package/dist/sessions/compress.js.map +1 -1
  139. package/dist/sessions/drafts.d.ts +14 -10
  140. package/dist/sessions/drafts.js +38 -43
  141. package/dist/sessions/drafts.js.map +1 -1
  142. package/dist/sessions/export.d.ts +2 -0
  143. package/dist/sessions/export.js +6 -2
  144. package/dist/sessions/export.js.map +1 -1
  145. package/dist/sessions/gateway-sessions.d.ts +86 -0
  146. package/dist/sessions/gateway-sessions.js +914 -0
  147. package/dist/sessions/gateway-sessions.js.map +1 -0
  148. package/dist/sessions/gateway-watcher.d.ts +10 -11
  149. package/dist/sessions/gateway-watcher.js +25 -21
  150. package/dist/sessions/gateway-watcher.js.map +1 -1
  151. package/dist/sessions/goals.d.ts +31 -0
  152. package/dist/sessions/goals.js +75 -0
  153. package/dist/sessions/goals.js.map +1 -0
  154. package/dist/sessions/journal.d.ts +5 -79
  155. package/dist/sessions/journal.js +15 -606
  156. package/dist/sessions/journal.js.map +1 -1
  157. package/dist/sessions/list.d.ts +34 -18
  158. package/dist/sessions/list.js +161 -147
  159. package/dist/sessions/list.js.map +1 -1
  160. package/dist/sessions/merge.d.ts +77 -13
  161. package/dist/sessions/merge.js +315 -65
  162. package/dist/sessions/merge.js.map +1 -1
  163. package/dist/sessions/notices.d.ts +22 -0
  164. package/dist/sessions/notices.js +72 -0
  165. package/dist/sessions/notices.js.map +1 -0
  166. package/dist/sessions/pending.d.ts +10 -4
  167. package/dist/sessions/pending.js +83 -7
  168. package/dist/sessions/pending.js.map +1 -1
  169. package/dist/sessions/prefix-index.d.ts +85 -0
  170. package/dist/sessions/prefix-index.js +243 -0
  171. package/dist/sessions/prefix-index.js.map +1 -0
  172. package/dist/sessions/recovery.d.ts +4 -7
  173. package/dist/sessions/recovery.js +100 -283
  174. package/dist/sessions/recovery.js.map +1 -1
  175. package/dist/sessions/relay.d.ts +20 -20
  176. package/dist/sessions/relay.js +205 -127
  177. package/dist/sessions/relay.js.map +1 -1
  178. package/dist/sessions/service.d.ts +251 -78
  179. package/dist/sessions/service.js +1510 -564
  180. package/dist/sessions/service.js.map +1 -1
  181. package/dist/sessions/session.d.ts +20 -2
  182. package/dist/sessions/session.js +33 -5
  183. package/dist/sessions/session.js.map +1 -1
  184. package/dist/sessions/shares.d.ts +7 -6
  185. package/dist/sessions/shares.js +22 -45
  186. package/dist/sessions/shares.js.map +1 -1
  187. package/dist/sessions/source-kind.js +1 -0
  188. package/dist/sessions/source-kind.js.map +1 -1
  189. package/dist/sessions/state-db-identity.d.ts +18 -0
  190. package/dist/sessions/state-db-identity.js +67 -0
  191. package/dist/sessions/state-db-identity.js.map +1 -0
  192. package/dist/sessions/state-db-worker.js +24 -5
  193. package/dist/sessions/state-db-worker.js.map +1 -1
  194. package/dist/sessions/state-db.d.ts +157 -21
  195. package/dist/sessions/state-db.js +1145 -204
  196. package/dist/sessions/state-db.js.map +1 -1
  197. package/dist/sessions/state-saved.d.ts +1 -1
  198. package/dist/sessions/state-saved.js +35 -11
  199. package/dist/sessions/state-saved.js.map +1 -1
  200. package/dist/sessions/storage/backend.d.ts +171 -0
  201. package/dist/sessions/storage/backend.js +19 -0
  202. package/dist/sessions/storage/backend.js.map +1 -0
  203. package/dist/sessions/storage/conformance.d.ts +20 -0
  204. package/dist/sessions/storage/conformance.js +237 -0
  205. package/dist/sessions/storage/conformance.js.map +1 -0
  206. package/dist/sessions/storage/document.d.ts +16 -0
  207. package/dist/sessions/storage/document.js +44 -0
  208. package/dist/sessions/storage/document.js.map +1 -0
  209. package/dist/sessions/storage/json-documents.d.ts +25 -0
  210. package/dist/sessions/storage/json-documents.js +277 -0
  211. package/dist/sessions/storage/json-documents.js.map +1 -0
  212. package/dist/sessions/storage/json-files.d.ts +23 -0
  213. package/dist/sessions/storage/json-files.js +244 -0
  214. package/dist/sessions/storage/json-files.js.map +1 -0
  215. package/dist/sessions/storage/json-installation.d.ts +3 -0
  216. package/dist/sessions/storage/json-installation.js +31 -0
  217. package/dist/sessions/storage/json-installation.js.map +1 -0
  218. package/dist/sessions/storage/json-journal.d.ts +113 -0
  219. package/dist/sessions/storage/json-journal.js +756 -0
  220. package/dist/sessions/storage/json-journal.js.map +1 -0
  221. package/dist/sessions/storage/json-recovery.d.ts +4 -0
  222. package/dist/sessions/storage/json-recovery.js +195 -0
  223. package/dist/sessions/storage/json-recovery.js.map +1 -0
  224. package/dist/sessions/storage/json.d.ts +82 -0
  225. package/dist/sessions/storage/json.js +350 -0
  226. package/dist/sessions/storage/json.js.map +1 -0
  227. package/dist/sessions/storage/row.d.ts +6 -0
  228. package/dist/sessions/storage/row.js +49 -0
  229. package/dist/sessions/storage/row.js.map +1 -0
  230. package/dist/sessions/storage/search-text.d.ts +4 -0
  231. package/dist/sessions/storage/search-text.js +16 -0
  232. package/dist/sessions/storage/search-text.js.map +1 -0
  233. package/dist/sessions/store.d.ts +67 -73
  234. package/dist/sessions/store.js +341 -607
  235. package/dist/sessions/store.js.map +1 -1
  236. package/dist/sessions/streams.d.ts +12 -7
  237. package/dist/sessions/streams.js +58 -15
  238. package/dist/sessions/streams.js.map +1 -1
  239. package/dist/sessions/titles.js +1 -1
  240. package/dist/sessions/titles.js.map +1 -1
  241. package/dist/sessions/todo.d.ts +5 -0
  242. package/dist/sessions/todo.js +28 -21
  243. package/dist/sessions/todo.js.map +1 -1
  244. package/dist/sessions/tool-display.d.ts +8 -5
  245. package/dist/sessions/tool-display.js +28 -16
  246. package/dist/sessions/tool-display.js.map +1 -1
  247. package/dist/sessions/turn-context.d.ts +10 -1
  248. package/dist/sessions/turn-context.js +13 -6
  249. package/dist/sessions/turn-context.js.map +1 -1
  250. package/dist/sessions/turn.d.ts +110 -22
  251. package/dist/sessions/turn.js +918 -380
  252. package/dist/sessions/turn.js.map +1 -1
  253. package/dist/sessions/wakeup-pause.d.ts +8 -13
  254. package/dist/sessions/wakeup-pause.js +31 -49
  255. package/dist/sessions/wakeup-pause.js.map +1 -1
  256. package/dist/sessions/window.js +13 -12
  257. package/dist/sessions/window.js.map +1 -1
  258. package/dist/settings.d.ts +19 -7
  259. package/dist/settings.js +179 -183
  260. package/dist/settings.js.map +1 -1
  261. package/dist/sidecar/client.d.ts +41 -4
  262. package/dist/sidecar/client.js +192 -42
  263. package/dist/sidecar/client.js.map +1 -1
  264. package/dist/sidecar/discover.d.ts +2 -1
  265. package/dist/sidecar/discover.js +93 -10
  266. package/dist/sidecar/discover.js.map +1 -1
  267. package/dist/sidecar/env.d.ts +4 -0
  268. package/dist/sidecar/env.js +3 -0
  269. package/dist/sidecar/env.js.map +1 -0
  270. package/dist/sidecar/fake.d.ts +6 -2
  271. package/dist/sidecar/fake.js +34 -4
  272. package/dist/sidecar/fake.js.map +1 -1
  273. package/dist/spa.d.ts +9 -4
  274. package/dist/spa.js +36 -12
  275. package/dist/spa.js.map +1 -1
  276. package/dist/startup-timing.d.ts +66 -0
  277. package/dist/startup-timing.js +129 -0
  278. package/dist/startup-timing.js.map +1 -0
  279. package/dist/test/env-file.d.ts +5 -0
  280. package/dist/test/env-file.js +88 -0
  281. package/dist/test/env-file.js.map +1 -0
  282. package/dist/test/fs-handles.d.ts +11 -0
  283. package/dist/test/fs-handles.js +31 -0
  284. package/dist/test/fs-handles.js.map +1 -0
  285. package/dist/test/harness.d.ts +1 -0
  286. package/dist/test/harness.js +1 -1
  287. package/dist/test/harness.js.map +1 -1
  288. package/dist/test/passkeys.d.ts +22 -0
  289. package/dist/test/passkeys.js +62 -0
  290. package/dist/test/passkeys.js.map +1 -0
  291. package/dist/test/storage.d.ts +15 -0
  292. package/dist/test/storage.js +26 -0
  293. package/dist/test/storage.js.map +1 -0
  294. package/dist/tools/commands.d.ts +6 -1
  295. package/dist/tools/commands.js +8 -2
  296. package/dist/tools/commands.js.map +1 -1
  297. package/dist/tools/connectors.d.ts +33 -0
  298. package/dist/tools/connectors.js +121 -0
  299. package/dist/tools/connectors.js.map +1 -0
  300. package/dist/tools/crons.d.ts +46 -5
  301. package/dist/tools/crons.js +100 -26
  302. package/dist/tools/crons.js.map +1 -1
  303. package/dist/tools/dashboard-plugins.d.ts +34 -5
  304. package/dist/tools/dashboard-plugins.js +146 -14
  305. package/dist/tools/dashboard-plugins.js.map +1 -1
  306. package/dist/tools/extensions.d.ts +5 -4
  307. package/dist/tools/extensions.js +213 -207
  308. package/dist/tools/extensions.js.map +1 -1
  309. package/dist/tools/gateway-restart.d.ts +82 -0
  310. package/dist/tools/gateway-restart.js +222 -0
  311. package/dist/tools/gateway-restart.js.map +1 -0
  312. package/dist/tools/health.d.ts +28 -4
  313. package/dist/tools/health.js +171 -50
  314. package/dist/tools/health.js.map +1 -1
  315. package/dist/tools/hygiene.d.ts +4 -3
  316. package/dist/tools/hygiene.js +23 -9
  317. package/dist/tools/hygiene.js.map +1 -1
  318. package/dist/tools/insights.d.ts +1 -1
  319. package/dist/tools/insights.js +2 -2
  320. package/dist/tools/insights.js.map +1 -1
  321. package/dist/tools/kanban.d.ts +4 -2
  322. package/dist/tools/kanban.js +28 -19
  323. package/dist/tools/kanban.js.map +1 -1
  324. package/dist/tools/mcp-health.js +74 -24
  325. package/dist/tools/mcp-health.js.map +1 -1
  326. package/dist/tools/mcp.js +19 -1
  327. package/dist/tools/mcp.js.map +1 -1
  328. package/dist/tools/memory-masks.d.ts +5 -0
  329. package/dist/tools/memory-masks.js +256 -0
  330. package/dist/tools/memory-masks.js.map +1 -0
  331. package/dist/tools/memory.d.ts +29 -3
  332. package/dist/tools/memory.js +69 -27
  333. package/dist/tools/memory.js.map +1 -1
  334. package/dist/tools/plugin-oauth.d.ts +14 -0
  335. package/dist/tools/plugin-oauth.js +53 -0
  336. package/dist/tools/plugin-oauth.js.map +1 -0
  337. package/dist/tools/plugin-settings.d.ts +15 -0
  338. package/dist/tools/plugin-settings.js +90 -0
  339. package/dist/tools/plugin-settings.js.map +1 -0
  340. package/dist/tools/prune-advice.d.ts +50 -0
  341. package/dist/tools/prune-advice.js +114 -0
  342. package/dist/tools/prune-advice.js.map +1 -0
  343. package/dist/tools/skills.d.ts +13 -5
  344. package/dist/tools/skills.js +53 -19
  345. package/dist/tools/skills.js.map +1 -1
  346. package/dist/tools/update-notifications.d.ts +102 -17
  347. package/dist/tools/update-notifications.js +400 -82
  348. package/dist/tools/update-notifications.js.map +1 -1
  349. package/dist/tools/update-rollback.d.ts +11 -0
  350. package/dist/tools/update-rollback.js +28 -0
  351. package/dist/tools/update-rollback.js.map +1 -0
  352. package/dist/tools/updates.d.ts +100 -33
  353. package/dist/tools/updates.js +1085 -345
  354. package/dist/tools/updates.js.map +1 -1
  355. package/dist/util.d.ts +2 -0
  356. package/dist/util.js +5 -0
  357. package/dist/util.js.map +1 -1
  358. package/dist/workspace/git.d.ts +16 -1
  359. package/dist/workspace/git.js +291 -11
  360. package/dist/workspace/git.js.map +1 -1
  361. package/dist/workspace/media.d.ts +12 -9
  362. package/dist/workspace/media.js +98 -38
  363. package/dist/workspace/media.js.map +1 -1
  364. package/dist/workspace/preview.js +4 -14
  365. package/dist/workspace/preview.js.map +1 -1
  366. package/dist/workspace/rollback.d.ts +8 -4
  367. package/dist/workspace/rollback.js +22 -12
  368. package/dist/workspace/rollback.js.map +1 -1
  369. package/dist/workspace/workspaces.d.ts +15 -19
  370. package/dist/workspace/workspaces.js +55 -127
  371. package/dist/workspace/workspaces.js.map +1 -1
  372. package/dist/workspace/worktrees.js +170 -32
  373. package/dist/workspace/worktrees.js.map +1 -1
  374. package/package.json +6 -4
  375. package/sidecar/agent_dependency.json +4 -4
  376. package/sidecar/agent_support.json +29 -0
  377. package/sidecar/scripts/record-fixtures.py +12 -3
  378. package/sidecar/scripts/replay_sidecar.py +8 -0
  379. package/sidecar/scripts/suite_runner.py +458 -0
  380. package/sidecar/scripts/test.sh +11 -5
  381. package/sidecar/talaria_sidecar/__init__.py +6 -1
  382. package/sidecar/talaria_sidecar/__main__.py +13 -4
  383. package/sidecar/talaria_sidecar/agent_mutation.py +1111 -0
  384. package/sidecar/talaria_sidecar/agent_services.py +1116 -0
  385. package/sidecar/talaria_sidecar/context_detail.py +59 -0
  386. package/sidecar/talaria_sidecar/dependency_sync.py +85 -0
  387. package/sidecar/talaria_sidecar/home.py +133 -14
  388. package/sidecar/talaria_sidecar/methods/__init__.py +2 -2
  389. package/sidecar/talaria_sidecar/methods/aux.py +211 -41
  390. package/sidecar/talaria_sidecar/methods/chat.py +1378 -200
  391. package/sidecar/talaria_sidecar/methods/checkpoints.py +29 -4
  392. package/sidecar/talaria_sidecar/methods/commands.py +483 -13
  393. package/sidecar/talaria_sidecar/methods/config.py +195 -6
  394. package/sidecar/talaria_sidecar/methods/connectors.py +375 -0
  395. package/sidecar/talaria_sidecar/methods/cron.py +374 -36
  396. package/sidecar/talaria_sidecar/methods/cron_execution.py +284 -0
  397. package/sidecar/talaria_sidecar/methods/dashboard_plugins.py +301 -0
  398. package/sidecar/talaria_sidecar/methods/gateway.py +215 -55
  399. package/sidecar/talaria_sidecar/methods/gateway_sessions.py +418 -0
  400. package/sidecar/talaria_sidecar/methods/goals.py +81 -41
  401. package/sidecar/talaria_sidecar/methods/kanban.py +82 -30
  402. package/sidecar/talaria_sidecar/methods/memory.py +84 -0
  403. package/sidecar/talaria_sidecar/methods/oauth.py +144 -13
  404. package/sidecar/talaria_sidecar/methods/plugin_catalog.py +198 -0
  405. package/sidecar/talaria_sidecar/methods/plugin_oauth.py +234 -0
  406. package/sidecar/talaria_sidecar/methods/process.py +229 -16
  407. package/sidecar/talaria_sidecar/methods/profiles.py +48 -9
  408. package/sidecar/talaria_sidecar/methods/providers.py +196 -26
  409. package/sidecar/talaria_sidecar/methods/runtime.py +71 -1
  410. package/sidecar/talaria_sidecar/methods/skills.py +83 -5
  411. package/sidecar/talaria_sidecar/methods/state_db.py +405 -112
  412. package/sidecar/talaria_sidecar/methods/stt.py +159 -78
  413. package/sidecar/talaria_sidecar/methods/text.py +14 -1
  414. package/sidecar/talaria_sidecar/methods/toolsets.py +51 -0
  415. package/sidecar/talaria_sidecar/methods/usage.py +113 -14
  416. package/sidecar/talaria_sidecar/methods/worktree.py +145 -19
  417. package/sidecar/talaria_sidecar/methods/write_approval.py +181 -0
  418. package/sidecar/talaria_sidecar/rpc.py +70 -7
  419. package/sidecar/talaria_sidecar/runtime.py +122 -14
  420. package/sidecar/talaria_sidecar/speed.py +47 -0
  421. package/sidecar/talaria_sidecar/startup_timing.py +119 -0
  422. package/static/dist/FILES.txt +242 -215
  423. package/static/dist/THIRD_PARTY_LICENSES.md +6 -22
  424. package/static/dist/assets/AppShell-3isgvoro.js +8 -0
  425. package/static/dist/assets/Button-f4n6dapf.js +1 -0
  426. package/static/dist/assets/ChatPage-k7b6xfax.js +4 -0
  427. package/static/dist/assets/ConnectTargets-juqvt5lm.js +1 -0
  428. package/static/dist/assets/Dialog-hta5utr3.js +1 -0
  429. package/static/dist/assets/ExtensionRoute-zrhjn0wm.js +1 -0
  430. package/static/dist/assets/Field-b6ez48oz.js +1 -0
  431. package/static/dist/assets/HubRoute-iwvso2tz.js +2 -0
  432. package/static/dist/assets/LinkCheckContext-ix6zqqkk.js +1 -0
  433. package/static/dist/assets/Markdown-jdeth7zq.js +2 -0
  434. package/static/dist/assets/MarkdownRenderer-fbswsgld.js +302 -0
  435. package/static/dist/assets/MarkdownRenderer-i9o6nr38.css +1 -0
  436. package/static/dist/assets/OAuthSignIn-bpd8hom3.js +1 -0
  437. package/static/dist/assets/ResourceSwitch-odi6dy2o.js +1 -0
  438. package/static/dist/assets/RightPanel-eu6enlo6.js +1 -0
  439. package/static/dist/assets/Select-kr07928w.js +1 -0
  440. package/static/dist/assets/SessionListPanel-etb2i54l.js +1 -0
  441. package/static/dist/assets/SettingsLayout-eu3xxp23.js +1 -0
  442. package/static/dist/assets/States-icab19yg.js +1 -0
  443. package/static/dist/assets/TerminalPanel-hngmsr8b.js +16 -0
  444. package/static/dist/assets/Toaster-nb2uzjw1.js +1 -0
  445. package/static/dist/assets/_app-ga1moszl.js +1 -0
  446. package/static/dist/assets/_app.ext._extensionId-na62087t.js +1 -0
  447. package/static/dist/assets/_app.index-jypgdqoi.js +1 -0
  448. package/static/dist/assets/_app.insights-kabejdtm.js +1 -0
  449. package/static/dist/assets/_app.kanban-m19kfcmx.js +1 -0
  450. package/static/dist/assets/_app.logs-iw4m96sz.js +1 -0
  451. package/static/dist/assets/_app.memory-jq5frwcg.js +1 -0
  452. package/static/dist/assets/_app.profiles-kwa3m7rp.js +1 -0
  453. package/static/dist/assets/_app.session._sessionId-o5lyeipj.js +1 -0
  454. package/static/dist/assets/_app.settings-ckl8hdll.js +1 -0
  455. package/static/dist/assets/_app.settings._section-dtdjk98a.js +3 -0
  456. package/static/dist/assets/_app.skills-n016rihd.js +1 -0
  457. package/static/dist/assets/_app.tasks-n8zuqsqe.js +1 -0
  458. package/static/dist/assets/_app.todos-btew5v2s.js +1 -0
  459. package/static/dist/assets/_app.workspaces-lnfk95ch.js +1 -0
  460. package/static/dist/assets/abnfDiagram-VCTEODGH-dttheegb.js +1 -0
  461. package/static/dist/assets/{angular-html-nu6l31w3.js → angular-html-l28bd5fo.js} +1 -1
  462. package/static/dist/assets/{angular-ts-fbx4f8mm.js → angular-ts-ffzx1vj0.js} +1 -1
  463. package/static/dist/assets/{apl-bx2xr7dh.js → apl-b7h7mmy4.js} +1 -1
  464. package/static/dist/assets/{arc-7popfhbk.js → arc-fk1b21lm.js} +1 -1
  465. package/static/dist/assets/architecture-7GRP2DOG-ic435919.js +1 -0
  466. package/static/dist/assets/architectureDiagram-5GKGNRK7-8r3glgiq.js +36 -0
  467. package/static/dist/assets/archive-il7c6053.js +1 -0
  468. package/static/dist/assets/{astro-g77i97cb.js → astro-k117fy0t.js} +1 -1
  469. package/static/dist/assets/back-gu3nu279.js +1 -0
  470. package/static/dist/assets/{blade-boo0u92y.js → blade-npefsmn8.js} +1 -1
  471. package/static/dist/assets/{blockDiagram-I7D4REHJ-jzthp1wa.js → blockDiagram-I7D4REHJ-jenyos6c.js} +4 -4
  472. package/static/dist/assets/{c-cat0w3sc.js → c-2umg6kbn.js} +1 -1
  473. package/static/dist/assets/{c4Diagram-7LVT6UL2-mwr67mt8.js → c4Diagram-7LVT6UL2-nzlx7yc4.js} +1 -1
  474. package/static/dist/assets/cancel-bsnfo36u.js +1 -0
  475. package/static/dist/assets/channel-dsbtk01y.js +1 -0
  476. package/static/dist/assets/{chunk-4HAMMTFA-gpq1y228.js → chunk-4HAMMTFA-g0cru63b.js} +20 -20
  477. package/static/dist/assets/{chunk-75Z2AOVW-ktje58c4.js → chunk-75Z2AOVW-7rkswkjw.js} +1 -1
  478. package/static/dist/assets/chunk-DU6HZSFF-fn73jzdo.js +128 -0
  479. package/static/dist/assets/{chunk-F27PBJKO-cmev85ti.js → chunk-F27PBJKO-oey8e72m.js} +1 -1
  480. package/static/dist/assets/{chunk-FOHPRMQF-opuflp73.js → chunk-FOHPRMQF-ipewusgj.js} +8 -8
  481. package/static/dist/assets/{chunk-GMAD6QVW-htjgt22y.js → chunk-GMAD6QVW-l2a32wiy.js} +6 -6
  482. package/static/dist/assets/{chunk-GVQU2GXP-qndvoxl7.js → chunk-GVQU2GXP-o9dwzh8h.js} +1 -1
  483. package/static/dist/assets/{chunk-IMKFNOWR-e5bkd5q6.js → chunk-IMKFNOWR-eblwj20b.js} +5 -5
  484. package/static/dist/assets/{chunk-L3NEJ4N5-mj1155r6.js → chunk-L3NEJ4N5-o2mufspb.js} +1 -1
  485. package/static/dist/assets/chunk-OSK3NFVY-ijp9pw29.js +10 -0
  486. package/static/dist/assets/{chunk-P2QGCYS3-f7t54xfm.js → chunk-P2QGCYS3-hs9hqwl4.js} +1 -1
  487. package/static/dist/assets/{chunk-POPQ4Y6H-i927v9oa.js → chunk-POPQ4Y6H-bp9rsqez.js} +1 -1
  488. package/static/dist/assets/{chunk-PWAF6VOD-m84lmnyt.js → chunk-PWAF6VOD-brkprov6.js} +1 -1
  489. package/static/dist/assets/{chunk-SHT3W25Y-mi0tlcu9.js → chunk-SHT3W25Y-gmpv0pxz.js} +13 -13
  490. package/static/dist/assets/{chunk-SVP7TREG-dnau702j.js → chunk-SVP7TREG-oldm08fu.js} +4 -4
  491. package/static/dist/assets/{chunk-TICWLB2K-edem1gkg.js → chunk-TICWLB2K-ooqilfv7.js} +6 -6
  492. package/static/dist/assets/{chunk-XXDRQBXY-n40pf9vy.js → chunk-XXDRQBXY-jkmnqu65.js} +1 -1
  493. package/static/dist/assets/classDiagram-ZZMXUADV-fvgcv24g.js +1 -0
  494. package/static/dist/assets/classDiagram-v2-VYDZK3BY-fvgcv24g.js +1 -0
  495. package/static/dist/assets/{cobol-go622aep.js → cobol-ssf9hkh7.js} +1 -1
  496. package/static/dist/assets/{coffee-jwo1xjhq.js → coffee-lsi9fwae.js} +1 -1
  497. package/static/dist/assets/copied-bz3gkazh.js +1 -0
  498. package/static/dist/assets/copy-jo006coq.js +1 -0
  499. package/static/dist/assets/cose-bilkent-JH36ORCC-layy2r27.js +1 -0
  500. package/static/dist/assets/{cpp-nre7j0kq.js → cpp-lfrh4y55.js} +1 -1
  501. package/static/dist/assets/{crystal-lviso2je.js → crystal-efh4pte7.js} +1 -1
  502. package/static/dist/assets/{css-ywz9j4hb.js → css-i82qdo89.js} +1 -1
  503. package/static/dist/assets/cynefin-OW5HDTMX-d47op7qs.js +1 -0
  504. package/static/dist/assets/cynefinDiagram-5FMLGOSQ-doa7594y.js +62 -0
  505. package/static/dist/assets/cytoscape.esm-fjn2algp.js +321 -0
  506. package/static/dist/assets/dagre-GXQ25YYZ-os768dp4.js +4 -0
  507. package/static/dist/assets/dagre-o5jmjz46.js +1 -0
  508. package/static/dist/assets/{diagram-S7CK7UJ4-l8abxaes.js → diagram-S7CK7UJ4-fyi81nxd.js} +4 -4
  509. package/static/dist/assets/diagram-UQ7AKVKN-j3exggaq.js +41 -0
  510. package/static/dist/assets/{diagram-VSXAHHWV-fnky6lvc.js → diagram-VSXAHHWV-omo1en2l.js} +1 -1
  511. package/static/dist/assets/diagram-VX7I27RA-oro2cyu0.js +24 -0
  512. package/static/dist/assets/diagram-Z3DM3KII-byt9vdb7.js +24 -0
  513. package/static/dist/assets/dist-crc46di9.js +7 -0
  514. package/static/dist/assets/dist-etpoyscq.js +44 -0
  515. package/static/dist/assets/{dist-c4c2m3kv.js → dist-nb670eu6.js} +1 -1
  516. package/static/dist/assets/ebnfDiagram-PWID7BFC-ee3haugh.js +1 -0
  517. package/static/dist/assets/{edge-dvv35byi.js → edge-lrob635n.js} +1 -1
  518. package/static/dist/assets/{elixir-i2f1ki1g.js → elixir-kdpxeq93.js} +1 -1
  519. package/static/dist/assets/{elm-cpepyjm4.js → elm-c8irj9uh.js} +1 -1
  520. package/static/dist/assets/erDiagram-RLTQ6QDP-d1e93yff.js +99 -0
  521. package/static/dist/assets/{erb-idlyfheg.js → erb-flwsv146.js} +1 -1
  522. package/static/dist/assets/eventmodeling-NTZA5JFV-i1ihb40c.js +1 -0
  523. package/static/dist/assets/flowDiagram-HODETNUW-jahfpiod.js +1 -0
  524. package/static/dist/assets/folder-plus-ivoglq98.js +1 -0
  525. package/static/dist/assets/{ganttDiagram-EL5Y4UJY-ngbsyp37.js → ganttDiagram-EL5Y4UJY-m7g0jud4.js} +1 -1
  526. package/static/dist/assets/{git-rebase-d9lpfpbn.js → git-rebase-bli19aoq.js} +1 -1
  527. package/static/dist/assets/gitGraph-4MIJSDKK-hzdj07yy.js +1 -0
  528. package/static/dist/assets/{gitGraphDiagram-WWUBYQGX-eravdti4.js → gitGraphDiagram-WWUBYQGX-dm9agbna.js} +1 -1
  529. package/static/dist/assets/{glimmer-js-39i0urfb.js → glimmer-js-d4icg38p.js} +1 -1
  530. package/static/dist/assets/{glimmer-ts-gdtd6n73.js → glimmer-ts-bk75772u.js} +1 -1
  531. package/static/dist/assets/{glsl-o1djm5pp.js → glsl-lqormp2b.js} +1 -1
  532. package/static/dist/assets/{graphql-kj6rz55t.js → graphql-hw6s5qzd.js} +1 -1
  533. package/static/dist/assets/{hack-pe1qqr2i.js → hack-ozrv6l4d.js} +1 -1
  534. package/static/dist/assets/{haml-cknnbcqs.js → haml-gytfosdt.js} +1 -1
  535. package/static/dist/assets/{handlebars-hwq64orh.js → handlebars-b6g7jffd.js} +1 -1
  536. package/static/dist/assets/highlighted-body-KPVGNVTW-mmgz2czu.js +1 -0
  537. package/static/dist/assets/host-fr6lni1p.js +1 -0
  538. package/static/dist/assets/{html-derivative-h2i2pyjc.js → html-derivative-f1tqcroo.js} +1 -1
  539. package/static/dist/assets/{html-ha05xtvt.js → html-on6oj6yj.js} +1 -1
  540. package/static/dist/assets/{http-cf94zu27.js → http-odhufsl7.js} +1 -1
  541. package/static/dist/assets/{hurl-lslax568.js → hurl-mu680336.js} +1 -1
  542. package/static/dist/assets/index-73649w7o.js +10 -0
  543. package/static/dist/assets/index-lhf1fsdf.css +2 -0
  544. package/static/dist/assets/info-A6RAGUB7-lll1dqmm.js +1 -0
  545. package/static/dist/assets/infoDiagram-27XIBGKW-k7esc639.js +2 -0
  546. package/static/dist/assets/{ishikawaDiagram-5VMMS53U-i6ypq351.js → ishikawaDiagram-5VMMS53U-lgr6k9wo.js} +6 -6
  547. package/static/dist/assets/{java-ndjf2o89.js → java-nxbe8uju.js} +1 -1
  548. package/static/dist/assets/{javascript-coftlwy3.js → javascript-lz3kxcyz.js} +1 -1
  549. package/static/dist/assets/{jinja-etei9wy7.js → jinja-l5pk84gt.js} +1 -1
  550. package/static/dist/assets/{jison-hyekgft1.js → jison-jdutdwyy.js} +1 -1
  551. package/static/dist/assets/{journeyDiagram-3NMN7TZE-lduf1z95.js → journeyDiagram-3NMN7TZE-ndmbxuqk.js} +1 -1
  552. package/static/dist/assets/{json-lok0yaho.js → json-dnge4ssf.js} +1 -1
  553. package/static/dist/assets/{jsx-b64w0nbx.js → jsx-c3lwhkep.js} +1 -1
  554. package/static/dist/assets/{jsx-runtime-eu92a5pu.js → jsx-runtime-o40ukmjl.js} +1 -1
  555. package/static/dist/assets/{julia-jxxzz2yn.js → julia-hwd4rrcb.js} +1 -1
  556. package/static/dist/assets/{just-mc29iw9t.js → just-nka3oxdx.js} +1 -1
  557. package/static/dist/assets/{kanban-definition-UXKFOSKX-e18bu4pg.js → kanban-definition-UXKFOSKX-mjxym0jp.js} +28 -28
  558. package/static/dist/assets/katex-cbdd1ohw.css +1 -0
  559. package/static/dist/assets/katex-pbij2oo6.js +257 -0
  560. package/static/dist/assets/{latex-pafa03ft.js → latex-iqmr7e40.js} +1 -1
  561. package/static/dist/assets/lazyRouteComponent-cwb6l7xh.js +1 -0
  562. package/static/dist/assets/{line-meizqsvn.js → line-mtr5k6il.js} +1 -1
  563. package/static/dist/assets/linear-jlwrvvy6.js +1 -0
  564. package/static/dist/assets/link-iadw4ghw.js +2 -0
  565. package/static/dist/assets/{liquid-hz5c2pov.js → liquid-okmk9tbp.js} +1 -1
  566. package/static/dist/assets/locale-cs-n41hptse.js +5 -0
  567. package/static/dist/assets/locale-de-k7ht47ew.js +5 -0
  568. package/static/dist/assets/locale-es-ih078lco.js +5 -0
  569. package/static/dist/assets/locale-fr-ojabnf41.js +5 -0
  570. package/static/dist/assets/locale-it-kb96jufy.js +5 -0
  571. package/static/dist/assets/locale-ja-jpsp3xs1.js +7 -0
  572. package/static/dist/assets/locale-ko-cpzuy0n7.js +5 -0
  573. package/static/dist/assets/locale-pl-dbap4leu.js +5 -0
  574. package/static/dist/assets/locale-pt-nci7w72x.js +5 -0
  575. package/static/dist/assets/locale-ru-soghe4cs.js +7 -0
  576. package/static/dist/assets/locale-tr-ks00mu68.js +5 -0
  577. package/static/dist/assets/locale-vi-ij7twfm6.js +5 -0
  578. package/static/dist/assets/locale-zh-Hant-feakwr7a.js +5 -0
  579. package/static/dist/assets/locale-zh-ren0vjyv.js +7 -0
  580. package/static/dist/assets/login-lkhtzfcl.js +1 -0
  581. package/static/dist/assets/{lua-leyf8mlb.js → lua-krx4xj5h.js} +1 -1
  582. package/static/dist/assets/{marko-cn1fzpdv.js → marko-gbvpfehz.js} +1 -1
  583. package/static/dist/assets/{mdc-huhy88df.js → mdc-c21zlyi5.js} +1 -1
  584. package/static/dist/assets/mermaid-HWGCJPDP-jx0q5dm2.js +1 -0
  585. package/static/dist/assets/mermaid-parser.core-k91vdnvi.js +7 -0
  586. package/static/dist/assets/micromark-factory-space-fnmnpi6s.js +1 -0
  587. package/static/dist/assets/{mindmap-definition-YA3MSWOX-27b26eok.js → mindmap-definition-YA3MSWOX-ehztfea4.js} +28 -28
  588. package/static/dist/assets/{nginx-e7lvhsmn.js → nginx-f3d68ed4.js} +1 -1
  589. package/static/dist/assets/{nim-dun5d8mk.js → nim-dw0jcy70.js} +1 -1
  590. package/static/dist/assets/onboarding-f67z0a2r.js +1 -0
  591. package/static/dist/assets/packet-AYTQ26CC-ok2xrblz.js +1 -0
  592. package/static/dist/assets/pcmTap.worklet-74EKjWAZ.js +1 -0
  593. package/static/dist/assets/pegDiagram-XKGWAZYB-ec3rpj0m.js +1 -0
  594. package/static/dist/assets/{perl-bj3oqtet.js → perl-3c0r45c8.js} +1 -1
  595. package/static/dist/assets/{php-buzp12r0.js → php-rznhidvp.js} +1 -1
  596. package/static/dist/assets/pie-WAS4IAKB-iwkir23u.js +1 -0
  597. package/static/dist/assets/pieDiagram-E7YTZNPT-fcpqpekh.js +39 -0
  598. package/static/dist/assets/{pug-mjad7he9.js → pug-f2le4f3y.js} +1 -1
  599. package/static/dist/assets/{qml-d1gdp10s.js → qml-e2wbq9cr.js} +1 -1
  600. package/static/dist/assets/{quadrantDiagram-AXDQQJYC-hhue7d8o.js → quadrantDiagram-AXDQQJYC-lqsync43.js} +1 -1
  601. package/static/dist/assets/queryKeys-ed4n2egc.js +9 -0
  602. package/static/dist/assets/{r-o3r9c7ao.js → r-epfzuw6q.js} +1 -1
  603. package/static/dist/assets/radar-RG4KPBEZ-hje4jbk6.js +1 -0
  604. package/static/dist/assets/railroad-74A4TZTK-gll9n6qi.js +1 -0
  605. package/static/dist/assets/railroad-abnf-HS5TGJTU-o6h6lpn4.js +1 -0
  606. package/static/dist/assets/railroad-ebnf-LZEXJU2U-juaefj6o.js +1 -0
  607. package/static/dist/assets/railroad-peg-WCYAUIDC-cgfhvpah.js +1 -0
  608. package/static/dist/assets/railroadDiagram-O6MQD6OU-lp3w7awf.js +1 -0
  609. package/static/dist/assets/{razor-ilc585yr.js → razor-pea1u1d0.js} +1 -1
  610. package/static/dist/assets/refresh-cw-iccm7a4e.js +1 -0
  611. package/static/dist/assets/refresh-i9ya9dvl.js +1 -0
  612. package/static/dist/assets/{regexp-mpjtcvwm.js → regexp-hzte0a5x.js} +1 -1
  613. package/static/dist/assets/registry-g7w3353u.js +1 -0
  614. package/static/dist/assets/requirementDiagram-BXWQKSXE-ha8eibcf.js +84 -0
  615. package/static/dist/assets/rolldown-runtime-bnnw9q4a.js +1 -0
  616. package/static/dist/assets/{rst-jrkwjdyi.js → rst-m6tugj5o.js} +1 -1
  617. package/static/dist/assets/{ruby-n4tjcbpz.js → ruby-l19vq3w1.js} +1 -1
  618. package/static/dist/assets/runtime-nlxpnegr.js +1 -0
  619. package/static/dist/assets/{sankeyDiagram-P5KCCOFB-fqb8xcjf.js → sankeyDiagram-P5KCCOFB-oxf31pr9.js} +1 -1
  620. package/static/dist/assets/{sas-hjo6y93k.js → sas-ktdxo397.js} +1 -1
  621. package/static/dist/assets/{scss-ncidjv48.js → scss-kn3oxfwf.js} +1 -1
  622. package/static/dist/assets/{sequenceDiagram-WJ2MYXX4-dlcz6qjz.js → sequenceDiagram-WJ2MYXX4-jiq8lhyo.js} +11 -11
  623. package/static/dist/assets/settings_section_extensions_title-fadc7o65.js +1 -0
  624. package/static/dist/assets/share._token-o76ki0ly.js +2 -0
  625. package/static/dist/assets/{shellscript-m8whjpqd.js → shellscript-l100jtrg.js} +1 -1
  626. package/static/dist/assets/{shellsession-i5bj6syz.js → shellsession-m5qukwow.js} +1 -1
  627. package/static/dist/assets/sizeCapture-INFHLROL-dk1io13w.js +1 -0
  628. package/static/dist/assets/sliders-horizontal-ddcs88av.js +1 -0
  629. package/static/dist/assets/{soy-hhh36ysq.js → soy-mexlscur.js} +1 -1
  630. package/static/dist/assets/{sql-j21bzcl6.js → sql-o0ho5suh.js} +1 -1
  631. package/static/dist/assets/src-h89s0hs4.js +1 -0
  632. package/static/dist/assets/{stata-bbu2onh1.js → stata-be9ck1q3.js} +1 -1
  633. package/static/dist/assets/stateDiagram-D77RDMKH-f3fslnon.js +1 -0
  634. package/static/dist/assets/stateDiagram-v2-MP3YSRHH-hlt6yphw.js +1 -0
  635. package/static/dist/assets/{surrealql-l5vczuco.js → surrealql-gk1xkkyy.js} +1 -1
  636. package/static/dist/assets/{svelte-idn422g6.js → svelte-k6ecjilf.js} +1 -1
  637. package/static/dist/assets/swimlanes-42K2YHIH-k1hmk7jf.js +1 -0
  638. package/static/dist/assets/swimlanesDiagram-VR7AAH4N-hd5t9tnt.js +8 -0
  639. package/static/dist/assets/{templ-e22qou3c.js → templ-gf3bftk6.js} +1 -1
  640. package/static/dist/assets/{tex-deqpc5ee.js → tex-d21fqv1z.js} +1 -1
  641. package/static/dist/assets/{timeline-definition-24CTP7MA-b1vl2zil.js → timeline-definition-24CTP7MA-n3ncfy9r.js} +8 -8
  642. package/static/dist/assets/toast-liparz2j.js +56 -0
  643. package/static/dist/assets/treeView-Q6P3EWNA-l3y2pejt.js +1 -0
  644. package/static/dist/assets/treemap-WGGIJYW6-jown9axh.js +1 -0
  645. package/static/dist/assets/{ts-tags-ctnibc27.js → ts-tags-n0g61gr6.js} +1 -1
  646. package/static/dist/assets/{tsx-i163n32g.js → tsx-cvv7wv6q.js} +1 -1
  647. package/static/dist/assets/{twig-x0fi7wm8.js → twig-n1f67204.js} +1 -1
  648. package/static/dist/assets/{typescript-g18c34xz.js → typescript-og7o55cx.js} +1 -1
  649. package/static/dist/assets/untitled-mj86r4gz.js +1 -0
  650. package/static/dist/assets/useDebounced-g8r0ggve.js +1 -0
  651. package/static/dist/assets/useForm-o4uu74mx.js +1 -0
  652. package/static/dist/assets/{useParams-b4dq6n4q.js → useParams-ftsveu84.js} +1 -1
  653. package/static/dist/assets/{useSearch-ipfmv3he.js → useSearch-crqueqga.js} +1 -1
  654. package/static/dist/assets/vennDiagram-4TSXK5OY-dh59uq1c.js +34 -0
  655. package/static/dist/assets/{vue-mwu5l1bb.js → vue-ej4xpwqw.js} +1 -1
  656. package/static/dist/assets/{vue-html-nskj3du0.js → vue-html-d48xsjuo.js} +1 -1
  657. package/static/dist/assets/{vue-vine-cqe77smq.js → vue-vine-pev88ip6.js} +1 -1
  658. package/static/dist/assets/wardley-WFR3VGLG-e6d74b0j.js +1 -0
  659. package/static/dist/assets/wardleyDiagram-VM6X3IG4-hnofh78f.js +78 -0
  660. package/static/dist/assets/with-selector-nu1b5z0v.js +1 -0
  661. package/static/dist/assets/{xml-gau7gvrv.js → xml-ifxp6gqb.js} +1 -1
  662. package/static/dist/assets/{xsl-ew09zq8b.js → xsl-fug2cckc.js} +1 -1
  663. package/static/dist/assets/{xychartDiagram-S5SC5T6Z-e49523ab.js → xychartDiagram-S5SC5T6Z-bpymjelb.js} +6 -6
  664. package/static/dist/assets/{yaml-ofnrxtvf.js → yaml-fjmafnlo.js} +1 -1
  665. package/static/dist/extension-sdk.js +1 -1
  666. package/static/dist/index.html +1 -1
  667. package/static/dist/sw.js +180 -136
  668. package/static/dist/assets/AppShell-g3bkgnvt.js +0 -1
  669. package/static/dist/assets/ChatPage-oo7bdan6.js +0 -25
  670. package/static/dist/assets/Dialog-g355qxhp.js +0 -1
  671. package/static/dist/assets/ExtensionRoute-i2y9fvjm.js +0 -1
  672. package/static/dist/assets/HubRoute-lmkrbw47.js +0 -2
  673. package/static/dist/assets/Markdown-j4kut4j2.js +0 -598
  674. package/static/dist/assets/Markdown-lwviulmg.css +0 -1
  675. package/static/dist/assets/RightPanel-ohlsdzfl.js +0 -1
  676. package/static/dist/assets/Select-kddq75qc.js +0 -1
  677. package/static/dist/assets/SessionListPanel-lu3oy0hw.js +0 -1
  678. package/static/dist/assets/SettingsLayout-o9bv4mgb.js +0 -1
  679. package/static/dist/assets/States-eq6fe29m.js +0 -1
  680. package/static/dist/assets/Toaster-pc247u9f.js +0 -1
  681. package/static/dist/assets/_app-f8n1i0m1.js +0 -1
  682. package/static/dist/assets/_app.ext._extensionId-gfbzpoou.js +0 -1
  683. package/static/dist/assets/_app.index-bzzv80hk.js +0 -1
  684. package/static/dist/assets/_app.insights-dzixbryi.js +0 -1
  685. package/static/dist/assets/_app.kanban-c6hep2us.js +0 -1
  686. package/static/dist/assets/_app.logs-i69qds98.js +0 -1
  687. package/static/dist/assets/_app.memory-kl4vf0gd.js +0 -1
  688. package/static/dist/assets/_app.profiles-b8zinmyp.js +0 -1
  689. package/static/dist/assets/_app.session._sessionId-fn1bhde6.js +0 -1
  690. package/static/dist/assets/_app.settings-cg8plwmf.js +0 -1
  691. package/static/dist/assets/_app.settings._section-bkwbi9zn.js +0 -3
  692. package/static/dist/assets/_app.skills-cs47sbvs.js +0 -1
  693. package/static/dist/assets/_app.tasks-dwvk64tc.js +0 -1
  694. package/static/dist/assets/_app.todos-c8xjm8p3.js +0 -1
  695. package/static/dist/assets/_app.workspaces-ehvd1gds.js +0 -1
  696. package/static/dist/assets/abnfDiagram-VCTEODGH-c8kdixke.js +0 -1
  697. package/static/dist/assets/architecture-7GRP2DOG-6crvnylg.js +0 -1
  698. package/static/dist/assets/architectureDiagram-5GKGNRK7-cku06x1p.js +0 -36
  699. package/static/dist/assets/back-h7aun7ew.js +0 -1
  700. package/static/dist/assets/cancel-fhi0vcnu.js +0 -1
  701. package/static/dist/assets/channel-b2zo73z1.js +0 -1
  702. package/static/dist/assets/chunk-DU6HZSFF-ofajdixh.js +0 -128
  703. package/static/dist/assets/chunk-OSK3NFVY-e7gkikcw.js +0 -10
  704. package/static/dist/assets/classDiagram-ZZMXUADV-oe99st8x.js +0 -1
  705. package/static/dist/assets/classDiagram-v2-VYDZK3BY-oe99st8x.js +0 -1
  706. package/static/dist/assets/copied-hcplv46p.js +0 -1
  707. package/static/dist/assets/copy-magtofyp.js +0 -1
  708. package/static/dist/assets/cose-bilkent-JH36ORCC-eclcy6ja.js +0 -1
  709. package/static/dist/assets/cynefin-OW5HDTMX-siqlulkl.js +0 -1
  710. package/static/dist/assets/cynefinDiagram-5FMLGOSQ-i648tah9.js +0 -62
  711. package/static/dist/assets/cytoscape.esm-bqu53u12.js +0 -321
  712. package/static/dist/assets/dagre-GXQ25YYZ-mwn6uc17.js +0 -4
  713. package/static/dist/assets/dagre-lkoknbjn.js +0 -1
  714. package/static/dist/assets/diagram-UQ7AKVKN-mekq7zgq.js +0 -41
  715. package/static/dist/assets/diagram-VX7I27RA-xe6r5qfw.js +0 -24
  716. package/static/dist/assets/diagram-Z3DM3KII-nq07dg7k.js +0 -24
  717. package/static/dist/assets/ebnfDiagram-PWID7BFC-c62ipm3g.js +0 -1
  718. package/static/dist/assets/endpoints-klbxod4t.js +0 -64
  719. package/static/dist/assets/erDiagram-RLTQ6QDP-h39kmnzy.js +0 -99
  720. package/static/dist/assets/eventmodeling-NTZA5JFV-obfede4u.js +0 -1
  721. package/static/dist/assets/flowDiagram-HODETNUW-kdpsp1je.js +0 -1
  722. package/static/dist/assets/gitGraph-4MIJSDKK-fr2i7caa.js +0 -1
  723. package/static/dist/assets/highlighted-body-KPVGNVTW-jwpop9p8.js +0 -1
  724. package/static/dist/assets/host-i828xuo7.js +0 -1
  725. package/static/dist/assets/index-eh8zilnv.css +0 -2
  726. package/static/dist/assets/index-r648f4o1.js +0 -11
  727. package/static/dist/assets/info-A6RAGUB7-h11x0dxo.js +0 -1
  728. package/static/dist/assets/infoDiagram-27XIBGKW-dfh47dw9.js +0 -2
  729. package/static/dist/assets/lazyRouteComponent-e1y4t2i9.js +0 -1
  730. package/static/dist/assets/linear-becwlnhk.js +0 -1
  731. package/static/dist/assets/link-oot2yn73.js +0 -1
  732. package/static/dist/assets/login-gu28l9ou.js +0 -1
  733. package/static/dist/assets/mermaid-HWGCJPDP-mtwrj8fn.js +0 -1
  734. package/static/dist/assets/mermaid-parser.core-ntne45i9.js +0 -7
  735. package/static/dist/assets/not-found-ccnnac39.js +0 -1
  736. package/static/dist/assets/onboarding-lkphzu1s.js +0 -1
  737. package/static/dist/assets/onboarding_model_label-ftpjdwqk.js +0 -1
  738. package/static/dist/assets/packet-AYTQ26CC-l6jdka8p.js +0 -1
  739. package/static/dist/assets/pegDiagram-XKGWAZYB-g1er3bxj.js +0 -1
  740. package/static/dist/assets/pie-WAS4IAKB-i0ylcrt9.js +0 -1
  741. package/static/dist/assets/pieDiagram-E7YTZNPT-fbz1e55z.js +0 -39
  742. package/static/dist/assets/radar-RG4KPBEZ-f9b70aa4.js +0 -1
  743. package/static/dist/assets/railroad-74A4TZTK-lgsuoeda.js +0 -1
  744. package/static/dist/assets/railroad-abnf-HS5TGJTU-nf9d6pdx.js +0 -1
  745. package/static/dist/assets/railroad-ebnf-LZEXJU2U-f7ummkt5.js +0 -1
  746. package/static/dist/assets/railroad-peg-WCYAUIDC-oczq5tqs.js +0 -1
  747. package/static/dist/assets/railroadDiagram-O6MQD6OU-eqpy9fnz.js +0 -1
  748. package/static/dist/assets/refresh-abtu93ke.js +0 -1
  749. package/static/dist/assets/refresh-cw-hlwb02qv.js +0 -1
  750. package/static/dist/assets/requirementDiagram-BXWQKSXE-ogf6puhi.js +0 -84
  751. package/static/dist/assets/rolldown-runtime-b9miacsj.js +0 -1
  752. package/static/dist/assets/root-mbklpuv4.js +0 -1
  753. package/static/dist/assets/saved-girnabkf.js +0 -1
  754. package/static/dist/assets/settings_section_extensions_title-h14cwk6f.js +0 -1
  755. package/static/dist/assets/share._token-kl0r7ido.js +0 -2
  756. package/static/dist/assets/sizeCapture-INFHLROL-g612l48j.js +0 -1
  757. package/static/dist/assets/sliders-horizontal-n1zm34qq.js +0 -1
  758. package/static/dist/assets/src-hjyib4mu.js +0 -1
  759. package/static/dist/assets/sse-iwku0sjo.js +0 -1
  760. package/static/dist/assets/stateDiagram-D77RDMKH-fyoznpcs.js +0 -1
  761. package/static/dist/assets/stateDiagram-v2-MP3YSRHH-ixhx8r46.js +0 -1
  762. package/static/dist/assets/swimlanes-42K2YHIH-oefldhfy.js +0 -1
  763. package/static/dist/assets/swimlanesDiagram-VR7AAH4N-h9ersk2e.js +0 -8
  764. package/static/dist/assets/todoStore-jjr5yr78.js +0 -1
  765. package/static/dist/assets/treeView-Q6P3EWNA-f7hcci5o.js +0 -1
  766. package/static/dist/assets/treemap-WGGIJYW6-nl85071a.js +0 -1
  767. package/static/dist/assets/units-kgxzxfhi.js +0 -1
  768. package/static/dist/assets/untitled-cikfjntn.js +0 -1
  769. package/static/dist/assets/useForm-kqoqg0k9.js +0 -1
  770. package/static/dist/assets/useLocale-o59tbiea.js +0 -1
  771. package/static/dist/assets/vennDiagram-4TSXK5OY-h5hzbk0n.js +0 -34
  772. package/static/dist/assets/wardley-WFR3VGLG-jftvpm3e.js +0 -1
  773. package/static/dist/assets/wardleyDiagram-VM6X3IG4-hedh85ge.js +0 -78
  774. /package/static/dist/assets/{ChatPage-gmu5c7lf.css → TerminalPanel-gmu5c7lf.css} +0 -0
@@ -1,8 +1,21 @@
1
- import { existsSync, mkdirSync, readFileSync } from 'node:fs';
2
- import { dirname, resolve } from 'node:path';
3
1
  import { createHash, randomUUID } from 'node:crypto';
4
- import { atomicWriteSecretJson } from '../fs/atomic.js';
5
- const PHASES = new Set(['applying', 'awaiting_confirmation', 'restarting', 'succeeded', 'blocked', 'failed', 'unknown']);
2
+ import { readDocument } from '../sessions/storage/document.js';
3
+ import { str } from '../util.js';
4
+ export function updateNotificationOwner(session) {
5
+ const authType = str(session?.auth_type).trim();
6
+ if (authType === 'oidc') {
7
+ const issuer = str(session?.oidc_issuer).trim();
8
+ const subject = typeof session?.oidc_subject === 'string' ? session.oidc_subject : '';
9
+ if (issuer && subject.trim())
10
+ return `oidc:${createHash('sha256').update(JSON.stringify([issuer, subject]), 'utf8').digest('hex')}`;
11
+ const token = str(session?.token).trim();
12
+ if (token)
13
+ return `oidc-session:${createHash('sha256').update(JSON.stringify([token]), 'utf8').digest('hex')}`;
14
+ }
15
+ const username = str(session?.username).trim();
16
+ return username ? `${authType || 'auth'}:${username}` : 'local-owner';
17
+ }
18
+ const PHASES = new Set(['applying', 'awaiting_confirmation', 'waiting_for_idle', 'restarting', 'verifying', 'succeeded', 'blocked', 'failed', 'unknown']);
6
19
  const REVISION = /^[a-f0-9]{40}$/;
7
20
  const PER_SCOPE_LIMIT = 50;
8
21
  const GLOBAL_LIMIT = 500;
@@ -10,52 +23,130 @@ export const FRONTEND_BUILD = /^[a-f0-9]{64}$/;
10
23
  export const TAB_ID = /^[A-Za-z0-9_-]{8,64}$/;
11
24
  export const WEB_REFRESH_KIND = 'web_refresh';
12
25
  export const WEB_REFRESH_ACTION = 'reload';
26
+ /** TAL-953: restart the gateway now instead of waiting for its running work to finish. */
27
+ export const GATEWAY_RESTART_NOW = 'restart_gateway_now';
28
+ const GATEWAY_RESTART_NOW_ACTION = { id: GATEWAY_RESTART_NOW, label: 'Restart now', style: 'destructive', acknowledges: false };
13
29
  /** A closed tab stops checking in; its refresh notice is dropped once unseen this long. An open tab recreates it on its next check. */
14
30
  const TAB_TTL_MS = 60 * 60 * 1000;
15
- const copy = (row) => ({
16
- id: row.id, kind: row.kind, target: row.target, phase: row.phase, severity: row.severity,
17
- persistent: row.persistent, requires_acknowledgement: row.requires_acknowledgement, actions: row.actions,
18
- destination: row.destination,
19
- title: row.title, message: row.message, created_at: row.created_at, updated_at: row.updated_at, read_at: row.read_at,
20
- acknowledged_at: row.acknowledged_at, acknowledged_action_id: row.acknowledged_action_id,
21
- verified_revision: row.verified_revision, verified_version: row.verified_version, detail: row.detail,
22
- unread: row.read_at === null,
23
- active: row.kind === 'update' && ['applying', 'restarting'].includes(row.phase),
24
- requires_interaction: row.requires_acknowledgement && row.acknowledged_at === null,
25
- can_dismiss: isDismissible(row),
26
- });
31
+ const FAILED_MESSAGE = 'The update could not be completed.';
32
+ const STEP_IDS = new Set(['install', 'web_restart', 'ready', 'gateway_wait', 'gateway_restart', 'agent_ready']);
33
+ /** Phases in which an update the user started presents its Updating dialog to every tab that can see it. */
34
+ const PRESENTING = new Set(['applying', 'restarting', 'verifying']);
35
+ const TERMINAL_FAILURE = new Set(['failed', 'blocked', 'unknown']);
36
+ /** TAL-953: the waiting gateway restart's message, with the running task count once one is known. */
37
+ const gatewayWaitingMessage = (tasks) => tasks > 0
38
+ ? `Waiting for ${String(tasks)} running gateway task${tasks === 1 ? '' : 's'} to finish before restarting the gateway.`
39
+ : 'Waiting for running gateway tasks to finish before restarting the gateway.';
27
40
  const wording = (target, phase) => {
28
41
  const name = target === 'webui' ? 'Talaria Web' : 'Hermes Agent';
29
42
  const messages = {
30
43
  applying: `Installing the selected ${name} update.`,
31
44
  awaiting_confirmation: 'This Hermes Agent revision needs confirmation before it can be installed.',
32
- restarting: target === 'webui' ? 'The update is installed. Talaria Web is restarting.' : 'The update is installed. Hermes Agent is restarting.',
45
+ waiting_for_idle: gatewayWaitingMessage(0),
46
+ restarting: target === 'webui' ? 'The update is installed. Talaria Web is restarting.' : 'The update is installed. The messaging gateway is restarting.',
47
+ verifying: 'The update is installed. Checking that Hermes Agent responds.',
33
48
  succeeded: `${name} was updated successfully.`,
34
49
  blocked: 'The update is waiting for active work to finish.',
35
- failed: 'The update could not be completed. Open System settings for details.',
50
+ failed: FAILED_MESSAGE,
36
51
  unknown: 'The connection closed before completion could be verified. Check the installed version before trying again.',
37
52
  };
38
53
  return { title: `${name} update`, message: messages[phase] };
39
54
  };
55
+ const RELOAD_IN_DIALOG = { id: WEB_REFRESH_ACTION, label: 'Reload', style: 'primary', acknowledges: false };
56
+ /** Release tags name versions as `web-v1.2.3`; the dialog shows `1.2.3`. */
57
+ const shownVersion = (version) => version ? ` ${version.replace(/^web-(?:exp-)?v/, '')}` : '';
58
+ /** TAL-1138: the step an update is on, or null once it succeeded. `webPending`: its Talaria Web restart has not happened yet. */
59
+ function currentStep(row, webPending) {
60
+ if (TERMINAL_FAILURE.has(row.phase))
61
+ return row.failed_step ?? 'install';
62
+ if (row.phase === 'succeeded')
63
+ return null;
64
+ if (row.phase === 'restarting')
65
+ return row.target === 'webui' ? 'web_restart' : 'gateway_restart';
66
+ if (row.phase === 'waiting_for_idle')
67
+ return webPending ? 'web_restart' : 'gateway_wait';
68
+ if (row.phase === 'verifying')
69
+ return webPending ? 'web_restart' : 'agent_ready';
70
+ return 'install';
71
+ }
72
+ /**
73
+ * TAL-1138: the update's steps as the Updating dialog lists them. Web: Installing, Restarting Talaria Web, Ready.
74
+ * Agent: Installing, Restarting Talaria Web, Waiting for gateway tasks (only once the gateway was busy), Restarting
75
+ * gateway, Agent responding. An update that finished without restarting anything lists only the steps it ran.
76
+ */
77
+ function updateSteps(row, webPending) {
78
+ if (row.kind !== 'update' || !row.target)
79
+ return [];
80
+ const current = currentStep(row, webPending);
81
+ const undecided = ['applying', 'awaiting_confirmation'].includes(row.phase);
82
+ // Each restart step needs its own evidence: a scheduled Web restart, or a gateway restart under way or recorded.
83
+ const webRestarts = undecided || row.web_restart_boot !== null || current === 'web_restart';
84
+ const gatewayRestarts = undecided || ['waiting_for_idle', 'restarting'].includes(row.phase) || row.gateway_baseline !== null || current === 'gateway_wait' || current === 'gateway_restart';
85
+ const succeeded = row.phase === 'succeeded';
86
+ const tasks = row.gateway_tasks ?? 0;
87
+ const plan = row.target === 'webui'
88
+ ? [['install', 'Installing'], ...(webRestarts ? [['web_restart', 'Restarting Talaria Web']] : []), ['ready', succeeded ? `Talaria Web${shownVersion(row.verified_version)} is ready` : 'Ready']]
89
+ : [
90
+ ['install', 'Installing'],
91
+ ...(webRestarts ? [['web_restart', 'Restarting Talaria Web']] : []),
92
+ ...(row.gateway_tasks !== null || current === 'gateway_wait' ? [['gateway_wait', tasks > 0 ? `Waiting for ${String(tasks)} gateway task${tasks === 1 ? '' : 's'}` : 'Waiting for gateway tasks']] : []),
93
+ ...(gatewayRestarts ? [['gateway_restart', 'Restarting gateway']] : []),
94
+ ['agent_ready', succeeded ? `Hermes Agent${shownVersion(row.verified_version)} is running` : 'Agent responding'],
95
+ ];
96
+ const at = current === null ? plan.length : plan.findIndex(([id]) => id === current);
97
+ return plan.map(([id, label], index) => ({ id, label, state: index < at ? 'done' : index > at ? 'pending' : TERMINAL_FAILURE.has(row.phase) ? 'failed' : 'active' }));
98
+ }
40
99
  export class UpdateNotificationStore {
100
+ documents;
41
101
  now;
42
- rows;
43
- file;
102
+ rows = [];
103
+ revision = null;
104
+ writes = Promise.resolve();
44
105
  /** Last check-in per tab refresh notice; kept in memory so polling never rewrites the store. */
45
106
  tabSeen = new Map();
46
107
  loadedAt;
47
- constructor(stateDir, now = () => new Date()) {
108
+ /** This server process; an update whose Web restart another process scheduled has restarted Web. */
109
+ boot = randomUUID();
110
+ constructor(documents, now = () => new Date()) {
111
+ this.documents = documents;
48
112
  this.now = now;
49
- this.file = resolve(stateDir, 'update-notifications.json');
50
- this.rows = this.load();
51
113
  this.loadedAt = this.now().valueOf();
52
114
  }
115
+ async initialize() { this.rows = await this.load(); }
116
+ /** Startup warnings outlive any chat or Agent. Repeats retain read/dismissal state until the full text changes. */
117
+ async agentWarning(scope, key, notice) {
118
+ const row = this.rows.find((entry) => entry.kind === 'agent_warning' && entry.notice_key === key && entry.owner === scope.owner && entry.profile === scope.profile);
119
+ if (!notice) {
120
+ if (!row)
121
+ return;
122
+ this.rows = this.rows.filter((entry) => entry !== row);
123
+ return this.save();
124
+ }
125
+ const message = safeText(notice.text, '', 500);
126
+ if (!message)
127
+ return;
128
+ const textHash = createHash('sha256').update(notice.text).digest('hex');
129
+ const severity = notice.level === 'error' ? 'critical' : notice.level === 'warn' ? 'warning' : 'info';
130
+ if (!row) {
131
+ await this.createRow(scope, { kind: 'agent_warning', target: 'agent', phase: 'active', severity, persistent: true, title: 'Agent warning', message }, { notice_key: key, notice_text_hash: textHash });
132
+ return;
133
+ }
134
+ row.updated_at = this.now().toISOString();
135
+ if (row.notice_text_hash !== textHash) {
136
+ row.message = message;
137
+ row.severity = severity;
138
+ row.notice_text_hash = textHash;
139
+ row.read_at = null;
140
+ row.dismissed_at = null;
141
+ }
142
+ await this.save();
143
+ }
53
144
  /**
54
145
  * Compare the frontend build a tab loaded with the build this server now serves. A mismatch keeps one
55
146
  * persistent, tab-scoped refresh notice per tab; a match resolves and removes it. Unknown builds change nothing.
56
147
  */
57
- syncTabBuild(scope, loadedBuild, currentBuild) {
58
- this.pruneClosedTabs();
148
+ async syncTabBuild(scope, loadedBuild, currentBuild) {
149
+ await this.pruneClosedTabs();
59
150
  const tab = scope.tab && TAB_ID.test(scope.tab) ? scope.tab : null;
60
151
  const loaded = loadedBuild && FRONTEND_BUILD.test(loadedBuild) ? loadedBuild : null;
61
152
  const current = currentBuild && FRONTEND_BUILD.test(currentBuild) ? currentBuild : null;
@@ -67,11 +158,20 @@ export class UpdateNotificationStore {
67
158
  if (existing) {
68
159
  this.rows = this.rows.filter((row) => row !== existing);
69
160
  this.tabSeen.delete(existing.id);
70
- this.save();
161
+ await this.save();
71
162
  }
72
163
  return state;
73
164
  }
74
165
  state.refresh_required = true;
166
+ // TAL-1138: the Web update this tab started offers Reload in its own Updating dialog instead.
167
+ if (this.rows.some((row) => this.isVisible(row, scope) && this.reloadsInDialog(row, tab, true))) {
168
+ if (existing) {
169
+ this.rows = this.rows.filter((row) => row !== existing);
170
+ this.tabSeen.delete(existing.id);
171
+ await this.save();
172
+ }
173
+ return state;
174
+ }
75
175
  const stamp = this.now().toISOString();
76
176
  if (existing) {
77
177
  this.tabSeen.set(existing.id, this.now().valueOf());
@@ -79,7 +179,7 @@ export class UpdateNotificationStore {
79
179
  existing.expected_identity = current;
80
180
  existing.updated_at = stamp;
81
181
  existing.read_at = null;
82
- this.save();
182
+ await this.save();
83
183
  }
84
184
  state.notification_id = existing.id;
85
185
  return state;
@@ -93,35 +193,126 @@ export class UpdateNotificationStore {
93
193
  created_at: stamp, updated_at: stamp, read_at: null, acknowledged_at: null,
94
194
  acknowledged_action_id: null, verified_revision: null, verified_version: null, detail: null,
95
195
  performed_action_ids: [], dismissed_at: null, expected_identity: current, tab_id: tab, watchers: [],
196
+ web_restart_boot: null, gateway_tasks: null, gateway_baseline: null, failed_step: null,
96
197
  };
97
198
  if (!this.hasProtectedCapacity(row))
98
199
  return state;
99
200
  this.rows.push(row);
100
201
  this.tabSeen.set(row.id, this.now().valueOf());
101
- this.save();
202
+ await this.save();
102
203
  state.notification_id = row.id;
103
204
  return state;
104
205
  }
105
- begin(scope, target) {
206
+ async begin(scope, target) {
106
207
  const text = wording(target, 'applying');
107
- const created = this.create(scope, {
208
+ const created = (await this.create(scope, {
108
209
  kind: 'update', target, phase: 'applying', ...text,
109
210
  destination: { key: 'settings.system', label: 'Open System settings' },
110
211
  visibility: 'server',
111
- });
112
- this.watch(scope, created.id);
212
+ }));
213
+ await this.watch(scope, created.id);
113
214
  return created;
114
215
  }
216
+ /** A retained notice still needs loaded-readiness verification after native debt clears. */
217
+ hasPendingAgentRecovery() {
218
+ const row = this.rows.findLast((entry) => entry.kind === 'agent_recovery');
219
+ return row !== undefined && row.phase !== 'succeeded';
220
+ }
221
+ /** Recovery has its own row, so it can never rewrite the initiating update's failed outcome. */
222
+ async agentRecovery(state) {
223
+ if (state.phase === 'idle')
224
+ return;
225
+ const phase = state.phase === 'complete' ? 'succeeded' : state.phase === 'running' ? 'applying' : 'blocked';
226
+ const title = 'Hermes Agent recovery';
227
+ const message = state.phase === 'complete' ? 'Hermes Agent is usable again. The original update result is unchanged.'
228
+ : state.phase === 'running' ? 'Recovering Hermes Agent after an interrupted update.'
229
+ : state.phase === 'waiting' ? 'Hermes Agent recovery will retry automatically.' : 'Hermes Agent recovery needs attention.';
230
+ const row = this.rows.findLast((entry) => entry.kind === 'agent_recovery');
231
+ if (!row) {
232
+ await this.create({ owner: '*', profile: 'default', serverOwner: true }, {
233
+ kind: 'agent_recovery', target: 'agent', phase, title, message, visibility: 'server',
234
+ severity: state.phase === 'blocked' ? 'warning' : 'info',
235
+ });
236
+ return this.agentRecovery(state);
237
+ }
238
+ if (row.phase === phase && row.message === message && row.detail === safeDetail(state.detail))
239
+ return;
240
+ row.phase = phase;
241
+ row.title = title;
242
+ row.message = message;
243
+ row.detail = safeDetail(state.detail);
244
+ row.severity = state.phase === 'blocked' ? 'warning' : 'info';
245
+ row.updated_at = this.now().toISOString();
246
+ row.dismissed_at = null;
247
+ row.read_at = null;
248
+ await this.save();
249
+ }
250
+ /**
251
+ * A question the server asks about one profile (TAL-1274), seen by every server owner while that profile is active. Its
252
+ * open row is refreshed in place; null withdraws it once nothing asks it any more. An answered row stays as history.
253
+ */
254
+ async profileQuestion(profile, kind, input) {
255
+ const open = this.rows.find((row) => row.kind === kind && row.owner === '*' && row.profile === profile && row.acknowledged_at === null);
256
+ if (!input) {
257
+ if (!open)
258
+ return;
259
+ this.rows = this.rows.filter((row) => row !== open);
260
+ return this.save();
261
+ }
262
+ if (!open) {
263
+ await this.create({ owner: '*', profile, serverOwner: true }, { ...input, kind, requiresAcknowledgement: true });
264
+ return;
265
+ }
266
+ const message = safeText(input.message, '', 500);
267
+ const detail = safeDetail(input.detail);
268
+ if (!message || (open.message === message && open.detail === detail))
269
+ return;
270
+ open.message = message;
271
+ open.detail = detail;
272
+ open.updated_at = this.now().toISOString();
273
+ open.read_at = null;
274
+ await this.save();
275
+ }
276
+ /** Drop all profile-scoped state, including dismissed warning identities, when a profile is deleted. */
277
+ async forgetProfile(profile) {
278
+ const kept = this.rows.filter((row) => !(row.visibility === 'profile' && row.profile === profile));
279
+ if (kept.length === this.rows.length)
280
+ return;
281
+ this.rows = kept;
282
+ await this.save();
283
+ }
284
+ /** The open question `id` of `kind` this scope sees, or null. */
285
+ openQuestion(scope, id, kind) {
286
+ const row = this.visible(scope, id);
287
+ return row?.kind === kind && row.owner === '*' && row.acknowledged_at === null ? this.publish(row, scope.tab) : null;
288
+ }
289
+ /** Record the answer to an open question: its outcome replaces the question, which then leaves only Dismiss. */
290
+ async answerQuestion(scope, id, kind, actionId, outcome) {
291
+ const row = this.visible(scope, id);
292
+ if (row?.kind !== kind || row.owner !== '*' || row.acknowledged_at !== null || !row.actions.some((action) => action.id === actionId))
293
+ return null;
294
+ const stamp = this.now().toISOString();
295
+ Object.assign(row, {
296
+ phase: 'succeeded', severity: 'info', message: safeText(outcome, row.message, 500), detail: null, actions: [],
297
+ updated_at: stamp, read_at: row.read_at ?? stamp, acknowledged_at: stamp, acknowledged_action_id: actionId,
298
+ performed_action_ids: [...row.performed_action_ids, actionId],
299
+ });
300
+ await this.save();
301
+ return this.publish(row, scope.tab);
302
+ }
115
303
  /** Let the requesting tab follow an update operation it started or rejoined. Watchers live as long as the record; only a server owner's Update click adds one. */
116
- watch(scope, id) {
304
+ async watch(scope, id) {
117
305
  const tab = scope.tab && TAB_ID.test(scope.tab) ? scope.tab : null;
118
306
  const row = this.rows.find((entry) => entry.id === id && entry.kind === 'update' && this.isVisible(entry, scope));
119
307
  if (!tab || !row)
120
308
  return;
121
309
  row.watchers = [...row.watchers.filter((watcher) => watcher.tab !== tab), { tab, at: this.now().toISOString() }];
122
- this.save();
310
+ await this.save();
311
+ }
312
+ async create(scope, input) {
313
+ return this.publish(await this.createRow(scope, input));
123
314
  }
124
- create(scope, input) {
315
+ async createRow(scope, input, notice = {}) {
125
316
  const kind = safeToken(input.kind, '');
126
317
  const phase = safeToken(input.phase, '');
127
318
  const title = safeText(input.title, '', 160);
@@ -134,60 +325,117 @@ export class UpdateNotificationStore {
134
325
  const stamp = this.now().toISOString();
135
326
  const row = {
136
327
  id: randomUUID(), owner: scope.owner.slice(0, 256), profile: scope.profile.slice(0, 64), visibility: input.visibility ?? 'profile',
137
- kind, target: input.target ?? null, phase, severity: input.severity ?? 'info',
328
+ ...notice, kind, target: input.target ?? null, phase, severity: input.severity ?? 'info',
138
329
  persistent: input.requiresAcknowledgement === true || input.persistent === true,
139
330
  requires_acknowledgement: input.requiresAcknowledgement === true, actions,
140
331
  destination: safeDestination(input.destination), title, message,
141
332
  created_at: stamp, updated_at: stamp, read_at: null, acknowledged_at: null,
142
- acknowledged_action_id: null, verified_revision: null, verified_version: null, detail: null,
333
+ acknowledged_action_id: null, verified_revision: null, verified_version: null, detail: safeDetail(input.detail),
143
334
  performed_action_ids: [], dismissed_at: null, expected_identity: null, tab_id: null, watchers: [],
335
+ web_restart_boot: null, gateway_tasks: null, gateway_baseline: null, failed_step: null,
144
336
  };
145
337
  if (!this.hasProtectedCapacity(row))
146
338
  throw new Error('Update notification protected capacity reached');
147
339
  this.rows.push(row);
148
- this.save();
149
- return copy(row);
340
+ await this.save();
341
+ return row;
150
342
  }
151
343
  activeUpdate(scope, target) {
152
- const row = [...this.rows].reverse().find((entry) => this.isVisible(entry, scope) && entry.kind === 'update' && entry.target === target && ['applying', 'awaiting_confirmation', 'restarting'].includes(entry.phase));
153
- return row ? copy(row) : null;
344
+ const row = [...this.rows].reverse().find((entry) => this.isVisible(entry, scope) && entry.kind === 'update' && entry.target === target && ['applying', 'awaiting_confirmation', 'restarting', 'verifying'].includes(entry.phase));
345
+ return row ? this.publish(row) : null;
154
346
  }
155
- transition(id, phase, expectedIdentity, verifiedIdentity, detail) {
347
+ async transition(id, phase, expectedIdentity, verifiedIdentity, detail) {
156
348
  const row = this.rows.find((entry) => entry.id === id);
157
349
  if (!row)
158
350
  return null;
159
351
  const phaseChanged = row.phase !== phase;
352
+ // TAL-1138: a failure keeps the step it stopped at, so the dialog marks that step failed.
353
+ if (!TERMINAL_FAILURE.has(phase))
354
+ row.failed_step = null;
355
+ else if (!TERMINAL_FAILURE.has(row.phase))
356
+ row.failed_step = currentStep(row, this.webPending(row)) ?? 'install';
357
+ if (row.kind === 'update' && row.target === 'webui' && phase === 'restarting')
358
+ row.web_restart_boot = this.boot;
160
359
  row.phase = phase;
161
360
  if (row.target)
162
361
  Object.assign(row, wording(row.target, phase));
362
+ if (phase === 'awaiting_confirmation')
363
+ row.message = safeText(detail, row.message, 500);
163
364
  row.updated_at = this.now().toISOString();
164
365
  if (phaseChanged)
165
366
  row.read_at = null;
166
367
  row.expected_identity = expectedIdentity?.trim().slice(0, 160) || null;
167
- row.detail = phase === 'failed' || phase === 'blocked' || phase === 'succeeded' ? safeDetail(detail) : null;
368
+ row.detail = phase === 'applying' || phase === 'failed' || phase === 'blocked' || phase === 'succeeded' || phase === 'waiting_for_idle' || phase === 'verifying' ? safeDetail(detail) : null;
369
+ // The gateway restart is server-wide: every server owner sees the wait and can restart now, and a later update joins it.
370
+ if (row.kind === 'update' && phase === 'waiting_for_idle' && row.visibility === 'server')
371
+ row.owner = '*';
372
+ // Only a waiting gateway restart offers an action; entering the wait offers it afresh.
373
+ if (row.kind === 'update') {
374
+ row.actions = phase === 'waiting_for_idle' ? [GATEWAY_RESTART_NOW_ACTION] : [];
375
+ row.performed_action_ids = row.performed_action_ids.filter((action) => action !== GATEWAY_RESTART_NOW);
376
+ }
168
377
  if (verifiedIdentity) {
169
378
  row.verified_revision = typeof verifiedIdentity.revision === 'string' && REVISION.test(verifiedIdentity.revision) ? verifiedIdentity.revision : null;
170
379
  row.verified_version = safeText(verifiedIdentity.version, '', 80) || null;
171
380
  }
172
- this.save();
173
- return copy(row);
381
+ await this.save();
382
+ return this.publish(row);
383
+ }
384
+ /** TAL-953: update the waiting gateway restart's message as its running task count changes. */
385
+ async gatewayWaiting(id, tasks) {
386
+ const row = this.rows.find((entry) => entry.id === id && entry.kind === 'update' && entry.phase === 'waiting_for_idle');
387
+ const message = gatewayWaitingMessage(tasks);
388
+ const counted = tasks > 0 ? tasks : row?.gateway_tasks ?? null;
389
+ if (!row || (row.message === message && row.gateway_tasks === counted))
390
+ return;
391
+ row.message = message;
392
+ row.gateway_tasks = counted;
393
+ row.updated_at = this.now().toISOString();
394
+ await this.save();
395
+ }
396
+ /** TAL-1138: this Agent update scheduled a Talaria Web restart; its gateway steps follow the restarted server. */
397
+ async markWebRestart(id) {
398
+ const row = this.rows.find((entry) => entry.id === id && entry.kind === 'update');
399
+ if (!row || row.web_restart_boot === this.boot)
400
+ return;
401
+ row.web_restart_boot = this.boot;
402
+ row.updated_at = this.now().toISOString();
403
+ await this.save();
404
+ }
405
+ /** TAL-1138: the live gateway processes a restart must replace before the update's check can pass. */
406
+ async recordGatewayBaseline(id, baseline) {
407
+ const row = this.rows.find((entry) => entry.id === id && entry.kind === 'update');
408
+ if (!row)
409
+ return;
410
+ row.gateway_baseline = baseline.slice(0, 8).map((entry) => ({ ...entry }));
411
+ await this.save();
174
412
  }
175
- list(scope) {
176
- this.pruneClosedTabs();
413
+ /**
414
+ * TAL-953: gateway restarts still waiting for idle, and (TAL-1138) restarted gateways still being checked, newest
415
+ * first, with the profile each update ran under, so a restarted server resumes them.
416
+ */
417
+ pendingGatewayRestarts() {
418
+ return this.rows.filter((row) => row.kind === 'update' && (row.phase === 'waiting_for_idle' || row.phase === 'verifying'))
419
+ .sort((a, b) => b.created_at.localeCompare(a.created_at))
420
+ .map((row) => ({ id: row.id, profile: row.profile, detail: row.detail, phase: row.phase, baseline: row.gateway_baseline }));
421
+ }
422
+ /** `stale`: the requesting tab runs an older frontend build than the server serves (`syncTabBuild`'s comparison). */
423
+ async list(scope, stale = false) {
424
+ await this.pruneClosedTabs();
177
425
  const scoped = this.rows.filter((row) => this.isVisible(row, scope) && row.dismissed_at === null);
178
426
  const ordered = scoped.sort((a, b) => b.updated_at.localeCompare(a.updated_at));
179
427
  const protectedRows = ordered.filter(isProtected);
180
428
  const visible = [...protectedRows, ...ordered.filter((row) => !isProtected(row)).slice(0, Math.max(0, PER_SCOPE_LIMIT - protectedRows.length))]
181
429
  .sort((a, b) => b.updated_at.localeCompare(a.updated_at));
182
- const notifications = visible.map(copy);
183
- const clearableCount = scoped.filter(isDismissible).length;
184
430
  const tab = scope.tab && TAB_ID.test(scope.tab) ? scope.tab : null;
431
+ const notifications = visible.map((row) => this.publish(row, tab, stale));
432
+ const clearableCount = scoped.filter(isDismissible).length;
185
433
  const joinedAt = (row) => row.watchers.find((watcher) => watcher.tab === tab)?.at ?? '';
186
434
  const tabUpdate = tab ? this.rows.filter((row) => row.kind === 'update' && joinedAt(row) !== '' && this.isVisible(row, scope))
187
435
  .sort((a, b) => joinedAt(b).localeCompare(joinedAt(a)) || b.created_at.localeCompare(a.created_at))[0] : undefined;
188
- return { scope_id: updateNotificationScopeId(scope), notifications, tab_update: tabUpdate ? copy(tabUpdate) : null, tab_joined_at: tabUpdate ? joinedAt(tabUpdate) : null, unread_count: visible.filter((row) => row.read_at === null).length, clearable_count: clearableCount, can_clear: clearableCount > 0 };
436
+ return { scope_id: updateNotificationScopeId(scope), notifications, tab_update: tabUpdate ? this.publish(tabUpdate, tab, stale) : null, tab_joined_at: tabUpdate ? joinedAt(tabUpdate) : null, unread_count: visible.filter((row) => row.read_at === null).length, clearable_count: clearableCount, can_clear: clearableCount > 0 };
189
437
  }
190
- clear(scope) {
438
+ async clear(scope, stale = false) {
191
439
  const stamp = this.now().toISOString();
192
440
  let changed = false;
193
441
  for (const row of this.rows) {
@@ -197,40 +445,41 @@ export class UpdateNotificationStore {
197
445
  changed = true;
198
446
  }
199
447
  if (changed)
200
- this.save();
201
- return this.list(scope);
448
+ (await this.save());
449
+ return (await this.list(scope, stale));
202
450
  }
203
- read(scope, id) {
451
+ async read(scope, id) {
204
452
  const row = this.visible(scope, id);
205
453
  if (!row)
206
454
  return null;
207
455
  if (row.read_at === null) {
208
456
  row.read_at = this.now().toISOString();
209
- this.save();
457
+ (await this.save());
210
458
  }
211
- return copy(row);
459
+ return this.publish(row);
212
460
  }
213
- dismiss(scope, id) {
461
+ async dismiss(scope, id) {
214
462
  const row = this.rows.find((entry) => entry.id === id && this.isVisible(entry, scope));
215
463
  if (!row)
216
464
  return 'not_found';
217
- if (row.requires_acknowledgement && row.acknowledged_at === null)
465
+ if (!isDismissible(row))
218
466
  return 'acknowledgement_required';
219
467
  if (row.dismissed_at === null) {
220
468
  const stamp = this.now().toISOString();
221
469
  row.dismissed_at = stamp;
222
470
  row.read_at ??= stamp;
223
- this.save();
471
+ (await this.save());
224
472
  }
225
473
  return 'dismissed';
226
474
  }
227
- action(scope, id, actionId) {
475
+ async action(scope, id, actionId) {
228
476
  const row = this.visible(scope, id);
229
- const action = row?.actions.find((candidate) => candidate.id === actionId);
477
+ // A Reload in the Updating dialog is offered only while the tab is stale; the action itself never depends on it.
478
+ const action = row ? this.publish(row, scope.tab, true).actions.find((candidate) => candidate.id === actionId) : undefined;
230
479
  if (!row || !action)
231
480
  return null;
232
481
  if (row.performed_action_ids.includes(action.id))
233
- return copy(row);
482
+ return this.publish(row, scope.tab, true);
234
483
  const stamp = this.now().toISOString();
235
484
  row.updated_at = stamp;
236
485
  row.read_at ??= stamp;
@@ -239,15 +488,15 @@ export class UpdateNotificationStore {
239
488
  row.acknowledged_at = stamp;
240
489
  row.acknowledged_action_id = action.id;
241
490
  }
242
- this.save();
243
- return copy(row);
491
+ await this.save();
492
+ return this.publish(row, scope.tab, true);
244
493
  }
245
- cancelUpdate(scope, id) {
494
+ async cancelUpdate(scope, id) {
246
495
  const row = this.rows.find((entry) => entry.id === id && this.isVisible(entry, scope) && entry.kind === 'update');
247
496
  if (!row)
248
497
  return null;
249
498
  if (row.phase === 'blocked' && row.message === 'The update was cancelled before installation.')
250
- return copy(row);
499
+ return this.publish(row);
251
500
  if (row.phase !== 'awaiting_confirmation')
252
501
  return null;
253
502
  const stamp = this.now().toISOString();
@@ -255,15 +504,25 @@ export class UpdateNotificationStore {
255
504
  row.message = 'The update was cancelled before installation.';
256
505
  row.updated_at = stamp;
257
506
  row.read_at ??= stamp;
258
- this.save();
259
- return copy(row);
507
+ await this.save();
508
+ return this.publish(row);
260
509
  }
261
- reconcileInterruptedUpdates(currentWebIdentity, currentWebVersion = null) {
510
+ async reconcileInterruptedUpdates(currentWebIdentity, currentWebVersion = null) {
262
511
  let changed = false;
263
512
  for (const row of this.rows) {
513
+ if (row.kind === 'agent_recovery' && row.phase === 'applying') {
514
+ row.phase = 'unknown';
515
+ row.message = 'Agent recovery was interrupted. Current readiness has not been verified.';
516
+ row.severity = 'warning';
517
+ row.updated_at = this.now().toISOString();
518
+ row.read_at = null;
519
+ changed = true;
520
+ continue;
521
+ }
264
522
  if (row.kind !== 'update' || (row.target !== 'webui' && row.target !== 'agent') || !['applying', 'restarting'].includes(row.phase))
265
523
  continue;
266
524
  const phase = row.target === 'webui' && row.phase === 'restarting' && currentWebIdentity && REVISION.test(currentWebIdentity) && row.expected_identity === currentWebIdentity ? 'succeeded' : 'unknown';
525
+ row.failed_step = phase === 'unknown' ? currentStep(row, false) ?? 'install' : null;
267
526
  row.phase = phase;
268
527
  Object.assign(row, wording(row.target, phase));
269
528
  row.updated_at = this.now().toISOString();
@@ -275,7 +534,44 @@ export class UpdateNotificationStore {
275
534
  changed = true;
276
535
  }
277
536
  if (changed)
278
- this.save();
537
+ (await this.save());
538
+ }
539
+ /** TAL-1138: this update's Talaria Web restart is scheduled but has not happened yet. */
540
+ webPending(row) { return row.web_restart_boot === this.boot; }
541
+ /**
542
+ * TAL-1138: a Web update that `tab` started finished while the tab still runs the old build. The tab's Updating
543
+ * dialog offers Reload in place of the separate refresh notice; a later Web update takes that over.
544
+ */
545
+ reloadsInDialog(row, tab, stale) {
546
+ if (!stale || !tab || row.kind !== 'update' || row.target !== 'webui' || row.phase !== 'succeeded' || !row.watchers.some((watcher) => watcher.tab === tab))
547
+ return false;
548
+ return !this.rows.some((other) => other !== row && other.kind === 'update' && other.target === 'webui' && other.created_at > row.created_at);
549
+ }
550
+ /** The record as clients see it; `tab` and `stale` (its loaded build is not the one served) decide the Reload in its dialog. */
551
+ publish(row, tab = null, stale = false) {
552
+ const webPending = this.webPending(row);
553
+ const reload = this.reloadsInDialog(row, tab, stale);
554
+ const presents = reload || (row.kind === 'update' && row.watchers.length > 0 && (PRESENTING.has(row.phase) || (row.phase === 'waiting_for_idle' && webPending)));
555
+ return {
556
+ id: row.id, kind: row.kind, target: row.target, phase: row.phase, severity: row.severity,
557
+ persistent: row.persistent, requires_acknowledgement: row.requires_acknowledgement,
558
+ // The Restart now action waits for the restarted Web server, which runs the gateway restart.
559
+ actions: reload ? [RELOAD_IN_DIALOG] : row.kind === 'update' && row.phase === 'waiting_for_idle' && webPending ? [] : row.actions,
560
+ destination: row.kind === 'update' && row.phase === 'failed' && row.destination?.key === 'settings.system' ? null : row.destination,
561
+ title: row.title,
562
+ // Old persisted failures still carry the obsolete guidance; correct only that generic copy.
563
+ message: row.kind === 'update' && row.phase === 'failed' && row.message === `${FAILED_MESSAGE} Open System settings for details.` ? FAILED_MESSAGE : row.message,
564
+ created_at: row.created_at, updated_at: row.updated_at, read_at: row.read_at,
565
+ acknowledged_at: row.acknowledged_at, acknowledged_action_id: row.acknowledged_action_id,
566
+ verified_revision: row.verified_revision, verified_version: row.verified_version, detail: row.detail,
567
+ unread: row.read_at === null,
568
+ active: ['update', 'agent_recovery'].includes(row.kind) && ['applying', 'restarting', 'verifying'].includes(row.phase),
569
+ requires_interaction: row.requires_acknowledgement && row.acknowledged_at === null,
570
+ can_dismiss: isDismissible(row),
571
+ steps: updateSteps(row, webPending),
572
+ presents_dialog: presents,
573
+ dialog_close: presents ? 'none' : row.kind !== 'update' ? 'close' : row.phase === 'waiting_for_idle' ? 'restart_later' : row.phase === 'succeeded' ? 'auto' : 'close',
574
+ };
279
575
  }
280
576
  visible(scope, id) {
281
577
  return this.rows.find((row) => row.id === id && this.isVisible(row, scope) && row.dismissed_at === null) ?? null;
@@ -285,13 +581,15 @@ export class UpdateNotificationStore {
285
581
  return row.tab_id === scope.tab && row.owner === scope.owner && row.profile === scope.profile;
286
582
  if (row.visibility === 'server')
287
583
  return scope.serverOwner === true && (row.owner === scope.owner || row.owner === '*');
584
+ if (row.owner === '*')
585
+ return scope.serverOwner === true && (row.profile === scope.profile || (row.profile === 'default' && scope.rootProfile === true));
288
586
  return row.owner === scope.owner && row.profile === scope.profile;
289
587
  }
290
588
  hasProtectedCapacity(row) {
291
589
  const peers = this.rows.filter((entry) => isProtected(entry) && isTabNotice(entry) === isTabNotice(row));
292
590
  return peers.filter((entry) => retentionBucket(entry) === retentionBucket(row)).length < PER_SCOPE_LIMIT && peers.length < GLOBAL_LIMIT;
293
591
  }
294
- pruneClosedTabs() {
592
+ async pruneClosedTabs() {
295
593
  const cutoff = this.now().valueOf() - TAB_TTL_MS;
296
594
  const closed = this.rows.filter((row) => row.tab_id !== null && (this.tabSeen.get(row.id) ?? this.loadedAt) < cutoff);
297
595
  if (closed.length === 0)
@@ -299,13 +597,13 @@ export class UpdateNotificationStore {
299
597
  for (const row of closed)
300
598
  this.tabSeen.delete(row.id);
301
599
  this.rows = this.rows.filter((row) => !closed.includes(row));
302
- this.save();
600
+ await this.save();
303
601
  }
304
- load() {
305
- if (!existsSync(this.file))
306
- return [];
602
+ async load() {
307
603
  try {
308
- const parsed = JSON.parse(readFileSync(this.file, 'utf8'));
604
+ const record = await readDocument(this.documents, 'update-notifications', 'update-notifications', { replaceInvalid: true });
605
+ this.revision = record?.revision ?? null;
606
+ const parsed = record?.value;
309
607
  if (!Array.isArray(parsed))
310
608
  return [];
311
609
  return parsed.flatMap((value) => {
@@ -319,9 +617,11 @@ export class UpdateNotificationStore {
319
617
  return [];
320
618
  const kind = safeToken(row.kind, 'update');
321
619
  const target = row.target === 'webui' || row.target === 'agent' ? row.target : null;
322
- const phase = safeToken(row.phase, 'unknown');
620
+ // TAL-1138: `verifying` is stored as Stable's `restarting` plus a flag Stable ignores.
621
+ const phase = row.phase === 'restarting' && row.verifying === true ? 'verifying' : safeToken(row.phase, 'unknown');
323
622
  const fallback = target && PHASES.has(phase) ? wording(target, phase) : { title: 'Server notification', message: 'This server needs your attention.' };
324
623
  return [{
624
+ ...(typeof row.notice_key === 'string' ? { notice_key: row.notice_key, notice_text_hash: typeof row.notice_text_hash === 'string' ? row.notice_text_hash : '' } : {}),
325
625
  id: row.id, owner: row.owner.slice(0, 256), profile: row.profile.slice(0, 64), visibility: row.visibility === 'profile' ? 'profile' : 'server', kind, target, phase,
326
626
  severity: row.severity === 'critical' || row.severity === 'warning' ? row.severity : 'info',
327
627
  persistent: row.persistent === true,
@@ -341,6 +641,10 @@ export class UpdateNotificationStore {
341
641
  expected_identity: typeof row.expected_identity === 'string' ? row.expected_identity.slice(0, 160) : null,
342
642
  tab_id: typeof row.tab_id === 'string' ? row.tab_id : null,
343
643
  watchers: Array.isArray(row.watchers) ? row.watchers.flatMap((watcher) => isRecord(watcher) && typeof watcher.tab === 'string' && TAB_ID.test(watcher.tab) && typeof watcher.at === 'string' ? [{ tab: watcher.tab, at: watcher.at }] : []) : [],
644
+ web_restart_boot: typeof row.web_restart_boot === 'string' ? row.web_restart_boot.slice(0, 64) : null,
645
+ gateway_tasks: typeof row.gateway_tasks === 'number' && Number.isInteger(row.gateway_tasks) && row.gateway_tasks > 0 ? row.gateway_tasks : null,
646
+ gateway_baseline: Array.isArray(row.gateway_baseline) ? row.gateway_baseline.slice(0, 8).flatMap((entry) => isRecord(entry) && typeof entry.dir === 'string' && typeof entry.pid === 'number' && Number.isInteger(entry.pid) && entry.pid > 0 && (entry.start_time === null || typeof entry.start_time === 'number') ? [{ dir: entry.dir, pid: entry.pid, start_time: entry.start_time }] : []) : null,
647
+ failed_step: typeof row.failed_step === 'string' && STEP_IDS.has(row.failed_step) ? row.failed_step : null,
344
648
  }];
345
649
  });
346
650
  }
@@ -349,7 +653,7 @@ export class UpdateNotificationStore {
349
653
  }
350
654
  }
351
655
  /** Tab refresh notices are bounded by `hasProtectedCapacity` and kept apart, so they never evict or block other notifications. */
352
- save() {
656
+ async save() {
353
657
  const tabNotices = this.rows.filter(isTabNotice);
354
658
  const sorted = this.rows.filter((row) => !isTabNotice(row)).sort((a, b) => b.updated_at.localeCompare(a.updated_at));
355
659
  const protectedRows = sorted.filter(isProtected);
@@ -372,8 +676,19 @@ export class UpdateNotificationStore {
372
676
  kept.push(row);
373
677
  }
374
678
  this.rows = [...kept.reverse(), ...tabNotices];
375
- mkdirSync(dirname(this.file), { recursive: true });
376
- atomicWriteSecretJson(this.file, this.rows);
679
+ // TAL-1138 fields are written only once set, so records that never use them keep their stored bytes. A check in
680
+ // progress is stored as `restarting`, which the current Stable release counts as active and reconciles on startup.
681
+ const rows = structuredClone(this.rows).map(({ web_restart_boot, gateway_tasks, gateway_baseline, failed_step, ...row }) => ({
682
+ ...row,
683
+ ...(row.phase === 'verifying' ? { phase: 'restarting', verifying: true } : {}),
684
+ ...(web_restart_boot === null ? {} : { web_restart_boot }),
685
+ ...(gateway_tasks === null ? {} : { gateway_tasks }),
686
+ ...(gateway_baseline === null ? {} : { gateway_baseline }),
687
+ ...(failed_step === null ? {} : { failed_step }),
688
+ }));
689
+ const write = this.writes.catch(() => undefined).then(async () => { this.revision = await this.documents.put('update-notifications', 'update-notifications', rows, this.revision); });
690
+ this.writes = write;
691
+ await write;
377
692
  }
378
693
  }
379
694
  const safeToken = (value, fallback) => typeof value === 'string' && /^[a-z0-9][a-z0-9_-]{0,63}$/.test(value) ? value : fallback;
@@ -400,8 +715,11 @@ const safeDestination = (value) => {
400
715
  return key && label ? { key, label } : null;
401
716
  };
402
717
  const isTabNotice = (row) => row.tab_id !== null;
403
- const isDismissible = (row) => !row.requires_acknowledgement || row.acknowledged_at !== null;
404
- const isProtected = (row) => (row.requires_acknowledgement && row.acknowledged_at === null) || (row.kind === 'update' && ['applying', 'awaiting_confirmation', 'restarting'].includes(row.phase));
718
+ /** A waiting gateway restart carries its Restart now action, so it stays until the restart runs. */
719
+ const isWaitingGatewayRestart = (row) => row.kind === 'update' && row.phase === 'waiting_for_idle';
720
+ const isDismissible = (row) => (!row.requires_acknowledgement || row.acknowledged_at !== null) && !isWaitingGatewayRestart(row);
721
+ /** Warning identities, including dismissed rows, must survive ordinary history pruning. */
722
+ const isProtected = (row) => row.kind === 'agent_warning' || (row.requires_acknowledgement && row.acknowledged_at === null) || (row.kind === 'update' && ['applying', 'awaiting_confirmation', 'waiting_for_idle', 'restarting', 'verifying'].includes(row.phase));
405
723
  const retentionBucket = (row) => `${row.owner}\u0000${row.visibility === 'server' ? '*' : row.profile}`;
406
724
  export const updateNotificationScopeId = (scope) => createHash('sha256').update(`${scope.owner}\u0000${scope.profile}\u0000${scope.serverOwner === true ? 'owner' : 'member'}`).digest('hex').slice(0, 24);
407
725
  //# sourceMappingURL=update-notifications.js.map