open-multi-agent-kit 0.95.2 → 0.96.1

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 (259) hide show
  1. package/CHANGELOG.md +60 -0
  2. package/README.md +37 -4
  3. package/dist/approvals/approval-receipt-store.d.ts.map +1 -1
  4. package/dist/approvals/approval-receipt-store.js +25 -0
  5. package/dist/approvals/approval-receipt-store.js.map +1 -1
  6. package/dist/commands/doctor-provider.d.ts.map +1 -1
  7. package/dist/commands/doctor-provider.js +15 -20
  8. package/dist/commands/doctor-provider.js.map +1 -1
  9. package/dist/commands/sdk-session-cli.d.ts +24 -0
  10. package/dist/commands/sdk-session-cli.d.ts.map +1 -0
  11. package/dist/commands/sdk-session-cli.js +225 -0
  12. package/dist/commands/sdk-session-cli.js.map +1 -0
  13. package/dist/core/advisory-judge-model.d.ts +18 -0
  14. package/dist/core/advisory-judge-model.d.ts.map +1 -0
  15. package/dist/core/advisory-judge-model.js +168 -0
  16. package/dist/core/advisory-judge-model.js.map +1 -0
  17. package/dist/core/advisory-judge-response.d.ts +8 -0
  18. package/dist/core/advisory-judge-response.d.ts.map +1 -0
  19. package/dist/core/advisory-judge-response.js +61 -0
  20. package/dist/core/advisory-judge-response.js.map +1 -0
  21. package/dist/core/advisory-judge-types.d.ts +53 -0
  22. package/dist/core/advisory-judge-types.d.ts.map +1 -0
  23. package/dist/core/advisory-judge-types.js +2 -0
  24. package/dist/core/advisory-judge-types.js.map +1 -0
  25. package/dist/core/advisory-judge.d.ts +8 -0
  26. package/dist/core/advisory-judge.d.ts.map +1 -0
  27. package/dist/core/advisory-judge.js +178 -0
  28. package/dist/core/advisory-judge.js.map +1 -0
  29. package/dist/core/agent-session-services.d.ts +1 -0
  30. package/dist/core/agent-session-services.d.ts.map +1 -1
  31. package/dist/core/agent-session-services.js +1 -0
  32. package/dist/core/agent-session-services.js.map +1 -1
  33. package/dist/core/agent-session.d.ts +6 -3
  34. package/dist/core/agent-session.d.ts.map +1 -1
  35. package/dist/core/agent-session.js +141 -184
  36. package/dist/core/agent-session.js.map +1 -1
  37. package/dist/core/auth-storage.d.ts.map +1 -1
  38. package/dist/core/auth-storage.js +28 -4
  39. package/dist/core/auth-storage.js.map +1 -1
  40. package/dist/core/compaction-gate.d.ts +28 -0
  41. package/dist/core/compaction-gate.d.ts.map +1 -0
  42. package/dist/core/compaction-gate.js +34 -0
  43. package/dist/core/compaction-gate.js.map +1 -0
  44. package/dist/core/context-budget-system-prompt-items.d.ts.map +1 -1
  45. package/dist/core/context-budget-system-prompt-items.js +5 -3
  46. package/dist/core/context-budget-system-prompt-items.js.map +1 -1
  47. package/dist/core/domain-loadouts.d.ts.map +1 -1
  48. package/dist/core/domain-loadouts.js +2 -2
  49. package/dist/core/domain-loadouts.js.map +1 -1
  50. package/dist/core/durable-goal-checkpoint.d.ts +6 -0
  51. package/dist/core/durable-goal-checkpoint.d.ts.map +1 -0
  52. package/dist/core/durable-goal-checkpoint.js +195 -0
  53. package/dist/core/durable-goal-checkpoint.js.map +1 -0
  54. package/dist/core/durable-goal-parse.d.ts +3 -0
  55. package/dist/core/durable-goal-parse.d.ts.map +1 -0
  56. package/dist/core/durable-goal-parse.js +86 -0
  57. package/dist/core/durable-goal-parse.js.map +1 -0
  58. package/dist/core/durable-goal-reducer.d.ts +3 -0
  59. package/dist/core/durable-goal-reducer.d.ts.map +1 -0
  60. package/dist/core/durable-goal-reducer.js +175 -0
  61. package/dist/core/durable-goal-reducer.js.map +1 -0
  62. package/dist/core/durable-goal-store.d.ts +19 -0
  63. package/dist/core/durable-goal-store.d.ts.map +1 -0
  64. package/dist/core/durable-goal-store.js +126 -0
  65. package/dist/core/durable-goal-store.js.map +1 -0
  66. package/dist/core/durable-goal.d.ts +92 -0
  67. package/dist/core/durable-goal.d.ts.map +1 -0
  68. package/dist/core/durable-goal.js +62 -0
  69. package/dist/core/durable-goal.js.map +1 -0
  70. package/dist/core/extensions/builtin/goal-controller.d.ts +3 -0
  71. package/dist/core/extensions/builtin/goal-controller.d.ts.map +1 -0
  72. package/dist/core/extensions/builtin/goal-controller.js +125 -0
  73. package/dist/core/extensions/builtin/goal-controller.js.map +1 -0
  74. package/dist/core/extensions/builtin/identical-loop.d.ts +3 -0
  75. package/dist/core/extensions/builtin/identical-loop.d.ts.map +1 -0
  76. package/dist/core/extensions/builtin/identical-loop.js +31 -0
  77. package/dist/core/extensions/builtin/identical-loop.js.map +1 -0
  78. package/dist/core/extensions/builtin/prompt-preset.d.ts +3 -0
  79. package/dist/core/extensions/builtin/prompt-preset.d.ts.map +1 -0
  80. package/dist/core/extensions/builtin/prompt-preset.js +13 -0
  81. package/dist/core/extensions/builtin/prompt-preset.js.map +1 -0
  82. package/dist/core/extensions/builtin/tool-pair-repair.d.ts +3 -0
  83. package/dist/core/extensions/builtin/tool-pair-repair.d.ts.map +1 -0
  84. package/dist/core/extensions/builtin/tool-pair-repair.js +12 -0
  85. package/dist/core/extensions/builtin/tool-pair-repair.js.map +1 -0
  86. package/dist/core/extensions/types.d.ts +6 -2
  87. package/dist/core/extensions/types.d.ts.map +1 -1
  88. package/dist/core/extensions/types.js.map +1 -1
  89. package/dist/core/goal-continuation.d.ts +13 -0
  90. package/dist/core/goal-continuation.d.ts.map +1 -0
  91. package/dist/core/goal-continuation.js +10 -0
  92. package/dist/core/goal-continuation.js.map +1 -0
  93. package/dist/core/grok-harness.d.ts +1 -1
  94. package/dist/core/grok-harness.d.ts.map +1 -1
  95. package/dist/core/grok-harness.js +1 -1
  96. package/dist/core/grok-harness.js.map +1 -1
  97. package/dist/core/grok-playbook.d.ts +1 -1
  98. package/dist/core/grok-playbook.d.ts.map +1 -1
  99. package/dist/core/grok-playbook.js +1 -1
  100. package/dist/core/grok-playbook.js.map +1 -1
  101. package/dist/core/identical-loop.d.ts +15 -0
  102. package/dist/core/identical-loop.d.ts.map +1 -0
  103. package/dist/core/identical-loop.js +34 -0
  104. package/dist/core/identical-loop.js.map +1 -0
  105. package/dist/core/index.d.ts +1 -1
  106. package/dist/core/index.d.ts.map +1 -1
  107. package/dist/core/index.js +1 -1
  108. package/dist/core/index.js.map +1 -1
  109. package/dist/core/model-prompt-policy.d.ts +11 -0
  110. package/dist/core/model-prompt-policy.d.ts.map +1 -0
  111. package/dist/core/model-prompt-policy.js +17 -0
  112. package/dist/core/model-prompt-policy.js.map +1 -0
  113. package/dist/core/model-registry.d.ts.map +1 -1
  114. package/dist/core/model-registry.js +16 -4
  115. package/dist/core/model-registry.js.map +1 -1
  116. package/dist/core/model-resolver.d.ts.map +1 -1
  117. package/dist/core/model-resolver.js +2 -2
  118. package/dist/core/model-resolver.js.map +1 -1
  119. package/dist/core/prompt-budget.d.ts +21 -0
  120. package/dist/core/prompt-budget.d.ts.map +1 -0
  121. package/dist/core/prompt-budget.js +51 -0
  122. package/dist/core/prompt-budget.js.map +1 -0
  123. package/dist/core/prompt-cache.d.ts +14 -0
  124. package/dist/core/prompt-cache.d.ts.map +1 -0
  125. package/dist/core/prompt-cache.js +16 -0
  126. package/dist/core/prompt-cache.js.map +1 -0
  127. package/dist/core/prompt-preset.d.ts +8 -0
  128. package/dist/core/prompt-preset.d.ts.map +1 -0
  129. package/dist/core/prompt-preset.js +56 -0
  130. package/dist/core/prompt-preset.js.map +1 -0
  131. package/dist/core/provider-resilience.d.ts +23 -0
  132. package/dist/core/provider-resilience.d.ts.map +1 -1
  133. package/dist/core/provider-resilience.js +34 -1
  134. package/dist/core/provider-resilience.js.map +1 -1
  135. package/dist/core/provider-retry.d.ts +29 -0
  136. package/dist/core/provider-retry.d.ts.map +1 -0
  137. package/dist/core/provider-retry.js +49 -0
  138. package/dist/core/provider-retry.js.map +1 -0
  139. package/dist/core/provider-usage.d.ts +2 -1
  140. package/dist/core/provider-usage.d.ts.map +1 -1
  141. package/dist/core/provider-usage.js +40 -6
  142. package/dist/core/provider-usage.js.map +1 -1
  143. package/dist/core/resource-loader.d.ts.map +1 -1
  144. package/dist/core/resource-loader.js +32 -0
  145. package/dist/core/resource-loader.js.map +1 -1
  146. package/dist/core/sandbox/backend.d.ts +12 -0
  147. package/dist/core/sandbox/backend.d.ts.map +1 -1
  148. package/dist/core/sandbox/backend.js +52 -42
  149. package/dist/core/sandbox/backend.js.map +1 -1
  150. package/dist/core/sandbox/policy.d.ts +2 -0
  151. package/dist/core/sandbox/policy.d.ts.map +1 -1
  152. package/dist/core/sandbox/policy.js +2 -1
  153. package/dist/core/sandbox/policy.js.map +1 -1
  154. package/dist/core/sdk.d.ts +2 -0
  155. package/dist/core/sdk.d.ts.map +1 -1
  156. package/dist/core/sdk.js +1 -0
  157. package/dist/core/sdk.js.map +1 -1
  158. package/dist/core/session-system-prompt.d.ts +28 -0
  159. package/dist/core/session-system-prompt.d.ts.map +1 -0
  160. package/dist/core/session-system-prompt.js +37 -0
  161. package/dist/core/session-system-prompt.js.map +1 -0
  162. package/dist/core/strict-record.d.ts +2 -0
  163. package/dist/core/strict-record.d.ts.map +1 -0
  164. package/dist/core/strict-record.js +9 -0
  165. package/dist/core/strict-record.js.map +1 -0
  166. package/dist/core/subagent-orchestration.d.ts.map +1 -1
  167. package/dist/core/subagent-orchestration.js +4 -2
  168. package/dist/core/subagent-orchestration.js.map +1 -1
  169. package/dist/core/tool-pair-repair.d.ts +11 -0
  170. package/dist/core/tool-pair-repair.d.ts.map +1 -0
  171. package/dist/core/tool-pair-repair.js +38 -0
  172. package/dist/core/tool-pair-repair.js.map +1 -0
  173. package/dist/core/tools/artifact-spill.d.ts +13 -0
  174. package/dist/core/tools/artifact-spill.d.ts.map +1 -0
  175. package/dist/core/tools/artifact-spill.js +26 -0
  176. package/dist/core/tools/artifact-spill.js.map +1 -0
  177. package/dist/core/tools/bash.d.ts +7 -4
  178. package/dist/core/tools/bash.d.ts.map +1 -1
  179. package/dist/core/tools/bash.js +8 -7
  180. package/dist/core/tools/bash.js.map +1 -1
  181. package/dist/core/tools/diagnostics.d.ts.map +1 -1
  182. package/dist/core/tools/diagnostics.js +8 -2
  183. package/dist/core/tools/diagnostics.js.map +1 -1
  184. package/dist/core/tools/index.d.ts +1 -1
  185. package/dist/core/tools/index.d.ts.map +1 -1
  186. package/dist/core/tools/index.js.map +1 -1
  187. package/dist/core/tools/read.d.ts +1 -0
  188. package/dist/core/tools/read.d.ts.map +1 -1
  189. package/dist/core/tools/read.js +10 -1
  190. package/dist/core/tools/read.js.map +1 -1
  191. package/dist/core/tools/tool-definition-wrapper.d.ts.map +1 -1
  192. package/dist/core/tools/tool-definition-wrapper.js +2 -0
  193. package/dist/core/tools/tool-definition-wrapper.js.map +1 -1
  194. package/dist/guardrails/evidence-protocol.d.ts +10 -0
  195. package/dist/guardrails/evidence-protocol.d.ts.map +1 -0
  196. package/dist/guardrails/evidence-protocol.js +34 -0
  197. package/dist/guardrails/evidence-protocol.js.map +1 -0
  198. package/dist/guardrails/evidence-system.d.ts +3 -1
  199. package/dist/guardrails/evidence-system.d.ts.map +1 -1
  200. package/dist/guardrails/evidence-system.js +22 -14
  201. package/dist/guardrails/evidence-system.js.map +1 -1
  202. package/dist/guardrails/replay-ledger-lock-owner.d.ts.map +1 -1
  203. package/dist/guardrails/replay-ledger-lock-owner.js +3 -1
  204. package/dist/guardrails/replay-ledger-lock-owner.js.map +1 -1
  205. package/dist/guardrails/replay-payload-hash.d.ts +6 -0
  206. package/dist/guardrails/replay-payload-hash.d.ts.map +1 -0
  207. package/dist/guardrails/replay-payload-hash.js +24 -0
  208. package/dist/guardrails/replay-payload-hash.js.map +1 -0
  209. package/dist/index.d.ts +20 -2
  210. package/dist/index.d.ts.map +1 -1
  211. package/dist/index.js +19 -0
  212. package/dist/index.js.map +1 -1
  213. package/dist/main.d.ts.map +1 -1
  214. package/dist/main.js +8 -0
  215. package/dist/main.js.map +1 -1
  216. package/dist/modes/interactive/theme/theme.d.ts.map +1 -1
  217. package/dist/modes/interactive/theme/theme.js +14 -3
  218. package/dist/modes/interactive/theme/theme.js.map +1 -1
  219. package/dist/types/evidence.d.ts +11 -3
  220. package/dist/types/evidence.d.ts.map +1 -1
  221. package/dist/types/evidence.js.map +1 -1
  222. package/docs/adaptorch-preview-spec.md +1 -1
  223. package/docs/adaptorch-preview.md +2 -2
  224. package/docs/book-to-skill.md +79 -0
  225. package/docs/compaction.md +10 -0
  226. package/docs/containerization.md +9 -0
  227. package/docs/docs.json +18 -2
  228. package/docs/environment-variables.md +11 -4
  229. package/docs/extensions.md +14 -1
  230. package/docs/grok-harness.md +35 -12
  231. package/docs/index.md +9 -5
  232. package/docs/loadout-domains/grok-harness.md +2 -2
  233. package/docs/models.md +21 -8
  234. package/docs/provider-resilience.md +42 -55
  235. package/docs/providers.md +13 -4
  236. package/docs/run-protocol.md +104 -0
  237. package/docs/sdk.md +111 -5
  238. package/docs/security.md +22 -32
  239. package/docs/sessions.md +20 -0
  240. package/docs/settings.md +2 -0
  241. package/docs/skills.md +9 -1
  242. package/docs/usage.md +38 -16
  243. package/examples/extensions/custom-provider-anthropic/package-lock.json +2 -2
  244. package/examples/extensions/custom-provider-anthropic/package.json +1 -1
  245. package/examples/extensions/custom-provider-gitlab-duo/index.ts +6 -1
  246. package/examples/extensions/custom-provider-gitlab-duo/package.json +1 -1
  247. package/examples/extensions/gondolin/package-lock.json +2 -2
  248. package/examples/extensions/gondolin/package.json +1 -1
  249. package/examples/extensions/sandbox/package-lock.json +2 -2
  250. package/examples/extensions/sandbox/package.json +1 -1
  251. package/examples/extensions/with-deps/package-lock.json +2 -2
  252. package/examples/extensions/with-deps/package.json +1 -1
  253. package/npm-shrinkwrap.json +37 -15
  254. package/package.json +8 -5
  255. package/dist/core/context-budget-compressors.d.ts +0 -50
  256. package/dist/core/context-budget-compressors.d.ts.map +0 -1
  257. package/dist/core/context-budget-compressors.js +0 -166
  258. package/dist/core/context-budget-compressors.js.map +0 -1
  259. package/dist/core/extensions/loader.js.bak-sharedjiti-20260812-111246 +0 -553
