open-multi-agent-kit 0.98.3 → 0.98.5

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (468) hide show
  1. package/CHANGELOG.md +44 -0
  2. package/README.md +12 -2
  3. package/dist/cli/args.d.ts +1 -0
  4. package/dist/cli/args.d.ts.map +1 -1
  5. package/dist/cli/args.js +14 -0
  6. package/dist/cli/args.js.map +1 -1
  7. package/dist/cli/help.d.ts.map +1 -1
  8. package/dist/cli/help.js +3 -0
  9. package/dist/cli/help.js.map +1 -1
  10. package/dist/cli/mcp-attach.d.ts +3 -3
  11. package/dist/cli/mcp-attach.d.ts.map +1 -1
  12. package/dist/cli/mcp-attach.js +5 -4
  13. package/dist/cli/mcp-attach.js.map +1 -1
  14. package/dist/cli/model-contract.d.ts +5 -0
  15. package/dist/cli/model-contract.d.ts.map +1 -0
  16. package/dist/cli/model-contract.js +45 -0
  17. package/dist/cli/model-contract.js.map +1 -0
  18. package/dist/commands/adaptorch-doctor-cli.d.ts.map +1 -1
  19. package/dist/commands/adaptorch-doctor-cli.js +32 -10
  20. package/dist/commands/adaptorch-doctor-cli.js.map +1 -1
  21. package/dist/commands/init-cli.d.ts +12 -0
  22. package/dist/commands/init-cli.d.ts.map +1 -0
  23. package/dist/commands/init-cli.js +76 -0
  24. package/dist/commands/init-cli.js.map +1 -0
  25. package/dist/commands/provider-sync-cli.d.ts +27 -0
  26. package/dist/commands/provider-sync-cli.d.ts.map +1 -0
  27. package/dist/commands/provider-sync-cli.js +177 -0
  28. package/dist/commands/provider-sync-cli.js.map +1 -0
  29. package/dist/commands/run-command.d.ts +9 -0
  30. package/dist/commands/run-command.d.ts.map +1 -0
  31. package/dist/commands/run-command.js +34 -0
  32. package/dist/commands/run-command.js.map +1 -0
  33. package/dist/commands/verified-run-cli.d.ts +6 -0
  34. package/dist/commands/verified-run-cli.d.ts.map +1 -0
  35. package/dist/commands/verified-run-cli.js +190 -0
  36. package/dist/commands/verified-run-cli.js.map +1 -0
  37. package/dist/core/active-skill-state.d.ts +7 -0
  38. package/dist/core/active-skill-state.d.ts.map +1 -0
  39. package/dist/core/active-skill-state.js +25 -0
  40. package/dist/core/active-skill-state.js.map +1 -0
  41. package/dist/core/agent-session-services.d.ts +10 -1
  42. package/dist/core/agent-session-services.d.ts.map +1 -1
  43. package/dist/core/agent-session-services.js +43 -0
  44. package/dist/core/agent-session-services.js.map +1 -1
  45. package/dist/core/agent-session.d.ts +7 -9
  46. package/dist/core/agent-session.d.ts.map +1 -1
  47. package/dist/core/agent-session.js +91 -126
  48. package/dist/core/agent-session.js.map +1 -1
  49. package/dist/core/codex-chatgpt-web-bridge.d.ts +99 -0
  50. package/dist/core/codex-chatgpt-web-bridge.d.ts.map +1 -0
  51. package/dist/core/codex-chatgpt-web-bridge.js +192 -0
  52. package/dist/core/codex-chatgpt-web-bridge.js.map +1 -0
  53. package/dist/core/codex-chatgpt-web-sync.d.ts +50 -0
  54. package/dist/core/codex-chatgpt-web-sync.d.ts.map +1 -0
  55. package/dist/core/codex-chatgpt-web-sync.js +119 -0
  56. package/dist/core/codex-chatgpt-web-sync.js.map +1 -0
  57. package/dist/core/compaction/compaction-headroom.d.ts +30 -0
  58. package/dist/core/compaction/compaction-headroom.d.ts.map +1 -0
  59. package/dist/core/compaction/compaction-headroom.js +48 -0
  60. package/dist/core/compaction/compaction-headroom.js.map +1 -0
  61. package/dist/core/compaction/compaction.d.ts +2 -29
  62. package/dist/core/compaction/compaction.d.ts.map +1 -1
  63. package/dist/core/compaction/compaction.js +19 -47
  64. package/dist/core/compaction/compaction.js.map +1 -1
  65. package/dist/core/compaction/overflow-retry-guard.d.ts +20 -0
  66. package/dist/core/compaction/overflow-retry-guard.d.ts.map +1 -0
  67. package/dist/core/compaction/overflow-retry-guard.js +38 -0
  68. package/dist/core/compaction/overflow-retry-guard.js.map +1 -0
  69. package/dist/core/context-budget-headroom-types.d.ts.map +1 -1
  70. package/dist/core/context-budget-headroom-types.js +1 -1
  71. package/dist/core/context-budget-headroom-types.js.map +1 -1
  72. package/dist/core/context-budget-token-counter-types.d.ts +27 -0
  73. package/dist/core/context-budget-token-counter-types.d.ts.map +1 -0
  74. package/dist/core/context-budget-token-counter-types.js +2 -0
  75. package/dist/core/context-budget-token-counter-types.js.map +1 -0
  76. package/dist/core/context-budget-token-counter.d.ts +2 -26
  77. package/dist/core/context-budget-token-counter.d.ts.map +1 -1
  78. package/dist/core/context-budget-token-counter.js +2 -0
  79. package/dist/core/context-budget-token-counter.js.map +1 -1
  80. package/dist/core/context-budget-v2-scoring.d.ts.map +1 -1
  81. package/dist/core/context-budget-v2-scoring.js +14 -10
  82. package/dist/core/context-budget-v2-scoring.js.map +1 -1
  83. package/dist/core/domain-router.d.ts.map +1 -1
  84. package/dist/core/domain-router.js +1 -1
  85. package/dist/core/domain-router.js.map +1 -1
  86. package/dist/core/grok-harness-dispatch.d.ts +4 -0
  87. package/dist/core/grok-harness-dispatch.d.ts.map +1 -1
  88. package/dist/core/grok-harness-dispatch.js +20 -3
  89. package/dist/core/grok-harness-dispatch.js.map +1 -1
  90. package/dist/core/grok-harness.d.ts +15 -9
  91. package/dist/core/grok-harness.d.ts.map +1 -1
  92. package/dist/core/grok-harness.js +34 -8
  93. package/dist/core/grok-harness.js.map +1 -1
  94. package/dist/core/mcp/tools.d.ts +2 -2
  95. package/dist/core/mcp/tools.d.ts.map +1 -1
  96. package/dist/core/mcp/tools.js +29 -3
  97. package/dist/core/mcp/tools.js.map +1 -1
  98. package/dist/core/model-registry-schema.d.ts +1081 -0
  99. package/dist/core/model-registry-schema.d.ts.map +1 -0
  100. package/dist/core/model-registry-schema.js +148 -0
  101. package/dist/core/model-registry-schema.js.map +1 -0
  102. package/dist/core/model-registry.d.ts.map +1 -1
  103. package/dist/core/model-registry.js +1 -146
  104. package/dist/core/model-registry.js.map +1 -1
  105. package/dist/core/model-resolver.d.ts +2 -1
  106. package/dist/core/model-resolver.d.ts.map +1 -1
  107. package/dist/core/model-resolver.js +2 -1
  108. package/dist/core/model-resolver.js.map +1 -1
  109. package/dist/core/prompt-preset.d.ts +1 -1
  110. package/dist/core/prompt-preset.d.ts.map +1 -1
  111. package/dist/core/prompt-preset.js +16 -1
  112. package/dist/core/prompt-preset.js.map +1 -1
  113. package/dist/core/prompt-settlement.d.ts +4 -3
  114. package/dist/core/prompt-settlement.d.ts.map +1 -1
  115. package/dist/core/prompt-settlement.js.map +1 -1
  116. package/dist/core/provider-display-names.d.ts.map +1 -1
  117. package/dist/core/provider-display-names.js +1 -0
  118. package/dist/core/provider-display-names.js.map +1 -1
  119. package/dist/core/provider-resilience.d.ts +8 -0
  120. package/dist/core/provider-resilience.d.ts.map +1 -1
  121. package/dist/core/provider-resilience.js +20 -3
  122. package/dist/core/provider-resilience.js.map +1 -1
  123. package/dist/core/provider-usage-types.d.ts +42 -0
  124. package/dist/core/provider-usage-types.d.ts.map +1 -0
  125. package/dist/core/provider-usage-types.js +2 -0
  126. package/dist/core/provider-usage-types.js.map +1 -0
  127. package/dist/core/provider-usage.d.ts +2 -31
  128. package/dist/core/provider-usage.d.ts.map +1 -1
  129. package/dist/core/provider-usage.js +4 -0
  130. package/dist/core/provider-usage.js.map +1 -1
  131. package/dist/core/redaction.d.ts.map +1 -1
  132. package/dist/core/redaction.js +18 -2
  133. package/dist/core/redaction.js.map +1 -1
  134. package/dist/core/run-budget-policy.d.ts +18 -0
  135. package/dist/core/run-budget-policy.d.ts.map +1 -0
  136. package/dist/core/run-budget-policy.js +52 -0
  137. package/dist/core/run-budget-policy.js.map +1 -0
  138. package/dist/core/run-budget.d.ts +33 -0
  139. package/dist/core/run-budget.d.ts.map +1 -0
  140. package/dist/core/run-budget.js +89 -0
  141. package/dist/core/run-budget.js.map +1 -0
  142. package/dist/core/run-execution-api.d.ts +15 -0
  143. package/dist/core/run-execution-api.d.ts.map +1 -0
  144. package/dist/core/run-execution-api.js +7 -0
  145. package/dist/core/run-execution-api.js.map +1 -0
  146. package/dist/core/run-journal.d.ts.map +1 -1
  147. package/dist/core/run-journal.js +30 -208
  148. package/dist/core/run-journal.js.map +1 -1
  149. package/dist/core/sandbox/policy-merge.d.ts +6 -0
  150. package/dist/core/sandbox/policy-merge.d.ts.map +1 -0
  151. package/dist/core/sandbox/policy-merge.js +74 -0
  152. package/dist/core/sandbox/policy-merge.js.map +1 -0
  153. package/dist/core/sandbox/policy-paths.d.ts +4 -0
  154. package/dist/core/sandbox/policy-paths.d.ts.map +1 -0
  155. package/dist/core/sandbox/policy-paths.js +21 -0
  156. package/dist/core/sandbox/policy-paths.js.map +1 -0
  157. package/dist/core/sandbox/policy-types.d.ts +75 -0
  158. package/dist/core/sandbox/policy-types.d.ts.map +1 -0
  159. package/dist/core/sandbox/policy-types.js +2 -0
  160. package/dist/core/sandbox/policy-types.js.map +1 -0
  161. package/dist/core/sandbox/policy.d.ts +3 -77
  162. package/dist/core/sandbox/policy.d.ts.map +1 -1
  163. package/dist/core/sandbox/policy.js +3 -98
  164. package/dist/core/sandbox/policy.js.map +1 -1
  165. package/dist/core/sdk-provider-stream.d.ts +14 -0
  166. package/dist/core/sdk-provider-stream.d.ts.map +1 -0
  167. package/dist/core/sdk-provider-stream.js +38 -0
  168. package/dist/core/sdk-provider-stream.js.map +1 -0
  169. package/dist/core/sdk.d.ts +5 -1
  170. package/dist/core/sdk.d.ts.map +1 -1
  171. package/dist/core/sdk.js +17 -33
  172. package/dist/core/sdk.js.map +1 -1
  173. package/dist/core/session-bash-service.d.ts +2 -2
  174. package/dist/core/session-bash-service.d.ts.map +1 -1
  175. package/dist/core/session-bash-service.js +21 -9
  176. package/dist/core/session-bash-service.js.map +1 -1
  177. package/dist/core/session-failure-cause.d.ts.map +1 -1
  178. package/dist/core/session-failure-cause.js +15 -3
  179. package/dist/core/session-failure-cause.js.map +1 -1
  180. package/dist/core/session-prompt-lifecycle.d.ts +25 -0
  181. package/dist/core/session-prompt-lifecycle.d.ts.map +1 -0
  182. package/dist/core/session-prompt-lifecycle.js +87 -0
  183. package/dist/core/session-prompt-lifecycle.js.map +1 -0
  184. package/dist/core/session-run-budget.d.ts +28 -0
  185. package/dist/core/session-run-budget.d.ts.map +1 -0
  186. package/dist/core/session-run-budget.js +127 -0
  187. package/dist/core/session-run-budget.js.map +1 -0
  188. package/dist/core/session-run-termination.d.ts +18 -0
  189. package/dist/core/session-run-termination.d.ts.map +1 -0
  190. package/dist/core/session-run-termination.js +72 -0
  191. package/dist/core/session-run-termination.js.map +1 -0
  192. package/dist/core/session-termination-types.d.ts +97 -0
  193. package/dist/core/session-termination-types.d.ts.map +1 -0
  194. package/dist/core/session-termination-types.js +26 -0
  195. package/dist/core/session-termination-types.js.map +1 -0
  196. package/dist/core/session-termination.d.ts +3 -97
  197. package/dist/core/session-termination.d.ts.map +1 -1
  198. package/dist/core/session-termination.js +25 -29
  199. package/dist/core/session-termination.js.map +1 -1
  200. package/dist/core/skill-selector.d.ts +40 -0
  201. package/dist/core/skill-selector.d.ts.map +1 -0
  202. package/dist/core/skill-selector.js +102 -0
  203. package/dist/core/skill-selector.js.map +1 -0
  204. package/dist/core/slash-commands.d.ts.map +1 -1
  205. package/dist/core/slash-commands.js +1 -0
  206. package/dist/core/slash-commands.js.map +1 -1
  207. package/dist/core/subagent-lane-launcher.d.ts +3 -2
  208. package/dist/core/subagent-lane-launcher.d.ts.map +1 -1
  209. package/dist/core/subagent-lane-launcher.js +24 -13
  210. package/dist/core/subagent-lane-launcher.js.map +1 -1
  211. package/dist/core/tools/render-utils.d.ts.map +1 -1
  212. package/dist/core/tools/render-utils.js +2 -4
  213. package/dist/core/tools/render-utils.js.map +1 -1
  214. package/dist/core/turn-metrics-record.d.ts +55 -0
  215. package/dist/core/turn-metrics-record.d.ts.map +1 -0
  216. package/dist/core/turn-metrics-record.js +149 -0
  217. package/dist/core/turn-metrics-record.js.map +1 -0
  218. package/dist/core/turn-metrics.d.ts +4 -56
  219. package/dist/core/turn-metrics.d.ts.map +1 -1
  220. package/dist/core/turn-metrics.js +12 -60
  221. package/dist/core/turn-metrics.js.map +1 -1
  222. package/dist/core/verified-run/broker.d.ts +26 -0
  223. package/dist/core/verified-run/broker.d.ts.map +1 -0
  224. package/dist/core/verified-run/broker.js +210 -0
  225. package/dist/core/verified-run/broker.js.map +1 -0
  226. package/dist/core/verified-run/candidate.d.ts +24 -0
  227. package/dist/core/verified-run/candidate.d.ts.map +1 -0
  228. package/dist/core/verified-run/candidate.js +167 -0
  229. package/dist/core/verified-run/candidate.js.map +1 -0
  230. package/dist/core/verified-run/check-receipt.d.ts +18 -0
  231. package/dist/core/verified-run/check-receipt.d.ts.map +1 -0
  232. package/dist/core/verified-run/check-receipt.js +92 -0
  233. package/dist/core/verified-run/check-receipt.js.map +1 -0
  234. package/dist/core/verified-run/coordinator.d.ts +39 -0
  235. package/dist/core/verified-run/coordinator.d.ts.map +1 -0
  236. package/dist/core/verified-run/coordinator.js +190 -0
  237. package/dist/core/verified-run/coordinator.js.map +1 -0
  238. package/dist/core/verified-run/dag-candidates.d.ts +8 -0
  239. package/dist/core/verified-run/dag-candidates.d.ts.map +1 -0
  240. package/dist/core/verified-run/dag-candidates.js +65 -0
  241. package/dist/core/verified-run/dag-candidates.js.map +1 -0
  242. package/dist/core/verified-run/dag-phase.d.ts +7 -0
  243. package/dist/core/verified-run/dag-phase.d.ts.map +1 -0
  244. package/dist/core/verified-run/dag-phase.js +92 -0
  245. package/dist/core/verified-run/dag-phase.js.map +1 -0
  246. package/dist/core/verified-run/dag-projection.d.ts +7 -0
  247. package/dist/core/verified-run/dag-projection.d.ts.map +1 -0
  248. package/dist/core/verified-run/dag-projection.js +90 -0
  249. package/dist/core/verified-run/dag-projection.js.map +1 -0
  250. package/dist/core/verified-run/dag-recovery.d.ts +13 -0
  251. package/dist/core/verified-run/dag-recovery.d.ts.map +1 -0
  252. package/dist/core/verified-run/dag-recovery.js +98 -0
  253. package/dist/core/verified-run/dag-recovery.js.map +1 -0
  254. package/dist/core/verified-run/dag-retry-projection.d.ts +9 -0
  255. package/dist/core/verified-run/dag-retry-projection.d.ts.map +1 -0
  256. package/dist/core/verified-run/dag-retry-projection.js +43 -0
  257. package/dist/core/verified-run/dag-retry-projection.js.map +1 -0
  258. package/dist/core/verified-run/dag-types.d.ts +47 -0
  259. package/dist/core/verified-run/dag-types.d.ts.map +1 -0
  260. package/dist/core/verified-run/dag-types.js +2 -0
  261. package/dist/core/verified-run/dag-types.js.map +1 -0
  262. package/dist/core/verified-run/event-parser.d.ts +3 -0
  263. package/dist/core/verified-run/event-parser.d.ts.map +1 -0
  264. package/dist/core/verified-run/event-parser.js +153 -0
  265. package/dist/core/verified-run/event-parser.js.map +1 -0
  266. package/dist/core/verified-run/events.d.ts +4 -0
  267. package/dist/core/verified-run/events.d.ts.map +1 -0
  268. package/dist/core/verified-run/events.js +3 -0
  269. package/dist/core/verified-run/events.js.map +1 -0
  270. package/dist/core/verified-run/evidence-binding.d.ts +18 -0
  271. package/dist/core/verified-run/evidence-binding.d.ts.map +1 -0
  272. package/dist/core/verified-run/evidence-binding.js +81 -0
  273. package/dist/core/verified-run/evidence-binding.js.map +1 -0
  274. package/dist/core/verified-run/evidence.d.ts +27 -0
  275. package/dist/core/verified-run/evidence.d.ts.map +1 -0
  276. package/dist/core/verified-run/evidence.js +100 -0
  277. package/dist/core/verified-run/evidence.js.map +1 -0
  278. package/dist/core/verified-run/journal.d.ts +32 -0
  279. package/dist/core/verified-run/journal.d.ts.map +1 -0
  280. package/dist/core/verified-run/journal.js +103 -0
  281. package/dist/core/verified-run/journal.js.map +1 -0
  282. package/dist/core/verified-run/namespace-identity.d.ts +11 -0
  283. package/dist/core/verified-run/namespace-identity.d.ts.map +1 -0
  284. package/dist/core/verified-run/namespace-identity.js +77 -0
  285. package/dist/core/verified-run/namespace-identity.js.map +1 -0
  286. package/dist/core/verified-run/owned-execution.d.ts +21 -0
  287. package/dist/core/verified-run/owned-execution.d.ts.map +1 -0
  288. package/dist/core/verified-run/owned-execution.js +43 -0
  289. package/dist/core/verified-run/owned-execution.js.map +1 -0
  290. package/dist/core/verified-run/phase-context.d.ts +9 -0
  291. package/dist/core/verified-run/phase-context.d.ts.map +1 -0
  292. package/dist/core/verified-run/phase-context.js +2 -0
  293. package/dist/core/verified-run/phase-context.js.map +1 -0
  294. package/dist/core/verified-run/process-gate.d.ts +5 -0
  295. package/dist/core/verified-run/process-gate.d.ts.map +1 -0
  296. package/dist/core/verified-run/process-gate.js +31 -0
  297. package/dist/core/verified-run/process-gate.js.map +1 -0
  298. package/dist/core/verified-run/projection.d.ts +4 -0
  299. package/dist/core/verified-run/projection.d.ts.map +1 -0
  300. package/dist/core/verified-run/projection.js +219 -0
  301. package/dist/core/verified-run/projection.js.map +1 -0
  302. package/dist/core/verified-run/recovery-clock.d.ts +19 -0
  303. package/dist/core/verified-run/recovery-clock.d.ts.map +1 -0
  304. package/dist/core/verified-run/recovery-clock.js +69 -0
  305. package/dist/core/verified-run/recovery-clock.js.map +1 -0
  306. package/dist/core/verified-run/recovery-command.d.ts +11 -0
  307. package/dist/core/verified-run/recovery-command.d.ts.map +1 -0
  308. package/dist/core/verified-run/recovery-command.js +73 -0
  309. package/dist/core/verified-run/recovery-command.js.map +1 -0
  310. package/dist/core/verified-run/recovery-projection.d.ts +12 -0
  311. package/dist/core/verified-run/recovery-projection.d.ts.map +1 -0
  312. package/dist/core/verified-run/recovery-projection.js +88 -0
  313. package/dist/core/verified-run/recovery-projection.js.map +1 -0
  314. package/dist/core/verified-run/recovery.d.ts +12 -0
  315. package/dist/core/verified-run/recovery.d.ts.map +1 -0
  316. package/dist/core/verified-run/recovery.js +115 -0
  317. package/dist/core/verified-run/recovery.js.map +1 -0
  318. package/dist/core/verified-run/run-types.d.ts +103 -0
  319. package/dist/core/verified-run/run-types.d.ts.map +1 -0
  320. package/dist/core/verified-run/run-types.js +2 -0
  321. package/dist/core/verified-run/run-types.js.map +1 -0
  322. package/dist/core/verified-run/scripted-writer.d.ts +15 -0
  323. package/dist/core/verified-run/scripted-writer.d.ts.map +1 -0
  324. package/dist/core/verified-run/scripted-writer.js +94 -0
  325. package/dist/core/verified-run/scripted-writer.js.map +1 -0
  326. package/dist/core/verified-run/session-port.d.ts +27 -0
  327. package/dist/core/verified-run/session-port.d.ts.map +1 -0
  328. package/dist/core/verified-run/session-port.js +2 -0
  329. package/dist/core/verified-run/session-port.js.map +1 -0
  330. package/dist/core/verified-run/storage.d.ts +15 -0
  331. package/dist/core/verified-run/storage.d.ts.map +1 -0
  332. package/dist/core/verified-run/storage.js +96 -0
  333. package/dist/core/verified-run/storage.js.map +1 -0
  334. package/dist/core/verified-run/verification-phase.d.ts +5 -0
  335. package/dist/core/verified-run/verification-phase.d.ts.map +1 -0
  336. package/dist/core/verified-run/verification-phase.js +56 -0
  337. package/dist/core/verified-run/verification-phase.js.map +1 -0
  338. package/dist/core/verified-run/work-recovery.d.ts +8 -0
  339. package/dist/core/verified-run/work-recovery.d.ts.map +1 -0
  340. package/dist/core/verified-run/work-recovery.js +44 -0
  341. package/dist/core/verified-run/work-recovery.js.map +1 -0
  342. package/dist/core/verified-run/writer-completion.d.ts +4 -0
  343. package/dist/core/verified-run/writer-completion.d.ts.map +1 -0
  344. package/dist/core/verified-run/writer-completion.js +27 -0
  345. package/dist/core/verified-run/writer-completion.js.map +1 -0
  346. package/dist/core/verified-run/writer-phase.d.ts +8 -0
  347. package/dist/core/verified-run/writer-phase.d.ts.map +1 -0
  348. package/dist/core/verified-run/writer-phase.js +76 -0
  349. package/dist/core/verified-run/writer-phase.js.map +1 -0
  350. package/dist/core/verified-run/writer-projection.d.ts +11 -0
  351. package/dist/core/verified-run/writer-projection.d.ts.map +1 -0
  352. package/dist/core/verified-run/writer-projection.js +70 -0
  353. package/dist/core/verified-run/writer-projection.js.map +1 -0
  354. package/dist/core/verified-run/writer-recovery.d.ts +16 -0
  355. package/dist/core/verified-run/writer-recovery.d.ts.map +1 -0
  356. package/dist/core/verified-run/writer-recovery.js +107 -0
  357. package/dist/core/verified-run/writer-recovery.js.map +1 -0
  358. package/dist/core/workload-permit-pool.d.ts +1 -3
  359. package/dist/core/workload-permit-pool.d.ts.map +1 -1
  360. package/dist/core/workload-permit-pool.js +11 -11
  361. package/dist/core/workload-permit-pool.js.map +1 -1
  362. package/dist/guardrails/evidence-system.d.ts +1 -1
  363. package/dist/guardrails/evidence-system.d.ts.map +1 -1
  364. package/dist/guardrails/evidence-system.js +18 -29
  365. package/dist/guardrails/evidence-system.js.map +1 -1
  366. package/dist/guardrails/merge-gate-result.d.ts +4 -0
  367. package/dist/guardrails/merge-gate-result.d.ts.map +1 -0
  368. package/dist/guardrails/merge-gate-result.js +32 -0
  369. package/dist/guardrails/merge-gate-result.js.map +1 -0
  370. package/dist/index.d.ts +3 -2
  371. package/dist/index.d.ts.map +1 -1
  372. package/dist/index.js +2 -2
  373. package/dist/index.js.map +1 -1
  374. package/dist/main.d.ts.map +1 -1
  375. package/dist/main.js +17 -23
  376. package/dist/main.js.map +1 -1
  377. package/dist/modes/interactive/components/session-failure.d.ts +13 -0
  378. package/dist/modes/interactive/components/session-failure.d.ts.map +1 -0
  379. package/dist/modes/interactive/components/session-failure.js +81 -0
  380. package/dist/modes/interactive/components/session-failure.js.map +1 -0
  381. package/dist/modes/interactive/interactive-login-options.d.ts +27 -0
  382. package/dist/modes/interactive/interactive-login-options.d.ts.map +1 -0
  383. package/dist/modes/interactive/interactive-login-options.js +54 -0
  384. package/dist/modes/interactive/interactive-login-options.js.map +1 -0
  385. package/dist/modes/interactive/interactive-mode.d.ts +8 -4
  386. package/dist/modes/interactive/interactive-mode.d.ts.map +1 -1
  387. package/dist/modes/interactive/interactive-mode.js +183 -171
  388. package/dist/modes/interactive/interactive-mode.js.map +1 -1
  389. package/dist/modes/interactive/interactive-resume-command.d.ts +3 -0
  390. package/dist/modes/interactive/interactive-resume-command.d.ts.map +1 -0
  391. package/dist/modes/interactive/interactive-resume-command.js +24 -0
  392. package/dist/modes/interactive/interactive-resume-command.js.map +1 -0
  393. package/dist/modes/interactive/interactive-tool-result.d.ts +32 -0
  394. package/dist/modes/interactive/interactive-tool-result.d.ts.map +1 -0
  395. package/dist/modes/interactive/interactive-tool-result.js +59 -0
  396. package/dist/modes/interactive/interactive-tool-result.js.map +1 -0
  397. package/dist/modes/interactive/tui-diagnostics.d.ts +36 -0
  398. package/dist/modes/interactive/tui-diagnostics.d.ts.map +1 -0
  399. package/dist/modes/interactive/tui-diagnostics.js +105 -0
  400. package/dist/modes/interactive/tui-diagnostics.js.map +1 -0
  401. package/dist/modes/interactive/tui-runtime-info.d.ts +20 -0
  402. package/dist/modes/interactive/tui-runtime-info.d.ts.map +1 -0
  403. package/dist/modes/interactive/tui-runtime-info.js +76 -0
  404. package/dist/modes/interactive/tui-runtime-info.js.map +1 -0
  405. package/dist/modes/print-mode.d.ts.map +1 -1
  406. package/dist/modes/print-mode.js +22 -0
  407. package/dist/modes/print-mode.js.map +1 -1
  408. package/dist/utils/clipboard-image.d.ts.map +1 -1
  409. package/dist/utils/clipboard-image.js +10 -60
  410. package/dist/utils/clipboard-image.js.map +1 -1
  411. package/dist/utils/terminal-links.d.ts +13 -0
  412. package/dist/utils/terminal-links.d.ts.map +1 -0
  413. package/dist/utils/terminal-links.js +68 -0
  414. package/dist/utils/terminal-links.js.map +1 -0
  415. package/dist/utils/windows-clipboard-image.d.ts +16 -0
  416. package/dist/utils/windows-clipboard-image.d.ts.map +1 -0
  417. package/dist/utils/windows-clipboard-image.js +87 -0
  418. package/dist/utils/windows-clipboard-image.js.map +1 -0
  419. package/docs/adaptorch-onboarding.md +80 -0
  420. package/docs/containerization.md +12 -0
  421. package/docs/context-files.md +97 -0
  422. package/docs/correctness-wall.md +8 -0
  423. package/docs/custom-provider.md +35 -0
  424. package/docs/development.md +28 -3
  425. package/docs/environment-variables.md +2 -0
  426. package/docs/grok-harness.md +4 -0
  427. package/docs/harness-boundaries.md +154 -0
  428. package/docs/harness-improvements.md +90 -0
  429. package/docs/json.md +19 -0
  430. package/docs/keybindings.md +2 -2
  431. package/docs/mcp.md +22 -2
  432. package/docs/metrics.md +66 -16
  433. package/docs/model-catalog-refresh.md +190 -0
  434. package/docs/model-contract.md +168 -0
  435. package/docs/models.md +21 -4
  436. package/docs/provider-resilience.md +5 -3
  437. package/docs/providers.md +68 -1
  438. package/docs/quickstart.md +4 -0
  439. package/docs/release-audit-0.98.4.md +112 -0
  440. package/docs/release-audit-0.98.5.md +84 -0
  441. package/docs/review-bundle-followup.md +195 -0
  442. package/docs/run-protocol.md +33 -1
  443. package/docs/runtime-algorithms.md +45 -0
  444. package/docs/sdk.md +204 -2
  445. package/docs/sessions.md +1 -1
  446. package/docs/settings.md +17 -1
  447. package/docs/skills.md +2 -0
  448. package/docs/tb21-audit.md +131 -0
  449. package/docs/terminal-setup.md +20 -0
  450. package/docs/usage.md +77 -1
  451. package/docs/verified-run-testing.md +417 -0
  452. package/docs/verified-run.md +388 -0
  453. package/docs/windows.md +48 -0
  454. package/examples/README.md +4 -0
  455. package/examples/context/AGENTS.md +64 -0
  456. package/examples/context/CLAUDE.md +17 -0
  457. package/examples/context/INTERNET.md +42 -0
  458. package/examples/extensions/custom-provider-anthropic/package-lock.json +2 -2
  459. package/examples/extensions/custom-provider-anthropic/package.json +1 -1
  460. package/examples/extensions/custom-provider-gitlab-duo/package.json +1 -1
  461. package/examples/extensions/gondolin/package-lock.json +2 -2
  462. package/examples/extensions/gondolin/package.json +1 -1
  463. package/examples/extensions/sandbox/package-lock.json +2 -2
  464. package/examples/extensions/sandbox/package.json +1 -1
  465. package/examples/extensions/with-deps/package-lock.json +2 -2
  466. package/examples/extensions/with-deps/package.json +1 -1
  467. package/npm-shrinkwrap.json +18 -18
  468. package/package.json +6 -6
