@maudecode/talaria-web 1.21.0 → 1.22.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 (360) hide show
  1. package/_release.json +4 -4
  2. package/dist/api/automation-router.d.ts +14 -14
  3. package/dist/api/chat-router.d.ts +217 -68
  4. package/dist/api/groups-router.d.ts +764 -0
  5. package/dist/api/groups-router.js +79 -0
  6. package/dist/api/groups-router.js.map +1 -0
  7. package/dist/api/raw-routes.js +3 -1
  8. package/dist/api/raw-routes.js.map +1 -1
  9. package/dist/api/sessions-router.d.ts +559 -160
  10. package/dist/api/sessions-router.js +9 -12
  11. package/dist/api/sessions-router.js.map +1 -1
  12. package/dist/api/settings-router.d.ts +911 -1
  13. package/dist/api/settings-router.js +53 -2
  14. package/dist/api/settings-router.js.map +1 -1
  15. package/dist/api/sse-routes.d.ts +1 -1
  16. package/dist/api/sse-routes.js +11 -3
  17. package/dist/api/sse-routes.js.map +1 -1
  18. package/dist/api/tools-raw.js +27 -136
  19. package/dist/api/tools-raw.js.map +1 -1
  20. package/dist/api/tools-router.d.ts +109 -24
  21. package/dist/api/tools-router.js +64 -7
  22. package/dist/api/tools-router.js.map +1 -1
  23. package/dist/app.js +5 -1
  24. package/dist/app.js.map +1 -1
  25. package/dist/auth/gate.js +5 -1
  26. package/dist/auth/gate.js.map +1 -1
  27. package/dist/config/agent-config.d.ts +6 -1
  28. package/dist/config/agent-config.js +75 -3
  29. package/dist/config/agent-config.js.map +1 -1
  30. package/dist/feedback.d.ts +18 -0
  31. package/dist/feedback.js +145 -0
  32. package/dist/feedback.js.map +1 -0
  33. package/dist/fs/stat.d.ts +2 -0
  34. package/dist/fs/stat.js +4 -0
  35. package/dist/fs/stat.js.map +1 -1
  36. package/dist/http/context.d.ts +7 -0
  37. package/dist/http/context.js +0 -6
  38. package/dist/http/context.js.map +1 -1
  39. package/dist/http/pinned.js +19 -8
  40. package/dist/http/pinned.js.map +1 -1
  41. package/dist/providers/catalog.d.ts +9 -1
  42. package/dist/providers/catalog.js +86 -6
  43. package/dist/providers/catalog.js.map +1 -1
  44. package/dist/redact.js +9 -3
  45. package/dist/redact.js.map +1 -1
  46. package/dist/runtime.js +27 -4
  47. package/dist/runtime.js.map +1 -1
  48. package/dist/server.js +1 -0
  49. package/dist/server.js.map +1 -1
  50. package/dist/sessions/anchor.d.ts +3 -2
  51. package/dist/sessions/anchor.js +11 -10
  52. package/dist/sessions/anchor.js.map +1 -1
  53. package/dist/sessions/cli-sessions.js +11 -6
  54. package/dist/sessions/cli-sessions.js.map +1 -1
  55. package/dist/sessions/compress.d.ts +10 -9
  56. package/dist/sessions/compress.js +31 -20
  57. package/dist/sessions/compress.js.map +1 -1
  58. package/dist/sessions/gateway-sessions.d.ts +11 -0
  59. package/dist/sessions/gateway-sessions.js +79 -24
  60. package/dist/sessions/gateway-sessions.js.map +1 -1
  61. package/dist/sessions/gateway-watcher.js +8 -4
  62. package/dist/sessions/gateway-watcher.js.map +1 -1
  63. package/dist/sessions/groups.d.ts +60 -0
  64. package/dist/sessions/groups.js +339 -0
  65. package/dist/sessions/groups.js.map +1 -0
  66. package/dist/sessions/list.d.ts +7 -2
  67. package/dist/sessions/list.js +13 -4
  68. package/dist/sessions/list.js.map +1 -1
  69. package/dist/sessions/merge.d.ts +14 -5
  70. package/dist/sessions/merge.js +42 -13
  71. package/dist/sessions/merge.js.map +1 -1
  72. package/dist/sessions/pending.d.ts +1 -1
  73. package/dist/sessions/pending.js +15 -6
  74. package/dist/sessions/pending.js.map +1 -1
  75. package/dist/sessions/prefix-index.d.ts +1 -14
  76. package/dist/sessions/prefix-index.js +1 -50
  77. package/dist/sessions/prefix-index.js.map +1 -1
  78. package/dist/sessions/reasoning-display.d.ts +2 -0
  79. package/dist/sessions/reasoning-display.js +31 -0
  80. package/dist/sessions/reasoning-display.js.map +1 -0
  81. package/dist/sessions/relay.d.ts +4 -1
  82. package/dist/sessions/relay.js +44 -7
  83. package/dist/sessions/relay.js.map +1 -1
  84. package/dist/sessions/service.d.ts +7 -2
  85. package/dist/sessions/service.js +104 -64
  86. package/dist/sessions/service.js.map +1 -1
  87. package/dist/sessions/session.d.ts +6 -0
  88. package/dist/sessions/session.js +13 -0
  89. package/dist/sessions/session.js.map +1 -1
  90. package/dist/sessions/shares.d.ts +1 -1
  91. package/dist/sessions/shares.js +13 -4
  92. package/dist/sessions/shares.js.map +1 -1
  93. package/dist/sessions/state-db.d.ts +2 -1
  94. package/dist/sessions/state-db.js +7 -3
  95. package/dist/sessions/state-db.js.map +1 -1
  96. package/dist/sessions/storage/json-documents.js +2 -0
  97. package/dist/sessions/storage/json-documents.js.map +1 -1
  98. package/dist/sessions/store.d.ts +1 -0
  99. package/dist/sessions/store.js +10 -3
  100. package/dist/sessions/store.js.map +1 -1
  101. package/dist/sessions/streams.d.ts +2 -0
  102. package/dist/sessions/streams.js +12 -0
  103. package/dist/sessions/streams.js.map +1 -1
  104. package/dist/sessions/todo.js +10 -1
  105. package/dist/sessions/todo.js.map +1 -1
  106. package/dist/sessions/turn.js +33 -9
  107. package/dist/sessions/turn.js.map +1 -1
  108. package/dist/settings.js +2 -1
  109. package/dist/settings.js.map +1 -1
  110. package/dist/spa.js +1 -1
  111. package/dist/spa.js.map +1 -1
  112. package/dist/test/group-fixture.d.ts +66 -0
  113. package/dist/test/group-fixture.js +89 -0
  114. package/dist/test/group-fixture.js.map +1 -0
  115. package/dist/test/harness.d.ts +3 -0
  116. package/dist/test/harness.js +3 -0
  117. package/dist/test/harness.js.map +1 -1
  118. package/dist/tools/connectors.d.ts +9 -1
  119. package/dist/tools/connectors.js +48 -0
  120. package/dist/tools/connectors.js.map +1 -1
  121. package/dist/tools/gateway-restart.d.ts +1 -1
  122. package/dist/tools/skills.d.ts +6 -0
  123. package/dist/tools/skills.js +17 -0
  124. package/dist/tools/skills.js.map +1 -1
  125. package/dist/tools/updates.d.ts +16 -9
  126. package/dist/tools/updates.js +63 -25
  127. package/dist/tools/updates.js.map +1 -1
  128. package/dist/workspace/fs.d.ts +2 -0
  129. package/dist/workspace/fs.js +63 -1
  130. package/dist/workspace/fs.js.map +1 -1
  131. package/dist/workspace/upload.d.ts +1 -1
  132. package/dist/workspace/upload.js +52 -37
  133. package/dist/workspace/upload.js.map +1 -1
  134. package/dist/workspace/workspaces.d.ts +5 -1
  135. package/dist/workspace/workspaces.js +32 -6
  136. package/dist/workspace/workspaces.js.map +1 -1
  137. package/package.json +2 -2
  138. package/sidecar/agent_importer.json +8 -0
  139. package/sidecar/scripts/agent_importer_contract.py +19 -0
  140. package/sidecar/scripts/test.sh +3 -1
  141. package/sidecar/talaria_sidecar/__init__.py +1 -1
  142. package/sidecar/talaria_sidecar/home.py +12 -5
  143. package/sidecar/talaria_sidecar/methods/__init__.py +2 -2
  144. package/sidecar/talaria_sidecar/methods/agent_imports.py +346 -0
  145. package/sidecar/talaria_sidecar/methods/chat.py +141 -58
  146. package/sidecar/talaria_sidecar/methods/commands.py +6 -4
  147. package/sidecar/talaria_sidecar/methods/config.py +8 -3
  148. package/sidecar/talaria_sidecar/methods/connectors.py +138 -4
  149. package/sidecar/talaria_sidecar/methods/dashboard_plugins.py +21 -0
  150. package/sidecar/talaria_sidecar/methods/delegation.py +126 -0
  151. package/sidecar/talaria_sidecar/methods/gateway.py +5 -0
  152. package/sidecar/talaria_sidecar/methods/gateway_sessions.py +35 -6
  153. package/sidecar/talaria_sidecar/methods/groups.py +120 -0
  154. package/sidecar/talaria_sidecar/methods/memory.py +27 -3
  155. package/sidecar/talaria_sidecar/methods/nous_account.py +130 -0
  156. package/sidecar/talaria_sidecar/methods/oauth.py +25 -4
  157. package/sidecar/talaria_sidecar/methods/outbound_drafts.py +1 -19
  158. package/sidecar/talaria_sidecar/methods/plugin_catalog.py +73 -2
  159. package/sidecar/talaria_sidecar/methods/providers.py +51 -1
  160. package/sidecar/talaria_sidecar/methods/skill_revisions.py +177 -0
  161. package/sidecar/talaria_sidecar/methods/skills.py +10 -0
  162. package/sidecar/talaria_sidecar/methods/tts.py +67 -0
  163. package/sidecar/talaria_sidecar/rpc.py +11 -2
  164. package/static/dist/FILES.txt +155 -143
  165. package/static/dist/THIRD_PARTY_LICENSES.md +1 -1
  166. package/static/dist/assets/AppShell-hvysbd9x.js +8 -0
  167. package/static/dist/assets/{Button-nuaikybd.js → Button-dlsibkzq.js} +1 -1
  168. package/static/dist/assets/ChatPage-jikwrwfd.js +2 -0
  169. package/static/dist/assets/Composer-mnke8ss2.js +5 -0
  170. package/static/dist/assets/ConnectTargets-ejplzo4q.js +1 -0
  171. package/static/dist/assets/Dialog-rksfyyq5.js +1 -0
  172. package/static/dist/assets/{ExtensionRoute-l1yjrso4.js → ExtensionRoute-igk5h0rj.js} +1 -1
  173. package/static/dist/assets/HubRoute-eooassx4.js +2 -0
  174. package/static/dist/assets/Markdown-m5pzgvtx.js +2 -0
  175. package/static/dist/assets/{MarkdownRenderer-ccgqrza3.js → MarkdownRenderer-74ysuomr.js} +6 -6
  176. package/static/dist/assets/OAuthSignIn-i4flsuq2.js +1 -0
  177. package/static/dist/assets/QueueCard-msz9wd1m.js +1 -0
  178. package/static/dist/assets/ResourceSwitch-b70zg4xd.js +1 -0
  179. package/static/dist/assets/RightPanel-f5v61m8j.js +1 -0
  180. package/static/dist/assets/Select-f3l897pt.js +1 -0
  181. package/static/dist/assets/SessionListPanel-brnzacw9.js +1 -0
  182. package/static/dist/assets/SettingsLayout-f4akmrt2.js +1 -0
  183. package/static/dist/assets/States-msohx3c0.js +1 -0
  184. package/static/dist/assets/TerminalPanel-bnu5xawo.js +16 -0
  185. package/static/dist/assets/Toaster-d6col3ch.js +1 -0
  186. package/static/dist/assets/_app-lrjgufcy.js +1 -0
  187. package/static/dist/assets/{_app.ext._extensionId-n797jp72.js → _app.ext._extensionId-k3xitxr1.js} +1 -1
  188. package/static/dist/assets/_app.groups-bt4wdwnd.js +1 -0
  189. package/static/dist/assets/{_app.index-ne43mdw2.js → _app.index-n3otiki0.js} +1 -1
  190. package/static/dist/assets/{_app.insights-fqonovb4.js → _app.insights-b0mzlh6m.js} +1 -1
  191. package/static/dist/assets/{_app.kanban-kysliv19.js → _app.kanban-d923g7j5.js} +1 -1
  192. package/static/dist/assets/{_app.logs-febut82r.js → _app.logs-donegue1.js} +1 -1
  193. package/static/dist/assets/{_app.memory-ha86oj1c.js → _app.memory-hdnled08.js} +1 -1
  194. package/static/dist/assets/{_app.profiles-cnu3gxxq.js → _app.profiles-fumot3jk.js} +1 -1
  195. package/static/dist/assets/{_app.session._sessionId-ifzjpcgn.js → _app.session._sessionId-crmdl2ux.js} +1 -1
  196. package/static/dist/assets/{_app.settings-nmakdiaf.js → _app.settings-jui8iesz.js} +1 -1
  197. package/static/dist/assets/_app.settings._section-do84hsqw.js +3 -0
  198. package/static/dist/assets/{_app.skills-f3wad8yo.js → _app.skills-heqcn21m.js} +1 -1
  199. package/static/dist/assets/_app.tasks-jiudtutt.js +1 -0
  200. package/static/dist/assets/{_app.todos-bml1m3r1.js → _app.todos-bl6kk2zq.js} +1 -1
  201. package/static/dist/assets/{_app.workspaces-f3d066lx.js → _app.workspaces-frvh3o7w.js} +1 -1
  202. package/static/dist/assets/_delete-qnxuo87s.js +1 -0
  203. package/static/dist/assets/{abnfDiagram-VCTEODGH-i53jc4yp.js → abnfDiagram-VCTEODGH-dppg3yfx.js} +1 -1
  204. package/static/dist/assets/{architecture-7GRP2DOG-e3bv5m6f.js → architecture-7GRP2DOG-gbajejh3.js} +1 -1
  205. package/static/dist/assets/{architectureDiagram-5GKGNRK7-pakekxu2.js → architectureDiagram-5GKGNRK7-bzrxyais.js} +1 -1
  206. package/static/dist/assets/archive-yhdyz231.js +1 -0
  207. package/static/dist/assets/autoReadClaim-nlyv8tu9.js +1 -0
  208. package/static/dist/assets/{blockDiagram-I7D4REHJ-bc6bo1n6.js → blockDiagram-I7D4REHJ-gmk9koab.js} +1 -1
  209. package/static/dist/assets/{c4Diagram-7LVT6UL2-btvwk2qx.js → c4Diagram-7LVT6UL2-bfqiqqcz.js} +1 -1
  210. package/static/dist/assets/channel-grt3rob4.js +1 -0
  211. package/static/dist/assets/{chunk-4HAMMTFA-dlwab11c.js → chunk-4HAMMTFA-i9s6h4wv.js} +1 -1
  212. package/static/dist/assets/{chunk-75Z2AOVW-dp5gh7i8.js → chunk-75Z2AOVW-gnt6pnso.js} +1 -1
  213. package/static/dist/assets/{chunk-DU6HZSFF-bi06zl1c.js → chunk-DU6HZSFF-gq439wot.js} +3 -3
  214. package/static/dist/assets/{chunk-F27PBJKO-kvv1rnlh.js → chunk-F27PBJKO-wvx90pbt.js} +1 -1
  215. package/static/dist/assets/{chunk-GMAD6QVW-ji0rx9by.js → chunk-GMAD6QVW-mc2gu30k.js} +1 -1
  216. package/static/dist/assets/{chunk-GVQU2GXP-nmz0j82p.js → chunk-GVQU2GXP-f8fxa2ym.js} +1 -1
  217. package/static/dist/assets/{chunk-IMKFNOWR-kmi1qx88.js → chunk-IMKFNOWR-lnsl31hj.js} +1 -1
  218. package/static/dist/assets/{chunk-L3NEJ4N5-xhb7mebj.js → chunk-L3NEJ4N5-kbfdidwu.js} +1 -1
  219. package/static/dist/assets/{chunk-OSK3NFVY-5a9sgscq.js → chunk-OSK3NFVY-dvxsduj6.js} +1 -1
  220. package/static/dist/assets/{chunk-P2QGCYS3-dfezp4vu.js → chunk-P2QGCYS3-ivo3i1wf.js} +1 -1
  221. package/static/dist/assets/{chunk-POPQ4Y6H-gd2vq3c0.js → chunk-POPQ4Y6H-i0gfu0hx.js} +1 -1
  222. package/static/dist/assets/{chunk-PWAF6VOD-wvw2nksf.js → chunk-PWAF6VOD-jb0fdyb0.js} +1 -1
  223. package/static/dist/assets/{chunk-SHT3W25Y-f58q97px.js → chunk-SHT3W25Y-b7ou2xsp.js} +1 -1
  224. package/static/dist/assets/{chunk-SVP7TREG-abgwpyz9.js → chunk-SVP7TREG-e2v7me5v.js} +1 -1
  225. package/static/dist/assets/{chunk-TICWLB2K-h4sbs8ds.js → chunk-TICWLB2K-e5zlai62.js} +1 -1
  226. package/static/dist/assets/classDiagram-ZZMXUADV-nnsp49jr.js +1 -0
  227. package/static/dist/assets/classDiagram-v2-VYDZK3BY-nnsp49jr.js +1 -0
  228. package/static/dist/assets/completionAudio-c5at041z.js +1 -0
  229. package/static/dist/assets/{copy-m9h56qa8.js → copy-jj3oiw13.js} +1 -1
  230. package/static/dist/assets/{cynefin-OW5HDTMX-g081vffs.js → cynefin-OW5HDTMX-n5n1ck70.js} +1 -1
  231. package/static/dist/assets/{cynefinDiagram-5FMLGOSQ-odxvjesk.js → cynefinDiagram-5FMLGOSQ-b33npu4f.js} +1 -1
  232. package/static/dist/assets/{dagre-GXQ25YYZ-cpdwzjs4.js → dagre-GXQ25YYZ-miwvae07.js} +1 -1
  233. package/static/dist/assets/{diagram-S7CK7UJ4-clv5mxvu.js → diagram-S7CK7UJ4-j8fphsp4.js} +1 -1
  234. package/static/dist/assets/{diagram-UQ7AKVKN-m2ia1mbf.js → diagram-UQ7AKVKN-5cixo166.js} +1 -1
  235. package/static/dist/assets/{diagram-VSXAHHWV-ea6zv636.js → diagram-VSXAHHWV-ii3bf92m.js} +1 -1
  236. package/static/dist/assets/{diagram-VX7I27RA-oqlef685.js → diagram-VX7I27RA-b3cfgx81.js} +1 -1
  237. package/static/dist/assets/{diagram-Z3DM3KII-kjubcbwu.js → diagram-Z3DM3KII-bey9lqr8.js} +1 -1
  238. package/static/dist/assets/{dist-carq1azj.js → dist-cb8um5dh.js} +4 -4
  239. package/static/dist/assets/{dist-crc46di9.js → dist-kpg5ccm9.js} +1 -1
  240. package/static/dist/assets/{ebnfDiagram-PWID7BFC-fg0zri3e.js → ebnfDiagram-PWID7BFC-2m4wrnqc.js} +1 -1
  241. package/static/dist/assets/{erDiagram-RLTQ6QDP-eb7pmk3x.js → erDiagram-RLTQ6QDP-kak5te0n.js} +1 -1
  242. package/static/dist/assets/{eventmodeling-NTZA5JFV-gvi1fxhn.js → eventmodeling-NTZA5JFV-ojcc486t.js} +1 -1
  243. package/static/dist/assets/flowDiagram-HODETNUW-kxr9sicu.js +1 -0
  244. package/static/dist/assets/folder-plus-fk6j7tlv.js +1 -0
  245. package/static/dist/assets/{ganttDiagram-EL5Y4UJY-jmisowrc.js → ganttDiagram-EL5Y4UJY-k6nfmhrh.js} +1 -1
  246. package/static/dist/assets/getPseudoElementBounds-mwj3vqni.js +1 -0
  247. package/static/dist/assets/{gitGraph-4MIJSDKK-m7kt3u6e.js → gitGraph-4MIJSDKK-bxq1lbhy.js} +1 -1
  248. package/static/dist/assets/{gitGraphDiagram-WWUBYQGX-nq7vfzh2.js → gitGraphDiagram-WWUBYQGX-ehvoankt.js} +1 -1
  249. package/static/dist/assets/group_discussions-fk5hry4l.js +1 -0
  250. package/static/dist/assets/{highlighted-body-KPVGNVTW-gcu017ay.js → highlighted-body-KPVGNVTW-nr4nfdq7.js} +1 -1
  251. package/static/dist/assets/{host-ipp4e84c.js → host-dhgqiozp.js} +1 -1
  252. package/static/dist/assets/index-hx7z4wdj.js +13 -0
  253. package/static/dist/assets/index-o8ebuc5x.css +2 -0
  254. package/static/dist/assets/{info-A6RAGUB7-idazwfqe.js → info-A6RAGUB7-dtsj0ybw.js} +1 -1
  255. package/static/dist/assets/{infoDiagram-27XIBGKW-bb9jh8gl.js → infoDiagram-27XIBGKW-jena90ao.js} +1 -1
  256. package/static/dist/assets/{ishikawaDiagram-5VMMS53U-nqc132rv.js → ishikawaDiagram-5VMMS53U-kia6bn5u.js} +1 -1
  257. package/static/dist/assets/{journeyDiagram-3NMN7TZE-fpvnhy44.js → journeyDiagram-3NMN7TZE-ipsa6icb.js} +1 -1
  258. package/static/dist/assets/{kanban-definition-UXKFOSKX-ndzqm6fu.js → kanban-definition-UXKFOSKX-moxx59kp.js} +1 -1
  259. package/static/dist/assets/katex-ic33v820.js +257 -0
  260. package/static/dist/assets/katex-qcv7xo0t.css +1 -0
  261. package/static/dist/assets/{lazyRouteComponent-javud235.js → lazyRouteComponent-i74ujrfk.js} +1 -1
  262. package/static/dist/assets/{line-g625e7cj.js → line-lgrkg9no.js} +1 -1
  263. package/static/dist/assets/link-2-fp49mwl2.js +1 -0
  264. package/static/dist/assets/{link-gfdaho08.js → link-es18mse1.js} +2 -2
  265. package/static/dist/assets/{locale-cs-n41hptse.js → locale-cs-brltdkcp.js} +1 -1
  266. package/static/dist/assets/{locale-de-k7ht47ew.js → locale-de-h6e9oq6v.js} +1 -1
  267. package/static/dist/assets/{locale-es-ih078lco.js → locale-es-oklmh80f.js} +1 -1
  268. package/static/dist/assets/{locale-fr-ojabnf41.js → locale-fr-b17ozoi2.js} +1 -1
  269. package/static/dist/assets/{locale-it-kb96jufy.js → locale-it-whe01eef.js} +1 -1
  270. package/static/dist/assets/{locale-ja-jpsp3xs1.js → locale-ja-g1s0rtpc.js} +1 -1
  271. package/static/dist/assets/{locale-pl-dbap4leu.js → locale-pl-d9p3lqcb.js} +1 -1
  272. package/static/dist/assets/{locale-pt-nci7w72x.js → locale-pt-l75on74f.js} +1 -1
  273. package/static/dist/assets/{locale-ru-soghe4cs.js → locale-ru-wl3mbsaw.js} +1 -1
  274. package/static/dist/assets/{locale-tr-ks00mu68.js → locale-tr-cz87itrq.js} +1 -1
  275. package/static/dist/assets/{locale-vi-ij7twfm6.js → locale-vi-elqj1y4k.js} +1 -1
  276. package/static/dist/assets/{locale-zh-Hant-feakwr7a.js → locale-zh-Hant-hf8gqm7d.js} +1 -1
  277. package/static/dist/assets/{locale-zh-ren0vjyv.js → locale-zh-cdckwb0u.js} +1 -1
  278. package/static/dist/assets/login-o6gfl4gy.js +1 -0
  279. package/static/dist/assets/mermaid-HWGCJPDP-n2kbzsao.js +1 -0
  280. package/static/dist/assets/{mermaid-parser.core-plzkuzov.js → mermaid-parser.core-fflovwf2.js} +3 -3
  281. package/static/dist/assets/{mindmap-definition-YA3MSWOX-ojrgs569.js → mindmap-definition-YA3MSWOX-ic8l9whi.js} +1 -1
  282. package/static/dist/assets/onboarding-bxm7gdrr.js +1 -0
  283. package/static/dist/assets/{packet-AYTQ26CC-gyaf9s8h.js → packet-AYTQ26CC-ntci3088.js} +1 -1
  284. package/static/dist/assets/{pegDiagram-XKGWAZYB-bf6xj8mq.js → pegDiagram-XKGWAZYB-e3btz04w.js} +1 -1
  285. package/static/dist/assets/{pie-WAS4IAKB-f5ymzelo.js → pie-WAS4IAKB-o2dc7l36.js} +1 -1
  286. package/static/dist/assets/{pieDiagram-E7YTZNPT-d0qjl3zi.js → pieDiagram-E7YTZNPT-gro55rrw.js} +1 -1
  287. package/static/dist/assets/presence-lq6m12ga.js +1 -0
  288. package/static/dist/assets/prompt_queue_cancelled-cebcuagu.js +1 -0
  289. package/static/dist/assets/{quadrantDiagram-AXDQQJYC-oqy1mras.js → quadrantDiagram-AXDQQJYC-fxulmd7d.js} +1 -1
  290. package/static/dist/assets/queryKeys-cnvn6pea.js +9 -0
  291. package/static/dist/assets/{radar-RG4KPBEZ-b6jcjvda.js → radar-RG4KPBEZ-9pcospra.js} +1 -1
  292. package/static/dist/assets/{railroad-74A4TZTK-e3a6lk5k.js → railroad-74A4TZTK-nzdga12j.js} +1 -1
  293. package/static/dist/assets/{railroad-abnf-HS5TGJTU-ff5hocrx.js → railroad-abnf-HS5TGJTU-ep3ytel0.js} +1 -1
  294. package/static/dist/assets/{railroad-ebnf-LZEXJU2U-exkhyw4n.js → railroad-ebnf-LZEXJU2U-iw7uc1wy.js} +1 -1
  295. package/static/dist/assets/{railroad-peg-WCYAUIDC-jefk9b7c.js → railroad-peg-WCYAUIDC-fo3b3gme.js} +1 -1
  296. package/static/dist/assets/{railroadDiagram-O6MQD6OU-e4amks1i.js → railroadDiagram-O6MQD6OU-lxpxf8f0.js} +1 -1
  297. package/static/dist/assets/{refresh-cw-lfp4u1oh.js → refresh-cw-d14h79x5.js} +1 -1
  298. package/static/dist/assets/rename-ccd52yws.js +1 -0
  299. package/static/dist/assets/{requirementDiagram-BXWQKSXE-c77k1e2y.js → requirementDiagram-BXWQKSXE-lrozucd2.js} +1 -1
  300. package/static/dist/assets/{sankeyDiagram-P5KCCOFB-oa1cc52s.js → sankeyDiagram-P5KCCOFB-iusxy9mq.js} +1 -1
  301. package/static/dist/assets/{sequenceDiagram-WJ2MYXX4-j20gqt22.js → sequenceDiagram-WJ2MYXX4-o987q8ti.js} +1 -1
  302. package/static/dist/assets/{share._token-kmfoflw6.js → share._token-bfw7f9m5.js} +2 -2
  303. package/static/dist/assets/sliders-horizontal-l65hoa3x.js +1 -0
  304. package/static/dist/assets/{stateDiagram-D77RDMKH-co2ghkdp.js → stateDiagram-D77RDMKH-hh23v7y5.js} +1 -1
  305. package/static/dist/assets/stateDiagram-v2-MP3YSRHH-jukr0d8h.js +1 -0
  306. package/static/dist/assets/{swimlanes-42K2YHIH-m30cktqe.js → swimlanes-42K2YHIH-gj2t3rm8.js} +1 -1
  307. package/static/dist/assets/swimlanesDiagram-VR7AAH4N-ik9m9j2m.js +8 -0
  308. package/static/dist/assets/{timeline-definition-24CTP7MA-liuep6fl.js → timeline-definition-24CTP7MA-84s2w2sr.js} +1 -1
  309. package/static/dist/assets/toast-gqqcvxiy.js +56 -0
  310. package/static/dist/assets/{treeView-Q6P3EWNA-np5d2jv2.js → treeView-Q6P3EWNA-cmuj50l7.js} +1 -1
  311. package/static/dist/assets/{treemap-WGGIJYW6-cmpltxh1.js → treemap-WGGIJYW6-dpjlg0xc.js} +1 -1
  312. package/static/dist/assets/tts-jw84jlqy.js +1 -0
  313. package/static/dist/assets/{useForm-f1udzsjf.js → useForm-lxzhiqao.js} +1 -1
  314. package/static/dist/assets/{useParams-ierevvts.js → useParams-dt6gkoq7.js} +1 -1
  315. package/static/dist/assets/{useSearch-i7nr9ypl.js → useSearch-o8t49csk.js} +1 -1
  316. package/static/dist/assets/useTranscript-gx9umcc2.js +1 -0
  317. package/static/dist/assets/{vennDiagram-4TSXK5OY-b2g42qrg.js → vennDiagram-4TSXK5OY-g9g5o8vy.js} +1 -1
  318. package/static/dist/assets/{wardley-WFR3VGLG-lb0eqbff.js → wardley-WFR3VGLG-ij35obrl.js} +1 -1
  319. package/static/dist/assets/{wardleyDiagram-VM6X3IG4-ermwaqha.js → wardleyDiagram-VM6X3IG4-f9my7q7w.js} +1 -1
  320. package/static/dist/assets/{xychartDiagram-S5SC5T6Z-dll0jldk.js → xychartDiagram-S5SC5T6Z-olqx1s1p.js} +1 -1
  321. package/static/dist/index.html +1 -1
  322. package/static/dist/sw.js +1 -1
  323. package/static/dist/assets/AppShell-c5989995.js +0 -8
  324. package/static/dist/assets/ChatPage-bfg4khph.js +0 -6
  325. package/static/dist/assets/ConnectTargets-k5wo9yo8.js +0 -1
  326. package/static/dist/assets/Dialog-o8vo2aws.js +0 -1
  327. package/static/dist/assets/Field-j7o8cfps.js +0 -1
  328. package/static/dist/assets/HubRoute-efnwe4xz.js +0 -2
  329. package/static/dist/assets/Markdown-clqf5m22.js +0 -2
  330. package/static/dist/assets/OAuthSignIn-h7bjaqp6.js +0 -1
  331. package/static/dist/assets/ResourceSwitch-oai2zqaj.js +0 -1
  332. package/static/dist/assets/RightPanel-ho161a45.js +0 -1
  333. package/static/dist/assets/Select-d1g5a8bm.js +0 -1
  334. package/static/dist/assets/SessionListPanel-i7kaokhi.js +0 -1
  335. package/static/dist/assets/SettingsLayout-lnecm87w.js +0 -1
  336. package/static/dist/assets/States-easntmry.js +0 -1
  337. package/static/dist/assets/TerminalPanel-lxhwd4jl.js +0 -16
  338. package/static/dist/assets/Toaster-l4sciy8t.js +0 -1
  339. package/static/dist/assets/_app-mqexqbg8.js +0 -1
  340. package/static/dist/assets/_app.settings._section-djglnjmi.js +0 -3
  341. package/static/dist/assets/_app.tasks-l10py1c0.js +0 -1
  342. package/static/dist/assets/archive-ihqi7z2x.js +0 -1
  343. package/static/dist/assets/channel-jn4f8443.js +0 -1
  344. package/static/dist/assets/classDiagram-ZZMXUADV-dzrw66se.js +0 -1
  345. package/static/dist/assets/classDiagram-v2-VYDZK3BY-dzrw66se.js +0 -1
  346. package/static/dist/assets/completionAudio-ce86msbu.js +0 -1
  347. package/static/dist/assets/flowDiagram-HODETNUW-abekab15.js +0 -1
  348. package/static/dist/assets/folder-plus-ksaons88.js +0 -1
  349. package/static/dist/assets/index-d6vbxlra.js +0 -13
  350. package/static/dist/assets/index-ey6qo0zx.css +0 -2
  351. package/static/dist/assets/katex-cbdd1ohw.css +0 -1
  352. package/static/dist/assets/katex-pbij2oo6.js +0 -257
  353. package/static/dist/assets/login-iv6yq4xf.js +0 -1
  354. package/static/dist/assets/mermaid-HWGCJPDP-cwj5cl6k.js +0 -1
  355. package/static/dist/assets/onboarding-ff4emacu.js +0 -1
  356. package/static/dist/assets/queryKeys-x8fjxhut.js +0 -9
  357. package/static/dist/assets/sliders-horizontal-g5jkzd9k.js +0 -1
  358. package/static/dist/assets/stateDiagram-v2-MP3YSRHH-faw1opgh.js +0 -1
  359. package/static/dist/assets/swimlanesDiagram-VR7AAH4N-hfil433g.js +0 -8
  360. package/static/dist/assets/toast-zmb35u3r.js +0 -56
