@animalabs/agent-framework 0.23.2 → 0.24.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 (338) hide show
  1. package/README.md +212 -42
  2. package/dist/src/agent.d.ts +60 -9
  3. package/dist/src/agent.d.ts.map +1 -1
  4. package/dist/src/agent.js +92 -12
  5. package/dist/src/agent.js.map +1 -1
  6. package/dist/src/api/server.d.ts.map +1 -1
  7. package/dist/src/api/server.js +14 -12
  8. package/dist/src/api/server.js.map +1 -1
  9. package/dist/src/code-execution/engine.d.ts +177 -0
  10. package/dist/src/code-execution/engine.d.ts.map +1 -0
  11. package/dist/src/code-execution/engine.js +494 -0
  12. package/dist/src/code-execution/engine.js.map +1 -0
  13. package/dist/src/code-execution/index.d.ts +5 -10
  14. package/dist/src/code-execution/index.d.ts.map +1 -1
  15. package/dist/src/code-execution/index.js +5 -9
  16. package/dist/src/code-execution/index.js.map +1 -1
  17. package/dist/src/code-execution/isolate/calls.d.ts +114 -0
  18. package/dist/src/code-execution/isolate/calls.d.ts.map +1 -0
  19. package/dist/src/code-execution/isolate/calls.js +145 -0
  20. package/dist/src/code-execution/isolate/calls.js.map +1 -0
  21. package/dist/src/code-execution/isolate/child-entry.d.ts +2 -0
  22. package/dist/src/code-execution/isolate/child-entry.d.ts.map +1 -0
  23. package/dist/src/code-execution/isolate/child-entry.js +5 -0
  24. package/dist/src/code-execution/isolate/child-entry.js.map +1 -0
  25. package/dist/src/code-execution/isolate/child-main.d.ts +26 -0
  26. package/dist/src/code-execution/isolate/child-main.d.ts.map +1 -0
  27. package/dist/src/code-execution/isolate/child-main.js +132 -0
  28. package/dist/src/code-execution/isolate/child-main.js.map +1 -0
  29. package/dist/src/code-execution/isolate/child.d.ts +44 -0
  30. package/dist/src/code-execution/isolate/child.d.ts.map +1 -0
  31. package/dist/src/code-execution/isolate/child.js +315 -0
  32. package/dist/src/code-execution/isolate/child.js.map +1 -0
  33. package/dist/src/code-execution/isolate/frames.d.ts +80 -0
  34. package/dist/src/code-execution/isolate/frames.d.ts.map +1 -0
  35. package/dist/src/code-execution/isolate/frames.js +210 -0
  36. package/dist/src/code-execution/isolate/frames.js.map +1 -0
  37. package/dist/src/code-execution/isolate/output.d.ts +68 -0
  38. package/dist/src/code-execution/isolate/output.d.ts.map +1 -0
  39. package/dist/src/code-execution/isolate/output.js +143 -0
  40. package/dist/src/code-execution/isolate/output.js.map +1 -0
  41. package/dist/src/code-execution/isolate/prelude.d.ts +109 -0
  42. package/dist/src/code-execution/isolate/prelude.d.ts.map +1 -0
  43. package/dist/src/code-execution/isolate/prelude.js +401 -0
  44. package/dist/src/code-execution/isolate/prelude.js.map +1 -0
  45. package/dist/src/code-execution/isolate/protocol.d.ts +151 -0
  46. package/dist/src/code-execution/isolate/protocol.d.ts.map +1 -0
  47. package/dist/src/code-execution/isolate/protocol.js +150 -0
  48. package/dist/src/code-execution/isolate/protocol.js.map +1 -0
  49. package/dist/src/code-execution/isolate/render.d.ts +57 -0
  50. package/dist/src/code-execution/isolate/render.d.ts.map +1 -0
  51. package/dist/src/code-execution/isolate/render.js +214 -0
  52. package/dist/src/code-execution/isolate/render.js.map +1 -0
  53. package/dist/src/code-execution/isolate/runner.d.ts +250 -0
  54. package/dist/src/code-execution/isolate/runner.d.ts.map +1 -0
  55. package/dist/src/code-execution/isolate/runner.js +854 -0
  56. package/dist/src/code-execution/isolate/runner.js.map +1 -0
  57. package/dist/src/code-execution/isolate/scripts.d.ts +175 -0
  58. package/dist/src/code-execution/isolate/scripts.d.ts.map +1 -0
  59. package/dist/src/code-execution/isolate/scripts.js +357 -0
  60. package/dist/src/code-execution/isolate/scripts.js.map +1 -0
  61. package/dist/src/code-execution/quickjs.wasm +0 -0
  62. package/dist/src/code-execution/tool-definition.d.ts +93 -43
  63. package/dist/src/code-execution/tool-definition.d.ts.map +1 -1
  64. package/dist/src/code-execution/tool-definition.js +176 -142
  65. package/dist/src/code-execution/tool-definition.js.map +1 -1
  66. package/dist/src/deadline-timer.d.ts +3 -0
  67. package/dist/src/deadline-timer.d.ts.map +1 -1
  68. package/dist/src/deadline-timer.js +1 -1
  69. package/dist/src/deadline-timer.js.map +1 -1
  70. package/dist/src/framework.d.ts +1027 -440
  71. package/dist/src/framework.d.ts.map +1 -1
  72. package/dist/src/framework.js +4093 -2238
  73. package/dist/src/framework.js.map +1 -1
  74. package/dist/src/gate/event-gate.d.ts +28 -1
  75. package/dist/src/gate/event-gate.d.ts.map +1 -1
  76. package/dist/src/gate/event-gate.js +88 -10
  77. package/dist/src/gate/event-gate.js.map +1 -1
  78. package/dist/src/held-writes.d.ts +16 -3
  79. package/dist/src/held-writes.d.ts.map +1 -1
  80. package/dist/src/held-writes.js +16 -3
  81. package/dist/src/held-writes.js.map +1 -1
  82. package/dist/src/index.d.ts +6 -6
  83. package/dist/src/index.d.ts.map +1 -1
  84. package/dist/src/index.js +9 -8
  85. package/dist/src/index.js.map +1 -1
  86. package/dist/src/mcpl/channel-registry.d.ts +471 -75
  87. package/dist/src/mcpl/channel-registry.d.ts.map +1 -1
  88. package/dist/src/mcpl/channel-registry.js +1673 -337
  89. package/dist/src/mcpl/channel-registry.js.map +1 -1
  90. package/dist/src/mcpl/conversation-router.d.ts +12 -7
  91. package/dist/src/mcpl/conversation-router.d.ts.map +1 -1
  92. package/dist/src/mcpl/conversation-router.js +12 -7
  93. package/dist/src/mcpl/conversation-router.js.map +1 -1
  94. package/dist/src/mcpl/convert-block.d.ts.map +1 -1
  95. package/dist/src/mcpl/convert-block.js +9 -5
  96. package/dist/src/mcpl/convert-block.js.map +1 -1
  97. package/dist/src/mcpl/inbound-source.d.ts +50 -0
  98. package/dist/src/mcpl/inbound-source.d.ts.map +1 -1
  99. package/dist/src/mcpl/inbound-source.js +130 -0
  100. package/dist/src/mcpl/inbound-source.js.map +1 -1
  101. package/dist/src/mcpl/index.d.ts +2 -1
  102. package/dist/src/mcpl/index.d.ts.map +1 -1
  103. package/dist/src/mcpl/index.js +3 -2
  104. package/dist/src/mcpl/index.js.map +1 -1
  105. package/dist/src/mcpl/log-value.d.ts +6 -0
  106. package/dist/src/mcpl/log-value.d.ts.map +1 -1
  107. package/dist/src/mcpl/log-value.js +8 -0
  108. package/dist/src/mcpl/log-value.js.map +1 -1
  109. package/dist/src/mcpl/modern-connection.d.ts +15 -6
  110. package/dist/src/mcpl/modern-connection.d.ts.map +1 -1
  111. package/dist/src/mcpl/modern-connection.js +168 -53
  112. package/dist/src/mcpl/modern-connection.js.map +1 -1
  113. package/dist/src/mcpl/prose-grammar.d.ts +4 -5
  114. package/dist/src/mcpl/prose-grammar.d.ts.map +1 -1
  115. package/dist/src/mcpl/prose-grammar.js +4 -5
  116. package/dist/src/mcpl/prose-grammar.js.map +1 -1
  117. package/dist/src/mcpl/protocol-family.d.ts +97 -10
  118. package/dist/src/mcpl/protocol-family.d.ts.map +1 -1
  119. package/dist/src/mcpl/protocol-family.js +173 -16
  120. package/dist/src/mcpl/protocol-family.js.map +1 -1
  121. package/dist/src/mcpl/push-coalescer.d.ts +132 -14
  122. package/dist/src/mcpl/push-coalescer.d.ts.map +1 -1
  123. package/dist/src/mcpl/push-coalescer.js +227 -50
  124. package/dist/src/mcpl/push-coalescer.js.map +1 -1
  125. package/dist/src/mcpl/push-handler.d.ts +6 -1
  126. package/dist/src/mcpl/push-handler.d.ts.map +1 -1
  127. package/dist/src/mcpl/push-handler.js +4 -1
  128. package/dist/src/mcpl/push-handler.js.map +1 -1
  129. package/dist/src/mcpl/reference-fetcher.d.ts +2 -2
  130. package/dist/src/mcpl/reference-fetcher.d.ts.map +1 -1
  131. package/dist/src/mcpl/reference-fetcher.js +4 -4
  132. package/dist/src/mcpl/reference-fetcher.js.map +1 -1
  133. package/dist/src/mcpl/server-connection.d.ts +50 -21
  134. package/dist/src/mcpl/server-connection.d.ts.map +1 -1
  135. package/dist/src/mcpl/server-connection.js +158 -74
  136. package/dist/src/mcpl/server-connection.js.map +1 -1
  137. package/dist/src/mcpl/tags.d.ts +24 -0
  138. package/dist/src/mcpl/tags.d.ts.map +1 -1
  139. package/dist/src/mcpl/tags.js +33 -0
  140. package/dist/src/mcpl/tags.js.map +1 -1
  141. package/dist/src/mcpl/tool-result-normalize.d.ts +2 -1
  142. package/dist/src/mcpl/tool-result-normalize.d.ts.map +1 -1
  143. package/dist/src/mcpl/tool-result-normalize.js.map +1 -1
  144. package/dist/src/mcpl/transport.d.ts +55 -7
  145. package/dist/src/mcpl/transport.d.ts.map +1 -1
  146. package/dist/src/mcpl/transport.js +163 -34
  147. package/dist/src/mcpl/transport.js.map +1 -1
  148. package/dist/src/mcpl/types.d.ts +22 -6
  149. package/dist/src/mcpl/types.d.ts.map +1 -1
  150. package/dist/src/mcpl/types.js.map +1 -1
  151. package/dist/src/module-registry.d.ts +4 -2
  152. package/dist/src/module-registry.d.ts.map +1 -1
  153. package/dist/src/module-registry.js +100 -13
  154. package/dist/src/module-registry.js.map +1 -1
  155. package/dist/src/modules/discord/index.d.ts.map +1 -1
  156. package/dist/src/modules/discord/index.js +8 -13
  157. package/dist/src/modules/discord/index.js.map +1 -1
  158. package/dist/src/modules/history/index.d.ts.map +1 -1
  159. package/dist/src/modules/history/index.js +27 -4
  160. package/dist/src/modules/history/index.js.map +1 -1
  161. package/dist/src/modules/history/semantic.d.ts +15 -3
  162. package/dist/src/modules/history/semantic.d.ts.map +1 -1
  163. package/dist/src/modules/history/semantic.js +27 -5
  164. package/dist/src/modules/history/semantic.js.map +1 -1
  165. package/dist/src/modules/index.d.ts +1 -1
  166. package/dist/src/modules/index.d.ts.map +1 -1
  167. package/dist/src/modules/index.js.map +1 -1
  168. package/dist/src/modules/unknown-tool.d.ts +4 -1
  169. package/dist/src/modules/unknown-tool.d.ts.map +1 -1
  170. package/dist/src/modules/unknown-tool.js +4 -1
  171. package/dist/src/modules/unknown-tool.js.map +1 -1
  172. package/dist/src/modules/workspace/branch-intent.d.ts +3 -1
  173. package/dist/src/modules/workspace/branch-intent.d.ts.map +1 -1
  174. package/dist/src/modules/workspace/branch-intent.js +3 -1
  175. package/dist/src/modules/workspace/branch-intent.js.map +1 -1
  176. package/dist/src/modules/workspace/edit-plan.d.ts +265 -0
  177. package/dist/src/modules/workspace/edit-plan.d.ts.map +1 -0
  178. package/dist/src/modules/workspace/edit-plan.js +794 -0
  179. package/dist/src/modules/workspace/edit-plan.js.map +1 -0
  180. package/dist/src/modules/workspace/edit-text.d.ts +117 -0
  181. package/dist/src/modules/workspace/edit-text.d.ts.map +1 -0
  182. package/dist/src/modules/workspace/edit-text.js +584 -0
  183. package/dist/src/modules/workspace/edit-text.js.map +1 -0
  184. package/dist/src/modules/workspace/effects.d.ts +5 -4
  185. package/dist/src/modules/workspace/effects.d.ts.map +1 -1
  186. package/dist/src/modules/workspace/effects.js +78 -25
  187. package/dist/src/modules/workspace/effects.js.map +1 -1
  188. package/dist/src/modules/workspace/index.d.ts +484 -61
  189. package/dist/src/modules/workspace/index.d.ts.map +1 -1
  190. package/dist/src/modules/workspace/index.js +2173 -645
  191. package/dist/src/modules/workspace/index.js.map +1 -1
  192. package/dist/src/modules/workspace/observe.d.ts +213 -38
  193. package/dist/src/modules/workspace/observe.d.ts.map +1 -1
  194. package/dist/src/modules/workspace/observe.js +416 -36
  195. package/dist/src/modules/workspace/observe.js.map +1 -1
  196. package/dist/src/modules/workspace/reconcile.d.ts.map +1 -1
  197. package/dist/src/modules/workspace/reconcile.js +15 -8
  198. package/dist/src/modules/workspace/reconcile.js.map +1 -1
  199. package/dist/src/modules/workspace/text.d.ts +32 -0
  200. package/dist/src/modules/workspace/text.d.ts.map +1 -0
  201. package/dist/src/modules/workspace/text.js +67 -0
  202. package/dist/src/modules/workspace/text.js.map +1 -0
  203. package/dist/src/modules/workspace/types.d.ts +210 -6
  204. package/dist/src/modules/workspace/types.d.ts.map +1 -1
  205. package/dist/src/modules/workspace/types.js.map +1 -1
  206. package/dist/src/modules/workspace/watcher.d.ts +3 -2
  207. package/dist/src/modules/workspace/watcher.d.ts.map +1 -1
  208. package/dist/src/modules/workspace/watcher.js.map +1 -1
  209. package/dist/src/operator-log.d.ts +52 -24
  210. package/dist/src/operator-log.d.ts.map +1 -1
  211. package/dist/src/operator-log.js.map +1 -1
  212. package/dist/src/recovery/discord-awareness-outbox.d.ts +496 -72
  213. package/dist/src/recovery/discord-awareness-outbox.d.ts.map +1 -1
  214. package/dist/src/recovery/discord-awareness-outbox.js +1196 -289
  215. package/dist/src/recovery/discord-awareness-outbox.js.map +1 -1
  216. package/dist/src/recovery/offline-branch.d.ts +26 -1
  217. package/dist/src/recovery/offline-branch.d.ts.map +1 -1
  218. package/dist/src/recovery/offline-branch.js +164 -39
  219. package/dist/src/recovery/offline-branch.js.map +1 -1
  220. package/dist/src/recovery/recover-cli.js +23 -4
  221. package/dist/src/recovery/recover-cli.js.map +1 -1
  222. package/dist/src/send-tools.d.ts +11 -0
  223. package/dist/src/send-tools.d.ts.map +1 -0
  224. package/dist/src/send-tools.js +11 -0
  225. package/dist/src/send-tools.js.map +1 -0
  226. package/dist/src/tool-result-guard.d.ts +4 -3
  227. package/dist/src/tool-result-guard.d.ts.map +1 -1
  228. package/dist/src/tool-result-guard.js +5 -4
  229. package/dist/src/tool-result-guard.js.map +1 -1
  230. package/dist/src/tool-result-history.d.ts +1 -1
  231. package/dist/src/tool-result-history.js +1 -1
  232. package/dist/src/tune-out/coordinator.d.ts +21 -0
  233. package/dist/src/tune-out/coordinator.d.ts.map +1 -1
  234. package/dist/src/tune-out/coordinator.js +139 -37
  235. package/dist/src/tune-out/coordinator.js.map +1 -1
  236. package/dist/src/types/agent.d.ts +4 -0
  237. package/dist/src/types/agent.d.ts.map +1 -1
  238. package/dist/src/types/events.d.ts +62 -9
  239. package/dist/src/types/events.d.ts.map +1 -1
  240. package/dist/src/types/framework.d.ts +62 -58
  241. package/dist/src/types/framework.d.ts.map +1 -1
  242. package/dist/src/types/module.d.ts +40 -8
  243. package/dist/src/types/module.d.ts.map +1 -1
  244. package/dist/src/types/trace.d.ts +111 -10
  245. package/dist/src/types/trace.d.ts.map +1 -1
  246. package/dist/src/usage/types.d.ts +16 -0
  247. package/dist/src/usage/types.d.ts.map +1 -1
  248. package/dist/src/usage/usage-tracker.d.ts +14 -1
  249. package/dist/src/usage/usage-tracker.d.ts.map +1 -1
  250. package/dist/src/usage/usage-tracker.js +81 -41
  251. package/dist/src/usage/usage-tracker.js.map +1 -1
  252. package/package.json +6 -5
  253. package/src/agent.ts +93 -12
  254. package/src/api/server.ts +14 -12
  255. package/src/code-execution/engine.ts +595 -0
  256. package/src/code-execution/index.ts +5 -17
  257. package/src/code-execution/isolate/calls.ts +199 -0
  258. package/src/code-execution/isolate/child-entry.ts +5 -0
  259. package/src/code-execution/isolate/child-main.ts +132 -0
  260. package/src/code-execution/isolate/child.ts +327 -0
  261. package/src/code-execution/isolate/frames.ts +209 -0
  262. package/src/code-execution/isolate/output.ts +161 -0
  263. package/src/code-execution/isolate/prelude.ts +409 -0
  264. package/src/code-execution/isolate/protocol.ts +240 -0
  265. package/src/code-execution/isolate/render.ts +230 -0
  266. package/src/code-execution/isolate/runner.ts +911 -0
  267. package/src/code-execution/isolate/scripts.ts +479 -0
  268. package/src/code-execution/quickjs.wasm +0 -0
  269. package/src/code-execution/quickjs.wasm.LICENSES +149 -0
  270. package/src/code-execution/tool-definition.ts +236 -167
  271. package/src/deadline-timer.ts +1 -1
  272. package/src/framework.ts +4468 -2418
  273. package/src/gate/event-gate.ts +78 -11
  274. package/src/held-writes.ts +17 -3
  275. package/src/index.ts +30 -22
  276. package/src/mcpl/channel-registry.ts +1825 -368
  277. package/src/mcpl/conversation-router.ts +12 -7
  278. package/src/mcpl/convert-block.ts +9 -5
  279. package/src/mcpl/inbound-source.ts +131 -0
  280. package/src/mcpl/index.ts +4 -2
  281. package/src/mcpl/log-value.ts +9 -0
  282. package/src/mcpl/modern-connection.ts +162 -53
  283. package/src/mcpl/prose-grammar.ts +4 -5
  284. package/src/mcpl/protocol-family.ts +199 -21
  285. package/src/mcpl/push-coalescer.ts +306 -62
  286. package/src/mcpl/push-handler.ts +10 -2
  287. package/src/mcpl/reference-fetcher.ts +4 -4
  288. package/src/mcpl/server-connection.ts +180 -79
  289. package/src/mcpl/tags.ts +36 -0
  290. package/src/mcpl/tool-result-normalize.ts +2 -1
  291. package/src/mcpl/transport.ts +162 -33
  292. package/src/mcpl/types.ts +23 -6
  293. package/src/module-registry.ts +92 -13
  294. package/src/modules/discord/index.ts +8 -13
  295. package/src/modules/history/index.ts +25 -3
  296. package/src/modules/history/semantic.ts +29 -6
  297. package/src/modules/index.ts +1 -0
  298. package/src/modules/unknown-tool.ts +4 -1
  299. package/src/modules/workspace/branch-intent.ts +3 -1
  300. package/src/modules/workspace/edit-plan.ts +954 -0
  301. package/src/modules/workspace/edit-text.ts +618 -0
  302. package/src/modules/workspace/effects.ts +70 -19
  303. package/src/modules/workspace/index.ts +2247 -642
  304. package/src/modules/workspace/observe.ts +465 -56
  305. package/src/modules/workspace/reconcile.ts +14 -7
  306. package/src/modules/workspace/text.ts +68 -0
  307. package/src/modules/workspace/types.ts +211 -6
  308. package/src/modules/workspace/watcher.ts +3 -2
  309. package/src/operator-log.ts +47 -19
  310. package/src/recovery/discord-awareness-outbox.ts +1500 -356
  311. package/src/recovery/offline-branch.ts +189 -55
  312. package/src/recovery/recover-cli.ts +25 -4
  313. package/src/send-tools.ts +11 -0
  314. package/src/tool-result-guard.ts +6 -5
  315. package/src/tool-result-history.ts +1 -1
  316. package/src/tune-out/coordinator.ts +163 -42
  317. package/src/types/agent.ts +4 -0
  318. package/src/types/events.ts +62 -9
  319. package/src/types/framework.ts +62 -58
  320. package/src/types/module.ts +40 -8
  321. package/src/types/trace.ts +121 -15
  322. package/src/usage/types.ts +16 -0
  323. package/src/usage/usage-tracker.ts +86 -43
  324. package/dist/src/code-execution/py-runner.d.ts +0 -191
  325. package/dist/src/code-execution/py-runner.d.ts.map +0 -1
  326. package/dist/src/code-execution/py-runner.js +0 -655
  327. package/dist/src/code-execution/py-runner.js.map +0 -1
  328. package/dist/src/code-execution/runtime-py.d.ts +0 -50
  329. package/dist/src/code-execution/runtime-py.d.ts.map +0 -1
  330. package/dist/src/code-execution/runtime-py.js +0 -677
  331. package/dist/src/code-execution/runtime-py.js.map +0 -1
  332. package/dist/src/mcpl/prose-stream-router.d.ts +0 -88
  333. package/dist/src/mcpl/prose-stream-router.d.ts.map +0 -1
  334. package/dist/src/mcpl/prose-stream-router.js +0 -291
  335. package/dist/src/mcpl/prose-stream-router.js.map +0 -1
  336. package/src/code-execution/py-runner.ts +0 -791
  337. package/src/code-execution/runtime-py.ts +0 -677
  338. package/src/mcpl/prose-stream-router.ts +0 -268
