@maudecode/talaria-web 1.17.2 → 1.19.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (623) hide show
  1. package/_release.json +8 -8
  2. package/dist/api/auth-raw.d.ts +1 -1
  3. package/dist/api/auth-raw.js +20 -20
  4. package/dist/api/auth-raw.js.map +1 -1
  5. package/dist/api/automation-raw.d.ts +7 -1
  6. package/dist/api/automation-raw.js +74 -27
  7. package/dist/api/automation-raw.js.map +1 -1
  8. package/dist/api/automation-router.d.ts +128 -23
  9. package/dist/api/automation-router.js +29 -13
  10. package/dist/api/automation-router.js.map +1 -1
  11. package/dist/api/chat-router.d.ts +1845 -40
  12. package/dist/api/chat-router.js +196 -114
  13. package/dist/api/chat-router.js.map +1 -1
  14. package/dist/api/git-router.d.ts +37 -3
  15. package/dist/api/git-router.js +47 -48
  16. package/dist/api/git-router.js.map +1 -1
  17. package/dist/api/raw-routes.d.ts +9 -1
  18. package/dist/api/raw-routes.js +286 -73
  19. package/dist/api/raw-routes.js.map +1 -1
  20. package/dist/api/router.d.ts +16 -6
  21. package/dist/api/router.js +28 -26
  22. package/dist/api/router.js.map +1 -1
  23. package/dist/api/session-visibility.d.ts +4 -4
  24. package/dist/api/session-visibility.js +26 -16
  25. package/dist/api/session-visibility.js.map +1 -1
  26. package/dist/api/sessions-router.d.ts +3312 -131
  27. package/dist/api/sessions-router.js +287 -157
  28. package/dist/api/sessions-router.js.map +1 -1
  29. package/dist/api/settings-router.d.ts +457 -8
  30. package/dist/api/settings-router.js +54 -33
  31. package/dist/api/settings-router.js.map +1 -1
  32. package/dist/api/sse-routes.d.ts +7 -2
  33. package/dist/api/sse-routes.js +109 -62
  34. package/dist/api/sse-routes.js.map +1 -1
  35. package/dist/api/tools-raw.d.ts +5 -0
  36. package/dist/api/tools-raw.js +63 -55
  37. package/dist/api/tools-raw.js.map +1 -1
  38. package/dist/api/tools-router.d.ts +998 -85
  39. package/dist/api/tools-router.js +447 -61
  40. package/dist/api/tools-router.js.map +1 -1
  41. package/dist/api/transcribe-stream.d.ts +16 -0
  42. package/dist/api/transcribe-stream.js +172 -0
  43. package/dist/api/transcribe-stream.js.map +1 -0
  44. package/dist/app.d.ts +4 -1
  45. package/dist/app.js +98 -59
  46. package/dist/app.js.map +1 -1
  47. package/dist/auth/gate.js +15 -11
  48. package/dist/auth/gate.js.map +1 -1
  49. package/dist/auth/oidc.d.ts +5 -2
  50. package/dist/auth/oidc.js +8 -7
  51. package/dist/auth/oidc.js.map +1 -1
  52. package/dist/auth/passkeys.d.ts +15 -14
  53. package/dist/auth/passkeys.js +89 -91
  54. package/dist/auth/passkeys.js.map +1 -1
  55. package/dist/auth/store.d.ts +17 -7
  56. package/dist/auth/store.js +93 -52
  57. package/dist/auth/store.js.map +1 -1
  58. package/dist/bin/talaria-web.js +12 -81
  59. package/dist/bin/talaria-web.js.map +1 -1
  60. package/dist/cli/ctl.js +2 -1
  61. package/dist/cli/ctl.js.map +1 -1
  62. package/dist/cli/dotenv.d.ts +5 -0
  63. package/dist/cli/dotenv.js +15 -2
  64. package/dist/cli/dotenv.js.map +1 -1
  65. package/dist/cli/launcher.js +5 -5
  66. package/dist/cli/launcher.js.map +1 -1
  67. package/dist/cli/main.d.ts +1 -0
  68. package/dist/cli/main.js +85 -0
  69. package/dist/cli/main.js.map +1 -0
  70. package/dist/cli/supervise.d.ts +2 -0
  71. package/dist/cli/supervise.js +67 -4
  72. package/dist/cli/supervise.js.map +1 -1
  73. package/dist/config/agent-config.d.ts +34 -11
  74. package/dist/config/agent-config.js +116 -60
  75. package/dist/config/agent-config.js.map +1 -1
  76. package/dist/config.d.ts +4 -0
  77. package/dist/config.js +19 -6
  78. package/dist/config.js.map +1 -1
  79. package/dist/fs/atomic.d.ts +1 -0
  80. package/dist/fs/atomic.js +4 -1
  81. package/dist/fs/atomic.js.map +1 -1
  82. package/dist/fs/stat.d.ts +1 -0
  83. package/dist/fs/stat.js +11 -0
  84. package/dist/fs/stat.js.map +1 -0
  85. package/dist/http/context.d.ts +31 -12
  86. package/dist/http/context.js +60 -24
  87. package/dist/http/context.js.map +1 -1
  88. package/dist/http/csp.d.ts +2 -1
  89. package/dist/http/csp.js +3 -2
  90. package/dist/http/csp.js.map +1 -1
  91. package/dist/onboarding.d.ts +2 -2
  92. package/dist/onboarding.js +10 -8
  93. package/dist/onboarding.js.map +1 -1
  94. package/dist/profiles/profiles.d.ts +20 -4
  95. package/dist/profiles/profiles.js +115 -30
  96. package/dist/profiles/profiles.js.map +1 -1
  97. package/dist/projects.d.ts +15 -6
  98. package/dist/projects.js +55 -47
  99. package/dist/projects.js.map +1 -1
  100. package/dist/providers/catalog.d.ts +84 -14
  101. package/dist/providers/catalog.js +474 -151
  102. package/dist/providers/catalog.js.map +1 -1
  103. package/dist/providers/env-file.d.ts +10 -3
  104. package/dist/providers/env-file.js +24 -75
  105. package/dist/providers/env-file.js.map +1 -1
  106. package/dist/providers/runtime-env.d.ts +4 -2
  107. package/dist/providers/runtime-env.js +9 -6
  108. package/dist/providers/runtime-env.js.map +1 -1
  109. package/dist/providers/tables.d.ts +3 -1
  110. package/dist/providers/tables.js +4 -2
  111. package/dist/providers/tables.js.map +1 -1
  112. package/dist/raster-image.d.ts +7 -0
  113. package/dist/raster-image.js +267 -0
  114. package/dist/raster-image.js.map +1 -0
  115. package/dist/redact.js +342 -46
  116. package/dist/redact.js.map +1 -1
  117. package/dist/release.d.ts +7 -0
  118. package/dist/release.js +14 -0
  119. package/dist/release.js.map +1 -1
  120. package/dist/runtime.d.ts +5 -1
  121. package/dist/runtime.js +305 -96
  122. package/dist/runtime.js.map +1 -1
  123. package/dist/server.js +15 -0
  124. package/dist/server.js.map +1 -1
  125. package/dist/sessions/anchor.d.ts +9 -3
  126. package/dist/sessions/anchor.js +28 -36
  127. package/dist/sessions/anchor.js.map +1 -1
  128. package/dist/sessions/background-events.d.ts +2 -0
  129. package/dist/sessions/background-events.js +10 -0
  130. package/dist/sessions/background-events.js.map +1 -0
  131. package/dist/sessions/background-tasks.d.ts +26 -27
  132. package/dist/sessions/background-tasks.js +89 -97
  133. package/dist/sessions/background-tasks.js.map +1 -1
  134. package/dist/sessions/background-updates.d.ts +15 -8
  135. package/dist/sessions/background-updates.js +101 -25
  136. package/dist/sessions/background-updates.js.map +1 -1
  137. package/dist/sessions/cli-sessions.d.ts +27 -6
  138. package/dist/sessions/cli-sessions.js +152 -42
  139. package/dist/sessions/cli-sessions.js.map +1 -1
  140. package/dist/sessions/completions.d.ts +77 -9
  141. package/dist/sessions/completions.js +482 -45
  142. package/dist/sessions/completions.js.map +1 -1
  143. package/dist/sessions/compress.d.ts +8 -0
  144. package/dist/sessions/compress.js +2 -2
  145. package/dist/sessions/compress.js.map +1 -1
  146. package/dist/sessions/drafts.d.ts +14 -10
  147. package/dist/sessions/drafts.js +38 -43
  148. package/dist/sessions/drafts.js.map +1 -1
  149. package/dist/sessions/export.d.ts +5 -0
  150. package/dist/sessions/export.js +30 -0
  151. package/dist/sessions/export.js.map +1 -1
  152. package/dist/sessions/gateway-sessions.d.ts +46 -0
  153. package/dist/sessions/gateway-sessions.js +378 -0
  154. package/dist/sessions/gateway-sessions.js.map +1 -0
  155. package/dist/sessions/gateway-watcher.d.ts +7 -3
  156. package/dist/sessions/gateway-watcher.js +31 -19
  157. package/dist/sessions/gateway-watcher.js.map +1 -1
  158. package/dist/sessions/goals.d.ts +31 -0
  159. package/dist/sessions/goals.js +75 -0
  160. package/dist/sessions/goals.js.map +1 -0
  161. package/dist/sessions/handoff.d.ts +32 -0
  162. package/dist/sessions/handoff.js +114 -0
  163. package/dist/sessions/handoff.js.map +1 -0
  164. package/dist/sessions/journal.d.ts +5 -79
  165. package/dist/sessions/journal.js +15 -606
  166. package/dist/sessions/journal.js.map +1 -1
  167. package/dist/sessions/list.d.ts +31 -16
  168. package/dist/sessions/list.js +139 -129
  169. package/dist/sessions/list.js.map +1 -1
  170. package/dist/sessions/merge.d.ts +69 -13
  171. package/dist/sessions/merge.js +265 -64
  172. package/dist/sessions/merge.js.map +1 -1
  173. package/dist/sessions/notices.d.ts +22 -0
  174. package/dist/sessions/notices.js +72 -0
  175. package/dist/sessions/notices.js.map +1 -0
  176. package/dist/sessions/pending.d.ts +10 -4
  177. package/dist/sessions/pending.js +83 -7
  178. package/dist/sessions/pending.js.map +1 -1
  179. package/dist/sessions/prefix-index.d.ts +82 -0
  180. package/dist/sessions/prefix-index.js +232 -0
  181. package/dist/sessions/prefix-index.js.map +1 -0
  182. package/dist/sessions/recovery.d.ts +19 -0
  183. package/dist/sessions/recovery.js +322 -0
  184. package/dist/sessions/recovery.js.map +1 -0
  185. package/dist/sessions/relay.d.ts +38 -19
  186. package/dist/sessions/relay.js +302 -79
  187. package/dist/sessions/relay.js.map +1 -1
  188. package/dist/sessions/service.d.ts +260 -55
  189. package/dist/sessions/service.js +1448 -462
  190. package/dist/sessions/service.js.map +1 -1
  191. package/dist/sessions/session.d.ts +24 -2
  192. package/dist/sessions/session.js +69 -7
  193. package/dist/sessions/session.js.map +1 -1
  194. package/dist/sessions/shares.d.ts +7 -6
  195. package/dist/sessions/shares.js +22 -45
  196. package/dist/sessions/shares.js.map +1 -1
  197. package/dist/sessions/source-kind.js +1 -0
  198. package/dist/sessions/source-kind.js.map +1 -1
  199. package/dist/sessions/state-db-identity.d.ts +18 -0
  200. package/dist/sessions/state-db-identity.js +67 -0
  201. package/dist/sessions/state-db-identity.js.map +1 -0
  202. package/dist/sessions/state-db-worker.d.ts +1 -0
  203. package/dist/sessions/state-db-worker.js +35 -0
  204. package/dist/sessions/state-db-worker.js.map +1 -0
  205. package/dist/sessions/state-db.d.ts +113 -7
  206. package/dist/sessions/state-db.js +861 -44
  207. package/dist/sessions/state-db.js.map +1 -1
  208. package/dist/sessions/storage/backend.d.ts +162 -0
  209. package/dist/sessions/storage/backend.js +19 -0
  210. package/dist/sessions/storage/backend.js.map +1 -0
  211. package/dist/sessions/storage/conformance.d.ts +20 -0
  212. package/dist/sessions/storage/conformance.js +237 -0
  213. package/dist/sessions/storage/conformance.js.map +1 -0
  214. package/dist/sessions/storage/document.d.ts +16 -0
  215. package/dist/sessions/storage/document.js +44 -0
  216. package/dist/sessions/storage/document.js.map +1 -0
  217. package/dist/sessions/storage/json-documents.d.ts +23 -0
  218. package/dist/sessions/storage/json-documents.js +233 -0
  219. package/dist/sessions/storage/json-documents.js.map +1 -0
  220. package/dist/sessions/storage/json-files.d.ts +12 -0
  221. package/dist/sessions/storage/json-files.js +124 -0
  222. package/dist/sessions/storage/json-files.js.map +1 -0
  223. package/dist/sessions/storage/json-installation.d.ts +3 -0
  224. package/dist/sessions/storage/json-installation.js +31 -0
  225. package/dist/sessions/storage/json-installation.js.map +1 -0
  226. package/dist/sessions/storage/json-journal.d.ts +114 -0
  227. package/dist/sessions/storage/json-journal.js +686 -0
  228. package/dist/sessions/storage/json-journal.js.map +1 -0
  229. package/dist/sessions/storage/json-recovery.d.ts +4 -0
  230. package/dist/sessions/storage/json-recovery.js +195 -0
  231. package/dist/sessions/storage/json-recovery.js.map +1 -0
  232. package/dist/sessions/storage/json.d.ts +68 -0
  233. package/dist/sessions/storage/json.js +258 -0
  234. package/dist/sessions/storage/json.js.map +1 -0
  235. package/dist/sessions/storage/row.d.ts +6 -0
  236. package/dist/sessions/storage/row.js +49 -0
  237. package/dist/sessions/storage/row.js.map +1 -0
  238. package/dist/sessions/storage/search-text.d.ts +4 -0
  239. package/dist/sessions/storage/search-text.js +16 -0
  240. package/dist/sessions/storage/search-text.js.map +1 -0
  241. package/dist/sessions/store.d.ts +65 -68
  242. package/dist/sessions/store.js +305 -602
  243. package/dist/sessions/store.js.map +1 -1
  244. package/dist/sessions/streams.d.ts +4 -0
  245. package/dist/sessions/streams.js +9 -1
  246. package/dist/sessions/streams.js.map +1 -1
  247. package/dist/sessions/titles.d.ts +2 -0
  248. package/dist/sessions/titles.js +5 -1
  249. package/dist/sessions/titles.js.map +1 -1
  250. package/dist/sessions/todo.d.ts +5 -0
  251. package/dist/sessions/todo.js +28 -21
  252. package/dist/sessions/todo.js.map +1 -1
  253. package/dist/sessions/tool-display.d.ts +5 -4
  254. package/dist/sessions/tool-display.js +30 -50
  255. package/dist/sessions/tool-display.js.map +1 -1
  256. package/dist/sessions/turn-context.d.ts +11 -2
  257. package/dist/sessions/turn-context.js +18 -11
  258. package/dist/sessions/turn-context.js.map +1 -1
  259. package/dist/sessions/turn.d.ts +122 -17
  260. package/dist/sessions/turn.js +939 -358
  261. package/dist/sessions/turn.js.map +1 -1
  262. package/dist/sessions/wakeup-pause.d.ts +54 -0
  263. package/dist/sessions/wakeup-pause.js +163 -0
  264. package/dist/sessions/wakeup-pause.js.map +1 -0
  265. package/dist/sessions/window.js +13 -12
  266. package/dist/sessions/window.js.map +1 -1
  267. package/dist/settings.d.ts +19 -7
  268. package/dist/settings.js +178 -184
  269. package/dist/settings.js.map +1 -1
  270. package/dist/sidecar/client.d.ts +17 -3
  271. package/dist/sidecar/client.js +78 -8
  272. package/dist/sidecar/client.js.map +1 -1
  273. package/dist/sidecar/discover.d.ts +2 -1
  274. package/dist/sidecar/discover.js +93 -10
  275. package/dist/sidecar/discover.js.map +1 -1
  276. package/dist/sidecar/env.d.ts +4 -0
  277. package/dist/sidecar/env.js +3 -0
  278. package/dist/sidecar/env.js.map +1 -0
  279. package/dist/sidecar/fake.d.ts +2 -2
  280. package/dist/sidecar/fake.js +19 -2
  281. package/dist/sidecar/fake.js.map +1 -1
  282. package/dist/startup.d.ts +13 -5
  283. package/dist/startup.js +48 -0
  284. package/dist/startup.js.map +1 -1
  285. package/dist/test/env-file.d.ts +5 -0
  286. package/dist/test/env-file.js +88 -0
  287. package/dist/test/env-file.js.map +1 -0
  288. package/dist/test/harness.d.ts +1 -0
  289. package/dist/test/harness.js +1 -1
  290. package/dist/test/harness.js.map +1 -1
  291. package/dist/test/passkeys.d.ts +22 -0
  292. package/dist/test/passkeys.js +62 -0
  293. package/dist/test/passkeys.js.map +1 -0
  294. package/dist/test/storage.d.ts +15 -0
  295. package/dist/test/storage.js +26 -0
  296. package/dist/test/storage.js.map +1 -0
  297. package/dist/test/ts-worker-hooks.d.ts +1 -0
  298. package/dist/test/ts-worker-hooks.js +24 -0
  299. package/dist/test/ts-worker-hooks.js.map +1 -0
  300. package/dist/text/diff.d.ts +9 -14
  301. package/dist/text/diff.js +74 -108
  302. package/dist/text/diff.js.map +1 -1
  303. package/dist/tools/commands.d.ts +6 -1
  304. package/dist/tools/commands.js +8 -2
  305. package/dist/tools/commands.js.map +1 -1
  306. package/dist/tools/connectors.d.ts +33 -0
  307. package/dist/tools/connectors.js +121 -0
  308. package/dist/tools/connectors.js.map +1 -0
  309. package/dist/tools/crons.d.ts +38 -1
  310. package/dist/tools/crons.js +122 -18
  311. package/dist/tools/crons.js.map +1 -1
  312. package/dist/tools/dashboard-plugins.d.ts +53 -0
  313. package/dist/tools/dashboard-plugins.js +188 -0
  314. package/dist/tools/dashboard-plugins.js.map +1 -0
  315. package/dist/tools/extensions.d.ts +18 -5
  316. package/dist/tools/extensions.js +344 -266
  317. package/dist/tools/extensions.js.map +1 -1
  318. package/dist/tools/gateway-restart.d.ts +62 -0
  319. package/dist/tools/gateway-restart.js +142 -0
  320. package/dist/tools/gateway-restart.js.map +1 -0
  321. package/dist/tools/health.d.ts +44 -0
  322. package/dist/tools/health.js +201 -46
  323. package/dist/tools/health.js.map +1 -1
  324. package/dist/tools/hygiene.d.ts +4 -3
  325. package/dist/tools/hygiene.js +23 -9
  326. package/dist/tools/hygiene.js.map +1 -1
  327. package/dist/tools/kanban.d.ts +4 -2
  328. package/dist/tools/kanban.js +28 -19
  329. package/dist/tools/kanban.js.map +1 -1
  330. package/dist/tools/mcp.d.ts +13 -0
  331. package/dist/tools/mcp.js +88 -0
  332. package/dist/tools/mcp.js.map +1 -1
  333. package/dist/tools/memory-masks.d.ts +5 -0
  334. package/dist/tools/memory-masks.js +256 -0
  335. package/dist/tools/memory-masks.js.map +1 -0
  336. package/dist/tools/memory.d.ts +29 -3
  337. package/dist/tools/memory.js +69 -27
  338. package/dist/tools/memory.js.map +1 -1
  339. package/dist/tools/plugin-settings.d.ts +15 -0
  340. package/dist/tools/plugin-settings.js +90 -0
  341. package/dist/tools/plugin-settings.js.map +1 -0
  342. package/dist/tools/project-os.d.ts +11 -0
  343. package/dist/tools/project-os.js +267 -0
  344. package/dist/tools/project-os.js.map +1 -0
  345. package/dist/tools/skills.d.ts +14 -5
  346. package/dist/tools/skills.js +49 -16
  347. package/dist/tools/skills.js.map +1 -1
  348. package/dist/tools/update-notifications.d.ts +34 -15
  349. package/dist/tools/update-notifications.js +141 -57
  350. package/dist/tools/update-notifications.js.map +1 -1
  351. package/dist/tools/update-rollback.d.ts +11 -0
  352. package/dist/tools/update-rollback.js +28 -0
  353. package/dist/tools/update-rollback.js.map +1 -0
  354. package/dist/tools/updates.d.ts +110 -32
  355. package/dist/tools/updates.js +1112 -294
  356. package/dist/tools/updates.js.map +1 -1
  357. package/dist/tools/wiki.d.ts +68 -0
  358. package/dist/tools/wiki.js +413 -0
  359. package/dist/tools/wiki.js.map +1 -0
  360. package/dist/util.d.ts +2 -0
  361. package/dist/util.js +5 -0
  362. package/dist/util.js.map +1 -1
  363. package/dist/workspace/escape.d.ts +61 -0
  364. package/dist/workspace/escape.js +149 -0
  365. package/dist/workspace/escape.js.map +1 -0
  366. package/dist/workspace/extract.d.ts +22 -0
  367. package/dist/workspace/extract.js +308 -0
  368. package/dist/workspace/extract.js.map +1 -0
  369. package/dist/workspace/fs.d.ts +12 -0
  370. package/dist/workspace/fs.js +92 -23
  371. package/dist/workspace/fs.js.map +1 -1
  372. package/dist/workspace/git.d.ts +34 -1
  373. package/dist/workspace/git.js +328 -35
  374. package/dist/workspace/git.js.map +1 -1
  375. package/dist/workspace/media.d.ts +16 -13
  376. package/dist/workspace/media.js +43 -61
  377. package/dist/workspace/media.js.map +1 -1
  378. package/dist/workspace/rollback.d.ts +36 -22
  379. package/dist/workspace/rollback.js +178 -272
  380. package/dist/workspace/rollback.js.map +1 -1
  381. package/dist/workspace/unzip.js +4 -1
  382. package/dist/workspace/unzip.js.map +1 -1
  383. package/dist/workspace/upload.d.ts +7 -4
  384. package/dist/workspace/upload.js +5 -2
  385. package/dist/workspace/upload.js.map +1 -1
  386. package/dist/workspace/workspaces.d.ts +15 -19
  387. package/dist/workspace/workspaces.js +55 -127
  388. package/dist/workspace/workspaces.js.map +1 -1
  389. package/dist/workspace/worktrees.d.ts +2 -1
  390. package/dist/workspace/worktrees.js +179 -42
  391. package/dist/workspace/worktrees.js.map +1 -1
  392. package/package.json +7 -3
  393. package/sidecar/agent_dependency.json +4 -4
  394. package/sidecar/agent_support.json +26 -0
  395. package/sidecar/scripts/record-fixtures.py +12 -3
  396. package/sidecar/scripts/replay_sidecar.py +32 -0
  397. package/sidecar/scripts/suite_runner.py +302 -0
  398. package/sidecar/scripts/test.sh +12 -4
  399. package/sidecar/talaria_sidecar/__init__.py +6 -1
  400. package/sidecar/talaria_sidecar/__main__.py +4 -2
  401. package/sidecar/talaria_sidecar/agent_mutation.py +975 -0
  402. package/sidecar/talaria_sidecar/agent_services.py +1053 -0
  403. package/sidecar/talaria_sidecar/dependency_sync.py +85 -0
  404. package/sidecar/talaria_sidecar/home.py +56 -3
  405. package/sidecar/talaria_sidecar/methods/__init__.py +2 -2
  406. package/sidecar/talaria_sidecar/methods/aux.py +166 -24
  407. package/sidecar/talaria_sidecar/methods/chat.py +852 -135
  408. package/sidecar/talaria_sidecar/methods/checkpoints.py +89 -0
  409. package/sidecar/talaria_sidecar/methods/commands.py +294 -4
  410. package/sidecar/talaria_sidecar/methods/config.py +123 -4
  411. package/sidecar/talaria_sidecar/methods/connectors.py +343 -0
  412. package/sidecar/talaria_sidecar/methods/cron.py +395 -36
  413. package/sidecar/talaria_sidecar/methods/cron_execution.py +284 -0
  414. package/sidecar/talaria_sidecar/methods/gateway.py +212 -55
  415. package/sidecar/talaria_sidecar/methods/gateway_sessions.py +234 -0
  416. package/sidecar/talaria_sidecar/methods/goals.py +81 -41
  417. package/sidecar/talaria_sidecar/methods/kanban.py +108 -34
  418. package/sidecar/talaria_sidecar/methods/mcp.py +1 -1
  419. package/sidecar/talaria_sidecar/methods/memory.py +84 -0
  420. package/sidecar/talaria_sidecar/methods/oauth.py +5 -2
  421. package/sidecar/talaria_sidecar/methods/process.py +218 -15
  422. package/sidecar/talaria_sidecar/methods/profiles.py +121 -13
  423. package/sidecar/talaria_sidecar/methods/providers.py +217 -28
  424. package/sidecar/talaria_sidecar/methods/runtime.py +69 -1
  425. package/sidecar/talaria_sidecar/methods/skills.py +67 -4
  426. package/sidecar/talaria_sidecar/methods/state_db.py +316 -75
  427. package/sidecar/talaria_sidecar/methods/stt.py +159 -78
  428. package/sidecar/talaria_sidecar/methods/text.py +14 -1
  429. package/sidecar/talaria_sidecar/methods/toolsets.py +49 -0
  430. package/sidecar/talaria_sidecar/methods/usage.py +113 -14
  431. package/sidecar/talaria_sidecar/methods/worktree.py +26 -19
  432. package/sidecar/talaria_sidecar/methods/write_approval.py +181 -0
  433. package/sidecar/talaria_sidecar/rpc.py +45 -4
  434. package/sidecar/talaria_sidecar/runtime.py +98 -13
  435. package/sidecar/talaria_sidecar/speed.py +35 -0
  436. package/static/dist/FILES.txt +126 -126
  437. package/static/dist/assets/AppShell-cey33v9s.js +8 -0
  438. package/static/dist/assets/ChatPage-i8wnugr7.js +18 -0
  439. package/static/dist/assets/ConnectTargets-hg19553x.js +1 -0
  440. package/static/dist/assets/ExtensionRoute-cly4apm5.js +1 -0
  441. package/static/dist/assets/Field-j8uqoigz.js +9 -0
  442. package/static/dist/assets/HubRoute-e4bgz41j.js +2 -0
  443. package/static/dist/assets/Markdown-lahuichm.js +598 -0
  444. package/static/dist/assets/RightPanel-lbo4i0fn.js +1 -0
  445. package/static/dist/assets/Select-gqatm2e0.js +1 -0
  446. package/static/dist/assets/SessionListPanel-mfqayfjh.js +1 -0
  447. package/static/dist/assets/SettingsLayout-b8980u7k.js +1 -0
  448. package/static/dist/assets/States-e7dkgtxf.js +1 -0
  449. package/static/dist/assets/Toaster-bfqqy786.js +1 -0
  450. package/static/dist/assets/_app-n1n6pfx1.js +1 -0
  451. package/static/dist/assets/{_app.ext._extensionId-opyh9y0v.js → _app.ext._extensionId-buxjxav3.js} +1 -1
  452. package/static/dist/assets/_app.index-jt8zwiu2.js +1 -0
  453. package/static/dist/assets/_app.insights-cv76ml71.js +1 -0
  454. package/static/dist/assets/_app.kanban-h6ts53j7.js +1 -0
  455. package/static/dist/assets/_app.logs-dm873z90.js +1 -0
  456. package/static/dist/assets/_app.memory-glk5y6m8.js +1 -0
  457. package/static/dist/assets/_app.profiles-ka6zpstq.js +1 -0
  458. package/static/dist/assets/{_app.session._sessionId-bfd4h3id.js → _app.session._sessionId-g2vzghvc.js} +1 -1
  459. package/static/dist/assets/_app.settings-hgjdhzcd.js +1 -0
  460. package/static/dist/assets/_app.settings._section-jf2kmhae.js +3 -0
  461. package/static/dist/assets/_app.skills-cii852yq.js +1 -0
  462. package/static/dist/assets/_app.tasks-fp9q7atm.js +1 -0
  463. package/static/dist/assets/_app.todos-dw94qzue.js +1 -0
  464. package/static/dist/assets/_app.workspaces-inyygzze.js +1 -0
  465. package/static/dist/assets/{abnfDiagram-VCTEODGH-b2x1lqot.js → abnfDiagram-VCTEODGH-gjayq3ra.js} +1 -1
  466. package/static/dist/assets/architecture-7GRP2DOG-lp56972r.js +1 -0
  467. package/static/dist/assets/{architectureDiagram-5GKGNRK7-h38o5l7b.js → architectureDiagram-5GKGNRK7-nwb3xovn.js} +1 -1
  468. package/static/dist/assets/archive-b1j004vn.js +1 -0
  469. package/static/dist/assets/back-g74gkozu.js +1 -0
  470. package/static/dist/assets/{blockDiagram-I7D4REHJ-bqquxv2u.js → blockDiagram-I7D4REHJ-joedghi3.js} +1 -1
  471. package/static/dist/assets/{c4Diagram-7LVT6UL2-f3fb8w6z.js → c4Diagram-7LVT6UL2-hyrjrohe.js} +1 -1
  472. package/static/dist/assets/channel-es95o4y8.js +1 -0
  473. package/static/dist/assets/{chunk-4HAMMTFA-bzfyyzp3.js → chunk-4HAMMTFA-koouqbut.js} +1 -1
  474. package/static/dist/assets/{chunk-75Z2AOVW-ly99rfx5.js → chunk-75Z2AOVW-bl4bhdnt.js} +1 -1
  475. package/static/dist/assets/{chunk-DU6HZSFF-bg6ecfqf.js → chunk-DU6HZSFF-gpedttsp.js} +3 -3
  476. package/static/dist/assets/{chunk-F27PBJKO-e8k7mmqw.js → chunk-F27PBJKO-d8xxi0zi.js} +1 -1
  477. package/static/dist/assets/{chunk-GMAD6QVW-cmalnoaj.js → chunk-GMAD6QVW-jro0hl73.js} +1 -1
  478. package/static/dist/assets/{chunk-GVQU2GXP-gmif5o01.js → chunk-GVQU2GXP-djn6gbyu.js} +1 -1
  479. package/static/dist/assets/{chunk-IMKFNOWR-f1nwwh6u.js → chunk-IMKFNOWR-vw4p5p7o.js} +1 -1
  480. package/static/dist/assets/{chunk-L3NEJ4N5-oktfh5v7.js → chunk-L3NEJ4N5-n1hj77q8.js} +1 -1
  481. package/static/dist/assets/{chunk-OSK3NFVY-b1sdx96z.js → chunk-OSK3NFVY-oy0gwn2n.js} +1 -1
  482. package/static/dist/assets/{chunk-P2QGCYS3-fhu4nzxt.js → chunk-P2QGCYS3-onf1hz6c.js} +1 -1
  483. package/static/dist/assets/{chunk-POPQ4Y6H-em31rnef.js → chunk-POPQ4Y6H-m8sqn7cs.js} +1 -1
  484. package/static/dist/assets/{chunk-PWAF6VOD-bxhhyftw.js → chunk-PWAF6VOD-ek4smc8x.js} +1 -1
  485. package/static/dist/assets/{chunk-SHT3W25Y-fmrvwcav.js → chunk-SHT3W25Y-g9gfvefo.js} +3 -3
  486. package/static/dist/assets/{chunk-SVP7TREG-lymukl2j.js → chunk-SVP7TREG-f9nfv2cu.js} +1 -1
  487. package/static/dist/assets/{chunk-TICWLB2K-lmza6k23.js → chunk-TICWLB2K-bnk3m1mq.js} +1 -1
  488. package/static/dist/assets/classDiagram-ZZMXUADV-kmihoqxh.js +1 -0
  489. package/static/dist/assets/classDiagram-v2-VYDZK3BY-kmihoqxh.js +1 -0
  490. package/static/dist/assets/copied-bli9tbcx.js +1 -0
  491. package/static/dist/assets/{copy-fw5b1pc6.js → copy-jamtd1pf.js} +1 -1
  492. package/static/dist/assets/{cynefin-OW5HDTMX-czlhbyhs.js → cynefin-OW5HDTMX-f8xfdd3f.js} +1 -1
  493. package/static/dist/assets/{cynefinDiagram-5FMLGOSQ-gq7mvswb.js → cynefinDiagram-5FMLGOSQ-n9lb99h9.js} +1 -1
  494. package/static/dist/assets/{dagre-GXQ25YYZ-cqdbf7dr.js → dagre-GXQ25YYZ-dgailddi.js} +4 -4
  495. package/static/dist/assets/{diagram-S7CK7UJ4-o6arxa58.js → diagram-S7CK7UJ4-m6aeoe7c.js} +1 -1
  496. package/static/dist/assets/{diagram-UQ7AKVKN-nhnd68tz.js → diagram-UQ7AKVKN-jall3j0x.js} +1 -1
  497. package/static/dist/assets/{diagram-VSXAHHWV-dk2sclzn.js → diagram-VSXAHHWV-hbawi7hn.js} +1 -1
  498. package/static/dist/assets/{diagram-VX7I27RA-n3k5nyx3.js → diagram-VX7I27RA-hendl2tt.js} +1 -1
  499. package/static/dist/assets/{diagram-Z3DM3KII-m6q9cwdh.js → diagram-Z3DM3KII-igwc35p3.js} +1 -1
  500. package/static/dist/assets/{ebnfDiagram-PWID7BFC-lsa5641p.js → ebnfDiagram-PWID7BFC-c64knz08.js} +1 -1
  501. package/static/dist/assets/{erDiagram-RLTQ6QDP-fo2ckbe6.js → erDiagram-RLTQ6QDP-brdu9lcm.js} +1 -1
  502. package/static/dist/assets/eventmodeling-NTZA5JFV-njk1j8wl.js +1 -0
  503. package/static/dist/assets/flowDiagram-HODETNUW-nma6f0ga.js +1 -0
  504. package/static/dist/assets/folder-plus-lvt9kudb.js +1 -0
  505. package/static/dist/assets/{ganttDiagram-EL5Y4UJY-nzqz6x9g.js → ganttDiagram-EL5Y4UJY-ma6jxj5i.js} +1 -1
  506. package/static/dist/assets/{gitGraph-4MIJSDKK-gukvcxe6.js → gitGraph-4MIJSDKK-naa9w6xa.js} +1 -1
  507. package/static/dist/assets/{gitGraphDiagram-WWUBYQGX-lqhdp8f0.js → gitGraphDiagram-WWUBYQGX-hzltvsod.js} +1 -1
  508. package/static/dist/assets/{highlighted-body-KPVGNVTW-igw6cp39.js → highlighted-body-KPVGNVTW-ghoavj8d.js} +1 -1
  509. package/static/dist/assets/host-hzm8n85n.js +1 -0
  510. package/static/dist/assets/index-drdcaqeq.css +2 -0
  511. package/static/dist/assets/index-jzm844he.js +11 -0
  512. package/static/dist/assets/{info-A6RAGUB7-gvu7a93l.js → info-A6RAGUB7-mn2ut5ko.js} +1 -1
  513. package/static/dist/assets/{infoDiagram-27XIBGKW-m8t8g6w1.js → infoDiagram-27XIBGKW-h6kuqvsb.js} +1 -1
  514. package/static/dist/assets/{ishikawaDiagram-5VMMS53U-l07vkbgj.js → ishikawaDiagram-5VMMS53U-e7bnwq7h.js} +1 -1
  515. package/static/dist/assets/{journeyDiagram-3NMN7TZE-hybkgj8l.js → journeyDiagram-3NMN7TZE-etd1bi6p.js} +1 -1
  516. package/static/dist/assets/{kanban-definition-UXKFOSKX-by13uvtn.js → kanban-definition-UXKFOSKX-emb1g9dz.js} +4 -4
  517. package/static/dist/assets/lazyRouteComponent-o816ytzl.js +1 -0
  518. package/static/dist/assets/{line-osxq6fq7.js → line-h0ojzsvs.js} +1 -1
  519. package/static/dist/assets/link-k01ryaf9.js +1 -0
  520. package/static/dist/assets/login-bsae49ew.js +1 -0
  521. package/static/dist/assets/mermaid-HWGCJPDP-ihl34s74.js +1 -0
  522. package/static/dist/assets/{mermaid-parser.core-i91oxmou.js → mermaid-parser.core-bnre27u8.js} +3 -3
  523. package/static/dist/assets/{mindmap-definition-YA3MSWOX-m82mx8ww.js → mindmap-definition-YA3MSWOX-o1vathns.js} +1 -1
  524. package/static/dist/assets/onboarding-c65tysya.js +1 -0
  525. package/static/dist/assets/onboarding_model_label-gpn28uix.js +1 -0
  526. package/static/dist/assets/{packet-AYTQ26CC-nbtgge2o.js → packet-AYTQ26CC-hatq7m2e.js} +1 -1
  527. package/static/dist/assets/pcmTap.worklet-74EKjWAZ.js +1 -0
  528. package/static/dist/assets/{pegDiagram-XKGWAZYB-f1zxzga1.js → pegDiagram-XKGWAZYB-gwisz8jv.js} +1 -1
  529. package/static/dist/assets/{pie-WAS4IAKB-of8vuhxs.js → pie-WAS4IAKB-fpftf0mk.js} +1 -1
  530. package/static/dist/assets/{pieDiagram-E7YTZNPT-o7y8ftio.js → pieDiagram-E7YTZNPT-khm1o9a6.js} +1 -1
  531. package/static/dist/assets/{quadrantDiagram-AXDQQJYC-iqiwia1t.js → quadrantDiagram-AXDQQJYC-owqc4uqn.js} +1 -1
  532. package/static/dist/assets/{radar-RG4KPBEZ-delnsy2v.js → radar-RG4KPBEZ-cntfwjpq.js} +1 -1
  533. package/static/dist/assets/{railroad-74A4TZTK-nspnyq9u.js → railroad-74A4TZTK-a7t5eibp.js} +1 -1
  534. package/static/dist/assets/railroad-abnf-HS5TGJTU-ol8cdktf.js +1 -0
  535. package/static/dist/assets/railroad-ebnf-LZEXJU2U-i8vzd429.js +1 -0
  536. package/static/dist/assets/railroad-peg-WCYAUIDC-nw3ulewz.js +1 -0
  537. package/static/dist/assets/{railroadDiagram-O6MQD6OU-z41tqx5z.js → railroadDiagram-O6MQD6OU-etuh0qa0.js} +1 -1
  538. package/static/dist/assets/{refresh-cw-nt1dtsx4.js → refresh-cw-mqbkv2a3.js} +1 -1
  539. package/static/dist/assets/refresh-l29ljp76.js +1 -0
  540. package/static/dist/assets/{requirementDiagram-BXWQKSXE-bdvif194.js → requirementDiagram-BXWQKSXE-oq2ulk22.js} +1 -1
  541. package/static/dist/assets/{sankeyDiagram-P5KCCOFB-h73e0rol.js → sankeyDiagram-P5KCCOFB-iqc02emv.js} +1 -1
  542. package/static/dist/assets/saved-ndd4t2xb.js +1 -0
  543. package/static/dist/assets/{sequenceDiagram-WJ2MYXX4-iv95mb1z.js → sequenceDiagram-WJ2MYXX4-i0v116q0.js} +2 -2
  544. package/static/dist/assets/settings_section_extensions_title-jhfo6o8z.js +1 -0
  545. package/static/dist/assets/share._token-c1ri0hy1.js +2 -0
  546. package/static/dist/assets/sliders-horizontal-j3jjt9tv.js +1 -0
  547. package/static/dist/assets/{stateDiagram-D77RDMKH-k417ixmf.js → stateDiagram-D77RDMKH-dnpt1ato.js} +1 -1
  548. package/static/dist/assets/stateDiagram-v2-MP3YSRHH-bxjacpk6.js +1 -0
  549. package/static/dist/assets/{swimlanes-42K2YHIH-esola70w.js → swimlanes-42K2YHIH-loqbdazb.js} +1 -1
  550. package/static/dist/assets/swimlanesDiagram-VR7AAH4N-id62p9hz.js +8 -0
  551. package/static/dist/assets/{timeline-definition-24CTP7MA-getrz2y8.js → timeline-definition-24CTP7MA-ol2hnvma.js} +1 -1
  552. package/static/dist/assets/toast-i3h34v6o.js +64 -0
  553. package/static/dist/assets/{treeView-Q6P3EWNA-hc7ap1q7.js → treeView-Q6P3EWNA-idrj6iox.js} +1 -1
  554. package/static/dist/assets/{treemap-WGGIJYW6-b7k1syy5.js → treemap-WGGIJYW6-lzr49vv5.js} +1 -1
  555. package/static/dist/assets/untitled-oaoya4qj.js +1 -0
  556. package/static/dist/assets/useForm-nfaxgmsk.js +1 -0
  557. package/static/dist/assets/{useParams-lhg566ew.js → useParams-gjc70qru.js} +1 -1
  558. package/static/dist/assets/{useSearch-lbrh6ejn.js → useSearch-e6ae539u.js} +1 -1
  559. package/static/dist/assets/{vennDiagram-4TSXK5OY-n6pcy5qb.js → vennDiagram-4TSXK5OY-bvwr9o2z.js} +1 -1
  560. package/static/dist/assets/{wardley-WFR3VGLG-lpa18vz1.js → wardley-WFR3VGLG-31ui8tma.js} +1 -1
  561. package/static/dist/assets/{wardleyDiagram-VM6X3IG4-kpclwwg7.js → wardleyDiagram-VM6X3IG4-k5wqtx4b.js} +1 -1
  562. package/static/dist/assets/{xychartDiagram-S5SC5T6Z-paa2n8y0.js → xychartDiagram-S5SC5T6Z-aqbgvujg.js} +1 -1
  563. package/static/dist/index.html +1 -1
  564. package/static/dist/sw.js +1 -1
  565. package/static/dist/assets/AppShell-fb2td9zi.js +0 -1
  566. package/static/dist/assets/ChatPage-cj96kiy9.js +0 -25
  567. package/static/dist/assets/Dialog-kxcg7ard.js +0 -1
  568. package/static/dist/assets/ExtensionRoute-jf7h0754.js +0 -1
  569. package/static/dist/assets/HubRoute-gmanpd5y.js +0 -2
  570. package/static/dist/assets/Markdown-mdwlvj3w.js +0 -598
  571. package/static/dist/assets/RightPanel-ftvrjlcp.js +0 -1
  572. package/static/dist/assets/Select-bilaypej.js +0 -1
  573. package/static/dist/assets/SessionListPanel-og8n36qs.js +0 -1
  574. package/static/dist/assets/SettingsLayout-jonjefmj.js +0 -1
  575. package/static/dist/assets/States-nmejrwrm.js +0 -1
  576. package/static/dist/assets/Toaster-nnl8zkt9.js +0 -1
  577. package/static/dist/assets/_app-gdidzd94.js +0 -1
  578. package/static/dist/assets/_app.index-hbarzbjx.js +0 -1
  579. package/static/dist/assets/_app.insights-luywlarz.js +0 -1
  580. package/static/dist/assets/_app.kanban-kincnbr8.js +0 -1
  581. package/static/dist/assets/_app.logs-oi2gr3gs.js +0 -1
  582. package/static/dist/assets/_app.memory-b6jfivt6.js +0 -1
  583. package/static/dist/assets/_app.profiles-lpvixmqp.js +0 -1
  584. package/static/dist/assets/_app.settings-vowx3iq0.js +0 -1
  585. package/static/dist/assets/_app.settings._section-cnntg1tu.js +0 -3
  586. package/static/dist/assets/_app.skills-fb57lpau.js +0 -1
  587. package/static/dist/assets/_app.tasks-eszpx1q7.js +0 -2
  588. package/static/dist/assets/_app.todos-nr05ac6w.js +0 -1
  589. package/static/dist/assets/_app.workspaces-d2luomu6.js +0 -1
  590. package/static/dist/assets/architecture-7GRP2DOG-hd0o7bde.js +0 -1
  591. package/static/dist/assets/back-bemaer09.js +0 -1
  592. package/static/dist/assets/cancel-drd0g6d9.js +0 -1
  593. package/static/dist/assets/channel-cpdgf867.js +0 -1
  594. package/static/dist/assets/classDiagram-ZZMXUADV-ko09sguk.js +0 -1
  595. package/static/dist/assets/classDiagram-v2-VYDZK3BY-ko09sguk.js +0 -1
  596. package/static/dist/assets/copied-ima3pysb.js +0 -1
  597. package/static/dist/assets/endpoints-d33siokx.js +0 -64
  598. package/static/dist/assets/eventmodeling-NTZA5JFV-emctlo64.js +0 -1
  599. package/static/dist/assets/flowDiagram-HODETNUW-bfi3moqa.js +0 -1
  600. package/static/dist/assets/index-cxq58xb1.js +0 -11
  601. package/static/dist/assets/index-hgtx08n5.css +0 -2
  602. package/static/dist/assets/lazyRouteComponent-af0lvgjx.js +0 -1
  603. package/static/dist/assets/link-jyxicdhg.js +0 -1
  604. package/static/dist/assets/login-ec21t39x.js +0 -1
  605. package/static/dist/assets/mermaid-HWGCJPDP-gfl8z3ep.js +0 -1
  606. package/static/dist/assets/onboarding-btnltvyz.js +0 -1
  607. package/static/dist/assets/onboarding_model_label-dp7xffoh.js +0 -1
  608. package/static/dist/assets/railroad-abnf-HS5TGJTU-nst1qxyn.js +0 -1
  609. package/static/dist/assets/railroad-ebnf-LZEXJU2U-ci37x8qy.js +0 -1
  610. package/static/dist/assets/railroad-peg-WCYAUIDC-aimkk07z.js +0 -1
  611. package/static/dist/assets/refresh-b4uams1i.js +0 -1
  612. package/static/dist/assets/saved-kg52csy7.js +0 -1
  613. package/static/dist/assets/settings_section_extensions_title-ej0iapxe.js +0 -1
  614. package/static/dist/assets/share._token-f97e94r0.js +0 -2
  615. package/static/dist/assets/sliders-horizontal-fj18it47.js +0 -1
  616. package/static/dist/assets/sse-fwpqtzbg.js +0 -1
  617. package/static/dist/assets/stateDiagram-v2-MP3YSRHH-hwn4apct.js +0 -1
  618. package/static/dist/assets/swimlanesDiagram-VR7AAH4N-d1h97oyg.js +0 -8
  619. package/static/dist/assets/todoStore-eginf9h4.js +0 -1
  620. package/static/dist/assets/tts-lxdxnmjd.js +0 -1
  621. package/static/dist/assets/untitled-ovpfthg4.js +0 -1
  622. package/static/dist/assets/useForm-bcblv1rx.js +0 -1
  623. package/static/dist/assets/useLocale-fi5jb8ma.js +0 -1