@@ -0,0 +1,75 @@
1
+ export type SandboxMode = "off" | "audit" | "enforce";
2
+ export type SandboxProfile = "readonly" | "workspace-write" | "dev-server" | "networked";
3
+ export type NetworkMode = "none" | "loopback" | "domain-allowlist" | "all-explicit";
4
+ export type PathAccessKind = "read" | "write";
5
+ export type SandboxPlatform = "linux" | "macos" | "unsupported";
6
+ export interface SandboxPolicy {
7
+ mode: SandboxMode;
8
+ profile: SandboxProfile;
9
+ filesystem: {
10
+ root: string;
11
+ readAllow: readonly string[];
12
+ readDeny: readonly string[];
13
+ writeAllow: readonly string[];
14
+ denyWrite: readonly string[];
15
+ tempWrite: readonly string[];
16
+ followSymlinks: false;
17
+ };
18
+ network: {
19
+ mode: NetworkMode;
20
+ allowedDomains: readonly string[];
21
+ deniedDomains: readonly string[];
22
+ allowUnixSockets: readonly string[];
23
+ allowBrowser: false;
24
+ };
25
+ process: {
26
+ allowExec: boolean;
27
+ allowShell: boolean;
28
+ allowPrivilege: false;
29
+ };
30
+ }
31
+ export interface ResolvedSandboxPath {
32
+ requestedPath: string;
33
+ exists: boolean;
34
+ realPath?: string;
35
+ nearestExistingParentRealPath?: string;
36
+ isSymlink?: boolean;
37
+ error?: string;
38
+ }
39
+ export type SandboxPathResolver = (requestPath: string) => ResolvedSandboxPath;
40
+ export interface PathAccessRequest {
41
+ kind: PathAccessKind;
42
+ path: string;
43
+ }
44
+ export interface SandboxDecision {
45
+ allowed: boolean;
46
+ rule: string;
47
+ reason: string;
48
+ }
49
+ export interface NetworkAccessRequest {
50
+ host?: string;
51
+ url?: string;
52
+ unixSocketPath?: string;
53
+ browser?: boolean;
54
+ loopback?: boolean;
55
+ }
56
+ export interface SandboxBackendStatus {
57
+ platform: SandboxPlatform;
58
+ backendAvailable: boolean;
59
+ domainAllowlistAvailable?: boolean;
60
+ /** Human-readable probe detail when the backend cannot enforce the policy. */
61
+ unavailableReason?: string;
62
+ }
63
+ export interface SandboxFallbackDecision extends SandboxDecision {
64
+ allowShell: boolean;
65
+ allowExec: boolean;
66
+ allowReadOnlyTools: boolean;
67
+ }
68
+ export interface BashSpawnPreflightContext {
69
+ command: string;
70
+ cwd: string;
71
+ }
72
+ export interface BashSpawnPreflightDecision extends SandboxDecision {
73
+ allowShell: boolean;
74
+ }
75
+ //# sourceMappingURL=policy-types.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"policy-types.d.ts","sourceRoot":"","sources":["../../../src/core/sandbox/policy-types.ts"],"names":[],"mappings":"AAAA,MAAM,MAAM,WAAW,GAAG,KAAK,GAAG,OAAO,GAAG,SAAS,CAAC;AACtD,MAAM,MAAM,cAAc,GAAG,UAAU,GAAG,iBAAiB,GAAG,YAAY,GAAG,WAAW,CAAC;AACzF,MAAM,MAAM,WAAW,GAAG,MAAM,GAAG,UAAU,GAAG,kBAAkB,GAAG,cAAc,CAAC;AACpF,MAAM,MAAM,cAAc,GAAG,MAAM,GAAG,OAAO,CAAC;AAC9C,MAAM,MAAM,eAAe,GAAG,OAAO,GAAG,OAAO,GAAG,aAAa,CAAC;AAEhE,MAAM,WAAW,aAAa;IAC7B,IAAI,EAAE,WAAW,CAAC;IAClB,OAAO,EAAE,cAAc,CAAC;IACxB,UAAU,EAAE;QACX,IAAI,EAAE,MAAM,CAAC;QACb,SAAS,EAAE,SAAS,MAAM,EAAE,CAAC;QAC7B,QAAQ,EAAE,SAAS,MAAM,EAAE,CAAC;QAC5B,UAAU,EAAE,SAAS,MAAM,EAAE,CAAC;QAC9B,SAAS,EAAE,SAAS,MAAM,EAAE,CAAC;QAC7B,SAAS,EAAE,SAAS,MAAM,EAAE,CAAC;QAC7B,cAAc,EAAE,KAAK,CAAC;KACtB,CAAC;IACF,OAAO,EAAE;QACR,IAAI,EAAE,WAAW,CAAC;QAClB,cAAc,EAAE,SAAS,MAAM,EAAE,CAAC;QAClC,aAAa,EAAE,SAAS,MAAM,EAAE,CAAC;QACjC,gBAAgB,EAAE,SAAS,MAAM,EAAE,CAAC;QACpC,YAAY,EAAE,KAAK,CAAC;KACpB,CAAC;IACF,OAAO,EAAE;QAAE,SAAS,EAAE,OAAO,CAAC;QAAC,UAAU,EAAE,OAAO,CAAC;QAAC,cAAc,EAAE,KAAK,CAAA;KAAE,CAAC;CAC5E;AACD,MAAM,WAAW,mBAAmB;IACnC,aAAa,EAAE,MAAM,CAAC;IACtB,MAAM,EAAE,OAAO,CAAC;IAChB,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,6BAA6B,CAAC,EAAE,MAAM,CAAC;IACvC,SAAS,CAAC,EAAE,OAAO,CAAC;IACpB,KAAK,CAAC,EAAE,MAAM,CAAC;CACf;AACD,MAAM,MAAM,mBAAmB,GAAG,CAAC,WAAW,EAAE,MAAM,KAAK,mBAAmB,CAAC;AAC/E,MAAM,WAAW,iBAAiB;IACjC,IAAI,EAAE,cAAc,CAAC;IACrB,IAAI,EAAE,MAAM,CAAC;CACb;AACD,MAAM,WAAW,eAAe;IAC/B,OAAO,EAAE,OAAO,CAAC;IACjB,IAAI,EAAE,MAAM,CAAC;IACb,MAAM,EAAE,MAAM,CAAC;CACf;AACD,MAAM,WAAW,oBAAoB;IACpC,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,GAAG,CAAC,EAAE,MAAM,CAAC;IACb,cAAc,CAAC,EAAE,MAAM,CAAC;IACxB,OAAO,CAAC,EAAE,OAAO,CAAC;IAClB,QAAQ,CAAC,EAAE,OAAO,CAAC;CACnB;AACD,MAAM,WAAW,oBAAoB;IACpC,QAAQ,EAAE,eAAe,CAAC;IAC1B,gBAAgB,EAAE,OAAO,CAAC;IAC1B,wBAAwB,CAAC,EAAE,OAAO,CAAC;IACnC,8EAA8E;IAC9E,iBAAiB,CAAC,EAAE,MAAM,CAAC;CAC3B;AACD,MAAM,WAAW,uBAAwB,SAAQ,eAAe;IAC/D,UAAU,EAAE,OAAO,CAAC;IACpB,SAAS,EAAE,OAAO,CAAC;IACnB,kBAAkB,EAAE,OAAO,CAAC;CAC5B;AACD,MAAM,WAAW,yBAAyB;IACzC,OAAO,EAAE,MAAM,CAAC;IAChB,GAAG,EAAE,MAAM,CAAC;CACZ;AACD,MAAM,WAAW,0BAA2B,SAAQ,eAAe;IAClE,UAAU,EAAE,OAAO,CAAC;CACpB","sourcesContent":["export type SandboxMode = \"off\" | \"audit\" | \"enforce\";\nexport type SandboxProfile = \"readonly\" | \"workspace-write\" | \"dev-server\" | \"networked\";\nexport type NetworkMode = \"none\" | \"loopback\" | \"domain-allowlist\" | \"all-explicit\";\nexport type PathAccessKind = \"read\" | \"write\";\nexport type SandboxPlatform = \"linux\" | \"macos\" | \"unsupported\";\n\nexport interface SandboxPolicy {\n\tmode: SandboxMode;\n\tprofile: SandboxProfile;\n\tfilesystem: {\n\t\troot: string;\n\t\treadAllow: readonly string[];\n\t\treadDeny: readonly string[];\n\t\twriteAllow: readonly string[];\n\t\tdenyWrite: readonly string[];\n\t\ttempWrite: readonly string[];\n\t\tfollowSymlinks: false;\n\t};\n\tnetwork: {\n\t\tmode: NetworkMode;\n\t\tallowedDomains: readonly string[];\n\t\tdeniedDomains: readonly string[];\n\t\tallowUnixSockets: readonly string[];\n\t\tallowBrowser: false;\n\t};\n\tprocess: { allowExec: boolean; allowShell: boolean; allowPrivilege: false };\n}\nexport interface ResolvedSandboxPath {\n\trequestedPath: string;\n\texists: boolean;\n\trealPath?: string;\n\tnearestExistingParentRealPath?: string;\n\tisSymlink?: boolean;\n\terror?: string;\n}\nexport type SandboxPathResolver = (requestPath: string) => ResolvedSandboxPath;\nexport interface PathAccessRequest {\n\tkind: PathAccessKind;\n\tpath: string;\n}\nexport interface SandboxDecision {\n\tallowed: boolean;\n\trule: string;\n\treason: string;\n}\nexport interface NetworkAccessRequest {\n\thost?: string;\n\turl?: string;\n\tunixSocketPath?: string;\n\tbrowser?: boolean;\n\tloopback?: boolean;\n}\nexport interface SandboxBackendStatus {\n\tplatform: SandboxPlatform;\n\tbackendAvailable: boolean;\n\tdomainAllowlistAvailable?: boolean;\n\t/** Human-readable probe detail when the backend cannot enforce the policy. */\n\tunavailableReason?: string;\n}\nexport interface SandboxFallbackDecision extends SandboxDecision {\n\tallowShell: boolean;\n\tallowExec: boolean;\n\tallowReadOnlyTools: boolean;\n}\nexport interface BashSpawnPreflightContext {\n\tcommand: string;\n\tcwd: string;\n}\nexport interface BashSpawnPreflightDecision extends SandboxDecision {\n\tallowShell: boolean;\n}\n"]}
@@ -0,0 +1,2 @@
1
+ export {};
2
+ //# sourceMappingURL=policy-types.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"policy-types.js","sourceRoot":"","sources":["../../../src/core/sandbox/policy-types.ts"],"names":[],"mappings":"","sourcesContent":["export type SandboxMode = \"off\" | \"audit\" | \"enforce\";\nexport type SandboxProfile = \"readonly\" | \"workspace-write\" | \"dev-server\" | \"networked\";\nexport type NetworkMode = \"none\" | \"loopback\" | \"domain-allowlist\" | \"all-explicit\";\nexport type PathAccessKind = \"read\" | \"write\";\nexport type SandboxPlatform = \"linux\" | \"macos\" | \"unsupported\";\n\nexport interface SandboxPolicy {\n\tmode: SandboxMode;\n\tprofile: SandboxProfile;\n\tfilesystem: {\n\t\troot: string;\n\t\treadAllow: readonly string[];\n\t\treadDeny: readonly string[];\n\t\twriteAllow: readonly string[];\n\t\tdenyWrite: readonly string[];\n\t\ttempWrite: readonly string[];\n\t\tfollowSymlinks: false;\n\t};\n\tnetwork: {\n\t\tmode: NetworkMode;\n\t\tallowedDomains: readonly string[];\n\t\tdeniedDomains: readonly string[];\n\t\tallowUnixSockets: readonly string[];\n\t\tallowBrowser: false;\n\t};\n\tprocess: { allowExec: boolean; allowShell: boolean; allowPrivilege: false };\n}\nexport interface ResolvedSandboxPath {\n\trequestedPath: string;\n\texists: boolean;\n\trealPath?: string;\n\tnearestExistingParentRealPath?: string;\n\tisSymlink?: boolean;\n\terror?: string;\n}\nexport type SandboxPathResolver = (requestPath: string) => ResolvedSandboxPath;\nexport interface PathAccessRequest {\n\tkind: PathAccessKind;\n\tpath: string;\n}\nexport interface SandboxDecision {\n\tallowed: boolean;\n\trule: string;\n\treason: string;\n}\nexport interface NetworkAccessRequest {\n\thost?: string;\n\turl?: string;\n\tunixSocketPath?: string;\n\tbrowser?: boolean;\n\tloopback?: boolean;\n}\nexport interface SandboxBackendStatus {\n\tplatform: SandboxPlatform;\n\tbackendAvailable: boolean;\n\tdomainAllowlistAvailable?: boolean;\n\t/** Human-readable probe detail when the backend cannot enforce the policy. */\n\tunavailableReason?: string;\n}\nexport interface SandboxFallbackDecision extends SandboxDecision {\n\tallowShell: boolean;\n\tallowExec: boolean;\n\tallowReadOnlyTools: boolean;\n}\nexport interface BashSpawnPreflightContext {\n\tcommand: string;\n\tcwd: string;\n}\nexport interface BashSpawnPreflightDecision extends SandboxDecision {\n\tallowShell: boolean;\n}\n"]}
@@ -1,83 +1,9 @@
1
- export type SandboxMode = "off" | "audit" | "enforce";
2
- export type SandboxProfile = "readonly" | "workspace-write" | "dev-server" | "networked";
3
- export type NetworkMode = "none" | "loopback" | "domain-allowlist" | "all-explicit";
4
- export type PathAccessKind = "read" | "write";
5
- export type SandboxPlatform = "linux" | "macos" | "unsupported";
6
- export interface SandboxPolicy {
7
- mode: SandboxMode;
8
- profile: SandboxProfile;
9
- filesystem: {
10
- root: string;
11
- readAllow: readonly string[];
12
- readDeny: readonly string[];
13
- writeAllow: readonly string[];
14
- denyWrite: readonly string[];
15
- tempWrite: readonly string[];
16
- followSymlinks: false;
17
- };
18
- network: {
19
- mode: NetworkMode;
20
- allowedDomains: readonly string[];
21
- deniedDomains: readonly string[];
22
- allowUnixSockets: readonly string[];
23
- allowBrowser: false;
24
- };
25
- process: {
26
- allowExec: boolean;
27
- allowShell: boolean;
28
- allowPrivilege: false;
29
- };
30
- }
31
- export interface ResolvedSandboxPath {
32
- requestedPath: string;
33
- exists: boolean;
34
- realPath?: string;
35
- nearestExistingParentRealPath?: string;
36
- isSymlink?: boolean;
37
- error?: string;
38
- }
39
- export type SandboxPathResolver = (requestPath: string) => ResolvedSandboxPath;
40
- export interface PathAccessRequest {
41
- kind: PathAccessKind;
42
- path: string;
43
- }
44
- export interface SandboxDecision {
45
- allowed: boolean;
46
- rule: string;
47
- reason: string;
48
- }
49
- export interface NetworkAccessRequest {
50
- host?: string;
51
- url?: string;
52
- unixSocketPath?: string;
53
- browser?: boolean;
54
- loopback?: boolean;
55
- }
56
- export interface SandboxBackendStatus {
57
- platform: SandboxPlatform;
58
- backendAvailable: boolean;
59
- domainAllowlistAvailable?: boolean;
60
- /** Human-readable probe detail when the backend cannot enforce the policy. */
61
- unavailableReason?: string;
62
- }
63
- export interface SandboxFallbackDecision extends SandboxDecision {
64
- allowShell: boolean;
65
- allowExec: boolean;
66
- allowReadOnlyTools: boolean;
67
- }
1
+ export { mergeSandboxPolicy } from "./policy-merge.ts";
2
+ import type { BashSpawnPreflightContext, BashSpawnPreflightDecision, NetworkAccessRequest, PathAccessRequest, SandboxBackendStatus, SandboxDecision, SandboxFallbackDecision, SandboxPathResolver, SandboxPolicy } from "./policy-types.ts";
3
+ export * from "./policy-types.ts";
68
4
  export declare function decidePathAccess(policy: SandboxPolicy, request: PathAccessRequest, resolver: SandboxPathResolver): SandboxDecision;
