@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,4 +1,3 @@
1
- /** Skills, memory, prompts, commands, notes, insights, logs, health, MCP, plugins, updates, diagnostics (Python `api/routes.py` handlers of the same paths). */
2
1
  import { implement } from '@orpc/server';
3
2
  import { createHash } from 'node:crypto';
4
3
  import { join } from 'node:path';
@@ -6,24 +5,34 @@ import { toolsContract } from '@maudecode/talaria-web-contracts';
6
5
  import { HttpError, requireFields } from './router.js';
7
6
  import { requestSessionIdGuard } from './session-visibility.js';
8
7
  import { activeProfileName, ensureTrustedAuthSession, sessionCanManageServer } from '../auth/gate.js';
9
- import { HttpFailure } from '../sessions/service.js';
8
+ import { currentChatReadiness, HttpFailure } from '../sessions/service.js';
10
9
  import { SessionNotFound } from '../sessions/store.js';
11
- import { insightsSessionRows } from '../sessions/state-db.js';
10
+ import { stateDbSessionReadAsync } from '../sessions/state-db.js';
12
11
  import { ConfigUnavailable } from '../config/agent-config.js';
13
12
  import { SidecarError } from '../sidecar/client.js';
14
13
  import { createPrompt, deletePrompt, externalNotesEnabled, loadPrompts, readMemory, writeMemory } from '../tools/memory.js';
15
14
  import { JoplinError, joplinNote, joplinSearch, notesSources } from '../tools/mcp.js';
15
+ import { catalogNames, connectorOperation, connectorsPage, connectorTools, rememberCatalogNames } from '../tools/connectors.js';
16
16
  import { resolveWikiLocation, wikiPages } from '../tools/wiki.js';
17
17
  import { buildInsights } from '../tools/insights.js';
18
- import { commandCatalog } from '../tools/commands.js';
19
- import { agentHealth, applyDashboardConfig, dashboardConfig, dashboardStatus, gatewayStatus, parseDashboardConfig, readLogTail, systemHealth } from '../tools/health.js';
18
+ import { commandCatalog, SESSION_EXEC_COMMANDS } from '../tools/commands.js';
19
+ import { spokenText } from './tools-raw.js';
20
+ import { agentHealth, applyDashboardConfig, dashboardConfig, dashboardStatus, gatewayStatus, parseDashboardConfig, readLogTail, remoteGatewayBaseUrl, systemHealth } from '../tools/health.js';
21
+ import { restartGateway } from '../tools/gateway-restart.js';
20
22
  import { projectOsDashboard } from '../tools/project-os.js';
23
+ import { PluginSettingsInvalid, planPluginSettings, pluginSettingsView, serializePluginSettingsSave } from '../tools/plugin-settings.js';
24
+ import { checkPastedRedirect } from '../tools/plugin-oauth.js';
25
+ import { oauthCall, oauthView } from './settings-router.js';
26
+ import { credentialShadowed, RuntimeCredentialError, writeRuntimeCredential } from '../providers/runtime-env.js';
27
+ import { EnvWriteError, loadEnvFile } from '../providers/env-file.js';
21
28
  import { loadGatewaySessionIdentityMap } from '../sessions/list.js';
22
29
  import { gitBadge } from '../workspace/git.js';
23
30
  import { sanitizeError } from '../workspace/media.js';
24
31
  import { normalizeChannel, updatesCheckView } from '../tools/updates.js';
25
32
  import { pyBool } from '../settings.js';
26
33
  import { str } from '../util.js';
34
+ import { redactString } from '../redact.js';
35
+ import { GATEWAY_RESTART_NOW, updateNotificationOwner } from '../tools/update-notifications.js';
27
36
  const os = implement(toolsContract).$context().use(requestSessionIdGuard);
28
37
  function failure(error) {
29
38
  if (error instanceof HttpError)
@@ -48,6 +57,8 @@ async function run(fn) {
48
57
  }
49
58
  }
50
59
  const home = (ctx) => ctx.deps.profileHome(activeProfileName(ctx));
