@aisy/core 0.1.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 (270) hide show
  1. package/LICENSE +202 -0
  2. package/dist/agent-loop/index.d.ts +4 -0
  3. package/dist/agent-loop/index.d.ts.map +1 -0
  4. package/dist/agent-loop/index.js +352 -0
  5. package/dist/agent-loop/index.js.map +1 -0
  6. package/dist/agent-loop/types.d.ts +183 -0
  7. package/dist/agent-loop/types.d.ts.map +1 -0
  8. package/dist/agent-loop/types.js +3 -0
  9. package/dist/agent-loop/types.js.map +1 -0
  10. package/dist/bin/aisy.d.ts +3 -0
  11. package/dist/bin/aisy.d.ts.map +1 -0
  12. package/dist/bin/aisy.js +14 -0
  13. package/dist/bin/aisy.js.map +1 -0
  14. package/dist/cli/index.d.ts +17 -0
  15. package/dist/cli/index.d.ts.map +1 -0
  16. package/dist/cli/index.js +114 -0
  17. package/dist/cli/index.js.map +1 -0
  18. package/dist/context-engine/index.d.ts +4 -0
  19. package/dist/context-engine/index.d.ts.map +1 -0
  20. package/dist/context-engine/index.js +126 -0
  21. package/dist/context-engine/index.js.map +1 -0
  22. package/dist/context-engine/types.d.ts +54 -0
  23. package/dist/context-engine/types.d.ts.map +1 -0
  24. package/dist/context-engine/types.js +4 -0
  25. package/dist/context-engine/types.js.map +1 -0
  26. package/dist/eval/index.d.ts +20 -0
  27. package/dist/eval/index.d.ts.map +1 -0
  28. package/dist/eval/index.js +128 -0
  29. package/dist/eval/index.js.map +1 -0
  30. package/dist/eval/types.d.ts +62 -0
  31. package/dist/eval/types.d.ts.map +1 -0
  32. package/dist/eval/types.js +17 -0
  33. package/dist/eval/types.js.map +1 -0
  34. package/dist/gateway/index.d.ts +5 -0
  35. package/dist/gateway/index.d.ts.map +1 -0
  36. package/dist/gateway/index.js +288 -0
  37. package/dist/gateway/index.js.map +1 -0
  38. package/dist/gateway/types.d.ts +194 -0
  39. package/dist/gateway/types.d.ts.map +1 -0
  40. package/dist/gateway/types.js +94 -0
  41. package/dist/gateway/types.js.map +1 -0
  42. package/dist/goals/index.d.ts +11 -0
  43. package/dist/goals/index.d.ts.map +1 -0
  44. package/dist/goals/index.js +21 -0
  45. package/dist/goals/index.js.map +1 -0
  46. package/dist/goals/types.d.ts +47 -0
  47. package/dist/goals/types.d.ts.map +1 -0
  48. package/dist/goals/types.js +5 -0
  49. package/dist/goals/types.js.map +1 -0
  50. package/dist/index.d.ts +56 -0
  51. package/dist/index.d.ts.map +1 -0
  52. package/dist/index.js +50 -0
  53. package/dist/index.js.map +1 -0
  54. package/dist/mcp/index.d.ts +5 -0
  55. package/dist/mcp/index.d.ts.map +1 -0
  56. package/dist/mcp/index.js +215 -0
  57. package/dist/mcp/index.js.map +1 -0
  58. package/dist/mcp/types.d.ts +148 -0
  59. package/dist/mcp/types.d.ts.map +1 -0
  60. package/dist/mcp/types.js +4 -0
  61. package/dist/mcp/types.js.map +1 -0
  62. package/dist/memory/index.d.ts +6 -0
  63. package/dist/memory/index.d.ts.map +1 -0
  64. package/dist/memory/index.js +419 -0
  65. package/dist/memory/index.js.map +1 -0
  66. package/dist/memory/types.d.ts +131 -0
  67. package/dist/memory/types.d.ts.map +1 -0
  68. package/dist/memory/types.js +33 -0
  69. package/dist/memory/types.js.map +1 -0
  70. package/dist/nightly/index.d.ts +4 -0
  71. package/dist/nightly/index.d.ts.map +1 -0
  72. package/dist/nightly/index.js +470 -0
  73. package/dist/nightly/index.js.map +1 -0
  74. package/dist/nightly/types.d.ts +326 -0
  75. package/dist/nightly/types.d.ts.map +1 -0
  76. package/dist/nightly/types.js +3 -0
  77. package/dist/nightly/types.js.map +1 -0
  78. package/dist/observability/index.d.ts +11 -0
  79. package/dist/observability/index.d.ts.map +1 -0
  80. package/dist/observability/index.js +396 -0
  81. package/dist/observability/index.js.map +1 -0
  82. package/dist/observability/types.d.ts +139 -0
  83. package/dist/observability/types.d.ts.map +1 -0
  84. package/dist/observability/types.js +4 -0
  85. package/dist/observability/types.js.map +1 -0
  86. package/dist/onboarding/index.d.ts +16 -0
  87. package/dist/onboarding/index.d.ts.map +1 -0
  88. package/dist/onboarding/index.js +787 -0
  89. package/dist/onboarding/index.js.map +1 -0
  90. package/dist/onboarding/interactive.d.ts +23 -0
  91. package/dist/onboarding/interactive.d.ts.map +1 -0
  92. package/dist/onboarding/interactive.js +45 -0
  93. package/dist/onboarding/interactive.js.map +1 -0
  94. package/dist/onboarding/types.d.ts +388 -0
  95. package/dist/onboarding/types.d.ts.map +1 -0
  96. package/dist/onboarding/types.js +35 -0
  97. package/dist/onboarding/types.js.map +1 -0
  98. package/dist/orchestration/index.d.ts +8 -0
  99. package/dist/orchestration/index.d.ts.map +1 -0
  100. package/dist/orchestration/index.js +706 -0
  101. package/dist/orchestration/index.js.map +1 -0
  102. package/dist/orchestration/types.d.ts +391 -0
  103. package/dist/orchestration/types.d.ts.map +1 -0
  104. package/dist/orchestration/types.js +30 -0
  105. package/dist/orchestration/types.js.map +1 -0
  106. package/dist/personality/index.d.ts +65 -0
  107. package/dist/personality/index.d.ts.map +1 -0
  108. package/dist/personality/index.js +339 -0
  109. package/dist/personality/index.js.map +1 -0
  110. package/dist/personality/types.d.ts +103 -0
  111. package/dist/personality/types.d.ts.map +1 -0
  112. package/dist/personality/types.js +15 -0
  113. package/dist/personality/types.js.map +1 -0
  114. package/dist/provider/index.d.ts +4 -0
  115. package/dist/provider/index.d.ts.map +1 -0
  116. package/dist/provider/index.js +236 -0
  117. package/dist/provider/index.js.map +1 -0
  118. package/dist/provider/types.d.ts +180 -0
  119. package/dist/provider/types.d.ts.map +1 -0
  120. package/dist/provider/types.js +4 -0
  121. package/dist/provider/types.js.map +1 -0
  122. package/dist/runtime/agent-cards.d.ts +14 -0
  123. package/dist/runtime/agent-cards.d.ts.map +1 -0
  124. package/dist/runtime/agent-cards.js +90 -0
  125. package/dist/runtime/agent-cards.js.map +1 -0
  126. package/dist/runtime/agent-runner.d.ts +30 -0
  127. package/dist/runtime/agent-runner.d.ts.map +1 -0
  128. package/dist/runtime/agent-runner.js +37 -0
  129. package/dist/runtime/agent-runner.js.map +1 -0
  130. package/dist/runtime/budget.d.ts +15 -0
  131. package/dist/runtime/budget.d.ts.map +1 -0
  132. package/dist/runtime/budget.js +24 -0
  133. package/dist/runtime/budget.js.map +1 -0
  134. package/dist/runtime/delegation-driver.d.ts +11 -0
  135. package/dist/runtime/delegation-driver.d.ts.map +1 -0
  136. package/dist/runtime/delegation-driver.js +132 -0
  137. package/dist/runtime/delegation-driver.js.map +1 -0
  138. package/dist/runtime/exact-cache.d.ts +10 -0
  139. package/dist/runtime/exact-cache.d.ts.map +1 -0
  140. package/dist/runtime/exact-cache.js +30 -0
  141. package/dist/runtime/exact-cache.js.map +1 -0
  142. package/dist/runtime/execute-tool.d.ts +29 -0
  143. package/dist/runtime/execute-tool.d.ts.map +1 -0
  144. package/dist/runtime/execute-tool.js +80 -0
  145. package/dist/runtime/execute-tool.js.map +1 -0
  146. package/dist/runtime/guardian.d.ts +9 -0
  147. package/dist/runtime/guardian.d.ts.map +1 -0
  148. package/dist/runtime/guardian.js +41 -0
  149. package/dist/runtime/guardian.js.map +1 -0
  150. package/dist/runtime/hook-gate.d.ts +17 -0
  151. package/dist/runtime/hook-gate.d.ts.map +1 -0
  152. package/dist/runtime/hook-gate.js +56 -0
  153. package/dist/runtime/hook-gate.js.map +1 -0
  154. package/dist/runtime/memory-adapter.d.ts +6 -0
  155. package/dist/runtime/memory-adapter.d.ts.map +1 -0
  156. package/dist/runtime/memory-adapter.js +38 -0
  157. package/dist/runtime/memory-adapter.js.map +1 -0
  158. package/dist/runtime/nightly-adapters.d.ts +48 -0
  159. package/dist/runtime/nightly-adapters.d.ts.map +1 -0
  160. package/dist/runtime/nightly-adapters.js +139 -0
  161. package/dist/runtime/nightly-adapters.js.map +1 -0
  162. package/dist/runtime/nightly-generator.d.ts +10 -0
  163. package/dist/runtime/nightly-generator.d.ts.map +1 -0
  164. package/dist/runtime/nightly-generator.js +335 -0
  165. package/dist/runtime/nightly-generator.js.map +1 -0
  166. package/dist/runtime/onboarding-node.d.ts +6 -0
  167. package/dist/runtime/onboarding-node.d.ts.map +1 -0
  168. package/dist/runtime/onboarding-node.js +356 -0
  169. package/dist/runtime/onboarding-node.js.map +1 -0
  170. package/dist/runtime/provider-anthropic.d.ts +43 -0
  171. package/dist/runtime/provider-anthropic.d.ts.map +1 -0
  172. package/dist/runtime/provider-anthropic.js +148 -0
  173. package/dist/runtime/provider-anthropic.js.map +1 -0
  174. package/dist/runtime/provider-cli.d.ts +18 -0
  175. package/dist/runtime/provider-cli.d.ts.map +1 -0
  176. package/dist/runtime/provider-cli.js +73 -0
  177. package/dist/runtime/provider-cli.js.map +1 -0
  178. package/dist/runtime/provider-openai.d.ts +30 -0
  179. package/dist/runtime/provider-openai.d.ts.map +1 -0
  180. package/dist/runtime/provider-openai.js +114 -0
  181. package/dist/runtime/provider-openai.js.map +1 -0
  182. package/dist/runtime/providers.d.ts +43 -0
  183. package/dist/runtime/providers.d.ts.map +1 -0
  184. package/dist/runtime/providers.js +72 -0
  185. package/dist/runtime/providers.js.map +1 -0
  186. package/dist/runtime/sandbox-bash.d.ts +21 -0
  187. package/dist/runtime/sandbox-bash.d.ts.map +1 -0
  188. package/dist/runtime/sandbox-bash.js +51 -0
  189. package/dist/runtime/sandbox-bash.js.map +1 -0
  190. package/dist/runtime/scoped-tool-executor.d.ts +10 -0
  191. package/dist/runtime/scoped-tool-executor.d.ts.map +1 -0
  192. package/dist/runtime/scoped-tool-executor.js +30 -0
  193. package/dist/runtime/scoped-tool-executor.js.map +1 -0
  194. package/dist/runtime/session-log.d.ts +6 -0
  195. package/dist/runtime/session-log.d.ts.map +1 -0
  196. package/dist/runtime/session-log.js +54 -0
  197. package/dist/runtime/session-log.js.map +1 -0
  198. package/dist/runtime/settings.d.ts +24 -0
  199. package/dist/runtime/settings.d.ts.map +1 -0
  200. package/dist/runtime/settings.js +29 -0
  201. package/dist/runtime/settings.js.map +1 -0
  202. package/dist/runtime/spawn-plan.d.ts +13 -0
  203. package/dist/runtime/spawn-plan.d.ts.map +1 -0
  204. package/dist/runtime/spawn-plan.js +107 -0
  205. package/dist/runtime/spawn-plan.js.map +1 -0
  206. package/dist/runtime/spend.d.ts +41 -0
  207. package/dist/runtime/spend.d.ts.map +1 -0
  208. package/dist/runtime/spend.js +0 -0
  209. package/dist/runtime/spend.js.map +1 -0
  210. package/dist/runtime/sub-agent-runner.d.ts +19 -0
  211. package/dist/runtime/sub-agent-runner.d.ts.map +1 -0
  212. package/dist/runtime/sub-agent-runner.js +47 -0
  213. package/dist/runtime/sub-agent-runner.js.map +1 -0
  214. package/dist/safety/grants.d.ts +7 -0
  215. package/dist/safety/grants.d.ts.map +1 -0
  216. package/dist/safety/grants.js +53 -0
  217. package/dist/safety/grants.js.map +1 -0
  218. package/dist/safety/index.d.ts +72 -0
  219. package/dist/safety/index.d.ts.map +1 -0
  220. package/dist/safety/index.js +464 -0
  221. package/dist/safety/index.js.map +1 -0
  222. package/dist/safety/types.d.ts +254 -0
  223. package/dist/safety/types.d.ts.map +1 -0
  224. package/dist/safety/types.js +3 -0
  225. package/dist/safety/types.js.map +1 -0
  226. package/dist/skills/index.d.ts +4 -0
  227. package/dist/skills/index.d.ts.map +1 -0
  228. package/dist/skills/index.js +463 -0
  229. package/dist/skills/index.js.map +1 -0
  230. package/dist/skills/types.d.ts +177 -0
  231. package/dist/skills/types.d.ts.map +1 -0
  232. package/dist/skills/types.js +3 -0
  233. package/dist/skills/types.js.map +1 -0
  234. package/dist/testing/clock.d.ts +8 -0
  235. package/dist/testing/clock.d.ts.map +1 -0
  236. package/dist/testing/clock.js +13 -0
  237. package/dist/testing/clock.js.map +1 -0
  238. package/dist/testing/effect-verifier.d.ts +15 -0
  239. package/dist/testing/effect-verifier.d.ts.map +1 -0
  240. package/dist/testing/effect-verifier.js +27 -0
  241. package/dist/testing/effect-verifier.js.map +1 -0
  242. package/dist/testing/index.d.ts +5 -0
  243. package/dist/testing/index.d.ts.map +1 -0
  244. package/dist/testing/index.js +5 -0
  245. package/dist/testing/index.js.map +1 -0
  246. package/dist/testing/provider-fake.d.ts +14 -0
  247. package/dist/testing/provider-fake.d.ts.map +1 -0
  248. package/dist/testing/provider-fake.js +18 -0
  249. package/dist/testing/provider-fake.js.map +1 -0
  250. package/dist/testing/sandbox-stub.d.ts +15 -0
  251. package/dist/testing/sandbox-stub.d.ts.map +1 -0
  252. package/dist/testing/sandbox-stub.js +15 -0
  253. package/dist/testing/sandbox-stub.js.map +1 -0
  254. package/dist/tools/index.d.ts +11 -0
  255. package/dist/tools/index.d.ts.map +1 -0
  256. package/dist/tools/index.js +0 -0
  257. package/dist/tools/index.js.map +1 -0
  258. package/dist/tools/types.d.ts +138 -0
  259. package/dist/tools/types.d.ts.map +1 -0
  260. package/dist/tools/types.js +4 -0
  261. package/dist/tools/types.js.map +1 -0
  262. package/dist/triggers/index.d.ts +4 -0
  263. package/dist/triggers/index.d.ts.map +1 -0
  264. package/dist/triggers/index.js +187 -0
  265. package/dist/triggers/index.js.map +1 -0
  266. package/dist/triggers/types.d.ts +74 -0
  267. package/dist/triggers/types.d.ts.map +1 -0
  268. package/dist/triggers/types.js +5 -0
  269. package/dist/triggers/types.js.map +1 -0
  270. package/package.json +36 -0