@@ -1 +1 @@
1
- {"version":3,"file":"subagent-orchestration.js","sourceRoot":"","sources":["../../src/core/subagent-orchestration.ts"],"names":[],"mappings":"AAAA,OAAO,EACN,sBAAsB,GAKtB,MAAM,sBAAsB,CAAC;AAC9B,OAAO,EACN,mBAAmB,EACnB,gBAAgB,EAEhB,qBAAqB,GAIrB,MAAM,eAAe,CAAC;AAiFvB,MAAM,uBAAuB,GAAG,CAAC,CAAC;AAElC,MAAM,gBAAgB,GAAwE;IAC7F,OAAO,EAAE;QACR,IAAI,EAAE,SAAS;QACf,WAAW,EAAE,SAAS;QACtB,WAAW,EAAE,MAAM;QACnB,SAAS,EAAE,aAAa;QACxB,kBAAkB,EAAE,SAAS;QAC7B,aAAa,EAAE,CAAC,aAAa,EAAE,SAAS,CAAC;QACzC,kBAAkB,EAAE,KAAK;KACzB;IACD,SAAS,EAAE;QACV,IAAI,EAAE,WAAW;QACjB,WAAW,EAAE,WAAW;QACxB,WAAW,EAAE,WAAW;QACxB,SAAS,EAAE,eAAe;QAC1B,kBAAkB,EAAE,SAAS;QAC7B,aAAa,EAAE,CAAC,aAAa,EAAE,wBAAwB,EAAE,gBAAgB,EAAE,SAAS,CAAC;QACrF,kBAAkB,EAAE,KAAK;KACzB;IACD,QAAQ,EAAE;QACT,IAAI,EAAE,UAAU;QAChB,WAAW,EAAE,UAAU;QACvB,WAAW,EAAE,UAAU;QACvB,SAAS,EAAE,cAAc;QACzB,kBAAkB,EAAE,SAAS;QAC7B,aAAa,EAAE,CAAC,aAAa,EAAE,wBAAwB,EAAE,WAAW,EAAE,gBAAgB,EAAE,SAAS,CAAC;QAClG,kBAAkB,EAAE,IAAI;KACxB;IACD,MAAM,EAAE;QACP,IAAI,EAAE,QAAQ;QACd,WAAW,EAAE,QAAQ;QACrB,WAAW,EAAE,QAAQ;QACrB,SAAS,EAAE,YAAY;QACvB,kBAAkB,EAAE,SAAS;QAC7B,aAAa,EAAE,CAAC,aAAa,EAAE,gBAAgB,EAAE,SAAS,CAAC;QAC3D,kBAAkB,EAAE,KAAK;KACzB;IACD,WAAW,EAAE;QACZ,IAAI,EAAE,WAAW;QACjB,WAAW,EAAE,WAAW;QACxB,WAAW,EAAE,WAAW;QACxB,SAAS,EAAE,eAAe;QAC1B,kBAAkB,EAAE,SAAS;QAC7B,aAAa,EAAE,CAAC,aAAa,EAAE,wBAAwB,EAAE,WAAW,EAAE,gBAAgB,EAAE,SAAS,CAAC;QAClG,kBAAkB,EAAE,KAAK;KACzB;IACD,UAAU,EAAE;QACX,IAAI,EAAE,UAAU;QAChB,WAAW,EAAE,UAAU;QACvB,WAAW,EAAE,UAAU;QACvB,SAAS,EAAE,cAAc;QACzB,kBAAkB,EAAE,SAAS;QAC7B,aAAa,EAAE,CAAC,aAAa,EAAE,wBAAwB,EAAE,WAAW,EAAE,gBAAgB,EAAE,SAAS,CAAC;QAClG,kBAAkB,EAAE,IAAI;KACxB;IACD,QAAQ,EAAE;QACT,IAAI,EAAE,UAAU;QAChB,WAAW,EAAE,UAAU;QACvB,WAAW,EAAE,UAAU;QACvB,SAAS,EAAE,cAAc;QACzB,kBAAkB,EAAE,MAAM;QAC1B,aAAa,EAAE,CAAC,aAAa,EAAE,wBAAwB,EAAE,gBAAgB,EAAE,SAAS,CAAC;QACrF,kBAAkB,EAAE,KAAK;KACzB;IACD,oBAAoB,EAAE;QACrB,IAAI,EAAE,oBAAoB;QAC1B,WAAW,EAAE,oBAAoB;QACjC,WAAW,EAAE,oBAAoB;QACjC,SAAS,EAAE,wBAAwB;QACnC,kBAAkB,EAAE,SAAS;QAC7B,aAAa,EAAE,CAAC,aAAa,EAAE,wBAAwB,EAAE,WAAW,EAAE,gBAAgB,EAAE,SAAS,CAAC;QAClG,kBAAkB,EAAE,IAAI;KACxB;CACD,CAAC;AAEF,MAAM,iCAAiC,GAAG;IACzC,aAAa;IACb,aAAa;IACb,cAAc;IACd,sBAAsB;CACb,CAAC;AASX,MAAM,UAAU,6BAA6B,CAAC,IAA+B,EAA0B;IACtG,OAAO,gBAAgB,CAAC,IAAI,CAAC,CAAC;AAAA,CAC9B;AAED,MAAM,UAAU,8BAA8B,CAAC,KAA0C,EAA6B;IACrH,IACC,KAAK,CAAC,gBAAgB,KAAK,SAAS;QACpC,CAAC,CAAC,MAAM,CAAC,SAAS,CAAC,KAAK,CAAC,gBAAgB,CAAC,IAAI,KAAK,CAAC,gBAAgB,GAAG,CAAC,CAAC,EACxE,CAAC;QACF,MAAM,IAAI,UAAU,CAAC,6CAA6C,CAAC,CAAC;IACrE,CAAC;IAED,MAAM,QAAQ,GAAa,EAAE,CAAC;IAC9B,MAAM,QAAQ,GAAa,EAAE,CAAC;IAC9B,QAAQ,CAAC,IAAI,CAAC,GAAG,kBAAkB,CAAC,KAAK,CAAC,KAAK,CAAC,CAAC,CAAC;IAClD,MAAM,SAAS,GAAG,iBAAiB,CAAC;QACnC,UAAU,EAAE,KAAK,CAAC,KAAK,CAAC,MAAM;QAC9B,IAAI,EAAE,KAAK,CAAC,SAAS;QACrB,SAAS,EAAE,KAAK,CAAC,cAAc,IAAI,uBAAuB;KAC1D,CAAC,CAAC;IACH,IAAI,SAAS,CAAC,OAAO,KAAK,UAAU;QAAE,QAAQ,CAAC,IAAI,CAAC,SAAS,CAAC,MAAM,CAAC,CAAC;IAEtE,MAAM,QAAQ,GAAG,KAAK,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC,IAAI,EAAE,KAAK,EAAE,EAAE,CAChD,WAAW,CAAC,IAAI,EAAE,KAAK,EAAE,KAAK,CAAC,KAAK,EAAE,KAAK,CAAC,SAAS,EAAE,KAAK,CAAC,SAAS,EAAE,QAAQ,EAAE,QAAQ,CAAC,CAC3F,CAAC;IACF,QAAQ,CAAC,IAAI,CAAC,GAAG,sBAAsB,CAAC,QAAQ,CAAC,CAAC,CAAC;IAEnD,MAAM,cAAc,GAAG,gCAAgC,CAAC,QAAQ,CAAC,CAAC;IAClE,MAAM,OAAO,GAAG,qBAAqB,CAAC,cAAc,EAAE,KAAK,CAAC,gBAAgB,EAAE,QAAQ,CAAC,CAAC;IACxF,MAAM,KAAK,GAAG,kBAAkB,CAAC,cAAc,EAAE,OAAO,CAAC,CAAC;IAE1D,OAAO;QACN,UAAU,EAAE,cAAc,CAAC,GAAG,CAAC,CAAC,IAAI,EAAE,EAAE,CAAC,IAAI,CAAC,KAAK,CAAC;QACpD,OAAO;QACP,KAAK;QACL,SAAS;QACT,QAAQ,EAAE,YAAY,CAAC,QAAQ,CAAC;QAChC,QAAQ,EAAE,YAAY,CAAC,QAAQ,CAAC;KAChC,CAAC;AAAA,CACF;AAED,MAAM,UAAU,iBAAiB,CAAC,OAIjC,EAAqB;IACrB,MAAM,SAAS,GAAG,OAAO,CAAC,SAAS,IAAI,uBAAuB,CAAC;IAC/D,IAAI,CAAC,MAAM,CAAC,SAAS,CAAC,OAAO,CAAC,UAAU,CAAC,IAAI,OAAO,CAAC,UAAU,GAAG,CAAC,EAAE,CAAC;QACrE,MAAM,IAAI,UAAU,CAAC,2CAA2C,CAAC,CAAC;IACnE,CAAC;IACD,IAAI,CAAC,MAAM,CAAC,SAAS,CAAC,SAAS,CAAC,IAAI,SAAS,GAAG,CAAC,EAAE,CAAC;QACnD,MAAM,IAAI,UAAU,CAAC,sCAAsC,CAAC,CAAC;IAC9D,CAAC;IAED,MAAM,YAAY,GAAG,OAAO,CAAC,UAAU,GAAG,SAAS,CAAC;IACpD,IAAI,CAAC,YAAY,EAAE,CAAC;QACnB,OAAO;YACN,OAAO,EAAE,SAAS;YAClB,MAAM,EAAE,YAAY,OAAO,CAAC,UAAU,6BAA6B,SAAS,EAAE;YAC9E,YAAY,EAAE,KAAK;YACnB,aAAa,EAAE,EAAE;SACjB,CAAC;IACH,CAAC;IAED,MAAM,aAAa,GAAG,0BAA0B,CAAC,OAAO,CAAC,IAAI,CAAC,CAAC;IAC/D,IAAI,aAAa,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC;QAC9B,OAAO;YACN,OAAO,EAAE,UAAU;YACnB,MAAM,EAAE,YAAY,OAAO,CAAC,UAAU,sBAAsB,SAAS,kCACpE,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,eAAe,aAAa,CAAC,IAAI,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC,CAAC,SAC7D,EAAE;YACF,YAAY,EAAE,IAAI;YAClB,aAAa;SACb,CAAC;IACH,CAAC;IAED,OAAO;QACN,OAAO,EAAE,SAAS;QAClB,MAAM,EAAE,YAAY,OAAO,CAAC,UAAU,sBAAsB,SAAS,iDAAiD;QACtH,YAAY,EAAE,IAAI;QAClB,aAAa,EAAE,EAAE;KACjB,CAAC;AAAA,CACF;AAED,MAAM,UAAU,0BAA0B,CAAC,IAAkC,EAAY;IACxF,IAAI,CAAC,IAAI;QAAE,OAAO,CAAC,GAAG,iCAAiC,EAAE,iBAAiB,CAAC,CAAC;IAC5E,MAAM,OAAO,GAAa,EAAE,CAAC;IAC7B,KAAK,MAAM,KAAK,IAAI,iCAAiC,EAAE,CAAC;QACvD,MAAM,KAAK,GAAG,IAAI,CAAC,KAAK,CAAC,CAAC;QAC1B,IAAI,KAAK,CAAC,IAAI,EAAE,CAAC,MAAM,KAAK,CAAC;YAAE,OAAO,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC;IACpD,CAAC;IACD,IAAI,CAAC,MAAM,CAAC,QAAQ,CAAC,IAAI,CAAC,eAAe,CAAC,IAAI,IAAI,CAAC,eAAe,IAAI,CAAC,EAAE,CAAC;QACzE,OAAO,CAAC,IAAI,CAAC,iBAAiB,CAAC,CAAC;IACjC,CAAC;IACD,OAAO,OAAO,CAAC;AAAA,CACf;AAED,SAAS,kBAAkB,CAAC,KAAkC,EAAY;IACzE,MAAM,QAAQ,GAAa,EAAE,CAAC;IAC9B,MAAM,OAAO,GAAG,IAAI,GAAG,EAAkB,CAAC;IAE1C,KAAK,MAAM,CAAC,KAAK,EAAE,IAAI,CAAC,IAAI,KAAK,CAAC,OAAO,EAAE,EAAE,CAAC;QAC7C,MAAM,EAAE,GAAG,IAAI,CAAC,EAAE,CAAC,IAAI,EAAE,CAAC;QAC1B,MAAM,KAAK,GAAG,EAAE,KAAK,EAAE,CAAC,CAAC,CAAC,iBAAiB,KAAK,EAAE,CAAC,CAAC,CAAC,QAAQ,EAAE,EAAE,CAAC;QAClE,IAAI,EAAE,KAAK,EAAE,EAAE,CAAC;YACf,QAAQ,CAAC,IAAI,CAAC,iBAAiB,KAAK,eAAe,CAAC,CAAC;QACtD,CAAC;aAAM,CAAC;YACP,MAAM,UAAU,GAAG,OAAO,CAAC,GAAG,CAAC,EAAE,CAAC,CAAC;YACnC,IAAI,UAAU,KAAK,SAAS,EAAE,CAAC;gBAC9B,OAAO,CAAC,GAAG,CAAC,EAAE,EAAE,KAAK,CAAC,CAAC;YACxB,CAAC;iBAAM,CAAC;gBACP,QAAQ,CAAC,IAAI,CAAC,qBAAqB,EAAE,eAAe,UAAU,QAAQ,KAAK,EAAE,CAAC,CAAC;YAChF,CAAC;QACF,CAAC;QAED,IAAI,IAAI,CAAC,IAAI,CAAC,IAAI,EAAE,KAAK,EAAE,EAAE,CAAC;YAC7B,QAAQ,CAAC,IAAI,CAAC,GAAG,KAAK,iBAAiB,CAAC,CAAC;QAC1C,CAAC;QAED,MAAM,gBAAgB,GAAG,IAAI,GAAG,EAAU,CAAC;QAC3C,KAAK,MAAM,UAAU,IAAI,IAAI,CAAC,SAAS,IAAI,EAAE,EAAE,CAAC;YAC/C,MAAM,YAAY,GAAG,UAAU,CAAC,IAAI,EAAE,CAAC;YACvC,IAAI,YAAY,KAAK,EAAE,EAAE,CAAC;gBACzB,QAAQ,CAAC,IAAI,CAAC,GAAG,KAAK,0BAA0B,CAAC,CAAC;gBAClD,SAAS;YACV,CAAC;YACD,IAAI,YAAY,KAAK,EAAE,EAAE,CAAC;gBACzB,QAAQ,CAAC,IAAI,CAAC,GAAG,KAAK,oBAAoB,CAAC,CAAC;YAC7C,CAAC;YACD,IAAI,gBAAgB,CAAC,GAAG,CAAC,YAAY,CAAC,EAAE,CAAC;gBACxC,QAAQ,CAAC,IAAI,CAAC,GAAG,KAAK,uBAAuB,YAAY,EAAE,CAAC,CAAC;YAC9D,CAAC;YACD,gBAAgB,CAAC,GAAG,CAAC,YAAY,CAAC,CAAC;QACpC,CAAC;IACF,CAAC;IAED,OAAO,QAAQ,CAAC;AAAA,CAChB;AAED,SAAS,WAAW,CACnB,IAAsB,EACtB,KAAa,EACb,KAAa,EACb,SAA8B,EAC9B,YAA0C,EAC1C,QAAkB,EAClB,QAAkB,EACH;IACf,MAAM,UAAU,GAAG,6BAA6B,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;IAC5D,IAAI,CAAC,IAAI,CAAC,UAAU,EAAE,MAAM,IAAI,CAAC,CAAC,GAAG,CAAC,IAAI,CAAC,UAAU,CAAC,kBAAkB,EAAE,CAAC;QAC1E,QAAQ,CAAC,IAAI,CAAC,QAAQ,IAAI,CAAC,EAAE,SAAS,IAAI,CAAC,IAAI,6BAA6B,CAAC,CAAC;IAC/E,CAAC;IACD,MAAM,SAAS,GAAG,YAAY,CAAC,IAAI,CAAC,SAAS,IAAI,EAAE,CAAC,CAAC;IAErD,MAAM,OAAO,GAAG,qBAAqB,CAAC,IAAI,EAAE,UAAU,EAAE,QAAQ,CAAC,CAAC;IAClE,MAAM,OAAO,GAAG,mBAAmB,CAAC,OAAO,EAAE,SAAS,EAAE,EAAE,cAAc,EAAE,IAAI,CAAC,cAAc,EAAE,CAAC,CAAC;IACjG,QAAQ,CAAC,IAAI,CAAC,GAAG,OAAO,CAAC,QAAQ,CAAC,GAAG,CAAC,CAAC,OAAO,EAAE,EAAE,CAAC,QAAQ,IAAI,CAAC,EAAE,KAAK,OAAO,EAAE,CAAC,CAAC,CAAC;IACnF,QAAQ,CAAC,IAAI,CAAC,GAAG,OAAO,CAAC,QAAQ,CAAC,GAAG,CAAC,CAAC,OAAO,EAAE,EAAE,CAAC,QAAQ,IAAI,CAAC,EAAE,KAAK,OAAO,EAAE,CAAC,CAAC,CAAC;IAEnF,MAAM,eAAe,GAAG,qBAAqB,CAAC;QAC7C,IAAI,EAAE,UAAU,CAAC,WAAW;QAC5B,iBAAiB,EAAE,IAAI,CAAC,SAAS;QACjC,kBAAkB,EAAE,IAAI,CAAC,UAAU;KACnC,CAAC,CAAC;IAEH,MAAM,KAAK,GAAG,sBAAsB,CAAC,IAAI,CAAC,EAAE,EAAE,UAAU,CAAC,WAAW,EAAE,IAAI,CAAC,IAAI,EAAE,OAAO,EAAE,eAAe,EAAE;QAC1G,gBAAgB,EAAE,IAAI,CAAC,SAAS;QAChC,iBAAiB,EAAE,IAAI,CAAC,UAAU;QAClC,YAAY,EAAE,IAAI,CAAC,YAAY;QAC/B,qBAAqB,EAAE,IAAI,CAAC,cAAc,IAAI,OAAO,CAAC,QAAQ,EAAE,aAAa;QAC7E,KAAK;QACL,OAAO;QACP,SAAS,EAAE,IAAI,CAAC,SAAS,IAAI,UAAU,CAAC,SAAS;QACjD,kBAAkB,EAAE,IAAI,CAAC,kBAAkB,IAAI,UAAU,CAAC,kBAAkB;QAC5E,YAAY;QACZ,aAAa,EAAE,UAAU,CAAC,aAAa;QACvC,SAAS;QACT,UAAU,EAAE,IAAI,CAAC,UAAU;KAC3B,CAAC,CAAC;IAEH,OAAO,EAAE,KAAK,EAAE,IAAI,EAAE,KAAK,EAAE,SAAS,EAAE,CAAC;AAAA,CACzC;AAED,SAAS,qBAAqB,CAC7B,IAAsB,EACtB,UAAkC,EAClC,QAAkB,EACD;IACjB,MAAM,WAAW,GAAG,IAAI,CAAC,WAAW,IAAI,UAAU,CAAC,WAAW,CAAC;IAC/D,MAAM,OAAO,GAAG,gBAAgB,CAAC,WAAW,CAAC,CAAC;IAC9C,IAAI,OAAO;QAAE,OAAO,OAAO,CAAC;IAC5B,QAAQ,CAAC,IAAI,CAAC,QAAQ,IAAI,CAAC,EAAE,qBAAqB,WAAW,EAAE,CAAC,CAAC;IACjE,OAAO,gBAAgB,CAAC,IAAI,CAAC;AAAA,CAC7B;AAED,SAAS,sBAAsB,CAAC,KAA8B,EAAY;IACzE,MAAM,GAAG,GAAG,IAAI,GAAG,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC,IAAI,EAAE,EAAE,CAAC,IAAI,CAAC,IAAI,CAAC,EAAE,CAAC,CAAC,CAAC;IACvD,MAAM,QAAQ,GAAa,EAAE,CAAC;IAC9B,KAAK,MAAM,IAAI,IAAI,KAAK,EAAE,CAAC;QAC1B,KAAK,MAAM,UAAU,IAAI,IAAI,CAAC,SAAS,EAAE,CAAC;YACzC,IAAI,CAAC,GAAG,CAAC,GAAG,CAAC,UAAU,CAAC,EAAE,CAAC;gBAC1B,QAAQ,CAAC,IAAI,CAAC,QAAQ,IAAI,CAAC,IAAI,CAAC,EAAE,4BAA4B,UAAU,EAAE,CAAC,CAAC;YAC7E,CAAC;QACF,CAAC;IACF,CAAC;IACD,OAAO,QAAQ,CAAC;AAAA,CAChB;AAED,SAAS,gCAAgC,CAAC,KAA8B,EAAkB;IACzF,MAAM,kBAAkB,GAAG,KAAK;SAC9B,MAAM,CAAC,CAAC,IAAI,EAAE,EAAE,CAAC,IAAI,CAAC,KAAK,CAAC,cAAc,KAAK,SAAS,IAAI,CAAC,qBAAqB,CAAC,IAAI,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;SACnG,GAAG,CAAC,CAAC,IAAI,EAAE,EAAE,CAAC,IAAI,CAAC,IAAI,CAAC,EAAE,CAAC,CAAC;IAE9B,OAAO,KAAK,CAAC,GAAG,CAAC,CAAC,IAAI,EAAE,EAAE,CAAC;QAC1B,IAAI,CAAC,wBAAwB,CAAC,IAAI,CAAC,IAAI,kBAAkB,CAAC,MAAM,KAAK,CAAC;YAAE,OAAO,IAAI,CAAC;QACpF,MAAM,SAAS,GAAG,YAAY,CAAC;YAC9B,GAAG,IAAI,CAAC,SAAS;YACjB,GAAG,kBAAkB,CAAC,MAAM,CAAC,CAAC,UAAU,EAAE,EAAE,CAAC,UAAU,KAAK,IAAI,CAAC,IAAI,CAAC,EAAE,CAAC;SACzE,CAAC,CAAC;QACH,IAAI,WAAW,CAAC,SAAS,EAAE,IAAI,CAAC,SAAS,CAAC;YAAE,OAAO,IAAI,CAAC;QACxD,OAAO;YACN,GAAG,IAAI;YACP,SAAS;YACT,KAAK,EAAE;gBACN,GAAG,IAAI,CAAC,KAAK;gBACb,SAAS;aACT;SACD,CAAC;IAAA,CACF,CAAC,CAAC;AAAA,CACH;AAED,SAAS,wBAAwB,CAAC,IAAkB,EAAW;IAC9D,IAAI,CAAC,qBAAqB,CAAC,IAAI,CAAC,IAAI,CAAC,IAAI,CAAC;QAAE,OAAO,KAAK,CAAC;IACzD,OAAO,CAAC,IAAI,CAAC,IAAI,CAAC,SAAS,IAAI,EAAE,CAAC,CAAC,IAAI,CAAC,aAAa,CAAC,CAAC;AAAA,CACvD;AAED,SAAS,qBAAqB,CAAC,IAA+B,EAAW;IACxE,OAAO,IAAI,KAAK,QAAQ,IAAI,IAAI,KAAK,WAAW,IAAI,IAAI,KAAK,UAAU,CAAC;AAAA,CACxE;AAED,SAAS,aAAa,CAAC,IAAY,EAAW;IAC7C,MAAM,UAAU,GAAG,aAAa,CAAC,IAAI,CAAC,CAAC;IACvC,OAAO,UAAU,KAAK,WAAW,IAAI,UAAU,CAAC,UAAU,CAAC,YAAY,CAAC,IAAI,UAAU,CAAC,QAAQ,CAAC,aAAa,CAAC,CAAC;AAAA,CAC/G;AAED,SAAS,qBAAqB,CAC7B,KAA8B,EAC9B,gBAAoC,EACpC,QAAkB,EACQ;IAC1B,MAAM,SAAS,GAAG,IAAI,GAAG,EAAU,CAAC;IACpC,MAAM,OAAO,GAA4B,EAAE,CAAC;IAE5C,OAAO,SAAS,CAAC,IAAI,GAAG,KAAK,CAAC,MAAM,EAAE,CAAC;QACtC,MAAM,KAAK,GAAG,KAAK,CAAC,MAAM,CACzB,CAAC,IAAI,EAAE,EAAE,CAAC,CAAC,SAAS,CAAC,GAAG,CAAC,IAAI,CAAC,IAAI,CAAC,EAAE,CAAC,IAAI,IAAI,CAAC,SAAS,CAAC,KAAK,CAAC,CAAC,UAAU,EAAE,EAAE,CAAC,SAAS,CAAC,GAAG,CAAC,UAAU,CAAC,CAAC,CACzG,CAAC;QACF,IAAI,KAAK,CAAC,MAAM,KAAK,CAAC,EAAE,CAAC;YACxB,MAAM,SAAS,GAAG,KAAK,CAAC,MAAM,CAAC,CAAC,IAAI,EAAE,EAAE,CAAC,CAAC,SAAS,CAAC,GAAG,CAAC,IAAI,CAAC,IAAI,CAAC,EAAE,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC,IAAI,EAAE,EAAE,CAAC,IAAI,CAAC,IAAI,CAAC,EAAE,CAAC,CAAC;YACnG,QAAQ,CAAC,IAAI,CAAC,0DAA0D,SAAS,CAAC,IAAI,CAAC,IAAI,CAAC,EAAE,CAAC,CAAC;YAChG,MAAM;QACP,CAAC;QAED,MAAM,UAAU,GAAG,KAAK,CAAC,IAAI,CAAC,CAAC,IAAI,EAAE,EAAE,CAAC,CAAC,IAAI,CAAC,KAAK,CAAC,SAAS,CAAC,cAAc,CAAC,CAAC;QAC9E,IAAI,UAAU,EAAE,CAAC;YAChB,OAAO,CAAC,IAAI,CAAC;gBACZ,KAAK,EAAE,OAAO,CAAC,MAAM;gBACrB,OAAO,EAAE,CAAC,UAAU,CAAC,IAAI,CAAC,EAAE,CAAC;gBAC7B,MAAM,EAAE,mBAAmB;aAC3B,CAAC,CAAC;YACH,SAAS,CAAC,GAAG,CAAC,UAAU,CAAC,IAAI,CAAC,EAAE,CAAC,CAAC;YAClC,SAAS;QACV,CAAC;QAED,MAAM,QAAQ,GAAmB,EAAE,CAAC;QACpC,KAAK,MAAM,IAAI,IAAI,KAAK,EAAE,CAAC;YAC1B,IAAI,gBAAgB,KAAK,SAAS,IAAI,QAAQ,CAAC,MAAM,IAAI,gBAAgB;gBAAE,MAAM;YACjF,IAAI,CAAC,QAAQ,CAAC,IAAI,CAAC,CAAC,YAAY,EAAE,EAAE,CAAC,aAAa,CAAC,YAAY,EAAE,IAAI,CAAC,CAAC,EAAE,CAAC;gBACzE,QAAQ,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;YACrB,CAAC;QACF,CAAC;QACD,MAAM,UAAU,GAAG,QAAQ,CAAC,MAAM,GAAG,CAAC,CAAC,CAAC,CAAC,QAAQ,CAAC,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,CAAC;QAC/D,KAAK,MAAM,IAAI,IAAI,UAAU;YAAE,SAAS,CAAC,GAAG,CAAC,IAAI,CAAC,IAAI,CAAC,EAAE,CAAC,CAAC;QAC3D,OAAO,CAAC,IAAI,CAAC;YACZ,KAAK,EAAE,OAAO,CAAC,MAAM;YACrB,OAAO,EAAE,UAAU,CAAC,GAAG,CAAC,CAAC,IAAI,EAAE,EAAE,CAAC,IAAI,CAAC,IAAI,CAAC,EAAE,CAAC;YAC/C,MAAM,EACL,gBAAgB,KAAK,SAAS,IAAI,KAAK,CAAC,MAAM,GAAG,UAAU,CAAC,MAAM,CAAC,CAAC,CAAC,gBAAgB,CAAC,CAAC,CAAC,gBAAgB;SACzG,CAAC,CAAC;IACJ,CAAC;IAED,OAAO,OAAO,CAAC;AAAA,CACf;AAED,SAAS,aAAa,CAAC,IAAkB,EAAE,KAAmB,EAAW;IACxE,OAAO,CACN,aAAa,CACZ,IAAI,CAAC,KAAK,CAAC,SAAS,CAAC,QAAQ,CAAC,GAAG,CAAC,CAAC,KAAK,EAAE,EAAE,CAAC,KAAK,CAAC,IAAI,CAAC,EACxD;QACC,GAAG,KAAK,CAAC,KAAK,CAAC,SAAS,CAAC,OAAO,CAAC,GAAG,CAAC,CAAC,KAAK,EAAE,EAAE,CAAC,KAAK,CAAC,IAAI,CAAC;QAC3D,GAAG,KAAK,CAAC,KAAK,CAAC,SAAS,CAAC,QAAQ,CAAC,GAAG,CAAC,CAAC,KAAK,EAAE,EAAE,CAAC,KAAK,CAAC,IAAI,CAAC;KAC5D,CACD;QACD,aAAa,CACZ,KAAK,CAAC,KAAK,CAAC,SAAS,CAAC,QAAQ,CAAC,GAAG,CAAC,CAAC,KAAK,EAAE,EAAE,CAAC,KAAK,CAAC,IAAI,CAAC,EACzD;YACC,GAAG,IAAI,CAAC,KAAK,CAAC,SAAS,CAAC,OAAO,CAAC,GAAG,CAAC,CAAC,KAAK,EAAE,EAAE,CAAC,KAAK,CAAC,IAAI,CAAC;YAC1D,GAAG,IAAI,CAAC,KAAK,CAAC,SAAS,CAAC,QAAQ,CAAC,GAAG,CAAC,CAAC,KAAK,EAAE,EAAE,CAAC,KAAK,CAAC,IAAI,CAAC;SAC3D,CACD,CACD,CAAC;AAAA,CACF;AAED,SAAS,aAAa,CAAC,OAA0B,EAAE,UAA6B,EAAW;IAC1F,KAAK,MAAM,MAAM,IAAI,OAAO,EAAE,CAAC;QAC9B,KAAK,MAAM,SAAS,IAAI,UAAU,EAAE,CAAC;YACpC,IAAI,cAAc,CAAC,MAAM,EAAE,SAAS,CAAC;gBAAE,OAAO,IAAI,CAAC;QACpD,CAAC;IACF,CAAC;IACD,OAAO,KAAK,CAAC;AAAA,CACb;AAED,SAAS,cAAc,CAAC,IAAY,EAAE,KAAa,EAAW;IAC7D,MAAM,cAAc,GAAG,aAAa,CAAC,IAAI,CAAC,CAAC;IAC3C,MAAM,eAAe,GAAG,aAAa,CAAC,KAAK,CAAC,CAAC;IAC7C,OAAO,CACN,cAAc,KAAK,eAAe;QAClC,cAAc,CAAC,UAAU,CAAC,GAAG,eAAe,GAAG,CAAC;QAChD,eAAe,CAAC,UAAU,CAAC,GAAG,cAAc,GAAG,CAAC,CAChD,CAAC;AAAA,CACF;AAED,SAAS,kBAAkB,CAC1B,KAA8B,EAC9B,OAAyC,EACjB;IACxB,MAAM,SAAS,GAAG,KAAK,CAAC,MAAM,CAAC;IAC/B,MAAM,SAAS,GAAG,KAAK,CAAC,MAAM,CAAC,CAAC,GAAG,EAAE,IAAI,EAAE,EAAE,CAAC,GAAG,GAAG,IAAI,CAAC,SAAS,CAAC,MAAM,EAAE,CAAC,CAAC,CAAC;IAC9E,MAAM,KAAK,GAAG,OAAO,CAAC,MAAM,CAAC,CAAC,GAAG,EAAE,KAAK,EAAE,EAAE,CAAC,IAAI,CAAC,GAAG,CAAC,GAAG,EAAE,KAAK,CAAC,OAAO,CAAC,MAAM,CAAC,EAAE,CAAC,CAAC,CAAC;IACrF,MAAM,aAAa,GAAG,OAAO,CAAC,MAAM,CAAC;IACrC,MAAM,cAAc,GAAG,KAAK,CAAC,MAAM,CAAC,CAAC,IAAI,EAAE,EAAE,CAAC,IAAI,CAAC,KAAK,CAAC,SAAS,CAAC,cAAc,CAAC,CAAC,MAAM,CAAC;IAC1F,MAAM,aAAa,GAAG,SAAS,KAAK,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,cAAc,GAAG,SAAS,CAAC;IACvE,MAAM,eAAe,GAAG,SAAS,IAAI,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,SAAS,GAAG,CAAC,SAAS,GAAG,CAAC,SAAS,GAAG,CAAC,CAAC,CAAC,CAAC;IACvF,MAAM,QAAQ,GAAG,cAAc,CAAC,KAAK,EAAE,OAAO,EAAE,KAAK,EAAE,aAAa,EAAE,SAAS,CAAC,CAAC;IAEjF,OAAO;QACN,QAAQ;QACR,KAAK;QACL,aAAa;QACb,eAAe,EAAE,KAAK,CAAC,eAAe,CAAC;QACvC,aAAa,EAAE,KAAK,CAAC,aAAa,CAAC;QACnC,SAAS;QACT,SAAS;KACT,CAAC;AAAA,CACF;AAED,SAAS,cAAc,CACtB,KAA8B,EAC9B,OAAyC,EACzC,KAAa,EACb,aAAqB,EACrB,SAAiB,EACW;IAC5B,IAAI,KAAK,CAAC,MAAM,IAAI,CAAC,IAAI,KAAK,IAAI,CAAC;QAAE,OAAO,QAAQ,CAAC;IACrD,IAAI,SAAS,KAAK,CAAC,IAAI,aAAa,KAAK,CAAC;QAAE,OAAO,UAAU,CAAC;IAC9D,IAAI,gBAAgB,CAAC,KAAK,EAAE,OAAO,CAAC;QAAE,OAAO,YAAY,CAAC;IAC1D,OAAO,QAAQ,CAAC;AAAA,CAChB;AAED,SAAS,gBAAgB,CAAC,KAA8B,EAAE,OAAyC,EAAW;IAC7G,IAAI,OAAO,CAAC,MAAM,GAAG,CAAC;QAAE,OAAO,KAAK,CAAC;IACrC,MAAM,UAAU,GAAG,OAAO,CAAC,CAAC,CAAC,CAAC;IAC9B,MAAM,UAAU,GAAG,OAAO,CAAC,OAAO,CAAC,MAAM,GAAG,CAAC,CAAC,CAAC;IAC/C,IAAI,UAAU,CAAC,OAAO,CAAC,MAAM,GAAG,CAAC,IAAI,UAAU,CAAC,OAAO,CAAC,MAAM,KAAK,CAAC;QAAE,OAAO,KAAK,CAAC;IACnF,MAAM,SAAS,GAAG,KAAK,CAAC,IAAI,CAAC,CAAC,IAAI,EAAE,EAAE,CAAC,IAAI,CAAC,IAAI,CAAC,EAAE,KAAK,UAAU,CAAC,OAAO,CAAC,CAAC,CAAC,CAAC,CAAC;IAC/E,IAAI,CAAC,SAAS;QAAE,OAAO,KAAK,CAAC;IAC7B,OAAO,UAAU,CAAC,OAAO,CAAC,KAAK,CAAC,CAAC,MAAM,EAAE,EAAE,CAAC,SAAS,CAAC,SAAS,CAAC,QAAQ,CAAC,MAAM,CAAC,CAAC,CAAC;AAAA,CAClF;AAED,SAAS,aAAa,CAAC,IAAY,EAAU;IAC5C,OAAO,IAAI,CAAC,UAAU,CAAC,IAAI,EAAE,GAAG,CAAC,CAAC,OAAO,CAAC,OAAO,EAAE,EAAE,CAAC,CAAC;AAAA,CACvD;AAED,SAAS,KAAK,CAAC,KAAa,EAAU;IACrC,OAAO,IAAI,CAAC,KAAK,CAAC,KAAK,GAAG,IAAI,CAAC,GAAG,IAAI,CAAC;AAAA,CACvC;AAED,SAAS,YAAY,CAAC,MAAyB,EAAY;IAC1D,OAAO,CAAC,GAAG,IAAI,GAAG,CAAC,MAAM,CAAC,CAAC;SACzB,GAAG,CAAC,CAAC,KAAK,EAAE,EAAE,CAAC,KAAK,CAAC,IAAI,EAAE,CAAC;SAC5B,MAAM,CAAC,CAAC,KAAK,EAAE,EAAE,CAAC,KAAK,KAAK,EAAE,CAAC;SAC/B,IAAI,EAAE,CAAC;AAAA,CACT;AAED,SAAS,WAAW,CAAC,IAAuB,EAAE,KAAwB,EAAW;IAChF,OAAO,IAAI,CAAC,MAAM,KAAK,KAAK,CAAC,MAAM,IAAI,IAAI,CAAC,KAAK,CAAC,CAAC,KAAK,EAAE,KAAK,EAAE,EAAE,CAAC,KAAK,KAAK,KAAK,CAAC,KAAK,CAAC,CAAC,CAAC;AAAA,CAC5F","sourcesContent":["import {\n\tbuildSubagentLaneGrant,\n\ttype LaneContextInheritanceMode,\n\ttype LaneEvidenceGate,\n\ttype LaneSpawnReceipt,\n\ttype SubagentLaneGrant,\n} from \"./loadout-runtime.ts\";\nimport {\n\tapplyLoadoutProfile,\n\tBUILTIN_LOADOUTS,\n\ttype CapabilityInventory,\n\tderiveSchedulerFields,\n\ttype LoadoutAuthority,\n\ttype LoadoutProfile,\n\ttype LoadoutRole,\n} from \"./loadouts.ts\";\n\nexport type SubagentOrchestrationRole =\n\t| \"planner\"\n\t| \"architect\"\n\t| \"executor\"\n\t| \"critic\"\n\t| \"visual-qa\"\n\t| \"rhwp-doc\"\n\t| \"security\"\n\t| \"package-maintainer\";\n\nexport type SubagentSchedulerTopology = \"serial\" | \"parallel\" | \"map-reduce\" | \"hybrid\";\n\nexport interface SubagentRoleAssignment {\n\treadonly role: SubagentOrchestrationRole;\n\treadonly loadoutRole: LoadoutRole;\n\treadonly loadoutName: string;\n\treadonly agentName: string;\n\treadonly contextInheritance: LaneContextInheritanceMode;\n\treadonly evidenceGates: readonly LaneEvidenceGate[];\n\treadonly writesProductFiles: boolean;\n}\n\nexport interface SubagentLaneSpec {\n\treadonly id: string;\n\treadonly role: SubagentOrchestrationRole;\n\treadonly task: string;\n\treadonly dependsOn?: readonly string[];\n\treadonly readScope?: readonly string[];\n\treadonly writeScope?: readonly string[];\n\treadonly acceptance?: readonly string[];\n\treadonly evidenceOutput?: string;\n\treadonly blockedPaths?: readonly string[];\n\treadonly contextInheritance?: LaneContextInheritanceMode;\n\treadonly grantAuthority?: LoadoutAuthority;\n\treadonly loadoutName?: string;\n\treadonly agentName?: string;\n}\n\nexport interface SpawnGateDecision {\n\treadonly outcome: \"allowed\" | \"rejected\";\n\treadonly reason: string;\n\treadonly planRequired: boolean;\n\treadonly missingFields: readonly string[];\n}\n\nexport interface SubagentScheduleBatch {\n\treadonly index: number;\n\treadonly laneIds: readonly string[];\n\treadonly reason: \"ready-parallel\" | \"serialized-writer\" | \"parallel-limit\";\n}\n\nexport interface SubagentRouteFeatures {\n\treadonly topology: SubagentSchedulerTopology;\n\treadonly width: number;\n\treadonly criticalDepth: number;\n\treadonly couplingDensity: number;\n\treadonly parallelRatio: number;\n\treadonly nodeCount: number;\n\treadonly edgeCount: number;\n}\n\nexport interface BuildSubagentOrchestrationPlanInput {\n\treadonly runId: string;\n\treadonly lanes: readonly SubagentLaneSpec[];\n\treadonly inventory: CapabilityInventory;\n\treadonly spawnPlan?: LaneSpawnReceipt;\n\treadonly spawnThreshold?: number;\n\treadonly maxParallelLanes?: number;\n}\n\nexport interface SubagentOrchestrationPlan {\n\treadonly laneGrants: readonly SubagentLaneGrant[];\n\treadonly batches: readonly SubagentScheduleBatch[];\n\treadonly route: SubagentRouteFeatures;\n\treadonly spawnGate: SpawnGateDecision;\n\treadonly blockers: readonly string[];\n\treadonly warnings: readonly string[];\n}\n\nconst DEFAULT_SPAWN_THRESHOLD = 4;\n\nconst ROLE_ASSIGNMENTS: Readonly<Record<SubagentOrchestrationRole, SubagentRoleAssignment>> = {\n\tplanner: {\n\t\trole: \"planner\",\n\t\tloadoutRole: \"planner\",\n\t\tloadoutName: \"plan\",\n\t\tagentName: \"omk-planner\",\n\t\tcontextInheritance: \"receipt\",\n\t\tevidenceGates: [\"plan-reread\", \"cleanup\"],\n\t\twritesProductFiles: false,\n\t},\n\tarchitect: {\n\t\trole: \"architect\",\n\t\tloadoutRole: \"architect\",\n\t\tloadoutName: \"architect\",\n\t\tagentName: \"omk-architect\",\n\t\tcontextInheritance: \"bounded\",\n\t\tevidenceGates: [\"plan-reread\", \"automated-verification\", \"adversarial-qa\", \"cleanup\"],\n\t\twritesProductFiles: false,\n\t},\n\texecutor: {\n\t\trole: \"executor\",\n\t\tloadoutRole: \"executor\",\n\t\tloadoutName: \"executor\",\n\t\tagentName: \"omk-executor\",\n\t\tcontextInheritance: \"bounded\",\n\t\tevidenceGates: [\"plan-reread\", \"automated-verification\", \"manual-qa\", \"adversarial-qa\", \"cleanup\"],\n\t\twritesProductFiles: true,\n\t},\n\tcritic: {\n\t\trole: \"critic\",\n\t\tloadoutRole: \"critic\",\n\t\tloadoutName: \"critic\",\n\t\tagentName: \"omk-critic\",\n\t\tcontextInheritance: \"receipt\",\n\t\tevidenceGates: [\"plan-reread\", \"adversarial-qa\", \"cleanup\"],\n\t\twritesProductFiles: false,\n\t},\n\t\"visual-qa\": {\n\t\trole: \"visual-qa\",\n\t\tloadoutRole: \"visual-qa\",\n\t\tloadoutName: \"visual-qa\",\n\t\tagentName: \"omk-visual-qa\",\n\t\tcontextInheritance: \"receipt\",\n\t\tevidenceGates: [\"plan-reread\", \"automated-verification\", \"manual-qa\", \"adversarial-qa\", \"cleanup\"],\n\t\twritesProductFiles: false,\n\t},\n\t\"rhwp-doc\": {\n\t\trole: \"rhwp-doc\",\n\t\tloadoutRole: \"rhwp-doc\",\n\t\tloadoutName: \"rhwp-doc\",\n\t\tagentName: \"omk-rhwp-doc\",\n\t\tcontextInheritance: \"bounded\",\n\t\tevidenceGates: [\"plan-reread\", \"automated-verification\", \"manual-qa\", \"adversarial-qa\", \"cleanup\"],\n\t\twritesProductFiles: true,\n\t},\n\tsecurity: {\n\t\trole: \"security\",\n\t\tloadoutRole: \"security\",\n\t\tloadoutName: \"security\",\n\t\tagentName: \"omk-security\",\n\t\tcontextInheritance: \"none\",\n\t\tevidenceGates: [\"plan-reread\", \"automated-verification\", \"adversarial-qa\", \"cleanup\"],\n\t\twritesProductFiles: false,\n\t},\n\t\"package-maintainer\": {\n\t\trole: \"package-maintainer\",\n\t\tloadoutRole: \"package-maintainer\",\n\t\tloadoutName: \"package-maintainer\",\n\t\tagentName: \"omk-package-maintainer\",\n\t\tcontextInheritance: \"bounded\",\n\t\tevidenceGates: [\"plan-reread\", \"automated-verification\", \"manual-qa\", \"adversarial-qa\", \"cleanup\"],\n\t\twritesProductFiles: true,\n\t},\n};\n\nconst REQUIRED_SPAWN_PLAN_STRING_FIELDS = [\n\t\"whyParallel\",\n\t\"whyNotLocal\",\n\t\"independence\",\n\t\"expectedReceiptShape\",\n] as const;\n\ninterface PreparedLane {\n\treadonly index: number;\n\treadonly spec: SubagentLaneSpec;\n\treadonly grant: SubagentLaneGrant;\n\treadonly dependsOn: readonly string[];\n}\n\nexport function resolveSubagentRoleAssignment(role: SubagentOrchestrationRole): SubagentRoleAssignment {\n\treturn ROLE_ASSIGNMENTS[role];\n}\n\nexport function buildSubagentOrchestrationPlan(input: BuildSubagentOrchestrationPlanInput): SubagentOrchestrationPlan {\n\tif (\n\t\tinput.maxParallelLanes !== undefined &&\n\t\t(!Number.isInteger(input.maxParallelLanes) || input.maxParallelLanes < 1)\n\t) {\n\t\tthrow new RangeError(\"maxParallelLanes must be a positive integer\");\n\t}\n\n\tconst blockers: string[] = [];\n\tconst warnings: string[] = [];\n\tblockers.push(...validateLaneIntake(input.lanes));\n\tconst spawnGate = evaluateSpawnGate({\n\t\tchildCount: input.lanes.length,\n\t\tplan: input.spawnPlan,\n\t\tthreshold: input.spawnThreshold ?? DEFAULT_SPAWN_THRESHOLD,\n\t});\n\tif (spawnGate.outcome === \"rejected\") blockers.push(spawnGate.reason);\n\n\tconst prepared = input.lanes.map((lane, index) =>\n\t\tprepareLane(lane, index, input.runId, input.inventory, input.spawnPlan, blockers, warnings),\n\t);\n\tblockers.push(...findDependencyBlockers(prepared));\n\n\tconst scheduledLanes = applyReceiptConsumerDependencies(prepared);\n\tconst batches = schedulePreparedLanes(scheduledLanes, input.maxParallelLanes, blockers);\n\tconst route = buildRouteFeatures(scheduledLanes, batches);\n\n\treturn {\n\t\tlaneGrants: scheduledLanes.map((lane) => lane.grant),\n\t\tbatches,\n\t\troute,\n\t\tspawnGate,\n\t\tblockers: uniqueSorted(blockers),\n\t\twarnings: uniqueSorted(warnings),\n\t};\n}\n\nexport function evaluateSpawnGate(request: {\n\treadonly childCount: number;\n\treadonly plan?: LaneSpawnReceipt;\n\treadonly threshold?: number;\n}): SpawnGateDecision {\n\tconst threshold = request.threshold ?? DEFAULT_SPAWN_THRESHOLD;\n\tif (!Number.isInteger(request.childCount) || request.childCount < 0) {\n\t\tthrow new RangeError(\"childCount must be a non-negative integer\");\n\t}\n\tif (!Number.isInteger(threshold) || threshold < 1) {\n\t\tthrow new RangeError(\"threshold must be a positive integer\");\n\t}\n\n\tconst planRequired = request.childCount > threshold;\n\tif (!planRequired) {\n\t\treturn {\n\t\t\toutcome: \"allowed\",\n\t\t\treason: `batch of ${request.childCount} is at or below threshold ${threshold}`,\n\t\t\tplanRequired: false,\n\t\t\tmissingFields: [],\n\t\t};\n\t}\n\n\tconst missingFields = findMissingSpawnPlanFields(request.plan);\n\tif (missingFields.length > 0) {\n\t\treturn {\n\t\t\toutcome: \"rejected\",\n\t\t\treason: `batch of ${request.childCount} exceeds threshold ${threshold} and the spawn-plan receipt is ${\n\t\t\t\trequest.plan ? `incomplete (${missingFields.join(\", \")})` : \"missing\"\n\t\t\t}`,\n\t\t\tplanRequired: true,\n\t\t\tmissingFields,\n\t\t};\n\t}\n\n\treturn {\n\t\toutcome: \"allowed\",\n\t\treason: `batch of ${request.childCount} exceeds threshold ${threshold} and a complete spawn-plan receipt was provided`,\n\t\tplanRequired: true,\n\t\tmissingFields: [],\n\t};\n}\n\nexport function findMissingSpawnPlanFields(plan: LaneSpawnReceipt | undefined): string[] {\n\tif (!plan) return [...REQUIRED_SPAWN_PLAN_STRING_FIELDS, \"maxInlineTokens\"];\n\tconst missing: string[] = [];\n\tfor (const field of REQUIRED_SPAWN_PLAN_STRING_FIELDS) {\n\t\tconst value = plan[field];\n\t\tif (value.trim().length === 0) missing.push(field);\n\t}\n\tif (!Number.isFinite(plan.maxInlineTokens) || plan.maxInlineTokens <= 0) {\n\t\tmissing.push(\"maxInlineTokens\");\n\t}\n\treturn missing;\n}\n\nfunction validateLaneIntake(lanes: readonly SubagentLaneSpec[]): string[] {\n\tconst blockers: string[] = [];\n\tconst seenIds = new Map<string, number>();\n\n\tfor (const [index, lane] of lanes.entries()) {\n\t\tconst id = lane.id.trim();\n\t\tconst label = id === \"\" ? `lane at index ${index}` : `lane ${id}`;\n\t\tif (id === \"\") {\n\t\t\tblockers.push(`lane at index ${index} has empty id`);\n\t\t} else {\n\t\t\tconst firstIndex = seenIds.get(id);\n\t\t\tif (firstIndex === undefined) {\n\t\t\t\tseenIds.set(id, index);\n\t\t\t} else {\n\t\t\t\tblockers.push(`duplicate lane id ${id} at indexes ${firstIndex} and ${index}`);\n\t\t\t}\n\t\t}\n\n\t\tif (lane.task.trim() === \"\") {\n\t\t\tblockers.push(`${label} has empty task`);\n\t\t}\n\n\t\tconst seenDependencies = new Set<string>();\n\t\tfor (const dependency of lane.dependsOn ?? []) {\n\t\t\tconst dependencyId = dependency.trim();\n\t\t\tif (dependencyId === \"\") {\n\t\t\t\tblockers.push(`${label} has empty dependency id`);\n\t\t\t\tcontinue;\n\t\t\t}\n\t\t\tif (dependencyId === id) {\n\t\t\t\tblockers.push(`${label} depends on itself`);\n\t\t\t}\n\t\t\tif (seenDependencies.has(dependencyId)) {\n\t\t\t\tblockers.push(`${label} repeats dependency ${dependencyId}`);\n\t\t\t}\n\t\t\tseenDependencies.add(dependencyId);\n\t\t}\n\t}\n\n\treturn blockers;\n}\n\nfunction prepareLane(\n\tspec: SubagentLaneSpec,\n\tindex: number,\n\trunId: string,\n\tinventory: CapabilityInventory,\n\tspawnReceipt: LaneSpawnReceipt | undefined,\n\tblockers: string[],\n\twarnings: string[],\n): PreparedLane {\n\tconst assignment = resolveSubagentRoleAssignment(spec.role);\n\tif ((spec.writeScope?.length ?? 0) > 0 && !assignment.writesProductFiles) {\n\t\tblockers.push(`lane ${spec.id} role ${spec.role} cannot write product files`);\n\t}\n\tconst dependsOn = uniqueSorted(spec.dependsOn ?? []);\n\n\tconst profile = resolveLoadoutProfile(spec, assignment, blockers);\n\tconst applied = applyLoadoutProfile(profile, inventory, { grantAuthority: spec.grantAuthority });\n\tblockers.push(...applied.blockers.map((blocker) => `lane ${spec.id}: ${blocker}`));\n\twarnings.push(...applied.warnings.map((warning) => `lane ${spec.id}: ${warning}`));\n\n\tconst schedulerFields = deriveSchedulerFields({\n\t\trole: assignment.loadoutRole,\n\t\tassignedReadPaths: spec.readScope,\n\t\tassignedWritePaths: spec.writeScope,\n\t});\n\n\tconst grant = buildSubagentLaneGrant(spec.id, assignment.loadoutRole, spec.task, applied, schedulerFields, {\n\t\tallowedReadPaths: spec.readScope,\n\t\tallowedWritePaths: spec.writeScope,\n\t\tblockedPaths: spec.blockedPaths,\n\t\tevidenceOutputPattern: spec.evidenceOutput ?? profile.evidence?.outputPattern,\n\t\trunId,\n\t\tprofile,\n\t\tagentName: spec.agentName ?? assignment.agentName,\n\t\tcontextInheritance: spec.contextInheritance ?? assignment.contextInheritance,\n\t\tspawnReceipt,\n\t\tevidenceGates: assignment.evidenceGates,\n\t\tdependsOn,\n\t\tacceptance: spec.acceptance,\n\t});\n\n\treturn { index, spec, grant, dependsOn };\n}\n\nfunction resolveLoadoutProfile(\n\tspec: SubagentLaneSpec,\n\tassignment: SubagentRoleAssignment,\n\tblockers: string[],\n): LoadoutProfile {\n\tconst loadoutName = spec.loadoutName ?? assignment.loadoutName;\n\tconst profile = BUILTIN_LOADOUTS[loadoutName];\n\tif (profile) return profile;\n\tblockers.push(`lane ${spec.id}: unknown loadout ${loadoutName}`);\n\treturn BUILTIN_LOADOUTS.none;\n}\n\nfunction findDependencyBlockers(lanes: readonly PreparedLane[]): string[] {\n\tconst ids = new Set(lanes.map((lane) => lane.spec.id));\n\tconst blockers: string[] = [];\n\tfor (const lane of lanes) {\n\t\tfor (const dependency of lane.dependsOn) {\n\t\t\tif (!ids.has(dependency)) {\n\t\t\t\tblockers.push(`lane ${lane.spec.id} depends on missing lane ${dependency}`);\n\t\t\t}\n\t\t}\n\t}\n\treturn blockers;\n}\n\nfunction applyReceiptConsumerDependencies(lanes: readonly PreparedLane[]): PreparedLane[] {\n\tconst receiptProducerIds = lanes\n\t\t.filter((lane) => lane.grant.evidenceOutput !== undefined && !isReceiptConsumerRole(lane.spec.role))\n\t\t.map((lane) => lane.spec.id);\n\n\treturn lanes.map((lane) => {\n\t\tif (!isReceiptReadingConsumer(lane) || receiptProducerIds.length === 0) return lane;\n\t\tconst dependsOn = uniqueSorted([\n\t\t\t...lane.dependsOn,\n\t\t\t...receiptProducerIds.filter((producerId) => producerId !== lane.spec.id),\n\t\t]);\n\t\tif (arrayEquals(dependsOn, lane.dependsOn)) return lane;\n\t\treturn {\n\t\t\t...lane,\n\t\t\tdependsOn,\n\t\t\tgrant: {\n\t\t\t\t...lane.grant,\n\t\t\t\tdependsOn,\n\t\t\t},\n\t\t};\n\t});\n}\n\nfunction isReceiptReadingConsumer(lane: PreparedLane): boolean {\n\tif (!isReceiptConsumerRole(lane.spec.role)) return false;\n\treturn (lane.spec.readScope ?? []).some(isReceiptPath);\n}\n\nfunction isReceiptConsumerRole(role: SubagentOrchestrationRole): boolean {\n\treturn role === \"critic\" || role === \"visual-qa\" || role === \"rhwp-doc\";\n}\n\nfunction isReceiptPath(path: string): boolean {\n\tconst normalized = normalizePath(path);\n\treturn normalized === \".omk/runs\" || normalized.startsWith(\".omk/runs/\") || normalized.includes(\"/.omk/runs/\");\n}\n\nfunction schedulePreparedLanes(\n\tlanes: readonly PreparedLane[],\n\tmaxParallelLanes: number | undefined,\n\tblockers: string[],\n): SubagentScheduleBatch[] {\n\tconst scheduled = new Set<string>();\n\tconst batches: SubagentScheduleBatch[] = [];\n\n\twhile (scheduled.size < lanes.length) {\n\t\tconst ready = lanes.filter(\n\t\t\t(lane) => !scheduled.has(lane.spec.id) && lane.dependsOn.every((dependency) => scheduled.has(dependency)),\n\t\t);\n\t\tif (ready.length === 0) {\n\t\t\tconst remaining = lanes.filter((lane) => !scheduled.has(lane.spec.id)).map((lane) => lane.spec.id);\n\t\t\tblockers.push(`lane dependency cycle or unsatisfied dependency among: ${remaining.join(\", \")}`);\n\t\t\tbreak;\n\t\t}\n\n\t\tconst serialized = ready.find((lane) => !lane.grant.scheduler.parallelizable);\n\t\tif (serialized) {\n\t\t\tbatches.push({\n\t\t\t\tindex: batches.length,\n\t\t\t\tlaneIds: [serialized.spec.id],\n\t\t\t\treason: \"serialized-writer\",\n\t\t\t});\n\t\t\tscheduled.add(serialized.spec.id);\n\t\t\tcontinue;\n\t\t}\n\n\t\tconst selected: PreparedLane[] = [];\n\t\tfor (const lane of ready) {\n\t\t\tif (maxParallelLanes !== undefined && selected.length >= maxParallelLanes) break;\n\t\t\tif (!selected.some((selectedLane) => lanesConflict(selectedLane, lane))) {\n\t\t\t\tselected.push(lane);\n\t\t\t}\n\t\t}\n\t\tconst batchLanes = selected.length > 0 ? selected : [ready[0]];\n\t\tfor (const lane of batchLanes) scheduled.add(lane.spec.id);\n\t\tbatches.push({\n\t\t\tindex: batches.length,\n\t\t\tlaneIds: batchLanes.map((lane) => lane.spec.id),\n\t\t\treason:\n\t\t\t\tmaxParallelLanes !== undefined && ready.length > batchLanes.length ? \"parallel-limit\" : \"ready-parallel\",\n\t\t});\n\t}\n\n\treturn batches;\n}\n\nfunction lanesConflict(left: PreparedLane, right: PreparedLane): boolean {\n\treturn (\n\t\tpathsConflict(\n\t\t\tleft.grant.scheduler.writeSet.map((entry) => entry.path),\n\t\t\t[\n\t\t\t\t...right.grant.scheduler.readSet.map((entry) => entry.path),\n\t\t\t\t...right.grant.scheduler.writeSet.map((entry) => entry.path),\n\t\t\t],\n\t\t) ||\n\t\tpathsConflict(\n\t\t\tright.grant.scheduler.writeSet.map((entry) => entry.path),\n\t\t\t[\n\t\t\t\t...left.grant.scheduler.readSet.map((entry) => entry.path),\n\t\t\t\t...left.grant.scheduler.writeSet.map((entry) => entry.path),\n\t\t\t],\n\t\t)\n\t);\n}\n\nfunction pathsConflict(writers: readonly string[], candidates: readonly string[]): boolean {\n\tfor (const writer of writers) {\n\t\tfor (const candidate of candidates) {\n\t\t\tif (pathIntersects(writer, candidate)) return true;\n\t\t}\n\t}\n\treturn false;\n}\n\nfunction pathIntersects(left: string, right: string): boolean {\n\tconst normalizedLeft = normalizePath(left);\n\tconst normalizedRight = normalizePath(right);\n\treturn (\n\t\tnormalizedLeft === normalizedRight ||\n\t\tnormalizedLeft.startsWith(`${normalizedRight}/`) ||\n\t\tnormalizedRight.startsWith(`${normalizedLeft}/`)\n\t);\n}\n\nfunction buildRouteFeatures(\n\tlanes: readonly PreparedLane[],\n\tbatches: readonly SubagentScheduleBatch[],\n): SubagentRouteFeatures {\n\tconst nodeCount = lanes.length;\n\tconst edgeCount = lanes.reduce((sum, lane) => sum + lane.dependsOn.length, 0);\n\tconst width = batches.reduce((max, batch) => Math.max(max, batch.laneIds.length), 0);\n\tconst criticalDepth = batches.length;\n\tconst parallelizable = lanes.filter((lane) => lane.grant.scheduler.parallelizable).length;\n\tconst parallelRatio = nodeCount === 0 ? 1 : parallelizable / nodeCount;\n\tconst couplingDensity = nodeCount <= 1 ? 0 : edgeCount / (nodeCount * (nodeCount - 1));\n\tconst topology = selectTopology(lanes, batches, width, criticalDepth, edgeCount);\n\n\treturn {\n\t\ttopology,\n\t\twidth,\n\t\tcriticalDepth,\n\t\tcouplingDensity: round(couplingDensity),\n\t\tparallelRatio: round(parallelRatio),\n\t\tnodeCount,\n\t\tedgeCount,\n\t};\n}\n\nfunction selectTopology(\n\tlanes: readonly PreparedLane[],\n\tbatches: readonly SubagentScheduleBatch[],\n\twidth: number,\n\tcriticalDepth: number,\n\tedgeCount: number,\n): SubagentSchedulerTopology {\n\tif (lanes.length <= 1 || width <= 1) return \"serial\";\n\tif (edgeCount === 0 && criticalDepth === 1) return \"parallel\";\n\tif (isMapReduceShape(lanes, batches)) return \"map-reduce\";\n\treturn \"hybrid\";\n}\n\nfunction isMapReduceShape(lanes: readonly PreparedLane[], batches: readonly SubagentScheduleBatch[]): boolean {\n\tif (batches.length < 2) return false;\n\tconst firstBatch = batches[0];\n\tconst finalBatch = batches[batches.length - 1];\n\tif (firstBatch.laneIds.length < 2 || finalBatch.laneIds.length !== 1) return false;\n\tconst finalLane = lanes.find((lane) => lane.spec.id === finalBatch.laneIds[0]);\n\tif (!finalLane) return false;\n\treturn firstBatch.laneIds.every((laneId) => finalLane.dependsOn.includes(laneId));\n}\n\nfunction normalizePath(path: string): string {\n\treturn path.replaceAll(\"\\\\\", \"/\").replace(/\\/+$/g, \"\");\n}\n\nfunction round(value: number): number {\n\treturn Math.round(value * 1000) / 1000;\n}\n\nfunction uniqueSorted(values: readonly string[]): string[] {\n\treturn [...new Set(values)]\n\t\t.map((value) => value.trim())\n\t\t.filter((value) => value !== \"\")\n\t\t.sort();\n}\n\nfunction arrayEquals(left: readonly string[], right: readonly string[]): boolean {\n\treturn left.length === right.length && left.every((value, index) => value === right[index]);\n}\n"]}
1
+ {"version":3,"file":"subagent-orchestration.js","sourceRoot":"","sources":["../../src/core/subagent-orchestration.ts"],"names":[],"mappings":"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","sourcesContent":["import {\n\tbuildSubagentLaneGrant,\n\ttype LaneContextInheritanceMode,\n\ttype LaneEvidenceGate,\n\ttype LaneSpawnReceipt,\n\ttype SubagentLaneGrant,\n} from \"./loadout-runtime.ts\";\nimport {\n\tapplyLoadoutProfile,\n\tBUILTIN_LOADOUTS,\n\ttype CapabilityInventory,\n\tderiveSchedulerFields,\n\ttype LoadoutAuthority,\n\ttype LoadoutProfile,\n\ttype LoadoutRole,\n} from \"./loadouts.ts\";\n\nexport type SubagentOrchestrationRole =\n\t| \"planner\"\n\t| \"architect\"\n\t| \"executor\"\n\t| \"critic\"\n\t| \"visual-qa\"\n\t| \"rhwp-doc\"\n\t| \"security\"\n\t| \"package-maintainer\";\n\nexport type SubagentSchedulerTopology = \"serial\" | \"parallel\" | \"map-reduce\" | \"hybrid\";\n\nexport interface SubagentRoleAssignment {\n\treadonly role: SubagentOrchestrationRole;\n\treadonly loadoutRole: LoadoutRole;\n\treadonly loadoutName: string;\n\treadonly agentName: string;\n\treadonly contextInheritance: LaneContextInheritanceMode;\n\treadonly evidenceGates: readonly LaneEvidenceGate[];\n\treadonly writesProductFiles: boolean;\n}\n\nexport interface SubagentLaneSpec {\n\treadonly id: string;\n\treadonly role: SubagentOrchestrationRole;\n\treadonly task: string;\n\treadonly dependsOn?: readonly string[];\n\treadonly readScope?: readonly string[];\n\treadonly writeScope?: readonly string[];\n\treadonly acceptance?: readonly string[];\n\treadonly evidenceOutput?: string;\n\treadonly blockedPaths?: readonly string[];\n\treadonly contextInheritance?: LaneContextInheritanceMode;\n\treadonly grantAuthority?: LoadoutAuthority;\n\treadonly loadoutName?: string;\n\treadonly agentName?: string;\n}\n\nexport interface SpawnGateDecision {\n\treadonly outcome: \"allowed\" | \"rejected\";\n\treadonly reason: string;\n\treadonly planRequired: boolean;\n\treadonly missingFields: readonly string[];\n}\n\nexport interface SubagentScheduleBatch {\n\treadonly index: number;\n\treadonly laneIds: readonly string[];\n\treadonly reason: \"ready-parallel\" | \"serialized-writer\" | \"parallel-limit\";\n}\n\nexport interface SubagentRouteFeatures {\n\treadonly topology: SubagentSchedulerTopology;\n\treadonly width: number;\n\treadonly criticalDepth: number;\n\treadonly couplingDensity: number;\n\treadonly parallelRatio: number;\n\treadonly nodeCount: number;\n\treadonly edgeCount: number;\n}\n\nexport interface BuildSubagentOrchestrationPlanInput {\n\treadonly runId: string;\n\treadonly lanes: readonly SubagentLaneSpec[];\n\treadonly inventory: CapabilityInventory;\n\treadonly spawnPlan?: LaneSpawnReceipt;\n\treadonly spawnThreshold?: number;\n\treadonly maxParallelLanes?: number;\n}\n\nexport interface SubagentOrchestrationPlan {\n\treadonly laneGrants: readonly SubagentLaneGrant[];\n\treadonly batches: readonly SubagentScheduleBatch[];\n\treadonly route: SubagentRouteFeatures;\n\treadonly spawnGate: SpawnGateDecision;\n\treadonly blockers: readonly string[];\n\treadonly warnings: readonly string[];\n}\n\nconst DEFAULT_SPAWN_THRESHOLD = 4;\n\nconst ROLE_ASSIGNMENTS: Readonly<Record<SubagentOrchestrationRole, SubagentRoleAssignment>> = {\n\tplanner: {\n\t\trole: \"planner\",\n\t\tloadoutRole: \"planner\",\n\t\tloadoutName: \"plan\",\n\t\tagentName: \"omk-planner\",\n\t\tcontextInheritance: \"receipt\",\n\t\tevidenceGates: [\"plan-reread\", \"cleanup\"],\n\t\twritesProductFiles: false,\n\t},\n\tarchitect: {\n\t\trole: \"architect\",\n\t\tloadoutRole: \"architect\",\n\t\tloadoutName: \"architect\",\n\t\tagentName: \"omk-architect\",\n\t\tcontextInheritance: \"bounded\",\n\t\tevidenceGates: [\"plan-reread\", \"automated-verification\", \"adversarial-qa\", \"cleanup\"],\n\t\twritesProductFiles: false,\n\t},\n\texecutor: {\n\t\trole: \"executor\",\n\t\tloadoutRole: \"executor\",\n\t\tloadoutName: \"executor\",\n\t\tagentName: \"omk-executor\",\n\t\tcontextInheritance: \"bounded\",\n\t\tevidenceGates: [\"plan-reread\", \"automated-verification\", \"manual-qa\", \"adversarial-qa\", \"cleanup\"],\n\t\twritesProductFiles: true,\n\t},\n\tcritic: {\n\t\trole: \"critic\",\n\t\tloadoutRole: \"critic\",\n\t\tloadoutName: \"critic\",\n\t\tagentName: \"omk-critic\",\n\t\tcontextInheritance: \"receipt\",\n\t\tevidenceGates: [\"plan-reread\", \"adversarial-qa\", \"cleanup\"],\n\t\twritesProductFiles: false,\n\t},\n\t\"visual-qa\": {\n\t\trole: \"visual-qa\",\n\t\tloadoutRole: \"visual-qa\",\n\t\tloadoutName: \"visual-qa\",\n\t\tagentName: \"omk-visual-qa\",\n\t\tcontextInheritance: \"receipt\",\n\t\tevidenceGates: [\"plan-reread\", \"automated-verification\", \"manual-qa\", \"adversarial-qa\", \"cleanup\"],\n\t\twritesProductFiles: false,\n\t},\n\t\"rhwp-doc\": {\n\t\trole: \"rhwp-doc\",\n\t\tloadoutRole: \"rhwp-doc\",\n\t\tloadoutName: \"rhwp-doc\",\n\t\tagentName: \"omk-rhwp-doc\",\n\t\tcontextInheritance: \"bounded\",\n\t\tevidenceGates: [\"plan-reread\", \"automated-verification\", \"manual-qa\", \"adversarial-qa\", \"cleanup\"],\n\t\twritesProductFiles: true,\n\t},\n\tsecurity: {\n\t\trole: \"security\",\n\t\tloadoutRole: \"security\",\n\t\tloadoutName: \"security\",\n\t\tagentName: \"omk-security\",\n\t\tcontextInheritance: \"none\",\n\t\tevidenceGates: [\"plan-reread\", \"automated-verification\", \"adversarial-qa\", \"cleanup\"],\n\t\twritesProductFiles: false,\n\t},\n\t\"package-maintainer\": {\n\t\trole: \"package-maintainer\",\n\t\tloadoutRole: \"package-maintainer\",\n\t\tloadoutName: \"package-maintainer\",\n\t\tagentName: \"omk-package-maintainer\",\n\t\tcontextInheritance: \"bounded\",\n\t\tevidenceGates: [\"plan-reread\", \"automated-verification\", \"manual-qa\", \"adversarial-qa\", \"cleanup\"],\n\t\twritesProductFiles: true,\n\t},\n};\n\nconst REQUIRED_SPAWN_PLAN_STRING_FIELDS = [\n\t\"whyParallel\",\n\t\"whyNotLocal\",\n\t\"independence\",\n\t\"expectedReceiptShape\",\n] as const;\n\ninterface PreparedLane {\n\treadonly index: number;\n\treadonly spec: SubagentLaneSpec;\n\treadonly grant: SubagentLaneGrant;\n\treadonly dependsOn: readonly string[];\n}\n\nexport function resolveSubagentRoleAssignment(role: SubagentOrchestrationRole): SubagentRoleAssignment {\n\treturn ROLE_ASSIGNMENTS[role];\n}\n\nexport function buildSubagentOrchestrationPlan(input: BuildSubagentOrchestrationPlanInput): SubagentOrchestrationPlan {\n\tif (\n\t\tinput.maxParallelLanes !== undefined &&\n\t\t(!Number.isInteger(input.maxParallelLanes) || input.maxParallelLanes < 1)\n\t) {\n\t\tthrow new RangeError(\"maxParallelLanes must be a positive integer\");\n\t}\n\n\tconst blockers: string[] = [];\n\tconst warnings: string[] = [];\n\tblockers.push(...validateLaneIntake(input.lanes));\n\tconst spawnGate = evaluateSpawnGate({\n\t\tchildCount: input.lanes.length,\n\t\tplan: input.spawnPlan,\n\t\tthreshold: input.spawnThreshold ?? DEFAULT_SPAWN_THRESHOLD,\n\t});\n\tif (spawnGate.outcome === \"rejected\") blockers.push(spawnGate.reason);\n\n\tconst prepared = input.lanes.map((lane, index) =>\n\t\tprepareLane(lane, index, input.runId, input.inventory, input.spawnPlan, blockers, warnings),\n\t);\n\tblockers.push(...findDependencyBlockers(prepared));\n\n\tconst scheduledLanes = applyReceiptConsumerDependencies(prepared);\n\tconst batches = schedulePreparedLanes(scheduledLanes, input.maxParallelLanes, blockers);\n\tconst route = buildRouteFeatures(scheduledLanes, batches);\n\n\treturn {\n\t\tlaneGrants: scheduledLanes.map((lane) => lane.grant),\n\t\tbatches,\n\t\troute,\n\t\tspawnGate,\n\t\tblockers: uniqueSorted(blockers),\n\t\twarnings: uniqueSorted(warnings),\n\t};\n}\n\nexport function evaluateSpawnGate(request: {\n\treadonly childCount: number;\n\treadonly plan?: LaneSpawnReceipt;\n\treadonly threshold?: number;\n}): SpawnGateDecision {\n\tconst threshold = request.threshold ?? DEFAULT_SPAWN_THRESHOLD;\n\tif (!Number.isInteger(request.childCount) || request.childCount < 0) {\n\t\tthrow new RangeError(\"childCount must be a non-negative integer\");\n\t}\n\tif (!Number.isInteger(threshold) || threshold < 1) {\n\t\tthrow new RangeError(\"threshold must be a positive integer\");\n\t}\n\n\tconst planRequired = request.childCount > threshold;\n\tif (!planRequired) {\n\t\treturn {\n\t\t\toutcome: \"allowed\",\n\t\t\treason: `batch of ${request.childCount} is at or below threshold ${threshold}`,\n\t\t\tplanRequired: false,\n\t\t\tmissingFields: [],\n\t\t};\n\t}\n\n\tconst missingFields = findMissingSpawnPlanFields(request.plan);\n\tif (missingFields.length > 0) {\n\t\treturn {\n\t\t\toutcome: \"rejected\",\n\t\t\treason: `batch of ${request.childCount} exceeds threshold ${threshold} and the spawn-plan receipt is ${\n\t\t\t\trequest.plan ? `incomplete (${missingFields.join(\", \")})` : \"missing\"\n\t\t\t}`,\n\t\t\tplanRequired: true,\n\t\t\tmissingFields,\n\t\t};\n\t}\n\n\treturn {\n\t\toutcome: \"allowed\",\n\t\treason: `batch of ${request.childCount} exceeds threshold ${threshold} and a complete spawn-plan receipt was provided`,\n\t\tplanRequired: true,\n\t\tmissingFields: [],\n\t};\n}\n\nexport function findMissingSpawnPlanFields(plan: LaneSpawnReceipt | undefined): string[] {\n\tif (!plan) return [...REQUIRED_SPAWN_PLAN_STRING_FIELDS, \"maxInlineTokens\"];\n\tconst missing: string[] = [];\n\tfor (const field of REQUIRED_SPAWN_PLAN_STRING_FIELDS) {\n\t\tconst value = plan[field];\n\t\tif (value.trim().length === 0) missing.push(field);\n\t}\n\tif (!Number.isFinite(plan.maxInlineTokens) || plan.maxInlineTokens <= 0) {\n\t\tmissing.push(\"maxInlineTokens\");\n\t}\n\treturn missing;\n}\n\nfunction validateLaneIntake(lanes: readonly SubagentLaneSpec[]): string[] {\n\tconst blockers: string[] = [];\n\tconst seenIds = new Map<string, number>();\n\n\tfor (const [index, lane] of lanes.entries()) {\n\t\tconst id = lane.id.trim();\n\t\tconst label = id === \"\" ? `lane at index ${index}` : `lane ${id}`;\n\t\tif (id === \"\") {\n\t\t\tblockers.push(`lane at index ${index} has empty id`);\n\t\t} else {\n\t\t\tconst firstIndex = seenIds.get(id);\n\t\t\tif (firstIndex === undefined) {\n\t\t\t\tseenIds.set(id, index);\n\t\t\t} else {\n\t\t\t\tblockers.push(`duplicate lane id ${id} at indexes ${firstIndex} and ${index}`);\n\t\t\t}\n\t\t}\n\n\t\tif (lane.task.trim() === \"\") {\n\t\t\tblockers.push(`${label} has empty task`);\n\t\t}\n\n\t\tconst seenDependencies = new Set<string>();\n\t\tfor (const dependency of lane.dependsOn ?? []) {\n\t\t\tconst dependencyId = dependency.trim();\n\t\t\tif (dependencyId === \"\") {\n\t\t\t\tblockers.push(`${label} has empty dependency id`);\n\t\t\t\tcontinue;\n\t\t\t}\n\t\t\tif (dependencyId === id) {\n\t\t\t\tblockers.push(`${label} depends on itself`);\n\t\t\t}\n\t\t\tif (seenDependencies.has(dependencyId)) {\n\t\t\t\tblockers.push(`${label} repeats dependency ${dependencyId}`);\n\t\t\t}\n\t\t\tseenDependencies.add(dependencyId);\n\t\t}\n\t}\n\n\treturn blockers;\n}\n\nfunction prepareLane(\n\tspec: SubagentLaneSpec,\n\tindex: number,\n\trunId: string,\n\tinventory: CapabilityInventory,\n\tspawnReceipt: LaneSpawnReceipt | undefined,\n\tblockers: string[],\n\twarnings: string[],\n): PreparedLane {\n\tconst assignment = resolveSubagentRoleAssignment(spec.role);\n\tif ((spec.writeScope?.length ?? 0) > 0 && !assignment.writesProductFiles) {\n\t\tblockers.push(`lane ${spec.id} role ${spec.role} cannot write product files`);\n\t}\n\tconst dependsOn = uniqueSorted(spec.dependsOn ?? []);\n\n\tconst profile = resolveLoadoutProfile(spec, assignment, blockers);\n\tconst applied = applyLoadoutProfile(profile, inventory, { grantAuthority: spec.grantAuthority });\n\tblockers.push(...applied.blockers.map((blocker) => `lane ${spec.id}: ${blocker}`));\n\twarnings.push(...applied.warnings.map((warning) => `lane ${spec.id}: ${warning}`));\n\n\tconst schedulerFields = deriveSchedulerFields({\n\t\trole: assignment.loadoutRole,\n\t\tassignedReadPaths: spec.readScope,\n\t\tassignedWritePaths: spec.writeScope,\n\t});\n\n\tconst grant = buildSubagentLaneGrant(spec.id, assignment.loadoutRole, spec.task, applied, schedulerFields, {\n\t\tallowedReadPaths: spec.readScope,\n\t\tallowedWritePaths: spec.writeScope,\n\t\tblockedPaths: spec.blockedPaths,\n\t\tevidenceOutputPattern: spec.evidenceOutput ?? profile.evidence?.outputPattern,\n\t\trunId,\n\t\tprofile,\n\t\tagentName: spec.agentName ?? assignment.agentName,\n\t\tcontextInheritance: spec.contextInheritance ?? assignment.contextInheritance,\n\t\tspawnReceipt,\n\t\tevidenceGates: assignment.evidenceGates,\n\t\tdependsOn,\n\t\tacceptance: spec.acceptance,\n\t});\n\n\treturn { index, spec, grant, dependsOn };\n}\n\nfunction resolveLoadoutProfile(\n\tspec: SubagentLaneSpec,\n\tassignment: SubagentRoleAssignment,\n\tblockers: string[],\n): LoadoutProfile {\n\tconst loadoutName = spec.loadoutName ?? assignment.loadoutName;\n\tconst profile = BUILTIN_LOADOUTS[loadoutName];\n\tif (profile) return profile;\n\tblockers.push(`lane ${spec.id}: unknown loadout ${loadoutName}`);\n\treturn BUILTIN_LOADOUTS.none;\n}\n\nfunction findDependencyBlockers(lanes: readonly PreparedLane[]): string[] {\n\tconst ids = new Set(lanes.map((lane) => lane.spec.id));\n\tconst blockers: string[] = [];\n\tfor (const lane of lanes) {\n\t\tfor (const dependency of lane.dependsOn) {\n\t\t\tif (!ids.has(dependency)) {\n\t\t\t\tblockers.push(`lane ${lane.spec.id} depends on missing lane ${dependency}`);\n\t\t\t}\n\t\t}\n\t}\n\treturn blockers;\n}\n\nfunction applyReceiptConsumerDependencies(lanes: readonly PreparedLane[]): PreparedLane[] {\n\tconst receiptProducerIds = lanes\n\t\t.filter((lane) => lane.grant.evidenceOutput !== undefined && !isReceiptConsumerRole(lane.spec.role))\n\t\t.map((lane) => lane.spec.id);\n\n\treturn lanes.map((lane) => {\n\t\tif (!isReceiptReadingConsumer(lane) || receiptProducerIds.length === 0) return lane;\n\t\tconst dependsOn = uniqueSorted([\n\t\t\t...lane.dependsOn,\n\t\t\t...receiptProducerIds.filter((producerId) => producerId !== lane.spec.id),\n\t\t]);\n\t\tif (arrayEquals(dependsOn, lane.dependsOn)) return lane;\n\t\treturn {\n\t\t\t...lane,\n\t\t\tdependsOn,\n\t\t\tgrant: {\n\t\t\t\t...lane.grant,\n\t\t\t\tdependsOn,\n\t\t\t},\n\t\t};\n\t});\n}\n\nfunction isReceiptReadingConsumer(lane: PreparedLane): boolean {\n\tif (!isReceiptConsumerRole(lane.spec.role)) return false;\n\treturn (lane.spec.readScope ?? []).some(isReceiptPath);\n}\n\nfunction isReceiptConsumerRole(role: SubagentOrchestrationRole): boolean {\n\treturn role === \"critic\" || role === \"visual-qa\" || role === \"rhwp-doc\";\n}\n\nfunction isReceiptPath(path: string): boolean {\n\tconst normalized = normalizePath(path);\n\treturn normalized === \".omk/runs\" || normalized.startsWith(\".omk/runs/\") || normalized.includes(\"/.omk/runs/\");\n}\n\nfunction schedulePreparedLanes(\n\tlanes: readonly PreparedLane[],\n\tmaxParallelLanes: number | undefined,\n\tblockers: string[],\n): SubagentScheduleBatch[] {\n\tconst scheduled = new Set<string>();\n\tconst batches: SubagentScheduleBatch[] = [];\n\n\twhile (scheduled.size < lanes.length) {\n\t\tconst ready = lanes\n\t\t\t.filter(\n\t\t\t\t(lane) => !scheduled.has(lane.spec.id) && lane.dependsOn.every((dependency) => scheduled.has(dependency)),\n\t\t\t)\n\t\t\t.sort((left, right) => (left.spec.id < right.spec.id ? -1 : left.spec.id > right.spec.id ? 1 : 0));\n\t\tif (ready.length === 0) {\n\t\t\tconst remaining = lanes.filter((lane) => !scheduled.has(lane.spec.id)).map((lane) => lane.spec.id);\n\t\t\tblockers.push(`lane dependency cycle or unsatisfied dependency among: ${remaining.join(\", \")}`);\n\t\t\tbreak;\n\t\t}\n\n\t\tconst serialized = ready.find((lane) => !lane.grant.scheduler.parallelizable);\n\t\tif (serialized) {\n\t\t\tbatches.push({\n\t\t\t\tindex: batches.length,\n\t\t\t\tlaneIds: [serialized.spec.id],\n\t\t\t\treason: \"serialized-writer\",\n\t\t\t});\n\t\t\tscheduled.add(serialized.spec.id);\n\t\t\tcontinue;\n\t\t}\n\n\t\tconst selected: PreparedLane[] = [];\n\t\tfor (const lane of ready) {\n\t\t\tif (maxParallelLanes !== undefined && selected.length >= maxParallelLanes) break;\n\t\t\tif (!selected.some((selectedLane) => lanesConflict(selectedLane, lane))) {\n\t\t\t\tselected.push(lane);\n\t\t\t}\n\t\t}\n\t\tconst batchLanes = selected.length > 0 ? selected : [ready[0]];\n\t\tfor (const lane of batchLanes) scheduled.add(lane.spec.id);\n\t\tbatches.push({\n\t\t\tindex: batches.length,\n\t\t\tlaneIds: batchLanes.map((lane) => lane.spec.id),\n\t\t\treason:\n\t\t\t\tmaxParallelLanes !== undefined && ready.length > batchLanes.length ? \"parallel-limit\" : \"ready-parallel\",\n\t\t});\n\t}\n\n\treturn batches;\n}\n\nfunction lanesConflict(left: PreparedLane, right: PreparedLane): boolean {\n\treturn (\n\t\tpathsConflict(\n\t\t\tleft.grant.scheduler.writeSet.map((entry) => entry.path),\n\t\t\t[\n\t\t\t\t...right.grant.scheduler.readSet.map((entry) => entry.path),\n\t\t\t\t...right.grant.scheduler.writeSet.map((entry) => entry.path),\n\t\t\t],\n\t\t) ||\n\t\tpathsConflict(\n\t\t\tright.grant.scheduler.writeSet.map((entry) => entry.path),\n\t\t\t[\n\t\t\t\t...left.grant.scheduler.readSet.map((entry) => entry.path),\n\t\t\t\t...left.grant.scheduler.writeSet.map((entry) => entry.path),\n\t\t\t],\n\t\t)\n\t);\n}\n\nfunction pathsConflict(writers: readonly string[], candidates: readonly string[]): boolean {\n\tfor (const writer of writers) {\n\t\tfor (const candidate of candidates) {\n\t\t\tif (pathIntersects(writer, candidate)) return true;\n\t\t}\n\t}\n\treturn false;\n}\n\nfunction pathIntersects(left: string, right: string): boolean {\n\tconst normalizedLeft = normalizePath(left);\n\tconst normalizedRight = normalizePath(right);\n\treturn (\n\t\tnormalizedLeft === normalizedRight ||\n\t\tnormalizedLeft.startsWith(`${normalizedRight}/`) ||\n\t\tnormalizedRight.startsWith(`${normalizedLeft}/`)\n\t);\n}\n\nfunction buildRouteFeatures(\n\tlanes: readonly PreparedLane[],\n\tbatches: readonly SubagentScheduleBatch[],\n): SubagentRouteFeatures {\n\tconst nodeCount = lanes.length;\n\tconst edgeCount = lanes.reduce((sum, lane) => sum + lane.dependsOn.length, 0);\n\tconst width = batches.reduce((max, batch) => Math.max(max, batch.laneIds.length), 0);\n\tconst criticalDepth = batches.length;\n\tconst parallelizable = lanes.filter((lane) => lane.grant.scheduler.parallelizable).length;\n\tconst parallelRatio = nodeCount === 0 ? 1 : parallelizable / nodeCount;\n\tconst couplingDensity = nodeCount <= 1 ? 0 : edgeCount / (nodeCount * (nodeCount - 1));\n\tconst topology = selectTopology(lanes, batches, width, criticalDepth, edgeCount);\n\n\treturn {\n\t\ttopology,\n\t\twidth,\n\t\tcriticalDepth,\n\t\tcouplingDensity: round(couplingDensity),\n\t\tparallelRatio: round(parallelRatio),\n\t\tnodeCount,\n\t\tedgeCount,\n\t};\n}\n\nfunction selectTopology(\n\tlanes: readonly PreparedLane[],\n\tbatches: readonly SubagentScheduleBatch[],\n\twidth: number,\n\tcriticalDepth: number,\n\tedgeCount: number,\n): SubagentSchedulerTopology {\n\tif (lanes.length <= 1 || width <= 1) return \"serial\";\n\tif (edgeCount === 0 && criticalDepth === 1) return \"parallel\";\n\tif (isMapReduceShape(lanes, batches)) return \"map-reduce\";\n\treturn \"hybrid\";\n}\n\nfunction isMapReduceShape(lanes: readonly PreparedLane[], batches: readonly SubagentScheduleBatch[]): boolean {\n\tif (batches.length < 2) return false;\n\tconst firstBatch = batches[0];\n\tconst finalBatch = batches[batches.length - 1];\n\tif (firstBatch.laneIds.length < 2 || finalBatch.laneIds.length !== 1) return false;\n\tconst finalLane = lanes.find((lane) => lane.spec.id === finalBatch.laneIds[0]);\n\tif (!finalLane) return false;\n\treturn firstBatch.laneIds.every((laneId) => finalLane.dependsOn.includes(laneId));\n}\n\nfunction normalizePath(path: string): string {\n\treturn path.replace(/\\\\/g, \"/\").replace(/\\/+$/g, \"\");\n}\n\nfunction round(value: number): number {\n\treturn Math.round(value * 1000) / 1000;\n}\n\nfunction uniqueSorted(values: readonly string[]): string[] {\n\treturn [...new Set(values)]\n\t\t.map((value) => value.trim())\n\t\t.filter((value) => value !== \"\")\n\t\t.sort();\n}\n\nfunction arrayEquals(left: readonly string[], right: readonly string[]): boolean {\n\treturn left.length === right.length && left.every((value, index) => value === right[index]);\n}\n"]}
@@ -0,0 +1,11 @@
1
+ export interface ToolContentBlock {
2
+ readonly type: string;
3
+ readonly id?: string;
4
+ }
5
+ export interface ToolPairMessage {
6
+ readonly role: string;
7
+ readonly content?: readonly ToolContentBlock[] | string;
8
+ readonly toolCallId?: string;
9
+ }
10
+ export declare function applyToolPairRepair<T extends ToolPairMessage>(messages: readonly T[]): T[];
11
+ //# sourceMappingURL=tool-pair-repair.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"tool-pair-repair.d.ts","sourceRoot":"","sources":["../../src/core/tool-pair-repair.ts"],"names":[],"mappings":"AAAA,MAAM,WAAW,gBAAgB;IAChC,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC;IACtB,QAAQ,CAAC,EAAE,CAAC,EAAE,MAAM,CAAC;CACrB;AAED,MAAM,WAAW,eAAe;IAC/B,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC;IACtB,QAAQ,CAAC,OAAO,CAAC,EAAE,SAAS,gBAAgB,EAAE,GAAG,MAAM,CAAC;IACxD,QAAQ,CAAC,UAAU,CAAC,EAAE,MAAM,CAAC;CAC7B;AAMD,wBAAgB,mBAAmB,CAAC,CAAC,SAAS,eAAe,EAAE,QAAQ,EAAE,SAAS,CAAC,EAAE,GAAG,CAAC,EAAE,CA8B1F","sourcesContent":["export interface ToolContentBlock {\n\treadonly type: string;\n\treadonly id?: string;\n}\n\nexport interface ToolPairMessage {\n\treadonly role: string;\n\treadonly content?: readonly ToolContentBlock[] | string;\n\treadonly toolCallId?: string;\n}\n\nfunction asBlocks(content: ToolPairMessage[\"content\"]): readonly ToolContentBlock[] {\n\treturn Array.isArray(content) ? content : [];\n}\n\nexport function applyToolPairRepair<T extends ToolPairMessage>(messages: readonly T[]): T[] {\n\tconst resultIds = new Set<string>();\n\tfor (const message of messages) {\n\t\tif (message.role === \"toolResult\" && typeof message.toolCallId === \"string\") {\n\t\t\tresultIds.add(message.toolCallId);\n\t\t}\n\t}\n\n\tconst keptIds = new Set<string>();\n\tconst repaired: T[] = [];\n\tfor (const message of messages) {\n\t\tif (message.role === \"assistant\") {\n\t\t\tconst original = asBlocks(message.content);\n\t\t\tconst content = original.filter((block) => {\n\t\t\t\tif (block.type !== \"toolCall\") return true;\n\t\t\t\tif (typeof block.id !== \"string\" || !resultIds.has(block.id)) return false;\n\t\t\t\tkeptIds.add(block.id);\n\t\t\t\treturn true;\n\t\t\t});\n\t\t\tif (content.length === 0) continue;\n\t\t\trepaired.push(content.length === original.length ? message : { ...message, content });\n\t\t\tcontinue;\n\t\t}\n\t\tif (message.role === \"toolResult\") {\n\t\t\tif (typeof message.toolCallId === \"string\" && keptIds.has(message.toolCallId)) repaired.push(message);\n\t\t\tcontinue;\n\t\t}\n\t\trepaired.push(message);\n\t}\n\treturn repaired;\n}\n"]}
@@ -0,0 +1,38 @@
1
+ function asBlocks(content) {
2
+ return Array.isArray(content) ? content : [];
3
+ }
4
+ export function applyToolPairRepair(messages) {
5
+ const resultIds = new Set();
6
+ for (const message of messages) {
7
+ if (message.role === "toolResult" && typeof message.toolCallId === "string") {
8
+ resultIds.add(message.toolCallId);
9
+ }
10
+ }
11
+ const keptIds = new Set();
12
+ const repaired = [];
13
+ for (const message of messages) {
14
+ if (message.role === "assistant") {
15
+ const original = asBlocks(message.content);
16
+ const content = original.filter((block) => {
17
+ if (block.type !== "toolCall")
18
+ return true;
19
+ if (typeof block.id !== "string" || !resultIds.has(block.id))
20
+ return false;
21
+ keptIds.add(block.id);
22
+ return true;
23
+ });
24
+ if (content.length === 0)
25
+ continue;
26
+ repaired.push(content.length === original.length ? message : { ...message, content });
27
+ continue;
28
+ }
29
+ if (message.role === "toolResult") {
30
+ if (typeof message.toolCallId === "string" && keptIds.has(message.toolCallId))
31
+ repaired.push(message);
32
+ continue;
33
+ }
34
+ repaired.push(message);
35
+ }
36
+ return repaired;
37
+ }
38
+ //# sourceMappingURL=tool-pair-repair.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"tool-pair-repair.js","sourceRoot":"","sources":["../../src/core/tool-pair-repair.ts"],"names":[],"mappings":"AAWA,SAAS,QAAQ,CAAC,OAAmC,EAA+B;IACnF,OAAO,KAAK,CAAC,OAAO,CAAC,OAAO,CAAC,CAAC,CAAC,CAAC,OAAO,CAAC,CAAC,CAAC,EAAE,CAAC;AAAA,CAC7C;AAED,MAAM,UAAU,mBAAmB,CAA4B,QAAsB,EAAO;IAC3F,MAAM,SAAS,GAAG,IAAI,GAAG,EAAU,CAAC;IACpC,KAAK,MAAM,OAAO,IAAI,QAAQ,EAAE,CAAC;QAChC,IAAI,OAAO,CAAC,IAAI,KAAK,YAAY,IAAI,OAAO,OAAO,CAAC,UAAU,KAAK,QAAQ,EAAE,CAAC;YAC7E,SAAS,CAAC,GAAG,CAAC,OAAO,CAAC,UAAU,CAAC,CAAC;QACnC,CAAC;IACF,CAAC;IAED,MAAM,OAAO,GAAG,IAAI,GAAG,EAAU,CAAC;IAClC,MAAM,QAAQ,GAAQ,EAAE,CAAC;IACzB,KAAK,MAAM,OAAO,IAAI,QAAQ,EAAE,CAAC;QAChC,IAAI,OAAO,CAAC,IAAI,KAAK,WAAW,EAAE,CAAC;YAClC,MAAM,QAAQ,GAAG,QAAQ,CAAC,OAAO,CAAC,OAAO,CAAC,CAAC;YAC3C,MAAM,OAAO,GAAG,QAAQ,CAAC,MAAM,CAAC,CAAC,KAAK,EAAE,EAAE,CAAC;gBAC1C,IAAI,KAAK,CAAC,IAAI,KAAK,UAAU;oBAAE,OAAO,IAAI,CAAC;gBAC3C,IAAI,OAAO,KAAK,CAAC,EAAE,KAAK,QAAQ,IAAI,CAAC,SAAS,CAAC,GAAG,CAAC,KAAK,CAAC,EAAE,CAAC;oBAAE,OAAO,KAAK,CAAC;gBAC3E,OAAO,CAAC,GAAG,CAAC,KAAK,CAAC,EAAE,CAAC,CAAC;gBACtB,OAAO,IAAI,CAAC;YAAA,CACZ,CAAC,CAAC;YACH,IAAI,OAAO,CAAC,MAAM,KAAK,CAAC;gBAAE,SAAS;YACnC,QAAQ,CAAC,IAAI,CAAC,OAAO,CAAC,MAAM,KAAK,QAAQ,CAAC,MAAM,CAAC,CAAC,CAAC,OAAO,CAAC,CAAC,CAAC,EAAE,GAAG,OAAO,EAAE,OAAO,EAAE,CAAC,CAAC;YACtF,SAAS;QACV,CAAC;QACD,IAAI,OAAO,CAAC,IAAI,KAAK,YAAY,EAAE,CAAC;YACnC,IAAI,OAAO,OAAO,CAAC,UAAU,KAAK,QAAQ,IAAI,OAAO,CAAC,GAAG,CAAC,OAAO,CAAC,UAAU,CAAC;gBAAE,QAAQ,CAAC,IAAI,CAAC,OAAO,CAAC,CAAC;YACtG,SAAS;QACV,CAAC;QACD,QAAQ,CAAC,IAAI,CAAC,OAAO,CAAC,CAAC;IACxB,CAAC;IACD,OAAO,QAAQ,CAAC;AAAA,CAChB","sourcesContent":["export interface ToolContentBlock {\n\treadonly type: string;\n\treadonly id?: string;\n}\n\nexport interface ToolPairMessage {\n\treadonly role: string;\n\treadonly content?: readonly ToolContentBlock[] | string;\n\treadonly toolCallId?: string;\n}\n\nfunction asBlocks(content: ToolPairMessage[\"content\"]): readonly ToolContentBlock[] {\n\treturn Array.isArray(content) ? content : [];\n}\n\nexport function applyToolPairRepair<T extends ToolPairMessage>(messages: readonly T[]): T[] {\n\tconst resultIds = new Set<string>();\n\tfor (const message of messages) {\n\t\tif (message.role === \"toolResult\" && typeof message.toolCallId === \"string\") {\n\t\t\tresultIds.add(message.toolCallId);\n\t\t}\n\t}\n\n\tconst keptIds = new Set<string>();\n\tconst repaired: T[] = [];\n\tfor (const message of messages) {\n\t\tif (message.role === \"assistant\") {\n\t\t\tconst original = asBlocks(message.content);\n\t\t\tconst content = original.filter((block) => {\n\t\t\t\tif (block.type !== \"toolCall\") return true;\n\t\t\t\tif (typeof block.id !== \"string\" || !resultIds.has(block.id)) return false;\n\t\t\t\tkeptIds.add(block.id);\n\t\t\t\treturn true;\n\t\t\t});\n\t\t\tif (content.length === 0) continue;\n\t\t\trepaired.push(content.length === original.length ? message : { ...message, content });\n\t\t\tcontinue;\n\t\t}\n\t\tif (message.role === \"toolResult\") {\n\t\t\tif (typeof message.toolCallId === \"string\" && keptIds.has(message.toolCallId)) repaired.push(message);\n\t\t\tcontinue;\n\t\t}\n\t\trepaired.push(message);\n\t}\n\treturn repaired;\n}\n"]}
@@ -0,0 +1,13 @@
1
+ export interface SpillInput {
2
+ readonly kind: "read" | "bash";
3
+ readonly preview: string;
4
+ readonly full: string;
5
+ readonly truncated: boolean;
6
+ readonly path: string;
7
+ }
8
+ export interface SpillResult {
9
+ readonly preview: string;
10
+ readonly path: string;
11
+ }
12
+ export declare function spillTruncatedOutput(input: SpillInput): SpillResult;
13
+ //# sourceMappingURL=artifact-spill.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"artifact-spill.d.ts","sourceRoot":"","sources":["../../../src/core/tools/artifact-spill.ts"],"names":[],"mappings":"AAMA,MAAM,WAAW,UAAU;IAC1B,QAAQ,CAAC,IAAI,EAAE,MAAM,GAAG,MAAM,CAAC;IAC/B,QAAQ,CAAC,OAAO,EAAE,MAAM,CAAC;IACzB,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC;IACtB,QAAQ,CAAC,SAAS,EAAE,OAAO,CAAC;IAC5B,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC;CACtB;AAED,MAAM,WAAW,WAAW;IAC3B,QAAQ,CAAC,OAAO,EAAE,MAAM,CAAC;IACzB,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC;CACtB;AAED,wBAAgB,oBAAoB,CAAC,KAAK,EAAE,UAAU,GAAG,WAAW,CAiBnE","sourcesContent":["import { createHash } from \"node:crypto\";\nimport { chmodSync, mkdtempSync, rmSync, writeFileSync } from \"node:fs\";\nimport { tmpdir } from \"node:os\";\nimport { join } from \"node:path\";\nimport { formatSize } from \"./truncate.ts\";\n\nexport interface SpillInput {\n\treadonly kind: \"read\" | \"bash\";\n\treadonly preview: string;\n\treadonly full: string;\n\treadonly truncated: boolean;\n\treadonly path: string;\n}\n\nexport interface SpillResult {\n\treadonly preview: string;\n\treadonly path: string;\n}\n\nexport function spillTruncatedOutput(input: SpillInput): SpillResult {\n\tif (!input.truncated) return { preview: input.preview, path: input.path };\n\tconst directory = mkdtempSync(join(tmpdir(), \"omk-spill-\"));\n\tchmodSync(directory, 0o700);\n\tconst sourceDigest = createHash(\"sha256\").update(input.path).digest(\"hex\").slice(0, 16);\n\tconst spillPath = join(directory, `${input.kind}-${sourceDigest}.txt`);\n\ttry {\n\t\twriteFileSync(spillPath, input.full, { encoding: \"utf8\", flag: \"wx\", mode: 0o600 });\n\t} catch (error) {\n\t\trmSync(directory, { recursive: true, force: true });\n\t\tthrow error;\n\t}\n\tconst size = formatSize(Buffer.byteLength(input.full, \"utf-8\"));\n\treturn {\n\t\tpreview: `${input.preview}\\n\\n[Full ${input.kind} output spilled to ${spillPath} (${size}).]`,\n\t\tpath: spillPath,\n\t};\n}\n"]}
@@ -0,0 +1,26 @@
1
+ import { createHash } from "node:crypto";
2
+ import { chmodSync, mkdtempSync, rmSync, writeFileSync } from "node:fs";
3
+ import { tmpdir } from "node:os";
4
+ import { join } from "node:path";
5
+ import { formatSize } from "./truncate.js";
6
+ export function spillTruncatedOutput(input) {
7
+ if (!input.truncated)
8
+ return { preview: input.preview, path: input.path };
9
+ const directory = mkdtempSync(join(tmpdir(), "omk-spill-"));
10
+ chmodSync(directory, 0o700);
11
+ const sourceDigest = createHash("sha256").update(input.path).digest("hex").slice(0, 16);
12
+ const spillPath = join(directory, `${input.kind}-${sourceDigest}.txt`);
13
+ try {
14
+ writeFileSync(spillPath, input.full, { encoding: "utf8", flag: "wx", mode: 0o600 });
15
+ }
16
+ catch (error) {
17
+ rmSync(directory, { recursive: true, force: true });
18
+ throw error;
19
+ }
20
+ const size = formatSize(Buffer.byteLength(input.full, "utf-8"));
21
+ return {
22
+ preview: `${input.preview}\n\n[Full ${input.kind} output spilled to ${spillPath} (${size}).]`,
23
+ path: spillPath,
24
+ };
25
+ }
26
+ //# sourceMappingURL=artifact-spill.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"artifact-spill.js","sourceRoot":"","sources":["../../../src/core/tools/artifact-spill.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,UAAU,EAAE,MAAM,aAAa,CAAC;AACzC,OAAO,EAAE,SAAS,EAAE,WAAW,EAAE,MAAM,EAAE,aAAa,EAAE,MAAM,SAAS,CAAC;AACxE,OAAO,EAAE,MAAM,EAAE,MAAM,SAAS,CAAC;AACjC,OAAO,EAAE,IAAI,EAAE,MAAM,WAAW,CAAC;AACjC,OAAO,EAAE,UAAU,EAAE,MAAM,eAAe,CAAC;AAe3C,MAAM,UAAU,oBAAoB,CAAC,KAAiB,EAAe;IACpE,IAAI,CAAC,KAAK,CAAC,SAAS;QAAE,OAAO,EAAE,OAAO,EAAE,KAAK,CAAC,OAAO,EAAE,IAAI,EAAE,KAAK,CAAC,IAAI,EAAE,CAAC;IAC1E,MAAM,SAAS,GAAG,WAAW,CAAC,IAAI,CAAC,MAAM,EAAE,EAAE,YAAY,CAAC,CAAC,CAAC;IAC5D,SAAS,CAAC,SAAS,EAAE,KAAK,CAAC,CAAC;IAC5B,MAAM,YAAY,GAAG,UAAU,CAAC,QAAQ,CAAC,CAAC,MAAM,CAAC,KAAK,CAAC,IAAI,CAAC,CAAC,MAAM,CAAC,KAAK,CAAC,CAAC,KAAK,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC;IACxF,MAAM,SAAS,GAAG,IAAI,CAAC,SAAS,EAAE,GAAG,KAAK,CAAC,IAAI,IAAI,YAAY,MAAM,CAAC,CAAC;IACvE,IAAI,CAAC;QACJ,aAAa,CAAC,SAAS,EAAE,KAAK,CAAC,IAAI,EAAE,EAAE,QAAQ,EAAE,MAAM,EAAE,IAAI,EAAE,IAAI,EAAE,IAAI,EAAE,KAAK,EAAE,CAAC,CAAC;IACrF,CAAC;IAAC,OAAO,KAAK,EAAE,CAAC;QAChB,MAAM,CAAC,SAAS,EAAE,EAAE,SAAS,EAAE,IAAI,EAAE,KAAK,EAAE,IAAI,EAAE,CAAC,CAAC;QACpD,MAAM,KAAK,CAAC;IACb,CAAC;IACD,MAAM,IAAI,GAAG,UAAU,CAAC,MAAM,CAAC,UAAU,CAAC,KAAK,CAAC,IAAI,EAAE,OAAO,CAAC,CAAC,CAAC;IAChE,OAAO;QACN,OAAO,EAAE,GAAG,KAAK,CAAC,OAAO,aAAa,KAAK,CAAC,IAAI,sBAAsB,SAAS,KAAK,IAAI,KAAK;QAC7F,IAAI,EAAE,SAAS;KACf,CAAC;AAAA,CACF","sourcesContent":["import { createHash } from \"node:crypto\";\nimport { chmodSync, mkdtempSync, rmSync, writeFileSync } from \"node:fs\";\nimport { tmpdir } from \"node:os\";\nimport { join } from \"node:path\";\nimport { formatSize } from \"./truncate.ts\";\n\nexport interface SpillInput {\n\treadonly kind: \"read\" | \"bash\";\n\treadonly preview: string;\n\treadonly full: string;\n\treadonly truncated: boolean;\n\treadonly path: string;\n}\n\nexport interface SpillResult {\n\treadonly preview: string;\n\treadonly path: string;\n}\n\nexport function spillTruncatedOutput(input: SpillInput): SpillResult {\n\tif (!input.truncated) return { preview: input.preview, path: input.path };\n\tconst directory = mkdtempSync(join(tmpdir(), \"omk-spill-\"));\n\tchmodSync(directory, 0o700);\n\tconst sourceDigest = createHash(\"sha256\").update(input.path).digest(\"hex\").slice(0, 16);\n\tconst spillPath = join(directory, `${input.kind}-${sourceDigest}.txt`);\n\ttry {\n\t\twriteFileSync(spillPath, input.full, { encoding: \"utf8\", flag: \"wx\", mode: 0o600 });\n\t} catch (error) {\n\t\trmSync(directory, { recursive: true, force: true });\n\t\tthrow error;\n\t}\n\tconst size = formatSize(Buffer.byteLength(input.full, \"utf-8\"));\n\treturn {\n\t\tpreview: `${input.preview}\\n\\n[Full ${input.kind} output spilled to ${spillPath} (${size}).]`,\n\t\tpath: spillPath,\n\t};\n}\n"]}
@@ -41,10 +41,13 @@ export interface BashOperations {
41
41
  * This is useful for extensions that intercept user_bash and still want OMK's
42
42
  * standard local shell behavior while wrapping, sandboxing, or rewriting commands.
43
43
  */
44
- export declare function createLocalBashOperations(options?: {
45
- shellPath?: string;
46
- sandboxPolicy?: BashSandboxPreflight;
47
- }): BashOperations;
44
+ export interface LocalBashOperationsOptions {
45
+ readonly shellPath?: string;
46
+ readonly sandboxPolicy?: BashSandboxPreflight;
47
+ /** Override backend probing for embedders and deterministic tests. */
48
+ readonly detectSandboxBackend?: () => SandboxBackendStatus;
49
+ }
50
+ export declare function createLocalBashOperations(options?: LocalBashOperationsOptions): BashOperations;
48
51
  /**
49
52
  * Sandbox preflight inputs for local bash operations. When provided to
50
53
  * {@link createLocalBashOperations}, every spawn is gated by the sandbox spawn
@@ -1 +1 @@
1
- {"version":3,"file":"bash.d.ts","sourceRoot":"","sources":["../../../src/core/tools/bash.ts"],"names":[],"mappings":"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","sourcesContent":["import { spawn } from \"node:child_process\";\nimport { constants } from \"node:fs\";\nimport { access as fsAccess } from \"node:fs/promises\";\nimport type { AgentTool } from \"omk-agent-core\";\nimport { Container, Text, truncateToWidth } from \"omk-tui\";\nimport { type Static, Type } from \"typebox\";\nimport { keyHint } from \"../../modes/interactive/components/keybinding-hints.ts\";\nimport { truncateToVisualLines } from \"../../modes/interactive/components/visual-truncate.ts\";\nimport { theme } from \"../../modes/interactive/theme/theme.ts\";\nimport { waitForChildProcess } from \"../../utils/child-process.ts\";\nimport {\n\tgetShellConfig,\n\tgetShellEnv,\n\tkillProcessTree,\n\ttrackDetachedChildPid,\n\tuntrackDetachedChildPid,\n} from \"../../utils/shell.ts\";\nimport { classifyShellCommand } from \"../command-safety.ts\";\nimport type { ExtensionContext, ToolDefinition, ToolRenderResultOptions } from \"../extensions/types.ts\";\nimport { assertLoadoutAccess, type LoadoutAccessGuard } from \"../loadout-access-policy.ts\";\nimport { detectSandboxBackend } from \"../sandbox/backend.ts\";\nimport type { SandboxBackendStatus, SandboxPathResolver, SandboxPolicy } from \"../sandbox/policy.ts\";\nimport { buildSandboxedSpawnRequest, type SandboxedSpawnRequest } from \"../sandbox/spawn.ts\";\nimport { OutputAccumulator } from \"./output-accumulator.ts\";\nimport { getTextOutput, invalidArgText, str } from \"./render-utils.ts\";\nimport { wrapToolDefinition } from \"./tool-definition-wrapper.ts\";\nimport { DEFAULT_MAX_BYTES, DEFAULT_MAX_LINES, formatSize, type TruncationResult } from \"./truncate.ts\";\n\nconst bashSchema = Type.Object({\n\tcommand: Type.String({ description: \"Bash command to execute\" }),\n\ttimeout: Type.Optional(Type.Number({ description: \"Timeout in seconds (optional, no default timeout)\" })),\n});\n\nexport type BashToolInput = Static<typeof bashSchema>;\n\nexport interface BashToolDetails {\n\ttruncation?: TruncationResult;\n\tfullOutputPath?: string;\n}\n\n/**\n * Pluggable operations for the bash tool.\n * Override these to delegate command execution to remote systems (for example SSH).\n */\nexport interface BashOperations {\n\t/**\n\t * Execute a command and stream output.\n\t * @param command The command to execute\n\t * @param cwd Working directory\n\t * @param options Execution options\n\t * @returns Promise resolving to exit code (null if killed)\n\t */\n\texec: (\n\t\tcommand: string,\n\t\tcwd: string,\n\t\toptions: {\n\t\t\tonData: (data: Buffer) => void;\n\t\t\tsignal?: AbortSignal;\n\t\t\ttimeout?: number;\n\t\t\tenv?: NodeJS.ProcessEnv;\n\t\t},\n\t) => Promise<{ exitCode: number | null }>;\n}\n\n/**\n * Create bash operations using OMK's built-in local shell execution backend.\n *\n * This is useful for extensions that intercept user_bash and still want OMK's\n * standard local shell behavior while wrapping, sandboxing, or rewriting commands.\n */\nexport function createLocalBashOperations(options?: {\n\tshellPath?: string;\n\tsandboxPolicy?: BashSandboxPreflight;\n}): BashOperations {\n\tconst sandbox = options?.sandboxPolicy;\n\treturn {\n\t\texec: async (command, cwd, { onData, signal, timeout, env }) => {\n\t\t\tconst { shell, args } = getShellConfig(options?.shellPath);\n\t\t\tlet spawnCommand = shell;\n\t\t\tlet spawnArgs = [...args, command];\n\t\t\tlet spawnCwd = cwd;\n\t\t\tlet spawnEnv: NodeJS.ProcessEnv = env ?? getShellEnv();\n\t\t\tif (sandbox) {\n\t\t\t\tconst backend = sandbox.backend ?? defaultBashSandboxBackend();\n\t\t\t\tconst request = buildSandboxedSpawnRequest({\n\t\t\t\t\targv: [shell, ...args, command],\n\t\t\t\t\tcwd,\n\t\t\t\t\tenv: spawnEnv,\n\t\t\t\t\tpolicy: sandbox.policy,\n\t\t\t\t\tbackend,\n\t\t\t\t\tresolver: sandbox.resolver,\n\t\t\t\t});\n\t\t\t\tsandbox.onSpawnDecision?.(request);\n\t\t\t\tif (!request.allowed) {\n\t\t\t\t\tthrow new Error(`sandbox: shell denied\\n[${request.rule}] ${request.reason}`);\n\t\t\t\t}\n\t\t\t\tspawnCommand = request.argv[0];\n\t\t\t\tspawnArgs = [...request.argv.slice(1)];\n\t\t\t\tspawnCwd = request.cwd;\n\t\t\t\tspawnEnv = request.env;\n\t\t\t}\n\t\t\ttry {\n\t\t\t\tawait fsAccess(spawnCwd, constants.F_OK);\n\t\t\t} catch {\n\t\t\t\tthrow new Error(`Working directory does not exist: ${spawnCwd}\\nCannot execute bash commands.`);\n\t\t\t}\n\t\t\tif (signal?.aborted) {\n\t\t\t\tthrow new Error(\"aborted\");\n\t\t\t}\n\n\t\t\t// nosemgrep: javascript.lang.security.detect-child-process.detect-child-process -- argv-array spawn; sandbox policy is applied above and shell mode is not used.\n\t\t\tconst child = spawn(spawnCommand, spawnArgs, {\n\t\t\t\tcwd: spawnCwd,\n\t\t\t\tdetached: process.platform !== \"win32\",\n\t\t\t\tenv: spawnEnv,\n\t\t\t\tstdio: [\"ignore\", \"pipe\", \"pipe\"],\n\t\t\t\twindowsHide: true,\n\t\t\t});\n\t\t\tif (child.pid) trackDetachedChildPid(child.pid);\n\t\t\tlet timedOut = false;\n\t\t\tlet timeoutHandle: NodeJS.Timeout | undefined;\n\t\t\tconst onAbort = () => {\n\t\t\t\tif (child.pid) killProcessTree(child.pid);\n\t\t\t};\n\n\t\t\ttry {\n\t\t\t\t// Set timeout if provided.\n\t\t\t\tif (timeout !== undefined && timeout > 0) {\n\t\t\t\t\ttimeoutHandle = setTimeout(() => {\n\t\t\t\t\t\ttimedOut = true;\n\t\t\t\t\t\tif (child.pid) killProcessTree(child.pid);\n\t\t\t\t\t}, timeout * 1000);\n\t\t\t\t}\n\t\t\t\t// Stream stdout and stderr.\n\t\t\t\tchild.stdout?.on(\"data\", onData);\n\t\t\t\tchild.stderr?.on(\"data\", onData);\n\t\t\t\t// Handle abort signal by killing the entire process tree.\n\t\t\t\tif (signal) {\n\t\t\t\t\tif (signal.aborted) onAbort();\n\t\t\t\t\telse signal.addEventListener(\"abort\", onAbort, { once: true });\n\t\t\t\t}\n\t\t\t\t// Handle shell spawn errors and wait for the process to terminate without hanging\n\t\t\t\t// on inherited stdio handles held by detached descendants.\n\t\t\t\tconst exitCode = await waitForChildProcess(child);\n\t\t\t\tif (signal?.aborted) {\n\t\t\t\t\tthrow new Error(\"aborted\");\n\t\t\t\t}\n\t\t\t\tif (timedOut) {\n\t\t\t\t\tthrow new Error(`timeout:${timeout}`);\n\t\t\t\t}\n\t\t\t\treturn { exitCode };\n\t\t\t} finally {\n\t\t\t\tif (child.pid) untrackDetachedChildPid(child.pid);\n\t\t\t\tif (timeoutHandle) clearTimeout(timeoutHandle);\n\t\t\t\tif (signal) signal.removeEventListener(\"abort\", onAbort);\n\t\t\t}\n\t\t},\n\t};\n}\n\n/**\n * Sandbox preflight inputs for local bash operations. When provided to\n * {@link createLocalBashOperations}, every spawn is gated by the sandbox spawn\n * builder: shell is denied when an OS sandbox backend is missing under enforce\n * mode, the environment is filtered, and available backends wrap the spawned\n * command. When omitted, local bash behavior is unchanged.\n */\nexport interface BashSandboxPreflight {\n\t/** Policy that decides whether this spawn may proceed. */\n\tpolicy: SandboxPolicy;\n\t/**\n\t * Availability of an OS-level sandbox backend. Local operations auto-detect\n\t * macOS sandbox-exec or Linux bubblewrap when this is omitted.\n\t */\n\tbackend?: SandboxBackendStatus;\n\t/** Optional resolver used to canonicalize the working directory before the root check. */\n\tresolver?: SandboxPathResolver;\n\t/** Observer for each sandbox spawn decision (audit/enforce ledger recording). */\n\tonSpawnDecision?: (decision: SandboxedSpawnRequest) => void;\n}\n\nfunction defaultBashSandboxBackend(): SandboxBackendStatus {\n\treturn detectSandboxBackend();\n}\n\nexport interface BashSpawnContext {\n\tcommand: string;\n\tcwd: string;\n\tenv: NodeJS.ProcessEnv;\n}\n\nexport type BashSpawnHook = (context: BashSpawnContext) => BashSpawnContext;\n\nconst SESSION_ENV_KEYS = [\"PI_SESSION_ID\", \"PI_SESSION_FILE\", \"PI_PROVIDER\", \"PI_MODEL\", \"PI_REASONING_LEVEL\"] as const;\n\nfunction resolveSpawnContext(\n\tcommand: string,\n\tcwd: string,\n\tspawnHook: BashSpawnHook | undefined,\n\texposeSessionEnvironment: boolean,\n\tctx: ExtensionContext | undefined,\n): BashSpawnContext {\n\tconst env = { ...getShellEnv() };\n\t// Anti-spoof: never inherit PI_* session metadata from the parent environment.\n\tfor (const key of SESSION_ENV_KEYS) delete env[key];\n\tif (exposeSessionEnvironment && ctx?.sessionManager) {\n\t\tconst model = ctx.model;\n\t\tenv.PI_SESSION_ID = ctx.sessionManager.getSessionId();\n\t\tconst sessionFile = ctx.sessionManager.getSessionFile();\n\t\tif (sessionFile) env.PI_SESSION_FILE = sessionFile;\n\t\tif (model) {\n\t\t\tenv.PI_PROVIDER = model.provider;\n\t\t\tenv.PI_MODEL = model.id;\n\t\t}\n\t\tif (ctx.thinkingLevel) env.PI_REASONING_LEVEL = ctx.thinkingLevel;\n\t}\n\tconst baseContext: BashSpawnContext = { command, cwd, env };\n\treturn spawnHook ? spawnHook(baseContext) : baseContext;\n}\n\nexport interface BashToolOptions {\n\t/** Custom operations for command execution. Default: local shell */\n\toperations?: BashOperations;\n\t/** Command prefix prepended to every command (for example shell setup commands) */\n\tcommandPrefix?: string;\n\t/** Optional explicit shell path from settings */\n\tshellPath?: string;\n\t/** Expose current session metadata as PI_* environment variables. Default: true */\n\texposeSessionEnvironment?: boolean;\n\t/** Trusted sandbox policy for local shell execution */\n\tsandboxPolicy?: BashSandboxPreflight;\n\tloadoutAccessGuard?: LoadoutAccessGuard;\n\t/** Hook to adjust command, cwd, or env before execution */\n\tspawnHook?: BashSpawnHook;\n}\n\nconst BASH_PREVIEW_LINES = 5;\nconst BASH_UPDATE_THROTTLE_MS = 100;\n\ntype BashRenderState = {\n\tstartedAt: number | undefined;\n\tendedAt: number | undefined;\n\tinterval: NodeJS.Timeout | undefined;\n};\n\ntype BashResultRenderState = {\n\tcachedWidth: number | undefined;\n\tcachedLines: string[] | undefined;\n\tcachedSkipped: number | undefined;\n};\n\nclass BashResultRenderComponent extends Container {\n\tstate: BashResultRenderState = {\n\t\tcachedWidth: undefined,\n\t\tcachedLines: undefined,\n\t\tcachedSkipped: undefined,\n\t};\n}\n\nfunction formatDuration(ms: number): string {\n\treturn `${(ms / 1000).toFixed(1)}s`;\n}\n\nfunction formatBashCall(args: { command?: string; timeout?: number } | undefined): string {\n\tconst command = str(args?.command);\n\tconst timeout = args?.timeout as number | undefined;\n\tconst timeoutSuffix = timeout ? theme.fg(\"muted\", ` (timeout ${timeout}s)`) : \"\";\n\tconst commandDisplay = command === null ? invalidArgText(theme) : command ? command : theme.fg(\"toolOutput\", \"...\");\n\treturn theme.fg(\"toolTitle\", theme.bold(`$ ${commandDisplay}`)) + timeoutSuffix;\n}\n\nfunction rebuildBashResultRenderComponent(\n\tcomponent: BashResultRenderComponent,\n\tresult: {\n\t\tcontent: Array<{ type: string; text?: string; data?: string; mimeType?: string }>;\n\t\tdetails?: BashToolDetails;\n\t},\n\toptions: ToolRenderResultOptions,\n\tshowImages: boolean,\n\tstartedAt: number | undefined,\n\tendedAt: number | undefined,\n): void {\n\tconst state = component.state;\n\tcomponent.clear();\n\n\tlet output = getTextOutput(result as any, showImages).trim();\n\tconst truncation = result.details?.truncation;\n\tconst fullOutputPath = result.details?.fullOutputPath;\n\tif (!options.isPartial && truncation?.truncated && fullOutputPath && output.endsWith(\"]\")) {\n\t\tconst footerStart = output.lastIndexOf(\"\\n\\n[\");\n\t\tif (footerStart !== -1 && output.slice(footerStart).includes(fullOutputPath)) {\n\t\t\toutput = output.slice(0, footerStart).trimEnd();\n\t\t}\n\t}\n\n\tif (output) {\n\t\tconst styledOutput = output\n\t\t\t.split(\"\\n\")\n\t\t\t.map((line) => theme.fg(\"toolOutput\", line))\n\t\t\t.join(\"\\n\");\n\n\t\tif (options.expanded) {\n\t\t\tcomponent.addChild(new Text(`\\n${styledOutput}`, 0, 0));\n\t\t} else {\n\t\t\tcomponent.addChild({\n\t\t\t\trender: (width: number) => {\n\t\t\t\t\tif (state.cachedLines === undefined || state.cachedWidth !== width) {\n\t\t\t\t\t\tconst preview = truncateToVisualLines(styledOutput, BASH_PREVIEW_LINES, width);\n\t\t\t\t\t\tstate.cachedLines = preview.visualLines;\n\t\t\t\t\t\tstate.cachedSkipped = preview.skippedCount;\n\t\t\t\t\t\tstate.cachedWidth = width;\n\t\t\t\t\t}\n\t\t\t\t\tif (state.cachedSkipped && state.cachedSkipped > 0) {\n\t\t\t\t\t\tconst hint =\n\t\t\t\t\t\t\ttheme.fg(\"muted\", `... (${state.cachedSkipped} earlier lines,`) +\n\t\t\t\t\t\t\t` ${keyHint(\"app.tools.expand\", \"to expand\")})`;\n\t\t\t\t\t\treturn [\"\", truncateToWidth(hint, width, \"...\"), ...(state.cachedLines ?? [])];\n\t\t\t\t\t}\n\t\t\t\t\treturn [\"\", ...(state.cachedLines ?? [])];\n\t\t\t\t},\n\t\t\t\tinvalidate: () => {\n\t\t\t\t\tstate.cachedWidth = undefined;\n\t\t\t\t\tstate.cachedLines = undefined;\n\t\t\t\t\tstate.cachedSkipped = undefined;\n\t\t\t\t},\n\t\t\t});\n\t\t}\n\t}\n\n\tif (truncation?.truncated || fullOutputPath) {\n\t\tconst warnings: string[] = [];\n\t\tif (fullOutputPath) {\n\t\t\twarnings.push(`Full output: ${fullOutputPath}`);\n\t\t}\n\t\tif (truncation?.truncated) {\n\t\t\tif (truncation.truncatedBy === \"lines\") {\n\t\t\t\twarnings.push(`Truncated: showing ${truncation.outputLines} of ${truncation.totalLines} lines`);\n\t\t\t} else {\n\t\t\t\twarnings.push(\n\t\t\t\t\t`Truncated: ${truncation.outputLines} lines shown (${formatSize(truncation.maxBytes ?? DEFAULT_MAX_BYTES)} limit)`,\n\t\t\t\t);\n\t\t\t}\n\t\t}\n\t\tcomponent.addChild(new Text(`\\n${theme.fg(\"warning\", `[${warnings.join(\". \")}]`)}`, 0, 0));\n\t}\n\n\tif (startedAt !== undefined) {\n\t\tconst label = options.isPartial ? \"Elapsed\" : \"Took\";\n\t\tconst endTime = endedAt ?? Date.now();\n\t\tcomponent.addChild(new Text(`\\n${theme.fg(\"muted\", `${label} ${formatDuration(endTime - startedAt)}`)}`, 0, 0));\n\t}\n}\n\nexport function createBashToolDefinition(\n\tcwd: string,\n\toptions?: BashToolOptions,\n): ToolDefinition<typeof bashSchema, BashToolDetails | undefined, BashRenderState> {\n\tconst ops =\n\t\toptions?.operations ??\n\t\tcreateLocalBashOperations({ shellPath: options?.shellPath, sandboxPolicy: options?.sandboxPolicy });\n\tconst commandPrefix = options?.commandPrefix;\n\tconst exposeSessionEnvironment = options?.exposeSessionEnvironment ?? true;\n\tconst spawnHook = options?.spawnHook;\n\treturn {\n\t\tname: \"bash\",\n\t\tlabel: \"bash\",\n\t\tdescription: `Execute a bash command in the current working directory. Returns stdout and stderr. Output is truncated to last ${DEFAULT_MAX_LINES} lines or ${DEFAULT_MAX_BYTES / 1024}KB (whichever is hit first). If truncated, full output is saved to a temp file. Optionally provide a timeout in seconds.`,\n\t\tpromptSnippet: \"Execute bash commands (ls, grep, find, etc.)\",\n\t\tpromptGuidelines: exposeSessionEnvironment\n\t\t\t? [\"Inspect PI_* environment variables for current model and session details.\"]\n\t\t\t: undefined,\n\t\tparameters: bashSchema,\n\t\tasync execute(\n\t\t\t_toolCallId,\n\t\t\t{ command, timeout }: { command: string; timeout?: number },\n\t\t\tsignal?: AbortSignal,\n\t\t\tonUpdate?,\n\t\t\tctx?,\n\t\t) {\n\t\t\tconst resolvedCommand = commandPrefix ? `${commandPrefix}\\n${command}` : command;\n\t\t\tconst spawnContext = resolveSpawnContext(resolvedCommand, cwd, spawnHook, exposeSessionEnvironment, ctx);\n\t\t\tassertLoadoutAccess(options?.loadoutAccessGuard, {\n\t\t\t\toperation: \"execute\",\n\t\t\t\ttoolName: \"bash\",\n\t\t\t\tcommand: spawnContext.command,\n\t\t\t});\n\n\t\t\t// Safety floor: re-classify the EFFECTIVE command after commandPrefix/spawnHook.\n\t\t\t// Skipped entirely in YOLO mode (OMK_YOLO=1 / OMK_COMMAND_SAFETY=0).\n\t\t\tconst yolo =\n\t\t\t\tprocess.env.OMK_YOLO === \"1\" ||\n\t\t\t\tprocess.env.OMK_YOLO === \"true\" ||\n\t\t\t\tprocess.env.OMK_DISABLE_COMMAND_SAFETY === \"1\" ||\n\t\t\t\tprocess.env.OMK_DISABLE_COMMAND_SAFETY === \"true\" ||\n\t\t\t\t[\"0\", \"false\", \"off\", \"disable\", \"disabled\"].includes(\n\t\t\t\t\tString(process.env.OMK_COMMAND_SAFETY ?? \"\").toLowerCase(),\n\t\t\t\t);\n\t\t\tif (!yolo) {\n\t\t\t\tconst effectiveVerdict = classifyShellCommand(spawnContext.command);\n\t\t\t\tif (effectiveVerdict.risk === \"block\") {\n\t\t\t\t\tthrow new Error(`command-safety: blocked\\n[${effectiveVerdict.rule}] ${effectiveVerdict.reason}`);\n\t\t\t\t}\n\t\t\t}\n\n\t\t\tconst output = new OutputAccumulator({ tempFilePrefix: \"omk-bash\" });\n\t\t\tlet updateTimer: NodeJS.Timeout | undefined;\n\t\t\tlet updateDirty = false;\n\t\t\tlet lastUpdateAt = 0;\n\n\t\t\tconst emitOutputUpdate = () => {\n\t\t\t\tif (!onUpdate || !updateDirty) return;\n\t\t\t\tupdateDirty = false;\n\t\t\t\tlastUpdateAt = Date.now();\n\t\t\t\tconst snapshot = output.snapshot({ persistIfTruncated: true });\n\t\t\t\tonUpdate({\n\t\t\t\t\tcontent: [{ type: \"text\", text: snapshot.content || \"\" }],\n\t\t\t\t\tdetails: {\n\t\t\t\t\t\ttruncation: snapshot.truncation.truncated ? snapshot.truncation : undefined,\n\t\t\t\t\t\tfullOutputPath: snapshot.fullOutputPath,\n\t\t\t\t\t},\n\t\t\t\t});\n\t\t\t};\n\n\t\t\tconst clearUpdateTimer = () => {\n\t\t\t\tif (updateTimer) {\n\t\t\t\t\tclearTimeout(updateTimer);\n\t\t\t\t\tupdateTimer = undefined;\n\t\t\t\t}\n\t\t\t};\n\n\t\t\tconst scheduleOutputUpdate = () => {\n\t\t\t\tif (!onUpdate) return;\n\t\t\t\tupdateDirty = true;\n\t\t\t\tconst delay = BASH_UPDATE_THROTTLE_MS - (Date.now() - lastUpdateAt);\n\t\t\t\tif (delay <= 0) {\n\t\t\t\t\tclearUpdateTimer();\n\t\t\t\t\temitOutputUpdate();\n\t\t\t\t\treturn;\n\t\t\t\t}\n\t\t\t\tupdateTimer ??= setTimeout(() => {\n\t\t\t\t\tupdateTimer = undefined;\n\t\t\t\t\temitOutputUpdate();\n\t\t\t\t}, delay);\n\t\t\t};\n\n\t\t\tif (onUpdate) {\n\t\t\t\tonUpdate({ content: [], details: undefined });\n\t\t\t}\n\n\t\t\tconst handleData = (data: Buffer) => {\n\t\t\t\toutput.append(data);\n\t\t\t\tscheduleOutputUpdate();\n\t\t\t};\n\n\t\t\tconst finishOutput = async () => {\n\t\t\t\toutput.finish();\n\t\t\t\tclearUpdateTimer();\n\t\t\t\temitOutputUpdate();\n\t\t\t\tconst snapshot = output.snapshot({ persistIfTruncated: true });\n\t\t\t\tawait output.closeTempFile();\n\t\t\t\treturn snapshot;\n\t\t\t};\n\n\t\t\tconst formatOutput = (snapshot: Awaited<ReturnType<typeof finishOutput>>, emptyText = \"(no output)\") => {\n\t\t\t\tconst truncation = snapshot.truncation;\n\t\t\t\tlet text = snapshot.content || emptyText;\n\t\t\t\tlet details: BashToolDetails | undefined;\n\t\t\t\tif (truncation.truncated) {\n\t\t\t\t\tdetails = { truncation, fullOutputPath: snapshot.fullOutputPath };\n\t\t\t\t\tconst startLine = truncation.totalLines - truncation.outputLines + 1;\n\t\t\t\t\tconst endLine = truncation.totalLines;\n\t\t\t\t\tif (truncation.lastLinePartial) {\n\t\t\t\t\t\tconst lastLineSize = formatSize(output.getLastLineBytes());\n\t\t\t\t\t\ttext += `\\n\\n[Showing last ${formatSize(truncation.outputBytes)} of line ${endLine} (line is ${lastLineSize}). Full output: ${snapshot.fullOutputPath}]`;\n\t\t\t\t\t} else if (truncation.truncatedBy === \"lines\") {\n\t\t\t\t\t\ttext += `\\n\\n[Showing lines ${startLine}-${endLine} of ${truncation.totalLines}. Full output: ${snapshot.fullOutputPath}]`;\n\t\t\t\t\t} else {\n\t\t\t\t\t\ttext += `\\n\\n[Showing lines ${startLine}-${endLine} of ${truncation.totalLines} (${formatSize(DEFAULT_MAX_BYTES)} limit). Full output: ${snapshot.fullOutputPath}]`;\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t\treturn { text, details };\n\t\t\t};\n\n\t\t\tconst appendStatus = (text: string, status: string) => `${text ? `${text}\\n\\n` : \"\"}${status}`;\n\n\t\t\ttry {\n\t\t\t\tlet exitCode: number | null;\n\t\t\t\ttry {\n\t\t\t\t\tconst result = await ops.exec(spawnContext.command, spawnContext.cwd, {\n\t\t\t\t\t\tonData: handleData,\n\t\t\t\t\t\tsignal,\n\t\t\t\t\t\ttimeout,\n\t\t\t\t\t\tenv: spawnContext.env,\n\t\t\t\t\t});\n\t\t\t\t\texitCode = result.exitCode;\n\t\t\t\t} catch (err) {\n\t\t\t\t\tconst snapshot = await finishOutput();\n\t\t\t\t\tconst { text } = formatOutput(snapshot, \"\");\n\t\t\t\t\tif (err instanceof Error && err.message === \"aborted\") {\n\t\t\t\t\t\tthrow new Error(appendStatus(text, \"Command aborted\"));\n\t\t\t\t\t}\n\t\t\t\t\tif (err instanceof Error && err.message.startsWith(\"timeout:\")) {\n\t\t\t\t\t\tconst timeoutSecs = err.message.split(\":\")[1];\n\t\t\t\t\t\tthrow new Error(appendStatus(text, `Command timed out after ${timeoutSecs} seconds`));\n\t\t\t\t\t}\n\t\t\t\t\tthrow err;\n\t\t\t\t}\n\n\t\t\t\tconst snapshot = await finishOutput();\n\t\t\t\tconst { text: outputText, details } = formatOutput(snapshot);\n\t\t\t\tif (exitCode !== 0 && exitCode !== null) {\n\t\t\t\t\tthrow new Error(appendStatus(outputText, `Command exited with code ${exitCode}`));\n\t\t\t\t}\n\t\t\t\treturn { content: [{ type: \"text\", text: outputText }], details };\n\t\t\t} finally {\n\t\t\t\tclearUpdateTimer();\n\t\t\t}\n\t\t},\n\t\trenderCall(args, _theme, context) {\n\t\t\tconst state = context.state;\n\t\t\tif (context.executionStarted && state.startedAt === undefined) {\n\t\t\t\tstate.startedAt = Date.now();\n\t\t\t\tstate.endedAt = undefined;\n\t\t\t}\n\t\t\tconst text = (context.lastComponent as Text | undefined) ?? new Text(\"\", 0, 0);\n\t\t\ttext.setText(formatBashCall(args));\n\t\t\treturn text;\n\t\t},\n\t\trenderResult(result, options, _theme, context) {\n\t\t\tconst state = context.state;\n\t\t\tif (state.startedAt !== undefined && options.isPartial && !state.interval) {\n\t\t\t\tstate.interval = setInterval(() => context.invalidate(), 1000);\n\t\t\t}\n\t\t\tif (!options.isPartial || context.isError) {\n\t\t\t\tstate.endedAt ??= Date.now();\n\t\t\t\tif (state.interval) {\n\t\t\t\t\tclearInterval(state.interval);\n\t\t\t\t\tstate.interval = undefined;\n\t\t\t\t}\n\t\t\t}\n\t\t\tconst component =\n\t\t\t\t(context.lastComponent as BashResultRenderComponent | undefined) ?? new BashResultRenderComponent();\n\t\t\trebuildBashResultRenderComponent(\n\t\t\t\tcomponent,\n\t\t\t\tresult as any,\n\t\t\t\toptions,\n\t\t\t\tcontext.showImages,\n\t\t\t\tstate.startedAt,\n\t\t\t\tstate.endedAt,\n\t\t\t);\n\t\t\tcomponent.invalidate();\n\t\t\treturn component;\n\t\t},\n\t};\n}\n\nexport function createBashTool(cwd: string, options?: BashToolOptions): AgentTool<typeof bashSchema> {\n\treturn wrapToolDefinition(createBashToolDefinition(cwd, options));\n}\n"]}
1
+ {"version":3,"file":"bash.d.ts","sourceRoot":"","sources":["../../../src/core/tools/bash.ts"],"names":[],"mappings":"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","sourcesContent":["import { spawn } from \"node:child_process\";\nimport { constants } from \"node:fs\";\nimport { access as fsAccess } from \"node:fs/promises\";\nimport type { AgentTool } from \"omk-agent-core\";\nimport { Container, Text, truncateToWidth } from \"omk-tui\";\nimport { type Static, Type } from \"typebox\";\nimport { keyHint } from \"../../modes/interactive/components/keybinding-hints.ts\";\nimport { truncateToVisualLines } from \"../../modes/interactive/components/visual-truncate.ts\";\nimport { theme } from \"../../modes/interactive/theme/theme.ts\";\nimport { waitForChildProcess } from \"../../utils/child-process.ts\";\nimport {\n\tgetShellConfig,\n\tgetShellEnv,\n\tkillProcessTree,\n\ttrackDetachedChildPid,\n\tuntrackDetachedChildPid,\n} from \"../../utils/shell.ts\";\nimport { classifyShellCommand } from \"../command-safety.ts\";\nimport type { ExtensionContext, ToolDefinition, ToolRenderResultOptions } from \"../extensions/types.ts\";\nimport { assertLoadoutAccess, type LoadoutAccessGuard } from \"../loadout-access-policy.ts\";\nimport { detectSandboxBackend } from \"../sandbox/backend.ts\";\nimport type { SandboxBackendStatus, SandboxPathResolver, SandboxPolicy } from \"../sandbox/policy.ts\";\nimport { buildSandboxedSpawnRequest, type SandboxedSpawnRequest } from \"../sandbox/spawn.ts\";\nimport { OutputAccumulator } from \"./output-accumulator.ts\";\nimport { getTextOutput, invalidArgText, str } from \"./render-utils.ts\";\nimport { wrapToolDefinition } from \"./tool-definition-wrapper.ts\";\nimport { DEFAULT_MAX_BYTES, DEFAULT_MAX_LINES, formatSize, type TruncationResult } from \"./truncate.ts\";\n\nconst bashSchema = Type.Object({\n\tcommand: Type.String({ description: \"Bash command to execute\" }),\n\ttimeout: Type.Optional(Type.Number({ description: \"Timeout in seconds (optional, no default timeout)\" })),\n});\n\nexport type BashToolInput = Static<typeof bashSchema>;\n\nexport interface BashToolDetails {\n\ttruncation?: TruncationResult;\n\tfullOutputPath?: string;\n}\n\n/**\n * Pluggable operations for the bash tool.\n * Override these to delegate command execution to remote systems (for example SSH).\n */\nexport interface BashOperations {\n\t/**\n\t * Execute a command and stream output.\n\t * @param command The command to execute\n\t * @param cwd Working directory\n\t * @param options Execution options\n\t * @returns Promise resolving to exit code (null if killed)\n\t */\n\texec: (\n\t\tcommand: string,\n\t\tcwd: string,\n\t\toptions: {\n\t\t\tonData: (data: Buffer) => void;\n\t\t\tsignal?: AbortSignal;\n\t\t\ttimeout?: number;\n\t\t\tenv?: NodeJS.ProcessEnv;\n\t\t},\n\t) => Promise<{ exitCode: number | null }>;\n}\n\n/**\n * Create bash operations using OMK's built-in local shell execution backend.\n *\n * This is useful for extensions that intercept user_bash and still want OMK's\n * standard local shell behavior while wrapping, sandboxing, or rewriting commands.\n */\nexport interface LocalBashOperationsOptions {\n\treadonly shellPath?: string;\n\treadonly sandboxPolicy?: BashSandboxPreflight;\n\t/** Override backend probing for embedders and deterministic tests. */\n\treadonly detectSandboxBackend?: () => SandboxBackendStatus;\n}\n\nexport function createLocalBashOperations(options?: LocalBashOperationsOptions): BashOperations {\n\tconst sandbox = options?.sandboxPolicy;\n\tlet detectedBackend: SandboxBackendStatus | undefined;\n\tconst resolveBackend = (): SandboxBackendStatus => {\n\t\tif (sandbox?.backend) return sandbox.backend;\n\t\tdetectedBackend ??= (options?.detectSandboxBackend ?? defaultBashSandboxBackend)();\n\t\treturn detectedBackend;\n\t};\n\treturn {\n\t\texec: async (command, cwd, { onData, signal, timeout, env }) => {\n\t\t\tconst { shell, args } = getShellConfig(options?.shellPath);\n\t\t\tlet spawnCommand = shell;\n\t\t\tlet spawnArgs = [...args, command];\n\t\t\tlet spawnCwd = cwd;\n\t\t\tlet spawnEnv: NodeJS.ProcessEnv = env ?? getShellEnv();\n\t\t\tif (sandbox) {\n\t\t\t\tconst backend = resolveBackend();\n\t\t\t\tconst request = buildSandboxedSpawnRequest({\n\t\t\t\t\targv: [shell, ...args, command],\n\t\t\t\t\tcwd,\n\t\t\t\t\tenv: spawnEnv,\n\t\t\t\t\tpolicy: sandbox.policy,\n\t\t\t\t\tbackend,\n\t\t\t\t\tresolver: sandbox.resolver,\n\t\t\t\t});\n\t\t\t\tsandbox.onSpawnDecision?.(request);\n\t\t\t\tif (!request.allowed) {\n\t\t\t\t\tthrow new Error(`sandbox: shell denied\\n[${request.rule}] ${request.reason}`);\n\t\t\t\t}\n\t\t\t\tspawnCommand = request.argv[0];\n\t\t\t\tspawnArgs = [...request.argv.slice(1)];\n\t\t\t\tspawnCwd = request.cwd;\n\t\t\t\tspawnEnv = request.env;\n\t\t\t}\n\t\t\ttry {\n\t\t\t\tawait fsAccess(spawnCwd, constants.F_OK);\n\t\t\t} catch {\n\t\t\t\tthrow new Error(`Working directory does not exist: ${spawnCwd}\\nCannot execute bash commands.`);\n\t\t\t}\n\t\t\tif (signal?.aborted) {\n\t\t\t\tthrow new Error(\"aborted\");\n\t\t\t}\n\n\t\t\t// nosemgrep: javascript.lang.security.detect-child-process.detect-child-process -- argv-array spawn; sandbox policy is applied above and shell mode is not used.\n\t\t\tconst child = spawn(spawnCommand, spawnArgs, {\n\t\t\t\tcwd: spawnCwd,\n\t\t\t\tdetached: process.platform !== \"win32\",\n\t\t\t\tenv: spawnEnv,\n\t\t\t\tstdio: [\"ignore\", \"pipe\", \"pipe\"],\n\t\t\t\twindowsHide: true,\n\t\t\t});\n\t\t\tif (child.pid) trackDetachedChildPid(child.pid);\n\t\t\tlet timedOut = false;\n\t\t\tlet timeoutHandle: NodeJS.Timeout | undefined;\n\t\t\tconst onAbort = () => {\n\t\t\t\tif (child.pid) killProcessTree(child.pid);\n\t\t\t};\n\n\t\t\ttry {\n\t\t\t\t// Set timeout if provided.\n\t\t\t\tif (timeout !== undefined && timeout > 0) {\n\t\t\t\t\ttimeoutHandle = setTimeout(() => {\n\t\t\t\t\t\ttimedOut = true;\n\t\t\t\t\t\tif (child.pid) killProcessTree(child.pid);\n\t\t\t\t\t}, timeout * 1000);\n\t\t\t\t}\n\t\t\t\t// Stream stdout and stderr.\n\t\t\t\tchild.stdout?.on(\"data\", onData);\n\t\t\t\tchild.stderr?.on(\"data\", onData);\n\t\t\t\t// Handle abort signal by killing the entire process tree.\n\t\t\t\tif (signal) {\n\t\t\t\t\tif (signal.aborted) onAbort();\n\t\t\t\t\telse signal.addEventListener(\"abort\", onAbort, { once: true });\n\t\t\t\t}\n\t\t\t\t// Handle shell spawn errors and wait for the process to terminate without hanging\n\t\t\t\t// on inherited stdio handles held by detached descendants.\n\t\t\t\tconst exitCode = await waitForChildProcess(child);\n\t\t\t\tif (signal?.aborted) {\n\t\t\t\t\tthrow new Error(\"aborted\");\n\t\t\t\t}\n\t\t\t\tif (timedOut) {\n\t\t\t\t\tthrow new Error(`timeout:${timeout}`);\n\t\t\t\t}\n\t\t\t\treturn { exitCode };\n\t\t\t} finally {\n\t\t\t\tif (child.pid) untrackDetachedChildPid(child.pid);\n\t\t\t\tif (timeoutHandle) clearTimeout(timeoutHandle);\n\t\t\t\tif (signal) signal.removeEventListener(\"abort\", onAbort);\n\t\t\t}\n\t\t},\n\t};\n}\n\n/**\n * Sandbox preflight inputs for local bash operations. When provided to\n * {@link createLocalBashOperations}, every spawn is gated by the sandbox spawn\n * builder: shell is denied when an OS sandbox backend is missing under enforce\n * mode, the environment is filtered, and available backends wrap the spawned\n * command. When omitted, local bash behavior is unchanged.\n */\nexport interface BashSandboxPreflight {\n\t/** Policy that decides whether this spawn may proceed. */\n\tpolicy: SandboxPolicy;\n\t/**\n\t * Availability of an OS-level sandbox backend. Local operations auto-detect\n\t * macOS sandbox-exec or Linux bubblewrap when this is omitted.\n\t */\n\tbackend?: SandboxBackendStatus;\n\t/** Optional resolver used to canonicalize the working directory before the root check. */\n\tresolver?: SandboxPathResolver;\n\t/** Observer for each sandbox spawn decision (audit/enforce ledger recording). */\n\tonSpawnDecision?: (decision: SandboxedSpawnRequest) => void;\n}\n\nfunction defaultBashSandboxBackend(): SandboxBackendStatus {\n\treturn detectSandboxBackend();\n}\n\nexport interface BashSpawnContext {\n\tcommand: string;\n\tcwd: string;\n\tenv: NodeJS.ProcessEnv;\n}\n\nexport type BashSpawnHook = (context: BashSpawnContext) => BashSpawnContext;\n\nconst SESSION_ENV_KEYS = [\"PI_SESSION_ID\", \"PI_SESSION_FILE\", \"PI_PROVIDER\", \"PI_MODEL\", \"PI_REASONING_LEVEL\"] as const;\n\nfunction resolveSpawnContext(\n\tcommand: string,\n\tcwd: string,\n\tspawnHook: BashSpawnHook | undefined,\n\texposeSessionEnvironment: boolean,\n\tctx: ExtensionContext | undefined,\n): BashSpawnContext {\n\tconst env = { ...getShellEnv() };\n\t// Anti-spoof: never inherit PI_* session metadata from the parent environment.\n\tfor (const key of SESSION_ENV_KEYS) delete env[key];\n\tif (exposeSessionEnvironment && ctx?.sessionManager) {\n\t\tconst model = ctx.model;\n\t\tenv.PI_SESSION_ID = ctx.sessionManager.getSessionId();\n\t\tconst sessionFile = ctx.sessionManager.getSessionFile();\n\t\tif (sessionFile) env.PI_SESSION_FILE = sessionFile;\n\t\tif (model) {\n\t\t\tenv.PI_PROVIDER = model.provider;\n\t\t\tenv.PI_MODEL = model.id;\n\t\t}\n\t\tif (ctx.thinkingLevel) env.PI_REASONING_LEVEL = ctx.thinkingLevel;\n\t}\n\tconst baseContext: BashSpawnContext = { command, cwd, env };\n\treturn spawnHook ? spawnHook(baseContext) : baseContext;\n}\n\nexport interface BashToolOptions {\n\t/** Custom operations for command execution. Default: local shell */\n\toperations?: BashOperations;\n\t/** Command prefix prepended to every command (for example shell setup commands) */\n\tcommandPrefix?: string;\n\t/** Optional explicit shell path from settings */\n\tshellPath?: string;\n\t/** Expose current session metadata as PI_* environment variables. Default: true */\n\texposeSessionEnvironment?: boolean;\n\t/** Trusted sandbox policy for local shell execution */\n\tsandboxPolicy?: BashSandboxPreflight;\n\tloadoutAccessGuard?: LoadoutAccessGuard;\n\t/** Hook to adjust command, cwd, or env before execution */\n\tspawnHook?: BashSpawnHook;\n}\n\nconst BASH_PREVIEW_LINES = 5;\nconst BASH_UPDATE_THROTTLE_MS = 100;\n\ntype BashRenderState = {\n\tstartedAt: number | undefined;\n\tendedAt: number | undefined;\n\tinterval: NodeJS.Timeout | undefined;\n};\n\ntype BashResultRenderState = {\n\tcachedWidth: number | undefined;\n\tcachedLines: string[] | undefined;\n\tcachedSkipped: number | undefined;\n};\n\nclass BashResultRenderComponent extends Container {\n\tstate: BashResultRenderState = {\n\t\tcachedWidth: undefined,\n\t\tcachedLines: undefined,\n\t\tcachedSkipped: undefined,\n\t};\n}\n\nfunction formatDuration(ms: number): string {\n\treturn `${(ms / 1000).toFixed(1)}s`;\n}\n\nfunction formatBashCall(args: { command?: string; timeout?: number } | undefined): string {\n\tconst command = str(args?.command);\n\tconst timeout = args?.timeout as number | undefined;\n\tconst timeoutSuffix = timeout ? theme.fg(\"muted\", ` (timeout ${timeout}s)`) : \"\";\n\tconst commandDisplay = command === null ? invalidArgText(theme) : command ? command : theme.fg(\"toolOutput\", \"...\");\n\treturn theme.fg(\"toolTitle\", theme.bold(`$ ${commandDisplay}`)) + timeoutSuffix;\n}\n\nfunction rebuildBashResultRenderComponent(\n\tcomponent: BashResultRenderComponent,\n\tresult: {\n\t\tcontent: Array<{ type: string; text?: string; data?: string; mimeType?: string }>;\n\t\tdetails?: BashToolDetails;\n\t},\n\toptions: ToolRenderResultOptions,\n\tshowImages: boolean,\n\tstartedAt: number | undefined,\n\tendedAt: number | undefined,\n): void {\n\tconst state = component.state;\n\tcomponent.clear();\n\n\tlet output = getTextOutput(result as any, showImages).trim();\n\tconst truncation = result.details?.truncation;\n\tconst fullOutputPath = result.details?.fullOutputPath;\n\tif (!options.isPartial && truncation?.truncated && fullOutputPath && output.endsWith(\"]\")) {\n\t\tconst footerStart = output.lastIndexOf(\"\\n\\n[\");\n\t\tif (footerStart !== -1 && output.slice(footerStart).includes(fullOutputPath)) {\n\t\t\toutput = output.slice(0, footerStart).trimEnd();\n\t\t}\n\t}\n\n\tif (output) {\n\t\tconst styledOutput = output\n\t\t\t.split(\"\\n\")\n\t\t\t.map((line) => theme.fg(\"toolOutput\", line))\n\t\t\t.join(\"\\n\");\n\n\t\tif (options.expanded) {\n\t\t\tcomponent.addChild(new Text(`\\n${styledOutput}`, 0, 0));\n\t\t} else {\n\t\t\tcomponent.addChild({\n\t\t\t\trender: (width: number) => {\n\t\t\t\t\tif (state.cachedLines === undefined || state.cachedWidth !== width) {\n\t\t\t\t\t\tconst preview = truncateToVisualLines(styledOutput, BASH_PREVIEW_LINES, width);\n\t\t\t\t\t\tstate.cachedLines = preview.visualLines;\n\t\t\t\t\t\tstate.cachedSkipped = preview.skippedCount;\n\t\t\t\t\t\tstate.cachedWidth = width;\n\t\t\t\t\t}\n\t\t\t\t\tif (state.cachedSkipped && state.cachedSkipped > 0) {\n\t\t\t\t\t\tconst hint =\n\t\t\t\t\t\t\ttheme.fg(\"muted\", `... (${state.cachedSkipped} earlier lines,`) +\n\t\t\t\t\t\t\t` ${keyHint(\"app.tools.expand\", \"to expand\")})`;\n\t\t\t\t\t\treturn [\"\", truncateToWidth(hint, width, \"...\"), ...(state.cachedLines ?? [])];\n\t\t\t\t\t}\n\t\t\t\t\treturn [\"\", ...(state.cachedLines ?? [])];\n\t\t\t\t},\n\t\t\t\tinvalidate: () => {\n\t\t\t\t\tstate.cachedWidth = undefined;\n\t\t\t\t\tstate.cachedLines = undefined;\n\t\t\t\t\tstate.cachedSkipped = undefined;\n\t\t\t\t},\n\t\t\t});\n\t\t}\n\t}\n\n\tif (truncation?.truncated || fullOutputPath) {\n\t\tconst warnings: string[] = [];\n\t\tif (fullOutputPath) {\n\t\t\twarnings.push(`Full output: ${fullOutputPath}`);\n\t\t}\n\t\tif (truncation?.truncated) {\n\t\t\tif (truncation.truncatedBy === \"lines\") {\n\t\t\t\twarnings.push(`Truncated: showing ${truncation.outputLines} of ${truncation.totalLines} lines`);\n\t\t\t} else {\n\t\t\t\twarnings.push(\n\t\t\t\t\t`Truncated: ${truncation.outputLines} lines shown (${formatSize(truncation.maxBytes ?? DEFAULT_MAX_BYTES)} limit)`,\n\t\t\t\t);\n\t\t\t}\n\t\t}\n\t\tcomponent.addChild(new Text(`\\n${theme.fg(\"warning\", `[${warnings.join(\". \")}]`)}`, 0, 0));\n\t}\n\n\tif (startedAt !== undefined) {\n\t\tconst label = options.isPartial ? \"Elapsed\" : \"Took\";\n\t\tconst endTime = endedAt ?? Date.now();\n\t\tcomponent.addChild(new Text(`\\n${theme.fg(\"muted\", `${label} ${formatDuration(endTime - startedAt)}`)}`, 0, 0));\n\t}\n}\n\nexport function createBashToolDefinition(\n\tcwd: string,\n\toptions?: BashToolOptions,\n): ToolDefinition<typeof bashSchema, BashToolDetails | undefined, BashRenderState> {\n\tconst ops =\n\t\toptions?.operations ??\n\t\tcreateLocalBashOperations({ shellPath: options?.shellPath, sandboxPolicy: options?.sandboxPolicy });\n\tconst commandPrefix = options?.commandPrefix;\n\tconst exposeSessionEnvironment = options?.exposeSessionEnvironment ?? true;\n\tconst spawnHook = options?.spawnHook;\n\treturn {\n\t\tname: \"bash\",\n\t\tlabel: \"bash\",\n\t\tdescription: `Execute a bash command in the current working directory. Returns stdout and stderr. Output is truncated to last ${DEFAULT_MAX_LINES} lines or ${DEFAULT_MAX_BYTES / 1024}KB (whichever is hit first). If truncated, full output is saved to a temp file. Optionally provide a timeout in seconds.`,\n\t\tpromptSnippet: \"Execute bash commands (ls, grep, find, etc.)\",\n\t\tpromptGuidelines: exposeSessionEnvironment\n\t\t\t? [\"Inspect PI_* environment variables for current model and session details.\"]\n\t\t\t: undefined,\n\t\tparameters: bashSchema,\n\t\tasync execute(\n\t\t\t_toolCallId,\n\t\t\t{ command, timeout }: { command: string; timeout?: number },\n\t\t\tsignal?: AbortSignal,\n\t\t\tonUpdate?,\n\t\t\tctx?,\n\t\t) {\n\t\t\tconst resolvedCommand = commandPrefix ? `${commandPrefix}\\n${command}` : command;\n\t\t\tconst spawnContext = resolveSpawnContext(resolvedCommand, cwd, spawnHook, exposeSessionEnvironment, ctx);\n\t\t\tassertLoadoutAccess(options?.loadoutAccessGuard, {\n\t\t\t\toperation: \"execute\",\n\t\t\t\ttoolName: \"bash\",\n\t\t\t\tcommand: spawnContext.command,\n\t\t\t});\n\n\t\t\t// Safety floor: re-classify the EFFECTIVE command after commandPrefix/spawnHook.\n\t\t\t// Skipped entirely in YOLO mode (OMK_YOLO=1 / OMK_COMMAND_SAFETY=0).\n\t\t\tconst yolo =\n\t\t\t\tprocess.env.OMK_YOLO === \"1\" ||\n\t\t\t\tprocess.env.OMK_YOLO === \"true\" ||\n\t\t\t\tprocess.env.OMK_DISABLE_COMMAND_SAFETY === \"1\" ||\n\t\t\t\tprocess.env.OMK_DISABLE_COMMAND_SAFETY === \"true\" ||\n\t\t\t\t[\"0\", \"false\", \"off\", \"disable\", \"disabled\"].includes(\n\t\t\t\t\tString(process.env.OMK_COMMAND_SAFETY ?? \"\").toLowerCase(),\n\t\t\t\t);\n\t\t\tif (!yolo) {\n\t\t\t\tconst effectiveVerdict = classifyShellCommand(spawnContext.command);\n\t\t\t\tif (effectiveVerdict.risk === \"block\") {\n\t\t\t\t\tthrow new Error(`command-safety: blocked\\n[${effectiveVerdict.rule}] ${effectiveVerdict.reason}`);\n\t\t\t\t}\n\t\t\t}\n\n\t\t\tconst output = new OutputAccumulator({ tempFilePrefix: \"omk-bash\" });\n\t\t\tlet updateTimer: NodeJS.Timeout | undefined;\n\t\t\tlet updateDirty = false;\n\t\t\tlet lastUpdateAt = 0;\n\n\t\t\tconst emitOutputUpdate = () => {\n\t\t\t\tif (!onUpdate || !updateDirty) return;\n\t\t\t\tupdateDirty = false;\n\t\t\t\tlastUpdateAt = Date.now();\n\t\t\t\tconst snapshot = output.snapshot({ persistIfTruncated: true });\n\t\t\t\tonUpdate({\n\t\t\t\t\tcontent: [{ type: \"text\", text: snapshot.content || \"\" }],\n\t\t\t\t\tdetails: {\n\t\t\t\t\t\ttruncation: snapshot.truncation.truncated ? snapshot.truncation : undefined,\n\t\t\t\t\t\tfullOutputPath: snapshot.fullOutputPath,\n\t\t\t\t\t},\n\t\t\t\t});\n\t\t\t};\n\n\t\t\tconst clearUpdateTimer = () => {\n\t\t\t\tif (updateTimer) {\n\t\t\t\t\tclearTimeout(updateTimer);\n\t\t\t\t\tupdateTimer = undefined;\n\t\t\t\t}\n\t\t\t};\n\n\t\t\tconst scheduleOutputUpdate = () => {\n\t\t\t\tif (!onUpdate) return;\n\t\t\t\tupdateDirty = true;\n\t\t\t\tconst delay = BASH_UPDATE_THROTTLE_MS - (Date.now() - lastUpdateAt);\n\t\t\t\tif (delay <= 0) {\n\t\t\t\t\tclearUpdateTimer();\n\t\t\t\t\temitOutputUpdate();\n\t\t\t\t\treturn;\n\t\t\t\t}\n\t\t\t\tupdateTimer ??= setTimeout(() => {\n\t\t\t\t\tupdateTimer = undefined;\n\t\t\t\t\temitOutputUpdate();\n\t\t\t\t}, delay);\n\t\t\t};\n\n\t\t\tif (onUpdate) {\n\t\t\t\tonUpdate({ content: [], details: undefined });\n\t\t\t}\n\n\t\t\tconst handleData = (data: Buffer) => {\n\t\t\t\toutput.append(data);\n\t\t\t\tscheduleOutputUpdate();\n\t\t\t};\n\n\t\t\tconst finishOutput = async () => {\n\t\t\t\toutput.finish();\n\t\t\t\tclearUpdateTimer();\n\t\t\t\temitOutputUpdate();\n\t\t\t\tconst snapshot = output.snapshot({ persistIfTruncated: true });\n\t\t\t\tawait output.closeTempFile();\n\t\t\t\treturn snapshot;\n\t\t\t};\n\n\t\t\tconst formatOutput = (snapshot: Awaited<ReturnType<typeof finishOutput>>, emptyText = \"(no output)\") => {\n\t\t\t\tconst truncation = snapshot.truncation;\n\t\t\t\tlet text = snapshot.content || emptyText;\n\t\t\t\tlet details: BashToolDetails | undefined;\n\t\t\t\tif (truncation.truncated) {\n\t\t\t\t\tdetails = { truncation, fullOutputPath: snapshot.fullOutputPath };\n\t\t\t\t\tconst startLine = truncation.totalLines - truncation.outputLines + 1;\n\t\t\t\t\tconst endLine = truncation.totalLines;\n\t\t\t\t\tif (truncation.lastLinePartial) {\n\t\t\t\t\t\tconst lastLineSize = formatSize(output.getLastLineBytes());\n\t\t\t\t\t\ttext += `\\n\\n[Showing last ${formatSize(truncation.outputBytes)} of line ${endLine} (line is ${lastLineSize}). Full output: ${snapshot.fullOutputPath}]`;\n\t\t\t\t\t} else if (truncation.truncatedBy === \"lines\") {\n\t\t\t\t\t\ttext += `\\n\\n[Showing lines ${startLine}-${endLine} of ${truncation.totalLines}. Full output: ${snapshot.fullOutputPath}]`;\n\t\t\t\t\t} else {\n\t\t\t\t\t\ttext += `\\n\\n[Showing lines ${startLine}-${endLine} of ${truncation.totalLines} (${formatSize(DEFAULT_MAX_BYTES)} limit). Full output: ${snapshot.fullOutputPath}]`;\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t\treturn { text, details };\n\t\t\t};\n\n\t\t\tconst appendStatus = (text: string, status: string) => `${text ? `${text}\\n\\n` : \"\"}${status}`;\n\n\t\t\ttry {\n\t\t\t\tlet exitCode: number | null;\n\t\t\t\ttry {\n\t\t\t\t\tconst result = await ops.exec(spawnContext.command, spawnContext.cwd, {\n\t\t\t\t\t\tonData: handleData,\n\t\t\t\t\t\tsignal,\n\t\t\t\t\t\ttimeout,\n\t\t\t\t\t\tenv: spawnContext.env,\n\t\t\t\t\t});\n\t\t\t\t\texitCode = result.exitCode;\n\t\t\t\t} catch (err) {\n\t\t\t\t\tconst snapshot = await finishOutput();\n\t\t\t\t\tconst { text } = formatOutput(snapshot, \"\");\n\t\t\t\t\tif (err instanceof Error && err.message === \"aborted\") {\n\t\t\t\t\t\tthrow new Error(appendStatus(text, \"Command aborted\"));\n\t\t\t\t\t}\n\t\t\t\t\tif (err instanceof Error && err.message.startsWith(\"timeout:\")) {\n\t\t\t\t\t\tconst timeoutSecs = err.message.split(\":\")[1];\n\t\t\t\t\t\tthrow new Error(appendStatus(text, `Command timed out after ${timeoutSecs} seconds`));\n\t\t\t\t\t}\n\t\t\t\t\tthrow err;\n\t\t\t\t}\n\n\t\t\t\tconst snapshot = await finishOutput();\n\t\t\t\tconst { text: outputText, details } = formatOutput(snapshot);\n\t\t\t\tif (exitCode !== 0 && exitCode !== null) {\n\t\t\t\t\tthrow new Error(appendStatus(outputText, `Command exited with code ${exitCode}`));\n\t\t\t\t}\n\t\t\t\treturn { content: [{ type: \"text\", text: outputText }], details };\n\t\t\t} finally {\n\t\t\t\tclearUpdateTimer();\n\t\t\t}\n\t\t},\n\t\trenderCall(args, _theme, context) {\n\t\t\tconst state = context.state;\n\t\t\tif (context.executionStarted && state.startedAt === undefined) {\n\t\t\t\tstate.startedAt = Date.now();\n\t\t\t\tstate.endedAt = undefined;\n\t\t\t}\n\t\t\tconst text = (context.lastComponent as Text | undefined) ?? new Text(\"\", 0, 0);\n\t\t\ttext.setText(formatBashCall(args));\n\t\t\treturn text;\n\t\t},\n\t\trenderResult(result, options, _theme, context) {\n\t\t\tconst state = context.state;\n\t\t\tif (state.startedAt !== undefined && options.isPartial && !state.interval) {\n\t\t\t\tstate.interval = setInterval(() => context.invalidate(), 1000);\n\t\t\t}\n\t\t\tif (!options.isPartial || context.isError) {\n\t\t\t\tstate.endedAt ??= Date.now();\n\t\t\t\tif (state.interval) {\n\t\t\t\t\tclearInterval(state.interval);\n\t\t\t\t\tstate.interval = undefined;\n\t\t\t\t}\n\t\t\t}\n\t\t\tconst component =\n\t\t\t\t(context.lastComponent as BashResultRenderComponent | undefined) ?? new BashResultRenderComponent();\n\t\t\trebuildBashResultRenderComponent(\n\t\t\t\tcomponent,\n\t\t\t\tresult as any,\n\t\t\t\toptions,\n\t\t\t\tcontext.showImages,\n\t\t\t\tstate.startedAt,\n\t\t\t\tstate.endedAt,\n\t\t\t);\n\t\t\tcomponent.invalidate();\n\t\t\treturn component;\n\t\t},\n\t};\n}\n\nexport function createBashTool(cwd: string, options?: BashToolOptions): AgentTool<typeof bashSchema> {\n\treturn wrapToolDefinition(createBashToolDefinition(cwd, options));\n}\n"]}
@@ -20,14 +20,15 @@ const bashSchema = Type.Object({
20
20
  command: Type.String({ description: "Bash command to execute" }),
21
21
  timeout: Type.Optional(Type.Number({ description: "Timeout in seconds (optional, no default timeout)" })),
22
22
  });
23
- /**
24
- * Create bash operations using OMK's built-in local shell execution backend.
25
- *
26
- * This is useful for extensions that intercept user_bash and still want OMK's
27
- * standard local shell behavior while wrapping, sandboxing, or rewriting commands.
28
- */
29
23
  export function createLocalBashOperations(options) {
30
24
  const sandbox = options?.sandboxPolicy;
25
+ let detectedBackend;
26
+ const resolveBackend = () => {
27
+ if (sandbox?.backend)
28
+ return sandbox.backend;
29
+ detectedBackend ??= (options?.detectSandboxBackend ?? defaultBashSandboxBackend)();
30
+ return detectedBackend;
31
+ };
31
32
  return {
32
33
  exec: async (command, cwd, { onData, signal, timeout, env }) => {
33
34
  const { shell, args } = getShellConfig(options?.shellPath);
@@ -36,7 +37,7 @@ export function createLocalBashOperations(options) {
36
37
  let spawnCwd = cwd;
37
38
  let spawnEnv = env ?? getShellEnv();
38
39
  if (sandbox) {
39
- const backend = sandbox.backend ?? defaultBashSandboxBackend();
40
+ const backend = resolveBackend();
40
41
  const request = buildSandboxedSpawnRequest({
41
42
  argv: [shell, ...args, command],
42
43
  cwd,