@aigne/agent-runtime 1.12.0-beta.5

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 (234) hide show
  1. package/LICENSE.md +26 -0
  2. package/README.md +79 -0
  3. package/dist/agent-runners/ai-runner.cjs +133 -0
  4. package/dist/agent-runners/ai-runner.d.cts +33 -0
  5. package/dist/agent-runners/ai-runner.d.cts.map +1 -0
  6. package/dist/agent-runners/ai-runner.d.mts +33 -0
  7. package/dist/agent-runners/ai-runner.d.mts.map +1 -0
  8. package/dist/agent-runners/ai-runner.mjs +134 -0
  9. package/dist/agent-runners/ai-runner.mjs.map +1 -0
  10. package/dist/agent-runners/ash-runner.cjs +272 -0
  11. package/dist/agent-runners/ash-runner.d.cts +30 -0
  12. package/dist/agent-runners/ash-runner.d.cts.map +1 -0
  13. package/dist/agent-runners/ash-runner.d.mts +30 -0
  14. package/dist/agent-runners/ash-runner.d.mts.map +1 -0
  15. package/dist/agent-runners/ash-runner.mjs +273 -0
  16. package/dist/agent-runners/ash-runner.mjs.map +1 -0
  17. package/dist/agent-runners/budget.cjs +71 -0
  18. package/dist/agent-runners/budget.d.cts +40 -0
  19. package/dist/agent-runners/budget.d.cts.map +1 -0
  20. package/dist/agent-runners/budget.d.mts +40 -0
  21. package/dist/agent-runners/budget.d.mts.map +1 -0
  22. package/dist/agent-runners/budget.mjs +67 -0
  23. package/dist/agent-runners/budget.mjs.map +1 -0
  24. package/dist/agent-runners/code-runner.cjs +61 -0
  25. package/dist/agent-runners/code-runner.mjs +61 -0
  26. package/dist/agent-runners/code-runner.mjs.map +1 -0
  27. package/dist/agent-runners/env-whitelist.cjs +36 -0
  28. package/dist/agent-runners/env-whitelist.d.cts +5 -0
  29. package/dist/agent-runners/env-whitelist.d.cts.map +1 -0
  30. package/dist/agent-runners/env-whitelist.d.mts +5 -0
  31. package/dist/agent-runners/env-whitelist.d.mts.map +1 -0
  32. package/dist/agent-runners/env-whitelist.mjs +36 -0
  33. package/dist/agent-runners/env-whitelist.mjs.map +1 -0
  34. package/dist/agent-runners/guide-rails.cjs +47 -0
  35. package/dist/agent-runners/guide-rails.d.cts +16 -0
  36. package/dist/agent-runners/guide-rails.d.cts.map +1 -0
  37. package/dist/agent-runners/guide-rails.d.mts +16 -0
  38. package/dist/agent-runners/guide-rails.d.mts.map +1 -0
  39. package/dist/agent-runners/guide-rails.mjs +48 -0
  40. package/dist/agent-runners/guide-rails.mjs.map +1 -0
  41. package/dist/agent-runners/hook-channel.cjs +55 -0
  42. package/dist/agent-runners/hook-channel.d.cts +38 -0
  43. package/dist/agent-runners/hook-channel.d.cts.map +1 -0
  44. package/dist/agent-runners/hook-channel.d.mts +38 -0
  45. package/dist/agent-runners/hook-channel.d.mts.map +1 -0
  46. package/dist/agent-runners/hook-channel.mjs +55 -0
  47. package/dist/agent-runners/hook-channel.mjs.map +1 -0
  48. package/dist/agent-runners/hooks.cjs +107 -0
  49. package/dist/agent-runners/hooks.d.cts +41 -0
  50. package/dist/agent-runners/hooks.d.cts.map +1 -0
  51. package/dist/agent-runners/hooks.d.mts +41 -0
  52. package/dist/agent-runners/hooks.d.mts.map +1 -0
  53. package/dist/agent-runners/hooks.mjs +107 -0
  54. package/dist/agent-runners/hooks.mjs.map +1 -0
  55. package/dist/agent-runners/memory-afs.cjs +342 -0
  56. package/dist/agent-runners/memory-afs.d.cts +221 -0
  57. package/dist/agent-runners/memory-afs.d.cts.map +1 -0
  58. package/dist/agent-runners/memory-afs.d.mts +221 -0
  59. package/dist/agent-runners/memory-afs.d.mts.map +1 -0
  60. package/dist/agent-runners/memory-afs.mjs +326 -0
  61. package/dist/agent-runners/memory-afs.mjs.map +1 -0
  62. package/dist/agent-runners/memory-archive.cjs +263 -0
  63. package/dist/agent-runners/memory-archive.d.cts +47 -0
  64. package/dist/agent-runners/memory-archive.d.cts.map +1 -0
  65. package/dist/agent-runners/memory-archive.d.mts +47 -0
  66. package/dist/agent-runners/memory-archive.d.mts.map +1 -0
  67. package/dist/agent-runners/memory-archive.mjs +257 -0
  68. package/dist/agent-runners/memory-archive.mjs.map +1 -0
  69. package/dist/agent-runners/orchestrator-runner.cjs +302 -0
  70. package/dist/agent-runners/orchestrator-runner.d.cts +23 -0
  71. package/dist/agent-runners/orchestrator-runner.d.cts.map +1 -0
  72. package/dist/agent-runners/orchestrator-runner.d.mts +23 -0
  73. package/dist/agent-runners/orchestrator-runner.d.mts.map +1 -0
  74. package/dist/agent-runners/orchestrator-runner.mjs +303 -0
  75. package/dist/agent-runners/orchestrator-runner.mjs.map +1 -0
  76. package/dist/agent-runners/orchestrator-state.cjs +68 -0
  77. package/dist/agent-runners/orchestrator-state.d.cts +23 -0
  78. package/dist/agent-runners/orchestrator-state.d.cts.map +1 -0
  79. package/dist/agent-runners/orchestrator-state.d.mts +23 -0
  80. package/dist/agent-runners/orchestrator-state.d.mts.map +1 -0
  81. package/dist/agent-runners/orchestrator-state.mjs +65 -0
  82. package/dist/agent-runners/orchestrator-state.mjs.map +1 -0
  83. package/dist/agent-runners/retry.cjs +30 -0
  84. package/dist/agent-runners/retry.d.cts +13 -0
  85. package/dist/agent-runners/retry.d.cts.map +1 -0
  86. package/dist/agent-runners/retry.d.mts +13 -0
  87. package/dist/agent-runners/retry.d.mts.map +1 -0
  88. package/dist/agent-runners/retry.mjs +30 -0
  89. package/dist/agent-runners/retry.mjs.map +1 -0
  90. package/dist/agent-runners/scratchpad-afs.cjs +276 -0
  91. package/dist/agent-runners/scratchpad-afs.d.cts +103 -0
  92. package/dist/agent-runners/scratchpad-afs.d.cts.map +1 -0
  93. package/dist/agent-runners/scratchpad-afs.d.mts +103 -0
  94. package/dist/agent-runners/scratchpad-afs.d.mts.map +1 -0
  95. package/dist/agent-runners/scratchpad-afs.mjs +271 -0
  96. package/dist/agent-runners/scratchpad-afs.mjs.map +1 -0
  97. package/dist/agent-runners/stream-router.cjs +72 -0
  98. package/dist/agent-runners/stream-router.d.cts +22 -0
  99. package/dist/agent-runners/stream-router.d.cts.map +1 -0
  100. package/dist/agent-runners/stream-router.d.mts +22 -0
  101. package/dist/agent-runners/stream-router.d.mts.map +1 -0
  102. package/dist/agent-runners/stream-router.mjs +72 -0
  103. package/dist/agent-runners/stream-router.mjs.map +1 -0
  104. package/dist/agent-runners/system-prompt.cjs +35 -0
  105. package/dist/agent-runners/system-prompt.d.cts +17 -0
  106. package/dist/agent-runners/system-prompt.d.cts.map +1 -0
  107. package/dist/agent-runners/system-prompt.d.mts +17 -0
  108. package/dist/agent-runners/system-prompt.d.mts.map +1 -0
  109. package/dist/agent-runners/system-prompt.mjs +34 -0
  110. package/dist/agent-runners/system-prompt.mjs.map +1 -0
  111. package/dist/agent-runners/team-modes/aggregates.cjs +36 -0
  112. package/dist/agent-runners/team-modes/aggregates.mjs +35 -0
  113. package/dist/agent-runners/team-modes/aggregates.mjs.map +1 -0
  114. package/dist/agent-runners/team-modes/iterate.cjs +46 -0
  115. package/dist/agent-runners/team-modes/iterate.mjs +47 -0
  116. package/dist/agent-runners/team-modes/iterate.mjs.map +1 -0
  117. package/dist/agent-runners/team-modes/parallel.cjs +59 -0
  118. package/dist/agent-runners/team-modes/parallel.mjs +60 -0
  119. package/dist/agent-runners/team-modes/parallel.mjs.map +1 -0
  120. package/dist/agent-runners/team-modes/reflection.cjs +155 -0
  121. package/dist/agent-runners/team-modes/reflection.mjs +156 -0
  122. package/dist/agent-runners/team-modes/reflection.mjs.map +1 -0
  123. package/dist/agent-runners/team-modes/sequential.cjs +63 -0
  124. package/dist/agent-runners/team-modes/sequential.mjs +64 -0
  125. package/dist/agent-runners/team-modes/sequential.mjs.map +1 -0
  126. package/dist/agent-runners/team-modes/utils.cjs +39 -0
  127. package/dist/agent-runners/team-modes/utils.mjs +36 -0
  128. package/dist/agent-runners/team-modes/utils.mjs.map +1 -0
  129. package/dist/agent-runners/team-runner.cjs +277 -0
  130. package/dist/agent-runners/team-runner.d.cts +34 -0
  131. package/dist/agent-runners/team-runner.d.cts.map +1 -0
  132. package/dist/agent-runners/team-runner.d.mts +34 -0
  133. package/dist/agent-runners/team-runner.d.mts.map +1 -0
  134. package/dist/agent-runners/team-runner.mjs +278 -0
  135. package/dist/agent-runners/team-runner.mjs.map +1 -0
  136. package/dist/agent-runners/template-context.cjs +32 -0
  137. package/dist/agent-runners/template-context.d.cts +43 -0
  138. package/dist/agent-runners/template-context.d.cts.map +1 -0
  139. package/dist/agent-runners/template-context.d.mts +43 -0
  140. package/dist/agent-runners/template-context.d.mts.map +1 -0
  141. package/dist/agent-runners/template-context.mjs +33 -0
  142. package/dist/agent-runners/template-context.mjs.map +1 -0
  143. package/dist/index.cjs +123 -0
  144. package/dist/index.d.cts +29 -0
  145. package/dist/index.d.mts +29 -0
  146. package/dist/index.mjs +29 -0
  147. package/dist/program/agent-action.cjs +496 -0
  148. package/dist/program/agent-action.d.cts +42 -0
  149. package/dist/program/agent-action.d.cts.map +1 -0
  150. package/dist/program/agent-action.d.mts +42 -0
  151. package/dist/program/agent-action.d.mts.map +1 -0
  152. package/dist/program/agent-action.mjs +497 -0
  153. package/dist/program/agent-action.mjs.map +1 -0
  154. package/dist/program/agent-messages-tools.cjs +137 -0
  155. package/dist/program/agent-messages-tools.d.cts +59 -0
  156. package/dist/program/agent-messages-tools.d.cts.map +1 -0
  157. package/dist/program/agent-messages-tools.d.mts +59 -0
  158. package/dist/program/agent-messages-tools.d.mts.map +1 -0
  159. package/dist/program/agent-messages-tools.mjs +130 -0
  160. package/dist/program/agent-messages-tools.mjs.map +1 -0
  161. package/dist/program/agent-runner-registry.cjs +314 -0
  162. package/dist/program/agent-runner-registry.d.cts +52 -0
  163. package/dist/program/agent-runner-registry.d.cts.map +1 -0
  164. package/dist/program/agent-runner-registry.d.mts +52 -0
  165. package/dist/program/agent-runner-registry.d.mts.map +1 -0
  166. package/dist/program/agent-runner-registry.mjs +313 -0
  167. package/dist/program/agent-runner-registry.mjs.map +1 -0
  168. package/dist/program/agent-subscribe.cjs +72 -0
  169. package/dist/program/agent-subscribe.d.cts +18 -0
  170. package/dist/program/agent-subscribe.d.cts.map +1 -0
  171. package/dist/program/agent-subscribe.d.mts +18 -0
  172. package/dist/program/agent-subscribe.d.mts.map +1 -0
  173. package/dist/program/agent-subscribe.mjs +73 -0
  174. package/dist/program/agent-subscribe.mjs.map +1 -0
  175. package/dist/program/agent-tools.cjs +135 -0
  176. package/dist/program/agent-tools.d.cts +35 -0
  177. package/dist/program/agent-tools.d.cts.map +1 -0
  178. package/dist/program/agent-tools.d.mts +35 -0
  179. package/dist/program/agent-tools.d.mts.map +1 -0
  180. package/dist/program/agent-tools.mjs +136 -0
  181. package/dist/program/agent-tools.mjs.map +1 -0
  182. package/dist/program/manifest-nesting.cjs +57 -0
  183. package/dist/program/manifest-nesting.d.cts +13 -0
  184. package/dist/program/manifest-nesting.d.cts.map +1 -0
  185. package/dist/program/manifest-nesting.d.mts +13 -0
  186. package/dist/program/manifest-nesting.d.mts.map +1 -0
  187. package/dist/program/manifest-nesting.mjs +57 -0
  188. package/dist/program/manifest-nesting.mjs.map +1 -0
  189. package/dist/program/result-contract.cjs +55 -0
  190. package/dist/program/result-contract.d.cts +23 -0
  191. package/dist/program/result-contract.d.cts.map +1 -0
  192. package/dist/program/result-contract.d.mts +23 -0
  193. package/dist/program/result-contract.d.mts.map +1 -0
  194. package/dist/program/result-contract.mjs +51 -0
  195. package/dist/program/result-contract.mjs.map +1 -0
  196. package/dist/program/runner-error.cjs +71 -0
  197. package/dist/program/runner-error.d.cts +25 -0
  198. package/dist/program/runner-error.d.cts.map +1 -0
  199. package/dist/program/runner-error.d.mts +25 -0
  200. package/dist/program/runner-error.d.mts.map +1 -0
  201. package/dist/program/runner-error.mjs +72 -0
  202. package/dist/program/runner-error.mjs.map +1 -0
  203. package/dist/program/scoped-afs.cjs +538 -0
  204. package/dist/program/scoped-afs.d.cts +245 -0
  205. package/dist/program/scoped-afs.d.cts.map +1 -0
  206. package/dist/program/scoped-afs.d.mts +245 -0
  207. package/dist/program/scoped-afs.d.mts.map +1 -0
  208. package/dist/program/scoped-afs.mjs +531 -0
  209. package/dist/program/scoped-afs.mjs.map +1 -0
  210. package/dist/program/session-hierarchy.cjs +1 -0
  211. package/dist/program/session-hierarchy.d.cts +2 -0
  212. package/dist/program/session-hierarchy.d.mts +2 -0
  213. package/dist/program/session-hierarchy.mjs +3 -0
  214. package/dist/program/tool-discovery/ash-frontmatter.cjs +83 -0
  215. package/dist/program/tool-discovery/ash-frontmatter.d.cts +21 -0
  216. package/dist/program/tool-discovery/ash-frontmatter.d.cts.map +1 -0
  217. package/dist/program/tool-discovery/ash-frontmatter.d.mts +21 -0
  218. package/dist/program/tool-discovery/ash-frontmatter.d.mts.map +1 -0
  219. package/dist/program/tool-discovery/ash-frontmatter.mjs +84 -0
  220. package/dist/program/tool-discovery/ash-frontmatter.mjs.map +1 -0
  221. package/dist/program/tool-discovery/dot-path-resolver.cjs +60 -0
  222. package/dist/program/tool-discovery/dot-path-resolver.mjs +61 -0
  223. package/dist/program/tool-discovery/dot-path-resolver.mjs.map +1 -0
  224. package/dist/program/tool-discovery/skill-gate.cjs +36 -0
  225. package/dist/program/tool-discovery/skill-gate.d.cts +10 -0
  226. package/dist/program/tool-discovery/skill-gate.d.cts.map +1 -0
  227. package/dist/program/tool-discovery/skill-gate.d.mts +10 -0
  228. package/dist/program/tool-discovery/skill-gate.d.mts.map +1 -0
  229. package/dist/program/tool-discovery/skill-gate.mjs +35 -0
  230. package/dist/program/tool-discovery/skill-gate.mjs.map +1 -0
  231. package/dist/providers/basic/ash/dist/index.cjs +1809 -0
  232. package/dist/providers/basic/ash/dist/index.mjs +1807 -0
  233. package/dist/providers/basic/ash/dist/index.mjs.map +1 -0
  234. package/package.json +67 -0