@@ -0,0 +1,181 @@
1
+ """``write_approval.*``: the Agent's staged skill and memory writes (TAL-819).
2
+
3
+ With ``skills.write_approval`` or ``memory.write_approval`` on, the Agent stages writes under
4
+ ``<home>/pending/<kind>/<id>.json`` instead of committing them. These methods list them with
5
+ the diff an approval would apply, and approve or reject them through the Agent's own
6
+ ``/skills`` and ``/memory`` review handlers.
7
+ """
8
+
9
+ from __future__ import annotations
10
+
11
+ import contextlib
12
+ import difflib
13
+ import hashlib
14
+ import re
15
+ import tempfile
16
+ import threading
17
+ from pathlib import Path
18
+
19
+ from ..errors import InvalidParams, RpcError
20
+ from ..home import profile_home_param, scoped_home
21
+ from ..rpc import CallContext
22
+
23
+ KINDS = ("skills", "memory")
24
+ # The Agent names records ``uuid4().hex[:8]`` and builds their path from the id; anything else could leave the pending dir.
25
+ _ID = re.compile(r"[A-Za-z0-9_-]{1,64}")
26
+ # One review at a time in this process, so two approvals of one record cannot both replay it.
27
+ _LOCK = threading.Lock()
28
+
29
+
30
+ def _agent():
31
+ try:
32
+ from hermes_cli import write_approval_commands
33
+ from tools import write_approval
34
+ except ImportError as exc:
35
+ raise RpcError("This Hermes Agent cannot review staged writes", condition="write_approval_unavailable") from exc
36
+ return write_approval, write_approval_commands
37
+
38
+
39
+ def _kind(params: dict) -> str:
40
+ kind = str(params.get("kind") or "")
41
+ if kind not in KINDS:
42
+ raise InvalidParams("kind must be skills or memory")
43
+ return kind
44
+
45
+
46
+ def _memory_diff(payload: dict) -> str:
47
+ """Replay the record on a scratch copy of its file through the Agent's approve path; the diff is what approval commits."""
48
+ from tools.memory_tool import ENTRY_DELIMITER, apply_memory_pending, load_on_disk_store
49
+
50
+ store = load_on_disk_store()
51
+ target = "user" if payload.get("target") == "user" else "memory"
52
+ real = store._path_for(target)
53
+ before = list(store._entries_for(target))
54
+ with tempfile.TemporaryDirectory(prefix="talaria-pending-") as scratch:
55
+ copy = Path(scratch) / real.name
56
+ if real.is_file():
57
+ copy.write_bytes(real.read_bytes())
58
+ # The store resolves every read, lock and write through ``self._path_for``.
59
+ store._path_for = lambda t: Path(scratch) / ("USER.md" if t == "user" else "MEMORY.md")
60
+ result = apply_memory_pending(payload, store)
61
+ after = list(store._entries_for(target))
62
+ if not result.get("success"):
63
+ raise _Unapprovable(f"(approve would fail: {result.get('error') or 'unknown error'})")
64
+ lines = lambda entries: ENTRY_DELIMITER.join(entries).splitlines(keepends=True) # noqa: E731
65
+ diff = difflib.unified_diff(lines(before), lines(after), fromfile=f"a/{real.name}", tofile=f"b/{real.name}")
66
+ return "".join(diff) or "(no textual change)"
67
+
68
+
69
+ class _Unapprovable(Exception):
70
+ """A write with no diff the user could review: its message replaces the diff and approval is refused."""
71
+
72
+
73
+ def _skill_names(payload: dict) -> list[str]:
74
+ ops = payload.get("operations") or [] if payload.get("action") == "batch" else [payload]
75
+ return list(dict.fromkeys(str(op.get("name")) for op in ops if isinstance(op, dict) and op.get("name")))
76
+
77
+
78
+ def _item(wa, kind: str, record: dict) -> dict:
79
+ payload = record.get("payload") if isinstance(record.get("payload"), dict) else {}
80
+ if kind == "memory":
81
+ target = "user" if payload.get("target") == "user" else "memory"
82
+ else:
83
+ target = ", ".join(_skill_names(payload))
84
+ diff, approvable = _diff(wa, kind, record)
85
+ return {
86
+ "id": str(record.get("id") or ""), "kind": kind, "target": target, "op": str(payload.get("action") or record.get("action") or ""),
87
+ "summary": str(record.get("summary") or ""), "origin": str(record.get("origin") or "foreground"),
88
+ "created_at": float(record.get("created_at") or 0), "diff": diff,
89
+ "approvable": approvable, "revision": _revision(diff) if approvable else "",
90
+ }
91
+
92
+
93
+ def _diff(wa, kind: str, record: dict) -> tuple[str, bool]:
94
+ """The diff approving ``record`` applies and whether it may be approved; a diff that cannot be built is never approvable."""
95
+ payload = record.get("payload") if isinstance(record.get("payload"), dict) else {}
96
+ try:
97
+ return (_memory_diff(payload) if kind == "memory" else wa.skill_pending_diff(record)), True
98
+ except _Unapprovable as exc:
99
+ return str(exc), False
100
+ except Exception as exc: # noqa: BLE001 - one unreadable record must not hide the rest
101
+ return f"(diff unavailable: {exc})", False
102
+
103
+
104
+ def _apply_lock(kind: str, record: dict):
105
+ """Hold the Agent's own per-skill locks across the revision check and the apply (they are re-entrant in this thread, so
106
+ the Agent's apply takes them again). Memory needs none: the Agent applies a staged remove/patch only to the exact entry
107
+ it pinned at staging and an add only appends, so a concurrent write can never be dropped by an approval."""
108
+ if kind != "skills":
109
+ return contextlib.nullcontext()
110
+ from tools.skill_manager_tool import _skill_mutation_locks
111
+
112
+ return _skill_mutation_locks(_skill_names(record.get("payload") if isinstance(record.get("payload"), dict) else {}))
113
+
114
+
115
+ def _revision(diff: str) -> str:
116
+ """What the reviewer saw: the diff changes whenever the record or the file it applies to does."""
117
+ return hashlib.sha256(diff.encode("utf-8")).hexdigest()
118
+
119
+
120
+ def pending(kind: str) -> dict:
121
+ try:
122
+ wa, _ = _agent()
123
+ except RpcError:
124
+ return {"supported": False, "enabled": False, "items": []}
125
+ items = [_item(wa, kind, record) for record in wa.list_pending(kind) if _ID.fullmatch(str(record.get("id") or ""))]
126
+ return {"supported": True, "enabled": wa.write_approval_enabled(kind), "items": items}
127
+
128
+
129
+ def review(kind: str, verb: str, writes: list[dict]) -> dict:
130
+ """``approve`` or ``reject`` each write through the Agent's handler; a record that is gone afterwards was applied or dropped.
131
+
132
+ An approval applies only while the write's diff still has the ``revision`` the reviewer saw; a changed file or record
133
+ is refused, so nothing lands that the user did not review.
134
+ """
135
+ wa, commands = _agent()
136
+ if not writes or any(not (isinstance(w, dict) and _ID.fullmatch(str(w.get("id") or "")) and isinstance(w.get("revision"), str)) for w in writes):
137
+ raise InvalidParams("writes must be pending write ids with the revision reviewed")
138
+ results = []
139
+ with _LOCK:
140
+ for write in writes:
141
+ pending_id = write["id"]
142
+ record = wa.get_pending(kind, pending_id)
143
+ if record is None:
144
+ results.append({"id": pending_id, "done": False, "message": f"No pending {kind} write with id '{pending_id}'."})
145
+ continue
146
+ if verb == "reject":
147
+ message = commands.handle_pending_subcommand(kind, [verb, pending_id]) or ""
148
+ else:
149
+ with _apply_lock(kind, record):
150
+ diff, approvable = _diff(wa, kind, record)
151
+ if not approvable:
152
+ results.append({"id": pending_id, "done": False, "message": f"This write cannot be approved: {diff}"})
153
+ continue
154
+ if _revision(diff) != write["revision"]:
155
+ results.append({"id": pending_id, "done": False, "message": "This write's diff changed after you reviewed it. Review the new diff, then approve again."})
156
+ continue
157
+ store = None
158
+ if kind == "memory":
159
+ from tools.memory_tool import load_on_disk_store
160
+
161
+ store = load_on_disk_store()
162
+ message = commands.handle_pending_subcommand(kind, [verb, pending_id], memory_store=store) or ""
163
+ results.append({"id": pending_id, "done": wa.get_pending(kind, pending_id) is None, "message": message})
164
+ return {"results": results}
165
+
166
+
167
+ def register(registry) -> None:
168
+ @registry.method("write_approval.pending")
169
+ def pending_(ctx: CallContext, params: dict) -> dict:
170
+ kind = _kind(params)
171
+ with scoped_home(profile_home_param(params)):
172
+ return pending(kind)
173
+
174
+ for verb in ("approve", "reject"):
175
+ def handler(ctx: CallContext, params: dict, verb: str = verb) -> dict:
176
+ kind = _kind(params)
177
+ writes = list(params.get("writes") or [])
178
+ with scoped_home(profile_home_param(params)):
179
+ return review(kind, verb, writes)
180
+
181
+ registry.method(f"write_approval.{verb}")(handler)
@@ -13,6 +13,9 @@ from __future__ import annotations
13
13
 