@@ -0,0 +1,19 @@
1
+ """Provision reviewed native API bytes outside tests, into the checker's disposable directory."""
2
+ import hashlib
3
+ import json
4
+ from pathlib import Path
5
+ from urllib.request import urlopen
6
+
7
+
8
+ def provision(target):
9
+ reviewed = json.loads((Path(__file__).parents[1] / 'agent_importer.json').read_text())
10
+ pin = reviewed['revision']
11
+ target = Path(target)
12
+ target.mkdir()
13
+ for name, expected in reviewed['files'].items():
14
+ with urlopen(f'https://raw.githubusercontent.com/NousResearch/hermes-official-plugins/{pin}/agent-importers/{name}', timeout=30) as response:
15
+ body = response.read(256 * 1024)
16
+ if hashlib.sha256(body).hexdigest() != expected:
17
+ raise ValueError('Reviewed importer contract source changed')
18
+ (target / name).write_bytes(body)
19
+ return target
@@ -12,7 +12,8 @@ fi
12
12
  venv="$here/.venv"
13
13
  if [[ ! -x "$venv/bin/python" ]]; then
14
14
  "$runner" -m venv "$venv"
15
- "$venv/bin/python" -m pip install --quiet --disable-pip-version-check "pytest>=8,<10"
15
+ # pytest 9.2 renames parametrized case ids, which the reviewed inventory in tests/process_inventory.json lists.
16
+ "$venv/bin/python" -m pip install --quiet --disable-pip-version-check "pytest>=8,<9.2"
16
17
  fi