@@ -0,0 +1,538 @@
1
+ const require_index = require('../providers/basic/ash/dist/index.cjs');
2
+ const require_budget = require('../agent-runners/budget.cjs');
3
+ const require_scratchpad_afs = require('../agent-runners/scratchpad-afs.cjs');
4
+ const require_memory_afs = require('../agent-runners/memory-afs.cjs');
5
+ const require_agent_messages_tools = require('./agent-messages-tools.cjs');
6
+ let _aigne_afs = require("@aigne/afs");
7
+
8
+ //#region src/program/scoped-afs.ts
9
+ /**
10
+ * Chain-depth hard cap. Mirrors `HARD_CAP` in
11
+ * `providers/basic/ash/src/spawn-depth.ts`; kept in sync manually because
12
+ * importing across package boundaries for a constant isn't worth the
13
+ * dependency. Any change there must be reflected here.
14
+ *
15
+ * Semantics match `spawn-depth.ts`: a child whose post-increment depth
16
+ * would be **>= HARD_CAP** is rejected with `CHAIN_DEPTH_EXCEEDED`. With
17
+ * root.chainDepth = 0 this means the deepest reachable child is depth 9;
18
+ * attempting to spawn depth 10 throws.
19
+ */
20
+ const CHAIN_DEPTH_HARD_CAP = 10;
21
+ /** Default ops applied when a manifest tool entry omits `ops`. */
22
+ const DEFAULT_TOOL_OPS = [
23
+ "read",
24
+ "list",
25
+ "exec",
26
+ "query"
27
+ ];
28
+ /**
29
+ * Built-in messaging tool path — every scope surfaces
30
+ * `/proc/messaging/tools/*`
31
+ * so the LLM can call `agent_post_message` / `agent_read_messages` without
32
+ * each manifest having to declare them. See B32 in
33
+ * `providers/basic/ash/src/agent-run.ts`.
34
+ */
35
+ const MESSAGING_TOOL_PATH = require_agent_messages_tools.MESSAGING_TOOLS_GLOB;
36
+ /**
37
+ * Budget mount — per-scope `/.meta/budget/{limit,remaining,consumed}` state
38
+ * files driven by the exec middleware in `attachBudgetMount`. Path contract:
39
+ *
40
+ * - `read("/.meta/budget/limit")` → configured ceiling (tokens)
41
+ * - `read("/.meta/budget/remaining")` → `max(0, limit - consumed)`
42
+ * - `read("/.meta/budget/consumed")` → tokens decremented so far
43
+ * - `write("/.meta/budget/*", ...)` → always `PERMISSION_DENIED`; only
44
+ * the middleware may mutate state (via the internal `BudgetState` ref).
45
+ * - `list("/.meta/budget")` → three-entry listing (above keys).
46
+ *
47
+ * The exec middleware wraps the underlying `afs.exec`:
48
+ * 1. Pre-check `consumed < limit`; otherwise throw `BUDGET_EXHAUSTED`.
49
+ * 2. Call underlying exec.
50
+ * 3. Extract `tokens_used` from the result and serialize the increment
51
+ * against the rootSession mutex so concurrent sub-runs don't race.
52
+ *
53
+ * Child scopes created by `projectForChild` inherit via a new `BudgetState`
54
+ * whose `parent` points back to the caller's state. Each scope's middleware
55
+ * only decrements its *own* `consumed` — propagation to ancestors happens
56
+ * naturally because `child.exec` delegates to `parent.exec` through the
57
+ * prototype chain, so every ancestor's middleware runs once per call and
58
+ * the rootSession mutex keeps the sequence of increments linear.
59
+ */
60
+ const BUDGET_MOUNT_ROOT = "/.meta/budget";
61
+ const BUDGET_KEY_LIMIT = "limit";
62
+ const BUDGET_KEY_REMAINING = "remaining";
63
+ const BUDGET_KEY_CONSUMED = "consumed";
64
+ const BUDGET_KEYS = [
65
+ BUDGET_KEY_LIMIT,
66
+ BUDGET_KEY_REMAINING,
67
+ BUDGET_KEY_CONSUMED
68
+ ];
69
+ /**
70
+ * Process-local mutex map keyed on `rootSession`. Every decrement for a
71
+ * given scope tree serializes against the same promise chain, so two
72
+ * concurrent sub-runs sharing a rootSession cannot double-count or see a
73
+ * mid-update view of `consumed`. Phase 2 will swap the Map for an AFS KV
74
+ * provider so the guarantee holds across processes; the API shape stays.
75
+ */
76
+ const rootBudgetLocks = /* @__PURE__ */ new Map();
77
+ async function withRootBudgetLock(rootSession, fn) {
78
+ const stored = (rootBudgetLocks.get(rootSession) ?? Promise.resolve()).then(fn, fn);
79
+ rootBudgetLocks.set(rootSession, stored);
80
+ try {
81
+ return await stored;
82
+ } finally {
83
+ if (rootBudgetLocks.get(rootSession) === stored) rootBudgetLocks.delete(rootSession);
84
+ }
85
+ }
86
+ function createBudgetState(init) {
87
+ if (!init.rootSession || typeof init.rootSession !== "string") throw new Error(`BUDGET_INVALID: rootSession must be a non-empty string`);
88
+ if (typeof init.limit !== "number" || Number.isNaN(init.limit) || init.limit < 0) throw new Error(`BUDGET_INVALID: limit must be a non-negative number`);
89
+ return {
90
+ rootSession: init.rootSession,
91
+ limit: Math.floor(init.limit),
92
+ consumed: 0
93
+ };
94
+ }
95
+ function budgetRemaining(state) {
96
+ return Math.max(0, state.limit - state.consumed);
97
+ }
98
+ function isBudgetPath(path) {
99
+ return path === BUDGET_MOUNT_ROOT || path.startsWith(`${BUDGET_MOUNT_ROOT}/`);
100
+ }
101
+ function parseBudgetKey(path) {
102
+ if (!path.startsWith(`${BUDGET_MOUNT_ROOT}/`)) return null;
103
+ const key = path.slice(14);
104
+ return BUDGET_KEYS.includes(key) ? key : null;
105
+ }
106
+ function budgetValue(state, key) {
107
+ if (key === BUDGET_KEY_LIMIT) return state.limit;
108
+ if (key === BUDGET_KEY_CONSUMED) return state.consumed;
109
+ return budgetRemaining(state);
110
+ }
111
+ /**
112
+ * Extract `tokens_used` from an exec result. Supports both legacy
113
+ * `data.total_tokens` (the agent-run envelope) and `data._meta.tokens_used`
114
+ * (team/orchestrator aggregate meta). Anything else → 0.
115
+ */
116
+ function extractTokensUsed(result) {
117
+ const data = result?.data;
118
+ if (!data || typeof data !== "object") return 0;
119
+ const candidates = [data.total_tokens, data._meta?.tokens_used];
120
+ for (const value of candidates) if (typeof value === "number" && Number.isFinite(value) && value > 0) return Math.floor(value);
121
+ return 0;
122
+ }
123
+ /**
124
+ * Overlay the budget mount on an AFS root:
125
+ * - `/.meta/budget/{limit,remaining,consumed}` → live reads
126
+ * - `/.meta/budget/*` writes → `PERMISSION_DENIED`
127
+ * - `exec(...)` → pre-check `BUDGET_EXHAUSTED`, then decrement by
128
+ * `tokens_used` under the rootSession mutex.
129
+ *
130
+ * The overlay is non-enumerable (matches the scratch/memory pattern) and
131
+ * transparent for non-budget paths, which fall through via the prototype
132
+ * chain. Every projected child attaches its own overlay backed by its own
133
+ * `BudgetState`, so sibling scopes never see each other's `consumed`.
134
+ */
135
+ function attachBudgetMount(afs, state) {
136
+ const child = Object.create(afs);
137
+ Object.defineProperty(child, "read", {
138
+ value: async (path, options) => {
139
+ const key = parseBudgetKey(path);
140
+ if (key) return {
141
+ success: true,
142
+ data: {
143
+ content: String(budgetValue(state, key)),
144
+ path
145
+ }
146
+ };
147
+ return afs.read.call(afs, path, options);
148
+ },
149
+ enumerable: false,
150
+ writable: false,
151
+ configurable: false
152
+ });
153
+ Object.defineProperty(child, "write", {
154
+ value: async (path, payload, options) => {
155
+ if (isBudgetPath(path)) {
156
+ const err = /* @__PURE__ */ new Error(`PERMISSION_DENIED: ${path} is managed by the budget exec middleware and cannot be written directly`);
157
+ err.code = "PERMISSION_DENIED";
158
+ throw err;
159
+ }
160
+ if (typeof afs.write !== "function") throw new Error(`BUDGET_NO_UNDERLYING_WRITE: afs.write not available for ${path}`);
161
+ return afs.write.call(afs, path, payload, options);
162
+ },
163
+ enumerable: false,
164
+ writable: false,
165
+ configurable: false
166
+ });
167
+ Object.defineProperty(child, "list", {
168
+ value: async (path, options) => {
169
+ if (path === BUDGET_MOUNT_ROOT || path === `${BUDGET_MOUNT_ROOT}/`) return {
170
+ success: true,
171
+ data: { list: BUDGET_KEYS.map((name) => ({
172
+ path: `${BUDGET_MOUNT_ROOT}/${name}`,
173
+ name,
174
+ type: "file"
175
+ })) }
176
+ };
177
+ return afs.list.call(afs, path, options);
178
+ },
179
+ enumerable: false,
180
+ writable: false,
181
+ configurable: false
182
+ });
183
+ Object.defineProperty(child, "exec", {
184
+ value: async (path, args, options) => {
185
+ if (state.consumed >= state.limit) {
186
+ const err = /* @__PURE__ */ new Error(`BUDGET_EXHAUSTED: scope budget exhausted (path=${path}, limit=${state.limit}, consumed=${state.consumed})`);
187
+ err.code = "BUDGET_EXHAUSTED";
188
+ throw err;
189
+ }
190
+ const result = await afs.exec.call(afs, path, args, options);
191
+ const used = extractTokensUsed(result);
192
+ if (used > 0) await withRootBudgetLock(state.rootSession, () => {
193
+ state.consumed += used;
194
+ });
195
+ return result;
196
+ },
197
+ enumerable: false,
198
+ writable: false,
199
+ configurable: false
200
+ });
201
+ return child;
202
+ }
203
+ /**
204
+ * Resolve a child scope's budget. The child's effective limit is the
205
+ * result of `resolveBudget({manifest, parentRemaining})`; consumed starts
206
+ * at 0. Ancestor updates are handled by the middleware chain itself
207
+ * (each scope's middleware runs once per call via the prototype chain),
208
+ * so the child's `BudgetState` is independent from the parent's.
209
+ *
210
+ * Returns `undefined` when the parent has no active budget — zero-overhead
211
+ * path for legacy callers that never opt in.
212
+ *
213
+ * Inheritance rules (P5 deferred nit documented here for clarity):
214
+ *
215
+ * - Parent has budget, child manifest declares one → `resolveBudget`
216
+ * clamps `min(childBudget.totalTokens, parentRemaining)`.
217
+ * - Parent has budget, child manifest omits budget → `resolveBudget` uses
218
+ * `DEFAULT_TOTAL_TOKENS` (80k) then clamps to `parentRemaining`. Net
219
+ * effect: an undeclared child never exceeds the parent's remaining
220
+ * window, which is the conservative default.
221
+ * - Parent has no budget → child is unbudgeted too; the whole
222
+ * `/.meta/budget/*` overlay is skipped (zero-overhead legacy path).
223
+ *
224
+ * The clamp is only a ceiling. Actual spend is still accounted per call
225
+ * via the exec middleware (`afs.exec` → decrement under `rootSession`
226
+ * mutex), so siblings can't double-spend the parent's remaining window.
227
+ */
228
+ function deriveChildBudgetState(parent, childBudget) {
229
+ if (!parent) return void 0;
230
+ const resolved = require_budget.resolveBudget({
231
+ manifest: childBudget,
232
+ parentRemaining: budgetRemaining(parent)
233
+ });
234
+ return createBudgetState({
235
+ rootSession: parent.rootSession,
236
+ limit: resolved.totalTokens
237
+ });
238
+ }
239
+ function assertSession(session) {
240
+ if (session === void 0) return;
241
+ if (typeof session !== "string" || session.length === 0) throw new Error(`SCOPE_INVALID_INPUT: session must be a non-empty string`);
242
+ if (session.includes("/") || session.includes("\\")) throw new Error(`SCOPE_INVALID_INPUT: session must not contain path separators`);
243
+ if (session.includes("\0")) throw new Error(`SCOPE_INVALID_INPUT: session must not contain null bytes`);
244
+ }
245
+ function assertMemberPath(memberPath) {
246
+ if (typeof memberPath !== "string" || memberPath.length === 0) throw new Error(`SCOPE_INVALID_MEMBER: memberPath must be a non-empty string`);
247
+ if (memberPath.includes("\0")) throw new Error(`SCOPE_INVALID_MEMBER: memberPath must not contain null bytes`);
248
+ if (memberPath.split("/").some((s) => s === "..")) throw new Error(`SCOPE_INVALID_MEMBER: memberPath must not traverse parent directories`);
249
+ }
250
+ function assertChildManifest(manifest) {
251
+ if (!manifest || typeof manifest !== "object") throw new Error(`SCOPE_INVALID_INPUT: childManifest is required`);
252
+ }
253
+ /**
254
+ * Normalize a manifest's `tools` field into `ToolEntry[]`, rejecting shapes
255
+ * that would let a dispatcher smuggle traversal or typo past intersection:
256
+ * - non-string / empty path → TOOL_PATH_INVALID
257
+ * - path containing `..` or `\0` → TOOL_PATH_INVALID
258
+ * - ops must be a non-empty string[] when provided
259
+ *
260
+ * The Phase 1 contract: one call site (projectForChild) owns normalization;
261
+ * older runner-local normalize helpers delegate here.
262
+ */
263
+ function normalizeManifestTools(manifest) {
264
+ const raw = manifest.tools ?? [];
265
+ const result = [];
266
+ raw.forEach((t, idx) => {
267
+ const path = typeof t === "string" ? t : t?.path;
268
+ if (typeof path !== "string" || path.length === 0) throw new Error(`TOOL_PATH_INVALID: manifest.tools[${idx}].path must be a non-empty string`);
269
+ if (path.includes("\0")) throw new Error(`TOOL_PATH_INVALID: manifest.tools[${idx}].path must not contain null bytes`);
270
+ if (path.includes("..")) throw new Error(`TOOL_PATH_INVALID: manifest.tools[${idx}].path must not contain ".."`);
271
+ if (typeof t === "string") {
272
+ result.push({
273
+ path,
274
+ ops: [...DEFAULT_TOOL_OPS]
275
+ });
276
+ return;
277
+ }
278
+ const ops = t.ops ?? [...DEFAULT_TOOL_OPS];
279
+ if (!Array.isArray(ops) || ops.length === 0 || ops.some((op) => typeof op !== "string")) throw new Error(`TOOL_PATH_INVALID: manifest.tools[${idx}].ops must be a non-empty string[]`);
280
+ const entry = {
281
+ path,
282
+ ops: require_index.withQueryPairing(ops)
283
+ };
284
+ if (t.maxDepth != null) entry.maxDepth = t.maxDepth;
285
+ result.push(entry);
286
+ });
287
+ return result;
288
+ }
289
+ /**
290
+ * Phase 5 canonical session accessor — runners must read the effective
291
+ * session id from `ctx.afs.scope.session` rather than from the legacy
292
+ * `context.session` field. This helper keeps back-compat while the four
293
+ * runners are swapped: if the AFS already carries a scope, return
294
+ * `scope.session`; otherwise fall back to the deprecated `fallback`
295
+ * argument. P6 removes the fallback path once `RunnerContext.session` is
296
+ * deleted.
297
+ */
298
+ function runnerSession(afs, fallback) {
299
+ return afs.scope?.session ?? fallback;
300
+ }
301
+ /**
302
+ * Phase 5 canonical parent-session accessor. Mirrors `runnerSession` but
303
+ * surfaces the parent's session id so runners can tag sub-runs without
304
+ * consulting the legacy `context.parentSession` field. Returns undefined
305
+ * for root scopes (no parent) — callers must treat undefined as "root".
306
+ */
307
+ function runnerParentSession(afs, fallback) {
308
+ return afs.scope?.parentSession ?? fallback;
309
+ }
310
+ /**
311
+ * Shared session-resolution ladder for every runner. Reads session and
312
+ * parentSession from scope first (legacy context fields only as fallback
313
+ * until P6) and, when both are set, derives the child session id.
314
+ *
315
+ * Collapses the ai / ash / team / orchestrator entry blocks into one
316
+ * place — any adjustment to the derivation rule now has a single owner.
317
+ */
318
+ function resolveChildSession(afs, ctx, deriveChildSession) {
319
+ const parentSession = runnerParentSession(afs, ctx.parentSession);
320
+ let session = runnerSession(afs, ctx.session);
321
+ if (parentSession && session) session = deriveChildSession(parentSession);
322
+ return {
323
+ session,
324
+ parentSession
325
+ };
326
+ }
327
+ /**
328
+ * Lift a raw `AFSRoot` into a root-level `AgentScope`. Root scopes are
329
+ * unbounded by construction — `scope.allowedTools` is the caller's own
330
+ * manifest tools (or fully permissive when omitted), and `chainDepth` is 0.
331
+ *
332
+ * Top-level runners (agent-run action handler, test harnesses) use this to
333
+ * bootstrap the scope chain; downstream runners never construct a root
334
+ * scope themselves. Omit `manifestTools` (or pass `[]`) to keep the root
335
+ * fully permissive — useful for tests that don't declare tools.
336
+ */
337
+ function rootAgentScope(afs, opts) {
338
+ assertSession(opts.session);
339
+ const allowedTools = opts.manifestTools && opts.manifestTools.length > 0 ? opts.manifestTools : [{
340
+ path: "/**",
341
+ ops: [
342
+ "read",
343
+ "list",
344
+ "exec",
345
+ "write",
346
+ "search",
347
+ "query"
348
+ ]
349
+ }];
350
+ let withBudget = afs;
351
+ let budgetState;
352
+ if (opts.budget) {
353
+ const resolved = require_budget.resolveBudget({ manifest: opts.budget });
354
+ budgetState = createBudgetState({
355
+ rootSession: opts.session,
356
+ limit: resolved.totalTokens
357
+ });
358
+ withBudget = attachBudgetMount(afs, budgetState);
359
+ }
360
+ return attachScope(withBudget, {
361
+ session: opts.session,
362
+ rootSession: opts.session,
363
+ chainDepth: 0,
364
+ allowedPaths: allowedTools.map((t) => t.path),
365
+ allowedTools,
366
+ budget: budgetState,
367
+ memoryDomain: opts.memoryDomain
368
+ });
369
+ }
370
+ /**
371
+ * Top-level runner bootstrap — if the caller's AFS is already a scope, use
372
+ * it verbatim; otherwise synthesize a root scope and attach a fresh
373
+ * `/scratch/*` mount. Team and orchestrator runners call this so hook
374
+ * events and `state.yml` writes land in the scope-local scratch rather
375
+ * than the legacy `/modules/memory/runs/` tree.
376
+ *
377
+ * Pass `manifestTools` + `session` to drive the synthetic root scope's
378
+ * descriptor; the caller's own manifest is typically the source, and
379
+ * `scratchRetention` follows `manifest.scratch` (run → session default).
380
+ */
381
+ function ensureScopeWithMounts(afs, opts) {
382
+ if (afs.scope) return afs;
383
+ return require_scratchpad_afs.attachScratchMount(rootAgentScope(afs, {
384
+ session: opts.session,
385
+ manifestTools: opts.manifestTools,
386
+ budget: opts.budget,
387
+ memoryDomain: require_memory_afs.extractManifestDomain(opts.memory)
388
+ }), opts.scratchProvider ?? require_scratchpad_afs.createScratchProvider({
389
+ session: sanitizeSessionForScratch(opts.session),
390
+ retention: opts.scratchRetention ?? "session"
391
+ }));
392
+ }
393
+ /**
394
+ * Resolve the `AgentScope` a parent runner projects children from.
395
+ *
396
+ * Phase 6 — if the caller already handed us a scoped AFS (via
397
+ * `projectForChild` / `ensureScopeWithMounts`), reuse it: its `allowedTools`
398
+ * is already the post-intersection view. Otherwise synthesize a root scope
399
+ * from the caller's `manifest.tools`, normalized via `normalizeManifestTools`
400
+ * for a single source of truth. Callers that want a tighter inherited
401
+ * set must hand over a scoped AFS built via `projectForChild` or
402
+ * `ensureScopeWithMounts`.
403
+ */
404
+ function resolveParentAgentScope(opts) {
405
+ if (opts.afs.scope) return opts.afs;
406
+ const manifestTools = normalizeManifestTools(opts.manifest);
407
+ return rootAgentScope(opts.afs, {
408
+ session: opts.session ?? "root",
409
+ manifestTools: manifestTools.length > 0 ? manifestTools : void 0
410
+ });
411
+ }
412
+ function attachScope(afs, scope) {
413
+ const child = Object.create(afs);
414
+ Object.defineProperty(child, "scope", {
415
+ value: scope,
416
+ enumerable: true,
417
+ writable: false,
418
+ configurable: false
419
+ });
420
+ return child;
421
+ }
422
+ /**
423
+ * Narrow down `parent` for a child agent:
424
+ * - path projection via existing `projectSubAgent` (rewrite + readonly)
425
+ * - tool ACL intersection via existing `intersectTools` (paths + ops)
426
+ * - scope descriptor: session / rootSession / chainDepth+1 / allowedPaths
427
+ *
428
+ * If the parent has a non-empty `scope.allowedTools` and the child declares
429
+ * a non-empty `manifest.tools` that doesn't overlap (intersection empty),
430
+ * we throw `TOOL_INTERSECTION_EMPTY` — an empty intersection means the
431
+ * dispatcher has asked for an unreachable child scope, which is a hard
432
+ * error rather than a silently-permissive default.
433
+ *
434
+ * See design.md §5 for the full six-step mount composition; P2–P5 add
435
+ * scratch / memory / budget / session arms to the same function.
436
+ */
437
+ function projectForChild(parent, options) {
438
+ assertChildManifest(options.childManifest);
439
+ assertMemberPath(options.memberPath);
440
+ assertSession(options.session);
441
+ if (!parent || typeof parent !== "object" || !parent.scope) throw new Error(`SCOPE_INVALID_INPUT: parent scope is required`);
442
+ const nextDepth = parent.scope.chainDepth + 1;
443
+ if (nextDepth >= CHAIN_DEPTH_HARD_CAP) throw new Error(`CHAIN_DEPTH_EXCEEDED: chainDepth ${nextDepth} reaches hard cap ${CHAIN_DEPTH_HARD_CAP}`);
444
+ const childDeclaredTools = normalizeManifestTools(options.childManifest);
445
+ const parentAllowed = parent.scope.allowedTools;
446
+ const intersected = childDeclaredTools.length === 0 ? [] : require_index.intersectTools([...parentAllowed], childDeclaredTools);
447
+ if (childDeclaredTools.length > 0 && intersected.length === 0) throw new Error(`TOOL_INTERSECTION_EMPTY: child manifest declares tools that don't intersect parent scope`);
448
+ const withMessaging = ensureMessagingTool(intersected);
449
+ const projectedAfs = (0, _aigne_afs.projectSubAgent)(parent, {
450
+ memberPath: options.memberPath,
451
+ mode: "readonly"
452
+ });
453
+ const childSession = options.session ?? deriveDefaultChildSession(parent.scope.session, options.memberPath);
454
+ const withScratch = require_scratchpad_afs.attachScratchMount(projectedAfs, require_scratchpad_afs.createScratchProvider({
455
+ session: sanitizeSessionForScratch(childSession),
456
+ retention: options.childManifest.scratch ? "session" : "run"
457
+ }));
458
+ const memoryDomain = isMemoryEnabled(options.childManifest.memory) ? require_memory_afs.resolveMemoryDomain({
459
+ manifestMemory: options.childManifest.memory,
460
+ parentDomain: parent.scope.memoryDomain,
461
+ memberPath: options.memberPath
462
+ }) : void 0;
463
+ const inheritsParentMemoryMount = memoryDomain !== void 0 && memoryDomain === parent.scope.memoryDomain;
464
+ const withMemory = memoryDomain && !inheritsParentMemoryMount ? require_memory_afs.attachMemoryMount(withScratch, require_memory_afs.createMemoryProvider({
465
+ domain: memoryDomain,
466
+ storage: require_memory_afs.buildMemoryStorageForAfs(parent),
467
+ ...require_memory_afs.buildMemoryIndexOptsForAfs(parent)
468
+ })) : withScratch;
469
+ const finalTools = memoryDomain ? ensureMemoryTool(withMessaging) : withMessaging;
470
+ const childBudget = deriveChildBudgetState(parent.scope.budget, options.childManifest.budget);
471
+ return attachScope(childBudget ? attachBudgetMount(withMemory, childBudget) : withMemory, {
472
+ session: childSession,
473
+ parentSession: parent.scope.session,
474
+ rootSession: parent.scope.rootSession,
475
+ chainDepth: nextDepth,
476
+ allowedPaths: finalTools.map((t) => t.path),
477
+ allowedTools: finalTools,
478
+ memoryDomain,
479
+ budget: childBudget
480
+ });
481
+ }
482
+ /** `memory: true` | `memory: { … }` both count; `false`/`undefined` do not. */
483
+ function isMemoryEnabled(value) {
484
+ return value === true || typeof value === "object" && value !== null;
485
+ }
486
+ const MEMORY_TOOL_PATH = "/memory/**";
487
+ function ensureMemoryTool(tools) {
488
+ if (tools.some((t) => t.path === MEMORY_TOOL_PATH || t.path === "/memory")) return tools;
489
+ return [...tools, {
490
+ path: MEMORY_TOOL_PATH,
491
+ ops: [
492
+ "read",
493
+ "list",
494
+ "exec"
495
+ ]
496
+ }];
497
+ }
498
+ /**
499
+ * The scope descriptor's `session` may come from callers that tolerate path
500
+ * segments (e.g. `.../planner-0`). The scratch provider rejects separators
501
+ * and dots, so we collapse the caller-supplied id down to a bare token
502
+ * before handing it over.
503
+ */
504
+ function sanitizeSessionForScratch(session) {
505
+ const trimmed = (session ?? "").replace(/\/+$/, "");
506
+ const cleaned = trimmed.slice(trimmed.lastIndexOf("/") + 1).replace(/\.\./g, "").replace(/\0/g, "");
507
+ return cleaned.length > 0 ? cleaned : "scope";
508
+ }
509
+ function ensureMessagingTool(tools) {
510
+ if (tools.some((t) => t.path === MESSAGING_TOOL_PATH || t.path === require_agent_messages_tools.MESSAGING_TOOLS_ROOT)) return tools;
511
+ return [...tools, {
512
+ path: MESSAGING_TOOL_PATH,
513
+ ops: ["exec"]
514
+ }];
515
+ }
516
+ function deriveDefaultChildSession(parentSession, memberPath) {
517
+ return `${parentSession}.${memberPath.split("/").filter(Boolean).pop() ?? "child"}.${Math.random().toString(36).slice(2, 8)}`;
518
+ }
519
+ /**
520
+ * Phase 2 target — serialize a scope for cross-process hand-off (MCP
521
+ * sandbox worker, code-agent runner, …). Always throws in Phase 0/1 so
522
+ * no caller is tempted to persist a partial descriptor before the sandbox
523
+ * boundary exists.
524
+ */
525
+ function toJSON(_scope) {
526
+ throw new Error("AGENT_SCOPE_TOJSON_PHASE_2: scope serialization lands with the MCP sandbox (Phase 2)");
527
+ }
528
+
529
+ //#endregion
530
+ exports.CHAIN_DEPTH_HARD_CAP = CHAIN_DEPTH_HARD_CAP;
531
+ exports.ensureScopeWithMounts = ensureScopeWithMounts;
532
+ exports.normalizeManifestTools = normalizeManifestTools;
533
+ exports.projectForChild = projectForChild;
534
+ exports.resolveChildSession = resolveChildSession;
535
+ exports.resolveParentAgentScope = resolveParentAgentScope;
536
+ exports.rootAgentScope = rootAgentScope;
537
+ exports.runnerSession = runnerSession;
538
+ exports.toJSON = toJSON;