14
14
  import json
15
15
  import logging
16
+ import os
17
+ import queue
18
+ import time
16
19
  import sys
17
20
  import threading
18
21
  import traceback
@@ -121,6 +124,9 @@ class RpcServer:
121
124
  def request_shutdown(self, exit_code: int = 0) -> None:
122
125
  self.exit_code = exit_code
123
126
  self._closed.set()
127
+ with self._active_lock:
128
+ for ctx in self._active.values():
129
+ ctx.cancel_event.set()
124
130
 
125
131
  # ── dispatch ──────────────────────────────────────────────────────────
126
132
  def _register(self, request: dict) -> CallContext | None:
@@ -182,12 +188,38 @@ class RpcServer:
182
188
 
183
189
  def serve_forever(self) -> int:
184
190
  """Read requests until stdin closes or shutdown is requested."""
185
- while not self._closed.is_set():
191
+ incoming = queue.Queue(maxsize=1)
192
+ def read_input():
186
193
  try:
187
- raw = self._in.readline()
194
+ try:
195
+ fd = self._in.fileno()
196
+ except (AttributeError, OSError, ValueError):
197
+ fd = None
198
+ if fd is None:
199
+ while raw := self._in.readline():
200
+ incoming.put(raw)
201
+ else:
202
+ # An unbuffered OS read cannot hold sys.stdin's Python buffer lock at interpreter exit.
203
+ pending = []
204
+ while chunk := os.read(fd, 65536):
205
+ lines = chunk.split(b"\n")
206
+ pending.append(lines[0])
207
+ for line in lines[1:]:
208
+ incoming.put(b"".join(pending))
209
+ pending = [line]
210
+ if pending:
211
+ incoming.put(b"".join(pending))
188
212
  except (OSError, ValueError):