@@ -0,0 +1,15 @@
1
+ export interface BudgetTracker {
2
+ /** Configured cap in USD; 0 (or absent) means unlimited. */
3
+ capFor(agentId: string): number;
4
+ /** Live spend for the agent (from the ledger). */
5
+ spentFor(agentId: string): number;
6
+ /** Remaining USD; Infinity when uncapped, clamped to 0 at/over the cap. */
7
+ remainingFor(agentId: string): number;
8
+ /** True iff a cap is set and spend has reached it. */
9
+ over(agentId: string): boolean;
10
+ }
11
+ export declare function makeBudgetTracker(deps: {
12
+ caps: Record<string, number>;
13
+ spent: (agentId: string) => number;
14
+ }): BudgetTracker;
15
+ //# sourceMappingURL=budget.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"budget.d.ts","sourceRoot":"","sources":["../../src/runtime/budget.ts"],"names":[],"mappings":"AASA,MAAM,WAAW,aAAa;IAC5B,4DAA4D;IAC5D,MAAM,CAAC,OAAO,EAAE,MAAM,GAAG,MAAM,CAAA;IAC/B,kDAAkD;IAClD,QAAQ,CAAC,OAAO,EAAE,MAAM,GAAG,MAAM,CAAA;IACjC,2EAA2E;IAC3E,YAAY,CAAC,OAAO,EAAE,MAAM,GAAG,MAAM,CAAA;IACrC,sDAAsD;IACtD,IAAI,CAAC,OAAO,EAAE,MAAM,GAAG,OAAO,CAAA;CAC/B;AAED,wBAAgB,iBAAiB,CAAC,IAAI,EAAE;IACtC,IAAI,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAA;IAC5B,KAAK,EAAE,CAAC,OAAO,EAAE,MAAM,KAAK,MAAM,CAAA;CACnC,GAAG,aAAa,CAchB"}
@@ -0,0 +1,24 @@
1
+ // Per-agent budget tracker (runtime, ADR-0050 Phase 3).
2
+ //
3
+ // Caps come from config (providers.json agents[*].budgetUsd + the main agent);
4
+ // `spent` is read live from the spend ledger (byAgent), so the tracker holds no
5
+ // state of its own. The transport gates a turn when `budgetEnabled` is set and
6
+ // the agent is over its cap (emitting budget.capped). Mid-turn enforcement and
7
+ // sub-agent inheritance arrive with the delegation runtime (ADR-0039); the
8
+ // tracker already keys on arbitrary agent ids so it is ready for both.
9
+ export function makeBudgetTracker(deps) {
10
+ const capFor = (agentId) => deps.caps[agentId] ?? 0;
11
+ return {
12
+ capFor,
13
+ spentFor: (agentId) => deps.spent(agentId),
14
+ remainingFor: (agentId) => {
15
+ const cap = capFor(agentId);
16
+ return cap > 0 ? Math.max(0, cap - deps.spent(agentId)) : Infinity;
17
+ },
18
+ over: (agentId) => {
19
+ const cap = capFor(agentId);
20
+ return cap > 0 && deps.spent(agentId) >= cap;
21
+ },
22
+ };
23
+ }
24
+ //# sourceMappingURL=budget.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"budget.js","sourceRoot":"","sources":["../../src/runtime/budget.ts"],"names":[],"mappings":"AAAA,wDAAwD;AACxD,EAAE;AACF,+EAA+E;AAC/E,gFAAgF;AAChF,+EAA+E;AAC/E,+EAA+E;AAC/E,2EAA2E;AAC3E,uEAAuE;AAavE,MAAM,UAAU,iBAAiB,CAAC,IAGjC;IACC,MAAM,MAAM,GAAG,CAAC,OAAe,EAAU,EAAE,CAAC,IAAI,CAAC,IAAI,CAAC,OAAO,CAAC,IAAI,CAAC,CAAA;IACnE,OAAO;QACL,MAAM;QACN,QAAQ,EAAE,CAAC,OAAO,EAAE,EAAE,CAAC,IAAI,CAAC,KAAK,CAAC,OAAO,CAAC;QAC1C,YAAY,EAAE,CAAC,OAAO,EAAE,EAAE;YACxB,MAAM,GAAG,GAAG,MAAM,CAAC,OAAO,CAAC,CAAA;YAC3B,OAAO,GAAG,GAAG,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC,EAAE,GAAG,GAAG,IAAI,CAAC,KAAK,CAAC,OAAO,CAAC,CAAC,CAAC,CAAC,CAAC,QAAQ,CAAA;QACpE,CAAC;QACD,IAAI,EAAE,CAAC,OAAO,EAAE,EAAE;YAChB,MAAM,GAAG,GAAG,MAAM,CAAC,OAAO,CAAC,CAAA;YAC3B,OAAO,GAAG,GAAG,CAAC,IAAI,IAAI,CAAC,KAAK,CAAC,OAAO,CAAC,IAAI,GAAG,CAAA;QAC9C,CAAC;KACF,CAAA;AACH,CAAC"}
@@ -0,0 +1,11 @@
1
+ import type { DelegationManager, DelegationHandle, DelegationTask, TaskObservation } from '../orchestration/index.js';
2
+ export interface DelegationDriverDeps {
3
+ manager: DelegationManager;
4
+ runTask: (handle: DelegationHandle, task: DelegationTask) => Promise<TaskObservation>;
5
+ onEvent?: (e: {
6
+ kind: string;
7
+ detail: unknown;
8
+ }) => void;
9
+ }
10
+ export declare function runDelegation(deps: DelegationDriverDeps): Promise<TaskObservation[]>;
11
+ //# sourceMappingURL=delegation-driver.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"delegation-driver.d.ts","sourceRoot":"","sources":["../../src/runtime/delegation-driver.ts"],"names":[],"mappings":"AAcA,OAAO,KAAK,EAAE,iBAAiB,EAAE,gBAAgB,EAAE,cAAc,EAAE,eAAe,EAAE,MAAM,2BAA2B,CAAA;AAErH,MAAM,WAAW,oBAAoB;IACnC,OAAO,EAAE,iBAAiB,CAAA;IAC1B,OAAO,EAAE,CAAC,MAAM,EAAE,gBAAgB,EAAE,IAAI,EAAE,cAAc,KAAK,OAAO,CAAC,eAAe,CAAC,CAAA;IACrF,OAAO,CAAC,EAAE,CAAC,CAAC,EAAE;QAAE,IAAI,EAAE,MAAM,CAAC;QAAC,MAAM,EAAE,OAAO,CAAA;KAAE,KAAK,IAAI,CAAA;CACzD;AAmED,wBAAsB,aAAa,CAAC,IAAI,EAAE,oBAAoB,GAAG,OAAO,CAAC,eAAe,EAAE,CAAC,CA6D1F"}
@@ -0,0 +1,132 @@
1
+ // delegation-driver.ts — Tier-3 sub-agent delegation driver (ADR-0039, Task C1).
2
+ //
3
+ // Drives a DelegationManager's schedule: runs independent (write-disjoint) ready
4
+ // tasks CONCURRENTLY and serializes write-overlapping ones.
5
+ //
6
+ // Overlap predicate: two tasks' `scope.owns` glob sets overlap if any glob in A
7
+ // equals any glob in B, OR if one glob is a structural prefix of the other at a
8
+ // path-segment boundary — delegating to the same `patternsMayOverlap` logic that
9
+ // the manager itself uses. Practically, `['a/**']` vs `['b/**']` do NOT overlap
10
+ // (different roots → same batch); `['shared/**']` vs `['shared/**']` DO overlap
11
+ // (identical → different batches). This mirrors the manager's own spawn-time
12
+ // disjointness assertion so the driver never attempts concurrent spawns the
13
+ // manager would reject.
14
+ // ---------------------------------------------------------------------------
15
+ // Overlap predicate — mirrors orchestration/index.ts `patternsMayOverlap` so
16
+ // the driver's batching decision matches the manager's spawn-time guard.
17
+ // ---------------------------------------------------------------------------
18
+ function globRoot(glob) {
19
+ const idx = glob.search(/[*?]/);
20
+ return idx === -1 ? glob : glob.slice(0, idx);
21
+ }
22
+ function patternsMayOverlap(a, b) {
23
+ if (a === b)
24
+ return true;
25
+ const ra = globRoot(a);
26
+ const rb = globRoot(b);
27
+ const [shorter, longer] = ra.length <= rb.length ? [ra, rb] : [rb, ra];
28
+ if (!longer.startsWith(shorter))
29
+ return false;
30
+ return longer.length === shorter.length || shorter.endsWith('/') || longer[shorter.length] === '/';
31
+ }
32
+ function ownsOverlap(ownsA, ownsB) {
33
+ for (const a of ownsA) {
34
+ for (const b of ownsB) {
35
+ if (patternsMayOverlap(a, b))
36
+ return true;
37
+ }
38
+ }
39
+ return false;
40
+ }
41
+ // ---------------------------------------------------------------------------
42
+ // Greedy disjoint batching.
43
+ //
44
+ // Tasks are partitioned into ordered batches. A task joins the CURRENT batch
45
+ // iff its scope.owns is write-disjoint from every task already in that batch.
46
+ // A task that would overlap any member of the current batch is deferred to the
47
+ // next batch. Each batch is then run with Promise.all (fully concurrent).
48
+ //
49
+ // Result: disjoint tasks share a batch (concurrent); overlapping tasks land in
50
+ // separate batches (serialized across batches).
51
+ // ---------------------------------------------------------------------------
52
+ function greedyDisjointBatches(tasks) {
53
+ const batches = [];
54
+ for (const task of tasks) {
55
+ let placed = false;
56
+ for (const batch of batches) {
57
+ const fits = batch.every(b => !ownsOverlap(task.scope.owns, b.scope.owns));
58
+ if (fits) {
59
+ batch.push(task);
60
+ placed = true;
61
+ break;
62
+ }
63
+ }
64
+ if (!placed) {
65
+ batches.push([task]);
66
+ }
67
+ }
68
+ return batches;
69
+ }
70
+ // ---------------------------------------------------------------------------
71
+ // runDelegation — main driver loop.
72
+ // ---------------------------------------------------------------------------
73
+ export async function runDelegation(deps) {
74
+ const { manager, runTask, onEvent } = deps;
75
+ const observations = [];
76
+ const attempted = new Set();
77
+ for (;;) {
78
+ // Filter to tasks that haven't been attempted yet.
79
+ const ready = manager.readySet().filter(t => !attempted.has(t.taskId));
80
+ if (ready.length === 0)
81
+ break;
82
+ // Termination guard: if we have ready tasks but all were already attempted,
83
+ // we're stuck (runTask failed to close them). Break to avoid infinite loop.
84
+ // (The filter above already handles this — if ready is empty after filter, we break.)
85
+ const batches = greedyDisjointBatches(ready);
86
+ for (const batch of batches) {
87
+ for (const t of batch)
88
+ attempted.add(t.taskId);
89
+ const settled = await Promise.allSettled(batch.map(async (t) => {
90
+ let handle;
91
+ try {
92
+ handle = manager.spawn(t.taskId);
93
+ }
94
+ catch (err) {
95
+ const msg = err instanceof Error ? err.message : String(err);
96
+ onEvent?.({ kind: 'task-error', detail: { taskId: t.taskId, error: msg } });
97
+ // spawn() threw (e.g. null assignedTo, unknown card) — synthesise a failed
98
+ // observation so the manager can cascade-skip downstream tasks.
99
+ return {
100
+ delegationId: t.taskId,
101
+ status: 'failed',
102
+ summary: msg,
103
+ touched: [],
104
+ result: null,
105
+ cost: { iterations: 0, spendUsd: 0, wallMs: 0 },
106
+ };
107
+ }
108
+ try {
109
+ return await runTask(handle, t);
110
+ }
111
+ catch (err) {
112
+ const msg = err instanceof Error ? err.message : String(err);
113
+ onEvent?.({ kind: 'task-error', detail: { taskId: t.taskId, error: msg } });
114
+ // Convert an uncaught runTask error into a proper delegation failure so
115
+ // the manager cascade-skips downstream; the driver never leaves a task open.
116
+ return handle.fail(msg, { iterations: 0, spendUsd: 0, wallMs: 0 });
117
+ }
118
+ }));
119
+ for (const r of settled) {
120
+ if (r.status === 'fulfilled')
121
+ observations.push(r.value);
122
+ }
123
+ }
124
+ // Advance state + record cascade-skips.
125
+ const sched = manager.schedule();
126
+ if (sched.cascadeSkipped.length > 0) {
127
+ onEvent?.({ kind: 'cascade-skip', detail: sched.cascadeSkipped });
128
+ }
129
+ }
130
+ return observations;
131
+ }
132
+ //# sourceMappingURL=delegation-driver.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"delegation-driver.js","sourceRoot":"","sources":["../../src/runtime/delegation-driver.ts"],"names":[],"mappings":"AAAA,iFAAiF;AACjF,EAAE;AACF,iFAAiF;AACjF,4DAA4D;AAC5D,EAAE;AACF,gFAAgF;AAChF,gFAAgF;AAChF,iFAAiF;AACjF,gFAAgF;AAChF,gFAAgF;AAChF,6EAA6E;AAC7E,4EAA4E;AAC5E,wBAAwB;AAUxB,8EAA8E;AAC9E,6EAA6E;AAC7E,yEAAyE;AACzE,8EAA8E;AAE9E,SAAS,QAAQ,CAAC,IAAY;IAC5B,MAAM,GAAG,GAAG,IAAI,CAAC,MAAM,CAAC,MAAM,CAAC,CAAA;IAC/B,OAAO,GAAG,KAAK,CAAC,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC,EAAE,GAAG,CAAC,CAAA;AAC/C,CAAC;AAED,SAAS,kBAAkB,CAAC,CAAS,EAAE,CAAS;IAC9C,IAAI,CAAC,KAAK,CAAC;QAAE,OAAO,IAAI,CAAA;IACxB,MAAM,EAAE,GAAG,QAAQ,CAAC,CAAC,CAAC,CAAA;IACtB,MAAM,EAAE,GAAG,QAAQ,CAAC,CAAC,CAAC,CAAA;IACtB,MAAM,CAAC,OAAO,EAAE,MAAM,CAAC,GAAG,EAAE,CAAC,MAAM,IAAI,EAAE,CAAC,MAAM,CAAC,CAAC,CAAC,CAAC,EAAE,EAAE,EAAE,CAAC,CAAC,CAAC,CAAC,CAAC,EAAE,EAAE,EAAE,CAAC,CAAA;IACtE,IAAI,CAAC,MAAM,CAAC,UAAU,CAAC,OAAO,CAAC;QAAE,OAAO,KAAK,CAAA;IAC7C,OAAO,MAAM,CAAC,MAAM,KAAK,OAAO,CAAC,MAAM,IAAI,OAAO,CAAC,QAAQ,CAAC,GAAG,CAAC,IAAI,MAAM,CAAC,OAAO,CAAC,MAAM,CAAC,KAAK,GAAG,CAAA;AACpG,CAAC;AAED,SAAS,WAAW,CAAC,KAAe,EAAE,KAAe;IACnD,KAAK,MAAM,CAAC,IAAI,KAAK,EAAE,CAAC;QACtB,KAAK,MAAM,CAAC,IAAI,KAAK,EAAE,CAAC;YACtB,IAAI,kBAAkB,CAAC,CAAC,EAAE,CAAC,CAAC;gBAAE,OAAO,IAAI,CAAA;QAC3C,CAAC;IACH,CAAC;IACD,OAAO,KAAK,CAAA;AACd,CAAC;AAED,8EAA8E;AAC9E,4BAA4B;AAC5B,EAAE;AACF,6EAA6E;AAC7E,8EAA8E;AAC9E,+EAA+E;AAC/E,0EAA0E;AAC1E,EAAE;AACF,+EAA+E;AAC/E,gDAAgD;AAChD,8EAA8E;AAE9E,SAAS,qBAAqB,CAAC,KAAuB;IACpD,MAAM,OAAO,GAAuB,EAAE,CAAA;IAEtC,KAAK,MAAM,IAAI,IAAI,KAAK,EAAE,CAAC;QACzB,IAAI,MAAM,GAAG,KAAK,CAAA;QAClB,KAAK,MAAM,KAAK,IAAI,OAAO,EAAE,CAAC;YAC5B,MAAM,IAAI,GAAG,KAAK,CAAC,KAAK,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,WAAW,CAAC,IAAI,CAAC,KAAK,CAAC,IAAI,EAAE,CAAC,CAAC,KAAK,CAAC,IAAI,CAAC,CAAC,CAAA;YAC1E,IAAI,IAAI,EAAE,CAAC;gBACT,KAAK,CAAC,IAAI,CAAC,IAAI,CAAC,CAAA;gBAChB,MAAM,GAAG,IAAI,CAAA;gBACb,MAAK;YACP,CAAC;QACH,CAAC;QACD,IAAI,CAAC,MAAM,EAAE,CAAC;YACZ,OAAO,CAAC,IAAI,CAAC,CAAC,IAAI,CAAC,CAAC,CAAA;QACtB,CAAC;IACH,CAAC;IAED,OAAO,OAAO,CAAA;AAChB,CAAC;AAED,8EAA8E;AAC9E,oCAAoC;AACpC,8EAA8E;AAE9E,MAAM,CAAC,KAAK,UAAU,aAAa,CAAC,IAA0B;IAC5D,MAAM,EAAE,OAAO,EAAE,OAAO,EAAE,OAAO,EAAE,GAAG,IAAI,CAAA;IAC1C,MAAM,YAAY,GAAsB,EAAE,CAAA;IAC1C,MAAM,SAAS,GAAG,IAAI,GAAG,EAAU,CAAA;IAEnC,SAAS,CAAC;QACR,mDAAmD;QACnD,MAAM,KAAK,GAAG,OAAO,CAAC,QAAQ,EAAE,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,SAAS,CAAC,GAAG,CAAC,CAAC,CAAC,MAAM,CAAC,CAAC,CAAA;QACtE,IAAI,KAAK,CAAC,MAAM,KAAK,CAAC;YAAE,MAAK;QAE7B,4EAA4E;QAC5E,4EAA4E;QAC5E,sFAAsF;QAEtF,MAAM,OAAO,GAAG,qBAAqB,CAAC,KAAK,CAAC,CAAA;QAE5C,KAAK,MAAM,KAAK,IAAI,OAAO,EAAE,CAAC;YAC5B,KAAK,MAAM,CAAC,IAAI,KAAK;gBAAE,SAAS,CAAC,GAAG,CAAC,CAAC,CAAC,MAAM,CAAC,CAAA;YAC9C,MAAM,OAAO,GAAG,MAAM,OAAO,CAAC,UAAU,CACtC,KAAK,CAAC,GAAG,CAAC,KAAK,EAAE,CAAC,EAAE,EAAE;gBACpB,IAAI,MAAM,CAAA;gBACV,IAAI,CAAC;oBACH,MAAM,GAAG,OAAO,CAAC,KAAK,CAAC,CAAC,CAAC,MAAM,CAAC,CAAA;gBAClC,CAAC;gBAAC,OAAO,GAAG,EAAE,CAAC;oBACb,MAAM,GAAG,GAAG,GAAG,YAAY,KAAK,CAAC,CAAC,CAAC,GAAG,CAAC,OAAO,CAAC,CAAC,CAAC,MAAM,CAAC,GAAG,CAAC,CAAA;oBAC5D,OAAO,EAAE,CAAC,EAAE,IAAI,EAAE,YAAY,EAAE,MAAM,EAAE,EAAE,MAAM,EAAE,CAAC,CAAC,MAAM,EAAE,KAAK,EAAE,GAAG,EAAE,EAAE,CAAC,CAAA;oBAC3E,2EAA2E;oBAC3E,gEAAgE;oBAChE,OAAO;wBACL,YAAY,EAAE,CAAC,CAAC,MAAM;wBACtB,MAAM,EAAE,QAAiB;wBACzB,OAAO,EAAE,GAAG;wBACZ,OAAO,EAAE,EAAE;wBACX,MAAM,EAAE,IAAI;wBACZ,IAAI,EAAE,EAAE,UAAU,EAAE,CAAC,EAAE,QAAQ,EAAE,CAAC,EAAE,MAAM,EAAE,CAAC,EAAE;qBAChD,CAAA;gBACH,CAAC;gBACD,IAAI,CAAC;oBACH,OAAO,MAAM,OAAO,CAAC,MAAM,EAAE,CAAC,CAAC,CAAA;gBACjC,CAAC;gBAAC,OAAO,GAAG,EAAE,CAAC;oBACb,MAAM,GAAG,GAAG,GAAG,YAAY,KAAK,CAAC,CAAC,CAAC,GAAG,CAAC,OAAO,CAAC,CAAC,CAAC,MAAM,CAAC,GAAG,CAAC,CAAA;oBAC5D,OAAO,EAAE,CAAC,EAAE,IAAI,EAAE,YAAY,EAAE,MAAM,EAAE,EAAE,MAAM,EAAE,CAAC,CAAC,MAAM,EAAE,KAAK,EAAE,GAAG,EAAE,EAAE,CAAC,CAAA;oBAC3E,wEAAwE;oBACxE,6EAA6E;oBAC7E,OAAO,MAAM,CAAC,IAAI,CAAC,GAAG,EAAE,EAAE,UAAU,EAAE,CAAC,EAAE,QAAQ,EAAE,CAAC,EAAE,MAAM,EAAE,CAAC,EAAE,CAAC,CAAA;gBACpE,CAAC;YACH,CAAC,CAAC,CACH,CAAA;YACD,KAAK,MAAM,CAAC,IAAI,OAAO,EAAE,CAAC;gBACxB,IAAI,CAAC,CAAC,MAAM,KAAK,WAAW;oBAAE,YAAY,CAAC,IAAI,CAAC,CAAC,CAAC,KAAK,CAAC,CAAA;YAC1D,CAAC;QACH,CAAC;QAED,wCAAwC;QACxC,MAAM,KAAK,GAAG,OAAO,CAAC,QAAQ,EAAE,CAAA;QAChC,IAAI,KAAK,CAAC,cAAc,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC;YACpC,OAAO,EAAE,CAAC,EAAE,IAAI,EAAE,cAAc,EAAE,MAAM,EAAE,KAAK,CAAC,cAAc,EAAE,CAAC,CAAA;QACnE,CAAC;IACH,CAAC;IAED,OAAO,YAAY,CAAA;AACrB,CAAC"}
@@ -0,0 +1,10 @@
1
+ import type { ProviderAdapter, ModelResponse } from '../agent-loop/types.js';
2
+ export interface ExactCacheStore {
3
+ get(key: string): ModelResponse | undefined;
4
+ set(key: string, value: ModelResponse): void;
5
+ }
6
+ export declare function makeMemoryExactCacheStore(): ExactCacheStore;
7
+ /** Content-addressed exact-response cache. ONLY for deterministic, non-stateful
8
+ * paths (eval-replay, nightly re-run). NEVER wrap the live agent loop (ADR-0055). */
9
+ export declare function makeExactCache(inner: ProviderAdapter, store: ExactCacheStore, namespace: string): ProviderAdapter;
10
+ //# sourceMappingURL=exact-cache.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"exact-cache.d.ts","sourceRoot":"","sources":["../../src/runtime/exact-cache.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,eAAe,EAAgB,aAAa,EAAE,MAAM,wBAAwB,CAAA;AAE1F,MAAM,WAAW,eAAe;IAC9B,GAAG,CAAC,GAAG,EAAE,MAAM,GAAG,aAAa,GAAG,SAAS,CAAA;IAC3C,GAAG,CAAC,GAAG,EAAE,MAAM,EAAE,KAAK,EAAE,aAAa,GAAG,IAAI,CAAA;CAC7C;AAED,wBAAgB,yBAAyB,IAAI,eAAe,CAG3D;AAUD;sFACsF;AACtF,wBAAgB,cAAc,CAAC,KAAK,EAAE,eAAe,EAAE,KAAK,EAAE,eAAe,EAAE,SAAS,EAAE,MAAM,GAAG,eAAe,CAWjH"}
@@ -0,0 +1,30 @@
1
+ import { createHash } from 'node:crypto';
2
+ export function makeMemoryExactCacheStore() {
3
+ const m = new Map();
4
+ return { get: (k) => m.get(k), set: (k, v) => void m.set(k, v) };
5
+ }
6
+ function keyOf(namespace, req) {
7
+ const h = createHash('sha256');
8
+ h.update(namespace);
9
+ h.update('\0');
10
+ h.update(Buffer.from(req.prefixBytes));
11
+ h.update('\0');
12
+ h.update(JSON.stringify(req.spans));
13
+ return h.digest('hex');
14
+ }
15
+ /** Content-addressed exact-response cache. ONLY for deterministic, non-stateful
16
+ * paths (eval-replay, nightly re-run). NEVER wrap the live agent loop (ADR-0055). */
17
+ export function makeExactCache(inner, store, namespace) {
18
+ return {
19
+ async complete(req, signal) {
20
+ const key = keyOf(namespace, req);
21
+ const hit = store.get(key);
22
+ if (hit)
23
+ return hit;
24
+ const res = await inner.complete(req, signal);
25
+ store.set(key, res);
26
+ return res;
27
+ },
28
+ };
29
+ }
30
+ //# sourceMappingURL=exact-cache.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"exact-cache.js","sourceRoot":"","sources":["../../src/runtime/exact-cache.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,UAAU,EAAE,MAAM,aAAa,CAAA;AAQxC,MAAM,UAAU,yBAAyB;IACvC,MAAM,CAAC,GAAG,IAAI,GAAG,EAAyB,CAAA;IAC1C,OAAO,EAAE,GAAG,EAAE,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,GAAG,EAAE,CAAC,CAAC,EAAE,CAAC,EAAE,EAAE,CAAC,KAAK,CAAC,CAAC,GAAG,CAAC,CAAC,EAAE,CAAC,CAAC,EAAE,CAAA;AAClE,CAAC;AAED,SAAS,KAAK,CAAC,SAAiB,EAAE,GAAiB;IACjD,MAAM,CAAC,GAAG,UAAU,CAAC,QAAQ,CAAC,CAAA;IAC9B,CAAC,CAAC,MAAM,CAAC,SAAS,CAAC,CAAC;IAAC,CAAC,CAAC,MAAM,CAAC,IAAI,CAAC,CAAA;IACnC,CAAC,CAAC,MAAM,CAAC,MAAM,CAAC,IAAI,CAAC,GAAG,CAAC,WAAW,CAAC,CAAC,CAAC;IAAC,CAAC,CAAC,MAAM,CAAC,IAAI,CAAC,CAAA;IACtD,CAAC,CAAC,MAAM,CAAC,IAAI,CAAC,SAAS,CAAC,GAAG,CAAC,KAAK,CAAC,CAAC,CAAA;IACnC,OAAO,CAAC,CAAC,MAAM,CAAC,KAAK,CAAC,CAAA;AACxB,CAAC;AAED;sFACsF;AACtF,MAAM,UAAU,cAAc,CAAC,KAAsB,EAAE,KAAsB,EAAE,SAAiB;IAC9F,OAAO;QACL,KAAK,CAAC,QAAQ,CAAC,GAAG,EAAE,MAAM;YACxB,MAAM,GAAG,GAAG,KAAK,CAAC,SAAS,EAAE,GAAG,CAAC,CAAA;YACjC,MAAM,GAAG,GAAG,KAAK,CAAC,GAAG,CAAC,GAAG,CAAC,CAAA;YAC1B,IAAI,GAAG;gBAAE,OAAO,GAAG,CAAA;YACnB,MAAM,GAAG,GAAG,MAAM,KAAK,CAAC,QAAQ,CAAC,GAAG,EAAE,MAAM,CAAC,CAAA;YAC7C,KAAK,CAAC,GAAG,CAAC,GAAG,EAAE,GAAG,CAAC,CAAA;YACnB,OAAO,GAAG,CAAA;QACZ,CAAC;KACF,CAAA;AACH,CAAC"}
@@ -0,0 +1,29 @@
1
+ import type { ToolCall } from '../agent-loop/types.js';
2
+ import type { TaskObservation } from '../orchestration/index.js';
3
+ export interface ToolResult {
4
+ ok: boolean;
5
+ output: string;
6
+ }
7
+ export interface FsPort {
8
+ readFile(path: string): string;
9
+ writeFile(path: string, content: string): void;
10
+ listDir(path: string): string[];
11
+ exists(path: string): boolean;
12
+ }
13
+ export interface ExecuteToolDeps {
14
+ fs: FsPort;
15
+ /** Workspace root; file paths are resolved under it and may not escape. */
16
+ workspaceRoot: string;
17
+ /** Sandbox shell port (Safety 05). Absent ⇒ bash reports unavailable. */
18
+ runBash?: (cmd: string) => Promise<{
19
+ stdout: string;
20
+ stderr: string;
21
+ exitCode: number;
22
+ }>;
23
+ /** Memory FTS read port. Absent ⇒ search_memory reports unavailable. */
24
+ searchMemory?: (query: string) => Promise<string> | string;
25
+ /** Sub-agent delegation runner. Absent ⇒ spawn_subagent reports unavailable. */
26
+ spawnSubagent?: (planJson: string) => Promise<TaskObservation[]>;
27
+ }
28
+ export declare function makeToolExecutor(deps: ExecuteToolDeps): (call: ToolCall) => Promise<ToolResult>;
29
+ //# sourceMappingURL=execute-tool.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"execute-tool.d.ts","sourceRoot":"","sources":["../../src/runtime/execute-tool.ts"],"names":[],"mappings":"AASA,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,wBAAwB,CAAA;AACtD,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,2BAA2B,CAAA;AAEhE,MAAM,WAAW,UAAU;IACzB,EAAE,EAAE,OAAO,CAAA;IACX,MAAM,EAAE,MAAM,CAAA;CACf;AAED,MAAM,WAAW,MAAM;IACrB,QAAQ,CAAC,IAAI,EAAE,MAAM,GAAG,MAAM,CAAA;IAC9B,SAAS,CAAC,IAAI,EAAE,MAAM,EAAE,OAAO,EAAE,MAAM,GAAG,IAAI,CAAA;IAC9C,OAAO,CAAC,IAAI,EAAE,MAAM,GAAG,MAAM,EAAE,CAAA;IAC/B,MAAM,CAAC,IAAI,EAAE,MAAM,GAAG,OAAO,CAAA;CAC9B;AAED,MAAM,WAAW,eAAe;IAC9B,EAAE,EAAE,MAAM,CAAA;IACV,2EAA2E;IAC3E,aAAa,EAAE,MAAM,CAAA;IACrB,yEAAyE;IACzE,OAAO,CAAC,EAAE,CAAC,GAAG,EAAE,MAAM,KAAK,OAAO,CAAC;QAAE,MAAM,EAAE,MAAM,CAAC;QAAC,MAAM,EAAE,MAAM,CAAC;QAAC,QAAQ,EAAE,MAAM,CAAA;KAAE,CAAC,CAAA;IACxF,wEAAwE;IACxE,YAAY,CAAC,EAAE,CAAC,KAAK,EAAE,MAAM,KAAK,OAAO,CAAC,MAAM,CAAC,GAAG,MAAM,CAAA;IAC1D,gFAAgF;IAChF,aAAa,CAAC,EAAE,CAAC,QAAQ,EAAE,MAAM,KAAK,OAAO,CAAC,eAAe,EAAE,CAAC,CAAA;CACjE;AAOD,wBAAgB,gBAAgB,CAC9B,IAAI,EAAE,eAAe,GACpB,CAAC,IAAI,EAAE,QAAQ,KAAK,OAAO,CAAC,UAAU,CAAC,CAgEzC"}
@@ -0,0 +1,80 @@
1
+ // Tool executor (runtime).
2
+ //
3
+ // Maps an approved ToolCall to a real implementation via injected ports. This is
4
+ // the agent-loop's `executeTool` seam; it runs ONLY after hookGate.pre has
5
+ // allowed the call, so it is not a security boundary — but it still confines
6
+ // filesystem operations to the workspace as defense-in-depth. Side-effecting
7
+ // tools (bash) are injected ports so the sandbox stays swappable/testable.
8
+ import { isAbsolute, normalize, resolve } from 'node:path';
9
+ function arg(call, key) {
10
+ const v = call.args[key];
11
+ return typeof v === 'string' ? v : '';
12
+ }
13
+ export function makeToolExecutor(deps) {
14
+ const root = resolve(deps.workspaceRoot);
15
+ /** Resolve a tool-supplied path under the workspace root; null if it escapes. */
16
+ const confine = (p) => {
17
+ if (p.length === 0)
18
+ return null;
19
+ const abs = isAbsolute(p) ? normalize(p) : resolve(root, p);
20
+ if (abs !== root && !abs.startsWith(root + '/'))
21
+ return null;
22
+ return abs;
23
+ };
24
+ return async (call) => {
25
+ switch (call.name) {
26
+ case 'read_file': {
27
+ const path = confine(arg(call, 'path'));
28
+ if (!path)
29
+ return { ok: false, output: 'read_file: path outside workspace' };
30
+ if (!deps.fs.exists(path))
31
+ return { ok: false, output: `read_file: not found: ${path}` };
32
+ return { ok: true, output: deps.fs.readFile(path) };
33
+ }
34
+ case 'write_file': {
35
+ const path = confine(arg(call, 'path'));
36
+ if (!path)
37
+ return { ok: false, output: 'write_file: path outside workspace' };
38
+ deps.fs.writeFile(path, arg(call, 'content'));
39
+ return { ok: true, output: `wrote ${path}` };
40
+ }
41
+ case 'list_dir': {
42
+ const path = confine(arg(call, 'path') || '.');
43
+ if (!path)
44
+ return { ok: false, output: 'list_dir: path outside workspace' };
45
+ if (!deps.fs.exists(path))
46
+ return { ok: false, output: `list_dir: not found: ${path}` };
47
+ return { ok: true, output: deps.fs.listDir(path).join('\n') };
48
+ }
49
+ case 'bash': {
50
+ if (!deps.runBash)
51
+ return { ok: false, output: 'bash: sandbox unavailable' };
52
+ const r = await deps.runBash(arg(call, 'cmd'));
53
+ const body = [r.stdout, r.stderr].filter((s) => s.length > 0).join('\n');
54
+ return { ok: r.exitCode === 0, output: `${body}\n(exit ${r.exitCode})`.trim() };
55
+ }
56
+ case 'search_memory': {
57
+ if (!deps.searchMemory)
58
+ return { ok: false, output: 'search_memory: unavailable' };
59
+ return { ok: true, output: await deps.searchMemory(arg(call, 'query')) };
60
+ }
61
+ case 'spawn_subagent': {
62
+ if (!deps.spawnSubagent)
63
+ return { ok: false, output: 'spawn_subagent: delegation not available' };
64
+ const planArg = arg(call, 'plan');
65
+ if (planArg.length === 0)
66
+ return { ok: false, output: 'spawn_subagent: plan must be a JSON string' };
67
+ const observations = await deps.spawnSubagent(planArg);
68
+ return { ok: true, output: JSON.stringify(observations) };
69
+ }
70
+ case 'goal_done':
71
+ // Tier-0 claim: no side effect. The orchestrator (Phase C) intercepts this
72
+ // sentinel before it reaches here; this case ensures graceful handling in
73
+ // any runner that reaches the base executor (e.g. sub-agents).
74
+ return { ok: true, output: '__goal_done__' };
75
+ default:
76
+ return { ok: false, output: `unsupported tool: ${call.name}` };
77
+ }
78
+ };
79
+ }
80
+ //# sourceMappingURL=execute-tool.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"execute-tool.js","sourceRoot":"","sources":["../../src/runtime/execute-tool.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,9 @@
1
+ import type { LoopGuardian } from '../agent-loop/types.js';
2
+ export interface GuardianDeps {
3
+ /** How many consecutive repeats of a period trip the guardian. Default 3. */
4
+ repeats?: number;
5
+ /** Largest cycle period to detect (1..3). Default 3. */
6
+ maxPeriod?: 1 | 2 | 3;
7
+ }
8
+ export declare function makeGuardian(deps?: GuardianDeps): LoopGuardian;
9
+ //# sourceMappingURL=guardian.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"guardian.d.ts","sourceRoot":"","sources":["../../src/runtime/guardian.ts"],"names":[],"mappings":"AAQA,OAAO,KAAK,EAAE,YAAY,EAAY,MAAM,wBAAwB,CAAA;AAEpE,MAAM,WAAW,YAAY;IAC3B,6EAA6E;IAC7E,OAAO,CAAC,EAAE,MAAM,CAAA;IAChB,wDAAwD;IACxD,SAAS,CAAC,EAAE,CAAC,GAAG,CAAC,GAAG,CAAC,CAAA;CACtB;AAMD,wBAAgB,YAAY,CAAC,IAAI,GAAE,YAAiB,GAAG,YAAY,CA6BlE"}
@@ -0,0 +1,41 @@
1
+ // Loop guardian (runtime) — agent-loop LoopGuardian shape.
2
+ //
3
+ // Detects repeating tool-call cycles so a stuck agent halts instead of looping
4
+ // forever. observe() is called on every dispatch; it trips when the recent
5
+ // signature stream shows a period-1/2/3 pattern repeated `repeats` times (e.g.
6
+ // the same call 3× in a row, or an A,B,A,B,A,B oscillation). note('replan')
7
+ // resets the window — a fresh plan is a fresh execution context (§5.3).
8
+ function sig(call) {
9
+ return `${call.name}:${JSON.stringify(call.args)}`;
10
+ }
11
+ export function makeGuardian(deps = {}) {
12
+ const repeats = deps.repeats ?? 3;
13
+ const maxPeriod = deps.maxPeriod ?? 3;
14
+ let window = [];
15
+ /** True if the tail is `period`-pattern repeated `repeats` times. */
16
+ const isCycle = (period) => {
17
+ const need = period * repeats;
18
+ if (window.length < need)
19
+ return false;
20
+ const tail = window.slice(window.length - need);
21
+ for (let i = period; i < tail.length; i++) {
22
+ if (tail[i] !== tail[i - period])
23
+ return false;
24
+ }
25
+ return true;
26
+ };
27
+ return {
28
+ observe(call) {
29
+ window.push(sig(call));
30
+ for (let p = 1; p <= maxPeriod; p = (p + 1)) {
31
+ if (isCycle(p))
32
+ return { trip: true, period: p };
33
+ }
34
+ return { trip: false };
35
+ },
36
+ note(_event) {
37
+ window = [];
38
+ },
39
+ };
40
+ }
41
+ //# sourceMappingURL=guardian.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"guardian.js","sourceRoot":"","sources":["../../src/runtime/guardian.ts"],"names":[],"mappings":"AAAA,2DAA2D;AAC3D,EAAE;AACF,+EAA+E;AAC/E,2EAA2E;AAC3E,+EAA+E;AAC/E,4EAA4E;AAC5E,wEAAwE;AAWxE,SAAS,GAAG,CAAC,IAAc;IACzB,OAAO,GAAG,IAAI,CAAC,IAAI,IAAI,IAAI,CAAC,SAAS,CAAC,IAAI,CAAC,IAAI,CAAC,EAAE,CAAA;AACpD,CAAC;AAED,MAAM,UAAU,YAAY,CAAC,OAAqB,EAAE;IAClD,MAAM,OAAO,GAAG,IAAI,CAAC,OAAO,IAAI,CAAC,CAAA;IACjC,MAAM,SAAS,GAAG,IAAI,CAAC,SAAS,IAAI,CAAC,CAAA;IACrC,IAAI,MAAM,GAAa,EAAE,CAAA;IAEzB,qEAAqE;IACrE,MAAM,OAAO,GAAG,CAAC,MAAc,EAAW,EAAE;QAC1C,MAAM,IAAI,GAAG,MAAM,GAAG,OAAO,CAAA;QAC7B,IAAI,MAAM,CAAC,MAAM,GAAG,IAAI;YAAE,OAAO,KAAK,CAAA;QACtC,MAAM,IAAI,GAAG,MAAM,CAAC,KAAK,CAAC,MAAM,CAAC,MAAM,GAAG,IAAI,CAAC,CAAA;QAC/C,KAAK,IAAI,CAAC,GAAG,MAAM,EAAE,CAAC,GAAG,IAAI,CAAC,MAAM,EAAE,CAAC,EAAE,EAAE,CAAC;YAC1C,IAAI,IAAI,CAAC,CAAC,CAAC,KAAK,IAAI,CAAC,CAAC,GAAG,MAAM,CAAC;gBAAE,OAAO,KAAK,CAAA;QAChD,CAAC;QACD,OAAO,IAAI,CAAA;IACb,CAAC,CAAA;IAED,OAAO;QACL,OAAO,CAAC,IAAc;YACpB,MAAM,CAAC,IAAI,CAAC,GAAG,CAAC,IAAI,CAAC,CAAC,CAAA;YACtB,KAAK,IAAI,CAAC,GAAG,CAAc,EAAE,CAAC,IAAI,SAAS,EAAE,CAAC,GAAG,CAAC,CAAC,GAAG,CAAC,CAAc,EAAE,CAAC;gBACtE,IAAI,OAAO,CAAC,CAAC,CAAC;oBAAE,OAAO,EAAE,IAAI,EAAE,IAAI,EAAE,MAAM,EAAE,CAAC,EAAE,CAAA;YAClD,CAAC;YACD,OAAO,EAAE,IAAI,EAAE,KAAK,EAAE,CAAA;QACxB,CAAC;QAED,IAAI,CAAC,MAAgB;YACnB,MAAM,GAAG,EAAE,CAAA;QACb,CAAC;KACF,CAAA;AACH,CAAC"}
@@ -0,0 +1,17 @@
1
+ import type { HookGate } from '../agent-loop/types.js';
2
+ import type { SafetyPolicy, GrantStore, GrantScope } from '../safety/index.js';
3
+ import type { PendingAction } from '../gateway/index.js';
4
+ export type ApprovalDecision = {
5
+ decision: 'confirmed';
6
+ scope?: GrantScope;
7
+ } | {
8
+ decision: 'rejected';
9
+ };
10
+ export interface HookGateDeps {
11
+ safety: SafetyPolicy;
12
+ grants: GrantStore;
13
+ /** Human approval round-trip — the transport issues a card and awaits the tap. */
14
+ approve(action: PendingAction): Promise<ApprovalDecision>;
15
+ }
16
+ export declare function makeHookGate(deps: HookGateDeps): HookGate;
17
+ //# sourceMappingURL=hook-gate.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"hook-gate.d.ts","sourceRoot":"","sources":["../../src/runtime/hook-gate.ts"],"names":[],"mappings":"AAWA,OAAO,KAAK,EAAE,QAAQ,EAAqC,MAAM,wBAAwB,CAAA;AACzF,OAAO,KAAK,EACV,YAAY,EAEZ,UAAU,EACV,UAAU,EAGX,MAAM,oBAAoB,CAAA;AAC3B,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,qBAAqB,CAAA;AAExD,MAAM,MAAM,gBAAgB,GACxB;IAAE,QAAQ,EAAE,WAAW,CAAC;IAAC,KAAK,CAAC,EAAE,UAAU,CAAA;CAAE,GAC7C;IAAE,QAAQ,EAAE,UAAU,CAAA;CAAE,CAAA;AAE5B,MAAM,WAAW,YAAY;IAC3B,MAAM,EAAE,YAAY,CAAA;IACpB,MAAM,EAAE,UAAU,CAAA;IAClB,kFAAkF;IAClF,OAAO,CAAC,MAAM,EAAE,aAAa,GAAG,OAAO,CAAC,gBAAgB,CAAC,CAAA;CAC1D;AAeD,wBAAgB,YAAY,CAAC,IAAI,EAAE,YAAY,GAAG,QAAQ,CAkCzD"}
@@ -0,0 +1,56 @@
1
+ // HookGate adapter (runtime).
2
+ //
3
+ // Bridges the agent-loop's HookGate to the deterministic SafetyPolicy + the
4
+ // scoped-grant store + the human approval round-trip. The loop awaits pre(), so
5
+ // the entire "ask" resolution lives here: on a Tier-2/3 `ask` verdict we build a
6
+ // PendingAction, hand it to the injected approve() port (the transport issues
7
+ // the card and waits for the tap), and return allow/deny to the loop. On a
8
+ // confirmed Tier-2 with a remembered scope we record the grant, so the next
9
+ // matching call is allowed by SafetyPolicy.evaluate without another card.
10
+ import { randomUUID } from 'node:crypto';
11
+ function toSafetyCall(call, ctx) {
12
+ return {
13
+ tool: call.name,
14
+ args: call.args,
15
+ argsTainted: ctx.provenance === 'untrusted',
16
+ };
17
+ }
18
+ /** Narrowing is carried on HookCtx; surface it to SafetyPolicy as a synthetic span. */
19
+ function safetyCtx(ctx) {
20
+ return ctx.narrowed ? [{ text: '', provenance: 'untrusted', source: 'narrowed' }] : [];
21
+ }
22
+ export function makeHookGate(deps) {
23
+ return {
24
+ async pre(call, ctx) {
25
+ const verdict = deps.safety.evaluate(toSafetyCall(call, ctx), safetyCtx(ctx));
26
+ if (verdict.decision === 'allow')
27
+ return 'allow';
28
+ if (verdict.decision === 'deny')
29
+ return 'deny';
30
+ if (verdict.decision === 'modify') {
31
+ return { modify: { name: verdict.rewritten.tool, args: verdict.rewritten.args } };
32
+ }
33
+ // verdict.decision === 'ask' — resolve via the human approval round-trip.
34
+ const action = {
35
+ actionId: randomUUID(),
36
+ actionHash: verdict.card.actionHash,
37
+ tier: verdict.tier,
38
+ requiresStepUp: verdict.tier === 3,
39
+ summary: verdict.card.actionSummary,
40
+ };
41
+ const result = await deps.approve(action);
42
+ if (result.decision !== 'confirmed')
43
+ return 'deny';
44
+ // Remember the grant only for Tier-2 (Tier-3 is never grantable, ADR-0047).
45
+ if (result.scope && action.tier === 2) {
46
+ deps.grants.record(call.name, result.scope);
47
+ }
48
+ return 'allow';
49
+ },
50
+ async post(_call, _result) {
51
+ // PostToolUse is a no-op for the MVP spine; redaction/observability hooks
52
+ // attach here later.
53
+ },
54
+ };
55
+ }
56
+ //# sourceMappingURL=hook-gate.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"hook-gate.js","sourceRoot":"","sources":["../../src/runtime/hook-gate.ts"],"names":[],"mappings":"AAAA,8BAA8B;AAC9B,EAAE;AACF,4EAA4E;AAC5E,gFAAgF;AAChF,iFAAiF;AACjF,8EAA8E;AAC9E,2EAA2E;AAC3E,4EAA4E;AAC5E,0EAA0E;AAE1E,OAAO,EAAE,UAAU,EAAE,MAAM,aAAa,CAAA;AAuBxC,SAAS,YAAY,CAAC,IAAkB,EAAE,GAAY;IACpD,OAAO;QACL,IAAI,EAAE,IAAI,CAAC,IAAI;QACf,IAAI,EAAE,IAAI,CAAC,IAAI;QACf,WAAW,EAAE,GAAG,CAAC,UAAU,KAAK,WAAW;KAC5C,CAAA;AACH,CAAC;AAED,uFAAuF;AACvF,SAAS,SAAS,CAAC,GAAY;IAC7B,OAAO,GAAG,CAAC,QAAQ,CAAC,CAAC,CAAC,CAAC,EAAE,IAAI,EAAE,EAAE,EAAE,UAAU,EAAE,WAAW,EAAE,MAAM,EAAE,UAAU,EAAE,CAAC,CAAC,CAAC,CAAC,EAAE,CAAA;AACxF,CAAC;AAED,MAAM,UAAU,YAAY,CAAC,IAAkB;IAC7C,OAAO;QACL,KAAK,CAAC,GAAG,CAAC,IAAkB,EAAE,GAAY;YACxC,MAAM,OAAO,GAAY,IAAI,CAAC,MAAM,CAAC,QAAQ,CAAC,YAAY,CAAC,IAAI,EAAE,GAAG,CAAC,EAAE,SAAS,CAAC,GAAG,CAAC,CAAC,CAAA;YAEtF,IAAI,OAAO,CAAC,QAAQ,KAAK,OAAO;gBAAE,OAAO,OAAO,CAAA;YAChD,IAAI,OAAO,CAAC,QAAQ,KAAK,MAAM;gBAAE,OAAO,MAAM,CAAA;YAC9C,IAAI,OAAO,CAAC,QAAQ,KAAK,QAAQ,EAAE,CAAC;gBAClC,OAAO,EAAE,MAAM,EAAE,EAAE,IAAI,EAAE,OAAO,CAAC,SAAS,CAAC,IAAI,EAAE,IAAI,EAAE,OAAO,CAAC,SAAS,CAAC,IAAI,EAAE,EAAE,CAAA;YACnF,CAAC;YAED,0EAA0E;YAC1E,MAAM,MAAM,GAAkB;gBAC5B,QAAQ,EAAE,UAAU,EAAE;gBACtB,UAAU,EAAE,OAAO,CAAC,IAAI,CAAC,UAAU;gBACnC,IAAI,EAAE,OAAO,CAAC,IAAI;gBAClB,cAAc,EAAE,OAAO,CAAC,IAAI,KAAK,CAAC;gBAClC,OAAO,EAAE,OAAO,CAAC,IAAI,CAAC,aAAa;aACpC,CAAA;YACD,MAAM,MAAM,GAAG,MAAM,IAAI,CAAC,OAAO,CAAC,MAAM,CAAC,CAAA;YACzC,IAAI,MAAM,CAAC,QAAQ,KAAK,WAAW;gBAAE,OAAO,MAAM,CAAA;YAElD,4EAA4E;YAC5E,IAAI,MAAM,CAAC,KAAK,IAAI,MAAM,CAAC,IAAI,KAAK,CAAC,EAAE,CAAC;gBACtC,IAAI,CAAC,MAAM,CAAC,MAAM,CAAC,IAAI,CAAC,IAAI,EAAE,MAAM,CAAC,KAAK,CAAC,CAAA;YAC7C,CAAC;YACD,OAAO,OAAO,CAAA;QAChB,CAAC;QAED,KAAK,CAAC,IAAI,CAAC,KAAmB,EAAE,OAAgB;YAC9C,0EAA0E;YAC1E,qBAAqB;QACvB,CAAC;KACF,CAAA;AACH,CAAC"}
@@ -0,0 +1,6 @@
1
+ import type { MemoryPort } from '../agent-loop/types.js';
2
+ import type { Memory } from '../memory/index.js';
3
+ export declare function makeMemoryPort(memory: Memory, nowIso: () => string): MemoryPort;
4
+ /** Bridge Memory.search → the execute-tool searchMemory port (hits → text). */
5
+ export declare function makeMemorySearch(memory: Memory, limit?: number): (query: string) => Promise<string>;
6
+ //# sourceMappingURL=memory-adapter.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"memory-adapter.d.ts","sourceRoot":"","sources":["../../src/runtime/memory-adapter.ts"],"names":[],"mappings":"AAKA,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,wBAAwB,CAAA;AACxD,OAAO,KAAK,EAAE,MAAM,EAAa,MAAM,oBAAoB,CAAA;AAE3D,wBAAgB,cAAc,CAAC,MAAM,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,MAAM,GAAG,UAAU,CAa/E;AAED,+EAA+E;AAC/E,wBAAgB,gBAAgB,CAAC,MAAM,EAAE,MAAM,EAAE,KAAK,SAAI,GAAG,CAAC,KAAK,EAAE,MAAM,KAAK,OAAO,CAAC,MAAM,CAAC,CAe9F"}
@@ -0,0 +1,38 @@
1
+ // packages/core-ts/src/runtime/memory-adapter.ts
2
+ // Bridge the memory component (Memory) to the agent-loop ports. The two
3
+ // FrozenSnapshot shapes differ — memory yields {bytes, sha256}; the loop wants
4
+ // {prefixBytes, prefixHash, breakpoints, takenAt} — so this is a real translation.
5
+ export function makeMemoryPort(memory, nowIso) {
6
+ return {
7
+ snapshot: async () => {
8
+ const snap = await memory.readFrozenSnapshot();
9
+ return {
10
+ prefixBytes: new Uint8Array(snap.bytes),
11
+ prefixHash: snap.sha256,
12
+ breakpoints: [],
13
+ takenAt: nowIso(),
14
+ };
15
+ },
16
+ forget: (factRef, humanConfirmed) => memory.forget(factRef, 'operator forget', humanConfirmed),
17
+ };
18
+ }
19
+ /** Bridge Memory.search → the execute-tool searchMemory port (hits → text). */
20
+ export function makeMemorySearch(memory, limit = 8) {
21
+ return async (query) => {
22
+ let hits;
23
+ try {
24
+ hits = await memory.search(query, { limit });
25
+ }
26
+ catch {
27
+ // A cold start (no index on disk until the first write) or a transient
28
+ // read error must NOT crash the turn — the loop's catch only handles its
29
+ // own Halt and would otherwise surface as an unhandled rejection in the
30
+ // transport. The model just gets "no memory" and continues.
31
+ return 'Память: индекс пуст или недоступен.';
32
+ }
33
+ if (hits.length === 0)
34
+ return 'Память: ничего не найдено.';
35
+ return hits.map((h) => `• [${h.factKey}] ${h.text}`).join('\n');
36
+ };
37
+ }
38
+ //# sourceMappingURL=memory-adapter.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"memory-adapter.js","sourceRoot":"","sources":["../../src/runtime/memory-adapter.ts"],"names":[],"mappings":"AAAA,iDAAiD;AACjD,wEAAwE;AACxE,+EAA+E;AAC/E,mFAAmF;AAKnF,MAAM,UAAU,cAAc,CAAC,MAAc,EAAE,MAAoB;IACjE,OAAO;QACL,QAAQ,EAAE,KAAK,IAAI,EAAE;YACnB,MAAM,IAAI,GAAG,MAAM,MAAM,CAAC,kBAAkB,EAAE,CAAA;YAC9C,OAAO;gBACL,WAAW,EAAE,IAAI,UAAU,CAAC,IAAI,CAAC,KAAK,CAAC;gBACvC,UAAU,EAAE,IAAI,CAAC,MAAM;gBACvB,WAAW,EAAE,EAAE;gBACf,OAAO,EAAE,MAAM,EAAE;aAClB,CAAA;QACH,CAAC;QACD,MAAM,EAAE,CAAC,OAAO,EAAE,cAAc,EAAE,EAAE,CAAC,MAAM,CAAC,MAAM,CAAC,OAAO,EAAE,iBAAiB,EAAE,cAAc,CAAC;KAC/F,CAAA;AACH,CAAC;AAED,+EAA+E;AAC/E,MAAM,UAAU,gBAAgB,CAAC,MAAc,EAAE,KAAK,GAAG,CAAC;IACxD,OAAO,KAAK,EAAE,KAAa,EAAE,EAAE;QAC7B,IAAI,IAAiB,CAAA;QACrB,IAAI,CAAC;YACH,IAAI,GAAG,MAAM,MAAM,CAAC,MAAM,CAAC,KAAK,EAAE,EAAE,KAAK,EAAE,CAAC,CAAA;QAC9C,CAAC;QAAC,MAAM,CAAC;YACP,uEAAuE;YACvE,yEAAyE;YACzE,wEAAwE;YACxE,4DAA4D;YAC5D,OAAO,qCAAqC,CAAA;QAC9C,CAAC;QACD,IAAI,IAAI,CAAC,MAAM,KAAK,CAAC;YAAE,OAAO,4BAA4B,CAAA;QAC1D,OAAO,IAAI,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,MAAM,CAAC,CAAC,OAAO,KAAK,CAAC,CAAC,IAAI,EAAE,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,CAAA;IACjE,CAAC,CAAA;AACH,CAAC"}