60
+ /** Profile homes with an `stt.warm` in flight (TAL-916). */
61
+ const warmingHomes = new Set();
51
62
  function runningSidecar(ctx) {
52
63
  const sidecar = ctx.deps.sidecar();
53
64
  if (!sidecar)
@@ -62,92 +73,203 @@ function commandFailure(error, notFound, message) {
62
73
  throw new HttpError(400, error.message);
63
74
  return failure(error);
64
75
  }
76
+ /** TAL-820: several profiles have third-party plugins and one of them loads its plugins into the shared sidecar process. */
77
+ async function pluginIsolationAdvisory(ctx) {
78
+ if (ctx.deps.isolatedProfileMode())
79
+ return false;
80
+ const { profiles } = await runningSidecar(ctx).call('plugins.isolation', { base_home: ctx.deps.profileHome('default') });
81
+ const withPlugins = profiles.filter((profile) => profile.third_party_plugins > 0);
82
+ return withPlugins.length > 1 && withPlugins.some((profile) => profile.isolation === 'in_process');
83
+ }
84
+ /** TAL-806: the active profile's plugins that declare settings; none on an Agent without the settings module. */
85
+ async function pluginSettingsList(ctx) {
86
+ const result = await runningSidecar(ctx).call('plugins.settings', { profile_home: home(ctx) });
87
+ return result.plugins.map((entry) => ({ key: entry.key, fields: pluginSettingsFieldsView(ctx, entry.fields) }));
88
+ }
89
+ /** TAL-1276: each plugin's declared OAuth clients by key; empty on an Agent without plugin OAuth. */
90
+ async function pluginOAuthClients(ctx) {
91
+ const result = await runningSidecar(ctx).call('plugins.oauth_status', { profile_home: home(ctx) });
92
+ return new Map(result.supported ? result.plugins.map((entry) => [entry.key, entry.clients.map((client) => ({ ...client, can_sign_out: client.state !== 'logged_out' }))]) : []);
93
+ }
94
+ const pluginSettingsFieldsView = (ctx, fields) => {
95
+ const rootProfile = ctx.deps.isRootProfile(activeProfileName(ctx));
96
+ return pluginSettingsView(fields, (envVar) => credentialShadowed(ctx.deps.config.env, rootProfile, envVar));
97
+ };
98
+ /** A refusal that proves nothing was written; a timeout or a sidecar exit leaves the outcome unknown. */
99
+ const definitiveRefusal = (error) => error instanceof SidecarError ? ['plugin_settings_managed', 'plugin_settings_changed', 'plugin_not_found'].includes(error.condition) || error.code === -32602
100
+ : error instanceof EnvWriteError ? error.condition !== 'sidecar_unavailable'
101
+ : error instanceof RuntimeCredentialError;
102
+ /** TAL-818: a sidecar `connectors.*` condition as the HTTP status the contract names; the body's `code` is the condition. */
103
+ const CONNECTOR_STATUS = {
104
+ connectors_unavailable: 404, connector_not_found: 404, connection_not_found: 404, operation_not_found: 404,
105
+ connectors_sign_in: 403, connectors_forbidden: 403, policy_invalid: 400, connectors_failed: 502,
106
+ policy_conflict: 409, connectors_org_required: 409, operation_settled: 409, operation_refused: 409,
107
+ };
108
+ async function connectorCall(ctx, method, params) {
109
+ try {
110
+ // A connect waits up to 31 s for its link; every portal request inside a call is bounded at 30 s.
111
+ return await runningSidecar(ctx).call(method, { ...params, profile_home: home(ctx) }, { timeoutMs: 90_000 });
112
+ }
113
+ catch (error) {
114
+ const status = error instanceof SidecarError ? CONNECTOR_STATUS[error.condition] : undefined;
115
+ if (status !== undefined)
116
+ throw new HttpError(status, error.message, { code: error.condition });
117
+ if (error instanceof SidecarError && error.code === -32602)
118
+ throw new HttpError(400, error.message);
119
+ throw error;
120
+ }
121
+ }
122
+ /** The catalog's app names for the active profile: the last page read's, else one catalog read; none when it fails. */
123
+ async function connectorNames(ctx) {
124
+ return catalogNames(home(ctx)) ?? await connectorCall(ctx, 'connectors.catalog', {}).then((r) => rememberCatalogNames(home(ctx), r.connectors), () => ({}));
125
+ }
126
+ /** An operation as the contract shows it, with the apps' catalog names. */
127
+ const operationView = async (ctx, snapshot) => connectorOperation(snapshot, await connectorNames(ctx));
128
+ /** Read failures never create an identity. Auth refusals become a page sign-in state; unreadable rules fail closed. */
129
+ const connectorRead = (ctx, method) => connectorCall(ctx, method, {}).then((value) => ({ value, error: null, signInRequired: false }), (error) => {
130
+ if (error instanceof HttpError && (method === 'connectors.policy.get' || error.data?.code === 'connectors_sign_in')) {
131
+ return { value: null, error: error.message, signInRequired: error.data?.code === 'connectors_sign_in' };
132
+ }
133
+ throw error;
134
+ });
65
135
  const health = (ctx) => agentHealth({ env: ctx.deps.config.env, hermesHome: ctx.deps.config.hermesHome, profileHome: () => home(ctx), fetch: () => ctx.deps.fetch, now: ctx.deps.nowSeconds });
136
+ /**
137
+ * TAL-805: the active profile's gateway mode from sidecar `gateway.mode`; null for a remote gateway. A named profile never
138
+ * borrows the root's health: when the sidecar cannot answer, it reads `stopped`, while the root profile reads null and keeps
139
+ * its health. The root profile's gateway in another container (`health` alive from its fresh runtime status) is invisible
140
+ * to the sidecar's process checks, so it stays `own`.
141
+ */
142
+ async function gatewayMode(ctx, health) {
143
+ if (remoteGatewayBaseUrl(ctx.deps.config.env) !== null)
144
+ return null;
145
+ const sidecar = ctx.deps.sidecar();
146
+ const name = activeProfileName(ctx);
147
+ const isDefault = ctx.deps.isRootProfile(name);
148
+ let mode = null;
149
+ try {
150
+ if (sidecar)
151
+ mode = (await sidecar.call('gateway.mode', { profile_home: home(ctx), name, is_default: isDefault }, { timeoutMs: 10_000 })).gateway_mode;
152
+ }
153
+ catch {
154
+ mode = null;
155
+ }
156
+ if (mode === null)
157
+ return isDefault ? null : 'stopped';
158
+ return mode === 'stopped' && isDefault && health.alive === true ? 'own' : mode;
159
+ }
66
160
  /** Python `_gateway_status_payload` for the active profile. */
67
161
  async function currentGatewayStatus(ctx) {
68
162
  const sessionsPath = join(home(ctx), 'sessions', 'sessions.json');
69
- return gatewayStatus(await health(ctx), loadGatewaySessionIdentityMap(sessionsPath), sessionsPath);
163
+ const probe = await health(ctx);
164
+ return gatewayStatus(probe, loadGatewaySessionIdentityMap(sessionsPath), sessionsPath, await gatewayMode(ctx, probe));
70
165
  }
71
166
  const GATEWAY_ACTION_TIMEOUT_S = 60;
72
- /** Python `_handle_gateway_lifecycle` through sidecar `gateway.control`: 409 busy, 504 timeout, 500 failure; CLI output never leaves the server. */
167
+ /** Python `_handle_gateway_lifecycle` through sidecar `gateway.control`: 409 busy, 504 timeout, 500 failure; only the Agent's first error line (`reason`) leaves the server, never its CLI output (TAL-884). */
73
168
  async function gatewayAction(ctx, action) {
74
169
  const sidecar = ctx.deps.sidecar();
75
170
  if (!sidecar)
76
171
  throw new HttpError(500, 'Hermes Agent sidecar is not running', { ok: false, action });
77
172
  let outcome;
78
173
  try {
79
- outcome = await sidecar.call('gateway.control', { profile_home: home(ctx), action, background_wait_seconds: GATEWAY_ACTION_TIMEOUT_S }, { timeoutMs: 300_000 });
174
+ outcome = await sidecar.call('gateway.control', { profile_home: home(ctx), action, interrupt: true, background_wait_seconds: GATEWAY_ACTION_TIMEOUT_S }, { timeoutMs: 300_000 });
80
175
  }
81
176
  catch (error) {
82
177
  throw new HttpError(500, sanitizeError(error), { ok: false, action });
83
178
  }
179
+ if (outcome.status === 'busy_live_work')
180
+ throw new HttpError(409, outcome.reason || 'The gateway still has live work.', { ok: false, action });
84
181
  if (outcome.status === 'busy')
85
182
  throw new HttpError(409, 'Another gateway action is already in progress; try again shortly.', { ok: false, action });
86
183
  if (outcome.timed_out)
87
184
  throw new HttpError(504, `Gateway ${action} timed out after ${String(GATEWAY_ACTION_TIMEOUT_S)} seconds`, { ok: false, action });
88
- if (outcome.status === 'failed' && outcome.returncode !== undefined)
89
- throw new HttpError(500, `Gateway ${action} failed with exit code ${String(outcome.returncode)}`, { ok: false, action, returncode: outcome.returncode });
185
+ if (outcome.status === 'failed' && outcome.returncode !== undefined) {
186
+ const error = outcome.reason ? `Gateway ${action} failed: ${outcome.reason}` : `Gateway ${action} failed with exit code ${String(outcome.returncode)}`;
187
+ throw new HttpError(500, error, { ok: false, action, returncode: outcome.returncode });
188
+ }
90
189
  if (outcome.status === 'failed')
91
190
  throw new HttpError(500, outcome.message, { ok: false, action });
92
191
  return { ok: true, action, message: `Gateway ${action} completed.`, status: await currentGatewayStatus(ctx) };
93
192
  }
94
193
  const principalHash = (...parts) => createHash('sha256').update(JSON.stringify(parts), 'utf8').digest('hex');
95
- export function updateNotificationOwner(session) {
96
- const authType = str(session?.auth_type).trim();
97
- if (authType === 'oidc') {
98
- const issuer = str(session?.oidc_issuer).trim();
99
- const subject = typeof session?.oidc_subject === 'string' ? session.oidc_subject : '';
100
- if (issuer && subject.trim())
101
- return `oidc:${principalHash(issuer, subject)}`;
102
- const token = str(session?.token).trim();
103
- if (token)
104
- return `oidc-session:${principalHash(token)}`;
105
- }
106
- const username = str(session?.username).trim();
107
- return username ? `${authType || 'auth'}:${username}` : 'local-owner';
108
- }
109
194
  async function updateNotificationScope(ctx, tab) {
110
195
  const session = await ensureTrustedAuthSession(ctx);
196
+ const profile = activeProfileName(ctx);
111
197
  return {
112
198
  owner: updateNotificationOwner(session),
113
- profile: activeProfileName(ctx),
199
+ profile,
114
200
  serverOwner: await sessionCanManageServer(ctx, session),
115
201
  tab: tab ?? null,
202
+ rootProfile: ctx.deps.isRootProfile(profile),
116
203
  };
117
204
  }
118
- async function applyWithNotification(ctx, target, apply, confirmed = false, tab) {
119
- const scope = await updateNotificationScope(ctx, tab);
205
+ async function applyWithNotification(ctx, input, action) {
206
+ const target = updateTarget(input.target);
207
+ const confirmed = input.confirmed_agent_revision !== undefined || input.agent_refresh_token !== undefined;
208
+ const scope = await updateNotificationScope(ctx, input.tab_id);
120
209
  const active = ctx.deps.updateNotifications.activeUpdate(scope, target);
121
210
  if (active)
122
- ctx.deps.updateNotifications.watch(scope, active.id);
123
- if (active && (active.phase === 'applying' || active.phase === 'restarting')) {
211
+ (await ctx.deps.updateNotifications.watch(scope, active.id));
212
+ if (active && (active.phase === 'applying' || active.phase === 'restarting' || active.phase === 'verifying')) {
124
213
  return { ok: false, status: 'already_in_progress', message: 'Update already in progress', notification_id: active.id };
125
214
  }
126
- const notification = active ?? ctx.deps.updateNotifications.begin(scope, target);
215
+ const notification = active ?? (await ctx.deps.updateNotifications.begin(scope, target));
127
216
  if (active?.phase === 'awaiting_confirmation' && confirmed)
128
- ctx.deps.updateNotifications.transition(notification.id, 'applying');
217
+ (await ctx.deps.updateNotifications.transition(notification.id, 'applying'));
218
+ // TAL-1138: the gateways running before an Agent update; the update's check needs a new process for each.
219
+ const gatewaysBefore = target === 'agent' ? await ctx.deps.gatewayRestarts.gateways(scope.profile).catch(() => []) : [];
129
220
  try {
130
- const result = await apply();
221
+ const options = { agentChannel: input.agent_channel, confirmedRevision: input.confirmed_agent_revision, version: input.version, refreshToken: input.agent_refresh_token, mutationIntent: principalHash(scope.owner, scope.profile, notification.id),
222
+ // TAL-1429: the Updating dialog shows what the running update waits for; a lost refresh only delays that wording.
223
+ onProgress: (detail) => { ctx.deps.updateNotifications.transition(notification.id, 'applying', null, undefined, detail).catch(() => undefined); } };
224
+ const result = action === 'apply' ? await ctx.deps.updates.apply(target, bodyChannel(input.channel), () => true, options)
225
+ : action === 'force' ? await ctx.deps.updates.force(target, bodyChannel(input.channel), options)
226
+ : await ctx.deps.updates.clearLock(target, options);
131
227
  const verifiedIdentity = typeof result.verified_revision === 'string'
132
228
  ? { revision: result.verified_revision, version: typeof result.verified_version === 'string' ? result.verified_version : null }
133
229
  : undefined;
134
230
  if (result.confirmation_required === true)
135
- ctx.deps.updateNotifications.transition(notification.id, 'awaiting_confirmation', null, verifiedIdentity);
231
+ (await ctx.deps.updateNotifications.transition(notification.id, 'awaiting_confirmation', null, verifiedIdentity, result.message));
136
232
  else if (result.restart_blocked === true)
137
- ctx.deps.updateNotifications.transition(notification.id, 'blocked', null, verifiedIdentity, result.message);
233
+ (await ctx.deps.updateNotifications.transition(notification.id, 'blocked', null, verifiedIdentity, result.message));
138
234
  else if (result.ok !== true)
139
- ctx.deps.updateNotifications.transition(notification.id, 'failed', null, verifiedIdentity, result.message || result.error);
235
+ (await ctx.deps.updateNotifications.transition(notification.id, 'failed', null, verifiedIdentity, result.message || result.error));
140
236
  else if (target === 'webui' && result.restart_scheduled === true) {
141
- ctx.deps.updateNotifications.transition(notification.id, 'restarting', str(result.sourceRevision || result.candidate_revision), verifiedIdentity);
237
+ await ctx.deps.updateNotifications.transition(notification.id, 'restarting', str(result.sourceRevision || result.candidate_revision), verifiedIdentity);
238
+ }
239
+ else if (target === 'agent' && result.gateway_restart === 'resumed') {
240
+ // TAL-1138: the native updater restarted the gateways inside its writer pause. Agent responding still needs the
241
+ // new gateway processes and a current Agent runtime; a scheduled Web restart runs that check from the new server.
242
+ const detail = result.stash_conflict === true ? str(result.message) : null;
243
+ await ctx.deps.updateNotifications.recordGatewayBaseline(notification.id, gatewaysBefore);
244
+ await ctx.deps.updateNotifications.transition(notification.id, 'verifying', null, verifiedIdentity, detail);
245
+ if (result.restart_scheduled === true)
246
+ (await ctx.deps.updateNotifications.markWebRestart(notification.id));
247
+ else
248
+ void ctx.deps.gatewayRestarts.verify(notification.id, scope.profile, gatewaysBefore, detail);
249
+ }
250
+ else if (result.gateway_restart === 'waiting_for_idle' || (target === 'agent' && ctx.deps.gatewayRestarts.pendingId() !== null)) {
251
+ // TAL-953: the gateway restarts once its own work drains. A restart already waiting covers this update too, and a
252
+ // repeated request that found the Agent current follows that wait rather than reporting success before it.
253
+ const detail = result.stash_conflict === true ? str(result.message) : null;
254
+ await ctx.deps.updateNotifications.transition(notification.id, 'waiting_for_idle', null, verifiedIdentity, detail);
255
+ // TAL-1138: a scheduled Web restart goes first, and the restarted server resumes this wait.
256
+ if (result.restart_scheduled === true && ctx.deps.gatewayRestarts.pendingId() === null) {
257
+ await ctx.deps.updateNotifications.markWebRestart(notification.id);
258
+ return { ...result, notification_id: notification.id };
259
+ }
260
+ const pending = (await ctx.deps.gatewayRestarts.schedule(notification.id, scope.profile, detail));
261
+ if (pending !== notification.id)
262
+ (await ctx.deps.updateNotifications.watch(scope, pending));
263
+ return { ...result, notification_id: pending };
142
264
  }
143
265
  else {
144
266
  // A kept Agent stash needs the user's attention; its recovery commands ride on the success record.
145
- ctx.deps.updateNotifications.transition(notification.id, 'succeeded', null, verifiedIdentity, result.stash_conflict === true ? result.message : undefined);
267
+ await ctx.deps.updateNotifications.transition(notification.id, 'succeeded', null, verifiedIdentity, result.stash_conflict === true ? result.message : undefined);
146
268
  }
147
269
  return { ...result, notification_id: notification.id };
148
270
  }
149
271
  catch (error) {
150
- ctx.deps.updateNotifications.transition(notification.id, 'failed', null, undefined, error instanceof Error ? error.message : null);
272
+ await ctx.deps.updateNotifications.transition(notification.id, 'failed', null, undefined, error instanceof Error ? error.message : null);
151
273
  throw error;
152
274
  }
153
275
  }
@@ -225,10 +347,10 @@ export function sanitizeClientEvent(payload) {
225
347
  out.event = 'unknown';
226
348
  return out;
227
349
  }
228
- function memoryWorkspace(ctx, sessionId, workspace) {
350
+ async function memoryWorkspace(ctx, sessionId, workspace) {
229
351
  if (sessionId) {
230
352
  try {
231
- const session = ctx.deps.sessionStore.get(sessionId, { metadataOnly: true });
353
+ const session = (await ctx.deps.sessionStore.get(sessionId, { metadataOnly: true }));
232
354
  if (!ctx.deps.workspaces.profileSupportsLocalIo(session.profile))
233
355
  return null;
234
356
  const ws = str(session.workspace).trim();
@@ -241,11 +363,11 @@ function memoryWorkspace(ctx, sessionId, workspace) {
241
363
  const profile = activeProfileName(ctx);
242
364
  if (!ctx.deps.workspaces.profileSupportsLocalIo(profile))
243
365
  return null;
244
- const raw = workspace || (ctx.deps.config.env.TERMINAL_CWD ?? '') || ctx.deps.workspaces.lastWorkspace(profile);
366
+ const raw = workspace || (ctx.deps.config.env.TERMINAL_CWD ?? '') || (await ctx.deps.workspaces.lastWorkspace(profile));
245
367
  if (!raw)
246
368
  return null;
247
369
  try {
248
- return ctx.deps.workspaces.resolveTrusted(raw, profile);
370
+ return (await ctx.deps.workspaces.resolveTrusted(raw, profile));
249
371
  }
250
372
  catch {
251
373
  return null;
@@ -277,7 +399,13 @@ async function wikiLocation(ctx) {
277
399
  const config = await ctx.deps.agentConfig.read(profileHome).catch(() => ({}));
278
400
  return resolveWikiLocation(ctx.deps.config.env, profileHome, config, ctx.deps.config.homeDir);
279
401
  }
402
+ /** TAL-819: the Agent's review handler per write; its message can quote the entry text an approval replaced or removed. */
403
+ async function reviewPendingWrites(ctx, verb, input) {
404
+ const { results } = await runningSidecar(ctx).call(`write_approval.${verb}`, { profile_home: home(ctx), kind: input.kind, writes: input.writes });
405
+ return { results: results.map((r) => ({ ...r, message: redactString(r.message, ctx.deps.sessions.deps.redactEnabled()) })) };
406
+ }
280
407
  export const toolsRouter = os.router({
408
+ toolsetsCatalog: os.toolsetsCatalog.handler(({ input, context: { ctx } }) => run(() => runningSidecar(ctx).call('toolsets.catalog', { profile_home: home(ctx), enabled_toolsets: input.toolsets }))),
281
409
  skills: {
282
410
  list: os.skills.list.handler(({ input, context: { ctx } }) => run(async () => ({ skills: await ctx.deps.skills.list(home(ctx), str(input.category).trim() || null) }))),
283
411
  usage: os.skills.usage.handler(({ context: { ctx } }) => run(() => ctx.deps.skills.usage(home(ctx)))),
@@ -308,15 +436,32 @@ export const toolsRouter = os.router({
308
436
  memory: {
309
437
  get: os.memory.get.handler(({ input, context: { ctx } }) => run(async () => {
310
438
  const config = await ctx.deps.agentConfig.read(home(ctx));
311
- return readMemory(home(ctx), config, memoryWorkspace(ctx, str(input.session_id), str(input.workspace)), ctx.deps.config.env, ctx.deps.sessions.deps.redactEnabled());
439
+ return readMemory(home(ctx), config, (await memoryWorkspace(ctx, str(input.session_id), str(input.workspace))), ctx.deps.config.env, ctx.deps.sessions.deps.redactEnabled(), ctx.deps.auth.signingKey());
312
440
  })),
313
441
  write: os.memory.write.handler(({ input, context: { ctx } }) => run(async () => {
314
442
  const section = input.section ?? input.target;
315
443
  if (section === undefined || input.content === undefined)
316
444
  throw new HttpError(400, 'Missing required field(s): section, content');
317
- return writeMemory(home(ctx), await ctx.deps.agentConfig.read(home(ctx)), str(section), str(input.content));
445
+ const profileHome = home(ctx);
446
+ return writeMemory(profileHome, await ctx.deps.agentConfig.read(profileHome), str(section), str(input.content), input.revision, {
447
+ key: ctx.deps.auth.signingKey(),
448
+ check: (target, content) => runningSidecar(ctx).call('memory.check', { profile_home: profileHome, target, content }),
449
+ write: (target, base, content) => runningSidecar(ctx).call('memory.write', { profile_home: profileHome, section: target, base, content }),
450
+ });
318
451
  })),
319
452
  },
453
+ pendingWrites: {
454
+ list: os.pendingWrites.list.handler(({ input, context: { ctx } }) => run(async () => {
455
+ // Without the Agent nothing can be reviewed, so the page shows no panel (the Agent's own status reports it down).
456
+ const sidecar = ctx.deps.sidecar();
457
+ const { enabled, items } = sidecar ? await sidecar.call('write_approval.pending', { profile_home: home(ctx), kind: input.kind }) : { enabled: false, items: [] };
458
+ const redact = (text) => redactString(text, ctx.deps.sessions.deps.redactEnabled());
459
+ // Display text is redacted like the memory page; `revision` stays the sidecar's hash of the raw diff it rechecks.
460
+ return { kind: input.kind, visible: items.length > 0, enabled, items: items.map((item) => ({ ...item, summary: redact(item.summary), diff: redact(item.diff) })) };
461
+ })),
462
+ approve: os.pendingWrites.approve.handler(({ input, context: { ctx } }) => run(() => reviewPendingWrites(ctx, 'approve', input))),
463
+ reject: os.pendingWrites.reject.handler(({ input, context: { ctx } }) => run(() => reviewPendingWrites(ctx, 'reject', input))),
464
+ },
320
465
  prompts: {
321
466
  list: os.prompts.list.handler(({ context: { ctx } }) => run(() => ({ prompts: loadPrompts(home(ctx)) }))),
322
467
  create: os.prompts.create.handler(({ input, context: { ctx } }) => run(() => ({ ok: true, prompt: createPrompt(home(ctx), str(input.text), str(input.label), ctx.deps.nowSeconds()) }))),
@@ -337,12 +482,30 @@ export const toolsRouter = os.router({
337
482
  const command = str(input.command).trim();
338
483
  if (!command)
339
484
  throw new HttpError(400, 'command is required');
485
+ const [, name = '', args = ''] = /^\/?(\S*)\s*([\s\S]*)$/.exec(command) ?? [];
486
+ const sessionId = str(input.session_id).trim();
487
+ if (sessionId)
488
+ (await ctx.deps.sessions.assertWritable(sessionId));
489
+ // TAL-902: a session command runs on the chat's own agent (the request guard already checked the chat's profile).
490
+ if (SESSION_EXEC_COMMANDS.has(name.toLowerCase())) {
491
+ return { output: await ctx.deps.turns.refine(sessionId ? (await ctx.deps.sessionStore.get(sessionId)) : null, args.trim()) };
492
+ }
493
+ // TAL-904: a chat's command runs under that chat's session and the workspace its next turn would use. An unknown
494
+ // chat (404) or a workspace that turn would refuse (400) refuses the command rather than run it half-bound.
495
+ const chat = sessionId ? { session_id: sessionId, workspace: (await ctx.deps.sessions.turnWorkspace((await ctx.deps.sessionStore.get(sessionId, { metadataOnly: true })))) } : {};
496
+ let output;
340
497
  try {
341
- return { output: (await runningSidecar(ctx).call('commands.exec', { profile_home: home(ctx), command }, { timeoutMs: 120_000 })).output };
498
+ output = (await runningSidecar(ctx).call('commands.exec', { profile_home: home(ctx), command, ...chat }, { timeoutMs: 120_000 })).output;
342
499
  }
343
500
  catch (error) {
344
501
  return commandFailure(error, 'command_not_found', 'Plugin command not found');
345
502
  }
503
+ // TAL-1274: an /autoprune answer typed in the composer withdraws the profile's open auto-prune question.
504
+ if (name.toLowerCase() === 'autoprune') {
505
+ const profile = activeProfileName(ctx);
506
+ await ctx.deps.pruneAdvice.check(ctx.deps.isRootProfile(profile) ? 'default' : profile, home(ctx));
507
+ }
508
+ return { output };
346
509
  })),
347
510
  bundles: os.commands.bundles.handler(({ context: { ctx } }) => run(async () => {
348
511
  const sidecar = ctx.deps.sidecar();
@@ -401,25 +564,25 @@ export const toolsRouter = os.router({
401
564
  browse: os.wiki.browse.handler(({ context: { ctx } }) => run(async () => wikiPages.browse(await wikiLocation(ctx)))),
402
565
  page: os.wiki.page.handler(({ input, context: { ctx } }) => run(async () => wikiPages.page(await wikiLocation(ctx), str(input.path)))),
403
566
  },
404
- insights: os.insights.handler(({ input, context: { ctx } }) => run(() => {
567
+ insights: os.insights.handler(({ input, context: { ctx } }) => run(async () => {
405
568
  let entries = [];
406
569
  try {
407
- entries = ctx.deps.sessionStore.readIndexEntries();
570
+ entries = (await ctx.deps.sessionStore.readIndexEntries());
408
571
  }
409
572
  catch {
410
573
  entries = [];
411
574
  }
412
- return buildInsights(entries, input.days, ctx.deps.nowSeconds(), (cutoff) => insightsSessionRows(join(home(ctx), 'state.db'), cutoff));
575
+ return buildInsights(entries, input.days, ctx.deps.nowSeconds(), (cutoff) => stateDbSessionReadAsync([], 'insightsSessionRows', join(home(ctx), 'state.db'), cutoff));
413
576
  })),
414
- logs: os.logs.handler(({ input, context: { ctx } }) => run(() => readLogTail(home(ctx), input.file, input.tail))),
577
+ logs: os.logs.handler(({ input, signal, context: { ctx } }) => run(() => readLogTail(home(ctx), input.file, input.tail, signal))),
415
578
  ops: {
416
- agent: os.ops.agent.handler(({ context: { ctx } }) => run(() => health(ctx))),
579
+ agent: os.ops.agent.handler(({ context: { ctx } }) => run(async () => { const [gateway, chat] = await Promise.all([health(ctx), currentChatReadiness(ctx.deps.sidecar())]); return { ...gateway, chat }; })),
417
580
  system: os.ops.system.handler(({ context: { ctx } }) => run(() => systemHealth(ctx.deps.config.homeDir, ctx.deps.runtimeDiagnostics()))),
418
581
  restart: os.ops.restart.handler(({ context: { ctx } }) => run(async () => {
419
582
  const sidecar = ctx.deps.sidecar();
420
583
  if (!sidecar)
421
584
  throw new HttpError(500, 'Hermes Agent sidecar is not running');
422
- const outcome = await sidecar.call('gateway.restart', { profile_home: home(ctx) }, { timeoutMs: 300_000 });
585
+ const outcome = await restartGateway(sidecar, home(ctx), true);
423
586
  if (outcome.status === 'completed')
424
587
  return { ok: true, message: 'Gateway service restarted successfully' };
425
588
  if (outcome.status === 'busy')
@@ -433,11 +596,11 @@ export const toolsRouter = os.router({
433
596
  await ctx.deps.agentConfig.update(home(ctx), (config) => { applyDashboardConfig(config, next); });
434
597
  return next;
435
598
  })),
436
- projectOs: os.ops.projectOs.handler(({ input, context: { ctx } }) => run(() => {
599
+ projectOs: os.ops.projectOs.handler(({ input, context: { ctx } }) => run(async () => {
437
600
  const profile = activeProfileName(ctx);
438
601
  return projectOsDashboard(str(input.board), {
439
602
  localIo: ctx.deps.workspaces.profileSupportsLocalIo(profile),
440
- lastWorkspace: ctx.deps.workspaces.lastWorkspace(profile),
603
+ lastWorkspace: (await ctx.deps.workspaces.lastWorkspace(profile)),
441
604
  boards: async () => (await runningSidecar(ctx).call('kanban.boards', { profile_home: home(ctx), include_archived: true })).boards,
442
605
  git: async (repoRoot) => gitBadge(await ctx.deps.git.status(repoRoot, { useCache: true })),
443
606
  cwd: process.cwd(),
@@ -471,9 +634,50 @@ export const toolsRouter = os.router({
471
634
  update: os.mcp.update.handler(({ input, context: { ctx } }) => run(() => { const { name, ...body } = input; return ctx.deps.mcp.update(home(ctx), decodeURIComponent(name), body); })),
472
635
  delete: os.mcp.delete.handler(({ input, context: { ctx } }) => run(() => ctx.deps.mcp.delete(home(ctx), decodeURIComponent(input.name)))),
473
636
  },
637
+ connectors: {
638
+ // Fails closed: no sidecar, or one that cannot answer, hides the page.
639
+ available: os.connectors.available.handler(({ context: { ctx } }) => run(async () => ({ available: ctx.deps.sidecar() ? await connectorCall(ctx, 'connectors.available', {}).then((r) => r.available, () => false) : false }))),
640
+ page: os.connectors.page.handler(({ context: { ctx } }) => run(async () => {
641
+ if (!ctx.deps.sidecar() || !(await connectorCall(ctx, 'connectors.available', {})).available)
642
+ return { available: false, connectors: [], policy_revision: null, rules_error: null, sign_in_required: false };
643
+ const [catalog, accounts, policy] = await Promise.all([
644
+ connectorRead(ctx, 'connectors.catalog'), connectorRead(ctx, 'connectors.accounts'), connectorRead(ctx, 'connectors.policy.get'),
645
+ ]);
646
+ rememberCatalogNames(home(ctx), catalog.value?.connectors ?? []);
647
+ return connectorsPage(catalog.value?.connectors ?? [], accounts.value?.accounts ?? [], policy.value, policy.error, catalog.signInRequired || accounts.signInRequired || policy.signInRequired);
648
+ })),
649
+ tools: os.connectors.tools.handler(({ input, context: { ctx } }) => run(async () => {
650
+ const [listing, policy] = await Promise.all([connectorCall(ctx, 'connectors.tools', { connector: input.connector }), connectorRead(ctx, 'connectors.policy.get')]);
651
+ return connectorTools(listing, policy.value);
652
+ })),
653
+ setPolicy: os.connectors.setPolicy.handler(({ input, context: { ctx } }) => run(async () => {
654
+ const change = input.tool === undefined ? (typeof input.enabled === 'boolean' ? { enabled: input.enabled } : null)
655
+ : typeof input.tool_enabled === 'boolean' && input.enabled === undefined ? { tool: input.tool, tool_enabled: input.tool_enabled } : null;
656
+ if (!change)
657
+ throw new HttpError(400, 'Send `enabled`, or `tool` with `tool_enabled`.', { code: 'policy_invalid' });
658
+ const { revision } = await connectorCall(ctx, 'connectors.policy.set', { connector: input.connector, expected_revision: input.revision, ...change });
659
+ return { ok: true, revision };
660
+ })),
661
+ connect: os.connectors.connect.handler(({ input, context: { ctx } }) => run(async () => operationView(ctx, await connectorCall(ctx, 'connectors.connect', { connector: input.connector })))),
662
+ removeAccount: os.connectors.removeAccount.handler(({ input, context: { ctx } }) => run(async () => {
663
+ await connectorCall(ctx, 'connectors.remove', { connection_id: input.connection_id });
664
+ return { ok: true };
665
+ })),
666
+ operation: os.connectors.operation.handler(({ input, context: { ctx } }) => run(async () => operationView(ctx, await connectorCall(ctx, 'connectors.operation', { op_id: input.op_id })))),
667
+ respond: os.connectors.respond.handler(({ input, context: { ctx } }) => run(async () => {
668
+ // Only a move the operation offers now reaches the Agent: the view decides, the sidecar applies.
669
+ const view = connectorOperation(await connectorCall(ctx, 'connectors.operation', { op_id: input.op_id }));
670
+ const { action } = input;
671
+ const offered = action === 'continue' ? view.can_continue : view.targets.some((t) => t.name === input.target && t.actions.includes(action));
672
+ if (!offered)
673
+ throw new HttpError(409, 'That move is not open on this connection.', { code: 'operation_refused' });
674
+ return operationView(ctx, await connectorCall(ctx, 'connectors.respond', { op_id: input.op_id, action, ...(input.target ? { target: input.target } : {}), ...(input.env ? { env: input.env } : {}) }));
675
+ })),
676
+ },
474
677
  plugins: os.plugins.handler(({ context: { ctx } }) => run(async () => {
475
678
  const sidecar = ctx.deps.sidecar();
476
679
  const hooks = ['pre_tool_call', 'post_tool_call', 'pre_llm_call', 'post_llm_call'];
680
+ const editable = await sessionCanManageServer(ctx, await ensureTrustedAuthSession(ctx));
477
681
  if (!sidecar)
478
682
  return { plugins: [], empty: true, supported_hooks: hooks, read_only: true, unavailable: true };
479
683
  try {
@@ -483,22 +687,140 @@ export const toolsRouter = os.router({
483
687
  if (v && typeof v === 'object' && !Array.isArray(v) && typeof v.provider === 'string')
484
688
  selected[k] = str(v.provider).trim().toLowerCase();
485
689
  const result = await sidecar.call('plugins.list', { profile_home: home(ctx), selected_providers: selected });
486
- return { plugins: result.plugins, empty: result.plugins.length === 0, supported_hooks: result.supported_hooks, read_only: true };
690
+ // A settings failure leaves the list itself readable.
691
+ const declared = await pluginSettingsList(ctx).catch((error) => { ctx.deps.log(`[plugins] settings fields failed: ${str(error.message)}`); return []; });
692
+ const settings = new Map(declared.map((entry) => [entry.key, entry.fields]));
693
+ // So does an OAuth status failure.
694
+ const oauth = await pluginOAuthClients(ctx).catch((error) => { ctx.deps.log(`[plugins] oauth status failed: ${str(error.message)}`); return new Map(); });
695
+ const plugins = result.plugins.map(({ update_available, latest_revision, ...plugin }) => ({
696
+ ...plugin,
697
+ ...(update_available === undefined ? {} : { update: { available: update_available, ...(latest_revision ? { latest_revision } : {}) } }),
698
+ ...(settings.has(plugin.key) ? { settings: settings.get(plugin.key) } : {}),
699
+ ...(oauth.has(plugin.key) ? { oauth_clients: oauth.get(plugin.key) } : {}),
700
+ }));
701
+ // An advisory failure leaves the list itself readable.
702
+ const advisory = await pluginIsolationAdvisory(ctx).catch((error) => { ctx.deps.log(`[plugins] isolation advisory failed: ${str(error.message)}`); return false; });
703
+ return { plugins, empty: plugins.length === 0, supported_hooks: result.supported_hooks, read_only: !editable, plugin_isolation_advisory: advisory };
487
704
  }
488
705
  catch (error) {
489
706
  ctx.deps.log(`[plugins] visibility payload failed: ${str(error.message)}`);
490
707
  return { plugins: [], empty: true, supported_hooks: hooks, read_only: true, unavailable: true };
491
708
  }
492
709
  })),
710
+ pluginCatalog: os.pluginCatalog.handler(({ input, context: { ctx } }) => run(async () => {
711
+ const result = await runningSidecar(ctx).call('plugins.catalog', { profile_home: home(ctx), ...input });
712
+ const readOnly = !await sessionCanManageServer(ctx, await ensureTrustedAuthSession(ctx));
713
+ return { ...result, read_only: readOnly, entries: result.entries.map((entry) => ({ ...entry, can_install: !readOnly && entry.can_install })) };
714
+ })),
715
+ pluginInstall: os.pluginInstall.handler(({ input, context: { ctx } }) => run(async () => {
716
+ try {
717
+ return await runningSidecar(ctx).call('plugins.install', { profile_home: home(ctx), ...input }, { timeoutMs: 0 });
718
+ }
719
+ catch (error) {
720
+ if (error instanceof SidecarError && error.condition === 'plugin_install_consent_changed')
721
+ throw new HttpError(409, error.message, { condition: error.condition });
722
+ if (error instanceof SidecarError && error.condition === 'plugin_install_refused')
723
+ throw new HttpError(409, error.message, { condition: error.condition });
724
+ if (error instanceof SidecarError && error.condition === 'plugin_catalog_unsupported')
725
+ throw new HttpError(503, error.message, { condition: error.condition });
726
+ if (!definitiveRefusal(error))
727
+ throw new HttpError(503, 'Install outcome is unknown. Refresh Plugins to check the installed identity before trying again.', { condition: 'plugin_install_unconfirmed' });
728
+ throw error;
729
+ }
730
+ })),
731
+ pluginUpdate: os.pluginUpdate.handler(({ input, context: { ctx } }) => run(async () => {
732
+ try {
733
+ return await runningSidecar(ctx).call('plugins.update', { profile_home: home(ctx), key: input.key, accept_caution: input.accept_caution, ...(input.consent_token ? { consent_token: input.consent_token } : {}) }, { timeoutMs: 0 });
734
+ }
735
+ catch (error) {
736
+ if (error instanceof SidecarError && error.condition === 'plugin_not_found')
737
+ throw new HttpError(404, error.message);
738
+ if (error instanceof SidecarError && ['plugin_update_refused', 'plugin_update_consent_changed'].includes(error.condition))
739
+ throw new HttpError(409, error.message, { condition: error.condition });
740
+ throw error;
741
+ }
742
+ })),
743
+ pluginSettings: os.pluginSettings.handler(({ input, context: { ctx } }) => run(() => serializePluginSettingsSave(async () => {
744
+ const sidecar = runningSidecar(ctx);
745
+ const fields = (await pluginSettingsList(ctx)).find((entry) => entry.key === input.key)?.fields;
746
+ if (!fields)
747
+ throw new HttpError(404, `Plugin '${input.key}' declares no settings`);
748
+ let plan;
749
+ try {
750
+ plan = planPluginSettings(fields, input.values ?? {}, input.secrets ?? {});
751
+ }
752
+ catch (error) {
753
+ if (error instanceof PluginSettingsInvalid)
754
+ throw new HttpError(400, error.message);
755
+ throw error;
756
+ }
757
+ const secretFields = fields.filter((field) => field.env && field.env in plan.secrets);
758
+ // Secrets never reach config.yaml: each goes to the profile `.env` under the name the manifest field declares. They are
759
+ // written first and restored if a later write fails, so a refused save changes neither file. The save call always runs:
760
+ // it resolves the plugin again and refuses (before writing) when a secret's `.env` name no longer matches its manifest.
761
+ const credential = (envVar, value) => writeRuntimeCredential({ env: ctx.deps.config.env, sidecar: ctx.deps.sidecar, log: ctx.deps.log }, ctx.deps.isRootProfile(activeProfileName(ctx)), home(ctx), envVar, value);
762
+ const previous = loadEnvFile(join(home(ctx), '.env'));
763
+ const applied = [];
764
+ let result;
765
+ try {
766
+ for (const [envVar, value] of Object.entries(plan.secrets)) {
767
+ await credential(envVar, value);
768
+ applied.push(envVar);
769
+ }
770
+ result = await sidecar.call('plugins.settings_save', { profile_home: home(ctx), key: input.key, values: plan.values, secret_envs: Object.fromEntries(secretFields.map((field) => [field.key, field.env])) });
771
+ }
772
+ catch (error) {
773
+ if (!definitiveRefusal(error)) {
774
+ throw new HttpError(503, 'The Agent sidecar stopped before confirming the save, so it may be partly applied; reload Settings to see what was saved', { condition: 'plugin_settings_unconfirmed' });
775
+ }
776
+ for (const envVar of applied.reverse()) {
777
+ await credential(envVar, previous[envVar] ?? null).catch((restore) => { ctx.deps.log(`[plugins] could not restore ${envVar} after a failed settings save: ${str(restore.message)}`); });
778
+ }
779
+ if (error instanceof SidecarError && error.condition === 'plugin_settings_managed')
780
+ throw new HttpError(403, error.message, { condition: error.condition });
781
+ if (error instanceof SidecarError && error.condition === 'plugin_settings_changed')
782
+ throw new HttpError(409, `${error.message}; reload and try again`, { condition: error.condition });
783
+ if (error instanceof SidecarError && error.condition === 'plugin_not_found')
784
+ throw new HttpError(404, error.message);
785
+ if (error instanceof SidecarError && error.code === -32602)
786
+ throw new HttpError(400, error.message);
787
+ if (error instanceof RuntimeCredentialError)
788
+ throw new HttpError(503, error.message);
789
+ if (error instanceof EnvWriteError)
790
+ throw new HttpError(error.status, `Failed to save a secret: ${error.message}`, { condition: error.condition });
791
+ throw error;
792
+ }
793
+ return { ok: true, key: result.key, runtime_application: result.runtime_application ?? 'restart_required', written: [...result.written, ...secretFields.map((field) => field.key)], settings: pluginSettingsFieldsView(ctx, result.fields) };
794
+ }))),
795
+ pluginOAuthRedirect: os.pluginOAuthRedirect.handler(({ input, context: { ctx } }) => run(async () => {
796
+ // Only this flow's own answer reaches the sidecar: its loopback address and its `state`.
797
+ const verdict = checkPastedRedirect(input.flow_id, home(ctx), input.url);
798
+ if (verdict === 'unknown')
799
+ throw new HttpError(404, 'Unknown or expired sign-in.', { condition: 'oauth_flow_not_found' });
800
+ if (verdict === 'invalid')
801
+ throw new HttpError(400, 'That is not the address this sign-in sends the browser back to.', { condition: 'oauth_redirect_invalid' });
802
+ return oauthView(await oauthCall(ctx, 'oauth.submit_redirect', { profile_home: home(ctx), flow_id: input.flow_id, url: input.url }));
803
+ })),
804
+ pluginOAuthLogout: os.pluginOAuthLogout.handler(({ input, context: { ctx } }) => run(async () => {
805
+ try {
806
+ const result = await runningSidecar(ctx).call('plugins.oauth_logout', { profile_home: home(ctx), key: input.key, id: input.id });
807
+ return { ok: true, removed: result.removed };
808
+ }
809
+ catch (error) {
810
+ if (error instanceof SidecarError && error.condition === 'oauth_unsupported')
811
+ throw new HttpError(409, error.message, { condition: error.condition });
812
+ return failure(error);
813
+ }
814
+ })),
493
815
  updates: {
494
- check: os.updates.check.handler(({ context: { ctx } }) => run(() => {
495
- const settings = ctx.deps.settings.load();
816
+ check: os.updates.check.handler(({ context: { ctx } }) => run(async () => {
817
+ const settings = (await ctx.deps.settings.load());
496
818
  if (settings.check_for_updates === false)
497
819
  return updatesCheckView({ disabled: true });
498
820
  return updatesCheckView(ctx.deps.updates.cachedStatus(!pyBool(settings.ignore_agent_updates)));
499
821
  })),
500
822
  checkNow: os.updates.checkNow.handler(({ input, context: { ctx } }) => run(async () => {
501
- const settings = ctx.deps.settings.load();
823
+ const settings = (await ctx.deps.settings.load());
502
824
  const force = pyBool(input.force);
503
825
  if (settings.check_for_updates === false && !force)
504
826
  return updatesCheckView({ disabled: true });
@@ -507,58 +829,90 @@ export const toolsRouter = os.router({
507
829
  ctx.deps.log(`[updates] checking for updates (force=${String(force)}, channel=${channel})`);
508
830
  return updatesCheckView(await ctx.deps.updates.check(force, !pyBool(settings.ignore_agent_updates), channel, input.agent_channel));
509
831
  })),
510
- apply: os.updates.apply.handler(({ input, context: { ctx } }) => run(() => { const target = updateTarget(input.target); return applyWithNotification(ctx, target, () => ctx.deps.updates.apply(target, bodyChannel(input.channel), () => true, { agentChannel: input.agent_channel, confirmedRevision: input.confirmed_agent_revision }), input.confirmed_agent_revision !== undefined, input.tab_id); })),
511
- force: os.updates.force.handler(({ input, context: { ctx } }) => run(() => { const target = updateTarget(input.target); return applyWithNotification(ctx, target, () => ctx.deps.updates.force(target, bodyChannel(input.channel), { agentChannel: input.agent_channel, confirmedRevision: input.confirmed_agent_revision }), input.confirmed_agent_revision !== undefined, input.tab_id); })),
512
- clearLock: os.updates.clearLock.handler(({ input, context: { ctx } }) => run(() => { const target = updateTarget(input.target); return applyWithNotification(ctx, target, () => ctx.deps.updates.clearLock(target, { agentChannel: input.agent_channel, confirmedRevision: input.confirmed_agent_revision }), input.confirmed_agent_revision !== undefined, input.tab_id); })),
513
- summary: os.updates.summary.handler(({ input, context: { ctx } }) => run(() => ctx.deps.updates.summarize(input.target, ctx.deps.settings.load().check_for_updates === false))),
832
+ apply: os.updates.apply.handler(({ input, context: { ctx } }) => run(() => applyWithNotification(ctx, input, 'apply'))),
833
+ force: os.updates.force.handler(({ input, context: { ctx } }) => run(() => applyWithNotification(ctx, input, 'force'))),
834
+ clearLock: os.updates.clearLock.handler(({ input, context: { ctx } }) => run(() => applyWithNotification(ctx, input, 'clearLock'))),
835
+ summary: os.updates.summary.handler(({ input, context: { ctx } }) => run(async () => ctx.deps.updates.summarize(input.target, (await ctx.deps.settings.load()).check_for_updates === false))),
514
836
  },
515
837
  updateNotifications: {
516
838
  list: os.updateNotifications.list.handler(({ input, context: { ctx } }) => run(async () => {
517
839
  const scope = await updateNotificationScope(ctx, input.tab_id);
518
- const frontendBuild = ctx.deps.updateNotifications.syncTabBuild(scope, input.loaded_build ?? null, ctx.deps.spa.buildId());
519
- return { ...ctx.deps.updateNotifications.list(scope), frontend_build: frontendBuild };
840
+ const frontendBuild = (await ctx.deps.updateNotifications.syncTabBuild(scope, input.loaded_build ?? null, ctx.deps.spa.buildId()));
841
+ return { ...(await ctx.deps.updateNotifications.list(scope, frontendBuild.refresh_required)), frontend_build: frontendBuild };
520
842
  })),
521
843
  read: os.updateNotifications.read.handler(({ input, context: { ctx } }) => run(async () => {
522
- const notification = ctx.deps.updateNotifications.read(await updateNotificationScope(ctx, input.tab_id), input.id);
844
+ const notification = (await ctx.deps.updateNotifications.read(await updateNotificationScope(ctx, input.tab_id), input.id));
523
845
  if (!notification)
524
846
  throw new HttpError(404, 'Update notification not found');
525
847
  return notification;
526
848
  })),
527
849
  dismiss: os.updateNotifications.dismiss.handler(({ input, context: { ctx } }) => run(async () => {
528
- const result = ctx.deps.updateNotifications.dismiss(await updateNotificationScope(ctx, input.tab_id), input.id);
850
+ const result = (await ctx.deps.updateNotifications.dismiss(await updateNotificationScope(ctx, input.tab_id), input.id));
529
851
  if (result === 'acknowledgement_required')
530
852
  throw new HttpError(409, 'This notification requires acknowledgement before it can be dismissed');
531
853
  return { ok: true };
532
854
  })),
533
855
  clear: os.updateNotifications.clear.handler(({ input, context: { ctx } }) => run(async () => {
534
856
  const scope = await updateNotificationScope(ctx, input.tab_id);
535
- const frontendBuild = ctx.deps.updateNotifications.syncTabBuild(scope, input.loaded_build ?? null, ctx.deps.spa.buildId());
536
- return { ...ctx.deps.updateNotifications.clear(scope), frontend_build: frontendBuild };
857
+ const frontendBuild = (await ctx.deps.updateNotifications.syncTabBuild(scope, input.loaded_build ?? null, ctx.deps.spa.buildId()));
858
+ return { ...(await ctx.deps.updateNotifications.clear(scope, frontendBuild.refresh_required)), frontend_build: frontendBuild };
537
859
  })),
538
860
  cancel: os.updateNotifications.cancel.handler(({ input, context: { ctx } }) => run(async () => {
539
- const notification = ctx.deps.updateNotifications.cancelUpdate(await updateNotificationScope(ctx), input.id);
861
+ const notification = (await ctx.deps.updateNotifications.cancelUpdate(await updateNotificationScope(ctx), input.id));
540
862
  if (!notification)
541
863
  throw new HttpError(404, 'Awaiting update notification not found');
542
864
  return notification;
543
865
  })),
544
866
  action: os.updateNotifications.action.handler(({ input, context: { ctx } }) => run(async () => {
545
- const notification = ctx.deps.updateNotifications.action(await updateNotificationScope(ctx, input.tab_id), input.id, input.action_id);
867
+ const scope = await updateNotificationScope(ctx, input.tab_id);
868
+ // TAL-1274: an auto-prune answer runs the Agent's /autoprune for the profile before the question records it.
869
+ const answer = await ctx.deps.pruneAdvice.answer(scope, input.id, input.action_id, home(ctx));
870
+ if (answer && 'refused' in answer)
871
+ throw new HttpError(409, answer.refused);
872
+ if (answer)
873
+ return answer.notification;
874
+ const notification = (await ctx.deps.updateNotifications.action(scope, input.id, input.action_id));
546
875
  if (!notification)
547
876
  throw new HttpError(404, 'Notification action not found');
877
+ if (input.action_id === GATEWAY_RESTART_NOW)
878
+ ctx.deps.gatewayRestarts.restartNow(notification.id);
548
879
  return notification;
549
880
  })),
550
881
  },
551
882
  transcribeCapability: os.transcribeCapability.handler(({ context: { ctx } }) => run(async () => {
883
+ const unavailable = { ok: true, available: false, provider: 'none', streaming: false, warm_supported: false };
552
884
  const sidecar = ctx.deps.sidecar();
553
885
  if (!sidecar)
554
- return { ok: true, available: false, provider: 'none' };
886
+ return unavailable;
555
887
  try {
556
888
  const cap = await sidecar.call('stt.capability', { profile_home: home(ctx) });
557
- return { ok: true, available: cap.available, provider: cap.provider || 'none' };
889
+ return { ok: true, available: cap.available, provider: cap.provider || 'none', streaming: cap.available && cap.streaming, warm_supported: cap.available && cap.warm_supported };
558
890
  }
559
891
  catch {
560
- return { ok: true, available: false, provider: 'none' };
892
+ return unavailable;
893
+ }
894
+ })),
895
+ speech: {
896
+ prepare: os.speech.prepare.handler(({ input, context: { ctx } }) => run(async () => ({ spoken_text: await spokenText(ctx, input.text.trim()) }))),
897
+ },
898
+ transcribeWarm: os.transcribeWarm.handler(({ context: { ctx } }) => run(() => {
899
+ const sidecar = ctx.deps.sidecar();
900
+ const profileHome = home(ctx);
901
+ // One load per profile at a time: a record start during a running load joins it rather than holding another sidecar slot.
902
+ if (sidecar && !warmingHomes.has(profileHome)) {
903
+ warmingHomes.add(profileHome);
904
+ // The load outlives this request's write lease: it is the profile's activity until it settles, so the profile
905
+ // cannot be deleted under it. Taken while the request's lease still refuses a deletion in progress.
906
+ const release = ctx.deps.profileActivity(activeProfileName(ctx));
907
+ // A first use downloads the model, and the Agent's load cannot be cancelled, so the call has no deadline: the entry
908
+ // lives exactly as long as the sidecar worker (a sidecar exit rejects it). Nobody waits on it.
909
+ void sidecar.call('stt.warm', { profile_home: profileHome }, { timeoutMs: 0 })
910
+ .then((result) => { if (result.action === 'error')
911
+ ctx.deps.log(`[stt] warm-up failed (${result.provider}): ${str(result.error)}`); })
912
+ .catch((error) => { ctx.deps.log(`[stt] warm-up failed: ${str(error.message)}`); })
913
+ .finally(() => { warmingHomes.delete(profileHome); release(); });
561
914
  }
915
+ return { ok: true };
562
916
  })),
563
917
  clientEvents: os.clientEvents.handler(({ input, context: { ctx } }) => run(() => {
564
918
  if (ctx.deps.clientEventLimiter.limited(ctx.peer || 'unknown'))