@@ -8,7 +8,7 @@ import type { JsStore } from '@animalabs/chronicle';
8
8
  import type { Module, ModuleContext, ProcessState, EventResponse } from '../../types/module.js';
9
9
  import type { ProcessEvent, ToolDefinition, ToolCall, ToolResult } from '../../types/events.js';
10
10
  import type { WorkspaceConfig } from './types.js';
11
- export type { WorkspaceConfig, MountConfig, MountState, WorkspaceModuleState, ReadInput, ReadImageInput, WriteInput, EditInput, DeleteInput, LsInput, GlobInput, GrepInput, StatusInput, MaterializeInput, SyncInput, } from './types.js';
11
+ export type { WorkspaceConfig, MountConfig, MountState, WorkspaceModuleState, ReadInput, ReadImageInput, WriteInput, EditInput, EditManyInput, DeleteInput, LsInput, GlobInput, GrepInput, StatusInput, MaterializeInput, SyncInput, } from './types.js';
12
12
  /**
13
13
  * Why a workspace-owned filesystem read was refused. Distinguishes the cases a
14
14
  * peer needs to react to differently: a path that never resolved inside the
@@ -24,13 +24,25 @@ export type { WorkspaceConfig, MountConfig, MountState, WorkspaceModuleState, Re
24
24
  * link and, where it leads somewhere, its target, a symlink whose canonical
25
25
  * target lands outside the canonical mount root, or one among the path's
26
26
  * directories leading out of it (`escape`), a file swapped underneath the read
27
- * (`changed`), and a path in another mount's directory nested in the one
28
- * named, or reached through a symlink among the path's directories leading
29
- * there (`other_mount`), whose message names the mount that holds it and the
30
- * path to use there. A `mount_unavailable` for a root whose realpath or stat
31
- * fails otherwise carries that errno, such as EACCES.
27
+ * (`changed`), a path the mount's `include` doesn't cover (`outside_include`),
28
+ * and a path in another mount's directory nested in the one named
29
+ * (`other_mount`), whose message names the mount that holds it and the path
30
+ * to use there. A symlink leading into such a directory is `other_mount`
31
+ * only where its refusal names that mount: a directory, or a file that
32
+ * mount's include covers. Anywhere else, on a mount that doesn't follow
33
+ * symlinks, it gets the code of a link where it stands, `symlink` at the
34
+ * path itself and `parent_symlink` on its way, and on one that does,
35
+ * `escape`, as a path that leaves the mount. On a mount with an include, a
36
+ * link's message names its target only where a tool could name it: a
37
+ * directory, or a file the include covers. A link the include doesn't cover
38
+ * is outside the mount, and its message tells nothing of where it leads, so
39
+ * on a path's way its code is `parent_symlink` wherever it leads; named
40
+ * itself, it's refused as outside the include (`outside_include`), as any
41
+ * path the include doesn't cover is.
42
+ * A `mount_unavailable` for a root whose realpath or stat fails otherwise
43
+ * carries that errno, such as EACCES.
32
44
  */