17
18
  state="${TMPDIR:-/tmp}/talaria-sidecar-tests.$$"
18
19
  mkdir -p "$state"
@@ -20,6 +21,7 @@ trap 'rm -rf -- "$state"' EXIT
20
21
  cd "$here"
21
22
  # GitHub's relocated Linux Python needs LD_LIBRARY_PATH; nothing else from the caller's environment leaks in.
22
23
  env -i PATH="$PATH" HOME="$state" TMPDIR="$state" ${LD_LIBRARY_PATH:+LD_LIBRARY_PATH="$LD_LIBRARY_PATH"} \
24
+ HERMES_WEBUI_IMPORTER_DIR="${HERMES_WEBUI_IMPORTER_DIR:-}" \
23
25
  HERMES_WEBUI_AGENT_DIR="${HERMES_WEBUI_AGENT_DIR:-}" \
24
26
  HERMES_WEBUI_PYTHON="${HERMES_WEBUI_PYTHON:-}" \
25
27
  ${TALARIA_SIDECAR_WORKERS+TALARIA_SIDECAR_WORKERS="$TALARIA_SIDECAR_WORKERS"} \
@@ -12,4 +12,4 @@ import os
12
12
  # Also protect direct Python entry points before any method imports the Agent.
13
13
  os.environ["HERMES_DISABLE_LAZY_INSTALLS"] = "1"
