@aigne/aos 0.2.0-beta

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 (533) hide show
  1. package/CHANGELOG.md +49 -0
  2. package/LICENSE.md +26 -0
  3. package/dist/agent-dsl.cjs +116 -0
  4. package/dist/agent-dsl.d.cts +31 -0
  5. package/dist/agent-dsl.d.cts.map +1 -0
  6. package/dist/agent-dsl.d.mts +31 -0
  7. package/dist/agent-dsl.d.mts.map +1 -0
  8. package/dist/agent-dsl.mjs +115 -0
  9. package/dist/agent-dsl.mjs.map +1 -0
  10. package/dist/arc-compat.cjs +125 -0
  11. package/dist/arc-compat.d.cts +17 -0
  12. package/dist/arc-compat.d.cts.map +1 -0
  13. package/dist/arc-compat.d.mts +17 -0
  14. package/dist/arc-compat.d.mts.map +1 -0
  15. package/dist/arc-compat.mjs +123 -0
  16. package/dist/arc-compat.mjs.map +1 -0
  17. package/dist/auto-surface/compiler.cjs +36 -0
  18. package/dist/auto-surface/compiler.d.cts +7 -0
  19. package/dist/auto-surface/compiler.d.cts.map +1 -0
  20. package/dist/auto-surface/compiler.d.mts +7 -0
  21. package/dist/auto-surface/compiler.d.mts.map +1 -0
  22. package/dist/auto-surface/compiler.mjs +37 -0
  23. package/dist/auto-surface/compiler.mjs.map +1 -0
  24. package/dist/auto-surface/definition-dsl.cjs +333 -0
  25. package/dist/auto-surface/definition-dsl.d.cts +41 -0
  26. package/dist/auto-surface/definition-dsl.d.cts.map +1 -0
  27. package/dist/auto-surface/definition-dsl.d.mts +41 -0
  28. package/dist/auto-surface/definition-dsl.d.mts.map +1 -0
  29. package/dist/auto-surface/definition-dsl.mjs +332 -0
  30. package/dist/auto-surface/definition-dsl.mjs.map +1 -0
  31. package/dist/auto-surface/fragments.cjs +177 -0
  32. package/dist/auto-surface/fragments.d.cts +23 -0
  33. package/dist/auto-surface/fragments.d.cts.map +1 -0
  34. package/dist/auto-surface/fragments.d.mts +23 -0
  35. package/dist/auto-surface/fragments.d.mts.map +1 -0
  36. package/dist/auto-surface/fragments.mjs +175 -0
  37. package/dist/auto-surface/fragments.mjs.map +1 -0
  38. package/dist/auto-surface/index.d.mts +9 -0
  39. package/dist/auto-surface/layering.cjs +43 -0
  40. package/dist/auto-surface/layering.d.cts +7 -0
  41. package/dist/auto-surface/layering.d.cts.map +1 -0
  42. package/dist/auto-surface/layering.d.mts +7 -0
  43. package/dist/auto-surface/layering.d.mts.map +1 -0
  44. package/dist/auto-surface/layering.mjs +43 -0
  45. package/dist/auto-surface/layering.mjs.map +1 -0
  46. package/dist/auto-surface/projection.cjs +11 -0
  47. package/dist/auto-surface/projection.d.cts +11 -0
  48. package/dist/auto-surface/projection.d.cts.map +1 -0
  49. package/dist/auto-surface/projection.d.mts +11 -0
  50. package/dist/auto-surface/projection.d.mts.map +1 -0
  51. package/dist/auto-surface/projection.mjs +12 -0
  52. package/dist/auto-surface/projection.mjs.map +1 -0
  53. package/dist/auto-surface/projectors/settings-shell.cjs +114 -0
  54. package/dist/auto-surface/projectors/settings-shell.d.cts +10 -0
  55. package/dist/auto-surface/projectors/settings-shell.d.cts.map +1 -0
  56. package/dist/auto-surface/projectors/settings-shell.d.mts +10 -0
  57. package/dist/auto-surface/projectors/settings-shell.d.mts.map +1 -0
  58. package/dist/auto-surface/projectors/settings-shell.mjs +114 -0
  59. package/dist/auto-surface/projectors/settings-shell.mjs.map +1 -0
  60. package/dist/auto-surface/scenario.cjs +38 -0
  61. package/dist/auto-surface/scenario.d.cts +31 -0
  62. package/dist/auto-surface/scenario.d.cts.map +1 -0
  63. package/dist/auto-surface/scenario.d.mts +31 -0
  64. package/dist/auto-surface/scenario.d.mts.map +1 -0
  65. package/dist/auto-surface/scenario.mjs +37 -0
  66. package/dist/auto-surface/scenario.mjs.map +1 -0
  67. package/dist/auto-surface/types.cjs +9 -0
  68. package/dist/auto-surface/types.d.cts +153 -0
  69. package/dist/auto-surface/types.d.cts.map +1 -0
  70. package/dist/auto-surface/types.d.mts +153 -0
  71. package/dist/auto-surface/types.d.mts.map +1 -0
  72. package/dist/auto-surface/types.mjs +9 -0
  73. package/dist/auto-surface/types.mjs.map +1 -0
  74. package/dist/auto-surface/value-dsl.cjs +80 -0
  75. package/dist/auto-surface/value-dsl.d.cts +24 -0
  76. package/dist/auto-surface/value-dsl.d.cts.map +1 -0
  77. package/dist/auto-surface/value-dsl.d.mts +24 -0
  78. package/dist/auto-surface/value-dsl.d.mts.map +1 -0
  79. package/dist/auto-surface/value-dsl.mjs +79 -0
  80. package/dist/auto-surface/value-dsl.mjs.map +1 -0
  81. package/dist/blocklet/activation.cjs +94 -0
  82. package/dist/blocklet/activation.d.cts +30 -0
  83. package/dist/blocklet/activation.d.cts.map +1 -0
  84. package/dist/blocklet/activation.d.mts +30 -0
  85. package/dist/blocklet/activation.d.mts.map +1 -0
  86. package/dist/blocklet/activation.mjs +94 -0
  87. package/dist/blocklet/activation.mjs.map +1 -0
  88. package/dist/blocklet/did-space-registry.cjs +282 -0
  89. package/dist/blocklet/did-space-registry.d.cts +82 -0
  90. package/dist/blocklet/did-space-registry.d.cts.map +1 -0
  91. package/dist/blocklet/did-space-registry.d.mts +82 -0
  92. package/dist/blocklet/did-space-registry.d.mts.map +1 -0
  93. package/dist/blocklet/did-space-registry.mjs +281 -0
  94. package/dist/blocklet/did-space-registry.mjs.map +1 -0
  95. package/dist/blocklet/handlers.cjs +66 -0
  96. package/dist/blocklet/handlers.d.cts +16 -0
  97. package/dist/blocklet/handlers.d.cts.map +1 -0
  98. package/dist/blocklet/handlers.d.mts +16 -0
  99. package/dist/blocklet/handlers.d.mts.map +1 -0
  100. package/dist/blocklet/handlers.mjs +65 -0
  101. package/dist/blocklet/handlers.mjs.map +1 -0
  102. package/dist/blocklet/index.d.mts +7 -0
  103. package/dist/blocklet/manifest.d.cts +2 -0
  104. package/dist/blocklet/manifest.d.mts +2 -0
  105. package/dist/blocklet/manifest.mjs +3 -0
  106. package/dist/blocklet/registry.cjs +447 -0
  107. package/dist/blocklet/registry.d.cts +197 -0
  108. package/dist/blocklet/registry.d.cts.map +1 -0
  109. package/dist/blocklet/registry.d.mts +197 -0
  110. package/dist/blocklet/registry.d.mts.map +1 -0
  111. package/dist/blocklet/registry.mjs +441 -0
  112. package/dist/blocklet/registry.mjs.map +1 -0
  113. package/dist/blocklet/static-render.cjs +183 -0
  114. package/dist/blocklet/static-render.d.cts +55 -0
  115. package/dist/blocklet/static-render.d.cts.map +1 -0
  116. package/dist/blocklet/static-render.d.mts +55 -0
  117. package/dist/blocklet/static-render.d.mts.map +1 -0
  118. package/dist/blocklet/static-render.mjs +181 -0
  119. package/dist/blocklet/static-render.mjs.map +1 -0
  120. package/dist/blocklet/types.d.cts +70 -0
  121. package/dist/blocklet/types.d.cts.map +1 -0
  122. package/dist/blocklet/types.d.mts +70 -0
  123. package/dist/blocklet/types.d.mts.map +1 -0
  124. package/dist/devices/chain.cjs +127 -0
  125. package/dist/devices/chain.d.cts +48 -0
  126. package/dist/devices/chain.d.cts.map +1 -0
  127. package/dist/devices/chain.d.mts +48 -0
  128. package/dist/devices/chain.d.mts.map +1 -0
  129. package/dist/devices/chain.mjs +125 -0
  130. package/dist/devices/chain.mjs.map +1 -0
  131. package/dist/dsl-shared.cjs +290 -0
  132. package/dist/dsl-shared.d.cts +54 -0
  133. package/dist/dsl-shared.d.cts.map +1 -0
  134. package/dist/dsl-shared.d.mts +54 -0
  135. package/dist/dsl-shared.d.mts.map +1 -0
  136. package/dist/dsl-shared.mjs +287 -0
  137. package/dist/dsl-shared.mjs.map +1 -0
  138. package/dist/http/afs-mcp.cjs +85 -0
  139. package/dist/http/afs-mcp.d.cts +14 -0
  140. package/dist/http/afs-mcp.d.cts.map +1 -0
  141. package/dist/http/afs-mcp.d.mts +14 -0
  142. package/dist/http/afs-mcp.d.mts.map +1 -0
  143. package/dist/http/afs-mcp.mjs +86 -0
  144. package/dist/http/afs-mcp.mjs.map +1 -0
  145. package/dist/http/afs-raw.cjs +264 -0
  146. package/dist/http/afs-raw.d.cts +31 -0
  147. package/dist/http/afs-raw.d.cts.map +1 -0
  148. package/dist/http/afs-raw.d.mts +31 -0
  149. package/dist/http/afs-raw.d.mts.map +1 -0
  150. package/dist/http/afs-raw.mjs +264 -0
  151. package/dist/http/afs-raw.mjs.map +1 -0
  152. package/dist/http/afs-rest.cjs +30 -0
  153. package/dist/http/afs-rest.d.cts +21 -0
  154. package/dist/http/afs-rest.d.cts.map +1 -0
  155. package/dist/http/afs-rest.d.mts +21 -0
  156. package/dist/http/afs-rest.d.mts.map +1 -0
  157. package/dist/http/afs-rest.mjs +31 -0
  158. package/dist/http/afs-rest.mjs.map +1 -0
  159. package/dist/http/afs-rpc-wire.cjs +271 -0
  160. package/dist/http/afs-rpc-wire.d.cts +195 -0
  161. package/dist/http/afs-rpc-wire.d.cts.map +1 -0
  162. package/dist/http/afs-rpc-wire.d.mts +195 -0
  163. package/dist/http/afs-rpc-wire.d.mts.map +1 -0
  164. package/dist/http/afs-rpc-wire.mjs +262 -0
  165. package/dist/http/afs-rpc-wire.mjs.map +1 -0
  166. package/dist/http/afs-rpc.cjs +729 -0
  167. package/dist/http/afs-rpc.d.cts +103 -0
  168. package/dist/http/afs-rpc.d.cts.map +1 -0
  169. package/dist/http/afs-rpc.d.mts +103 -0
  170. package/dist/http/afs-rpc.d.mts.map +1 -0
  171. package/dist/http/afs-rpc.mjs +729 -0
  172. package/dist/http/afs-rpc.mjs.map +1 -0
  173. package/dist/http/afs-upload.cjs +116 -0
  174. package/dist/http/afs-upload.d.cts +40 -0
  175. package/dist/http/afs-upload.d.cts.map +1 -0
  176. package/dist/http/afs-upload.d.mts +40 -0
  177. package/dist/http/afs-upload.d.mts.map +1 -0
  178. package/dist/http/afs-upload.mjs +116 -0
  179. package/dist/http/afs-upload.mjs.map +1 -0
  180. package/dist/http/aup-client.cjs +60 -0
  181. package/dist/http/aup-client.d.cts +22 -0
  182. package/dist/http/aup-client.d.cts.map +1 -0
  183. package/dist/http/aup-client.d.mts +22 -0
  184. package/dist/http/aup-client.d.mts.map +1 -0
  185. package/dist/http/aup-client.mjs +59 -0
  186. package/dist/http/aup-client.mjs.map +1 -0
  187. package/dist/http/aup-event.cjs +100 -0
  188. package/dist/http/aup-event.d.cts +38 -0
  189. package/dist/http/aup-event.d.cts.map +1 -0
  190. package/dist/http/aup-event.d.mts +38 -0
  191. package/dist/http/aup-event.d.mts.map +1 -0
  192. package/dist/http/aup-event.mjs +101 -0
  193. package/dist/http/aup-event.mjs.map +1 -0
  194. package/dist/http/auth-context.cjs +66 -0
  195. package/dist/http/auth-context.d.cts +64 -0
  196. package/dist/http/auth-context.d.cts.map +1 -0
  197. package/dist/http/auth-context.d.mts +64 -0
  198. package/dist/http/auth-context.d.mts.map +1 -0
  199. package/dist/http/auth-context.mjs +66 -0
  200. package/dist/http/auth-context.mjs.map +1 -0
  201. package/dist/http/csrf.cjs +50 -0
  202. package/dist/http/csrf.d.cts +8 -0
  203. package/dist/http/csrf.d.cts.map +1 -0
  204. package/dist/http/csrf.d.mts +8 -0
  205. package/dist/http/csrf.d.mts.map +1 -0
  206. package/dist/http/csrf.mjs +49 -0
  207. package/dist/http/csrf.mjs.map +1 -0
  208. package/dist/http/handlers.cjs +106 -0
  209. package/dist/http/handlers.d.cts +39 -0
  210. package/dist/http/handlers.d.cts.map +1 -0
  211. package/dist/http/handlers.d.mts +39 -0
  212. package/dist/http/handlers.d.mts.map +1 -0
  213. package/dist/http/handlers.mjs +104 -0
  214. package/dist/http/handlers.mjs.map +1 -0
  215. package/dist/http/index.d.mts +1 -0
  216. package/dist/http/ingest-facade.cjs +315 -0
  217. package/dist/http/ingest-facade.mjs +314 -0
  218. package/dist/http/ingest-facade.mjs.map +1 -0
  219. package/dist/http/raw-url.cjs +136 -0
  220. package/dist/http/raw-url.d.cts +54 -0
  221. package/dist/http/raw-url.d.cts.map +1 -0
  222. package/dist/http/raw-url.d.mts +54 -0
  223. package/dist/http/raw-url.d.mts.map +1 -0
  224. package/dist/http/raw-url.mjs +136 -0
  225. package/dist/http/raw-url.mjs.map +1 -0
  226. package/dist/http/request-context.cjs +178 -0
  227. package/dist/http/request-context.d.cts +76 -0
  228. package/dist/http/request-context.d.cts.map +1 -0
  229. package/dist/http/request-context.d.mts +76 -0
  230. package/dist/http/request-context.d.mts.map +1 -0
  231. package/dist/http/request-context.mjs +179 -0
  232. package/dist/http/request-context.mjs.map +1 -0
  233. package/dist/index.cjs +197 -0
  234. package/dist/index.d.cts +63 -0
  235. package/dist/index.d.mts +68 -0
  236. package/dist/index.mjs +61 -0
  237. package/dist/mcp/index.cjs +9 -0
  238. package/dist/mcp/index.d.cts +5 -0
  239. package/dist/mcp/index.d.mts +5 -0
  240. package/dist/mcp/index.mjs +6 -0
  241. package/dist/mcp/prompts.cjs +17 -0
  242. package/dist/mcp/prompts.d.cts +8 -0
  243. package/dist/mcp/prompts.d.cts.map +1 -0
  244. package/dist/mcp/prompts.d.mts +8 -0
  245. package/dist/mcp/prompts.d.mts.map +1 -0
  246. package/dist/mcp/prompts.mjs +17 -0
  247. package/dist/mcp/prompts.mjs.map +1 -0
  248. package/dist/mcp/resources.cjs +22 -0
  249. package/dist/mcp/resources.d.cts +8 -0
  250. package/dist/mcp/resources.d.cts.map +1 -0
  251. package/dist/mcp/resources.d.mts +8 -0
  252. package/dist/mcp/resources.d.mts.map +1 -0
  253. package/dist/mcp/resources.mjs +22 -0
  254. package/dist/mcp/resources.mjs.map +1 -0
  255. package/dist/mcp/server.cjs +51 -0
  256. package/dist/mcp/server.d.cts +20 -0
  257. package/dist/mcp/server.d.cts.map +1 -0
  258. package/dist/mcp/server.d.mts +20 -0
  259. package/dist/mcp/server.d.mts.map +1 -0
  260. package/dist/mcp/server.mjs +52 -0
  261. package/dist/mcp/server.mjs.map +1 -0
  262. package/dist/mcp/tools.cjs +218 -0
  263. package/dist/mcp/tools.d.cts +8 -0
  264. package/dist/mcp/tools.d.cts.map +1 -0
  265. package/dist/mcp/tools.d.mts +8 -0
  266. package/dist/mcp/tools.d.mts.map +1 -0
  267. package/dist/mcp/tools.mjs +219 -0
  268. package/dist/mcp/tools.mjs.map +1 -0
  269. package/dist/mcp/utils.cjs +75 -0
  270. package/dist/mcp/utils.mjs +69 -0
  271. package/dist/mcp/utils.mjs.map +1 -0
  272. package/dist/mount/index.cjs +4 -0
  273. package/dist/mount/index.d.cts +3 -0
  274. package/dist/mount/index.d.mts +3 -0
  275. package/dist/mount/index.mjs +3 -0
  276. package/dist/mount/materializer.cjs +167 -0
  277. package/dist/mount/materializer.d.cts +97 -0
  278. package/dist/mount/materializer.d.cts.map +1 -0
  279. package/dist/mount/materializer.d.mts +97 -0
  280. package/dist/mount/materializer.d.mts.map +1 -0
  281. package/dist/mount/materializer.mjs +167 -0
  282. package/dist/mount/materializer.mjs.map +1 -0
  283. package/dist/mount/types.d.cts +90 -0
  284. package/dist/mount/types.d.cts.map +1 -0
  285. package/dist/mount/types.d.mts +90 -0
  286. package/dist/mount/types.d.mts.map +1 -0
  287. package/dist/mount-config.cjs +61 -0
  288. package/dist/mount-config.d.cts +19 -0
  289. package/dist/mount-config.d.cts.map +1 -0
  290. package/dist/mount-config.d.mts +19 -0
  291. package/dist/mount-config.d.mts.map +1 -0
  292. package/dist/mount-config.mjs +61 -0
  293. package/dist/mount-config.mjs.map +1 -0
  294. package/dist/projectors/aup-projector.cjs +190 -0
  295. package/dist/projectors/aup-projector.d.cts +59 -0
  296. package/dist/projectors/aup-projector.d.cts.map +1 -0
  297. package/dist/projectors/aup-projector.d.mts +59 -0
  298. package/dist/projectors/aup-projector.d.mts.map +1 -0
  299. package/dist/projectors/aup-projector.mjs +188 -0
  300. package/dist/projectors/aup-projector.mjs.map +1 -0
  301. package/dist/projectors/index.cjs +6 -0
  302. package/dist/projectors/index.d.cts +2 -0
  303. package/dist/projectors/index.d.mts +2 -0
  304. package/dist/projectors/index.mjs +3 -0
  305. package/dist/scaffold/afs.cjs +195 -0
  306. package/dist/scaffold/afs.d.cts +16 -0
  307. package/dist/scaffold/afs.d.cts.map +1 -0
  308. package/dist/scaffold/afs.d.mts +16 -0
  309. package/dist/scaffold/afs.d.mts.map +1 -0
  310. package/dist/scaffold/afs.mjs +195 -0
  311. package/dist/scaffold/afs.mjs.map +1 -0
  312. package/dist/scaffold/composition.cjs +92 -0
  313. package/dist/scaffold/composition.d.cts +10 -0
  314. package/dist/scaffold/composition.d.cts.map +1 -0
  315. package/dist/scaffold/composition.d.mts +10 -0
  316. package/dist/scaffold/composition.d.mts.map +1 -0
  317. package/dist/scaffold/composition.mjs +92 -0
  318. package/dist/scaffold/composition.mjs.map +1 -0
  319. package/dist/scaffold/dsl-error.cjs +21 -0
  320. package/dist/scaffold/dsl-error.d.cts +11 -0
  321. package/dist/scaffold/dsl-error.d.cts.map +1 -0
  322. package/dist/scaffold/dsl-error.d.mts +11 -0
  323. package/dist/scaffold/dsl-error.d.mts.map +1 -0
  324. package/dist/scaffold/dsl-error.mjs +20 -0
  325. package/dist/scaffold/dsl-error.mjs.map +1 -0
  326. package/dist/scaffold/index.d.mts +12 -0
  327. package/dist/scaffold/manifest-dsl.cjs +188 -0
  328. package/dist/scaffold/manifest-dsl.d.cts +8 -0
  329. package/dist/scaffold/manifest-dsl.d.cts.map +1 -0
  330. package/dist/scaffold/manifest-dsl.d.mts +8 -0
  331. package/dist/scaffold/manifest-dsl.d.mts.map +1 -0
  332. package/dist/scaffold/manifest-dsl.mjs +188 -0
  333. package/dist/scaffold/manifest-dsl.mjs.map +1 -0
  334. package/dist/scaffold/module-dsl.cjs +284 -0
  335. package/dist/scaffold/module-dsl.d.cts +8 -0
  336. package/dist/scaffold/module-dsl.d.cts.map +1 -0
  337. package/dist/scaffold/module-dsl.d.mts +8 -0
  338. package/dist/scaffold/module-dsl.d.mts.map +1 -0
  339. package/dist/scaffold/module-dsl.mjs +284 -0
  340. package/dist/scaffold/module-dsl.mjs.map +1 -0
  341. package/dist/scaffold/resolver.cjs +156 -0
  342. package/dist/scaffold/resolver.d.cts +7 -0
  343. package/dist/scaffold/resolver.d.cts.map +1 -0
  344. package/dist/scaffold/resolver.d.mts +7 -0
  345. package/dist/scaffold/resolver.d.mts.map +1 -0
  346. package/dist/scaffold/resolver.mjs +156 -0
  347. package/dist/scaffold/resolver.mjs.map +1 -0
  348. package/dist/scaffold/runtime.cjs +24 -0
  349. package/dist/scaffold/runtime.d.cts +19 -0
  350. package/dist/scaffold/runtime.d.cts.map +1 -0
  351. package/dist/scaffold/runtime.d.mts +19 -0
  352. package/dist/scaffold/runtime.d.mts.map +1 -0
  353. package/dist/scaffold/runtime.mjs +25 -0
  354. package/dist/scaffold/runtime.mjs.map +1 -0
  355. package/dist/scaffold/shell-dsl.cjs +279 -0
  356. package/dist/scaffold/shell-dsl.d.cts +8 -0
  357. package/dist/scaffold/shell-dsl.d.cts.map +1 -0
  358. package/dist/scaffold/shell-dsl.d.mts +8 -0
  359. package/dist/scaffold/shell-dsl.d.mts.map +1 -0
  360. package/dist/scaffold/shell-dsl.mjs +279 -0
  361. package/dist/scaffold/shell-dsl.mjs.map +1 -0
  362. package/dist/scaffold/surface-dsl.cjs +182 -0
  363. package/dist/scaffold/surface-dsl.d.cts +8 -0
  364. package/dist/scaffold/surface-dsl.d.cts.map +1 -0
  365. package/dist/scaffold/surface-dsl.d.mts +8 -0
  366. package/dist/scaffold/surface-dsl.d.mts.map +1 -0
  367. package/dist/scaffold/surface-dsl.mjs +182 -0
  368. package/dist/scaffold/surface-dsl.mjs.map +1 -0
  369. package/dist/scaffold/surfaces.cjs +84 -0
  370. package/dist/scaffold/surfaces.d.cts +23 -0
  371. package/dist/scaffold/surfaces.d.cts.map +1 -0
  372. package/dist/scaffold/surfaces.d.mts +24 -0
  373. package/dist/scaffold/surfaces.d.mts.map +1 -0
  374. package/dist/scaffold/surfaces.mjs +84 -0
  375. package/dist/scaffold/surfaces.mjs.map +1 -0
  376. package/dist/scaffold/types.d.cts +264 -0
  377. package/dist/scaffold/types.d.cts.map +1 -0
  378. package/dist/scaffold/types.d.mts +265 -0
  379. package/dist/scaffold/types.d.mts.map +1 -0
  380. package/dist/scaffold/workspace-dsl.cjs +339 -0
  381. package/dist/scaffold/workspace-dsl.d.cts +49 -0
  382. package/dist/scaffold/workspace-dsl.d.cts.map +1 -0
  383. package/dist/scaffold/workspace-dsl.d.mts +49 -0
  384. package/dist/scaffold/workspace-dsl.d.mts.map +1 -0
  385. package/dist/scaffold/workspace-dsl.mjs +337 -0
  386. package/dist/scaffold/workspace-dsl.mjs.map +1 -0
  387. package/dist/scope/index.d.mts +3 -0
  388. package/dist/scope/read-blocklet-scope.cjs +29 -0
  389. package/dist/scope/read-blocklet-scope.d.cts +8 -0
  390. package/dist/scope/read-blocklet-scope.d.cts.map +1 -0
  391. package/dist/scope/read-blocklet-scope.d.mts +8 -0
  392. package/dist/scope/read-blocklet-scope.d.mts.map +1 -0
  393. package/dist/scope/read-blocklet-scope.mjs +30 -0
  394. package/dist/scope/read-blocklet-scope.mjs.map +1 -0
  395. package/dist/scope/resolve-scoped-afs.cjs +87 -0
  396. package/dist/scope/resolve-scoped-afs.d.cts +7 -0
  397. package/dist/scope/resolve-scoped-afs.d.cts.map +1 -0
  398. package/dist/scope/resolve-scoped-afs.d.mts +7 -0
  399. package/dist/scope/resolve-scoped-afs.d.mts.map +1 -0
  400. package/dist/scope/resolve-scoped-afs.mjs +88 -0
  401. package/dist/scope/resolve-scoped-afs.mjs.map +1 -0
  402. package/dist/scope/types.d.cts +25 -0
  403. package/dist/scope/types.d.cts.map +1 -0
  404. package/dist/scope/types.d.mts +25 -0
  405. package/dist/scope/types.d.mts.map +1 -0
  406. package/dist/session/backends.cjs +90 -0
  407. package/dist/session/backends.d.cts +35 -0
  408. package/dist/session/backends.d.cts.map +1 -0
  409. package/dist/session/backends.d.mts +35 -0
  410. package/dist/session/backends.d.mts.map +1 -0
  411. package/dist/session/backends.mjs +89 -0
  412. package/dist/session/backends.mjs.map +1 -0
  413. package/dist/session/replication-resolver.cjs +323 -0
  414. package/dist/session/replication-resolver.d.cts +71 -0
  415. package/dist/session/replication-resolver.d.cts.map +1 -0
  416. package/dist/session/replication-resolver.d.mts +71 -0
  417. package/dist/session/replication-resolver.d.mts.map +1 -0
  418. package/dist/session/replication-resolver.mjs +323 -0
  419. package/dist/session/replication-resolver.mjs.map +1 -0
  420. package/dist/session/role-level.cjs +36 -0
  421. package/dist/session/role-level.d.cts +24 -0
  422. package/dist/session/role-level.d.cts.map +1 -0
  423. package/dist/session/role-level.d.mts +24 -0
  424. package/dist/session/role-level.d.mts.map +1 -0
  425. package/dist/session/role-level.mjs +35 -0
  426. package/dist/session/role-level.mjs.map +1 -0
  427. package/dist/session/session-dir-providers.cjs +254 -0
  428. package/dist/session/session-dir-providers.d.cts +32 -0
  429. package/dist/session/session-dir-providers.d.cts.map +1 -0
  430. package/dist/session/session-dir-providers.d.mts +32 -0
  431. package/dist/session/session-dir-providers.d.mts.map +1 -0
  432. package/dist/session/session-dir-providers.mjs +252 -0
  433. package/dist/session/session-dir-providers.mjs.map +1 -0
  434. package/dist/session/session-id.cjs +20 -0
  435. package/dist/session/session-id.d.cts +15 -0
  436. package/dist/session/session-id.d.cts.map +1 -0
  437. package/dist/session/session-id.d.mts +15 -0
  438. package/dist/session/session-id.d.mts.map +1 -0
  439. package/dist/session/session-id.mjs +20 -0
  440. package/dist/session/session-id.mjs.map +1 -0
  441. package/dist/session/session-user-afs.cjs +899 -0
  442. package/dist/session/session-user-afs.d.cts +296 -0
  443. package/dist/session/session-user-afs.d.cts.map +1 -0
  444. package/dist/session/session-user-afs.d.mts +296 -0
  445. package/dist/session/session-user-afs.d.mts.map +1 -0
  446. package/dist/session/session-user-afs.mjs +896 -0
  447. package/dist/session/session-user-afs.mjs.map +1 -0
  448. package/dist/session/settings-cascade.cjs +69 -0
  449. package/dist/session/settings-cascade.d.cts +81 -0
  450. package/dist/session/settings-cascade.d.cts.map +1 -0
  451. package/dist/session/settings-cascade.d.mts +81 -0
  452. package/dist/session/settings-cascade.d.mts.map +1 -0
  453. package/dist/session/settings-cascade.mjs +69 -0
  454. package/dist/session/settings-cascade.mjs.map +1 -0
  455. package/dist/session/settings-resolver.cjs +770 -0
  456. package/dist/session/settings-resolver.d.cts +177 -0
  457. package/dist/session/settings-resolver.d.cts.map +1 -0
  458. package/dist/session/settings-resolver.d.mts +177 -0
  459. package/dist/session/settings-resolver.d.mts.map +1 -0
  460. package/dist/session/settings-resolver.mjs +771 -0
  461. package/dist/session/settings-resolver.mjs.map +1 -0
  462. package/dist/session/settings-schema-store.cjs +0 -0
  463. package/dist/session/settings-schema-store.d.cts +72 -0
  464. package/dist/session/settings-schema-store.d.cts.map +1 -0
  465. package/dist/session/settings-schema-store.d.mts +72 -0
  466. package/dist/session/settings-schema-store.d.mts.map +1 -0
  467. package/dist/session/settings-schema-store.mjs +0 -0
  468. package/dist/session/settings-schema-store.mjs.map +1 -0
  469. package/dist/system-mounts/index.cjs +14 -0
  470. package/dist/system-mounts/index.d.cts +6 -0
  471. package/dist/system-mounts/index.d.mts +6 -0
  472. package/dist/system-mounts/index.mjs +6 -0
  473. package/dist/system-mounts/install.cjs +101 -0
  474. package/dist/system-mounts/install.d.cts +36 -0
  475. package/dist/system-mounts/install.d.cts.map +1 -0
  476. package/dist/system-mounts/install.d.mts +37 -0
  477. package/dist/system-mounts/install.d.mts.map +1 -0
  478. package/dist/system-mounts/install.mjs +102 -0
  479. package/dist/system-mounts/install.mjs.map +1 -0
  480. package/dist/system-mounts/installers.cjs +247 -0
  481. package/dist/system-mounts/installers.d.cts +13 -0
  482. package/dist/system-mounts/installers.d.cts.map +1 -0
  483. package/dist/system-mounts/installers.d.mts +14 -0
  484. package/dist/system-mounts/installers.d.mts.map +1 -0
  485. package/dist/system-mounts/installers.mjs +244 -0
  486. package/dist/system-mounts/installers.mjs.map +1 -0
  487. package/dist/system-mounts/lists.cjs +122 -0
  488. package/dist/system-mounts/lists.d.cts +34 -0
  489. package/dist/system-mounts/lists.d.cts.map +1 -0
  490. package/dist/system-mounts/lists.d.mts +34 -0
  491. package/dist/system-mounts/lists.d.mts.map +1 -0
  492. package/dist/system-mounts/lists.mjs +122 -0
  493. package/dist/system-mounts/lists.mjs.map +1 -0
  494. package/dist/system-mounts/types.d.cts +124 -0
  495. package/dist/system-mounts/types.d.cts.map +1 -0
  496. package/dist/system-mounts/types.d.mts +125 -0
  497. package/dist/system-mounts/types.d.mts.map +1 -0
  498. package/dist/system-mounts/validate.cjs +56 -0
  499. package/dist/system-mounts/validate.d.cts +34 -0
  500. package/dist/system-mounts/validate.d.cts.map +1 -0
  501. package/dist/system-mounts/validate.d.mts +34 -0
  502. package/dist/system-mounts/validate.d.mts.map +1 -0
  503. package/dist/system-mounts/validate.mjs +56 -0
  504. package/dist/system-mounts/validate.mjs.map +1 -0
  505. package/dist/terminal-llm.cjs +90 -0
  506. package/dist/terminal-llm.d.cts +50 -0
  507. package/dist/terminal-llm.d.cts.map +1 -0
  508. package/dist/terminal-llm.d.mts +50 -0
  509. package/dist/terminal-llm.d.mts.map +1 -0
  510. package/dist/terminal-llm.mjs +90 -0
  511. package/dist/terminal-llm.mjs.map +1 -0
  512. package/dist/terminal-repl.cjs +371 -0
  513. package/dist/terminal-repl.d.cts +69 -0
  514. package/dist/terminal-repl.d.cts.map +1 -0
  515. package/dist/terminal-repl.d.mts +69 -0
  516. package/dist/terminal-repl.d.mts.map +1 -0
  517. package/dist/terminal-repl.mjs +370 -0
  518. package/dist/terminal-repl.mjs.map +1 -0
  519. package/dist/transport/idle-timer.cjs +136 -0
  520. package/dist/transport/idle-timer.d.cts +92 -0
  521. package/dist/transport/idle-timer.d.cts.map +1 -0
  522. package/dist/transport/idle-timer.d.mts +92 -0
  523. package/dist/transport/idle-timer.d.mts.map +1 -0
  524. package/dist/transport/idle-timer.mjs +132 -0
  525. package/dist/transport/idle-timer.mjs.map +1 -0
  526. package/dist/web-component-dsl.cjs +153 -0
  527. package/dist/web-component-dsl.d.cts +27 -0
  528. package/dist/web-component-dsl.d.cts.map +1 -0
  529. package/dist/web-component-dsl.d.mts +27 -0
  530. package/dist/web-component-dsl.d.mts.map +1 -0
  531. package/dist/web-component-dsl.mjs +152 -0
  532. package/dist/web-component-dsl.mjs.map +1 -0
  533. package/package.json +81 -0