33
- export type WorkspaceReadErrorCode = 'unknown_mount' | 'traversal' | 'other_mount' | 'mount_unavailable' | 'not_found' | 'directory' | 'symlink' | 'parent_symlink' | 'escape' | 'changed';
45
+ export type WorkspaceReadErrorCode = 'unknown_mount' | 'traversal' | 'outside_include' | 'other_mount' | 'mount_unavailable' | 'not_found' | 'directory' | 'symlink' | 'parent_symlink' | 'escape' | 'changed';
34
46
  /** Where in the open sequence a `WorkspaceReadError` originated (diagnostics). */
35
47
  export type WorkspaceReadStage = 'parse'
36
48
  /** The mount root's check: a directory, the one the workspace was using. */
@@ -119,6 +131,10 @@ export declare class WorkspaceModule implements Module {
119
131
  private otherMounts;
120
132
  /** Whether each mount's root folds case (foldsCase), where disk has it, as the last start read it. */
121
133
  private rootFoldsCase;
134
+ /** Where the last start placed each mount's root (readNesting's `reals`). */
135
+ private placedRoots;
136
+ /** Each directory above each mount's configured path, with where the last start found it on disk (readNesting's `above`). */
137
+ private placedAbove;
122
138
  /**
123
139
  * Whether a file's mode is observed, taken in and applied (MountRuntime's
124
140
  * `modesObserved`): not on Windows, which reports no POSIX modes. A test
@@ -130,6 +146,12 @@ export declare class WorkspaceModule implements Module {
130
146
  * mounts, so restoration must be second-callback-safe like watcher
131
147
  * startup already is (issue #72). Cleared after application. */
132
148
  private savedState;
149
+ /**
150
+ * The mounts configured direct that run as 'chronicle' this session, with
151
+ * the changes the store held there that disk lacked (chooseKinds), for
152
+ * ensureRunning to say once both halves of the lifecycle have run.
153
+ */
154
+ private notDirect;
133
155
  constructor(config: WorkspaceConfig);
134
156
  /**
135
157
  * Inject the Chronicle store. Must be called after framework creation.
@@ -141,6 +163,16 @@ export declare class WorkspaceModule implements Module {
141
163
  * second. `ensureRunning()` gates on `ctx && mounts-populated`.
142
164
  */
143
165
  initStore(store: JsStore): void;
166
+ /**
167
+ * Whether each mount configured direct runs direct: not while the store
168
+ * holds changes there that disk lacks, on the branch selected then, so
169
+ * they stay in view (MountConfig.backend); it runs as 'chronicle' instead,
170
+ * and ensureRunning says so. Decided when initStore gives the store, and
171
+ * again at each start, which knows how the mounts nest, so a start that
172
+ * finds none held starts the mount direct. A path held more than one way
173
+ * is named for the last way set here.
174
+ */
175
+ private chooseKinds;
144
176
  /**
145
177
  * Run `fn` with the mount to itself: observation, decision and effect never
146
178
  * interleave with another pass or a tool write on the same mount (a disk
@@ -154,9 +186,28 @@ export declare class WorkspaceModule implements Module {
154
186
  * A mount as observation reads it, with the root identity the workspace
155
187
  * recorded for it, if any: what a pass reads beneath (runtime), with
156
188
  * rootIdentity's, and what a disk read checks its root against (readRoot),
157
- * with rootIdentityForRead's.
189
+ * with rootIdentityForRead's. A direct mount's has none (diskView).
158
190
  */
159
191
  private viewOf;
192
+ /**
193
+ * A mount's ignore list: its config's, or, for a mount configured direct
194
+ * that names none, the direct kind's default (MountConfig.ignore), whichever
195
+ * kind it runs as this session, as its watch mode goes by its config
196
+ * (watchOf).
197
+ */
198
+ private ignoreOf;
199
+ /**
200
+ * A direct mount as its tools read it: its view, with no root identity,
201
+ * since it promises what's at its root now and keeps no evidence to check
202
+ * that against (MountConfig.backend), and its root as realpath resolves it,
203
+ * or as given where that fails, as a pass's runtime takes it. The view
204
+ * reads beneath that root, so a walk, a listing and grep's reads judge
205
+ * and open their files beneath one root, however its configured path is
206
+ * repointed meanwhile. A read of one file goes through openContainedFile
207
+ * instead, which refuses it once its root is no longer the directory it
208
+ * checked.
209
+ */
210
+ private diskView;
160
211
  /** The view reconciliation needs of a mount, refreshed per pass. */
161
212
  private runtime;
162
213
  /**
@@ -168,8 +219,11 @@ export declare class WorkspaceModule implements Module {
168
219
  * under that spelling beside their own. So the start stops before a segment
169
220
  * spelled any other way, not there, or not a directory, and before a link,
170
221
  * which a walk of the whole mount doesn't go through either. It lists only
171
- * directories it has checked lie inside the mount, and none the mount
172
- * passes over by design, which the walk then answers for.
222
+ * directories it has checked lie inside the mount, and, on a 'chronicle'
223
+ * mount, none it passes over by design, which the walk then answers for.
224
+ * A direct mount walks a path its tools name whatever its ignore list or
225
+ * an editor's file name covers there (MountConfig.ignore), so there it
226
+ * lists such directories too, and only another mount's it doesn't.
173
227
  */
174
228
  private walkStart;
175
229
  /** One disk→store pass; the caller holds the mount's turn. Emits its events. */
@@ -217,16 +271,32 @@ export declare class WorkspaceModule implements Module {
217
271
  /**
218
272
  * Start chokidar watchers and emit workspace:mounted events.
219
273
  * Idempotent: safe to call from both start() and initStore(), fires once
220
- * per mount regardless of which runs second.
274
+ * per mount regardless of which runs second. Once both have run, it
275
+ * decides again which mounts configured direct run direct, now that the
276
+ * mounts' nesting is known, and says which don't, once for this start.
221
277
  */
222
278
  private ensureRunning;
279
+ /**
280
+ * Say, for whoever runs the host, which mounts configured direct run as
281
+ * 'chronicle' this session (chooseKinds), what the workspace holds there
282
+ * that keeps them so, and the two ways to start one direct: on stderr,
283
+ * and as one ops alert for them all (the framework's failures log, its
284
+ * `ops:alert` trace and, where one is set, its webhook, which posts one
285
+ * alert of a kind per cooldown and keeps only the start and end of a long
286
+ * one). So the words of fixed length, what's happening and the ways out,
287
+ * come first, and the mounts and what they hold after them.
288
+ */
289
+ private sayNotDirect;
223
290
  private initialScan;
224
291
  stop(): Promise<void>;
225
- /** Mount names + modes, for peer callers (framework spill/journal paths)
226
- * that need a writable mount without reaching into private state. */
292
+ /** Mount names + modes, and each mount's include where it sets one, for
293
+ * peer callers (framework spill/journal paths) that need a mount for files
294
+ * of their own, the first writable one without an include
295
+ * (firstWritableMountName), without reaching into private state. */
227
296
  getMounts(): Array<{
228
297
  name: string;
229
298
  mode: 'read-write' | 'read-only';
299
+ include?: readonly string[];
230
300
  }>;
231
301
  getTools(): ToolDefinition[];
232
302
  private generatedTextFiles;
@@ -248,8 +318,11 @@ export declare class WorkspaceModule implements Module {
248
318
  onProcess(event: ProcessEvent, _state: ProcessState): Promise<EventResponse>;
249
319
  /**
250
320
  * Resolve a mount-prefixed path (e.g. "tickets/2026-04-22-foo.md") to its
251
- * absolute filesystem path. Returns null if the mount is unknown or the
252
- * resolved path escapes the mount root.
321
+ * absolute filesystem path. Returns null if the mount is unknown or
322
+ * doesn't hold the path: one that leaves the mount's directory, lies in
323
+ * another mount's directory nested in it, or falls outside its include, or
324
+ * one that can't name a file of it, with a separator right after the
325
+ * mount's name or a lone UTF-16 surrogate.
253
326
  *
254
327
  * **Lexical containment only.** The guard reasons about `..` segments in the
255
328
  * path string; it knows nothing about what is on disk. A symlink inside the
@@ -258,6 +331,10 @@ export declare class WorkspaceModule implements Module {
258
331
  * path for resolution-only purposes (write targets, nonexistent paths,
259
332
  * display); for reading file content, use {@link readFileFromDisk}, which
260
333
  * enforces the mount's `followSymlinks` policy and canonical containment.
334
+ * It judges other mounts' directories by where the last start placed them,
335
+ * so for a direct mount whose root has moved since, it can differ from
336
+ * `readFileFromDisk`, which takes the nesting where the root lies now
337
+ * (movedNesting), about which paths lie in another mount's directory.
261
338
  *
262
339
  * @deprecated for direct filesystem reads — call `readFileFromDisk()`.
263
340
  */
@@ -278,10 +355,13 @@ export declare class WorkspaceModule implements Module {
278
355
  * (agent-framework #277).
279
356
  *
280
357
  * A write whose tree entry is set but that then fails returns success
281
- * false with `data: { inChronicle: true }`: its copy on disk was refused, or
282
- * something after the entry (recording its intent, the event, the push)
283
- * threw. The workspace's tools read the file from the tree, so it is there
284
- * for them, on the branch that was current when the entry was set.
358
+ * false with `data: { inChronicle: true }`: its copy on disk was refused,
359
+ * the store failed after recording the entry, which skips the push where
360
+ * the mount pushes, or something after the entry (recording its intent,
361
+ * the event, the push) threw. The workspace's tools read the file from the
362
+ * tree, so it is there for them, on the branch that was current when the
363
+ * entry was set. A set that threw and couldn't be read back throws, saying
364
+ * that whether the entry is set isn't known.
285
365
  */
286
366
  writeBinary(mountPrefixedPath: string, data: Buffer, mimeType: string, options?: {
287
367
  branch?: string;
@@ -289,8 +369,10 @@ export declare class WorkspaceModule implements Module {
289
369
  private writeBinaryUnderWay;
290
370
  /**
291
371
  * Read a file's raw bytes from a mount (through the Chronicle tree, synced
292
- * first like the `read` tool). Public API for the framework's synthesized
293
- * `read_image` tool and other peer callers that need binary content.
372
+ * first like the `read` tool; on a direct mount, from disk as
373
+ * readBinaryFromDisk reads it, at most the mount's `maxFileSize`). Public
374
+ * API for the framework's synthesized `read_image` tool and other peer
375
+ * callers that need binary content.
294
376
  */
295
377
  readBinary(mountPrefixedPath: string): Promise<{
296
378
  data: Buffer;
@@ -329,6 +411,8 @@ export declare class WorkspaceModule implements Module {
329
411
  } | {
330
412
  error: string;
331
413
  }>;
414
+ /** A file's bytes as readBinaryFromDisk reads them, once its path is parsed. */
415
+ private bytesFromDisk;
332
416
  /** The directories of the mounts nested inside a mount, mount-relative, in each spelling. */
333
417
  private othersOf;
334
418
  /**
@@ -351,17 +435,77 @@ export declare class WorkspaceModule implements Module {
351
435
  * as configured still names it as configured (resolveAbsolutePath). A
352
436
  * directory not on disk keeps the spellings the roots give alone. Each
353
437
  * mount's real root comes back beside the nesting (`reals`), for what
354
- * start reads there.
438
+ * start reads there, and each directory above each configured path with
439
+ * where it lies on disk (`above`), for a direct mount whose root moves
440
+ * (movedNesting).
355
441
  */
356
442
  private readNesting;
357
- /** The mounts nested in `mountName`, by directory, name and real root where it has one (MountView's `nested`), in each spelling known. */
443
+ /**
444
+ * The mounts nested in `mountName`, by directory, name, real root where it
445
+ * has one, and include (MountView's `nested`), in each spelling known.
446
+ */
358
447
  private nestedOf;
448
+ /**
449
+ * The mounts nested in `mount` as a call of it that resolved its root to
450
+ * `rootReal` sees them: movedNesting where that differs from where the
451
+ * last start placed it, the start's placement (nestedOf) otherwise.
452
+ */
453
+ private nestedFor;
454
+ /**
455
+ * The mounts nested in a direct mount whose root a check resolved to
456
+ * `rootReal`, where that's elsewhere than the last start placed it, as when
457
+ * a link it's configured through is repointed; null where the start's
458
+ * placement holds, or where nothing is at `rootReal`: there the parse's
459
+ * checks keep the start's placement, and a read says the root is gone. A
460
+ * direct mount reads beneath whatever directory is at its root, so a check
461
+ * judges which mount a path is by the root it resolved. A tool's parse
462
+ * resolves it once, and its respelling and its checks of the path it's
463
+ * given (parseFilePath's, refusesAsOutside, grep's) read disk beneath that
464
+ * root and judge by the nesting there. A read and a walk each resolve it
465
+ * for themselves, and judge the include and the nesting again beneath it.
466
+ * So a root repointed during a call can change which answer or refusal a
467
+ * path gets, but nothing a read or a walk serves is a file the include
468
+ * leaves out, nothing a walk serves lies in another mount's directory as
469
+ * its own nesting places it, and nothing a read serves lies in the
470
+ * directory of a mount its own nesting claims by real root. Whoever writes
471
+ * the disk can race a read in two ways, as a rename during a call can on
472
+ * any mount. On a disk that folds names, a read judges the include by the
473
+ * path as its parse spelled it, so a root repointed between the two can
474
+ * have it serve a file the new root spells otherwise (sameLevels). And a
475
+ * mount nested by its directories alone, since its real root holds this
476
+ * one, is judged by the parse's nesting, so a root repointed between a
477
+ * read's parse and its open can have it serve a path in that mount's
478
+ * directory. Each mount is placed as a start places it (placementOf), from
479
+ * where its real root and the directories above its configured path lie on
480
+ * disk. For a mount configured at this mount's own path or beneath it,
481
+ * that's where they lie now: beneath `rootReal` where they lie beneath this
482
+ * mount's path, and the directories above this mount's path as resolving
483
+ * that path finds them. For any other mount, it's where the last start
484
+ * found them. Each carries its own include, as nestedOf gives it. It
485
+ * resolves nothing but the directories on this mount's own configured path
486
+ * and those beneath its root, so a share elsewhere that doesn't answer
487
+ * holds only its own calls, unless such a directory is a link into it,
488
+ * where that mount's files lie. What it leaves to the next start: a mount
489
+ * configured elsewhere whose own root has moved since, as when a link on
490
+ * its configured path is repointed, this mount's own reached through
491
+ * another link among them, that mount's spellings through other links, and
492
+ * the other mounts' own placements, so a direct root moved into another
493
+ * mount's directory is that mount's too, as a nested mount's root moved
494
+ * while running stays placed.
495
+ */
496
+ private movedNesting;
359
497
  /**
360
498
  * The innermost mount nested in `mountName` whose directory holds a path
361
499
  * of that mount, judged lexically where the path lands (`.`, `..` and
362
500
  * repeated separators resolved, as for the traversal guard; a link of the
363
501
  * outer mount isn't followed), with the path to use there; undefined when
364
- * no nested mount's directory holds it.
502
+ * no nested mount's directory holds it. A path parsePath has respelled is
503
+ * compared with the directory's spellings exactly. One judged as given
504
+ * (`asGiven`, resolveAbsolutePath's) is compared loosely, as a disk that
505
+ * folds names may compare it (beginsWithDir), so it can't reach that
506
+ * mount's directory by spelling a segment otherwise. On a disk that tells
507
+ * names apart, that takes a directory of this mount's own spelled like the
508
+ * nested one in another way as that mount's too.
365
509
  */
366
510
  private holderOf;
367
511
  /**
@@ -372,41 +516,119 @@ export declare class WorkspaceModule implements Module {
372
516
  private otherMountNote;
373
517
  /**
374
518
  * parsePath for the file operations (read, write, edit, delete, and the
375
- * module's binary and disk reads and writes). A path in another mount's
376
- * directory nested in this one is that mount's: this mount's passes don't
377
- * observe it and its pushes don't write it, so its file operations refuse
378
- * it, naming the innermost mount that holds it and the path to use there.
519
+ * module's binary and disk reads and writes), refused where the mount
520
+ * doesn't hold the path. A path in another mount's directory nested in
521
+ * this one is that mount's: this mount's passes don't observe it and its
522
+ * pushes don't write it, so the refusal names the innermost mount that
523
+ * holds it and the path to use there. A path the mount's include doesn't
524
+ * cover is outside the mount, whatever disk or the workspace's history has
525
+ * there. A directory is checked the same way, since a path can be a
526
+ * directory on one side and a file on the other.
379
527
  */
380
528
  private parseFilePath;
381
529
  /**
382
530
  * The refusal for a path of `mount` that reaches a nested mount's directory
383
- * through a symlink on its way (nestedAtReal), or null where it doesn't. On
384
- * a mount that doesn't follow the link, the refusal is the link's own
385
- * (linkWords), as the readers and pushes give it. A mount with nothing
386
- * nested has nothing to find, so it pays nothing.
531
+ * through a symlink on its way (nestedAtReal), or a file this mount's own
532
+ * include leaves out (coversLanding), or, on a mount that follows links
533
+ * with an include, one realpath can't resolve, or null where it doesn't.
534
+ * On a mount that doesn't follow the link, the refusal is the link's own
535
+ * (linkWords), as the readers and pushes give it. On one that does, it
536
+ * names the nested mount only where the place is that mount's
537
+ * (namesNestedPlace); anywhere else the place is no mount's, so the path
538
+ * leaves this one, in the disk readers' words, as it does where it lands
539
+ * on a file this mount's include leaves out. A mount with nothing nested,
540
+ * and without both an include and links followed, has nothing to find, so
541
+ * it pays nothing. The caller gives the nesting and the root to judge by
542
+ * (`nested`, `root`). A direct mount's file operation gives those its
543
+ * parse found, so where the path lands, and any link on its way, is judged
544
+ * beneath the root that parse resolved; any other caller gives the start's
545
+ * nesting and the configured path.
546
+ */
547
+ private landingRefusal;
548
+ /**
549
+ * A parsed path, refused where the mount doesn't hold it: in a nested
550
+ * mount's directory first, naming the mount that holds it, then outside
551
+ * the mount's include. Each is judged on the path as the caller parsed it:
552
+ * as disk spells it for parseFilePath, as given for resolveAbsolutePath,
553
+ * which is synchronous and says so (`asGiven`, so the nested-mount check
554
+ * folds where disk does). The include's refusal shows the path as given
555
+ * (`given`), since it answers the path the caller asked about.
556
+ */
557
+ private refuseNotHeld;
558
+ /**
559
+ * Whether a mount-relative path names a file, as grep decides what a path
560
+ * it's given names: for a path the include covers, a file in the
561
+ * workspace's history, or anything but a directory on disk. Grep takes it
562
+ * as a directory only when neither side has a file there, and filters what
563
+ * it finds beneath it by the mount's include. A path the include doesn't
564
+ * cover names no file of the mount's, whatever disk or history holds
565
+ * there, so one refusesAsOutside lets through is a directory. A direct
566
+ * mount has no history: what a run of it as 'chronicle' left in the store
567
+ * isn't its own, so disk alone decides. Disk is read beneath `root`: a
568
+ * direct mount's is the root its parse resolved, a store-backed mount's
569
+ * its configured path.
570
+ */
571
+ private namesFile;
572
+ /**
573
+ * Whether sync, materialize, grep, glob or ls refuses a path it's given as
574
+ * outside the mount's include. A path the include doesn't cover is a scope
575
+ * exactly where a listing names a directory: where disk has a directory
576
+ * reached from the mount's root through directories, with no link among
577
+ * them, or the workspace's history holds an entry beneath it that's the
578
+ * mount's own to list (withinIncludes). The one exception is a directory
579
+ * the ignore list covers, which a listing passes over and which is still a
580
+ * scope when it's named, since a sync that names it takes in what's there
581
+ * (#276). Anything else is refused, a file at the path included, which no
582
+ * scope tool takes up. The walk descends no link it meets. Where covered
583
+ * history makes a name a scope and disk has since put a link there, a
584
+ * mount that doesn't follow symlinks refuses the link, as it refuses any
585
+ * link on a path's way, and on a mount that does, a pass of the scope
586
+ * follows the link, and its answer shows whether the link leads out of the
587
+ * mount. A
588
+ * path in another mount's directory nested in this one is that mount's,
589
+ * whatever this mount's include says, so it isn't refused here: each tool
590
+ * names the mount that holds it, as the file operations do. A direct mount
591
+ * has no history, as namesFile says, and is judged beneath the root its
592
+ * parse resolved (`root`), by the nesting there (`moved`, movedNesting).
387
593
  */
388
- private leadsIntoNested;
389
- /** A parsed path, refused if it lies in a nested mount's directory (parseFilePath). */
390
- private refuseNested;
594
+ private refusesAsOutside;
391
595
  /**
392
596
  * Parse a mount-prefixed path into its mount and mount-relative path, as
393
- * disk spells it (diskSpelling), with `path` the mount-prefixed path so
394
- * spelled. On a disk that folds names, a path spelled otherwise reaches
395
- * disk's file, so every tool takes it by disk's name: one name per file,
396
- * and the names its answers give are disk's, except that a path that names
397
- * a workspace entry exactly, or does once its directories take disk's
398
- * spelling, keeps the entry's spelling. A path the workspace records an
399
- * intent at, such as a deletion disk hasn't been given yet, counts as an
400
- * entry here, so the calls that settle it reach it. The workspace's
401
- * entries (entriesOf) stand in for disk where it has nothing yet, so a
402
- * draft has one name too. Neither applies to a path that disk's spelling
403
- * puts in a nested mount's directory.
597
+ * disk spells it (diskSpelling). `path` is the mount-prefixed path in that
598
+ * spelling where it differs from the one spelling, and otherwise the path
599
+ * as the caller gave it. The path is read in its one spelling first
600
+ * (parsePathAsGiven), so the respelling only ever sees a path with no
601
+ * empty, `.` or `..` segment and no separator before its first. On a disk
602
+ * that folds names, a path spelled otherwise reaches disk's file, so every
603
+ * tool takes it by disk's name: one name per file, and the names its
604
+ * answers give are disk's, except that a path that names a workspace entry
605
+ * exactly, or does once its directories take disk's spelling, keeps the
606
+ * entry's spelling, and what lies past a link on the way keeps the
607
+ * caller's, since the step reads nothing past a link. A path the workspace
608
+ * records an intent at, such as a deletion disk hasn't been given yet,
609
+ * counts as an entry here, so the calls that settle it reach it. The
610
+ * workspace's entries (entriesOf) stand in for disk where it has nothing
611
+ * yet, so a draft has one name too. Neither applies to a path that disk's
612
+ * spelling puts in a nested mount's directory. A direct mount holds no
613
+ * entries, so its paths take disk's spelling alone. Past a nested mount's
614
+ * directory the path stays as given, since what lies there is that mount's
615
+ * to name. Every answer shows `path`, a name the include leaves out
616
+ * included, since how disk spells a name the caller gave is no content of
617
+ * that file, except the include's own refusal, which shows the path
618
+ * exactly as given (refuseNotHeld), since it answers the path asked about.
404
619
  * A handler that must read something at the moment it's asked, as
405
620
  * handleSync reads the branch a path sync adopts on, reads it before
406
- * calling this, since this awaits disk. The entries are read when the
407
- * step needs them, some after those awaits, from the branch current then.
621
+ * calling this, since this awaits disk. The entries are read when the step
622
+ * needs them, some after those awaits, from the branch current then.
408
623
  */
409
624
  private parsePath;
625
+ /**
626
+ * How many segments the innermost nested mount's directory that holds
627
+ * `relativePath` has, in a spelling it's known by (othersOf), or, for a
628
+ * direct mount whose root has moved, in the nesting there (`moved`);
629
+ * undefined when no nested mount's directory holds it.
630
+ */
631
+ private nestedDepth;
410
632
  /**
411
633
  * A mount's entries on the current branch, and the paths it records an
412
634
  * intent at there, as diskSpelling reads them when it does, whether its
@@ -418,7 +640,19 @@ export declare class WorkspaceModule implements Module {
418
640
  */
419
641
  private entriesOf;
420
642
  /**
421
- * Parse a mount-prefixed path into (mountName, relativePath), as spelled.
643
+ * Parse a mount-prefixed path into its mount and the one mount-relative
644
+ * path every later step reads, as given, before disk's spelling
645
+ * (parsePath): `/` between segments (`\` read as `/` where it's the
646
+ * platform's separator), with no empty or `.` segment and no trailing `/`,
647
+ * and '' for the mount's root. So the traversal guard here and every later
648
+ * step judge one spelling of the path, which parsePath then respells name
649
+ * by name as disk lists them. A `..` segment takes back the segment before
650
+ * it, before anything looks the path up, so a mount's include judges the
651
+ * path every tool acts on, and one with nothing left to take back climbs
652
+ * above the mount's root and is refused, whatever it reaches afterwards. A
653
+ * separator straight after the mount's name would make the rest an
654
+ * absolute path, so that is refused too, and every reader that takes a
655
+ * path refuses it here, a disk reader included.
422
656
  */
423
657
  private parsePathAsGiven;
424
658
  /**
@@ -448,6 +682,8 @@ export declare class WorkspaceModule implements Module {
448
682
  * which answers while the evidence awaits reopening; where even it can't
449
683
  * be read, as when the evidence was never read back whole, the read is
450
684
  * refused too, with an errno only where no directory is at the root's path.
685
+ * A direct mount's root is checked against no identity, and its read reads
686
+ * no evidence: it promises what's at its root now (diskView).
451
687
  */
452
688
  private readRoot;
453
689
  /**
@@ -455,7 +691,9 @@ export declare class WorkspaceModule implements Module {
455
691
  * with the code and errno readRoot gives what is at its path now (its stage
456
692
  * and words are this check's): gone, or not a directory, with ENOENT or
457
693
  * ENOTDIR, so a caller reads a root gone mid-read as one gone before it; or
458
- * another directory, with none.
694
+ * another directory, with none. A direct mount reads whatever directory is
695
+ * at its root (MountConfig.backend), so for it, another directory there is
696
+ * one the next read reads.
459
697
  */
460
698
  private rootMoved;
461
699
  /**
@@ -469,7 +707,8 @@ export declare class WorkspaceModule implements Module {
469
707
  * among the directories on its way beneath the mount's root, wherever it
470
708
  * leads (linkOnTheWay), before anything resolves it: as `escape` for a
471
709
  * link leading outside the mount, as `other_mount` for one into a nested
472
- * mount's directory, and as `parent_symlink` for any other.
710
+ * mount's directory where its refusal names that mount, and as
711
+ * `parent_symlink` for any other.
473
712
  * 2. `lstat` the lexical path — refuse directories; refuse a final-component
474
713
  * symlink when the mount does not `followSymlinks`; refuse anything else
475
714
  * that isn't a regular file, such as a FIFO, without opening it.
@@ -518,7 +757,9 @@ export declare class WorkspaceModule implements Module {
518
757
  * - Once the workspace has recorded the mount root's identity, with the
519
758
  * first evidence it gathers there, a root that is another directory is
520
759
  * an unavailable mount: a replaced directory, a link swapped in for it,
521
- * or an unmounted drive's mountpoint. In any mount, recorded or not, a
760
+ * or an unmounted drive's mountpoint. A direct mount's reads check no
761
+ * recorded identity: they read beneath whatever directory is at its
762
+ * root (MountConfig.backend). In any mount, recorded or not, a
522
763
  * root that stops being the directory the read checked until the file
523
764
  * has been opened and checked is unavailable too: with ENOENT or
524
765
  * ENOTDIR where no directory is there, as before the read, and with no
@@ -526,9 +767,10 @@ export declare class WorkspaceModule implements Module {
526
767
  * the descriptor that was checked.
527
768
  *
528
769
  * Throws {@link WorkspaceReadError} with a `code` distinguishing unknown
529
- * mount, lexical traversal, a path in another mount's directory nested in
530
- * the one named (`other_mount`), unavailable mount, missing or non-regular
531
- * file, directory, policy-denied symlink, outside-mount target, and
770
+ * mount, lexical traversal, a path the mount's include doesn't cover
771
+ * (`outside_include`), a path in another mount's directory nested in the one named
772
+ * (`other_mount`), unavailable mount, missing or non-regular file,
773
+ * directory, policy-denied symlink, outside-mount target, and
532
774
  * file-changed-during-read.
533
775
  */
534
776
  readFileFromDisk(mountPrefixedPath: string, options?: ReadFileFromDiskOptions): Promise<WorkspaceDiskReadResult>;
@@ -543,9 +785,11 @@ export declare class WorkspaceModule implements Module {
543
785
  /**
544
786
  * Commit a tool's write or delete to the workspace tree, with the branch
545
787
  * intent it implies: store origin for a path disk never agreed with; for a
546
- * deletion, a tombstone, unless the evidence holds no agreed disk copy (P
788
+ * deletion, a tombstone, written before the entry is removed, unless the
789
+ * agreement's evidence for the path, P, holds no agreed disk copy (P
547
790
  * absent, or no P and store origin), when it clears the path's intent and
548
- * pushes nothing. It pushes the change to disk when the mount opts in via
791
+ * pushes nothing. It pushes the change to
792
+ * disk when the mount opts in via
549
793
  * `autoMaterialize` — required for cross-agent pipelines, since another
550
794
  * agent's watcher on the same directory only sees real filesystem events.
551
795
  * The push follows materialize's rule: a disk copy that changed since it
@@ -562,6 +806,24 @@ export declare class WorkspaceModule implements Module {
562
806
  * the path, as an edit makes).
563
807
  */
564
808
  private commitToolChange;
809
+ /**
810
+ * commitToolChange for several paths of one mount at once, as edit_many
811
+ * commits its files: every path's precondition is enforced before any entry
812
+ * is set, then a deletion's tombstone is written, then every entry is set
813
+ * in one record of the store, which takes all of them or none, then each
814
+ * other path's intent, by the rule commitToolChange's doc gives, which the
815
+ * code below applies, with no await between, and one push takes the paths
816
+ * to disk, but for a deletion that clears its path's intent. `onCommitted`
817
+ * is told of each path once the entries are set, also when the store throws
818
+ * after setting them, whose error then goes on in place of the push
819
+ * (changesLanded).
820
+ * Answers, by path, the reason for each that reached the workspace but not
821
+ * disk (`refused`), and, apart from it, why one whose bytes reached disk
822
+ * left the file's mode as disk had it (`modeKept`), and that a deletion
823
+ * clearing a conflict that named a disk file unlinked nothing (`notes`), as
824
+ * commitToolChange answers them for one path.
825
+ */
826
+ private commitToolChanges;
565
827
  /**
566
828
  * Before a tool reads or changes a path's workspace entry, a pending intent
567
829
  * on that path is settled by a pass over it, so the tool works from what
@@ -586,15 +848,163 @@ export declare class WorkspaceModule implements Module {
586
848
  private ensureSynced;
587
849
  /** Why the workspace holds no entry at a path, when disk explains it. */
588
850
  private notInWorkspace;
851
+ /**
852
+ * A file's bytes for read, from where the mount keeps what it reads: the
853
+ * workspace's copy, taken in from disk first where it holds none
854
+ * (ensureSynced); or, on a direct mount, disk's file as it is now
855
+ * (bytesOnDisk). An error says why there are none to read.
856
+ */
857
+ private bytesOf;
858
+ /**
859
+ * A direct mount's file for read: its bytes on disk as they are now,
860
+ * through the mount's boundary as readFileFromDisk reaches them
861
+ * (openContainedFile), whose refusals are the answer. What a 'chronicle'
862
+ * mount never stores, it doesn't show either: a file over the mount's
863
+ * size limit, and a binary one, with a NUL in its first 8 KB, which
864
+ * read_image reads where it's an image.
865
+ */
866
+ private bytesOnDisk;
589
867
  private handleRead;
590
868
  private handleReadImage;
591
869
  private handleWrite;
592
870
  private handleEdit;
871
+ private handleEditMany;
872
+ /**
873
+ * A call's edits, all or none, applied to the stored copies of their files:
874
+ * edit's one, or edit_many's in the files of one mount. Each edit is matched
875
+ * in its file's text as this call reads it, never in another edit's result
876
+ * (edit-plan.ts), and any problem refuses the call with none of its edits
877
+ * stored: edit names its first problem, and edit_many every problem found.
878
+ *
879
+ * Each edit's own input is checked first, and each path's mount. A problem
880
+ * there refuses edit at once, before any file's text is read, and edit_many
881
+ * when its edits name more than one mount, which no one pass settles.
882
+ * Otherwise edit_many goes on to settle and plan the rest, so its one
883
+ * refusal names the problems it finds; the settling is what a read or a
884
+ * listing of its files would take in from disk, and the refusal says what
885
+ * it took in. A failure before the commit sets the entries stores none of
886
+ * them, and edit_many's answer to it says so. A store that throws as it
887
+ * sets them is read back (commitToolChanges), so the answer says they're
888
+ * stored where its record landed, and that it can't tell where they
889
+ * couldn't be read back.
890
+ * Under the mount's turn, one pass settles every path with disk, by the
891
+ * rule a listing uses, so the edits apply to what disk now holds. That pass
892
+ * is the only step that awaits before the commit: every file is then read,
893
+ * every edit planned, and every entry set (commitToolChanges) with no turn
894
+ * of the event loop between, so no pass, branch change or other call moves
895
+ * the tree between a file's read and its set. Disk then takes what it can
896
+ * of the stored change.
897
+ *
898
+ * The answer is held to `maxChars`, the length the call's result may have
899
+ * (ToolCall.resultMaxChars), as edit-text.ts describes.
900
+ */
901
+ private applyEdits;
902
+ /**
903
+ * Where an edit's path is in its mount, or why the call can't edit it: a
904
+ * path no mount holds, one outside its mount or holding a lone surrogate
905
+ * (parsePath), one a nested mount holds or that leads into one through a
906
+ * link (parseFilePath), a path that names its mount's root, a read-only
907
+ * mount, or for edit_many a generated file. edit's
908
+ * generated file is refused before it gets here, by the same rule
909
+ * (handleToolCall checks a call's `path`, which edit_many's input lacks).
910
+ */
911
+ private editablePath;
912
+ /**
913
+ * Why a call can't change a generated file: another agent's is that agent's,
914
+ * and the agent's own is read-only, since it shows the agent's tool
915
+ * presentation, which set_tool_visibility and set_tool_description change.
916
+ */
917
+ private generatedFileRefusal;
918
+ /**
919
+ * The answer to edits stored but not finished: the commit set every file's
920
+ * entry, and then disk refused some of their pushes, or the store failed
921
+ * after recording them, so their push didn't run, or the rest of the call
922
+ * failed. It stays an error, since part of the call failed, and leads with
923
+ * what is stored, which must not be sent again: a second call can apply
924
+ * those edits twice. edit's is the answer write and delete give, one path's;
925
+ * edit_many's lists the files disk refused, each with its push's reason,
926
+ * notes each file disk took with its mode left as disk had it, as the
927
+ * success answer's `modeKept` does, within `maxChars`, and never says to
928
+ * send the call again. Where the store failed after recording the edits,
929
+ * which stand as on a success, it names each conflict the success answer
930
+ * would (`conflicts`, found only where the mount doesn't push).
931
+ */
932
+ private editsStoredButUnfinished;
593
933
  private handleDelete;
594
934
  private handleLs;
935
+ /**
936
+ * What a listing shows of a directory scope, from where the mount keeps
937
+ * what it reads: the store-backed kind's pass (listingFromStore), or, on a
938
+ * direct mount, disk (listingFromDisk). `keep` chooses the files shown.
939
+ */
940
+ private listingOf;
941
+ /**
942
+ * A 'chronicle' mount's listing: a pass over the scope under the three-way
943
+ * rule, each path it decided with its state, and the directories beneath
944
+ * the scope that disk or the workspace has.
945
+ */
946
+ private listingFromStore;
947
+ /**
948
+ * A direct mount's listing: its walk of the scope (diskWalk), with each
949
+ * entry it took as disk has it now, observed as a pass observes it: a
950
+ * file's size, or why the mount doesn't take it (a link it doesn't follow,
951
+ * one that leaves the mount, what isn't a regular file). A file gone since
952
+ * the walk listed it is no longer there to show.
953
+ */
954
+ private listingFromDisk;
955
+ /**
956
+ * A direct mount's walk of a scope, from its view (diskView): the entries
957
+ * it took that aren't directories (files, links and the like), in path
958
+ * order; the directories directly beneath a scope it doesn't descend; and
959
+ * the regions it couldn't see that a pass reports beside no tracked file:
960
+ * what it couldn't list, what the cap left, and a scope in another mount's
961
+ * directory, said as a listing says it. A path the walk names is walked
962
+ * whatever the mount's ignore list or an editor's file name covers there
963
+ * (MountConfig.ignore), as a path sync's walk is.
964
+ */
965
+ private diskWalk;
595
966
  private handleGlob;
596
967
  private handleGrep;
968
+ /**
969
+ * The texts a 'chronicle' mount's grep searches beneath `start`, or in the
970
+ * single file `relativePath` names, those `keep` lets through, each handed
971
+ * to `each` in path order: a pass over the scope, then each path's
972
+ * workspace copy, labelled with its state, and a conflict's disk side.
973
+ * What it doesn't search is in `skipped`, and what it couldn't see in
974
+ * `incomplete`, each mount-prefixed.
975
+ */
976
+ private textsFromStore;
977
+ /**
978
+ * The texts a direct mount's grep searches beneath `start`, or in the
979
+ * single file `relativePath` names, as namesFile judges it beneath `root`,
980
+ * the root grep's parse resolved, those `keep` lets through, each handed
981
+ * to `each` in path order: each file its walk took (diskWalk), read from
982
+ * disk as it is now, DIRECT_READS_AT_ONCE at a time. A file over the size
983
+ * limit, a binary one and one the mount doesn't take are in `skipped`,
984
+ * each with why, as a 'chronicle' mount's grep lists what it never stored;
985
+ * one gone since the walk listed it isn't there to search.
986
+ */
987
+ private textsFromDisk;
597
988
  private handleStatus;
989
+ /**
990
+ * What the store holds of a mount that disk lacks, on the selected branch,
991
+ * among the mount's own paths. Status counts the first three as pending:
992
+ * recorded conflicts; workspace deletions, pending until a push confirms
993
+ * them on disk (left there without applyDeletions, or unlinked but
994
+ * unconfirmed); and what disk owes by the evidence (entriesByEvidence's
995
+ * `owed`: every entry it doesn't show on disk, a refused or failed push's
996
+ * included). An entry from before the evidence isn't among them until a
997
+ * listing or a materialize checks it: unchecked isn't unpushed. A
998
+ * tombstone beside an entry that's still there, left by a deletion or a
999
+ * write that stopped partway (commitToolChanges), is no deletion: it holds
1000
+ * no change disk lacks, and its entry is judged by the evidence as any
1001
+ * other is. The fourth, intents that can't be read, may hold a deletion
1002
+ * or a conflict, so a mount configured direct counts them too (initStore).
1003
+ * Each lies where the mount's include covers, as status counts them: what
1004
+ * the workspace's history holds outside it is no change of the mount's,
1005
+ * and no push writes it to disk (pushUnlocked).
1006
+ */
1007
+ private heldChanges;
598
1008
  /**
599
1009
  * What a materialize of `mount` should consider: a named file, or every
600
1010
  * tracked path beneath a named directory; otherwise what the evidence says
@@ -610,10 +1020,11 @@ export declare class WorkspaceModule implements Module {
610
1020
  /**
611
1021
  * Whether a path of the mount is its own to push and to count as owed:
612
1022
  * not in another mount's directory nested in it. Copies the mount's tree
613
- * holds there (stored before the nesting) stay in its history and its
614
- * listings (and in status's fileCount, which counts the tree), passed over
615
- * by its syncs, and left out of what it pushes and of status's pending
616
- * changes, conflicts and workspace deletions.
1023
+ * holds there (stored before the nesting) stay in its history, and in its
1024
+ * listings and status's fileCount where that mount's include covers them
1025
+ * (withinIncludes). Its syncs pass over them, and
1026
+ * they're left out of what it pushes and of status's pending changes,
1027
+ * conflicts and workspace deletions.
617
1028
  */
618
1029
  private ownPaths;
619
1030
  /**
@@ -649,6 +1060,9 @@ export declare class WorkspaceModule implements Module {
649
1060
  * The watcher's ops only choose which paths to look at: each path is
650
1061
  * observed again and decided under the three-way rule, so an event that
651
1062
  * arrives late or out of order can't delete or revert anything by itself.
1063
+ * A path outside the mount (insideMount), such as one its include doesn't
1064
+ * cover, is no pass's to decide (gather), so a batch of nothing else takes
1065
+ * no turn of the mount.
652
1066
  */
653
1067
  private handleFsChanges;
654
1068
  /**
@@ -695,4 +1109,13 @@ export declare class WorkspaceModule implements Module {
695
1109
  */
696
1110
  private emitFsEvents;
697
1111
  }
1112
+ /**
1113
+ * Run `work` on each item, at most `width` at once, and hand each result to
1114
+ * `each` in the items' order, as soon as it and those before it are done.
1115
+ * A result handed on is let go, so what's held at once is at most `width`
1116
+ * results, as a direct grep's file contents are. A `work` that rejects
1117
+ * rejects this when its turn comes; any started after it finish unheard.
1118
+ * Exported for its tests.
1119
+ */
1120
+ export declare function inOrder<T, R>(items: readonly T[], width: number, work: (item: T) => Promise<R>, each: (result: R, item: T) => void): Promise<void>;
698
1121
  //# sourceMappingURL=index.d.ts.map