14
14
 
15
- SIDECAR_RPC_VERSION = 58
15
+ SIDECAR_RPC_VERSION = 66
@@ -310,8 +310,8 @@ def _recover_processes(home: Path) -> None:
310
310
 
311
311
 
312
312
  @contextlib.contextmanager
313
- def scoped_home(home: Path, *, load_plugins: bool = True):
314
- """Run the body with Hermes Agent resolving ``get_hermes_home()`` to ``home``."""
313
+ def scoped_home(home: Path, *, load_plugins: bool = True, recover_processes: bool = True, read_only: bool = False):
314
+ """Bind the home; read-only inspection skips credential hydration, terminal defaults and recovery."""
315
315
  home = Path(home).expanduser()
316
316
  stamp = _scope_stamp(home)
317
317
  try:
@@ -321,18 +321,25 @@ def scoped_home(home: Path, *, load_plugins: bool = True):
321
321
  if set_hermes_home_override is not None:
322
322
  token = set_hermes_home_override(home)
323
323
  try:
324
- with _secret_scope(home, stamp, load_plugins=load_plugins), _terminal_scope(home, stamp):
325
- _recover_processes(home)
324
+ if read_only:
326
325
  yield home
326
+ else:
327
+ with _secret_scope(home, stamp, load_plugins=load_plugins), _terminal_scope(home, stamp):
328
+ if recover_processes:
329
+ _recover_processes(home)
330
+ yield home
327
331
  finally:
328
332
  reset_hermes_home_override(token)
329
333
  return
334
+ if read_only:
335
+ raise RpcError("Read-only profile binding is unavailable", condition="agent_incompatible")
330
336
  with _ENV_LOCK:
331
337
  previous = os.environ.get("HERMES_HOME")
332
338
  os.environ["HERMES_HOME"] = str(home)
333
339
  try:
334
340
  with _secret_scope(home, stamp, load_plugins=load_plugins), _terminal_scope(home, stamp):
335
- _recover_processes(home)
341
+ if recover_processes:
342
+ _recover_processes(home)
336
343
  yield home
337
344
  finally:
338
345
  if previous is None:
@@ -29,9 +29,9 @@ class Registry:
29
29
 
30
30
  def build_methods(runtime: AgentRuntime) -> dict[str, Handler]:
31
31
  registry = Registry(runtime)
32
- from . import aux, chat, checkpoints, commands, config, connectors, cron, dashboard_plugins, gateway, goals, kanban, mcp, managed_buffers, memory, oauth, outbound_drafts, plugin_oauth, process, profiles, providers, skills, state_db, stt, text, toolsets, usage, worktree, write_approval # noqa: WPS433
32
+ from . import agent_imports, aux, chat, checkpoints, commands, config, connectors, cron, dashboard_plugins, delegation, gateway, goals, kanban, mcp, managed_buffers, memory, oauth, outbound_drafts, plugin_oauth, process, profiles, providers, skills, state_db, stt, tts, text, toolsets, usage, worktree, write_approval # noqa: WPS433
33
33
  from . import runtime as runtime_methods