69
5
  export declare function decideNetworkAccess(policy: SandboxPolicy, request: NetworkAccessRequest): SandboxDecision;
70
6
  export declare function decideSandboxFallback(policy: SandboxPolicy, backend: SandboxBackendStatus): SandboxFallbackDecision;
71
- export declare function mergeSandboxPolicy(base: SandboxPolicy, override: Partial<SandboxPolicy>, options?: {
72
- allowBroaden?: boolean;
73
- }): SandboxPolicy;
74
- export interface BashSpawnPreflightContext {
75
- command: string;
76
- cwd: string;
77
- }
78
- export interface BashSpawnPreflightDecision extends SandboxDecision {
79
- allowShell: boolean;
80
- }
81
7
  /**
82
8
  * Final pure preflight for a local bash spawn. Combines the backend-availability
83
9
  * fallback (deny shell when an OS sandbox backend is missing under enforce mode)
@@ -1 +1 @@
1
- {"version":3,"file":"policy.d.ts","sourceRoot":"","sources":["../../../src/core/sandbox/policy.ts"],"names":[],"mappings":"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","sourcesContent":["import path from \"node:path\";\n\nexport type SandboxMode = \"off\" | \"audit\" | \"enforce\";\nexport type SandboxProfile = \"readonly\" | \"workspace-write\" | \"dev-server\" | \"networked\";\nexport type NetworkMode = \"none\" | \"loopback\" | \"domain-allowlist\" | \"all-explicit\";\nexport type PathAccessKind = \"read\" | \"write\";\nexport type SandboxPlatform = \"linux\" | \"macos\" | \"unsupported\";\n\nexport interface SandboxPolicy {\n\tmode: SandboxMode;\n\tprofile: SandboxProfile;\n\tfilesystem: {\n\t\troot: string;\n\t\treadAllow: readonly string[];\n\t\treadDeny: readonly string[];\n\t\twriteAllow: readonly string[];\n\t\tdenyWrite: readonly string[];\n\t\ttempWrite: readonly string[];\n\t\tfollowSymlinks: false;\n\t};\n\tnetwork: {\n\t\tmode: NetworkMode;\n\t\tallowedDomains: readonly string[];\n\t\tdeniedDomains: readonly string[];\n\t\tallowUnixSockets: readonly string[];\n\t\tallowBrowser: false;\n\t};\n\tprocess: {\n\t\tallowExec: boolean;\n\t\tallowShell: boolean;\n\t\tallowPrivilege: false;\n\t};\n}\n\nexport interface ResolvedSandboxPath {\n\trequestedPath: string;\n\texists: boolean;\n\trealPath?: string;\n\tnearestExistingParentRealPath?: string;\n\tisSymlink?: boolean;\n\terror?: string;\n}\n\nexport type SandboxPathResolver = (requestPath: string) => ResolvedSandboxPath;\n\nexport interface PathAccessRequest {\n\tkind: PathAccessKind;\n\tpath: string;\n}\n\nexport interface SandboxDecision {\n\tallowed: boolean;\n\trule: string;\n\treason: string;\n}\n\nexport interface NetworkAccessRequest {\n\thost?: string;\n\turl?: string;\n\tunixSocketPath?: string;\n\tbrowser?: boolean;\n\tloopback?: boolean;\n}\n\nexport interface SandboxBackendStatus {\n\tplatform: SandboxPlatform;\n\tbackendAvailable: boolean;\n\tdomainAllowlistAvailable?: boolean;\n\t/** Human-readable probe detail when the backend cannot enforce the policy. */\n\tunavailableReason?: string;\n}\n\nexport interface SandboxFallbackDecision extends SandboxDecision {\n\tallowShell: boolean;\n\tallowExec: boolean;\n\tallowReadOnlyTools: boolean;\n}\n\nconst SENSITIVE_PATH_PATTERN =\n\t/(?:^|[/\\\\])(?:\\.env(?:\\..*)?|auth\\.json|oauth\\.json|\\.netrc|\\.npmrc|\\.pgpass|credentials|id_rsa|id_dsa|id_ecdsa|id_ed25519|.*(?:secret|token|private[_-]?key|credential).*)$/i;\n\nfunction decision(allowed: boolean, rule: string, reason: string): SandboxDecision {\n\treturn { allowed, rule, reason };\n}\n\nfunction normalize(value: string): string {\n\treturn path\n\t\t.resolve(value)\n\t\t.replace(/\\\\/g, \"/\")\n\t\t.replace(/\\/+$/g, (suffix) => (value === suffix ? \"/\" : \"\"));\n}\n\nfunction isInside(parent: string, child: string): boolean {\n\tconst normalizedParent = normalize(parent);\n\tconst normalizedChild = normalize(child);\n\treturn normalizedChild === normalizedParent || normalizedChild.startsWith(`${normalizedParent}/`);\n}\n\nfunction isSensitivePath(value: string): boolean {\n\treturn SENSITIVE_PATH_PATTERN.test(value.replace(/\\\\/g, \"/\"));\n}\n\nfunction stripGlobSuffix(pattern: string): string {\n\tif (pattern.endsWith(\"/**\")) return pattern.slice(0, -3);\n\tif (pattern.endsWith(\"/*\")) return pattern.slice(0, -2);\n\treturn pattern;\n}\n\nfunction matchesPattern(pattern: string, candidate: string): boolean {\n\tconst normalizedPattern = normalize(stripGlobSuffix(pattern));\n\tconst normalizedCandidate = normalize(candidate);\n\treturn normalizedCandidate === normalizedPattern || normalizedCandidate.startsWith(`${normalizedPattern}/`);\n}\n\nfunction matchesAny(patterns: readonly string[], candidate: string): boolean {\n\treturn patterns.some((pattern) => matchesPattern(pattern, candidate));\n}\n\nfunction resolvedDecisionPath(resolved: ResolvedSandboxPath): string | undefined {\n\treturn resolved.realPath ?? resolved.nearestExistingParentRealPath;\n}\n\nfunction rootEscaped(policy: SandboxPolicy, resolved: ResolvedSandboxPath): boolean {\n\tconst candidate = resolvedDecisionPath(resolved);\n\treturn candidate === undefined || !isInside(policy.filesystem.root, candidate);\n}\n\nexport function decidePathAccess(\n\tpolicy: SandboxPolicy,\n\trequest: PathAccessRequest,\n\tresolver: SandboxPathResolver,\n): SandboxDecision {\n\tif (policy.mode === \"off\") {\n\t\treturn decision(true, \"sandbox.off\", \"Sandbox policy is disabled.\");\n\t}\n\n\tif (request.path.includes(\"\\0\")) {\n\t\treturn decision(false, \"path.invalid\", \"Path contains a NUL byte.\");\n\t}\n\n\tif (isSensitivePath(request.path)) {\n\t\treturn decision(false, \"path.secret\", \"Sensitive credential-like paths are denied.\");\n\t}\n\n\tconst resolved = resolver(request.path);\n\tif (resolved.error) {\n\t\treturn decision(false, \"path.resolve_error\", resolved.error);\n\t}\n\tif (rootEscaped(policy, resolved)) {\n\t\treturn decision(false, \"path.root_escape\", \"Resolved path is outside the sandbox root.\");\n\t}\n\tif (resolved.isSymlink && !policy.filesystem.followSymlinks) {\n\t\treturn decision(false, \"path.symlink\", \"Symlink traversal is denied by policy.\");\n\t}\n\n\tconst candidate = resolvedDecisionPath(resolved) ?? request.path;\n\tif (request.kind === \"read\") {\n\t\tif (matchesAny(policy.filesystem.readDeny, candidate) || matchesAny(policy.filesystem.readDeny, request.path)) {\n\t\t\treturn decision(false, \"path.read_deny\", \"Read path matches a deny rule.\");\n\t\t}\n\t\tif (!matchesAny(policy.filesystem.readAllow, candidate)) {\n\t\t\treturn decision(false, \"path.read_not_allowed\", \"Read path is not in an allow rule.\");\n\t\t}\n\t\treturn decision(true, \"path.read_allow\", \"Read path is allowed.\");\n\t}\n\n\tif (matchesAny(policy.filesystem.denyWrite, candidate) || matchesAny(policy.filesystem.denyWrite, request.path)) {\n\t\treturn decision(false, \"path.deny_write\", \"Write path matches an unoverrideable denyWrite rule.\");\n\t}\n\tif (matchesAny(policy.filesystem.writeAllow, candidate) || matchesAny(policy.filesystem.tempWrite, candidate)) {\n\t\treturn decision(true, \"path.write_allow\", \"Write path is allowed.\");\n\t}\n\treturn decision(false, \"path.write_not_allowed\", \"Write path is not in an allow rule.\");\n}\n\nfunction hostFromRequest(request: NetworkAccessRequest): string | undefined {\n\tif (request.host) return request.host.toLowerCase();\n\tif (!request.url) return undefined;\n\ttry {\n\t\treturn new URL(request.url).hostname.toLowerCase();\n\t} catch {\n\t\treturn undefined;\n\t}\n}\n\nfunction hostMatches(patterns: readonly string[], host: string): boolean {\n\treturn patterns.some((pattern) => {\n\t\tconst normalized = pattern.toLowerCase();\n\t\treturn host === normalized || host.endsWith(`.${normalized}`);\n\t});\n}\n\nexport function decideNetworkAccess(policy: SandboxPolicy, request: NetworkAccessRequest): SandboxDecision {\n\tif (policy.mode === \"off\") return decision(true, \"sandbox.off\", \"Sandbox policy is disabled.\");\n\tif (request.browser || request.unixSocketPath) {\n\t\treturn decision(false, \"network.socket_or_browser\", \"Browser and Unix socket access is denied by default.\");\n\t}\n\tif (policy.network.mode === \"none\") {\n\t\treturn decision(false, \"network.none\", \"Network access is disabled by policy.\");\n\t}\n\tif (request.loopback) {\n\t\treturn policy.network.mode === \"loopback\" ||\n\t\t\tpolicy.network.mode === \"domain-allowlist\" ||\n\t\t\tpolicy.network.mode === \"all-explicit\"\n\t\t\t? decision(true, \"network.loopback\", \"Loopback access is allowed.\")\n\t\t\t: decision(false, \"network.loopback_denied\", \"Loopback access is denied.\");\n\t}\n\tconst host = hostFromRequest(request);\n\tif (!host) return decision(false, \"network.unknown_host\", \"Network host could not be resolved from request.\");\n\tif (hostMatches(policy.network.deniedDomains, host)) {\n\t\treturn decision(false, \"network.domain_deny\", \"Host matches a denied domain.\");\n\t}\n\tif (policy.network.mode === \"all-explicit\") {\n\t\treturn decision(true, \"network.explicit_all\", \"Explicit network profile allows outbound host access.\");\n\t}\n\tif (policy.network.mode === \"domain-allowlist\" && hostMatches(policy.network.allowedDomains, host)) {\n\t\treturn decision(true, \"network.domain_allow\", \"Host matches an allowed domain.\");\n\t}\n\treturn decision(false, \"network.domain_not_allowed\", \"Host is not allowed by network policy.\");\n}\n\nexport function decideSandboxFallback(policy: SandboxPolicy, backend: SandboxBackendStatus): SandboxFallbackDecision {\n\tif (policy.mode === \"off\") {\n\t\treturn {\n\t\t\t...decision(true, \"sandbox.off\", \"Sandbox policy is disabled.\"),\n\t\t\tallowShell: true,\n\t\t\tallowExec: true,\n\t\t\tallowReadOnlyTools: true,\n\t\t};\n\t}\n\tif (backend.backendAvailable) {\n\t\treturn {\n\t\t\t...decision(true, \"sandbox.backend_available\", \"Sandbox backend is available.\"),\n\t\t\tallowShell: policy.process.allowShell,\n\t\t\tallowExec: policy.process.allowExec,\n\t\t\tallowReadOnlyTools: true,\n\t\t};\n\t}\n\tif (policy.mode === \"audit\") {\n\t\treturn {\n\t\t\t...decision(true, \"sandbox.audit_fallback\", \"Audit mode permits execution without backend.\"),\n\t\t\tallowShell: true,\n\t\t\tallowExec: true,\n\t\t\tallowReadOnlyTools: true,\n\t\t};\n\t}\n\tconst backendDetail = backend.unavailableReason ? ` ${backend.unavailableReason}` : \"\";\n\treturn {\n\t\t...decision(\n\t\t\tfalse,\n\t\t\t\"sandbox.backend_missing\",\n\t\t\t`Enforce mode blocks shell and exec when no backend is available.${backendDetail}`,\n\t\t),\n\t\tallowShell: false,\n\t\tallowExec: false,\n\t\tallowReadOnlyTools: true,\n\t};\n}\n\nexport function mergeSandboxPolicy(\n\tbase: SandboxPolicy,\n\toverride: Partial<SandboxPolicy>,\n\toptions: { allowBroaden?: boolean } = {},\n): SandboxPolicy {\n\tconst allowBroaden = options.allowBroaden === true;\n\treturn {\n\t\tmode: override.mode ?? base.mode,\n\t\tprofile: override.profile ?? base.profile,\n\t\tfilesystem: {\n\t\t\troot: override.filesystem?.root ?? base.filesystem.root,\n\t\t\treadAllow: allowBroaden\n\t\t\t\t? (override.filesystem?.readAllow ?? base.filesystem.readAllow)\n\t\t\t\t: intersectOrBase(base.filesystem.readAllow, override.filesystem?.readAllow),\n\t\t\treadDeny: union(base.filesystem.readDeny, override.filesystem?.readDeny),\n\t\t\twriteAllow: allowBroaden\n\t\t\t\t? (override.filesystem?.writeAllow ?? base.filesystem.writeAllow)\n\t\t\t\t: intersectOrBase(base.filesystem.writeAllow, override.filesystem?.writeAllow),\n\t\t\tdenyWrite: union(base.filesystem.denyWrite, override.filesystem?.denyWrite),\n\t\t\ttempWrite: allowBroaden\n\t\t\t\t? (override.filesystem?.tempWrite ?? base.filesystem.tempWrite)\n\t\t\t\t: intersectOrBase(base.filesystem.tempWrite, override.filesystem?.tempWrite),\n\t\t\tfollowSymlinks: false,\n\t\t},\n\t\tnetwork: {\n\t\t\tmode: allowBroaden\n\t\t\t\t? (override.network?.mode ?? base.network.mode)\n\t\t\t\t: narrowNetworkMode(base.network.mode, override.network?.mode),\n\t\t\tallowedDomains: allowBroaden\n\t\t\t\t? (override.network?.allowedDomains ?? base.network.allowedDomains)\n\t\t\t\t: intersectOrBase(base.network.allowedDomains, override.network?.allowedDomains),\n\t\t\tdeniedDomains: union(base.network.deniedDomains, override.network?.deniedDomains),\n\t\t\tallowUnixSockets: allowBroaden\n\t\t\t\t? (override.network?.allowUnixSockets ?? base.network.allowUnixSockets)\n\t\t\t\t: intersectOrBase(base.network.allowUnixSockets, override.network?.allowUnixSockets),\n\t\t\tallowBrowser: false,\n\t\t},\n\t\tprocess: {\n\t\t\tallowExec: allowBroaden\n\t\t\t\t? (override.process?.allowExec ?? base.process.allowExec)\n\t\t\t\t: base.process.allowExec && (override.process?.allowExec ?? true),\n\t\t\tallowShell: allowBroaden\n\t\t\t\t? (override.process?.allowShell ?? base.process.allowShell)\n\t\t\t\t: base.process.allowShell && (override.process?.allowShell ?? true),\n\t\t\tallowPrivilege: false,\n\t\t},\n\t};\n}\n\nfunction union(base: readonly string[], override: readonly string[] | undefined): string[] {\n\treturn [...new Set([...base, ...(override ?? [])])];\n}\n\nfunction intersectOrBase(base: readonly string[], override: readonly string[] | undefined): string[] {\n\tif (override === undefined) return [...base];\n\tconst result: string[] = [];\n\tfor (const candidate of override) {\n\t\tfor (const entry of base) {\n\t\t\tif (normalize(candidate) === normalize(entry)) {\n\t\t\t\tresult.push(candidate);\n\t\t\t\tcontinue;\n\t\t\t}\n\t\t\tif (matchesPattern(entry, candidate)) {\n\t\t\t\tresult.push(candidate);\n\t\t\t\tcontinue;\n\t\t\t}\n\t\t\tif (matchesPattern(candidate, entry)) {\n\t\t\t\tresult.push(entry);\n\t\t\t}\n\t\t}\n\t}\n\treturn [...new Set(result)];\n}\n\nfunction narrowNetworkMode(base: NetworkMode, override: NetworkMode | undefined): NetworkMode {\n\tif (override === undefined) return base;\n\tconst rank: Record<NetworkMode, number> = { none: 0, loopback: 1, \"domain-allowlist\": 2, \"all-explicit\": 3 };\n\treturn rank[override] <= rank[base] ? override : base;\n}\n\nexport interface BashSpawnPreflightContext {\n\tcommand: string;\n\tcwd: string;\n}\n\nexport interface BashSpawnPreflightDecision extends SandboxDecision {\n\tallowShell: boolean;\n}\n\n/**\n * Final pure preflight for a local bash spawn. Combines the backend-availability\n * fallback (deny shell when an OS sandbox backend is missing under enforce mode)\n * with a working-directory containment check (deny when cwd resolves outside the\n * sandbox root). This helper does not itself wrap the process in an OS sandbox; it\n * only decides whether the spawn may proceed.\n */\nexport function preflightBashSpawn(\n\tpolicy: SandboxPolicy,\n\tbackend: SandboxBackendStatus,\n\tcontext: BashSpawnPreflightContext,\n\tresolver?: SandboxPathResolver,\n): BashSpawnPreflightDecision {\n\tif (policy.mode === \"off\") {\n\t\treturn { ...decision(true, \"sandbox.off\", \"Sandbox policy is disabled.\"), allowShell: true };\n\t}\n\tif (!policy.process.allowShell) {\n\t\treturn {\n\t\t\t...decision(false, \"process.shell_denied\", \"Shell execution is disabled by policy.\"),\n\t\t\tallowShell: false,\n\t\t};\n\t}\n\tconst fallback = decideSandboxFallback(policy, backend);\n\tif (!fallback.allowShell) {\n\t\treturn { ...decision(false, fallback.rule, fallback.reason), allowShell: false };\n\t}\n\tif (context.cwd.includes(\"\\0\")) {\n\t\treturn { ...decision(false, \"cwd.invalid\", \"Working directory contains a NUL byte.\"), allowShell: false };\n\t}\n\tconst resolved = resolver?.(context.cwd);\n\tif (resolved?.error) {\n\t\treturn { ...decision(false, \"cwd.resolve_error\", resolved.error), allowShell: false };\n\t}\n\tif (resolved?.isSymlink) {\n\t\treturn {\n\t\t\t...decision(false, \"cwd.symlink\", \"Working directory is a symlink and traversal is denied.\"),\n\t\t\tallowShell: false,\n\t\t};\n\t}\n\tconst candidate = resolved ? (resolvedDecisionPath(resolved) ?? context.cwd) : context.cwd;\n\tif (!isInside(policy.filesystem.root, candidate)) {\n\t\treturn {\n\t\t\t...decision(false, \"cwd.root_escape\", \"Working directory is outside the sandbox root.\"),\n\t\t\tallowShell: false,\n\t\t};\n\t}\n\treturn {\n\t\t...decision(true, \"sandbox.shell_preflight_ok\", \"Bash spawn is permitted by sandbox policy.\"),\n\t\tallowShell: true,\n\t};\n}\n"]}
1
+ {"version":3,"file":"policy.d.ts","sourceRoot":"","sources":["../../../src/core/sandbox/policy.ts"],"names":[],"mappings":"AAEA,OAAO,EAAE,kBAAkB,EAAE,MAAM,mBAAmB,CAAC;AAEvD,OAAO,KAAK,EACX,yBAAyB,EACzB,0BAA0B,EAC1B,oBAAoB,EACpB,iBAAiB,EAEjB,oBAAoB,EACpB,eAAe,EACf,uBAAuB,EACvB,mBAAmB,EACnB,aAAa,EACb,MAAM,mBAAmB,CAAC;AAE3B,cAAc,mBAAmB,CAAC;AA0BlC,wBAAgB,gBAAgB,CAC/B,MAAM,EAAE,aAAa,EACrB,OAAO,EAAE,iBAAiB,EAC1B,QAAQ,EAAE,mBAAmB,GAC3B,eAAe,CA0CjB;AAmBD,wBAAgB,mBAAmB,CAAC,MAAM,EAAE,aAAa,EAAE,OAAO,EAAE,oBAAoB,GAAG,eAAe,CA2BzG;AAED,wBAAgB,qBAAqB,CAAC,MAAM,EAAE,aAAa,EAAE,OAAO,EAAE,oBAAoB,GAAG,uBAAuB,CAoCnH;AAED;;;;;;GAMG;AACH,wBAAgB,kBAAkB,CACjC,MAAM,EAAE,aAAa,EACrB,OAAO,EAAE,oBAAoB,EAC7B,OAAO,EAAE,yBAAyB,EAClC,QAAQ,CAAC,EAAE,mBAAmB,GAC5B,0BAA0B,CAsC5B","sourcesContent":["import { isInsideSandboxPath as isInside, matchesSandboxPath as matchesPattern } from \"./policy-paths.ts\";\n\nexport { mergeSandboxPolicy } from \"./policy-merge.ts\";\n\nimport type {\n\tBashSpawnPreflightContext,\n\tBashSpawnPreflightDecision,\n\tNetworkAccessRequest,\n\tPathAccessRequest,\n\tResolvedSandboxPath,\n\tSandboxBackendStatus,\n\tSandboxDecision,\n\tSandboxFallbackDecision,\n\tSandboxPathResolver,\n\tSandboxPolicy,\n} from \"./policy-types.ts\";\n\nexport * from \"./policy-types.ts\";\n\nconst SENSITIVE_PATH_PATTERN =\n\t/(?:^|[/\\\\])(?:\\.env(?:\\..*)?|auth\\.json|oauth\\.json|\\.netrc|\\.npmrc|\\.pgpass|credentials|id_rsa|id_dsa|id_ecdsa|id_ed25519|.*(?:secret|token|private[_-]?key|credential).*)$/i;\n\nfunction decision(allowed: boolean, rule: string, reason: string): SandboxDecision {\n\treturn { allowed, rule, reason };\n}\n\nfunction isSensitivePath(value: string): boolean {\n\treturn SENSITIVE_PATH_PATTERN.test(value.replace(/\\\\/g, \"/\"));\n}\n\nfunction matchesAny(patterns: readonly string[], candidate: string): boolean {\n\treturn patterns.some((pattern) => matchesPattern(pattern, candidate));\n}\n\nfunction resolvedDecisionPath(resolved: ResolvedSandboxPath): string | undefined {\n\treturn resolved.realPath ?? resolved.nearestExistingParentRealPath;\n}\n\nfunction rootEscaped(policy: SandboxPolicy, resolved: ResolvedSandboxPath): boolean {\n\tconst candidate = resolvedDecisionPath(resolved);\n\treturn candidate === undefined || !isInside(policy.filesystem.root, candidate);\n}\n\nexport function decidePathAccess(\n\tpolicy: SandboxPolicy,\n\trequest: PathAccessRequest,\n\tresolver: SandboxPathResolver,\n): SandboxDecision {\n\tif (policy.mode === \"off\") {\n\t\treturn decision(true, \"sandbox.off\", \"Sandbox policy is disabled.\");\n\t}\n\n\tif (request.path.includes(\"\\0\")) {\n\t\treturn decision(false, \"path.invalid\", \"Path contains a NUL byte.\");\n\t}\n\n\tif (isSensitivePath(request.path)) {\n\t\treturn decision(false, \"path.secret\", \"Sensitive credential-like paths are denied.\");\n\t}\n\n\tconst resolved = resolver(request.path);\n\tif (resolved.error) {\n\t\treturn decision(false, \"path.resolve_error\", resolved.error);\n\t}\n\tif (rootEscaped(policy, resolved)) {\n\t\treturn decision(false, \"path.root_escape\", \"Resolved path is outside the sandbox root.\");\n\t}\n\tif (resolved.isSymlink && !policy.filesystem.followSymlinks) {\n\t\treturn decision(false, \"path.symlink\", \"Symlink traversal is denied by policy.\");\n\t}\n\n\tconst candidate = resolvedDecisionPath(resolved) ?? request.path;\n\tif (request.kind === \"read\") {\n\t\tif (matchesAny(policy.filesystem.readDeny, candidate) || matchesAny(policy.filesystem.readDeny, request.path)) {\n\t\t\treturn decision(false, \"path.read_deny\", \"Read path matches a deny rule.\");\n\t\t}\n\t\tif (!matchesAny(policy.filesystem.readAllow, candidate)) {\n\t\t\treturn decision(false, \"path.read_not_allowed\", \"Read path is not in an allow rule.\");\n\t\t}\n\t\treturn decision(true, \"path.read_allow\", \"Read path is allowed.\");\n\t}\n\n\tif (matchesAny(policy.filesystem.denyWrite, candidate) || matchesAny(policy.filesystem.denyWrite, request.path)) {\n\t\treturn decision(false, \"path.deny_write\", \"Write path matches an unoverrideable denyWrite rule.\");\n\t}\n\tif (matchesAny(policy.filesystem.writeAllow, candidate) || matchesAny(policy.filesystem.tempWrite, candidate)) {\n\t\treturn decision(true, \"path.write_allow\", \"Write path is allowed.\");\n\t}\n\treturn decision(false, \"path.write_not_allowed\", \"Write path is not in an allow rule.\");\n}\n\nfunction hostFromRequest(request: NetworkAccessRequest): string | undefined {\n\tif (request.host) return request.host.toLowerCase();\n\tif (!request.url) return undefined;\n\ttry {\n\t\treturn new URL(request.url).hostname.toLowerCase();\n\t} catch {\n\t\treturn undefined;\n\t}\n}\n\nfunction hostMatches(patterns: readonly string[], host: string): boolean {\n\treturn patterns.some((pattern) => {\n\t\tconst normalized = pattern.toLowerCase();\n\t\treturn host === normalized || host.endsWith(`.${normalized}`);\n\t});\n}\n\nexport function decideNetworkAccess(policy: SandboxPolicy, request: NetworkAccessRequest): SandboxDecision {\n\tif (policy.mode === \"off\") return decision(true, \"sandbox.off\", \"Sandbox policy is disabled.\");\n\tif (request.browser || request.unixSocketPath) {\n\t\treturn decision(false, \"network.socket_or_browser\", \"Browser and Unix socket access is denied by default.\");\n\t}\n\tif (policy.network.mode === \"none\") {\n\t\treturn decision(false, \"network.none\", \"Network access is disabled by policy.\");\n\t}\n\tif (request.loopback) {\n\t\treturn policy.network.mode === \"loopback\" ||\n\t\t\tpolicy.network.mode === \"domain-allowlist\" ||\n\t\t\tpolicy.network.mode === \"all-explicit\"\n\t\t\t? decision(true, \"network.loopback\", \"Loopback access is allowed.\")\n\t\t\t: decision(false, \"network.loopback_denied\", \"Loopback access is denied.\");\n\t}\n\tconst host = hostFromRequest(request);\n\tif (!host) return decision(false, \"network.unknown_host\", \"Network host could not be resolved from request.\");\n\tif (hostMatches(policy.network.deniedDomains, host)) {\n\t\treturn decision(false, \"network.domain_deny\", \"Host matches a denied domain.\");\n\t}\n\tif (policy.network.mode === \"all-explicit\") {\n\t\treturn decision(true, \"network.explicit_all\", \"Explicit network profile allows outbound host access.\");\n\t}\n\tif (policy.network.mode === \"domain-allowlist\" && hostMatches(policy.network.allowedDomains, host)) {\n\t\treturn decision(true, \"network.domain_allow\", \"Host matches an allowed domain.\");\n\t}\n\treturn decision(false, \"network.domain_not_allowed\", \"Host is not allowed by network policy.\");\n}\n\nexport function decideSandboxFallback(policy: SandboxPolicy, backend: SandboxBackendStatus): SandboxFallbackDecision {\n\tif (policy.mode === \"off\") {\n\t\treturn {\n\t\t\t...decision(true, \"sandbox.off\", \"Sandbox policy is disabled.\"),\n\t\t\tallowShell: true,\n\t\t\tallowExec: true,\n\t\t\tallowReadOnlyTools: true,\n\t\t};\n\t}\n\tif (backend.backendAvailable) {\n\t\treturn {\n\t\t\t...decision(true, \"sandbox.backend_available\", \"Sandbox backend is available.\"),\n\t\t\tallowShell: policy.process.allowShell,\n\t\t\tallowExec: policy.process.allowExec,\n\t\t\tallowReadOnlyTools: true,\n\t\t};\n\t}\n\tif (policy.mode === \"audit\") {\n\t\treturn {\n\t\t\t...decision(true, \"sandbox.audit_fallback\", \"Audit mode permits execution without backend.\"),\n\t\t\tallowShell: true,\n\t\t\tallowExec: true,\n\t\t\tallowReadOnlyTools: true,\n\t\t};\n\t}\n\tconst backendDetail = backend.unavailableReason ? ` ${backend.unavailableReason}` : \"\";\n\treturn {\n\t\t...decision(\n\t\t\tfalse,\n\t\t\t\"sandbox.backend_missing\",\n\t\t\t`Enforce mode blocks shell and exec when no backend is available.${backendDetail}`,\n\t\t),\n\t\tallowShell: false,\n\t\tallowExec: false,\n\t\tallowReadOnlyTools: true,\n\t};\n}\n\n/**\n * Final pure preflight for a local bash spawn. Combines the backend-availability\n * fallback (deny shell when an OS sandbox backend is missing under enforce mode)\n * with a working-directory containment check (deny when cwd resolves outside the\n * sandbox root). This helper does not itself wrap the process in an OS sandbox; it\n * only decides whether the spawn may proceed.\n */\nexport function preflightBashSpawn(\n\tpolicy: SandboxPolicy,\n\tbackend: SandboxBackendStatus,\n\tcontext: BashSpawnPreflightContext,\n\tresolver?: SandboxPathResolver,\n): BashSpawnPreflightDecision {\n\tif (policy.mode === \"off\") {\n\t\treturn { ...decision(true, \"sandbox.off\", \"Sandbox policy is disabled.\"), allowShell: true };\n\t}\n\tif (!policy.process.allowShell) {\n\t\treturn {\n\t\t\t...decision(false, \"process.shell_denied\", \"Shell execution is disabled by policy.\"),\n\t\t\tallowShell: false,\n\t\t};\n\t}\n\tconst fallback = decideSandboxFallback(policy, backend);\n\tif (!fallback.allowShell) {\n\t\treturn { ...decision(false, fallback.rule, fallback.reason), allowShell: false };\n\t}\n\tif (context.cwd.includes(\"\\0\")) {\n\t\treturn { ...decision(false, \"cwd.invalid\", \"Working directory contains a NUL byte.\"), allowShell: false };\n\t}\n\tconst resolved = resolver?.(context.cwd);\n\tif (resolved?.error) {\n\t\treturn { ...decision(false, \"cwd.resolve_error\", resolved.error), allowShell: false };\n\t}\n\tif (resolved?.isSymlink) {\n\t\treturn {\n\t\t\t...decision(false, \"cwd.symlink\", \"Working directory is a symlink and traversal is denied.\"),\n\t\t\tallowShell: false,\n\t\t};\n\t}\n\tconst candidate = resolved ? (resolvedDecisionPath(resolved) ?? context.cwd) : context.cwd;\n\tif (!isInside(policy.filesystem.root, candidate)) {\n\t\treturn {\n\t\t\t...decision(false, \"cwd.root_escape\", \"Working directory is outside the sandbox root.\"),\n\t\t\tallowShell: false,\n\t\t};\n\t}\n\treturn {\n\t\t...decision(true, \"sandbox.shell_preflight_ok\", \"Bash spawn is permitted by sandbox policy.\"),\n\t\tallowShell: true,\n\t};\n}\n"]}
@@ -1,34 +1,13 @@
1
- import path from "node:path";
1
+ import { isInsideSandboxPath as isInside, matchesSandboxPath as matchesPattern } from "./policy-paths.js";
2
+ export { mergeSandboxPolicy } from "./policy-merge.js";
3
+ export * from "./policy-types.js";
2
4
  const SENSITIVE_PATH_PATTERN = /(?:^|[/\\])(?:\.env(?:\..*)?|auth\.json|oauth\.json|\.netrc|\.npmrc|\.pgpass|credentials|id_rsa|id_dsa|id_ecdsa|id_ed25519|.*(?:secret|token|private[_-]?key|credential).*)$/i;
