@maudecode/talaria-web 1.17.2 → 1.18.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 (387) 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 +4 -4
  4. package/dist/api/auth-raw.js.map +1 -1
  5. package/dist/api/automation-raw.d.ts +6 -0
  6. package/dist/api/automation-raw.js +53 -6
  7. package/dist/api/automation-raw.js.map +1 -1
  8. package/dist/api/automation-router.d.ts +26 -1
  9. package/dist/api/automation-router.js +16 -2
  10. package/dist/api/automation-router.js.map +1 -1
  11. package/dist/api/chat-router.d.ts +649 -15
  12. package/dist/api/chat-router.js +52 -50
  13. package/dist/api/chat-router.js.map +1 -1
  14. package/dist/api/git-router.d.ts +35 -1
  15. package/dist/api/git-router.js +18 -19
  16. package/dist/api/git-router.js.map +1 -1
  17. package/dist/api/raw-routes.d.ts +8 -0
  18. package/dist/api/raw-routes.js +247 -36
  19. package/dist/api/raw-routes.js.map +1 -1
  20. package/dist/api/router.d.ts +10 -0
  21. package/dist/api/router.js +10 -8
  22. package/dist/api/router.js.map +1 -1
  23. package/dist/api/sessions-router.d.ts +1492 -115
  24. package/dist/api/sessions-router.js +134 -8
  25. package/dist/api/sessions-router.js.map +1 -1
  26. package/dist/api/settings-router.d.ts +31 -0
  27. package/dist/api/settings-router.js +8 -3
  28. package/dist/api/settings-router.js.map +1 -1
  29. package/dist/api/sse-routes.d.ts +5 -0
  30. package/dist/api/sse-routes.js +50 -3
  31. package/dist/api/sse-routes.js.map +1 -1
  32. package/dist/api/tools-raw.js +6 -23
  33. package/dist/api/tools-raw.js.map +1 -1
  34. package/dist/api/tools-router.d.ts +356 -15
  35. package/dist/api/tools-router.js +148 -19
  36. package/dist/api/tools-router.js.map +1 -1
  37. package/dist/app.js +35 -15
  38. package/dist/app.js.map +1 -1
  39. package/dist/auth/gate.js +5 -2
  40. package/dist/auth/gate.js.map +1 -1
  41. package/dist/auth/oidc.d.ts +5 -2
  42. package/dist/auth/oidc.js +8 -7
  43. package/dist/auth/oidc.js.map +1 -1
  44. package/dist/bin/talaria-web.js +1 -1
  45. package/dist/bin/talaria-web.js.map +1 -1
  46. package/dist/cli/dotenv.js +1 -0
  47. package/dist/cli/dotenv.js.map +1 -1
  48. package/dist/config/agent-config.js +3 -2
  49. package/dist/config/agent-config.js.map +1 -1
  50. package/dist/config.d.ts +2 -0
  51. package/dist/config.js +5 -1
  52. package/dist/config.js.map +1 -1
  53. package/dist/http/context.d.ts +17 -3
  54. package/dist/http/context.js +31 -4
  55. package/dist/http/context.js.map +1 -1
  56. package/dist/http/csp.d.ts +2 -1
  57. package/dist/http/csp.js +3 -2
  58. package/dist/http/csp.js.map +1 -1
  59. package/dist/profiles/profiles.d.ts +10 -0
  60. package/dist/profiles/profiles.js +40 -2
  61. package/dist/profiles/profiles.js.map +1 -1
  62. package/dist/providers/catalog.d.ts +6 -2
  63. package/dist/providers/catalog.js +30 -11
  64. package/dist/providers/catalog.js.map +1 -1
  65. package/dist/raster-image.d.ts +7 -0
  66. package/dist/raster-image.js +267 -0
  67. package/dist/raster-image.js.map +1 -0
  68. package/dist/redact.js +327 -40
  69. package/dist/redact.js.map +1 -1
  70. package/dist/runtime.js +89 -23
  71. package/dist/runtime.js.map +1 -1
  72. package/dist/server.js +5 -0
  73. package/dist/server.js.map +1 -1
  74. package/dist/sessions/background-tasks.d.ts +2 -9
  75. package/dist/sessions/background-tasks.js +2 -12
  76. package/dist/sessions/background-tasks.js.map +1 -1
  77. package/dist/sessions/cli-sessions.d.ts +15 -4
  78. package/dist/sessions/cli-sessions.js +120 -29
  79. package/dist/sessions/cli-sessions.js.map +1 -1
  80. package/dist/sessions/completions.d.ts +48 -8
  81. package/dist/sessions/completions.js +222 -26
  82. package/dist/sessions/completions.js.map +1 -1
  83. package/dist/sessions/export.d.ts +5 -0
  84. package/dist/sessions/export.js +30 -0
  85. package/dist/sessions/export.js.map +1 -1
  86. package/dist/sessions/gateway-watcher.d.ts +7 -3
  87. package/dist/sessions/gateway-watcher.js +31 -19
  88. package/dist/sessions/gateway-watcher.js.map +1 -1
  89. package/dist/sessions/handoff.d.ts +32 -0
  90. package/dist/sessions/handoff.js +114 -0
  91. package/dist/sessions/handoff.js.map +1 -0
  92. package/dist/sessions/list.d.ts +7 -1
  93. package/dist/sessions/list.js +13 -5
  94. package/dist/sessions/list.js.map +1 -1
  95. package/dist/sessions/merge.d.ts +2 -4
  96. package/dist/sessions/merge.js +8 -15
  97. package/dist/sessions/merge.js.map +1 -1
  98. package/dist/sessions/recovery.d.ts +22 -0
  99. package/dist/sessions/recovery.js +506 -0
  100. package/dist/sessions/recovery.js.map +1 -0
  101. package/dist/sessions/relay.d.ts +21 -2
  102. package/dist/sessions/relay.js +156 -11
  103. package/dist/sessions/relay.js.map +1 -1
  104. package/dist/sessions/service.d.ts +108 -6
  105. package/dist/sessions/service.js +403 -29
  106. package/dist/sessions/service.js.map +1 -1
  107. package/dist/sessions/session.d.ts +6 -0
  108. package/dist/sessions/session.js +40 -2
  109. package/dist/sessions/session.js.map +1 -1
  110. package/dist/sessions/state-db-worker.d.ts +1 -0
  111. package/dist/sessions/state-db-worker.js +33 -0
  112. package/dist/sessions/state-db-worker.js.map +1 -0
  113. package/dist/sessions/state-db.d.ts +61 -0
  114. package/dist/sessions/state-db.js +291 -0
  115. package/dist/sessions/state-db.js.map +1 -1
  116. package/dist/sessions/store.d.ts +7 -0
  117. package/dist/sessions/store.js +31 -22
  118. package/dist/sessions/store.js.map +1 -1
  119. package/dist/sessions/titles.d.ts +2 -0
  120. package/dist/sessions/titles.js +4 -0
  121. package/dist/sessions/titles.js.map +1 -1
  122. package/dist/sessions/tool-display.d.ts +3 -3
  123. package/dist/sessions/tool-display.js +11 -37
  124. package/dist/sessions/tool-display.js.map +1 -1
  125. package/dist/sessions/turn-context.d.ts +1 -1
  126. package/dist/sessions/turn-context.js +11 -7
  127. package/dist/sessions/turn-context.js.map +1 -1
  128. package/dist/sessions/turn.d.ts +37 -2
  129. package/dist/sessions/turn.js +182 -49
  130. package/dist/sessions/turn.js.map +1 -1
  131. package/dist/sessions/wakeup-pause.d.ts +59 -0
  132. package/dist/sessions/wakeup-pause.js +181 -0
  133. package/dist/sessions/wakeup-pause.js.map +1 -0
  134. package/dist/settings.js +5 -7
  135. package/dist/settings.js.map +1 -1
  136. package/dist/sidecar/fake.d.ts +2 -2
  137. package/dist/sidecar/fake.js.map +1 -1
  138. package/dist/startup.d.ts +13 -5
  139. package/dist/startup.js +48 -0
  140. package/dist/startup.js.map +1 -1
  141. package/dist/test/ts-worker-hooks.d.ts +1 -0
  142. package/dist/test/ts-worker-hooks.js +24 -0
  143. package/dist/test/ts-worker-hooks.js.map +1 -0
  144. package/dist/text/diff.d.ts +9 -14
  145. package/dist/text/diff.js +74 -108
  146. package/dist/text/diff.js.map +1 -1
  147. package/dist/tools/crons.js +45 -8
  148. package/dist/tools/crons.js.map +1 -1
  149. package/dist/tools/dashboard-plugins.d.ts +53 -0
  150. package/dist/tools/dashboard-plugins.js +188 -0
  151. package/dist/tools/dashboard-plugins.js.map +1 -0
  152. package/dist/tools/extensions.d.ts +13 -1
  153. package/dist/tools/extensions.js +132 -60
  154. package/dist/tools/extensions.js.map +1 -1
  155. package/dist/tools/health.d.ts +32 -0
  156. package/dist/tools/health.js +111 -19
  157. package/dist/tools/health.js.map +1 -1
  158. package/dist/tools/mcp.d.ts +13 -0
  159. package/dist/tools/mcp.js +88 -0
  160. package/dist/tools/mcp.js.map +1 -1
  161. package/dist/tools/project-os.d.ts +11 -0
  162. package/dist/tools/project-os.js +267 -0
  163. package/dist/tools/project-os.js.map +1 -0
  164. package/dist/tools/skills.d.ts +5 -1
  165. package/dist/tools/skills.js +5 -3
  166. package/dist/tools/skills.js.map +1 -1
  167. package/dist/tools/updates.d.ts +27 -9
  168. package/dist/tools/updates.js +163 -51
  169. package/dist/tools/updates.js.map +1 -1
  170. package/dist/tools/wiki.d.ts +68 -0
  171. package/dist/tools/wiki.js +413 -0
  172. package/dist/tools/wiki.js.map +1 -0
  173. package/dist/workspace/escape.d.ts +61 -0
  174. package/dist/workspace/escape.js +149 -0
  175. package/dist/workspace/escape.js.map +1 -0
  176. package/dist/workspace/extract.d.ts +22 -0
  177. package/dist/workspace/extract.js +308 -0
  178. package/dist/workspace/extract.js.map +1 -0
  179. package/dist/workspace/fs.d.ts +12 -0
  180. package/dist/workspace/fs.js +92 -23
  181. package/dist/workspace/fs.js.map +1 -1
  182. package/dist/workspace/git.d.ts +18 -0
  183. package/dist/workspace/git.js +38 -25
  184. package/dist/workspace/git.js.map +1 -1
  185. package/dist/workspace/media.d.ts +4 -4
  186. package/dist/workspace/media.js +16 -45
  187. package/dist/workspace/media.js.map +1 -1
  188. package/dist/workspace/rollback.d.ts +34 -20
  189. package/dist/workspace/rollback.js +171 -265
  190. package/dist/workspace/rollback.js.map +1 -1
  191. package/dist/workspace/unzip.js +4 -1
  192. package/dist/workspace/unzip.js.map +1 -1
  193. package/dist/workspace/upload.d.ts +7 -4
  194. package/dist/workspace/upload.js +5 -2
  195. package/dist/workspace/upload.js.map +1 -1
  196. package/dist/workspace/worktrees.d.ts +2 -1
  197. package/dist/workspace/worktrees.js +14 -15
  198. package/dist/workspace/worktrees.js.map +1 -1
  199. package/package.json +4 -2
  200. package/sidecar/agent_dependency.json +4 -4
  201. package/sidecar/scripts/replay_sidecar.py +24 -0
  202. package/sidecar/talaria_sidecar/__init__.py +1 -1
  203. package/sidecar/talaria_sidecar/home.py +13 -2
  204. package/sidecar/talaria_sidecar/methods/__init__.py +2 -2
  205. package/sidecar/talaria_sidecar/methods/aux.py +39 -5
  206. package/sidecar/talaria_sidecar/methods/chat.py +9 -5
  207. package/sidecar/talaria_sidecar/methods/checkpoints.py +89 -0
  208. package/sidecar/talaria_sidecar/methods/commands.py +81 -0
  209. package/sidecar/talaria_sidecar/methods/cron.py +29 -2
  210. package/sidecar/talaria_sidecar/methods/gateway.py +32 -15
  211. package/sidecar/talaria_sidecar/methods/kanban.py +28 -7
  212. package/sidecar/talaria_sidecar/methods/mcp.py +1 -1
  213. package/sidecar/talaria_sidecar/methods/process.py +58 -4
  214. package/sidecar/talaria_sidecar/methods/profiles.py +77 -7
  215. package/sidecar/talaria_sidecar/methods/providers.py +27 -8
  216. package/sidecar/talaria_sidecar/methods/state_db.py +39 -5
  217. package/sidecar/talaria_sidecar/runtime.py +17 -1
  218. package/static/dist/FILES.txt +127 -126
  219. package/static/dist/assets/AppShell-g3bkgnvt.js +1 -0
  220. package/static/dist/assets/ChatPage-oo7bdan6.js +25 -0
  221. package/static/dist/assets/Dialog-g355qxhp.js +1 -0
  222. package/static/dist/assets/ExtensionRoute-i2y9fvjm.js +1 -0
  223. package/static/dist/assets/HubRoute-lmkrbw47.js +2 -0
  224. package/static/dist/assets/{Markdown-mdwlvj3w.js → Markdown-j4kut4j2.js} +114 -114
  225. package/static/dist/assets/{RightPanel-ftvrjlcp.js → RightPanel-ohlsdzfl.js} +1 -1
  226. package/static/dist/assets/Select-kddq75qc.js +1 -0
  227. package/static/dist/assets/SessionListPanel-lu3oy0hw.js +1 -0
  228. package/static/dist/assets/{SettingsLayout-jonjefmj.js → SettingsLayout-o9bv4mgb.js} +1 -1
  229. package/static/dist/assets/{States-nmejrwrm.js → States-eq6fe29m.js} +1 -1
  230. package/static/dist/assets/Toaster-pc247u9f.js +1 -0
  231. package/static/dist/assets/{_app-gdidzd94.js → _app-f8n1i0m1.js} +1 -1
  232. package/static/dist/assets/{_app.ext._extensionId-opyh9y0v.js → _app.ext._extensionId-gfbzpoou.js} +1 -1
  233. package/static/dist/assets/_app.index-bzzv80hk.js +1 -0
  234. package/static/dist/assets/_app.insights-dzixbryi.js +1 -0
  235. package/static/dist/assets/_app.kanban-c6hep2us.js +1 -0
  236. package/static/dist/assets/_app.logs-i69qds98.js +1 -0
  237. package/static/dist/assets/_app.memory-kl4vf0gd.js +1 -0
  238. package/static/dist/assets/_app.profiles-b8zinmyp.js +1 -0
  239. package/static/dist/assets/{_app.session._sessionId-bfd4h3id.js → _app.session._sessionId-fn1bhde6.js} +1 -1
  240. package/static/dist/assets/_app.settings-cg8plwmf.js +1 -0
  241. package/static/dist/assets/_app.settings._section-bkwbi9zn.js +3 -0
  242. package/static/dist/assets/_app.skills-cs47sbvs.js +1 -0
  243. package/static/dist/assets/_app.tasks-dwvk64tc.js +1 -0
  244. package/static/dist/assets/_app.todos-c8xjm8p3.js +1 -0
  245. package/static/dist/assets/_app.workspaces-ehvd1gds.js +1 -0
  246. package/static/dist/assets/{abnfDiagram-VCTEODGH-b2x1lqot.js → abnfDiagram-VCTEODGH-c8kdixke.js} +1 -1
  247. package/static/dist/assets/architecture-7GRP2DOG-6crvnylg.js +1 -0
  248. package/static/dist/assets/{architectureDiagram-5GKGNRK7-h38o5l7b.js → architectureDiagram-5GKGNRK7-cku06x1p.js} +1 -1
  249. package/static/dist/assets/{back-bemaer09.js → back-h7aun7ew.js} +1 -1
  250. package/static/dist/assets/{blockDiagram-I7D4REHJ-bqquxv2u.js → blockDiagram-I7D4REHJ-jzthp1wa.js} +1 -1
  251. package/static/dist/assets/{c4Diagram-7LVT6UL2-f3fb8w6z.js → c4Diagram-7LVT6UL2-mwr67mt8.js} +1 -1
  252. package/static/dist/assets/{cancel-drd0g6d9.js → cancel-fhi0vcnu.js} +1 -1
  253. package/static/dist/assets/channel-b2zo73z1.js +1 -0
  254. package/static/dist/assets/{chunk-4HAMMTFA-bzfyyzp3.js → chunk-4HAMMTFA-gpq1y228.js} +1 -1
  255. package/static/dist/assets/{chunk-75Z2AOVW-ly99rfx5.js → chunk-75Z2AOVW-ktje58c4.js} +1 -1
  256. package/static/dist/assets/{chunk-DU6HZSFF-bg6ecfqf.js → chunk-DU6HZSFF-ofajdixh.js} +3 -3
  257. package/static/dist/assets/{chunk-F27PBJKO-e8k7mmqw.js → chunk-F27PBJKO-cmev85ti.js} +1 -1
  258. package/static/dist/assets/{chunk-GMAD6QVW-cmalnoaj.js → chunk-GMAD6QVW-htjgt22y.js} +1 -1
  259. package/static/dist/assets/{chunk-GVQU2GXP-gmif5o01.js → chunk-GVQU2GXP-qndvoxl7.js} +1 -1
  260. package/static/dist/assets/{chunk-IMKFNOWR-f1nwwh6u.js → chunk-IMKFNOWR-e5bkd5q6.js} +1 -1
  261. package/static/dist/assets/{chunk-L3NEJ4N5-oktfh5v7.js → chunk-L3NEJ4N5-mj1155r6.js} +1 -1
  262. package/static/dist/assets/{chunk-OSK3NFVY-b1sdx96z.js → chunk-OSK3NFVY-e7gkikcw.js} +1 -1
  263. package/static/dist/assets/{chunk-P2QGCYS3-fhu4nzxt.js → chunk-P2QGCYS3-f7t54xfm.js} +1 -1
  264. package/static/dist/assets/{chunk-POPQ4Y6H-em31rnef.js → chunk-POPQ4Y6H-i927v9oa.js} +1 -1
  265. package/static/dist/assets/{chunk-PWAF6VOD-bxhhyftw.js → chunk-PWAF6VOD-m84lmnyt.js} +1 -1
  266. package/static/dist/assets/{chunk-SHT3W25Y-fmrvwcav.js → chunk-SHT3W25Y-mi0tlcu9.js} +1 -1
  267. package/static/dist/assets/{chunk-SVP7TREG-lymukl2j.js → chunk-SVP7TREG-dnau702j.js} +1 -1
  268. package/static/dist/assets/{chunk-TICWLB2K-lmza6k23.js → chunk-TICWLB2K-edem1gkg.js} +1 -1
  269. package/static/dist/assets/classDiagram-ZZMXUADV-oe99st8x.js +1 -0
  270. package/static/dist/assets/classDiagram-v2-VYDZK3BY-oe99st8x.js +1 -0
  271. package/static/dist/assets/{copied-ima3pysb.js → copied-hcplv46p.js} +1 -1
  272. package/static/dist/assets/{copy-fw5b1pc6.js → copy-magtofyp.js} +1 -1
  273. package/static/dist/assets/{cynefin-OW5HDTMX-czlhbyhs.js → cynefin-OW5HDTMX-siqlulkl.js} +1 -1
  274. package/static/dist/assets/{cynefinDiagram-5FMLGOSQ-gq7mvswb.js → cynefinDiagram-5FMLGOSQ-i648tah9.js} +1 -1
  275. package/static/dist/assets/{dagre-GXQ25YYZ-cqdbf7dr.js → dagre-GXQ25YYZ-mwn6uc17.js} +1 -1
  276. package/static/dist/assets/{diagram-S7CK7UJ4-o6arxa58.js → diagram-S7CK7UJ4-l8abxaes.js} +1 -1
  277. package/static/dist/assets/{diagram-UQ7AKVKN-nhnd68tz.js → diagram-UQ7AKVKN-mekq7zgq.js} +1 -1
  278. package/static/dist/assets/{diagram-VSXAHHWV-dk2sclzn.js → diagram-VSXAHHWV-fnky6lvc.js} +1 -1
  279. package/static/dist/assets/{diagram-VX7I27RA-n3k5nyx3.js → diagram-VX7I27RA-xe6r5qfw.js} +1 -1
  280. package/static/dist/assets/{diagram-Z3DM3KII-m6q9cwdh.js → diagram-Z3DM3KII-nq07dg7k.js} +1 -1
  281. package/static/dist/assets/{ebnfDiagram-PWID7BFC-lsa5641p.js → ebnfDiagram-PWID7BFC-c62ipm3g.js} +1 -1
  282. package/static/dist/assets/endpoints-klbxod4t.js +64 -0
  283. package/static/dist/assets/{erDiagram-RLTQ6QDP-fo2ckbe6.js → erDiagram-RLTQ6QDP-h39kmnzy.js} +1 -1
  284. package/static/dist/assets/eventmodeling-NTZA5JFV-obfede4u.js +1 -0
  285. package/static/dist/assets/flowDiagram-HODETNUW-kdpsp1je.js +1 -0
  286. package/static/dist/assets/{ganttDiagram-EL5Y4UJY-nzqz6x9g.js → ganttDiagram-EL5Y4UJY-ngbsyp37.js} +1 -1
  287. package/static/dist/assets/{gitGraph-4MIJSDKK-gukvcxe6.js → gitGraph-4MIJSDKK-fr2i7caa.js} +1 -1
  288. package/static/dist/assets/{gitGraphDiagram-WWUBYQGX-lqhdp8f0.js → gitGraphDiagram-WWUBYQGX-eravdti4.js} +1 -1
  289. package/static/dist/assets/{highlighted-body-KPVGNVTW-igw6cp39.js → highlighted-body-KPVGNVTW-jwpop9p8.js} +1 -1
  290. package/static/dist/assets/host-i828xuo7.js +1 -0
  291. package/static/dist/assets/index-eh8zilnv.css +2 -0
  292. package/static/dist/assets/{index-cxq58xb1.js → index-r648f4o1.js} +5 -5
  293. package/static/dist/assets/{info-A6RAGUB7-gvu7a93l.js → info-A6RAGUB7-h11x0dxo.js} +1 -1
  294. package/static/dist/assets/{infoDiagram-27XIBGKW-m8t8g6w1.js → infoDiagram-27XIBGKW-dfh47dw9.js} +1 -1
  295. package/static/dist/assets/{ishikawaDiagram-5VMMS53U-l07vkbgj.js → ishikawaDiagram-5VMMS53U-i6ypq351.js} +1 -1
  296. package/static/dist/assets/{journeyDiagram-3NMN7TZE-hybkgj8l.js → journeyDiagram-3NMN7TZE-lduf1z95.js} +1 -1
  297. package/static/dist/assets/{kanban-definition-UXKFOSKX-by13uvtn.js → kanban-definition-UXKFOSKX-e18bu4pg.js} +1 -1
  298. package/static/dist/assets/{lazyRouteComponent-af0lvgjx.js → lazyRouteComponent-e1y4t2i9.js} +1 -1
  299. package/static/dist/assets/{line-osxq6fq7.js → line-meizqsvn.js} +1 -1
  300. package/static/dist/assets/{link-jyxicdhg.js → link-oot2yn73.js} +1 -1
  301. package/static/dist/assets/login-gu28l9ou.js +1 -0
  302. package/static/dist/assets/mermaid-HWGCJPDP-mtwrj8fn.js +1 -0
  303. package/static/dist/assets/{mermaid-parser.core-i91oxmou.js → mermaid-parser.core-ntne45i9.js} +3 -3
  304. package/static/dist/assets/{mindmap-definition-YA3MSWOX-m82mx8ww.js → mindmap-definition-YA3MSWOX-27b26eok.js} +1 -1
  305. package/static/dist/assets/onboarding-lkphzu1s.js +1 -0
  306. package/static/dist/assets/{onboarding_model_label-dp7xffoh.js → onboarding_model_label-ftpjdwqk.js} +1 -1
  307. package/static/dist/assets/{packet-AYTQ26CC-nbtgge2o.js → packet-AYTQ26CC-l6jdka8p.js} +1 -1
  308. package/static/dist/assets/{pegDiagram-XKGWAZYB-f1zxzga1.js → pegDiagram-XKGWAZYB-g1er3bxj.js} +1 -1
  309. package/static/dist/assets/{pie-WAS4IAKB-of8vuhxs.js → pie-WAS4IAKB-i0ylcrt9.js} +1 -1
  310. package/static/dist/assets/{pieDiagram-E7YTZNPT-o7y8ftio.js → pieDiagram-E7YTZNPT-fbz1e55z.js} +1 -1
  311. package/static/dist/assets/{quadrantDiagram-AXDQQJYC-iqiwia1t.js → quadrantDiagram-AXDQQJYC-hhue7d8o.js} +1 -1
  312. package/static/dist/assets/{radar-RG4KPBEZ-delnsy2v.js → radar-RG4KPBEZ-f9b70aa4.js} +1 -1
  313. package/static/dist/assets/{railroad-74A4TZTK-nspnyq9u.js → railroad-74A4TZTK-lgsuoeda.js} +1 -1
  314. package/static/dist/assets/railroad-abnf-HS5TGJTU-nf9d6pdx.js +1 -0
  315. package/static/dist/assets/railroad-ebnf-LZEXJU2U-f7ummkt5.js +1 -0
  316. package/static/dist/assets/railroad-peg-WCYAUIDC-oczq5tqs.js +1 -0
  317. package/static/dist/assets/{railroadDiagram-O6MQD6OU-z41tqx5z.js → railroadDiagram-O6MQD6OU-eqpy9fnz.js} +1 -1
  318. package/static/dist/assets/{refresh-b4uams1i.js → refresh-abtu93ke.js} +1 -1
  319. package/static/dist/assets/{refresh-cw-nt1dtsx4.js → refresh-cw-hlwb02qv.js} +1 -1
  320. package/static/dist/assets/{requirementDiagram-BXWQKSXE-bdvif194.js → requirementDiagram-BXWQKSXE-ogf6puhi.js} +1 -1
  321. package/static/dist/assets/{sankeyDiagram-P5KCCOFB-h73e0rol.js → sankeyDiagram-P5KCCOFB-fqb8xcjf.js} +1 -1
  322. package/static/dist/assets/{saved-kg52csy7.js → saved-girnabkf.js} +1 -1
  323. package/static/dist/assets/{sequenceDiagram-WJ2MYXX4-iv95mb1z.js → sequenceDiagram-WJ2MYXX4-dlcz6qjz.js} +1 -1
  324. package/static/dist/assets/{settings_section_extensions_title-ej0iapxe.js → settings_section_extensions_title-h14cwk6f.js} +1 -1
  325. package/static/dist/assets/share._token-kl0r7ido.js +2 -0
  326. package/static/dist/assets/{sliders-horizontal-fj18it47.js → sliders-horizontal-n1zm34qq.js} +1 -1
  327. package/static/dist/assets/sse-iwku0sjo.js +1 -0
  328. package/static/dist/assets/{stateDiagram-D77RDMKH-k417ixmf.js → stateDiagram-D77RDMKH-fyoznpcs.js} +1 -1
  329. package/static/dist/assets/stateDiagram-v2-MP3YSRHH-ixhx8r46.js +1 -0
  330. package/static/dist/assets/{swimlanes-42K2YHIH-esola70w.js → swimlanes-42K2YHIH-oefldhfy.js} +1 -1
  331. package/static/dist/assets/swimlanesDiagram-VR7AAH4N-h9ersk2e.js +8 -0
  332. package/static/dist/assets/{timeline-definition-24CTP7MA-getrz2y8.js → timeline-definition-24CTP7MA-b1vl2zil.js} +1 -1
  333. package/static/dist/assets/todoStore-jjr5yr78.js +1 -0
  334. package/static/dist/assets/{treeView-Q6P3EWNA-hc7ap1q7.js → treeView-Q6P3EWNA-f7hcci5o.js} +1 -1
  335. package/static/dist/assets/{treemap-WGGIJYW6-b7k1syy5.js → treemap-WGGIJYW6-nl85071a.js} +1 -1
  336. package/static/dist/assets/{tts-lxdxnmjd.js → units-kgxzxfhi.js} +1 -1
  337. package/static/dist/assets/{untitled-ovpfthg4.js → untitled-cikfjntn.js} +1 -1
  338. package/static/dist/assets/{useForm-bcblv1rx.js → useForm-kqoqg0k9.js} +1 -1
  339. package/static/dist/assets/useLocale-o59tbiea.js +1 -0
  340. package/static/dist/assets/{useParams-lhg566ew.js → useParams-b4dq6n4q.js} +1 -1
  341. package/static/dist/assets/{useSearch-lbrh6ejn.js → useSearch-ipfmv3he.js} +1 -1
  342. package/static/dist/assets/{vennDiagram-4TSXK5OY-n6pcy5qb.js → vennDiagram-4TSXK5OY-h5hzbk0n.js} +1 -1
  343. package/static/dist/assets/{wardley-WFR3VGLG-lpa18vz1.js → wardley-WFR3VGLG-jftvpm3e.js} +1 -1
  344. package/static/dist/assets/{wardleyDiagram-VM6X3IG4-kpclwwg7.js → wardleyDiagram-VM6X3IG4-hedh85ge.js} +1 -1
  345. package/static/dist/assets/{xychartDiagram-S5SC5T6Z-paa2n8y0.js → xychartDiagram-S5SC5T6Z-e49523ab.js} +1 -1
  346. package/static/dist/index.html +1 -1
  347. package/static/dist/sw.js +1 -1
  348. package/static/dist/assets/AppShell-fb2td9zi.js +0 -1
  349. package/static/dist/assets/ChatPage-cj96kiy9.js +0 -25
  350. package/static/dist/assets/Dialog-kxcg7ard.js +0 -1
  351. package/static/dist/assets/ExtensionRoute-jf7h0754.js +0 -1
  352. package/static/dist/assets/HubRoute-gmanpd5y.js +0 -2
  353. package/static/dist/assets/Select-bilaypej.js +0 -1
  354. package/static/dist/assets/SessionListPanel-og8n36qs.js +0 -1
  355. package/static/dist/assets/Toaster-nnl8zkt9.js +0 -1
  356. package/static/dist/assets/_app.index-hbarzbjx.js +0 -1
  357. package/static/dist/assets/_app.insights-luywlarz.js +0 -1
  358. package/static/dist/assets/_app.kanban-kincnbr8.js +0 -1
  359. package/static/dist/assets/_app.logs-oi2gr3gs.js +0 -1
  360. package/static/dist/assets/_app.memory-b6jfivt6.js +0 -1
  361. package/static/dist/assets/_app.profiles-lpvixmqp.js +0 -1
  362. package/static/dist/assets/_app.settings-vowx3iq0.js +0 -1
  363. package/static/dist/assets/_app.settings._section-cnntg1tu.js +0 -3
  364. package/static/dist/assets/_app.skills-fb57lpau.js +0 -1
  365. package/static/dist/assets/_app.tasks-eszpx1q7.js +0 -2
  366. package/static/dist/assets/_app.todos-nr05ac6w.js +0 -1
  367. package/static/dist/assets/_app.workspaces-d2luomu6.js +0 -1
  368. package/static/dist/assets/architecture-7GRP2DOG-hd0o7bde.js +0 -1
  369. package/static/dist/assets/channel-cpdgf867.js +0 -1
  370. package/static/dist/assets/classDiagram-ZZMXUADV-ko09sguk.js +0 -1
  371. package/static/dist/assets/classDiagram-v2-VYDZK3BY-ko09sguk.js +0 -1
  372. package/static/dist/assets/endpoints-d33siokx.js +0 -64
  373. package/static/dist/assets/eventmodeling-NTZA5JFV-emctlo64.js +0 -1
  374. package/static/dist/assets/flowDiagram-HODETNUW-bfi3moqa.js +0 -1
  375. package/static/dist/assets/index-hgtx08n5.css +0 -2
  376. package/static/dist/assets/login-ec21t39x.js +0 -1
  377. package/static/dist/assets/mermaid-HWGCJPDP-gfl8z3ep.js +0 -1
  378. package/static/dist/assets/onboarding-btnltvyz.js +0 -1
  379. package/static/dist/assets/railroad-abnf-HS5TGJTU-nst1qxyn.js +0 -1
  380. package/static/dist/assets/railroad-ebnf-LZEXJU2U-ci37x8qy.js +0 -1
  381. package/static/dist/assets/railroad-peg-WCYAUIDC-aimkk07z.js +0 -1
  382. package/static/dist/assets/share._token-f97e94r0.js +0 -2
  383. package/static/dist/assets/sse-fwpqtzbg.js +0 -1
  384. package/static/dist/assets/stateDiagram-v2-MP3YSRHH-hwn4apct.js +0 -1
  385. package/static/dist/assets/swimlanesDiagram-VR7AAH4N-d1h97oyg.js +0 -8
  386. package/static/dist/assets/todoStore-eginf9h4.js +0 -1
  387. package/static/dist/assets/useLocale-fi5jb8ma.js +0 -1