34
34
 
35
- for module in (runtime_methods, goals, commands, kanban, state_db, profiles, skills, mcp, stt, cron, providers, oauth, plugin_oauth, aux, text, process, usage, gateway, worktree, checkpoints, memory, chat, config, toolsets, write_approval, connectors, dashboard_plugins, outbound_drafts, managed_buffers):
35
+ for module in (agent_imports, runtime_methods, goals, commands, kanban, state_db, profiles, skills, mcp, stt, tts, cron, providers, oauth, plugin_oauth, aux, delegation, text, process, usage, gateway, worktree, checkpoints, memory, chat, config, toolsets, write_approval, connectors, dashboard_plugins, outbound_drafts, managed_buffers):
36
36
  module.register(registry)
37
37
  return registry.methods
@@ -0,0 +1,346 @@
1
+ """Profile import adapter. Native planning runs on private snapshots; publication uses anchored descriptors."""
2
+ from __future__ import annotations
3
+
4
+ from contextlib import contextmanager, nullcontext
5
+ import hashlib
6
+ import json
7
+ from itertools import islice
8
+ import os
9
+ from pathlib import Path
10
+ import re
11
+ import secrets
12
+ import stat
13
+ import tempfile
14
+ import time
15
+
16
+ from .. import home as homes
17
+ from ..errors import InvalidParams, RpcError
18
+ from . import config, memory, plugin_catalog
19
+
20
+ _SOURCES = {'claude-code': ('.claude', 'Claude Code'), 'codex': ('.codex', 'Codex CLI'), 'cursor': ('.cursor', 'Cursor')}
21
+ _CREDENTIALS = {'.credentials.json', 'auth.json', 'credentials.json', 'cli-config.json', '.env'}
22
+ _TARGETS = ('config.yaml', 'memories', 'skills', 'import-sync.json')
23
+ _MEMORY_FILES = {'memories/MEMORY.md', 'memories/USER.md'}
24
+ _PREVIEWS = {}
25
+ _MAX_FILES = 2048
26
+ _MAX_BYTES = 16 * 1024 * 1024
27
+ _LEDGER = '.talaria-agent-imports'
28
+
29
+
30
+ def _result(status, *, items=None, stripped=None, receipt=None, sources=None, message=None, can_apply=False, catalog_required=False):
31
+ return dict(status=status, items=items or [], stripped_secrets=stripped or [], receipt=receipt,
32
+ sources=sources or [], message=message, can_apply=can_apply, catalog_required=catalog_required)
33
+
34
+
35
+ @contextmanager
36
+ def _directory(path):
37
+ """Open every ancestor without following links; the held descriptor owns all subsequent IO."""
38
+ path = Path(path)
39
+ if not path.is_absolute():
40
+ raise OSError('An absolute directory is required')
41
+ fd = os.open(path.anchor, os.O_RDONLY | os.O_DIRECTORY | os.O_NOFOLLOW)
42
+ try:
43
+ for part in path.parts[1:]:
44
+ child = os.open(part, os.O_RDONLY | os.O_DIRECTORY | os.O_NOFOLLOW, dir_fd=fd)
45
+ os.close(fd)
46
+ fd = child
47
+ yield fd
48
+ finally:
49
+ os.close(fd)
50
+
51
+
52
+ def _read(fd, name):
53
+ child = os.open(name, os.O_RDONLY | os.O_NOFOLLOW | os.O_NONBLOCK, dir_fd=fd)
54
+ try:
55
+ info = os.fstat(child)
56
+ if not stat.S_ISREG(info.st_mode) or info.st_nlink != 1 or info.st_size > _MAX_BYTES:
57
+ raise OSError('Unsafe or oversized import file')
58
+ with os.fdopen(os.dup(child), 'rb') as stream:
59
+ body = stream.read(_MAX_BYTES + 1)
60
+ after = os.fstat(child)
61
+ if (info.st_size, info.st_mtime_ns, info.st_ctime_ns) != (after.st_size, after.st_mtime_ns, after.st_ctime_ns):
62
+ raise OSError('Import input changed during read')
63
+ return body, (info.st_dev, info.st_ino, info.st_mode, info.st_mtime_ns, info.st_ctime_ns)
64
+ finally:
65
+ os.close(child)
66
+
67
+
68
+ def _snapshot(path, names):
69
+ """Bounded snapshot of only importer inputs. Credential stores are never read."""
70
+ files, identities = {}, {}
71
+ def walk(fd, name, rel):
72
+ try:
73
+ info = os.stat(name, dir_fd=fd, follow_symlinks=False)
74
+ except FileNotFoundError:
75
+ return
76
+ if rel.endswith('.lock') and rel[:-5] in _MEMORY_FILES:
77
+ if not stat.S_ISREG(info.st_mode) or info.st_nlink != 1:
78
+ raise OSError('Unsafe memory lock')
79
+ return
80
+ if stat.S_ISDIR(info.st_mode):
81
+ child = os.open(name, os.O_RDONLY | os.O_DIRECTORY | os.O_NOFOLLOW, dir_fd=fd)
82
+ try:
83
+ identities[rel] = (info.st_dev, info.st_ino, info.st_mode)
84
+ if len(identities) > _MAX_FILES:
85
+ raise OSError('Import tree too large')
86
+ with os.scandir(child) as entries:
87
+ names = [entry.name for entry in islice(entries, _MAX_FILES + 1)]
88
+ if len(names) > _MAX_FILES:
89
+ raise OSError('Import directory too large')
90
+ for entry in sorted(names):
91
+ if entry not in _CREDENTIALS and entry not in {'.git', '__pycache__'}:
92
+ walk(child, entry, rel + '/' + entry)
93
+ finally:
94
+ os.close(child)
95
+ else:
96
+ body, identity = _read(fd, name)
97
+ files[rel], identities[rel] = body, identity
98
+ if len(identities) > _MAX_FILES or sum(map(len, files.values())) > _MAX_BYTES:
99
+ raise OSError('Import tree too large')
100
+ with _directory(path) as fd:
101
+ info = os.fstat(fd)
102
+ identities['.'] = (info.st_dev, info.st_ino, info.st_mode)
103
+ for name in names:
104
+ walk(fd, name, name)
105
+ return files, identities
106
+
107
+
108
+ def _source(agent):
109
+ os_home = Path.home()
110
+ source = os_home / _SOURCES[agent][0]
111
+ names = {'claude-code': ['CLAUDE.md', 'settings.json', 'skills', 'commands'],
112
+ 'codex': ['AGENTS.md', 'config.toml', 'memories', 'skills'],
113
+ 'cursor': ['AGENTS.md', 'mcp.json', 'rules', 'skills']}[agent]
114
+ files, identity = _snapshot(source, names)
115
+ if agent == 'claude-code':
116
+ extra, extra_identity = _snapshot(os_home, ['.claude.json'])
117
+ files.update({'../' + k: v for k, v in extra.items()})
118
+ identity.update({'../' + k: v for k, v in extra_identity.items()})
119
+ return source, files, identity
120
+
121
+
122
+ def _stamp(snapshot):
123
+ files, identities = snapshot
124
+ return hashlib.sha256(json.dumps([identities, {k: hashlib.sha256(v).hexdigest() for k, v in files.items()}], sort_keys=True).encode()).hexdigest()
125
+
126
+
127
+ def _materialize(root, files, identities):
128
+ root.mkdir()
129
+ for name, info in identities.items():
130
+ if name != '.' and stat.S_ISDIR(info[2]):
131
+ (root / name).mkdir(parents=True, exist_ok=True)
132
+ for name, body in files.items():
133
+ path = root / name
134
+ path.parent.mkdir(parents=True, exist_ok=True)
135
+ path.write_bytes(body)
136
+ path.chmod(stat.S_IMODE(identities[name][2]))
137
+
138
+
139
+ def _project(report):
140
+ # No native reason, path, command, content or arbitrary detail crosses the boundary.
141
+ kinds = {'source': 'Source', 'settings': 'Settings', 'claude-md': 'Claude Code instructions',
142
+ 'agents-md': 'Instructions', 'command-allowlist': 'Allowed commands', 'command-denylist': 'Denied commands',
143
+ 'mcp-servers': 'MCP servers', 'skills': 'Skills', 'skill': 'Skill', 'memories': 'Memories',
144
+ 'rules': 'Cursor rules', 'config': 'Configuration', 'slash-commands': 'Slash commands'}
145
+ statuses = {'imported', 'skipped', 'conflict', 'error'}
146
+ items = report.get('items')
147
+ if not isinstance(items, list) or len(items) > _MAX_FILES:
148
+ raise ValueError('Invalid native report')
149
+ projected = []
150
+ for item in items:
151
+ if not isinstance(item, dict) or item.get('kind') not in kinds or item.get('status') not in statuses:
152
+ raise ValueError('Invalid native disposition')
153
+ projected.append(dict(kind=item['kind'], status=item['status'], label=kinds[item['kind']]))
154
+ stripped = report.get('stripped_secrets', [])
155
+ if not isinstance(stripped, list) or len(stripped) > _MAX_FILES:
156
+ raise ValueError('Invalid stripped-secret names')
157
+ return projected, [name for name in stripped if isinstance(name, str) and len(name) <= 200
158
+ and re.fullmatch(r'[A-Za-z0-9_.-]+', name)]
159
+
160
+
161
+ @contextmanager
162
+ def _parent(root_fd, rel, create=False):
163
+ parts = Path(rel).parts
164
+ if not parts or any(p in ('.', '..') for p in parts) or Path(rel).is_absolute():
165
+ raise OSError('Unsafe output path')
166
+ fd = os.dup(root_fd)
167
+ try:
168
+ for part in parts[:-1]:
169
+ if create:
170
+ try:
171
+ os.mkdir(part, 0o700, dir_fd=fd)
172
+ os.fsync(fd)
173
+ except FileExistsError:
174
+ pass
175
+ child = os.open(part, os.O_RDONLY | os.O_DIRECTORY | os.O_NOFOLLOW, dir_fd=fd)
176
+ os.close(fd)
177
+ fd = child
178
+ yield fd, parts[-1]
179
+ finally:
180
+ os.close(fd)
181
+
182
+
183
+ def _write(root_fd, rel, body, *, exclusive=False, mode=0o600, expected=None):
184
+ with _parent(root_fd, rel, create=True) as (fd, name):
185
+ tmp = '.import-' + secrets.token_hex(16)
186
+ child = os.open(tmp, os.O_WRONLY | os.O_CREAT | os.O_EXCL | os.O_NOFOLLOW, 0o600, dir_fd=fd)
187
+ try:
188
+ with os.fdopen(child, 'wb') as stream:
189
+ os.fchmod(stream.fileno(), stat.S_IMODE(mode) & 0o777)
190
+ stream.write(body)
191
+ stream.flush()
192
+ os.fsync(stream.fileno())
193
+ guard = memory.file_lock(Path(name), parent_fd=fd) if rel in _MEMORY_FILES else nullcontext()
194
+ with guard:
195
+ if expected is not None and _read(fd, name) != expected:
196
+ raise OSError('Import destination changed during publication')
197
+ if exclusive:
198
+ os.link(tmp, name, src_dir_fd=fd, dst_dir_fd=fd, follow_symlinks=False)
199
+ else:
200
+ # Replacing a link cannot follow it. Never mutate the old inode in place.
201
+ os.rename(tmp, name, src_dir_fd=fd, dst_dir_fd=fd)
202
+ os.fsync(fd)
203
+ finally:
204
+ try:
205
+ os.unlink(tmp, dir_fd=fd)
206
+ except FileNotFoundError:
207
+ pass
208
+
209
+
210
+ def _ledger(root_fd, token, result=None):
211
+ name = _LEDGER + '/' + hashlib.sha256(token.encode()).hexdigest() + '.json'
212
+ if result is not None:
213
+ _write(root_fd, name, json.dumps(result).encode())
214
+ return result
215
+ try:
216
+ with _parent(root_fd, name) as (fd, leaf):
217
+ return json.loads(_read(fd, leaf)[0])
218
+ except FileNotFoundError:
219
+ return None
220
+
221
+
222
+ def _refresh_runtime(home):
223
+ from .commands import _reload_mcp, _reload_skills
224
+ try:
225
+ with homes.scoped_home(home, load_plugins=False):
226
+ _reload_skills()
227
+ _reload_mcp(log_errors=False)
228
+ return True
229
+ except Exception:
230
+ return False
231
+
232
+
233
+ def run(ctx, params):
234
+ action, agent, token = params.get('action'), params.get('agent'), params.get('receipt')
235
+ if action not in ('discover', 'preview', 'apply', 'result') or action == 'preview' and agent not in _SOURCES or action in ('apply', 'result') and (not isinstance(token, str) or not 0 < len(token) <= 128):
236
+ raise InvalidParams('Invalid profile import request')
237
+ home = homes.profile_home_param(params)
238
+ with homes.scoped_home(home, load_plugins=False, read_only=True), plugin_catalog._lock:
239
+ try:
240
+ with _directory(home) as root_fd:
241
+ # Read the durable consumption record before plugin/source checks. A retry is readback only.
242
+ if action in ('apply', 'result'):
243
+ previous = _ledger(root_fd, token)
244
+ if previous is not None:
245
+ if 'expected' in previous:
246
+ files, _ = _snapshot(home, _TARGETS)
247
+ if all(name in files and hashlib.sha256(files[name]).hexdigest() == digest for name, digest in previous['expected'].items()):
248
+ return _ledger(root_fd, token, previous['confirmed'])
249
+ return previous['result']
250
+ return previous
251
+ if action == 'result':
252
+ # Fence a late apply that never reached the consumption record.
253
+ _PREVIEWS.pop(token, None)
254
+ return _result('changed', message='No import was confirmed. Preview again.')
255
+ try:
256
+ config.assert_config_writable(home)
257
+ except RpcError:
258
+ return _result('unavailable', message='Profile configuration is managed or its write policy cannot be verified. Import is unavailable.')
259
+ native = plugin_catalog.reviewed_importer(home)
260
+ if native is None:
261
+ return _result('unavailable', message='Install and enable Agent Importers from the plugin catalog.', catalog_required=True)
262
+ importer, sync, plugin = native
263
+ if action == 'discover':
264
+ sources = []
265
+ for name, (_, label) in _SOURCES.items():
266
+ try:
267
+ _source(name)
268
+ sources.append(dict(agent=name, label=label))
269
+ except OSError:
270
+ pass
271
+ return _result('available', sources=sources)
272
+ now = time.monotonic()
273
+ for old in list(_PREVIEWS):
274
+ if _PREVIEWS[old]['expires'] <= now:
275
+ del _PREVIEWS[old]
276
+ receipt = _PREVIEWS.get(token) if action == 'apply' else None
277
+ if action == 'apply' and (receipt is None or receipt['home'] != str(home)):
278
+ return _result('changed', message='Preview expired or belongs to another profile. Preview again.')
279
+ agent = receipt['agent'] if receipt else agent
280
+ source, source_files, source_identity = _source(agent)
281
+ if home == source or home in source.parents or source in home.parents:
282
+ raise OSError('Source overlaps the active profile')
283
+ target = _snapshot(home, _TARGETS)
284
+ identity = [str(home), str(source), plugin, _stamp((source_files, source_identity)), _stamp(target)]
285
+ if receipt and receipt['identity'] != identity:
286
+ return _result('changed', message='Source, profile or plugin changed. Preview again.')
287
+ if ctx is not None:
288
+ ctx.check_cancelled()
289
+ # Private temporary copies isolate the native path-based API from hostile path replacement.
290
+ with tempfile.TemporaryDirectory(prefix='talaria-import-') as temp:
291
+ stage_source, stage_target = Path(temp).resolve() / 'source', Path(temp).resolve() / 'target'
292
+ _materialize(stage_source, source_files, source_identity)
293
+ _materialize(stage_target, *target)
294
+ report = importer(agent, stage_source, stage_target, execute=False, overwrite=False).run()
295
+ items, stripped = _project(report)
296
+ plan = json.dumps([items, stripped], sort_keys=True)
297
+ if receipt and plan != receipt['plan']:
298
+ return _result('changed', message='Import plan changed. Preview again.')
299
+ if action == 'preview':
300
+ if not any(i['status'] == 'imported' for i in items):
301
+ return _result('preview', items=items, stripped=stripped)
302
+ token = secrets.token_urlsafe(32)
303
+ if len(_PREVIEWS) >= 64:
304
+ del _PREVIEWS[next(iter(_PREVIEWS))]
305
+ _PREVIEWS[token] = dict(home=str(home), agent=agent, identity=identity, plan=plan, expires=now + 300)
306
+ return _result('preview', items=items, stripped=stripped, receipt=token,
307
+ can_apply=any(i['status'] == 'imported' for i in items))
308
+ del _PREVIEWS[token]
309
+ unknown = _result('unknown', message='Import outcome is unknown. Check the profile before starting a new preview.')
310
+ # Fsync the consumed record before any native write. Restart or cancellation cannot replay it.
311
+ _ledger(root_fd, token, unknown)
312
+ try:
313
+ report = importer(agent, stage_source, stage_target, execute=True, overwrite=False).run()
314
+ items, stripped = _project(report)
315
+ sync.update_sync_manifest(agent, stage_source, stage_target, False, report,
316
+ refresh_digest=not any(i['status'] == 'error' for i in items))
317
+ manifest_path = stage_target / 'import-sync.json'
318
+ manifest = json.loads(manifest_path.read_text())
319
+ manifest['agents'][agent]['source'] = str(source)
320
+ manifest_path.write_text(json.dumps(manifest))
321
+ config.assert_config_writable(home)
322
+ output, output_identity = _snapshot(stage_target, _TARGETS)
323
+ # Check original objects again before publication; no write resolves a client/native path.
324
+ fresh_source = _source(agent)
325
+ if (plugin_catalog.reviewed_importer(home)[2] != plugin
326
+ or _stamp(fresh_source[1:]) != identity[3] or _stamp(_snapshot(home, _TARGETS)) != identity[4]):
327
+ return _ledger(root_fd, token, _result('changed', message='Import inputs changed before publication. Preview again.'))
328
+ result = _result('partial' if any(i['status'] == 'error' for i in items) else 'applied', items=items, stripped=stripped)
329
+ result['message'] = 'Files imported. Reload Skills and MCP before using the imported setup.'
330
+ _ledger(root_fd, token, dict(result=unknown, expected={k: hashlib.sha256(v).hexdigest() for k, v in output.items()}, confirmed=result))
331
+ for rel, body in output.items():
332
+ if target[0].get(rel) != body:
333
+ _write(root_fd, rel, body, exclusive=rel not in target[0], mode=output_identity[rel][2], expected=(target[0][rel], target[1][rel]) if rel in target[0] else None)
334
+ result = _result('partial' if any(i['status'] == 'error' for i in items) else 'applied', items=items, stripped=stripped)
335
+ if not _refresh_runtime(home):
336
+ result['message'] = 'Files imported. Reload Skills and MCP before using the imported setup.'
337
+ return _ledger(root_fd, token, result)
338
+ except Exception:
339
+ # Exceptions may include secret values. The durable unknown record is the only public result.
340
+ return unknown
341
+ except (OSError, ValueError, TypeError, KeyError):
342
+ return _result('unknown' if action == 'result' else 'changed' if action == 'apply' else 'unavailable', message='Import paths or state are unsafe, unavailable or changed. Check the profile before continuing.')
343
+
344
+
345
+ def register(registry):
346
+ registry.method('profiles.import')(run)