3
5
  function decision(allowed, rule, reason) {
4
6
  return { allowed, rule, reason };
5
7
  }
6
- function normalize(value) {
7
- return path
8
- .resolve(value)
9
- .replace(/\\/g, "/")
10
- .replace(/\/+$/g, (suffix) => (value === suffix ? "/" : ""));
11
- }
12
- function isInside(parent, child) {
13
- const normalizedParent = normalize(parent);
14
- const normalizedChild = normalize(child);
15
- return normalizedChild === normalizedParent || normalizedChild.startsWith(`${normalizedParent}/`);
16
- }
17
8
  function isSensitivePath(value) {
18
9
  return SENSITIVE_PATH_PATTERN.test(value.replace(/\\/g, "/"));
19
10
  }
20
- function stripGlobSuffix(pattern) {
21
- if (pattern.endsWith("/**"))
22
- return pattern.slice(0, -3);
23
- if (pattern.endsWith("/*"))
24
- return pattern.slice(0, -2);
25
- return pattern;
26
- }
27
- function matchesPattern(pattern, candidate) {
28
- const normalizedPattern = normalize(stripGlobSuffix(pattern));
29
- const normalizedCandidate = normalize(candidate);
30
- return normalizedCandidate === normalizedPattern || normalizedCandidate.startsWith(`${normalizedPattern}/`);
31
- }
32
11
  function matchesAny(patterns, candidate) {
33
12
  return patterns.some((pattern) => matchesPattern(pattern, candidate));
34
13
  }