@@ -0,0 +1 @@
1
+ {"version":3,"file":"escape.js","sourceRoot":"","sources":["../../src/workspace/escape.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,22 @@
1
+ export declare const ARCHIVE_SUFFIXES: readonly [".zip", ".tar", ".tar.gz", ".tgz", ".tar.bz2", ".tbz2", ".tar.xz", ".txz"];
2
+ /** A tiny archive of millions of empty members slips under the byte cap but exhausts inodes. */
3
+ export declare const MAX_ARCHIVE_MEMBERS = 10000;
4
+ /** Python `ValueError`: the archive was refused (format, slip, size, or member count). */
5
+ export declare class ArchiveRejected extends Error {
6
+ }
7
+ /** Python `BadZipFile` / `TarError`: the archive could not be read. */
8
+ export declare class CorruptArchive extends Error {
9
+ }
10
+ export interface Extraction {
11
+ extracted: number;
12
+ files: string[];
13
+ dest: string;
14
+ }
15
+ export declare function isArchiveName(name: string): boolean;
16
+ /**
17
+ * Extract `bytes` into a new directory named for the archive under `parent`. `root` is the trusted directory (the
18
+ * workspace or the session inbox) that `parent` lives in; every directory and file is created by an anchored walk
19
+ * from it. The member count, total size, and every member path are checked before anything is created, and a failed
20
+ * write removes the partial directory. `files` are relative to `parent`.
21
+ */
22
+ export declare function extractArchive(bytes: Buffer, filename: string, root: string, parent: string, cap: number): Promise<Extraction>;
@@ -0,0 +1,308 @@
1
+ /**
2
+ * Archive extraction for `/api/upload/extract` and `/api/workspace/upload` (Python `extract_archive`). Zip and tar
3
+ * (plain, gzip, bzip2, xz) members land in a fresh `<parent>/<stem>` directory through the anchored exclusive create,
4
+ * so a slipped name or a symlinked component never writes outside it. Every decompressor stops once its output passes
5
+ * the extracted-bytes cap, and partial output is removed on any failure.
6
+ */
7
+ import { closeSync, lstatSync } from 'node:fs';
8
+ import { randomInt } from 'node:crypto';
9
+ import { basename, join, relative } from 'node:path';
10
+ import { gunzipSync } from 'node:zlib';
11
+ import Bunzip from 'seek-bzip';
12
+ import xzPkg from 'xz-decompress';
13
+ import { writeFully } from '../fs/atomic.js';
14
+ import { makeAnchoredDir, openAnchoredCreateFd, rmtreeAnchored, safeResolve } from './fs.js';
15
+ import { resolvePathLikePython } from './paths.js';
16
+ import { BadZipError, readZip } from './unzip.js';
17
+ const { XzReadableStream } = xzPkg;
18
+ export const ARCHIVE_SUFFIXES = ['.zip', '.tar', '.tar.gz', '.tgz', '.tar.bz2', '.tbz2', '.tar.xz', '.txz'];
19
+ /** A tiny archive of millions of empty members slips under the byte cap but exhausts inodes. */
20
+ export const MAX_ARCHIVE_MEMBERS = 10_000;
21
+ /**
22
+ * A decompressed tar stream may exceed the file-byte cap only by its framing: each member costs a 512-byte header plus
23
+ * under 512 bytes of padding, and twice the member cap leaves room for directory and extended headers.
24
+ */
25
+ const TAR_FRAMING_BYTES = 2 * MAX_ARCHIVE_MEMBERS * 1024;
26
+ /** Python `ValueError`: the archive was refused (format, slip, size, or member count). */
27
+ export class ArchiveRejected extends Error {
28
+ }
29
+ /** Python `BadZipFile` / `TarError`: the archive could not be read. */
30
+ export class CorruptArchive extends Error {
31
+ }
32
+ export function isArchiveName(name) {
33
+ const lower = name.toLowerCase();
34
+ return ARCHIVE_SUFFIXES.some((suffix) => lower.endsWith(suffix));
35
+ }
36
+ /** Python `PurePath.stem`: the name without its last suffix (`a.tar.gz` -> `a.tar`, `.zip` -> `.zip`). */
37
+ function pythonStem(name) {
38
+ const dot = name.lastIndexOf('.');
39
+ return dot > 0 && dot < name.length - 1 ? name.slice(0, dot) : name;
40
+ }
41
+ function lexists(path) {
42
+ try {
43
+ lstatSync(path);
44
+ return true;
45
+ }
46
+ catch {
47
+ return false;
48
+ }
49
+ }
50
+ function tooLarge(cap) {
51
+ return new ArchiveRejected(`Extraction too large (> ${String(Math.floor(cap / (1024 * 1024)))} MB limit). Possible zip bomb.`);
52
+ }
53
+ /**
54
+ * Extract `bytes` into a new directory named for the archive under `parent`. `root` is the trusted directory (the
55
+ * workspace or the session inbox) that `parent` lives in; every directory and file is created by an anchored walk
56
+ * from it. The member count, total size, and every member path are checked before anything is created, and a failed
57
+ * write removes the partial directory. `files` are relative to `parent`.
58
+ */
59
+ export async function extractArchive(bytes, filename, root, parent, cap) {
60
+ const name = basename(filename);
61
+ const isZip = name.toLowerCase().endsWith('.zip');
62
+ if (!isZip && !isArchiveName(name))
63
+ throw new ArchiveRejected(`Unsupported archive format: ${filename}`);
64
+ const stem = pythonStem(name);
65
+ if (!stem || stem === '.' || stem === '..')
66
+ throw new ArchiveRejected(`Invalid archive name: ${filename}`);
67
+ const members = isZip ? zipMembers(bytes) : [...tarMembers(await decompressTar(bytes, cap + TAR_FRAMING_BYTES, cap))];
68
+ if (members.length > MAX_ARCHIVE_MEMBERS)
69
+ throw new ArchiveRejected(`Archive has too many files (> ${String(MAX_ARCHIVE_MEMBERS)}). Possible archive bomb.`);
70
+ // Declared sizes are binding: a zip member cannot inflate past its own, and a tar member is a slice of the stream.
71
+ if (members.reduce((sum, m) => sum + m.size, 0) > cap)
72
+ throw tooLarge(cap);
73
+ const parentResolved = resolvePathLikePython(parent);
74
+ let dest = join(parentResolved, stem);
75
+ for (let attempt = 0; lexists(dest); attempt += 1) {
76
+ if (attempt >= 1000)
77
+ throw new ArchiveRejected('Could not allocate a unique extraction directory');
78
+ dest = join(parentResolved, `${stem}_${String(randomInt(1000)).padStart(3, '0')}`);
79
+ }
80
+ const slip = isZip ? 'Zip' : 'Tar';
81
+ const plan = members.map((member) => {
82
+ let target;
83
+ try {
84
+ target = safeResolve(dest, member.name);
85
+ }
86
+ catch {
87
+ throw new ArchiveRejected(`${slip}-slip blocked: ${member.name}`);
88
+ }
89
+ if (target === dest)
90
+ throw new ArchiveRejected(`${slip}-slip blocked: ${member.name}`);
91
+ return { target, read: member.read };
92
+ });
93
+ makeAnchoredDir(root, dest);
94
+ try {
95
+ for (const { target, read } of plan) {
96
+ let data;
97
+ try {
98
+ data = read();
99
+ }
100
+ catch (error) {
101
+ throw error instanceof BadZipError ? new CorruptArchive(error.message) : error;
102
+ }
103
+ const fd = openAnchoredCreateFd(root, target);
104
+ try {
105
+ writeFully(fd, data);
106
+ }
107
+ finally {
108
+ closeSync(fd);
109
+ }
110
+ }
111
+ }
112
+ catch (error) {
113
+ try {
114
+ rmtreeAnchored(root, dest);
115
+ }
116
+ catch { /* the directory is already gone */ }
117
+ throw error;
118
+ }
119
+ return { extracted: plan.length, files: plan.map(({ target }) => relative(parentResolved, target)), dest };
120
+ }
121
+ function zipMembers(bytes) {
122
+ try {
123
+ return readZip(bytes).filter((entry) => !entry.isDir);
124
+ }
125
+ catch (error) {
126
+ throw error instanceof BadZipError ? new CorruptArchive(`File is not a zip file: ${error.message}`) : error;
127
+ }
128
+ }
129
+ /** The raw tar stream, decompressed by magic number like Python `tarfile.open(mode='r:*')`, never past `limit` bytes. */
130
+ async function decompressTar(bytes, limit, cap) {
131
+ if (bytes[0] === 0x1f && bytes[1] === 0x8b) {
132
+ try {
133
+ return gunzipSync(bytes, { maxOutputLength: limit });
134
+ }
135
+ catch (error) {
136
+ if (error.code === 'ERR_BUFFER_TOO_LARGE')
137
+ throw tooLarge(cap);
138
+ throw new CorruptArchive('Invalid gzip data');
139
+ }
140
+ }
141
+ if (bytes.subarray(0, 3).toString('latin1') === 'BZh') {
142
+ let out = Buffer.allocUnsafe(64 * 1024);
143
+ let pos = 0;
144
+ const sink = {
145
+ writeByte(byte) {
146
+ if (pos >= limit)
147
+ throw tooLarge(cap);
148
+ if (pos === out.length) {
149
+ const grown = Buffer.allocUnsafe(Math.min(out.length * 2, limit));
150
+ out.copy(grown);
151
+ out = grown;
152
+ }
153
+ out[pos++] = byte;
154
+ },
155
+ };
156
+ try {
157
+ Bunzip.decode(bytes, sink, true);
158
+ }
159
+ catch (error) {
160
+ if (error instanceof ArchiveRejected)
161
+ throw error;
162
+ throw new CorruptArchive('Invalid bzip2 data');
163
+ }
164
+ return out.subarray(0, pos);
165
+ }
166
+ if (bytes.subarray(0, 6).equals(Buffer.from([0xfd, 0x37, 0x7a, 0x58, 0x5a, 0x00]))) {
167
+ const reader = new XzReadableStream(new Blob([bytes]).stream()).getReader();
168
+ const chunks = [];
169
+ let total = 0;
170
+ try {
171
+ for (;;) {
172
+ const { done, value } = await reader.read();
173
+ if (done)
174
+ break;
175
+ total += value.length;
176
+ if (total > limit) {
177
+ await reader.cancel();
178
+ throw tooLarge(cap);
179
+ }
180
+ chunks.push(Buffer.from(value));
181
+ }
182
+ }
183
+ catch (error) {
184
+ if (error instanceof ArchiveRejected)
185
+ throw error;
186
+ throw new CorruptArchive('Invalid xz data');
187
+ }
188
+ return Buffer.concat(chunks, total);
189
+ }
190
+ return bytes;
191
+ }
192
+ const BLOCK = 512;
193
+ const REGULAR_TYPES = new Set(['0', '\0', '7']);
194
+ /** Python `tarfile`: these member types carry no data blocks even when their size field is set. */
195
+ const DATALESS_TYPES = new Set(['1', '2', '3', '4', '5', '6']);
196
+ function cString(buf, start, length) {
197
+ const field = buf.subarray(start, start + length);
198
+ const nul = field.indexOf(0);
199
+ return (nul < 0 ? field : field.subarray(0, nul)).toString('utf8');
200
+ }
201
+ /** Python `tarfile.nti`: an octal field, or GNU base-256 when the high bit is set. */
202
+ function tarNumber(header, start, length) {
203
+ const first = header[start] ?? 0;
204
+ if (first === 0o200) {
205
+ let n = 0;
206
+ for (let i = start + 1; i < start + length; i += 1)
207
+ n = n * 256 + (header[i] ?? 0);
208
+ return n;
209
+ }
210
+ if (first === 0o377)
211
+ throw new CorruptArchive('Invalid tar header');
212
+ const text = cString(header, start, length).trim();
213
+ if (!text)
214
+ return 0;
215
+ if (!/^[0-7]+$/.test(text))
216
+ throw new CorruptArchive('Invalid tar header');
217
+ return Number.parseInt(text, 8);
218
+ }
219
+ /** Python `tarfile.calc_chksums`: the stored checksum may be the unsigned or the signed byte sum. */
220
+ function checksumOk(header) {
221
+ let unsigned = 256;
222
+ let signed = 256;
223
+ for (let i = 0; i < BLOCK; i += 1) {
224
+ if (i >= 148 && i < 156)
225
+ continue;
226
+ const byte = header[i] ?? 0;
227
+ unsigned += byte;
228
+ signed += byte > 127 ? byte - 256 : byte;
229
+ }
230
+ const stored = tarNumber(header, 148, 8);
231
+ return stored === unsigned || stored === signed;
232
+ }
233
+ function paxRecords(data) {
234
+ const records = new Map();
235
+ let pos = 0;
236
+ while (pos < data.length && data[pos] !== 0) {
237
+ const space = data.indexOf(0x20, pos);
238
+ const length = space < 0 ? Number.NaN : Number(data.subarray(pos, space).toString('latin1'));
239
+ if (!Number.isInteger(length) || length <= space - pos || pos + length > data.length || data[pos + length - 1] !== 0x0a)
240
+ throw new CorruptArchive('Invalid pax header');
241
+ const record = data.subarray(space + 1, pos + length - 1).toString('utf8');
242
+ const eq = record.indexOf('=');
243
+ if (eq < 0)
244
+ throw new CorruptArchive('Invalid pax header');
245
+ records.set(record.slice(0, eq), record.slice(eq + 1));
246
+ pos += length;
247
+ }
248
+ return records;
249
+ }
250
+ /** A small ustar/pax/GNU reader: yields regular-file members only (links, devices, and directories are skipped). */
251
+ function* tarMembers(tar) {
252
+ if (tar.length < BLOCK)
253
+ throw new CorruptArchive('Invalid tar archive');
254
+ let offset = 0;
255
+ let longName = null;
256
+ let pax = new Map();
257
+ while (offset + BLOCK <= tar.length) {
258
+ const header = tar.subarray(offset, offset + BLOCK);
259
+ if (header.every((byte) => byte === 0))
260
+ return;
261
+ if (!checksumOk(header))
262
+ throw new CorruptArchive(offset === 0 ? 'Invalid tar archive' : 'Invalid tar header');
263
+ let name = cString(header, 0, 100);
264
+ if (header.subarray(257, 263).toString('latin1') === 'ustar\0') {
265
+ const prefix = cString(header, 345, 155);
266
+ if (prefix)
267
+ name = `${prefix}/${name}`;
268
+ }
269
+ let size = tarNumber(header, 124, 12);
270
+ let type = String.fromCharCode(header[156] ?? 0);
271
+ const dataStart = offset + BLOCK;
272
+ const padded = (n) => Math.ceil(n / BLOCK) * BLOCK;
273
+ if (type === 'x' || type === 'g' || type === 'L' || type === 'K') {
274
+ if (dataStart + size > tar.length)
275
+ throw new CorruptArchive('Unexpected end of tar data');
276
+ const data = tar.subarray(dataStart, dataStart + size);
277
+ if (type === 'x')
278
+ pax = paxRecords(data);
279
+ else if (type === 'L')
280
+ longName = cString(data, 0, data.length);
281
+ offset = dataStart + padded(size);
282
+ continue;
283
+ }
284
+ if (longName !== null)
285
+ name = longName;
286
+ const paxPath = pax.get('path');
287
+ if (paxPath !== undefined)
288
+ name = paxPath;
289
+ const paxSize = pax.get('size');
290
+ if (paxSize !== undefined) {
291
+ if (!/^\d+$/.test(paxSize))
292
+ throw new CorruptArchive('Invalid pax header');
293
+ size = Number(paxSize);
294
+ }
295
+ longName = null;
296
+ pax = new Map();
297
+ if (type === '\0' && name.endsWith('/'))
298
+ type = '5';
299
+ if (REGULAR_TYPES.has(type)) {
300
+ if (dataStart + size > tar.length)
301
+ throw new CorruptArchive('Unexpected end of tar data');
302
+ const data = tar.subarray(dataStart, dataStart + size);
303
+ yield { name, size, read: () => data };
304
+ }
305
+ offset = dataStart + (DATALESS_TYPES.has(type) ? 0 : padded(size));
306
+ }
307
+ }
308
+ //# sourceMappingURL=extract.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"extract.js","sourceRoot":"","sources":["../../src/workspace/extract.ts"],"names":[],"mappings":"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"}
@@ -7,6 +7,11 @@ export declare class NotFoundError extends Error {
7
7
  export declare function safeResolveWs(root: string, requested: string): string;
8
8
  /** Python `helpers.safe_resolve`: same rule, different error text. */
9
9
  export declare function safeResolve(root: string, requested: string): string;
10
+ /** Run `fn` with every anchored open of `root` refused unless the root is still the inode `id`. */
11
+ export declare function withPinnedRoot<T>(root: string, id: {
12
+ dev: number;
13
+ ino: number;
14
+ }, fn: () => T): T;
10
15
  /** Open `target` for reading with the anchored walk (Python `open_anchored_fd`). Caller closes the fd. */
11
16
  export declare function openAnchoredFd(root: string, target: string, opts: {
12
17
  wantDir: boolean;
@@ -20,6 +25,11 @@ export declare function openAnchoredWriteFd(root: string, target: string): numbe
20
25
  export declare function unlinkAnchored(root: string, target: string): void;
21
26
  /** Remove an empty directory through the anchored walk; a non-empty or symlinked target is left alone (throws). */
22
27
  export declare function rmdirAnchored(root: string, target: string): void;
28
+ /**
29
+ * Remove a directory tree through the anchored walk (Python `shutil.rmtree(dir_fd=...)`): every directory is
30
+ * opened from its parent's descriptor with `O_NOFOLLOW` and emptied through its own, so an entry swapped for a
31
+ * symlink mid-walk is unlinked as a link and never followed.
32
+ */
23
33
  export declare function rmtreeAnchored(root: string, target: string): void;
24
34
  export declare function renameAnchored(root: string, source: string, dest: string): void;
25
35
  /**
@@ -59,6 +69,8 @@ export interface FileContent {
59
69
  }
60
70
  export declare class FileTooLargeError extends Error {
61
71
  }
72
+ /** `raw` as UTF-8 text, or null for a binary file (a NUL byte, or bytes that do not round-trip). */
73
+ export declare function decodeText(raw: Buffer): string | null;
62
74
  /** Python `read_file_content` (office previews were dropped with TAL-245). */
63
75
  export declare function readFileContent(workspace: string, rel: string, opts?: {
64
76
  statOnly?: boolean;
@@ -11,7 +11,7 @@
11
11
  * a pathname swapped underneath us can never be followed. The sections are
12
12
  * synchronous, so nothing else in the process observes the temporary cwd.
13
13
  */
14
- import { closeSync, constants, existsSync, fstatSync, ftruncateSync, lstatSync, mkdirSync, openSync, readdirSync, readlinkSync, renameSync, rmdirSync, rmSync, statSync, unlinkSync } from 'node:fs';
14
+ import { closeSync, constants, existsSync, fstatSync, ftruncateSync, lstatSync, mkdirSync, openSync, readdirSync, readlinkSync, renameSync, rmdirSync, statSync, unlinkSync } from 'node:fs';
15
15
  import { createHash, randomBytes } from 'node:crypto';
16
16
  import { basename, dirname, join, relative, resolve, sep } from 'node:path';
17
17
  import { isWithin, resolvePathLikePython } from './paths.js';
@@ -135,6 +135,36 @@ function openChildDir(dir, name, opts = {}) {
135
135
  });
136
136
  return new DirHandle(fd, join(dir.path, name));
137
137
  }
138
+ /** A root whose pathname the caller validated earlier (escape grants): opening it must still yield that inode. */
139
+ let pinnedRoot = null;
140
+ /** Run `fn` with every anchored open of `root` refused unless the root is still the inode `id`. */
141
+ export function withPinnedRoot(root, id, fn) {
142
+ const previous = pinnedRoot;
143
+ pinnedRoot = { path: root, dev: id.dev, ino: id.ino };
144
+ try {
145
+ return fn();
146
+ }
147
+ finally {
148
+ pinnedRoot = previous;
149
+ }
150
+ }
151
+ function openRoot(root, rootResolved, target) {
152
+ let fd;
153
+ try {
154
+ fd = openSync(rootResolved, constants.O_RDONLY | O_DIRECTORY | O_NOFOLLOW);
155
+ }
156
+ catch {
157
+ throw new NotFoundError(`Not found: ${target}`);
158
+ }
159
+ if (pinnedRoot?.path === root) {
160
+ const st = fstatSync(fd);
161
+ if (st.dev !== pinnedRoot.dev || st.ino !== pinnedRoot.ino) {
162
+ closeSync(fd);
163
+ throw new NotFoundError(`Not found: ${target}`);
164
+ }
165
+ }
166
+ return fd;
167
+ }
138
168
  /** Walk from the root to the parent of the leaf, one descriptor at a time. Caller closes the returned handle. */
139
169
  function openAnchoredParent(root, target, opts = {}) {
140
170
  const rootResolved = resolvePathLikePython(root);
@@ -144,14 +174,7 @@ function openAnchoredParent(root, target, opts = {}) {
144
174
  const leaf = parts[parts.length - 1] ?? '';
145
175
  if (!leaf || leaf === '.' || leaf === '..')
146
176
  throw new PathTraversalError(`Invalid target: ${target}`);
147
- let fd;
148
- try {
149
- fd = openSync(rootResolved, constants.O_RDONLY | O_DIRECTORY | O_NOFOLLOW);
150
- }
151
- catch {
152
- throw new NotFoundError(`Not found: ${target}`);
153
- }
154
- let dir = new DirHandle(fd, rootResolved);
177
+ let dir = new DirHandle(openRoot(root, rootResolved, target), rootResolved);
155
178
  try {
156
179
  for (const part of parts.slice(0, -1)) {
157
180
  if (!part || part === '.' || part === '..')
@@ -173,12 +196,7 @@ export function openAnchoredFd(root, target, opts) {
173
196
  if (relParts(rootResolved, target).length === 0) {
174
197
  if (!opts.wantDir)
175
198
  throw new NotFoundError(`Not found: ${target}`);
176
- try {
177
- return openSync(rootResolved, constants.O_RDONLY | O_DIRECTORY | O_NOFOLLOW);
178
- }
179
- catch {
180
- throw new NotFoundError(`Not found: ${target}`);
181
- }
199
+ return openRoot(root, rootResolved, target);
182
200
  }
183
201
  const { dir, leaf } = openAnchoredParent(root, target);
184
202
  try {
@@ -273,16 +291,24 @@ export function rmdirAnchored(root, target) {
273
291
  dir.close();
274
292
  }
275
293
  }
294
+ /**
295
+ * Remove a directory tree through the anchored walk (Python `shutil.rmtree(dir_fd=...)`): every directory is
296
+ * opened from its parent's descriptor with `O_NOFOLLOW` and emptied through its own, so an entry swapped for a
297
+ * symlink mid-walk is unlinked as a link and never followed.
298
+ */
276
299
  export function rmtreeAnchored(root, target) {
277
300
  const targetResolved = resolvePathLikePython(target);
278
301
  const { dir, leaf } = openAnchoredParent(root, targetResolved);
279
302
  try {
280
- dir.anchored(() => {
281
- const entry = lstatSync(dir.child(leaf));
282
- if (entry.isSymbolicLink())
283
- throw new NotFoundError(`Not found: ${target}`);
284
- rmSync(dir.child(leaf), { recursive: true, force: false });
285
- });
303
+ // The leaf itself must still be a real directory; a symlinked or non-directory leaf is refused, not unlinked.
304
+ const sub = openChildDir(dir, leaf);
305
+ try {
306
+ emptyAnchoredDir(sub);
307
+ }
308
+ finally {
309
+ sub.close();
310
+ }
311
+ dir.anchored(() => { rmdirSync(dir.child(leaf)); });
286
312
  }
287
313
  catch (error) {
288
314
  if (error instanceof NotFoundError)
@@ -293,6 +319,44 @@ export function rmtreeAnchored(root, target) {
293
319
  dir.close();
294
320
  }
295
321
  }
322
+ /**
323
+ * Remove every entry of `dir` through its descriptor (Python `_rmtree_safe_fd`). Each subdirectory is opened
324
+ * `O_NOFOLLOW` and must still be the inode listed, so one swapped for another directory fails closed and one swapped
325
+ * for a symlink fails the open and is unlinked as a link. Subdirectories are emptied outside the anchored section
326
+ * so the cwd fallback never nests.
327
+ */
328
+ function emptyAnchoredDir(dir) {
329
+ const subdirs = dir.anchored(() => {
330
+ const found = [];
331
+ for (const name of readdirSync(dir.child('.'))) {
332
+ const listed = lstatSync(dir.child(name));
333
+ if (listed.isDirectory())
334
+ found.push({ name, listed });
335
+ else
336
+ unlinkSync(dir.child(name));
337
+ }
338
+ return found;
339
+ });
340
+ for (const { name, listed } of subdirs) {
341
+ let sub;
342
+ try {
343
+ sub = openChildDir(dir, name);
344
+ }
345
+ catch {
346
+ dir.anchored(() => { unlinkSync(dir.child(name)); });
347
+ continue;
348
+ }
349
+ try {
350
+ if (!sameFile(fstatSync(sub.fd), listed))
351
+ throw new NotFoundError(`Not found: ${sub.path}`);
352
+ emptyAnchoredDir(sub);
353
+ }
354
+ finally {
355
+ sub.close();
356
+ }
357
+ dir.anchored(() => { rmdirSync(dir.child(name)); });
358
+ }
359
+ }
296
360
  export function renameAnchored(root, source, dest) {
297
361
  const rootResolved = resolvePathLikePython(root);
298
362
  const sourceResolved = resolvePathLikePython(source);
@@ -510,6 +574,11 @@ function sortKeysDeep(value) {
510
574
  }
511
575
  export class FileTooLargeError extends Error {
512
576
  }
577
+ /** `raw` as UTF-8 text, or null for a binary file (a NUL byte, or bytes that do not round-trip). */
578
+ export function decodeText(raw) {
579
+ const content = raw.toString('utf8');
580
+ return raw.includes(0) || (content.includes('\uFFFD') && !raw.equals(Buffer.from(content, 'utf8'))) ? null : content;
581
+ }
513
582
  /** Python `read_file_content` (office previews were dropped with TAL-245). */
514
583
  export function readFileContent(workspace, rel, opts = {}) {
515
584
  const target = safeResolveWs(workspace, rel);
@@ -540,8 +609,8 @@ export function readFileContent(workspace, rel, opts = {}) {
540
609
  total += n;
541
610
  }
542
611
  const raw = buf.subarray(0, total);
543
- const content = raw.toString('utf8');
544
- if (raw.includes(0) || (content.includes('\uFFFD') && !raw.equals(Buffer.from(content, 'utf8'))))
612
+ const content = decodeText(raw);
613
+ if (content === null)
545
614
  return { path: rel, size: raw.length, binary: true };
546
615
  return { path: rel, content, size: raw.length, lines: (content.match(/\n/g)?.length ?? 0) + 1 };
547
616
  }