189
- break
190
- if not raw:
213
+ pass
214
+ finally:
215
+ incoming.put(None)
216
+ threading.Thread(target=read_input, name="rpc-input", daemon=True).start()
217
+ while not self._closed.is_set():
218
+ try:
219
+ raw = incoming.get(timeout=.1)
220
+ except queue.Empty:
221
+ continue
222
+ if raw is None or self._closed.is_set():
191
223
  break
192
224
  raw = raw.strip()
193
225
  if not raw:
@@ -209,6 +241,15 @@ class RpcServer:
209
241
  continue
210
242
  ctx = self._register(request)
211
243
  threading.Thread(target=self._dispatch_slot, args=(request, ctx), name=f"rpc-{request.get('method')}", daemon=True).start()
244
+ if self._closed.is_set():
245
+ # Let the terminal reply reach stdout before the process returns its final exit code.
246
+ deadline = time.monotonic() + 5
247
+ while time.monotonic() < deadline:
248
+ with self._active_lock:
249
+ terminal_reply = any(ctx.method in {"runtime.shutdown", "runtime.handshake"} for ctx in self._active.values())
250
+ if not terminal_reply:
251
+ break
252
+ threading.Event().wait(.01)
212
253
  return self.exit_code
213
254
 
214
255
  def _dispatch_slot(self, request: dict, ctx: CallContext | None) -> None:
@@ -10,12 +10,15 @@ from __future__ import annotations
10
10
 
11
11
  import errno
12
12
  import importlib
13
+ import hashlib
13
14
  import json
14
15
  import math
15
16
  import os
17
+ import re
16
18
  import stat
17
19
  import subprocess
18
20
  import sys
21
+ import sysconfig
19
22
  import threading
20
23
  import time
21
24
  from pathlib import Path
@@ -24,11 +27,8 @@ from . import SIDECAR_RPC_VERSION
24
27
  from .errors import RpcError
25
28
 
26
29
  PIN_PATH = Path(__file__).resolve().parent.parent / "agent_dependency.json"
27
- _RESTART_REQUIRED_MESSAGE = (
28
- "Hermes Agent was updated while Talaria Web was running. "
29
- "Talaria Web cannot verify that the Agent update completed safely. "
30
- "Check the Agent update outcome and environment first. "
31
- "Restart Talaria Web manually before retrying this action."
30
+ _RUNTIME_UNAVAILABLE_MESSAGE = (
31
+ "Agent runtime is unavailable. Check the Agent update outcome before retrying this action."
32
32
  )
33
33
  _AGENT_UPDATE_MARKER = ".hermes-update-in-progress"
34
34
  _AGENT_RECOVERY_MARKERS = (".update-incomplete", ".lazy-refresh-incomplete")
@@ -40,11 +40,16 @@ _MARKER_SAFE_OPEN_AVAILABLE = bool(_O_NOFOLLOW) and bool(_O_NONBLOCK)
40
40
 
41
41
 
42
42
  class AgentRuntimeStale(RpcError):
43
- def __init__(self, update_state: str | None):
44
- data = {"retryable": True, "restart_scheduled": False}
43
+ def __init__(self, update_state: str | None, message: str | None = None, *, source_changed: bool = False):
44
+ data = {"retryable": True, "restart_scheduled": False, "agent_source_changed": source_changed}
45
45
  if update_state is not None:
46
46
  data["agent_update_state"] = update_state
47
- super().__init__(_RESTART_REQUIRED_MESSAGE, condition="agent_runtime_stale", data=data)
47
+ if message is None:
48
+ message = {
49
+ "active": "Agent update is in progress. Wait for it to finish before starting new work.",
50
+ "incomplete": "Agent update recovery is incomplete. Finish the Agent update before starting new work.",
51
+ }.get(update_state, _RUNTIME_UNAVAILABLE_MESSAGE)
52
+ super().__init__(message, condition="agent_runtime_stale", data=data)
48
53
 
49
54
 
50
55
  class AgentIncompatible(RpcError):
@@ -205,6 +210,57 @@ def _marker_presence(marker: Path) -> str:
205
210
  return "present"
206
211
 
207
212
 
213
+ def installed_agent_version() -> str | None:
214
+ """Agents since v0.21.6 resolve their identity from the install stamp, else the checkout's release tag; their
215
+ ``__version__`` reads only the stamp, which a source checkout does not have."""
216
+ try:
217
+ from hermes_cli.version_info import get_version_info
218
+ except ModuleNotFoundError as error:
219
+ if error.name != "hermes_cli.version_info":
220
+ raise
221
+ return getattr(importlib.import_module("hermes_cli"), "__version__", None)
222
+ return get_version_info().base_version
223
+
224
+
225
+ def _python_abi(major: int | str, minor: int | str, free_threaded: bool) -> str:
226
+ """``3.14`` or ``3.14t``: regular and free-threaded builds of one version load different native extensions."""
227
+ return f"{major}.{minor}{'t' if free_threaded else ''}"
228
+
229
+
230
+ def _site_packages_python(entry: str) -> tuple[str, Path] | None:
231
+ """The Python ABI a ``sys.path`` site-packages directory was built for, and that venv's interpreter."""
232
+ path = Path(entry)
233
+ if path.name != "site-packages" or not path.is_dir():
234
+ return None
235
+ match = re.fullmatch(r"python(\d+)\.(\d+)(t?)", path.parent.name)
236
+ if match and path.parent.parent.name in {"lib", "lib64"}:
237
+ return _python_abi(match[1], match[2], bool(match[3])), path.parent.parent.parent / "bin" / "python"
238
+ if path.parent.name.lower() == "lib":
239
+ venv = path.parent.parent
240
+ try:
241
+ config = (venv / "pyvenv.cfg").read_text(encoding="utf-8")
242
+ except OSError:
243
+ return None
244
+ found = re.search(r"^\s*version(?:_info)?\s*=\s*(\d+)\.(\d+)", config, re.MULTILINE)
245
+ if found:
246
+ free_threaded = re.search(r"^\s*executable\s*=.*python\d+\.\d+t(?:\.exe)?\s*$", config, re.MULTILINE | re.IGNORECASE)
247
+ return _python_abi(found[1], found[2], bool(free_threaded)), venv / "Scripts" / "python.exe"
248
+ return None
249
+
250
+
251
+ def _check_site_packages_python() -> None:
252
+ """Compiled Agent dependencies load lazily on the first chat; fail the handshake when ``sys.path`` holds
253
+ site-packages built for another Python (a stale ``HERMES_WEBUI_PYTHON`` after a PM environment update)."""
254
+ running = _python_abi(sys.version_info[0], sys.version_info[1], bool(sysconfig.get_config_var("Py_GIL_DISABLED")))
255
+ for entry in sys.path:
256
+ built = _site_packages_python(entry)
257
+ if built is not None and built[0] != running:
258
+ raise ImportError(
259
+ f"interpreter Python {running} cannot load Agent packages built for Python {built[0]} ({entry}); "
260
+ f"unset HERMES_WEBUI_PYTHON or point it at {built[1]}"
261
+ )
262
+
263
+
208
264
  class AgentRuntime:
209
265
  """Loads the Agent once and guards against a changed checkout."""
210
266
 
@@ -212,6 +268,7 @@ class AgentRuntime:
212
268
  self.hermes_home = Path(hermes_home)
213
269
  self._stale_lock = threading.Lock()
214
270
  self._stale = False
271
+ self._source_changed = False
215
272
  self._stale_stamp: tuple | None = None
216
273
  self.agent_dir = Path(agent_dir).resolve() if agent_dir else None
217
274
  self.pin = read_pin()
@@ -227,8 +284,18 @@ class AgentRuntime:
227
284
  if self.loaded:
228
285
  return
229
286
  try:
287
+ # Direct Agent imports skip CLI startup's PM tool PATH activation.
288
+ if self.agent_dir is not None and (self.agent_dir / "pm").is_dir():
289
+ compose_path = getattr(importlib.import_module("pm"), "store_first_path", None)
290
+ if compose_path is not None:
291
+ os.environ["PATH"] = compose_path(os.environ.get("PATH", ""))
230
292
  module = importlib.import_module("run_agent")
231
293
  getattr(module, "AIAgent")
294
+ # Agent 0.21.3 snapshots its auth provider registry, discovered plugins included, when hermes_cli.auth
295
+ # first imports. Take it here, under the launch profile and before any profile-scoped method runs, so
296
+ # a named profile's plugin loaded later never enters that process-wide snapshot.
297
+ importlib.import_module("hermes_cli.auth")
298
+ _check_site_packages_python()
232
299
  except Exception as exc: # noqa: BLE001 - reported as a handshake condition
233
300
  self.import_error = f"{type(exc).__name__}: {exc}"
234
301
  raise AgentIncompatible(f"Hermes Agent could not be imported: {self.import_error}", import_error=self.import_error)
@@ -242,7 +309,7 @@ class AgentRuntime:
242
309
  @property
243
310
  def agent_version(self) -> str | None:
244
311
  try:
245
- return getattr(importlib.import_module("hermes_cli"), "__version__", None)
312
+ return installed_agent_version()
246
313
  except Exception: # noqa: BLE001
247
314
  return None
248
315
 
@@ -260,9 +327,12 @@ class AgentRuntime:
260
327
 
261
328
  def update_transaction_state(self) -> str:
262
329
  live = _read_live_agent_update(self.hermes_home / _AGENT_UPDATE_MARKER)
263
- if live == "unknown":
330
+ if live in {"unknown", "active"}:
331
+ return live
332
+ repair = self.web_repair_state()
333
+ if repair == "unknown":
264
334
  return "unknown"
265
- recovery = False
335
+ recovery = repair == "present"
266
336
  for root in self._install_roots():
267
337
  for name in _AGENT_RECOVERY_MARKERS:
268
338
  presence = _marker_presence(root / name)
@@ -273,6 +343,16 @@ class AgentRuntime:
273
343
  return "incomplete"
274
344
  return "unverified" if live == "absent" else live
275
345
 
346
+ def web_repair_state(self) -> str:
347
+ if self.agent_dir is None:
348
+ return "absent"
349
+ from .agent_mutation import recovery_receipts
350
+ try:
351
+ receipts, _ = recovery_receipts(self)
352
+ return 'present' if receipts else 'absent'
353
+ except (OSError, UnicodeError):
354
+ return 'unknown'
355
+
276
356
  def is_stale(self) -> bool:
277
357
  """True when the checkout revision no longer matches the loaded module.
278
358
 
@@ -294,14 +374,18 @@ class AgentRuntime:
294
374
  fresh = None
295
375
  if fresh is not None:
296
376
  break
377
+ self._source_changed = fresh is not None and fresh != self.revision
297
378
  self._stale = fresh != self.revision
298
379
  self._stale_stamp = stamp if fresh is not None else None
299
380
  return self._stale
300
381
 
301
382
  def ensure_current(self) -> None:
302
- """Raise ``agent_runtime_stale`` when the checkout changed since import."""
383
+ """Refuse Agent work until source drift or a durable Web update obligation is reconciled."""
384
+ repair = self.web_repair_state()
385
+ if repair != "absent":
386
+ raise AgentRuntimeStale("unknown" if repair == "unknown" else self.update_transaction_state())
303
387
  if self.is_stale():
304
- raise AgentRuntimeStale(self.update_transaction_state())
388
+ raise AgentRuntimeStale(self.update_transaction_state(), source_changed=self._source_changed)
305
389
 
306
390
  # ── handshake ─────────────────────────────────────────────────────────
307
391
  def describe(self) -> dict:
@@ -319,6 +403,7 @@ class AgentRuntime:
319
403
  "pinned_image": self.pin["image"],
320
404
  "compatible": self.loaded,
321
405
  "stale": self.is_stale(),
406
+ "agent_source_changed": self._source_changed,
322
407
  "update_state": self.update_transaction_state(),
323
408
  "import_error": self.import_error,
324
409
  }
@@ -0,0 +1,35 @@
1
+ """One route-aware speed gate for the model catalog and chat request overrides."""
2
+
3
+ from __future__ import annotations
4
+
5
+ import inspect
6
+ import re
7
+ from urllib.parse import urlparse
8
+
9
+
10
+ def fast_overrides(model: str, provider: str, base_url: str, tier: str) -> dict | None:
11
+ if tier not in ("priority", "ultrafast"):
12
+ return None
13
+ from hermes_cli import models
14
+
15
+ resolver = getattr(models, "resolve_fast_mode_overrides", None)
16
+ if resolver is not None:
17
+ if "tier" in inspect.signature(resolver).parameters:
18
+ return resolver(model, provider=provider, base_url=base_url, tier=tier)
19
+ return resolver(model, provider=provider, base_url=base_url) if tier == "priority" else None
20
+ # Older Agents have no resolver. Keep the former GPT-5/o-series gate, restricted to first-party routes.
21
+ hosts = {"openai": "api.openai.com", "openai-api": "api.openai.com", "openai-codex": "chatgpt.com"}
22
+ model = model.strip().lower().removeprefix("openai/")
23
+ host = urlparse(base_url).hostname if base_url else None
24
+ if tier == "priority" and provider in hosts and (not host or host == hosts[provider]) and (model.startswith("gpt-5") or re.match(r"o[0-9]", model)):
25
+ return {"service_tier": "priority"}
26
+ return None
27
+
28
+
29
+ def supported_speed_tiers(model: str, provider: str, base_url: str) -> list[dict]:
30
+ tiers = []
31
+ for tier in ("priority", "ultrafast"):
32
+ override = fast_overrides(model, provider, base_url, tier)
33
+ if override:
34
+ tiers.append({"id": "fast" if override.get("speed") == "fast" else tier, "service_tier": tier})
35
+ return [{"id": "standard", "service_tier": "default"}, *tiers] if tiers else []