@@ -158,80 +137,6 @@ export function decideSandboxFallback(policy, backend) {
158
137
  allowReadOnlyTools: true,
159
138
  };
160
139
  }
161
- export function mergeSandboxPolicy(base, override, options = {}) {
162
- const allowBroaden = options.allowBroaden === true;
163
- return {
164
- mode: override.mode ?? base.mode,
165
- profile: override.profile ?? base.profile,
166
- filesystem: {
167
- root: override.filesystem?.root ?? base.filesystem.root,
168
- readAllow: allowBroaden
169
- ? (override.filesystem?.readAllow ?? base.filesystem.readAllow)
170
- : intersectOrBase(base.filesystem.readAllow, override.filesystem?.readAllow),
171
- readDeny: union(base.filesystem.readDeny, override.filesystem?.readDeny),
172
- writeAllow: allowBroaden
173
- ? (override.filesystem?.writeAllow ?? base.filesystem.writeAllow)
174
- : intersectOrBase(base.filesystem.writeAllow, override.filesystem?.writeAllow),
175
- denyWrite: union(base.filesystem.denyWrite, override.filesystem?.denyWrite),
176
- tempWrite: allowBroaden
177
- ? (override.filesystem?.tempWrite ?? base.filesystem.tempWrite)
178
- : intersectOrBase(base.filesystem.tempWrite, override.filesystem?.tempWrite),
179
- followSymlinks: false,
180
- },
181
- network: {
182
- mode: allowBroaden
183
- ? (override.network?.mode ?? base.network.mode)
184
- : narrowNetworkMode(base.network.mode, override.network?.mode),
185
- allowedDomains: allowBroaden
186
- ? (override.network?.allowedDomains ?? base.network.allowedDomains)
187
- : intersectOrBase(base.network.allowedDomains, override.network?.allowedDomains),
188
- deniedDomains: union(base.network.deniedDomains, override.network?.deniedDomains),
189
- allowUnixSockets: allowBroaden
190
- ? (override.network?.allowUnixSockets ?? base.network.allowUnixSockets)
191
- : intersectOrBase(base.network.allowUnixSockets, override.network?.allowUnixSockets),
192
- allowBrowser: false,
193
- },
194
- process: {
195
- allowExec: allowBroaden
196
- ? (override.process?.allowExec ?? base.process.allowExec)
197
- : base.process.allowExec && (override.process?.allowExec ?? true),
198
- allowShell: allowBroaden
199
- ? (override.process?.allowShell ?? base.process.allowShell)
200
- : base.process.allowShell && (override.process?.allowShell ?? true),
201
- allowPrivilege: false,
202
- },
203
- };
204
- }
205
- function union(base, override) {
206
- return [...new Set([...base, ...(override ?? [])])];
207
- }
208
- function intersectOrBase(base, override) {
209
- if (override === undefined)
210
- return [...base];
211
- const result = [];
212
- for (const candidate of override) {
213
- for (const entry of base) {
214
- if (normalize(candidate) === normalize(entry)) {
215
- result.push(candidate);
216
- continue;
217
- }
218
- if (matchesPattern(entry, candidate)) {
219
- result.push(candidate);
220
- continue;
221
- }
222
- if (matchesPattern(candidate, entry)) {
223
- result.push(entry);
224
- }
225
- }
226
- }
227
- return [...new Set(result)];
228
- }
229
- function narrowNetworkMode(base, override) {
230
- if (override === undefined)
231
- return base;
232
- const rank = { none: 0, loopback: 1, "domain-allowlist": 2, "all-explicit": 3 };
233
- return rank[override] <= rank[base] ? override : base;
234
- }
235
140
  /**
236
141
  * Final pure preflight for a local bash spawn. Combines the backend-availability
237
142
  * fallback (deny shell when an OS sandbox backend is missing under enforce mode)
@@ -1 +1 @@
1
- {"version":3,"file":"policy.js","sourceRoot":"","sources":["../../../src/core/sandbox/policy.ts"],"names":[],"mappings":"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","sourcesContent":["import path from \"node:path\";\n\nexport type SandboxMode = \"off\" | \"audit\" | \"enforce\";\nexport type SandboxProfile = \"readonly\" | \"workspace-write\" | \"dev-server\" | \"networked\";\nexport type NetworkMode = \"none\" | \"loopback\" | \"domain-allowlist\" | \"all-explicit\";\nexport type PathAccessKind = \"read\" | \"write\";\nexport type SandboxPlatform = \"linux\" | \"macos\" | \"unsupported\";\n\nexport interface SandboxPolicy {\n\tmode: SandboxMode;\n\tprofile: SandboxProfile;\n\tfilesystem: {\n\t\troot: string;\n\t\treadAllow: readonly string[];\n\t\treadDeny: readonly string[];\n\t\twriteAllow: readonly string[];\n\t\tdenyWrite: readonly string[];\n\t\ttempWrite: readonly string[];\n\t\tfollowSymlinks: false;\n\t};\n\tnetwork: {\n\t\tmode: NetworkMode;\n\t\tallowedDomains: readonly string[];\n\t\tdeniedDomains: readonly string[];\n\t\tallowUnixSockets: readonly string[];\n\t\tallowBrowser: false;\n\t};\n\tprocess: {\n\t\tallowExec: boolean;\n\t\tallowShell: boolean;\n\t\tallowPrivilege: false;\n\t};\n}\n\nexport interface ResolvedSandboxPath {\n\trequestedPath: string;\n\texists: boolean;\n\trealPath?: string;\n\tnearestExistingParentRealPath?: string;\n\tisSymlink?: boolean;\n\terror?: string;\n}\n\nexport type SandboxPathResolver = (requestPath: string) => ResolvedSandboxPath;\n\nexport interface PathAccessRequest {\n\tkind: PathAccessKind;\n\tpath: string;\n}\n\nexport interface SandboxDecision {\n\tallowed: boolean;\n\trule: string;\n\treason: string;\n}\n\nexport interface NetworkAccessRequest {\n\thost?: string;\n\turl?: string;\n\tunixSocketPath?: string;\n\tbrowser?: boolean;\n\tloopback?: boolean;\n}\n\nexport interface SandboxBackendStatus {\n\tplatform: SandboxPlatform;\n\tbackendAvailable: boolean;\n\tdomainAllowlistAvailable?: boolean;\n\t/** Human-readable probe detail when the backend cannot enforce the policy. */\n\tunavailableReason?: string;\n}\n\nexport interface SandboxFallbackDecision extends SandboxDecision {\n\tallowShell: boolean;\n\tallowExec: boolean;\n\tallowReadOnlyTools: boolean;\n}\n\nconst SENSITIVE_PATH_PATTERN =\n\t/(?:^|[/\\\\])(?:\\.env(?:\\..*)?|auth\\.json|oauth\\.json|\\.netrc|\\.npmrc|\\.pgpass|credentials|id_rsa|id_dsa|id_ecdsa|id_ed25519|.*(?:secret|token|private[_-]?key|credential).*)$/i;\n\nfunction decision(allowed: boolean, rule: string, reason: string): SandboxDecision {\n\treturn { allowed, rule, reason };\n}\n\nfunction normalize(value: string): string {\n\treturn path\n\t\t.resolve(value)\n\t\t.replace(/\\\\/g, \"/\")\n\t\t.replace(/\\/+$/g, (suffix) => (value === suffix ? \"/\" : \"\"));\n}\n\nfunction isInside(parent: string, child: string): boolean {\n\tconst normalizedParent = normalize(parent);\n\tconst normalizedChild = normalize(child);\n\treturn normalizedChild === normalizedParent || normalizedChild.startsWith(`${normalizedParent}/`);\n}\n\nfunction isSensitivePath(value: string): boolean {\n\treturn SENSITIVE_PATH_PATTERN.test(value.replace(/\\\\/g, \"/\"));\n}\n\nfunction stripGlobSuffix(pattern: string): string {\n\tif (pattern.endsWith(\"/**\")) return pattern.slice(0, -3);\n\tif (pattern.endsWith(\"/*\")) return pattern.slice(0, -2);\n\treturn pattern;\n}\n\nfunction matchesPattern(pattern: string, candidate: string): boolean {\n\tconst normalizedPattern = normalize(stripGlobSuffix(pattern));\n\tconst normalizedCandidate = normalize(candidate);\n\treturn normalizedCandidate === normalizedPattern || normalizedCandidate.startsWith(`${normalizedPattern}/`);\n}\n\nfunction matchesAny(patterns: readonly string[], candidate: string): boolean {\n\treturn patterns.some((pattern) => matchesPattern(pattern, candidate));\n}\n\nfunction resolvedDecisionPath(resolved: ResolvedSandboxPath): string | undefined {\n\treturn resolved.realPath ?? resolved.nearestExistingParentRealPath;\n}\n\nfunction rootEscaped(policy: SandboxPolicy, resolved: ResolvedSandboxPath): boolean {\n\tconst candidate = resolvedDecisionPath(resolved);\n\treturn candidate === undefined || !isInside(policy.filesystem.root, candidate);\n}\n\nexport function decidePathAccess(\n\tpolicy: SandboxPolicy,\n\trequest: PathAccessRequest,\n\tresolver: SandboxPathResolver,\n): SandboxDecision {\n\tif (policy.mode === \"off\") {\n\t\treturn decision(true, \"sandbox.off\", \"Sandbox policy is disabled.\");\n\t}\n\n\tif (request.path.includes(\"\\0\")) {\n\t\treturn decision(false, \"path.invalid\", \"Path contains a NUL byte.\");\n\t}\n\n\tif (isSensitivePath(request.path)) {\n\t\treturn decision(false, \"path.secret\", \"Sensitive credential-like paths are denied.\");\n\t}\n\n\tconst resolved = resolver(request.path);\n\tif (resolved.error) {\n\t\treturn decision(false, \"path.resolve_error\", resolved.error);\n\t}\n\tif (rootEscaped(policy, resolved)) {\n\t\treturn decision(false, \"path.root_escape\", \"Resolved path is outside the sandbox root.\");\n\t}\n\tif (resolved.isSymlink && !policy.filesystem.followSymlinks) {\n\t\treturn decision(false, \"path.symlink\", \"Symlink traversal is denied by policy.\");\n\t}\n\n\tconst candidate = resolvedDecisionPath(resolved) ?? request.path;\n\tif (request.kind === \"read\") {\n\t\tif (matchesAny(policy.filesystem.readDeny, candidate) || matchesAny(policy.filesystem.readDeny, request.path)) {\n\t\t\treturn decision(false, \"path.read_deny\", \"Read path matches a deny rule.\");\n\t\t}\n\t\tif (!matchesAny(policy.filesystem.readAllow, candidate)) {\n\t\t\treturn decision(false, \"path.read_not_allowed\", \"Read path is not in an allow rule.\");\n\t\t}\n\t\treturn decision(true, \"path.read_allow\", \"Read path is allowed.\");\n\t}\n\n\tif (matchesAny(policy.filesystem.denyWrite, candidate) || matchesAny(policy.filesystem.denyWrite, request.path)) {\n\t\treturn decision(false, \"path.deny_write\", \"Write path matches an unoverrideable denyWrite rule.\");\n\t}\n\tif (matchesAny(policy.filesystem.writeAllow, candidate) || matchesAny(policy.filesystem.tempWrite, candidate)) {\n\t\treturn decision(true, \"path.write_allow\", \"Write path is allowed.\");\n\t}\n\treturn decision(false, \"path.write_not_allowed\", \"Write path is not in an allow rule.\");\n}\n\nfunction hostFromRequest(request: NetworkAccessRequest): string | undefined {\n\tif (request.host) return request.host.toLowerCase();\n\tif (!request.url) return undefined;\n\ttry {\n\t\treturn new URL(request.url).hostname.toLowerCase();\n\t} catch {\n\t\treturn undefined;\n\t}\n}\n\nfunction hostMatches(patterns: readonly string[], host: string): boolean {\n\treturn patterns.some((pattern) => {\n\t\tconst normalized = pattern.toLowerCase();\n\t\treturn host === normalized || host.endsWith(`.${normalized}`);\n\t});\n}\n\nexport function decideNetworkAccess(policy: SandboxPolicy, request: NetworkAccessRequest): SandboxDecision {\n\tif (policy.mode === \"off\") return decision(true, \"sandbox.off\", \"Sandbox policy is disabled.\");\n\tif (request.browser || request.unixSocketPath) {\n\t\treturn decision(false, \"network.socket_or_browser\", \"Browser and Unix socket access is denied by default.\");\n\t}\n\tif (policy.network.mode === \"none\") {\n\t\treturn decision(false, \"network.none\", \"Network access is disabled by policy.\");\n\t}\n\tif (request.loopback) {\n\t\treturn policy.network.mode === \"loopback\" ||\n\t\t\tpolicy.network.mode === \"domain-allowlist\" ||\n\t\t\tpolicy.network.mode === \"all-explicit\"\n\t\t\t? decision(true, \"network.loopback\", \"Loopback access is allowed.\")\n\t\t\t: decision(false, \"network.loopback_denied\", \"Loopback access is denied.\");\n\t}\n\tconst host = hostFromRequest(request);\n\tif (!host) return decision(false, \"network.unknown_host\", \"Network host could not be resolved from request.\");\n\tif (hostMatches(policy.network.deniedDomains, host)) {\n\t\treturn decision(false, \"network.domain_deny\", \"Host matches a denied domain.\");\n\t}\n\tif (policy.network.mode === \"all-explicit\") {\n\t\treturn decision(true, \"network.explicit_all\", \"Explicit network profile allows outbound host access.\");\n\t}\n\tif (policy.network.mode === \"domain-allowlist\" && hostMatches(policy.network.allowedDomains, host)) {\n\t\treturn decision(true, \"network.domain_allow\", \"Host matches an allowed domain.\");\n\t}\n\treturn decision(false, \"network.domain_not_allowed\", \"Host is not allowed by network policy.\");\n}\n\nexport function decideSandboxFallback(policy: SandboxPolicy, backend: SandboxBackendStatus): SandboxFallbackDecision {\n\tif (policy.mode === \"off\") {\n\t\treturn {\n\t\t\t...decision(true, \"sandbox.off\", \"Sandbox policy is disabled.\"),\n\t\t\tallowShell: true,\n\t\t\tallowExec: true,\n\t\t\tallowReadOnlyTools: true,\n\t\t};\n\t}\n\tif (backend.backendAvailable) {\n\t\treturn {\n\t\t\t...decision(true, \"sandbox.backend_available\", \"Sandbox backend is available.\"),\n\t\t\tallowShell: policy.process.allowShell,\n\t\t\tallowExec: policy.process.allowExec,\n\t\t\tallowReadOnlyTools: true,\n\t\t};\n\t}\n\tif (policy.mode === \"audit\") {\n\t\treturn {\n\t\t\t...decision(true, \"sandbox.audit_fallback\", \"Audit mode permits execution without backend.\"),\n\t\t\tallowShell: true,\n\t\t\tallowExec: true,\n\t\t\tallowReadOnlyTools: true,\n\t\t};\n\t}\n\tconst backendDetail = backend.unavailableReason ? ` ${backend.unavailableReason}` : \"\";\n\treturn {\n\t\t...decision(\n\t\t\tfalse,\n\t\t\t\"sandbox.backend_missing\",\n\t\t\t`Enforce mode blocks shell and exec when no backend is available.${backendDetail}`,\n\t\t),\n\t\tallowShell: false,\n\t\tallowExec: false,\n\t\tallowReadOnlyTools: true,\n\t};\n}\n\nexport function mergeSandboxPolicy(\n\tbase: SandboxPolicy,\n\toverride: Partial<SandboxPolicy>,\n\toptions: { allowBroaden?: boolean } = {},\n): SandboxPolicy {\n\tconst allowBroaden = options.allowBroaden === true;\n\treturn {\n\t\tmode: override.mode ?? base.mode,\n\t\tprofile: override.profile ?? base.profile,\n\t\tfilesystem: {\n\t\t\troot: override.filesystem?.root ?? base.filesystem.root,\n\t\t\treadAllow: allowBroaden\n\t\t\t\t? (override.filesystem?.readAllow ?? base.filesystem.readAllow)\n\t\t\t\t: intersectOrBase(base.filesystem.readAllow, override.filesystem?.readAllow),\n\t\t\treadDeny: union(base.filesystem.readDeny, override.filesystem?.readDeny),\n\t\t\twriteAllow: allowBroaden\n\t\t\t\t? (override.filesystem?.writeAllow ?? base.filesystem.writeAllow)\n\t\t\t\t: intersectOrBase(base.filesystem.writeAllow, override.filesystem?.writeAllow),\n\t\t\tdenyWrite: union(base.filesystem.denyWrite, override.filesystem?.denyWrite),\n\t\t\ttempWrite: allowBroaden\n\t\t\t\t? (override.filesystem?.tempWrite ?? base.filesystem.tempWrite)\n\t\t\t\t: intersectOrBase(base.filesystem.tempWrite, override.filesystem?.tempWrite),\n\t\t\tfollowSymlinks: false,\n\t\t},\n\t\tnetwork: {\n\t\t\tmode: allowBroaden\n\t\t\t\t? (override.network?.mode ?? base.network.mode)\n\t\t\t\t: narrowNetworkMode(base.network.mode, override.network?.mode),\n\t\t\tallowedDomains: allowBroaden\n\t\t\t\t? (override.network?.allowedDomains ?? base.network.allowedDomains)\n\t\t\t\t: intersectOrBase(base.network.allowedDomains, override.network?.allowedDomains),\n\t\t\tdeniedDomains: union(base.network.deniedDomains, override.network?.deniedDomains),\n\t\t\tallowUnixSockets: allowBroaden\n\t\t\t\t? (override.network?.allowUnixSockets ?? base.network.allowUnixSockets)\n\t\t\t\t: intersectOrBase(base.network.allowUnixSockets, override.network?.allowUnixSockets),\n\t\t\tallowBrowser: false,\n\t\t},\n\t\tprocess: {\n\t\t\tallowExec: allowBroaden\n\t\t\t\t? (override.process?.allowExec ?? base.process.allowExec)\n\t\t\t\t: base.process.allowExec && (override.process?.allowExec ?? true),\n\t\t\tallowShell: allowBroaden\n\t\t\t\t? (override.process?.allowShell ?? base.process.allowShell)\n\t\t\t\t: base.process.allowShell && (override.process?.allowShell ?? true),\n\t\t\tallowPrivilege: false,\n\t\t},\n\t};\n}\n\nfunction union(base: readonly string[], override: readonly string[] | undefined): string[] {\n\treturn [...new Set([...base, ...(override ?? [])])];\n}\n\nfunction intersectOrBase(base: readonly string[], override: readonly string[] | undefined): string[] {\n\tif (override === undefined) return [...base];\n\tconst result: string[] = [];\n\tfor (const candidate of override) {\n\t\tfor (const entry of base) {\n\t\t\tif (normalize(candidate) === normalize(entry)) {\n\t\t\t\tresult.push(candidate);\n\t\t\t\tcontinue;\n\t\t\t}\n\t\t\tif (matchesPattern(entry, candidate)) {\n\t\t\t\tresult.push(candidate);\n\t\t\t\tcontinue;\n\t\t\t}\n\t\t\tif (matchesPattern(candidate, entry)) {\n\t\t\t\tresult.push(entry);\n\t\t\t}\n\t\t}\n\t}\n\treturn [...new Set(result)];\n}\n\nfunction narrowNetworkMode(base: NetworkMode, override: NetworkMode | undefined): NetworkMode {\n\tif (override === undefined) return base;\n\tconst rank: Record<NetworkMode, number> = { none: 0, loopback: 1, \"domain-allowlist\": 2, \"all-explicit\": 3 };\n\treturn rank[override] <= rank[base] ? override : base;\n}\n\nexport interface BashSpawnPreflightContext {\n\tcommand: string;\n\tcwd: string;\n}\n\nexport interface BashSpawnPreflightDecision extends SandboxDecision {\n\tallowShell: boolean;\n}\n\n/**\n * Final pure preflight for a local bash spawn. Combines the backend-availability\n * fallback (deny shell when an OS sandbox backend is missing under enforce mode)\n * with a working-directory containment check (deny when cwd resolves outside the\n * sandbox root). This helper does not itself wrap the process in an OS sandbox; it\n * only decides whether the spawn may proceed.\n */\nexport function preflightBashSpawn(\n\tpolicy: SandboxPolicy,\n\tbackend: SandboxBackendStatus,\n\tcontext: BashSpawnPreflightContext,\n\tresolver?: SandboxPathResolver,\n): BashSpawnPreflightDecision {\n\tif (policy.mode === \"off\") {\n\t\treturn { ...decision(true, \"sandbox.off\", \"Sandbox policy is disabled.\"), allowShell: true };\n\t}\n\tif (!policy.process.allowShell) {\n\t\treturn {\n\t\t\t...decision(false, \"process.shell_denied\", \"Shell execution is disabled by policy.\"),\n\t\t\tallowShell: false,\n\t\t};\n\t}\n\tconst fallback = decideSandboxFallback(policy, backend);\n\tif (!fallback.allowShell) {\n\t\treturn { ...decision(false, fallback.rule, fallback.reason), allowShell: false };\n\t}\n\tif (context.cwd.includes(\"\\0\")) {\n\t\treturn { ...decision(false, \"cwd.invalid\", \"Working directory contains a NUL byte.\"), allowShell: false };\n\t}\n\tconst resolved = resolver?.(context.cwd);\n\tif (resolved?.error) {\n\t\treturn { ...decision(false, \"cwd.resolve_error\", resolved.error), allowShell: false };\n\t}\n\tif (resolved?.isSymlink) {\n\t\treturn {\n\t\t\t...decision(false, \"cwd.symlink\", \"Working directory is a symlink and traversal is denied.\"),\n\t\t\tallowShell: false,\n\t\t};\n\t}\n\tconst candidate = resolved ? (resolvedDecisionPath(resolved) ?? context.cwd) : context.cwd;\n\tif (!isInside(policy.filesystem.root, candidate)) {\n\t\treturn {\n\t\t\t...decision(false, \"cwd.root_escape\", \"Working directory is outside the sandbox root.\"),\n\t\t\tallowShell: false,\n\t\t};\n\t}\n\treturn {\n\t\t...decision(true, \"sandbox.shell_preflight_ok\", \"Bash spawn is permitted by sandbox policy.\"),\n\t\tallowShell: true,\n\t};\n}\n"]}
1
+ {"version":3,"file":"policy.js","sourceRoot":"","sources":["../../../src/core/sandbox/policy.ts"],"names":[],"mappings":"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","sourcesContent":["import { isInsideSandboxPath as isInside, matchesSandboxPath as matchesPattern } from \"./policy-paths.ts\";\n\nexport { mergeSandboxPolicy } from \"./policy-merge.ts\";\n\nimport type {\n\tBashSpawnPreflightContext,\n\tBashSpawnPreflightDecision,\n\tNetworkAccessRequest,\n\tPathAccessRequest,\n\tResolvedSandboxPath,\n\tSandboxBackendStatus,\n\tSandboxDecision,\n\tSandboxFallbackDecision,\n\tSandboxPathResolver,\n\tSandboxPolicy,\n} from \"./policy-types.ts\";\n\nexport * from \"./policy-types.ts\";\n\nconst SENSITIVE_PATH_PATTERN =\n\t/(?:^|[/\\\\])(?:\\.env(?:\\..*)?|auth\\.json|oauth\\.json|\\.netrc|\\.npmrc|\\.pgpass|credentials|id_rsa|id_dsa|id_ecdsa|id_ed25519|.*(?:secret|token|private[_-]?key|credential).*)$/i;\n\nfunction decision(allowed: boolean, rule: string, reason: string): SandboxDecision {\n\treturn { allowed, rule, reason };\n}\n\nfunction isSensitivePath(value: string): boolean {\n\treturn SENSITIVE_PATH_PATTERN.test(value.replace(/\\\\/g, \"/\"));\n}\n\nfunction matchesAny(patterns: readonly string[], candidate: string): boolean {\n\treturn patterns.some((pattern) => matchesPattern(pattern, candidate));\n}\n\nfunction resolvedDecisionPath(resolved: ResolvedSandboxPath): string | undefined {\n\treturn resolved.realPath ?? resolved.nearestExistingParentRealPath;\n}\n\nfunction rootEscaped(policy: SandboxPolicy, resolved: ResolvedSandboxPath): boolean {\n\tconst candidate = resolvedDecisionPath(resolved);\n\treturn candidate === undefined || !isInside(policy.filesystem.root, candidate);\n}\n\nexport function decidePathAccess(\n\tpolicy: SandboxPolicy,\n\trequest: PathAccessRequest,\n\tresolver: SandboxPathResolver,\n): SandboxDecision {\n\tif (policy.mode === \"off\") {\n\t\treturn decision(true, \"sandbox.off\", \"Sandbox policy is disabled.\");\n\t}\n\n\tif (request.path.includes(\"\\0\")) {\n\t\treturn decision(false, \"path.invalid\", \"Path contains a NUL byte.\");\n\t}\n\n\tif (isSensitivePath(request.path)) {\n\t\treturn decision(false, \"path.secret\", \"Sensitive credential-like paths are denied.\");\n\t}\n\n\tconst resolved = resolver(request.path);\n\tif (resolved.error) {\n\t\treturn decision(false, \"path.resolve_error\", resolved.error);\n\t}\n\tif (rootEscaped(policy, resolved)) {\n\t\treturn decision(false, \"path.root_escape\", \"Resolved path is outside the sandbox root.\");\n\t}\n\tif (resolved.isSymlink && !policy.filesystem.followSymlinks) {\n\t\treturn decision(false, \"path.symlink\", \"Symlink traversal is denied by policy.\");\n\t}\n\n\tconst candidate = resolvedDecisionPath(resolved) ?? request.path;\n\tif (request.kind === \"read\") {\n\t\tif (matchesAny(policy.filesystem.readDeny, candidate) || matchesAny(policy.filesystem.readDeny, request.path)) {\n\t\t\treturn decision(false, \"path.read_deny\", \"Read path matches a deny rule.\");\n\t\t}\n\t\tif (!matchesAny(policy.filesystem.readAllow, candidate)) {\n\t\t\treturn decision(false, \"path.read_not_allowed\", \"Read path is not in an allow rule.\");\n\t\t}\n\t\treturn decision(true, \"path.read_allow\", \"Read path is allowed.\");\n\t}\n\n\tif (matchesAny(policy.filesystem.denyWrite, candidate) || matchesAny(policy.filesystem.denyWrite, request.path)) {\n\t\treturn decision(false, \"path.deny_write\", \"Write path matches an unoverrideable denyWrite rule.\");\n\t}\n\tif (matchesAny(policy.filesystem.writeAllow, candidate) || matchesAny(policy.filesystem.tempWrite, candidate)) {\n\t\treturn decision(true, \"path.write_allow\", \"Write path is allowed.\");\n\t}\n\treturn decision(false, \"path.write_not_allowed\", \"Write path is not in an allow rule.\");\n}\n\nfunction hostFromRequest(request: NetworkAccessRequest): string | undefined {\n\tif (request.host) return request.host.toLowerCase();\n\tif (!request.url) return undefined;\n\ttry {\n\t\treturn new URL(request.url).hostname.toLowerCase();\n\t} catch {\n\t\treturn undefined;\n\t}\n}\n\nfunction hostMatches(patterns: readonly string[], host: string): boolean {\n\treturn patterns.some((pattern) => {\n\t\tconst normalized = pattern.toLowerCase();\n\t\treturn host === normalized || host.endsWith(`.${normalized}`);\n\t});\n}\n\nexport function decideNetworkAccess(policy: SandboxPolicy, request: NetworkAccessRequest): SandboxDecision {\n\tif (policy.mode === \"off\") return decision(true, \"sandbox.off\", \"Sandbox policy is disabled.\");\n\tif (request.browser || request.unixSocketPath) {\n\t\treturn decision(false, \"network.socket_or_browser\", \"Browser and Unix socket access is denied by default.\");\n\t}\n\tif (policy.network.mode === \"none\") {\n\t\treturn decision(false, \"network.none\", \"Network access is disabled by policy.\");\n\t}\n\tif (request.loopback) {\n\t\treturn policy.network.mode === \"loopback\" ||\n\t\t\tpolicy.network.mode === \"domain-allowlist\" ||\n\t\t\tpolicy.network.mode === \"all-explicit\"\n\t\t\t? decision(true, \"network.loopback\", \"Loopback access is allowed.\")\n\t\t\t: decision(false, \"network.loopback_denied\", \"Loopback access is denied.\");\n\t}\n\tconst host = hostFromRequest(request);\n\tif (!host) return decision(false, \"network.unknown_host\", \"Network host could not be resolved from request.\");\n\tif (hostMatches(policy.network.deniedDomains, host)) {\n\t\treturn decision(false, \"network.domain_deny\", \"Host matches a denied domain.\");\n\t}\n\tif (policy.network.mode === \"all-explicit\") {\n\t\treturn decision(true, \"network.explicit_all\", \"Explicit network profile allows outbound host access.\");\n\t}\n\tif (policy.network.mode === \"domain-allowlist\" && hostMatches(policy.network.allowedDomains, host)) {\n\t\treturn decision(true, \"network.domain_allow\", \"Host matches an allowed domain.\");\n\t}\n\treturn decision(false, \"network.domain_not_allowed\", \"Host is not allowed by network policy.\");\n}\n\nexport function decideSandboxFallback(policy: SandboxPolicy, backend: SandboxBackendStatus): SandboxFallbackDecision {\n\tif (policy.mode === \"off\") {\n\t\treturn {\n\t\t\t...decision(true, \"sandbox.off\", \"Sandbox policy is disabled.\"),\n\t\t\tallowShell: true,\n\t\t\tallowExec: true,\n\t\t\tallowReadOnlyTools: true,\n\t\t};\n\t}\n\tif (backend.backendAvailable) {\n\t\treturn {\n\t\t\t...decision(true, \"sandbox.backend_available\", \"Sandbox backend is available.\"),\n\t\t\tallowShell: policy.process.allowShell,\n\t\t\tallowExec: policy.process.allowExec,\n\t\t\tallowReadOnlyTools: true,\n\t\t};\n\t}\n\tif (policy.mode === \"audit\") {\n\t\treturn {\n\t\t\t...decision(true, \"sandbox.audit_fallback\", \"Audit mode permits execution without backend.\"),\n\t\t\tallowShell: true,\n\t\t\tallowExec: true,\n\t\t\tallowReadOnlyTools: true,\n\t\t};\n\t}\n\tconst backendDetail = backend.unavailableReason ? ` ${backend.unavailableReason}` : \"\";\n\treturn {\n\t\t...decision(\n\t\t\tfalse,\n\t\t\t\"sandbox.backend_missing\",\n\t\t\t`Enforce mode blocks shell and exec when no backend is available.${backendDetail}`,\n\t\t),\n\t\tallowShell: false,\n\t\tallowExec: false,\n\t\tallowReadOnlyTools: true,\n\t};\n}\n\n/**\n * Final pure preflight for a local bash spawn. Combines the backend-availability\n * fallback (deny shell when an OS sandbox backend is missing under enforce mode)\n * with a working-directory containment check (deny when cwd resolves outside the\n * sandbox root). This helper does not itself wrap the process in an OS sandbox; it\n * only decides whether the spawn may proceed.\n */\nexport function preflightBashSpawn(\n\tpolicy: SandboxPolicy,\n\tbackend: SandboxBackendStatus,\n\tcontext: BashSpawnPreflightContext,\n\tresolver?: SandboxPathResolver,\n): BashSpawnPreflightDecision {\n\tif (policy.mode === \"off\") {\n\t\treturn { ...decision(true, \"sandbox.off\", \"Sandbox policy is disabled.\"), allowShell: true };\n\t}\n\tif (!policy.process.allowShell) {\n\t\treturn {\n\t\t\t...decision(false, \"process.shell_denied\", \"Shell execution is disabled by policy.\"),\n\t\t\tallowShell: false,\n\t\t};\n\t}\n\tconst fallback = decideSandboxFallback(policy, backend);\n\tif (!fallback.allowShell) {\n\t\treturn { ...decision(false, fallback.rule, fallback.reason), allowShell: false };\n\t}\n\tif (context.cwd.includes(\"\\0\")) {\n\t\treturn { ...decision(false, \"cwd.invalid\", \"Working directory contains a NUL byte.\"), allowShell: false };\n\t}\n\tconst resolved = resolver?.(context.cwd);\n\tif (resolved?.error) {\n\t\treturn { ...decision(false, \"cwd.resolve_error\", resolved.error), allowShell: false };\n\t}\n\tif (resolved?.isSymlink) {\n\t\treturn {\n\t\t\t...decision(false, \"cwd.symlink\", \"Working directory is a symlink and traversal is denied.\"),\n\t\t\tallowShell: false,\n\t\t};\n\t}\n\tconst candidate = resolved ? (resolvedDecisionPath(resolved) ?? context.cwd) : context.cwd;\n\tif (!isInside(policy.filesystem.root, candidate)) {\n\t\treturn {\n\t\t\t...decision(false, \"cwd.root_escape\", \"Working directory is outside the sandbox root.\"),\n\t\t\tallowShell: false,\n\t\t};\n\t}\n\treturn {\n\t\t...decision(true, \"sandbox.shell_preflight_ok\", \"Bash spawn is permitted by sandbox policy.\"),\n\t\tallowShell: true,\n\t};\n}\n"]}
@@ -0,0 +1,14 @@
1
+ import { type ModelContract, type StreamFn } from "omk-agent-core";
2
+ import { type SimpleStreamOptions } from "omk-ai";
3
+ import type { ModelRegistry } from "./model-registry.ts";
4
+ import type { SettingsManager } from "./settings-manager.ts";
5
+ interface SdkProviderRuntime {
6
+ readonly modelRegistry: ModelRegistry;
7
+ readonly settingsManager: SettingsManager;
8
+ readonly modelContract?: ModelContract;
9
+ readonly onRateLimit?: (apiKey: string | undefined, ...args: Parameters<NonNullable<SimpleStreamOptions["onRateLimit"]>>) => void;
10
+ }
11
+ /** Shared by the main agent and first-party summary calls using agent.streamFn. */
12
+ export declare function createSdkProviderStream(runtime: SdkProviderRuntime): StreamFn;
13
+ export {};
14
+ //# sourceMappingURL=sdk-provider-stream.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"sdk-provider-stream.d.ts","sourceRoot":"","sources":["../../src/core/sdk-provider-stream.ts"],"names":[],"mappings":"AAAA,OAAO,EAEN,KAAK,aAAa,EAElB,KAAK,QAAQ,EAEb,MAAM,gBAAgB,CAAC;AACxB,OAAO,EAAE,KAAK,mBAAmB,EAAgB,MAAM,QAAQ,CAAC;AAChE,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,qBAAqB,CAAC;AAEzD,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,uBAAuB,CAAC;AAE7D,UAAU,kBAAkB;IAC3B,QAAQ,CAAC,aAAa,EAAE,aAAa,CAAC;IACtC,QAAQ,CAAC,eAAe,EAAE,eAAe,CAAC;IAC1C,QAAQ,CAAC,aAAa,CAAC,EAAE,aAAa,CAAC;IACvC,QAAQ,CAAC,WAAW,CAAC,EAAE,CACtB,MAAM,EAAE,MAAM,GAAG,SAAS,EAC1B,GAAG,IAAI,EAAE,UAAU,CAAC,WAAW,CAAC,mBAAmB,CAAC,aAAa,CAAC,CAAC,CAAC,KAChE,IAAI,CAAC;CACV;AAED,mFAAmF;AACnF,wBAAgB,uBAAuB,CAAC,OAAO,EAAE,kBAAkB,GAAG,QAAQ,CAsC7E","sourcesContent":["import {\n\tapplyModelContract,\n\ttype ModelContract,\n\tprojectToolImagesForModel,\n\ttype StreamFn,\n\tsnapshotModelContract,\n} from \"omk-agent-core\";\nimport { type SimpleStreamOptions, streamSimple } from \"omk-ai\";\nimport type { ModelRegistry } from \"./model-registry.ts\";\nimport { mergeProviderAttributionHeaders } from \"./provider-attribution.ts\";\nimport type { SettingsManager } from \"./settings-manager.ts\";\n\ninterface SdkProviderRuntime {\n\treadonly modelRegistry: ModelRegistry;\n\treadonly settingsManager: SettingsManager;\n\treadonly modelContract?: ModelContract;\n\treadonly onRateLimit?: (\n\t\tapiKey: string | undefined,\n\t\t...args: Parameters<NonNullable<SimpleStreamOptions[\"onRateLimit\"]>>\n\t) => void;\n}\n\n/** Shared by the main agent and first-party summary calls using agent.streamFn. */\nexport function createSdkProviderStream(runtime: SdkProviderRuntime): StreamFn {\n\tconst { modelRegistry, settingsManager } = runtime;\n\tconst contract = runtime.modelContract === undefined ? undefined : snapshotModelContract(runtime.modelContract);\n\treturn async (model, context, options) => {\n\t\tconst requestModel = contract ? structuredClone(model) : model;\n\t\tconst requestOptions = contract ? applyModelContract(contract, requestModel, options ?? {}) : options;\n\t\tconst requestContext = contract ? projectToolImagesForModel(context, requestModel).context : context;\n\t\trequestOptions?.signal?.throwIfAborted();\n\t\tconst auth = await modelRegistry.getApiKeyAndHeaders(requestModel);\n\t\tif (!auth.ok) throw new Error(auth.error);\n\t\trequestOptions?.signal?.throwIfAborted();\n\t\tconst providerRetrySettings = settingsManager.getProviderRetrySettings();\n\t\tconst httpIdleTimeoutMs = settingsManager.getHttpIdleTimeoutMs();\n\t\t// SDK timeout=0 means immediate failure, not unlimited waiting.\n\t\tconst effectiveTimeoutMs = httpIdleTimeoutMs === 0 ? 2147483647 : httpIdleTimeoutMs;\n\t\tconst timeoutMs = requestOptions?.timeoutMs ?? providerRetrySettings.timeoutMs ?? effectiveTimeoutMs;\n\t\tconst websocketConnectTimeoutMs =\n\t\t\trequestOptions?.websocketConnectTimeoutMs ?? settingsManager.getWebSocketConnectTimeoutMs();\n\t\treturn streamSimple(requestModel, requestContext, {\n\t\t\t...requestOptions,\n\t\t\tapiKey: auth.apiKey,\n\t\t\ttimeoutMs,\n\t\t\twebsocketConnectTimeoutMs,\n\t\t\tmaxRetries: requestOptions?.maxRetries ?? providerRetrySettings.maxRetries,\n\t\t\tmaxRetryDelayMs: requestOptions?.maxRetryDelayMs ?? providerRetrySettings.maxRetryDelayMs,\n\t\t\tonRateLimit: async (snapshot, responseModel) => {\n\t\t\t\truntime.onRateLimit?.(auth.apiKey, snapshot, responseModel);\n\t\t\t\tawait requestOptions?.onRateLimit?.(snapshot, responseModel);\n\t\t\t},\n\t\t\theaders: mergeProviderAttributionHeaders(\n\t\t\t\trequestModel,\n\t\t\t\tsettingsManager,\n\t\t\t\trequestOptions?.sessionId,\n\t\t\t\tauth.headers,\n\t\t\t\trequestOptions?.headers,\n\t\t\t),\n\t\t});\n\t};\n}\n"]}
@@ -0,0 +1,38 @@
1
+ import { applyModelContract, projectToolImagesForModel, snapshotModelContract, } from "omk-agent-core";
2
+ import { streamSimple } from "omk-ai";
3
+ import { mergeProviderAttributionHeaders } from "./provider-attribution.js";
4
+ /** Shared by the main agent and first-party summary calls using agent.streamFn. */
5
+ export function createSdkProviderStream(runtime) {
6
+ const { modelRegistry, settingsManager } = runtime;
7
+ const contract = runtime.modelContract === undefined ? undefined : snapshotModelContract(runtime.modelContract);
8
+ return async (model, context, options) => {
9
+ const requestModel = contract ? structuredClone(model) : model;
10
+ const requestOptions = contract ? applyModelContract(contract, requestModel, options ?? {}) : options;
11
+ const requestContext = contract ? projectToolImagesForModel(context, requestModel).context : context;
12
+ requestOptions?.signal?.throwIfAborted();
13
+ const auth = await modelRegistry.getApiKeyAndHeaders(requestModel);
14
+ if (!auth.ok)
15
+ throw new Error(auth.error);
16
+ requestOptions?.signal?.throwIfAborted();
17
+ const providerRetrySettings = settingsManager.getProviderRetrySettings();
18
+ const httpIdleTimeoutMs = settingsManager.getHttpIdleTimeoutMs();
19
+ // SDK timeout=0 means immediate failure, not unlimited waiting.
20
+ const effectiveTimeoutMs = httpIdleTimeoutMs === 0 ? 2147483647 : httpIdleTimeoutMs;
21
+ const timeoutMs = requestOptions?.timeoutMs ?? providerRetrySettings.timeoutMs ?? effectiveTimeoutMs;
22
+ const websocketConnectTimeoutMs = requestOptions?.websocketConnectTimeoutMs ?? settingsManager.getWebSocketConnectTimeoutMs();
23
+ return streamSimple(requestModel, requestContext, {
24
+ ...requestOptions,
25
+ apiKey: auth.apiKey,
26
+ timeoutMs,
27
+ websocketConnectTimeoutMs,
28
+ maxRetries: requestOptions?.maxRetries ?? providerRetrySettings.maxRetries,
29
+ maxRetryDelayMs: requestOptions?.maxRetryDelayMs ?? providerRetrySettings.maxRetryDelayMs,
30
+ onRateLimit: async (snapshot, responseModel) => {
31
+ runtime.onRateLimit?.(auth.apiKey, snapshot, responseModel);
32
+ await requestOptions?.onRateLimit?.(snapshot, responseModel);
33
+ },
34
+ headers: mergeProviderAttributionHeaders(requestModel, settingsManager, requestOptions?.sessionId, auth.headers, requestOptions?.headers),
35
+ });
36
+ };
37
+ }
38
+ //# sourceMappingURL=sdk-provider-stream.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"sdk-provider-stream.js","sourceRoot":"","sources":["../../src/core/sdk-provider-stream.ts"],"names":[],"mappings":"AAAA,OAAO,EACN,kBAAkB,EAElB,yBAAyB,EAEzB,qBAAqB,GACrB,MAAM,gBAAgB,CAAC;AACxB,OAAO,EAA4B,YAAY,EAAE,MAAM,QAAQ,CAAC;AAEhE,OAAO,EAAE,+BAA+B,EAAE,MAAM,2BAA2B,CAAC;AAa5E,mFAAmF;AACnF,MAAM,UAAU,uBAAuB,CAAC,OAA2B,EAAY;IAC9E,MAAM,EAAE,aAAa,EAAE,eAAe,EAAE,GAAG,OAAO,CAAC;IACnD,MAAM,QAAQ,GAAG,OAAO,CAAC,aAAa,KAAK,SAAS,CAAC,CAAC,CAAC,SAAS,CAAC,CAAC,CAAC,qBAAqB,CAAC,OAAO,CAAC,aAAa,CAAC,CAAC;IAChH,OAAO,KAAK,EAAE,KAAK,EAAE,OAAO,EAAE,OAAO,EAAE,EAAE,CAAC;QACzC,MAAM,YAAY,GAAG,QAAQ,CAAC,CAAC,CAAC,eAAe,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,KAAK,CAAC;QAC/D,MAAM,cAAc,GAAG,QAAQ,CAAC,CAAC,CAAC,kBAAkB,CAAC,QAAQ,EAAE,YAAY,EAAE,OAAO,IAAI,EAAE,CAAC,CAAC,CAAC,CAAC,OAAO,CAAC;QACtG,MAAM,cAAc,GAAG,QAAQ,CAAC,CAAC,CAAC,yBAAyB,CAAC,OAAO,EAAE,YAAY,CAAC,CAAC,OAAO,CAAC,CAAC,CAAC,OAAO,CAAC;QACrG,cAAc,EAAE,MAAM,EAAE,cAAc,EAAE,CAAC;QACzC,MAAM,IAAI,GAAG,MAAM,aAAa,CAAC,mBAAmB,CAAC,YAAY,CAAC,CAAC;QACnE,IAAI,CAAC,IAAI,CAAC,EAAE;YAAE,MAAM,IAAI,KAAK,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC;QAC1C,cAAc,EAAE,MAAM,EAAE,cAAc,EAAE,CAAC;QACzC,MAAM,qBAAqB,GAAG,eAAe,CAAC,wBAAwB,EAAE,CAAC;QACzE,MAAM,iBAAiB,GAAG,eAAe,CAAC,oBAAoB,EAAE,CAAC;QACjE,gEAAgE;QAChE,MAAM,kBAAkB,GAAG,iBAAiB,KAAK,CAAC,CAAC,CAAC,CAAC,UAAU,CAAC,CAAC,CAAC,iBAAiB,CAAC;QACpF,MAAM,SAAS,GAAG,cAAc,EAAE,SAAS,IAAI,qBAAqB,CAAC,SAAS,IAAI,kBAAkB,CAAC;QACrG,MAAM,yBAAyB,GAC9B,cAAc,EAAE,yBAAyB,IAAI,eAAe,CAAC,4BAA4B,EAAE,CAAC;QAC7F,OAAO,YAAY,CAAC,YAAY,EAAE,cAAc,EAAE;YACjD,GAAG,cAAc;YACjB,MAAM,EAAE,IAAI,CAAC,MAAM;YACnB,SAAS;YACT,yBAAyB;YACzB,UAAU,EAAE,cAAc,EAAE,UAAU,IAAI,qBAAqB,CAAC,UAAU;YAC1E,eAAe,EAAE,cAAc,EAAE,eAAe,IAAI,qBAAqB,CAAC,eAAe;YACzF,WAAW,EAAE,KAAK,EAAE,QAAQ,EAAE,aAAa,EAAE,EAAE,CAAC;gBAC/C,OAAO,CAAC,WAAW,EAAE,CAAC,IAAI,CAAC,MAAM,EAAE,QAAQ,EAAE,aAAa,CAAC,CAAC;gBAC5D,MAAM,cAAc,EAAE,WAAW,EAAE,CAAC,QAAQ,EAAE,aAAa,CAAC,CAAC;YAAA,CAC7D;YACD,OAAO,EAAE,+BAA+B,CACvC,YAAY,EACZ,eAAe,EACf,cAAc,EAAE,SAAS,EACzB,IAAI,CAAC,OAAO,EACZ,cAAc,EAAE,OAAO,CACvB;SACD,CAAC,CAAC;IAAA,CACH,CAAC;AAAA,CACF","sourcesContent":["import {\n\tapplyModelContract,\n\ttype ModelContract,\n\tprojectToolImagesForModel,\n\ttype StreamFn,\n\tsnapshotModelContract,\n} from \"omk-agent-core\";\nimport { type SimpleStreamOptions, streamSimple } from \"omk-ai\";\nimport type { ModelRegistry } from \"./model-registry.ts\";\nimport { mergeProviderAttributionHeaders } from \"./provider-attribution.ts\";\nimport type { SettingsManager } from \"./settings-manager.ts\";\n\ninterface SdkProviderRuntime {\n\treadonly modelRegistry: ModelRegistry;\n\treadonly settingsManager: SettingsManager;\n\treadonly modelContract?: ModelContract;\n\treadonly onRateLimit?: (\n\t\tapiKey: string | undefined,\n\t\t...args: Parameters<NonNullable<SimpleStreamOptions[\"onRateLimit\"]>>\n\t) => void;\n}\n\n/** Shared by the main agent and first-party summary calls using agent.streamFn. */\nexport function createSdkProviderStream(runtime: SdkProviderRuntime): StreamFn {\n\tconst { modelRegistry, settingsManager } = runtime;\n\tconst contract = runtime.modelContract === undefined ? undefined : snapshotModelContract(runtime.modelContract);\n\treturn async (model, context, options) => {\n\t\tconst requestModel = contract ? structuredClone(model) : model;\n\t\tconst requestOptions = contract ? applyModelContract(contract, requestModel, options ?? {}) : options;\n\t\tconst requestContext = contract ? projectToolImagesForModel(context, requestModel).context : context;\n\t\trequestOptions?.signal?.throwIfAborted();\n\t\tconst auth = await modelRegistry.getApiKeyAndHeaders(requestModel);\n\t\tif (!auth.ok) throw new Error(auth.error);\n\t\trequestOptions?.signal?.throwIfAborted();\n\t\tconst providerRetrySettings = settingsManager.getProviderRetrySettings();\n\t\tconst httpIdleTimeoutMs = settingsManager.getHttpIdleTimeoutMs();\n\t\t// SDK timeout=0 means immediate failure, not unlimited waiting.\n\t\tconst effectiveTimeoutMs = httpIdleTimeoutMs === 0 ? 2147483647 : httpIdleTimeoutMs;\n\t\tconst timeoutMs = requestOptions?.timeoutMs ?? providerRetrySettings.timeoutMs ?? effectiveTimeoutMs;\n\t\tconst websocketConnectTimeoutMs =\n\t\t\trequestOptions?.websocketConnectTimeoutMs ?? settingsManager.getWebSocketConnectTimeoutMs();\n\t\treturn streamSimple(requestModel, requestContext, {\n\t\t\t...requestOptions,\n\t\t\tapiKey: auth.apiKey,\n\t\t\ttimeoutMs,\n\t\t\twebsocketConnectTimeoutMs,\n\t\t\tmaxRetries: requestOptions?.maxRetries ?? providerRetrySettings.maxRetries,\n\t\t\tmaxRetryDelayMs: requestOptions?.maxRetryDelayMs ?? providerRetrySettings.maxRetryDelayMs,\n\t\t\tonRateLimit: async (snapshot, responseModel) => {\n\t\t\t\truntime.onRateLimit?.(auth.apiKey, snapshot, responseModel);\n\t\t\t\tawait requestOptions?.onRateLimit?.(snapshot, responseModel);\n\t\t\t},\n\t\t\theaders: mergeProviderAttributionHeaders(\n\t\t\t\trequestModel,\n\t\t\t\tsettingsManager,\n\t\t\t\trequestOptions?.sessionId,\n\t\t\t\tauth.headers,\n\t\t\t\trequestOptions?.headers,\n\t\t\t),\n\t\t});\n\t};\n}\n"]}
@@ -1,4 +1,4 @@
1
- import { type ThinkingLevel } from "omk-agent-core";
1
+ import { type ModelContract, type ThinkingLevel } from "omk-agent-core";
2
2
  import { type Model } from "omk-ai";
3
3
  import { ReplayLedgerManager } from "../guardrails/evidence-system.ts";
4
4
  import { AgentSession } from "./agent-session.ts";
@@ -22,6 +22,10 @@ export interface CreateAgentSessionOptions {
22
22
  modelRegistry?: ModelRegistry;
23
23
  /** Model to use. Default: from settings, else first available */
24
24
  model?: Model<any>;
25
+ /** Opt-in logical dispatch policy shared by the main loop and first-party summary stream. */
26
+ modelContract?: ModelContract;
27
+ /** Optional main-loop output limit; a contract supplies the default cap when omitted. */
28
+ maxTokens?: number;
25
29
  /** Thinking level. Default: from settings, else 'medium' (clamped to model capabilities) */
26
30
  thinkingLevel?: ThinkingLevel;
27
31
  /** Models available for cycling (Ctrl+P in interactive mode) */