@@ -0,0 +1,315 @@
1
+ let ufo = require("ufo");
2
+ let _aigne_afs = require("@aigne/afs");
3
+ let _aigne_afs_did_space = require("@aigne/afs-did-space");
4
+
5
+ //#region src/http/ingest-facade.ts
6
+ /**
7
+ * ingest-facade — the browser upload plane's server host (design §4.2, D1
8
+ * candidate-b). The afs-rpc handler intercepts the root-visible facade actions
9
+ *
10
+ * /.actions/ingest-prepare — plan + (grant) mint PUT grants + open a session
11
+ * /.actions/commit-upload — commit uploaded objects' metadata
12
+ * /.actions/abort-upload — abort a session (staged objects → GC)
13
+ *
14
+ * and injects them into `list('/.actions')`, so the browser only ever speaks in
15
+ * ROOT-VISIBLE paths (`/user/docs/a.pdf`) and never learns the mount boundary.
16
+ *
17
+ * Why a handler intercept (not a provider): the upload-plane actions
18
+ * (prepare/commit/abort-upload) take PROVIDER-RELATIVE paths (`/docs/a.pdf`) but
19
+ * the browser only knows root-visible paths. The intercept holds the composed
20
+ * per-request `SessionUserAFS` (writable `/user`) + verified caller, runs the
21
+ * shared `planIngest()` (one planning impl, core), then strips the mount prefix
22
+ * and delegates to the target mount's prepare/commit/abort-upload. The
23
+ * root-visible↔provider-relative translation lives only here — the browser never
24
+ * does mount math, and we never produce a `tree/user/...` double-prefix key.
25
+ *
26
+ * Transport split (design §4.4a): these are all `exec` (HTTP fast-path, CSRF +
27
+ * effect-gated). The legacy fallback's batchWrite is the browser's job (WS).
28
+ */
29
+ /** Capability-discovery version the browser checks before using this chain. */
30
+ const INGEST_PROTOCOL_VERSION = 1;
31
+ /** The three root-visible facade action names. */
32
+ const INGEST_FACADE_ACTIONS = [
33
+ "ingest-prepare",
34
+ "commit-upload",
35
+ "abort-upload"
36
+ ];
37
+ /**
38
+ * v1 grant mount used when there is no path to derive it from (abort-upload
39
+ * carries only a sessionId). v1 supports a single grant mount; prepare/commit
40
+ * derive the mount from their path args, abort falls back to this.
41
+ */
42
+ const V1_GRANT_MOUNT = "/user";
43
+ /** True for the three root-visible facade exec paths (exact match only). */
44
+ function isIngestFacadePath(path) {
45
+ return INGEST_FACADE_ACTIONS.some((a) => path === `/.actions/${a}`);
46
+ }
47
+ /**
48
+ * Append the three facade entries to a `list('/.actions')` result so the browser
49
+ * discovers the chain by listing the ROOT `/.actions` (design §4.5). Idempotent
50
+ * (won't duplicate an id already present) — applied identically in all scopes.
51
+ */
52
+ function injectIngestFacadeList(data) {
53
+ const arr = Array.isArray(data) ? [...data] : [];
54
+ const have = new Set(arr.map((e) => e?.id));
55
+ for (const name of INGEST_FACADE_ACTIONS) {
56
+ if (have.has(name)) continue;
57
+ arr.push({
58
+ id: name,
59
+ path: (0, ufo.joinURL)("/.actions", name),
60
+ meta: {
61
+ kind: "afs:executable",
62
+ protocolVersion: INGEST_PROTOCOL_VERSION
63
+ }
64
+ });
65
+ }
66
+ return arr;
67
+ }
68
+ /** v1: the mount prefix is the first path segment (`/user/docs` → `/user`). */
69
+ function mountPrefixOf(path) {
70
+ const seg = path.split("/").filter(Boolean)[0];
71
+ return seg ? `/${seg}` : null;
72
+ }
73
+ /** Strip the mount prefix → provider-relative path (`/user/docs/a.pdf` → `/docs/a.pdf`). */
74
+ function stripMount(path, mountPrefix) {
75
+ if (path === mountPrefix) return "/";
76
+ const rel = path.slice(mountPrefix.length);
77
+ return rel.startsWith("/") ? rel : `/${rel}`;
78
+ }
79
+ /** Re-add the mount prefix → root-visible path (`/docs/a.pdf` → `/user/docs/a.pdf`). */
80
+ function addMount(providerRel, mountPrefix) {
81
+ return (0, ufo.joinURL)(mountPrefix, providerRel);
82
+ }
83
+ /** Read the target mount's `prepare-upload.grantCapability` (design §4.5). */
84
+ async function isGrantCapable(afs, mountPrefix, context) {
85
+ try {
86
+ const r = await afs.list((0, ufo.joinURL)(mountPrefix, ".actions"), { context });
87
+ return (Array.isArray(r?.data) ? r.data : []).find((e) => e.id === "prepare-upload")?.meta?.grantCapability === true;
88
+ } catch {
89
+ return false;
90
+ }
91
+ }
92
+ function asStr(v) {
93
+ return typeof v === "string" && v ? v : void 0;
94
+ }
95
+ async function execIngestPrepare(afs, args, context, limits) {
96
+ const targetDir = asStr(args.targetDir);
97
+ if (!targetDir) return {
98
+ ok: false,
99
+ code: "AFS_VALIDATION_ERROR",
100
+ error: "targetDir must be a non-empty string"
101
+ };
102
+ const conflict = (0, _aigne_afs.normalizeConflict)(args.conflict) ?? "rename";
103
+ const rawEntries = Array.isArray(args.entries) ? args.entries : null;
104
+ if (!rawEntries || rawEntries.length === 0) return {
105
+ ok: false,
106
+ code: "AFS_VALIDATION_ERROR",
107
+ error: "entries must be a non-empty array"
108
+ };
109
+ const inputs = [];
110
+ for (const raw of rawEntries) {
111
+ const entry = raw;
112
+ const relPath = asStr(entry.relPath);
113
+ if (!relPath) return {
114
+ ok: false,
115
+ code: "AFS_VALIDATION_ERROR",
116
+ error: "every entry needs a non-empty relPath"
117
+ };
118
+ inputs.push({
119
+ relPath,
120
+ size: typeof entry.size === "number" && entry.size >= 0 ? entry.size : 0,
121
+ mimeType: asStr(entry.mimeType),
122
+ cid: asStr(entry.cid)
123
+ });
124
+ }
125
+ const plan = await (0, _aigne_afs.planIngest)(afs, targetDir, inputs.map((e) => ({
126
+ name: e.relPath,
127
+ relPath: e.relPath
128
+ })), conflict);
129
+ const mountPrefix = mountPrefixOf(targetDir);
130
+ const grantCapable = mountPrefix ? await isGrantCapable(afs, mountPrefix, context) : false;
131
+ const wantAbsent = conflict === "rename" || conflict === "error";
132
+ const responseEntries = [];
133
+ const grantInputs = [];
134
+ for (const pe of plan.entries) {
135
+ if (pe.status === "skipped") {
136
+ responseEntries.push({
137
+ relPath: pe.relPath,
138
+ finalPath: pe.finalPath,
139
+ status: "skipped"
140
+ });
141
+ continue;
142
+ }
143
+ if (pe.status === "failed") {
144
+ responseEntries.push({
145
+ relPath: pe.relPath,
146
+ finalPath: pe.finalPath,
147
+ status: "failed",
148
+ error: pe.error
149
+ });
150
+ continue;
151
+ }
152
+ const finalPath = pe.finalPath;
153
+ const ifMatch = wantAbsent ? _aigne_afs_did_space.AFS_IFMATCH_ABSENT : void 0;
154
+ const ref = {
155
+ relPath: pe.relPath,
156
+ finalPath,
157
+ status: "needs-upload",
158
+ ...ifMatch ? { ifMatch } : {}
159
+ };
160
+ responseEntries.push(ref);
161
+ const src = inputs[pe.index];
162
+ const size = src?.size ?? 0;
163
+ const failTooLarge = (capBytes, planeNote) => {
164
+ ref.status = "failed";
165
+ ref.error = {
166
+ code: "FILE_TOO_LARGE",
167
+ message: `File exceeds the ${capBytes}-byte ${planeNote} (declared ${size} bytes)`
168
+ };
169
+ delete ref.ifMatch;
170
+ };
171
+ if (size > limits.maxBytes) failTooLarge(limits.maxBytes, "upload limit");
172
+ else if (grantCapable && mountPrefix && src?.cid && size > 0) grantInputs.push({
173
+ ref,
174
+ providerRelPath: stripMount(finalPath, mountPrefix),
175
+ cid: src.cid,
176
+ size,
177
+ mimeType: src.mimeType,
178
+ ifMatch
179
+ });
180
+ else if (size > limits.legacyMaxBytes) failTooLarge(limits.legacyMaxBytes, "legacy upload limit (configure an R2 signer for larger files)");
181
+ }
182
+ let mode = "legacy";
183
+ let sessionId;
184
+ let expiresAt;
185
+ if (grantInputs.length > 0 && mountPrefix) {
186
+ const prepRes = await afs.exec((0, ufo.joinURL)(mountPrefix, ".actions/prepare-upload"), { entries: grantInputs.map((g) => ({
187
+ path: g.providerRelPath,
188
+ cid: g.cid,
189
+ size: g.size,
190
+ ...g.mimeType ? { mimeType: g.mimeType } : {},
191
+ ...g.ifMatch ? { ifMatch: g.ifMatch } : {}
192
+ })) }, { context });
193
+ if (!prepRes?.success) return {
194
+ ok: false,
195
+ code: prepRes?.error?.code ?? "AFS_ERROR",
196
+ error: prepRes?.error?.message ?? "prepare-upload failed"
197
+ };
198
+ const pdata = prepRes.data;
199
+ mode = "grant";
200
+ sessionId = pdata.sessionId;
201
+ expiresAt = pdata.expiresAt;
202
+ const byPath = new Map((pdata.entries ?? []).map((e) => [e.path, e]));
203
+ for (const g of grantInputs) {
204
+ const pe = byPath.get(g.providerRelPath);
205
+ if (!pe) continue;
206
+ g.ref.objectKey = pe.objectKey;
207
+ g.ref.checksumSha256 = pe.checksumSha256;
208
+ if (pe.grant) g.ref.grant = pe.grant;
209
+ }
210
+ }
211
+ return {
212
+ ok: true,
213
+ data: {
214
+ mode,
215
+ protocolVersion: INGEST_PROTOCOL_VERSION,
216
+ ...sessionId ? {
217
+ sessionId,
218
+ expiresAt
219
+ } : {},
220
+ entries: responseEntries
221
+ }
222
+ };
223
+ }
224
+ async function execCommitUpload(afs, args, context) {
225
+ const sessionId = asStr(args.sessionId);
226
+ if (!sessionId) return {
227
+ ok: false,
228
+ code: "AFS_VALIDATION_ERROR",
229
+ error: "sessionId required"
230
+ };
231
+ const rawEntries = Array.isArray(args.entries) ? args.entries : null;
232
+ if (!rawEntries || rawEntries.length === 0) return {
233
+ ok: false,
234
+ code: "AFS_VALIDATION_ERROR",
235
+ error: "entries must be a non-empty array"
236
+ };
237
+ const firstPath = asStr(rawEntries[0]?.path);
238
+ const mountPrefix = firstPath ? mountPrefixOf(firstPath) : null;
239
+ if (!mountPrefix) return {
240
+ ok: false,
241
+ code: "AFS_VALIDATION_ERROR",
242
+ error: "entry.path must be a root-visible path"
243
+ };
244
+ const providerEntries = rawEntries.map((raw) => {
245
+ const e = raw;
246
+ const p = asStr(e.path);
247
+ return {
248
+ ...e,
249
+ path: p ? stripMount(p, mountPrefix) : p
250
+ };
251
+ });
252
+ const res = await afs.exec((0, ufo.joinURL)(mountPrefix, ".actions/commit-upload"), {
253
+ sessionId,
254
+ entries: providerEntries
255
+ }, { context });
256
+ if (!res?.success) return {
257
+ ok: false,
258
+ code: res?.error?.code ?? "AFS_ERROR",
259
+ error: res?.error?.message ?? "commit-upload failed"
260
+ };
261
+ const data = res.data;
262
+ if (Array.isArray(data?.results)) data.results = data.results.map((r) => {
263
+ const out = { ...r };
264
+ const rp = asStr(r.path);
265
+ if (rp) out.path = addMount(rp, mountPrefix);
266
+ const inner = r.data;
267
+ if (inner && asStr(inner.path)) out.data = {
268
+ ...inner,
269
+ path: addMount(inner.path, mountPrefix)
270
+ };
271
+ return out;
272
+ });
273
+ return {
274
+ ok: true,
275
+ data
276
+ };
277
+ }
278
+ async function execAbortUpload(afs, args, context) {
279
+ const sessionId = asStr(args.sessionId);
280
+ if (!sessionId) return {
281
+ ok: false,
282
+ code: "AFS_VALIDATION_ERROR",
283
+ error: "sessionId required"
284
+ };
285
+ const res = await afs.exec((0, ufo.joinURL)(V1_GRANT_MOUNT, ".actions/abort-upload"), { sessionId }, { context });
286
+ if (!res?.success) return {
287
+ ok: false,
288
+ code: res?.error?.code ?? "AFS_ERROR",
289
+ error: res?.error?.message ?? "abort-upload failed"
290
+ };
291
+ return {
292
+ ok: true,
293
+ data: res.data
294
+ };
295
+ }
296
+ /**
297
+ * Run a root-visible facade exec. Caller MUST pre-check {@link isIngestFacadePath}.
298
+ * The authed-caller floor (design §4.7: all three are write-effect) is enforced
299
+ * here — the CSRF/Origin guard is the afs-rpc handler's job upstream.
300
+ */
301
+ async function execIngestFacade(input) {
302
+ const { afs, path, args, context, caller } = input;
303
+ if (!caller?.did) return {
304
+ status: 401,
305
+ error: "Authentication required for upload"
306
+ };
307
+ if (path === "/.actions/ingest-prepare") return execIngestPrepare(afs, args, context, input.limits ?? _aigne_afs.UPLOAD_LIMIT_DEFAULTS);
308
+ if (path === "/.actions/commit-upload") return execCommitUpload(afs, args, context);
309
+ return execAbortUpload(afs, args, context);
310
+ }
311
+
312
+ //#endregion
313
+ exports.execIngestFacade = execIngestFacade;
314
+ exports.injectIngestFacadeList = injectIngestFacadeList;
315
+ exports.isIngestFacadePath = isIngestFacadePath;
@@ -0,0 +1,314 @@
1
+ import { joinURL } from "ufo";
2
+ import { UPLOAD_LIMIT_DEFAULTS, normalizeConflict, planIngest } from "@aigne/afs";
3
+ import { AFS_IFMATCH_ABSENT } from "@aigne/afs-did-space";
4
+
5
+ //#region src/http/ingest-facade.ts
6
+ /**
7
+ * ingest-facade — the browser upload plane's server host (design §4.2, D1
8
+ * candidate-b). The afs-rpc handler intercepts the root-visible facade actions
9
+ *
10
+ * /.actions/ingest-prepare — plan + (grant) mint PUT grants + open a session
11
+ * /.actions/commit-upload — commit uploaded objects' metadata
12
+ * /.actions/abort-upload — abort a session (staged objects → GC)
13
+ *
14
+ * and injects them into `list('/.actions')`, so the browser only ever speaks in
15
+ * ROOT-VISIBLE paths (`/user/docs/a.pdf`) and never learns the mount boundary.
16
+ *
17
+ * Why a handler intercept (not a provider): the upload-plane actions
18
+ * (prepare/commit/abort-upload) take PROVIDER-RELATIVE paths (`/docs/a.pdf`) but
19
+ * the browser only knows root-visible paths. The intercept holds the composed
20
+ * per-request `SessionUserAFS` (writable `/user`) + verified caller, runs the
21
+ * shared `planIngest()` (one planning impl, core), then strips the mount prefix
22
+ * and delegates to the target mount's prepare/commit/abort-upload. The
23
+ * root-visible↔provider-relative translation lives only here — the browser never
24
+ * does mount math, and we never produce a `tree/user/...` double-prefix key.
25
+ *
26
+ * Transport split (design §4.4a): these are all `exec` (HTTP fast-path, CSRF +
27
+ * effect-gated). The legacy fallback's batchWrite is the browser's job (WS).
28
+ */
29
+ /** Capability-discovery version the browser checks before using this chain. */
30
+ const INGEST_PROTOCOL_VERSION = 1;
31
+ /** The three root-visible facade action names. */
32
+ const INGEST_FACADE_ACTIONS = [
33
+ "ingest-prepare",
34
+ "commit-upload",
35
+ "abort-upload"
36
+ ];
37
+ /**
38
+ * v1 grant mount used when there is no path to derive it from (abort-upload
39
+ * carries only a sessionId). v1 supports a single grant mount; prepare/commit
40
+ * derive the mount from their path args, abort falls back to this.
41
+ */
42
+ const V1_GRANT_MOUNT = "/user";
43
+ /** True for the three root-visible facade exec paths (exact match only). */
44
+ function isIngestFacadePath(path) {
45
+ return INGEST_FACADE_ACTIONS.some((a) => path === `/.actions/${a}`);
46
+ }
47
+ /**
48
+ * Append the three facade entries to a `list('/.actions')` result so the browser
49
+ * discovers the chain by listing the ROOT `/.actions` (design §4.5). Idempotent
50
+ * (won't duplicate an id already present) — applied identically in all scopes.
51
+ */
52
+ function injectIngestFacadeList(data) {
53
+ const arr = Array.isArray(data) ? [...data] : [];
54
+ const have = new Set(arr.map((e) => e?.id));
55
+ for (const name of INGEST_FACADE_ACTIONS) {
56
+ if (have.has(name)) continue;
57
+ arr.push({
58
+ id: name,
59
+ path: joinURL("/.actions", name),
60
+ meta: {
61
+ kind: "afs:executable",
62
+ protocolVersion: INGEST_PROTOCOL_VERSION
63
+ }
64
+ });
65
+ }
66
+ return arr;
67
+ }
68
+ /** v1: the mount prefix is the first path segment (`/user/docs` → `/user`). */
69
+ function mountPrefixOf(path) {
70
+ const seg = path.split("/").filter(Boolean)[0];
71
+ return seg ? `/${seg}` : null;
72
+ }
73
+ /** Strip the mount prefix → provider-relative path (`/user/docs/a.pdf` → `/docs/a.pdf`). */
74
+ function stripMount(path, mountPrefix) {
75
+ if (path === mountPrefix) return "/";
76
+ const rel = path.slice(mountPrefix.length);
77
+ return rel.startsWith("/") ? rel : `/${rel}`;
78
+ }
79
+ /** Re-add the mount prefix → root-visible path (`/docs/a.pdf` → `/user/docs/a.pdf`). */
80
+ function addMount(providerRel, mountPrefix) {
81
+ return joinURL(mountPrefix, providerRel);
82
+ }
83
+ /** Read the target mount's `prepare-upload.grantCapability` (design §4.5). */
84
+ async function isGrantCapable(afs, mountPrefix, context) {
85
+ try {
86
+ const r = await afs.list(joinURL(mountPrefix, ".actions"), { context });
87
+ return (Array.isArray(r?.data) ? r.data : []).find((e) => e.id === "prepare-upload")?.meta?.grantCapability === true;
88
+ } catch {
89
+ return false;
90
+ }
91
+ }
92
+ function asStr(v) {
93
+ return typeof v === "string" && v ? v : void 0;
94
+ }
95
+ async function execIngestPrepare(afs, args, context, limits) {
96
+ const targetDir = asStr(args.targetDir);
97
+ if (!targetDir) return {
98
+ ok: false,
99
+ code: "AFS_VALIDATION_ERROR",
100
+ error: "targetDir must be a non-empty string"
101
+ };
102
+ const conflict = normalizeConflict(args.conflict) ?? "rename";
103
+ const rawEntries = Array.isArray(args.entries) ? args.entries : null;
104
+ if (!rawEntries || rawEntries.length === 0) return {
105
+ ok: false,
106
+ code: "AFS_VALIDATION_ERROR",
107
+ error: "entries must be a non-empty array"
108
+ };
109
+ const inputs = [];
110
+ for (const raw of rawEntries) {
111
+ const entry = raw;
112
+ const relPath = asStr(entry.relPath);
113
+ if (!relPath) return {
114
+ ok: false,
115
+ code: "AFS_VALIDATION_ERROR",
116
+ error: "every entry needs a non-empty relPath"
117
+ };
118
+ inputs.push({
119
+ relPath,
120
+ size: typeof entry.size === "number" && entry.size >= 0 ? entry.size : 0,
121
+ mimeType: asStr(entry.mimeType),
122
+ cid: asStr(entry.cid)
123
+ });
124
+ }
125
+ const plan = await planIngest(afs, targetDir, inputs.map((e) => ({
126
+ name: e.relPath,
127
+ relPath: e.relPath
128
+ })), conflict);
129
+ const mountPrefix = mountPrefixOf(targetDir);
130
+ const grantCapable = mountPrefix ? await isGrantCapable(afs, mountPrefix, context) : false;
131
+ const wantAbsent = conflict === "rename" || conflict === "error";
132
+ const responseEntries = [];
133
+ const grantInputs = [];
134
+ for (const pe of plan.entries) {
135
+ if (pe.status === "skipped") {
136
+ responseEntries.push({
137
+ relPath: pe.relPath,
138
+ finalPath: pe.finalPath,
139
+ status: "skipped"
140
+ });
141
+ continue;
142
+ }
143
+ if (pe.status === "failed") {
144
+ responseEntries.push({
145
+ relPath: pe.relPath,
146
+ finalPath: pe.finalPath,
147
+ status: "failed",
148
+ error: pe.error
149
+ });
150
+ continue;
151
+ }
152
+ const finalPath = pe.finalPath;
153
+ const ifMatch = wantAbsent ? AFS_IFMATCH_ABSENT : void 0;
154
+ const ref = {
155
+ relPath: pe.relPath,
156
+ finalPath,
157
+ status: "needs-upload",
158
+ ...ifMatch ? { ifMatch } : {}
159
+ };
160
+ responseEntries.push(ref);
161
+ const src = inputs[pe.index];
162
+ const size = src?.size ?? 0;
163
+ const failTooLarge = (capBytes, planeNote) => {
164
+ ref.status = "failed";
165
+ ref.error = {
166
+ code: "FILE_TOO_LARGE",
167
+ message: `File exceeds the ${capBytes}-byte ${planeNote} (declared ${size} bytes)`
168
+ };
169
+ delete ref.ifMatch;
170
+ };
171
+ if (size > limits.maxBytes) failTooLarge(limits.maxBytes, "upload limit");
172
+ else if (grantCapable && mountPrefix && src?.cid && size > 0) grantInputs.push({
173
+ ref,
174
+ providerRelPath: stripMount(finalPath, mountPrefix),
175
+ cid: src.cid,
176
+ size,
177
+ mimeType: src.mimeType,
178
+ ifMatch
179
+ });
180
+ else if (size > limits.legacyMaxBytes) failTooLarge(limits.legacyMaxBytes, "legacy upload limit (configure an R2 signer for larger files)");
181
+ }
182
+ let mode = "legacy";
183
+ let sessionId;
184
+ let expiresAt;
185
+ if (grantInputs.length > 0 && mountPrefix) {
186
+ const prepRes = await afs.exec(joinURL(mountPrefix, ".actions/prepare-upload"), { entries: grantInputs.map((g) => ({
187
+ path: g.providerRelPath,
188
+ cid: g.cid,
189
+ size: g.size,
190
+ ...g.mimeType ? { mimeType: g.mimeType } : {},
191
+ ...g.ifMatch ? { ifMatch: g.ifMatch } : {}
192
+ })) }, { context });
193
+ if (!prepRes?.success) return {
194
+ ok: false,
195
+ code: prepRes?.error?.code ?? "AFS_ERROR",
196
+ error: prepRes?.error?.message ?? "prepare-upload failed"
197
+ };
198
+ const pdata = prepRes.data;
199
+ mode = "grant";
200
+ sessionId = pdata.sessionId;
201
+ expiresAt = pdata.expiresAt;
202
+ const byPath = new Map((pdata.entries ?? []).map((e) => [e.path, e]));
203
+ for (const g of grantInputs) {
204
+ const pe = byPath.get(g.providerRelPath);
205
+ if (!pe) continue;
206
+ g.ref.objectKey = pe.objectKey;
207
+ g.ref.checksumSha256 = pe.checksumSha256;
208
+ if (pe.grant) g.ref.grant = pe.grant;
209
+ }
210
+ }
211
+ return {
212
+ ok: true,
213
+ data: {
214
+ mode,
215
+ protocolVersion: INGEST_PROTOCOL_VERSION,
216
+ ...sessionId ? {
217
+ sessionId,
218
+ expiresAt
219
+ } : {},
220
+ entries: responseEntries
221
+ }
222
+ };
223
+ }
224
+ async function execCommitUpload(afs, args, context) {
225
+ const sessionId = asStr(args.sessionId);
226
+ if (!sessionId) return {
227
+ ok: false,
228
+ code: "AFS_VALIDATION_ERROR",
229
+ error: "sessionId required"
230
+ };
231
+ const rawEntries = Array.isArray(args.entries) ? args.entries : null;
232
+ if (!rawEntries || rawEntries.length === 0) return {
233
+ ok: false,
234
+ code: "AFS_VALIDATION_ERROR",
235
+ error: "entries must be a non-empty array"
236
+ };
237
+ const firstPath = asStr(rawEntries[0]?.path);
238
+ const mountPrefix = firstPath ? mountPrefixOf(firstPath) : null;
239
+ if (!mountPrefix) return {
240
+ ok: false,
241
+ code: "AFS_VALIDATION_ERROR",
242
+ error: "entry.path must be a root-visible path"
243
+ };
244
+ const providerEntries = rawEntries.map((raw) => {
245
+ const e = raw;
246
+ const p = asStr(e.path);
247
+ return {
248
+ ...e,
249
+ path: p ? stripMount(p, mountPrefix) : p
250
+ };
251
+ });
252
+ const res = await afs.exec(joinURL(mountPrefix, ".actions/commit-upload"), {
253
+ sessionId,
254
+ entries: providerEntries
255
+ }, { context });
256
+ if (!res?.success) return {
257
+ ok: false,
258
+ code: res?.error?.code ?? "AFS_ERROR",
259
+ error: res?.error?.message ?? "commit-upload failed"
260
+ };
261
+ const data = res.data;
262
+ if (Array.isArray(data?.results)) data.results = data.results.map((r) => {
263
+ const out = { ...r };
264
+ const rp = asStr(r.path);
265
+ if (rp) out.path = addMount(rp, mountPrefix);
266
+ const inner = r.data;
267
+ if (inner && asStr(inner.path)) out.data = {
268
+ ...inner,
269
+ path: addMount(inner.path, mountPrefix)
270
+ };
271
+ return out;
272
+ });
273
+ return {
274
+ ok: true,
275
+ data
276
+ };
277
+ }
278
+ async function execAbortUpload(afs, args, context) {
279
+ const sessionId = asStr(args.sessionId);
280
+ if (!sessionId) return {
281
+ ok: false,
282
+ code: "AFS_VALIDATION_ERROR",
283
+ error: "sessionId required"
284
+ };
285
+ const res = await afs.exec(joinURL(V1_GRANT_MOUNT, ".actions/abort-upload"), { sessionId }, { context });
286
+ if (!res?.success) return {
287
+ ok: false,
288
+ code: res?.error?.code ?? "AFS_ERROR",
289
+ error: res?.error?.message ?? "abort-upload failed"
290
+ };
291
+ return {
292
+ ok: true,
293
+ data: res.data
294
+ };
295
+ }
296
+ /**
297
+ * Run a root-visible facade exec. Caller MUST pre-check {@link isIngestFacadePath}.
298
+ * The authed-caller floor (design §4.7: all three are write-effect) is enforced
299
+ * here — the CSRF/Origin guard is the afs-rpc handler's job upstream.
300
+ */
301
+ async function execIngestFacade(input) {
302
+ const { afs, path, args, context, caller } = input;
303
+ if (!caller?.did) return {
304
+ status: 401,
305
+ error: "Authentication required for upload"
306
+ };
307
+ if (path === "/.actions/ingest-prepare") return execIngestPrepare(afs, args, context, input.limits ?? UPLOAD_LIMIT_DEFAULTS);
308
+ if (path === "/.actions/commit-upload") return execCommitUpload(afs, args, context);
309
+ return execAbortUpload(afs, args, context);
310
+ }
311
+
312
+ //#endregion
313
+ export { execIngestFacade, injectIngestFacadeList, isIngestFacadePath };
314
+ //# sourceMappingURL=ingest-facade.mjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"ingest-facade.mjs","names":[],"sources":["../../src/http/ingest-facade.ts"],"sourcesContent":["/**\n * ingest-facade — the browser upload plane's server host (design §4.2, D1\n * candidate-b). The afs-rpc handler intercepts the root-visible facade actions\n *\n * /.actions/ingest-prepare — plan + (grant) mint PUT grants + open a session\n * /.actions/commit-upload — commit uploaded objects' metadata\n * /.actions/abort-upload — abort a session (staged objects → GC)\n *\n * and injects them into `list('/.actions')`, so the browser only ever speaks in\n * ROOT-VISIBLE paths (`/user/docs/a.pdf`) and never learns the mount boundary.\n *\n * Why a handler intercept (not a provider): the upload-plane actions\n * (prepare/commit/abort-upload) take PROVIDER-RELATIVE paths (`/docs/a.pdf`) but\n * the browser only knows root-visible paths. The intercept holds the composed\n * per-request `SessionUserAFS` (writable `/user`) + verified caller, runs the\n * shared `planIngest()` (one planning impl, core), then strips the mount prefix\n * and delegates to the target mount's prepare/commit/abort-upload. The\n * root-visible↔provider-relative translation lives only here — the browser never\n * does mount math, and we never produce a `tree/user/...` double-prefix key.\n *\n * Transport split (design §4.4a): these are all `exec` (HTTP fast-path, CSRF +\n * effect-gated). The legacy fallback's batchWrite is the browser's job (WS).\n */\n\nimport {\n type IngestAFS,\n normalizeConflict,\n planIngest,\n UPLOAD_LIMIT_DEFAULTS,\n type UploadLimits,\n} from \"@aigne/afs\";\nimport { AFS_IFMATCH_ABSENT } from \"@aigne/afs-did-space\";\nimport { joinURL } from \"ufo\";\n\n/** Capability-discovery version the browser checks before using this chain. */\nexport const INGEST_PROTOCOL_VERSION = 1;\n\n/** The three root-visible facade action names. */\nexport const INGEST_FACADE_ACTIONS = [\"ingest-prepare\", \"commit-upload\", \"abort-upload\"] as const;\n\n/**\n * v1 grant mount used when there is no path to derive it from (abort-upload\n * carries only a sessionId). v1 supports a single grant mount; prepare/commit\n * derive the mount from their path args, abort falls back to this.\n */\nconst V1_GRANT_MOUNT = \"/user\";\n\n/** A minimal AFS surface the facade needs: plan via stat, delegate via exec/list. */\nexport interface FacadeAFS extends IngestAFS {\n exec(\n path: string,\n args: Record<string, unknown>,\n options?: unknown,\n ): Promise<{\n success?: boolean;\n data?: unknown;\n error?: { code?: string; message?: string };\n }>;\n list(path: string, options?: unknown): Promise<{ data?: unknown }>;\n}\n\n/** Caller shape the facade needs (authed-caller gate). */\ninterface FacadeCaller {\n did?: string | null;\n}\n\n/**\n * Discriminated facade outcome. The afs-rpc handler maps it to a Response:\n * - `{ status }` → `fail(status, error)` (401 authed-caller floor)\n * - `{ ok: true }` → 200 `{ ok: true, data }`\n * - `{ ok: false }` → 200 `{ ok: false, error, code? }` (semantic failure)\n */\nexport type FacadeResult =\n | { status: 401 | 403; error: string }\n | { ok: true; data: unknown }\n | { ok: false; error: string; code?: string };\n\n/** True for the three root-visible facade exec paths (exact match only). */\nexport function isIngestFacadePath(path: string): boolean {\n return INGEST_FACADE_ACTIONS.some((a) => path === `/.actions/${a}`);\n}\n\n/**\n * Append the three facade entries to a `list('/.actions')` result so the browser\n * discovers the chain by listing the ROOT `/.actions` (design §4.5). Idempotent\n * (won't duplicate an id already present) — applied identically in all scopes.\n */\nexport function injectIngestFacadeList(data: unknown): unknown[] {\n const arr = Array.isArray(data) ? [...data] : [];\n const have = new Set(arr.map((e) => (e as { id?: string } | null)?.id));\n for (const name of INGEST_FACADE_ACTIONS) {\n if (have.has(name)) continue;\n arr.push({\n id: name,\n path: joinURL(\"/.actions\", name),\n meta: { kind: \"afs:executable\", protocolVersion: INGEST_PROTOCOL_VERSION },\n });\n }\n return arr;\n}\n\n// ── helpers ──────────────────────────────────────────────────────────────────\n\n/** v1: the mount prefix is the first path segment (`/user/docs` → `/user`). */\nfunction mountPrefixOf(path: string): string | null {\n const seg = path.split(\"/\").filter(Boolean)[0];\n return seg ? `/${seg}` : null;\n}\n\n/** Strip the mount prefix → provider-relative path (`/user/docs/a.pdf` → `/docs/a.pdf`). */\nfunction stripMount(path: string, mountPrefix: string): string {\n if (path === mountPrefix) return \"/\";\n const rel = path.slice(mountPrefix.length);\n return rel.startsWith(\"/\") ? rel : `/${rel}`;\n}\n\n/** Re-add the mount prefix → root-visible path (`/docs/a.pdf` → `/user/docs/a.pdf`). */\nfunction addMount(providerRel: string, mountPrefix: string): string {\n return joinURL(mountPrefix, providerRel);\n}\n\n/** Read the target mount's `prepare-upload.grantCapability` (design §4.5). */\nasync function isGrantCapable(\n afs: FacadeAFS,\n mountPrefix: string,\n context: Record<string, unknown>,\n): Promise<boolean> {\n try {\n const r = await afs.list(joinURL(mountPrefix, \".actions\"), { context });\n const entries = (Array.isArray(r?.data) ? r.data : []) as Array<{\n id?: string;\n meta?: { grantCapability?: unknown };\n }>;\n return entries.find((e) => e.id === \"prepare-upload\")?.meta?.grantCapability === true;\n } catch {\n return false;\n }\n}\n\nfunction asStr(v: unknown): string | undefined {\n return typeof v === \"string\" && v ? v : undefined;\n}\n\n// ── ingest-prepare ───────────────────────────────────────────────────────────\n\ninterface PrepareEntryInput {\n relPath: string;\n size: number;\n mimeType?: string;\n cid?: string;\n}\n\nasync function execIngestPrepare(\n afs: FacadeAFS,\n args: Record<string, unknown>,\n context: Record<string, unknown>,\n limits: UploadLimits,\n): Promise<FacadeResult> {\n const targetDir = asStr(args.targetDir);\n if (!targetDir) {\n return {\n ok: false,\n code: \"AFS_VALIDATION_ERROR\",\n error: \"targetDir must be a non-empty string\",\n };\n }\n const conflict = normalizeConflict(args.conflict) ?? \"rename\";\n const rawEntries = Array.isArray(args.entries) ? args.entries : null;\n if (!rawEntries || rawEntries.length === 0) {\n return { ok: false, code: \"AFS_VALIDATION_ERROR\", error: \"entries must be a non-empty array\" };\n }\n const inputs: PrepareEntryInput[] = [];\n for (const raw of rawEntries) {\n const entry = raw as { relPath?: unknown; size?: unknown; mimeType?: unknown; cid?: unknown };\n const relPath = asStr(entry.relPath);\n if (!relPath) {\n return {\n ok: false,\n code: \"AFS_VALIDATION_ERROR\",\n error: \"every entry needs a non-empty relPath\",\n };\n }\n inputs.push({\n relPath,\n size: typeof entry.size === \"number\" && entry.size >= 0 ? entry.size : 0,\n mimeType: asStr(entry.mimeType),\n cid: asStr(entry.cid),\n });\n }\n\n // Plan (the single shared planning impl, core). finalPath is root-visible.\n const plan = await planIngest(\n afs,\n targetDir,\n inputs.map((e) => ({ name: e.relPath, relPath: e.relPath })),\n conflict,\n );\n\n const mountPrefix = mountPrefixOf(targetDir);\n const grantCapable = mountPrefix ? await isGrantCapable(afs, mountPrefix, context) : false;\n\n // The conflict intent that must survive the prepare→write window (D3 §4.2a):\n // rename/error mean \"do not clobber\" → expected-absent precondition.\n const wantAbsent = conflict === \"rename\" || conflict === \"error\";\n\n interface ResponseEntry {\n relPath: string;\n finalPath: string | null;\n status: string;\n error?: { code: string; message: string };\n ifMatch?: string;\n objectKey?: string;\n checksumSha256?: string;\n grant?: unknown;\n }\n interface GrantInput {\n ref: ResponseEntry;\n providerRelPath: string;\n cid: string;\n size: number;\n mimeType?: string;\n ifMatch?: string;\n }\n\n const responseEntries: ResponseEntry[] = [];\n const grantInputs: GrantInput[] = [];\n\n for (const pe of plan.entries) {\n if (pe.status === \"skipped\") {\n responseEntries.push({ relPath: pe.relPath, finalPath: pe.finalPath, status: \"skipped\" });\n continue;\n }\n if (pe.status === \"failed\") {\n responseEntries.push({\n relPath: pe.relPath,\n finalPath: pe.finalPath,\n status: \"failed\",\n error: pe.error,\n });\n continue;\n }\n // pending ⇒ finalPath non-null (planIngest invariant).\n const finalPath = pe.finalPath!;\n const ifMatch = wantAbsent ? AFS_IFMATCH_ABSENT : undefined;\n const ref: ResponseEntry = {\n relPath: pe.relPath,\n finalPath,\n status: \"needs-upload\",\n ...(ifMatch ? { ifMatch } : {}),\n };\n responseEntries.push(ref);\n\n const src = inputs[pe.index];\n const size = src?.size ?? 0;\n // upload-limits Phase 2 — declared-size routing + early reject (design §5).\n // Best-effort BANDWIDTH optimization (the real boundary is Phase 1's\n // decoded-byte WS cap). FILE_TOO_LARGE is PER-ENTRY (status:\"failed\" +\n // error.code, like NO_PLAN_ENTRY/REL_TRAVERSAL) — NOT a throw — so the rest\n // of the batch still plans + grants. The server decides routing here; it\n // never trusts the client to self-limit.\n const failTooLarge = (capBytes: number, planeNote: string) => {\n ref.status = \"failed\";\n ref.error = {\n code: \"FILE_TOO_LARGE\",\n message: `File exceeds the ${capBytes}-byte ${planeNote} (declared ${size} bytes)`,\n };\n delete ref.ifMatch; // a rejected entry is never uploaded\n };\n if (size > limits.maxBytes) {\n // Over the grant-plane (R2-direct) product cap — reject on either plane.\n failTooLarge(limits.maxBytes, \"upload limit\");\n } else if (grantCapable && mountPrefix && src?.cid && size > 0) {\n // grant-capable(signer) AND cid present AND 0 < size ≤ maxBytes → grant.\n grantInputs.push({\n ref,\n providerRelPath: stripMount(finalPath, mountPrefix),\n cid: src.cid,\n size,\n mimeType: src.mimeType,\n ifMatch,\n });\n } else if (size > limits.legacyMaxBytes) {\n // No grant capability (no signer / no cid / unknown size) AND too big for\n // the legacy through-memory plane → reject. CRITICAL: never silently fall\n // through to an UNCAPPED legacy write (design §5 / review R2).\n failTooLarge(\n limits.legacyMaxBytes,\n \"legacy upload limit (configure an R2 signer for larger files)\",\n );\n }\n // else → legacy: ref stays \"needs-upload\" (Phase 1 decoded-byte cap backstops);\n // unknown/0 declared size also lands here (never granted on a 0 size).\n }\n\n let mode: \"grant\" | \"legacy\" = \"legacy\";\n let sessionId: string | undefined;\n let expiresAt: string | undefined;\n\n if (grantInputs.length > 0 && mountPrefix) {\n const prepRes = await afs.exec(\n joinURL(mountPrefix, \".actions/prepare-upload\"),\n {\n entries: grantInputs.map((g) => ({\n path: g.providerRelPath,\n cid: g.cid,\n size: g.size,\n ...(g.mimeType ? { mimeType: g.mimeType } : {}),\n ...(g.ifMatch ? { ifMatch: g.ifMatch } : {}),\n })),\n },\n { context },\n );\n if (!prepRes?.success) {\n return {\n ok: false,\n code: prepRes?.error?.code ?? \"AFS_ERROR\",\n error: prepRes?.error?.message ?? \"prepare-upload failed\",\n };\n }\n const pdata = prepRes.data as {\n sessionId?: string;\n expiresAt?: string;\n entries?: Array<{\n path?: string;\n objectKey?: string;\n checksumSha256?: string;\n grant?: unknown;\n }>;\n };\n mode = \"grant\";\n sessionId = pdata.sessionId;\n expiresAt = pdata.expiresAt;\n const byPath = new Map((pdata.entries ?? []).map((e) => [e.path, e]));\n for (const g of grantInputs) {\n const pe = byPath.get(g.providerRelPath);\n if (!pe) continue;\n g.ref.objectKey = pe.objectKey;\n g.ref.checksumSha256 = pe.checksumSha256;\n if (pe.grant) g.ref.grant = pe.grant;\n }\n }\n\n return {\n ok: true,\n data: {\n mode,\n protocolVersion: INGEST_PROTOCOL_VERSION,\n ...(sessionId ? { sessionId, expiresAt } : {}),\n entries: responseEntries,\n },\n };\n}\n\n// ── commit-upload ────────────────────────────────────────────────────────────\n\nasync function execCommitUpload(\n afs: FacadeAFS,\n args: Record<string, unknown>,\n context: Record<string, unknown>,\n): Promise<FacadeResult> {\n const sessionId = asStr(args.sessionId);\n if (!sessionId) {\n return { ok: false, code: \"AFS_VALIDATION_ERROR\", error: \"sessionId required\" };\n }\n const rawEntries = Array.isArray(args.entries) ? args.entries : null;\n if (!rawEntries || rawEntries.length === 0) {\n return { ok: false, code: \"AFS_VALIDATION_ERROR\", error: \"entries must be a non-empty array\" };\n }\n const firstPath = asStr((rawEntries[0] as { path?: unknown })?.path);\n const mountPrefix = firstPath ? mountPrefixOf(firstPath) : null;\n if (!mountPrefix) {\n return {\n ok: false,\n code: \"AFS_VALIDATION_ERROR\",\n error: \"entry.path must be a root-visible path\",\n };\n }\n\n // Translate every entry's root-visible path → provider-relative for the mount.\n const providerEntries = rawEntries.map((raw) => {\n const e = raw as Record<string, unknown>;\n const p = asStr(e.path);\n return { ...e, path: p ? stripMount(p, mountPrefix) : p };\n });\n\n const res = await afs.exec(\n joinURL(mountPrefix, \".actions/commit-upload\"),\n { sessionId, entries: providerEntries },\n { context },\n );\n if (!res?.success) {\n return {\n ok: false,\n code: res?.error?.code ?? \"AFS_ERROR\",\n error: res?.error?.message ?? \"commit-upload failed\",\n };\n }\n // Re-add the mount prefix on every result path → root-visible for the browser.\n const data = res.data as { results?: Array<Record<string, unknown>> } & Record<string, unknown>;\n if (Array.isArray(data?.results)) {\n data.results = data.results.map((r) => {\n const out = { ...r };\n const rp = asStr(r.path);\n if (rp) out.path = addMount(rp, mountPrefix);\n const inner = r.data as { path?: unknown } | undefined;\n if (inner && asStr(inner.path)) {\n out.data = { ...inner, path: addMount(inner.path as string, mountPrefix) };\n }\n return out;\n });\n }\n return { ok: true, data };\n}\n\n// ── abort-upload ─────────────────────────────────────────────────────────────\n\nasync function execAbortUpload(\n afs: FacadeAFS,\n args: Record<string, unknown>,\n context: Record<string, unknown>,\n): Promise<FacadeResult> {\n const sessionId = asStr(args.sessionId);\n if (!sessionId) {\n return { ok: false, code: \"AFS_VALIDATION_ERROR\", error: \"sessionId required\" };\n }\n // abort carries no path; v1 routes to the single grant mount.\n const res = await afs.exec(\n joinURL(V1_GRANT_MOUNT, \".actions/abort-upload\"),\n { sessionId },\n { context },\n );\n if (!res?.success) {\n return {\n ok: false,\n code: res?.error?.code ?? \"AFS_ERROR\",\n error: res?.error?.message ?? \"abort-upload failed\",\n };\n }\n return { ok: true, data: res.data };\n}\n\n// ── dispatch ─────────────────────────────────────────────────────────────────\n\n/**\n * Run a root-visible facade exec. Caller MUST pre-check {@link isIngestFacadePath}.\n * The authed-caller floor (design §4.7: all three are write-effect) is enforced\n * here — the CSRF/Origin guard is the afs-rpc handler's job upstream.\n */\nexport async function execIngestFacade(input: {\n afs: FacadeAFS;\n path: string;\n args: Record<string, unknown>;\n context: Record<string, unknown>;\n caller: FacadeCaller | null;\n /**\n * Server-enforced upload caps (upload-limits Phase 2). The handler resolves\n * them at the runtime single env-read point; only ingest-prepare consumes them\n * (declared-size routing). Optional → safe defaults (never unlimited).\n */\n limits?: UploadLimits;\n}): Promise<FacadeResult> {\n const { afs, path, args, context, caller } = input;\n if (!caller?.did) {\n return { status: 401, error: \"Authentication required for upload\" };\n }\n if (path === \"/.actions/ingest-prepare\") {\n return execIngestPrepare(afs, args, context, input.limits ?? UPLOAD_LIMIT_DEFAULTS);\n }\n if (path === \"/.actions/commit-upload\") return execCommitUpload(afs, args, context);\n return execAbortUpload(afs, args, context);\n}\n"],"mappings":"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"}