@theoremjs/agents 0.3.0 → 0.3.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (568) hide show
  1. package/README.md +276 -995
  2. package/esm/mod.d.ts +33 -19
  3. package/esm/mod.js +18 -11
  4. package/esm/src/cli/commands/bench.js +36 -14
  5. package/esm/src/cli/commands/detect-compile.d.ts +17 -0
  6. package/esm/src/cli/commands/detect-compile.js +22 -0
  7. package/esm/src/cli/commands/eval.d.ts +3 -3
  8. package/esm/src/cli/commands/fuzz-canary.js +55 -16
  9. package/esm/src/cli/commands/profile.js +4 -4
  10. package/esm/src/cli/commands/run.d.ts +2 -2
  11. package/esm/src/cli/commands/run.js +1 -1
  12. package/esm/src/cli/commands/test.d.ts +4 -3
  13. package/esm/src/cli/commands/test.js +2 -2
  14. package/esm/src/cli/index.js +9 -9
  15. package/esm/src/cli/matrix/fixtures.js +25 -30
  16. package/esm/src/evals/attachments.d.ts +1 -0
  17. package/esm/src/evals/attachments.js +4 -2
  18. package/esm/src/evals/breakdown.d.ts +2 -0
  19. package/esm/src/evals/breakdown.js +1 -0
  20. package/esm/src/evals/graders/answer.d.ts +3 -0
  21. package/esm/src/evals/graders/answer.js +1 -0
  22. package/esm/src/evals/graders/code.d.ts +7 -31
  23. package/esm/src/evals/graders/code.js +4 -25
  24. package/esm/src/evals/graders/judge.d.ts +4 -0
  25. package/esm/src/evals/graders/judge.js +7 -5
  26. package/esm/src/evals/graders/latency.d.ts +1 -0
  27. package/esm/src/evals/graders/latency.js +3 -2
  28. package/esm/src/evals/graders/live.d.ts +3 -0
  29. package/esm/src/evals/graders/live.js +2 -0
  30. package/esm/src/evals/graders/media.js +1 -2
  31. package/esm/src/evals/graders/shared.js +1 -1
  32. package/esm/src/evals/graders/transcript.d.ts +2 -0
  33. package/esm/src/evals/graders/transcript.js +5 -3
  34. package/esm/src/evals/mod.d.ts +1 -9
  35. package/esm/src/evals/mod.js +1 -9
  36. package/esm/src/evals/record.d.ts +6 -0
  37. package/esm/src/evals/record.js +4 -2
  38. package/esm/src/evals/rubrics/mod.d.ts +1 -1
  39. package/esm/src/evals/rubrics/mod.js +1 -1
  40. package/esm/src/evals/rubrics/mustache.js +1 -1
  41. package/esm/src/evals/rubrics/types.js +1 -1
  42. package/esm/src/evals/run.d.ts +9 -52
  43. package/esm/src/evals/run.js +12 -46
  44. package/esm/src/evals/suite.d.ts +12 -3
  45. package/esm/src/evals/suite.js +9 -4
  46. package/esm/src/evals/summary.d.ts +3 -0
  47. package/esm/src/evals/summary.js +1 -0
  48. package/esm/src/evals/trial.d.ts +3 -16
  49. package/esm/src/evals/trial.js +7 -30
  50. package/esm/src/evals/types.d.ts +30 -121
  51. package/esm/src/evals/types.js +3 -16
  52. package/esm/src/evals/verdict.d.ts +5 -0
  53. package/esm/src/evals/verdict.js +4 -1
  54. package/esm/src/guardrails/boundaries.d.ts +41 -0
  55. package/esm/src/guardrails/boundaries.js +103 -0
  56. package/esm/src/guardrails/canary-gate.d.ts +1 -0
  57. package/esm/src/guardrails/canary.d.ts +49 -15
  58. package/esm/src/guardrails/canary.js +103 -30
  59. package/esm/src/guardrails/compile-egress.d.ts +6 -5
  60. package/esm/src/guardrails/compile-egress.js +6 -5
  61. package/esm/src/guardrails/corpus/canary-egress-attacks.d.ts +3 -1
  62. package/esm/src/guardrails/corpus/canary-egress-attacks.js +4 -2
  63. package/esm/src/guardrails/corpus/fuzz-inbound.js +14 -17
  64. package/esm/src/guardrails/corpus/inbound-payloads.d.ts +2 -0
  65. package/esm/src/guardrails/corpus/inbound-payloads.js +4 -2
  66. package/esm/src/guardrails/corpus/live-attacks.d.ts +2 -0
  67. package/esm/src/guardrails/corpus/live-attacks.js +6 -1
  68. package/esm/src/guardrails/corpus/mod.d.ts +1 -1
  69. package/esm/src/guardrails/corpus/secrets.d.ts +3 -3
  70. package/esm/src/guardrails/corpus/secrets.js +2 -2
  71. package/esm/src/guardrails/corpus/strings.d.ts +1 -1
  72. package/esm/src/guardrails/corpus/strings.js +1 -1
  73. package/esm/src/guardrails/corpus/types.d.ts +5 -1
  74. package/esm/src/guardrails/credential-rules.d.ts +36 -0
  75. package/esm/src/guardrails/credential-rules.js +3001 -0
  76. package/esm/src/guardrails/credential-scan.d.ts +45 -0
  77. package/esm/src/guardrails/credential-scan.js +172 -0
  78. package/esm/src/guardrails/destinations.d.ts +45 -0
  79. package/esm/src/guardrails/destinations.js +234 -0
  80. package/esm/src/guardrails/detect-at.d.ts +107 -0
  81. package/esm/src/guardrails/detect-at.js +434 -0
  82. package/esm/src/guardrails/detect-reply.d.ts +61 -0
  83. package/esm/src/guardrails/detect-reply.js +95 -0
  84. package/esm/src/guardrails/detect-stream.d.ts +33 -0
  85. package/esm/src/guardrails/detect-stream.js +77 -0
  86. package/esm/src/guardrails/detectors.d.ts +216 -0
  87. package/esm/src/guardrails/detectors.js +503 -0
  88. package/esm/src/guardrails/egress-automata.d.ts +4 -6
  89. package/esm/src/guardrails/egress-automata.js +24095 -4572
  90. package/esm/src/guardrails/egress-compiler.d.ts +38 -16
  91. package/esm/src/guardrails/egress-compiler.js +254 -60
  92. package/esm/src/guardrails/egress-patterns.d.ts +4 -2
  93. package/esm/src/guardrails/egress-patterns.js +6 -2
  94. package/esm/src/guardrails/egress-stream.d.ts +54 -36
  95. package/esm/src/guardrails/egress-stream.js +253 -124
  96. package/esm/src/guardrails/egress-urls.d.ts +6 -3
  97. package/esm/src/guardrails/egress-urls.js +14 -22
  98. package/esm/src/guardrails/egress.d.ts +26 -86
  99. package/esm/src/guardrails/egress.js +59 -309
  100. package/esm/src/guardrails/error.d.ts +13 -8
  101. package/esm/src/guardrails/error.js +23 -18
  102. package/esm/src/guardrails/event-schemas.d.ts +46 -3
  103. package/esm/src/guardrails/event-schemas.js +12 -5
  104. package/esm/src/guardrails/events.d.ts +5 -1
  105. package/esm/src/guardrails/events.js +4 -1
  106. package/esm/src/guardrails/hints.d.ts +14 -0
  107. package/esm/src/guardrails/hints.js +57 -0
  108. package/esm/src/guardrails/hits.d.ts +7 -1
  109. package/esm/src/guardrails/hits.js +12 -1
  110. package/esm/src/guardrails/host-patterns.d.ts +85 -0
  111. package/esm/src/guardrails/host-patterns.js +173 -0
  112. package/esm/src/guardrails/injection-patterns.d.ts +6 -1
  113. package/esm/src/guardrails/injection-patterns.js +33 -1
  114. package/esm/src/guardrails/injection-reversed.d.ts +9 -0
  115. package/esm/src/guardrails/injection-reversed.js +49 -0
  116. package/esm/src/guardrails/injection.d.ts +17 -1
  117. package/esm/src/guardrails/injection.js +259 -36
  118. package/esm/src/guardrails/labels.d.ts +40 -0
  119. package/esm/src/guardrails/labels.js +874 -0
  120. package/esm/src/guardrails/live-outbound-gate.d.ts +9 -8
  121. package/esm/src/guardrails/live-outbound-gate.js +100 -107
  122. package/esm/src/guardrails/mod.d.ts +29 -21
  123. package/esm/src/guardrails/mod.js +18 -13
  124. package/esm/src/guardrails/network.d.ts +4 -0
  125. package/esm/src/guardrails/network.js +21 -19
  126. package/esm/src/guardrails/normalize.d.ts +15 -1
  127. package/esm/src/guardrails/normalize.js +34 -1
  128. package/esm/src/guardrails/policy.d.ts +2 -17
  129. package/esm/src/guardrails/policy.js +12 -41
  130. package/esm/src/guardrails/progressive-yield.d.ts +65 -24
  131. package/esm/src/guardrails/progressive-yield.js +191 -147
  132. package/esm/src/guardrails/prompt-echo.d.ts +4 -2
  133. package/esm/src/guardrails/prompt-echo.js +87 -6
  134. package/esm/src/guardrails/quota.d.ts +1 -0
  135. package/esm/src/guardrails/quota.js +1 -1
  136. package/esm/src/guardrails/rules.d.ts +20 -29
  137. package/esm/src/guardrails/rules.js +23 -30
  138. package/esm/src/guardrails/sanitize.d.ts +32 -15
  139. package/esm/src/guardrails/sanitize.js +100 -124
  140. package/esm/src/guardrails/sensitive-groups.d.ts +21 -0
  141. package/esm/src/guardrails/sensitive-groups.js +12 -0
  142. package/esm/src/guardrails/sensitive.d.ts +16 -23
  143. package/esm/src/guardrails/sensitive.js +168 -47
  144. package/esm/src/guardrails/serialize.d.ts +1 -0
  145. package/esm/src/guardrails/testing.d.ts +4 -2
  146. package/esm/src/guardrails/testing.js +4 -2
  147. package/esm/src/guardrails/theorem-error.d.ts +4 -1
  148. package/esm/src/guardrails/theorem-error.js +3 -2
  149. package/esm/src/guardrails/thought-guard.d.ts +34 -13
  150. package/esm/src/guardrails/thought-guard.js +264 -64
  151. package/esm/src/guardrails/tool-directives.d.ts +29 -10
  152. package/esm/src/guardrails/tool-directives.js +133 -47
  153. package/esm/src/guardrails/tool-leak.d.ts +26 -0
  154. package/esm/src/guardrails/tool-leak.js +45 -0
  155. package/esm/src/guardrails/tool-result.d.ts +45 -14
  156. package/esm/src/guardrails/tool-result.js +94 -70
  157. package/esm/src/guardrails/types.d.ts +79 -71
  158. package/esm/src/guardrails/types.js +11 -7
  159. package/esm/src/host/client-turn.d.ts +29 -2
  160. package/esm/src/host/client-turn.js +46 -4
  161. package/esm/src/host/mint-trace.d.ts +1 -0
  162. package/esm/src/host/mint-trace.js +3 -2
  163. package/esm/src/host/mod.d.ts +2 -2
  164. package/esm/src/host/mod.js +1 -1
  165. package/esm/src/host/readStreamingJsonStringField.js +2 -43
  166. package/esm/src/host/reply.d.ts +6 -0
  167. package/esm/src/host/reply.js +7 -1
  168. package/esm/src/interface/blocks.d.ts +3 -0
  169. package/esm/src/interface/blocks.js +84 -14
  170. package/esm/src/interface/composer-actions.d.ts +4 -0
  171. package/esm/src/interface/composer-actions.js +5 -3
  172. package/esm/src/interface/draft.d.ts +6 -0
  173. package/esm/src/interface/draft.js +22 -11
  174. package/esm/src/interface/from-profile.d.ts +13 -1
  175. package/esm/src/interface/from-profile.js +66 -31
  176. package/esm/src/interface/history.d.ts +9 -3
  177. package/esm/src/interface/history.js +33 -24
  178. package/esm/src/interface/inputs.d.ts +1 -0
  179. package/esm/src/interface/inputs.js +3 -0
  180. package/esm/src/interface/mod.d.ts +4 -2
  181. package/esm/src/interface/mod.js +3 -2
  182. package/esm/src/interface/models.d.ts +7 -0
  183. package/esm/src/interface/models.js +5 -0
  184. package/esm/src/interface/pending.d.ts +9 -0
  185. package/esm/src/interface/pending.js +9 -3
  186. package/esm/src/interface/profile-interface.js +54 -40
  187. package/esm/src/interface/session.d.ts +12 -5
  188. package/esm/src/interface/session.js +17 -10
  189. package/esm/src/interface/stop.d.ts +13 -0
  190. package/esm/src/interface/stop.js +28 -0
  191. package/esm/src/interface/tool-calls.d.ts +14 -2
  192. package/esm/src/interface/tool-calls.js +64 -10
  193. package/esm/src/interface/tool-invoke.d.ts +2 -0
  194. package/esm/src/interface/tool-invoke.js +3 -1
  195. package/esm/src/interface/tool-media.d.ts +2 -0
  196. package/esm/src/interface/tool-media.js +2 -1
  197. package/esm/src/interface/types.d.ts +105 -40
  198. package/esm/src/interface/types.js +1 -0
  199. package/esm/src/kernel/api-catalog.d.ts +85 -0
  200. package/esm/src/kernel/api-catalog.js +229 -0
  201. package/esm/src/kernel/auth/crypto.d.ts +7 -2
  202. package/esm/src/kernel/auth/crypto.js +12 -10
  203. package/esm/src/kernel/auth/oauth.d.ts +2 -1
  204. package/esm/src/kernel/auth/oauth.js +23 -22
  205. package/esm/src/kernel/auth/typed-secret.js +2 -2
  206. package/esm/src/kernel/auth/types.d.ts +13 -0
  207. package/esm/src/kernel/checkpoint.d.ts +43 -0
  208. package/esm/src/kernel/checkpoint.js +58 -0
  209. package/esm/src/kernel/default-scope.d.ts +43 -5
  210. package/esm/src/kernel/default-scope.js +54 -5
  211. package/esm/src/kernel/engine/call-trace.d.ts +19 -0
  212. package/esm/src/kernel/engine/call-trace.js +29 -0
  213. package/esm/src/kernel/engine/compaction.d.ts +6 -5
  214. package/esm/src/kernel/engine/compaction.js +12 -11
  215. package/esm/src/kernel/engine/decision.d.ts +10 -8
  216. package/esm/src/kernel/engine/decision.js +173 -146
  217. package/esm/src/kernel/engine/embedding.d.ts +8 -0
  218. package/esm/src/kernel/engine/embedding.js +118 -0
  219. package/esm/src/kernel/engine/live-inbound.d.ts +14 -4
  220. package/esm/src/kernel/engine/live-inbound.js +36 -11
  221. package/esm/src/kernel/engine/live-ingress.d.ts +6 -0
  222. package/esm/src/kernel/engine/live-ingress.js +6 -1
  223. package/esm/src/kernel/engine/repair.js +12 -12
  224. package/esm/src/kernel/engine/runner/gates.d.ts +2 -2
  225. package/esm/src/kernel/engine/runner/gates.js +287 -101
  226. package/esm/src/kernel/engine/runner/mod.d.ts +19 -5
  227. package/esm/src/kernel/engine/runner/mod.js +107 -56
  228. package/esm/src/kernel/engine/runner/nested.d.ts +32 -0
  229. package/esm/src/kernel/engine/runner/nested.js +134 -0
  230. package/esm/src/kernel/engine/runner/schema-validation.d.ts +24 -3
  231. package/esm/src/kernel/engine/runner/schema-validation.js +78 -4
  232. package/esm/src/kernel/engine/runner/stages.d.ts +1 -1
  233. package/esm/src/kernel/engine/runner/stages.js +1 -8
  234. package/esm/src/kernel/engine/runner/state.d.ts +33 -12
  235. package/esm/src/kernel/engine/runner/state.js +11 -1
  236. package/esm/src/kernel/engine/runner/step-order.d.ts +27 -0
  237. package/esm/src/kernel/engine/runner/step-order.js +165 -0
  238. package/esm/src/kernel/engine/runner/steps.d.ts +2 -2
  239. package/esm/src/kernel/engine/runner/steps.js +328 -169
  240. package/esm/src/kernel/engine/runner/stream.d.ts +42 -11
  241. package/esm/src/kernel/engine/runner/stream.js +197 -46
  242. package/esm/src/kernel/engine/runner/usage.d.ts +5 -5
  243. package/esm/src/kernel/engine/runner/usage.js +12 -14
  244. package/esm/src/kernel/engine/session/mod.d.ts +8 -6
  245. package/esm/src/kernel/engine/session/mod.js +360 -129
  246. package/esm/src/kernel/engine/session/session-trace.d.ts +10 -10
  247. package/esm/src/kernel/engine/session/session-trace.js +41 -30
  248. package/esm/src/kernel/engine/token-estimate.d.ts +10 -64
  249. package/esm/src/kernel/engine/token-estimate.js +14 -194
  250. package/esm/src/kernel/engine/tool-trace.d.ts +3 -3
  251. package/esm/src/kernel/engine/tool-trace.js +2 -1
  252. package/esm/src/kernel/engine/turn-trace.d.ts +8 -7
  253. package/esm/src/kernel/engine/turn-trace.js +28 -36
  254. package/esm/src/kernel/engine/usage.d.ts +6 -0
  255. package/esm/src/kernel/engine/usage.js +17 -0
  256. package/esm/src/kernel/interaction-parts.d.ts +3 -0
  257. package/esm/src/kernel/interaction-parts.js +18 -0
  258. package/esm/src/kernel/json.d.ts +10 -0
  259. package/esm/src/kernel/json.js +3 -0
  260. package/esm/src/kernel/mod.d.ts +38 -11
  261. package/esm/src/kernel/mod.js +22 -7
  262. package/esm/src/kernel/profile-graph.d.ts +11 -6
  263. package/esm/src/kernel/profile-graph.js +14 -7
  264. package/esm/src/kernel/profile-presence.d.ts +10 -1
  265. package/esm/src/kernel/profile-presence.js +90 -75
  266. package/esm/src/kernel/profile-scope.d.ts +7 -3
  267. package/esm/src/kernel/profile-scope.js +67 -55
  268. package/esm/src/kernel/protocols/binding.d.ts +65 -0
  269. package/esm/src/kernel/protocols/binding.js +125 -0
  270. package/esm/src/kernel/protocols/limits.d.ts +15 -0
  271. package/esm/src/kernel/protocols/limits.js +28 -0
  272. package/esm/src/kernel/protocols/mod.d.ts +5 -0
  273. package/esm/src/kernel/protocols/mod.js +5 -0
  274. package/esm/src/kernel/protocols/prices.d.ts +36 -0
  275. package/esm/src/kernel/protocols/prices.js +37 -0
  276. package/esm/src/kernel/protocols/protocol.d.ts +253 -0
  277. package/esm/src/kernel/protocols/protocol.js +253 -0
  278. package/esm/src/kernel/protocols/provider.d.ts +108 -0
  279. package/esm/src/kernel/protocols/provider.js +143 -0
  280. package/esm/src/kernel/protocols/runtime.d.ts +55 -0
  281. package/esm/src/kernel/protocols/runtime.js +534 -0
  282. package/esm/src/kernel/provider-budget.d.ts +32 -0
  283. package/esm/src/kernel/provider-budget.js +262 -0
  284. package/esm/src/kernel/provider-dispatch.d.ts +13 -0
  285. package/esm/src/kernel/provider-dispatch.js +36 -0
  286. package/esm/src/kernel/provider-live.d.ts +7 -0
  287. package/esm/src/kernel/provider-live.js +189 -0
  288. package/esm/src/kernel/provider-runtime.d.ts +57 -0
  289. package/esm/src/kernel/provider-runtime.js +524 -0
  290. package/esm/src/kernel/registry/attachments.d.ts +15 -4
  291. package/esm/src/kernel/registry/attachments.js +31 -22
  292. package/esm/src/kernel/registry/catalog.d.ts +6 -0
  293. package/esm/src/kernel/registry/catalog.js +9 -2
  294. package/esm/src/kernel/registry/embedding-rules.d.ts +28 -0
  295. package/esm/src/kernel/registry/embedding-rules.js +66 -0
  296. package/esm/src/kernel/registry/ingress.d.ts +6 -2
  297. package/esm/src/kernel/registry/ingress.js +55 -10
  298. package/esm/src/kernel/registry/kernel-registry.d.ts +3 -0
  299. package/esm/src/kernel/registry/kernel-registry.js +9 -2
  300. package/esm/src/kernel/registry/profile-outputs.js +4 -1
  301. package/esm/src/kernel/registry/profiles.d.ts +38 -14
  302. package/esm/src/kernel/registry/profiles.js +280 -205
  303. package/esm/src/kernel/registry/provider-request.d.ts +3 -3
  304. package/esm/src/kernel/registry/provider-request.js +5 -13
  305. package/esm/src/kernel/registry/resolve.d.ts +4 -1
  306. package/esm/src/kernel/registry/resolve.js +59 -58
  307. package/esm/src/kernel/registry/schemas.d.ts +3 -0
  308. package/esm/src/kernel/registry/schemas.js +3 -1
  309. package/esm/src/kernel/registry/slot-fill.d.ts +7 -0
  310. package/esm/src/kernel/registry/slot-fill.js +22 -0
  311. package/esm/src/kernel/registry/system-prompt.js +7 -8
  312. package/esm/src/kernel/registry/vault.d.ts +14 -13
  313. package/esm/src/kernel/registry/vault.js +1 -14
  314. package/esm/src/kernel/schema.d.ts +100 -46
  315. package/esm/src/kernel/schema.js +499 -257
  316. package/esm/src/kernel/scope.d.ts +12 -5
  317. package/esm/src/kernel/scope.js +23 -3
  318. package/esm/src/kernel/stages.d.ts +38 -3
  319. package/esm/src/kernel/stages.js +82 -39
  320. package/esm/src/kernel/stop.d.ts +29 -6
  321. package/esm/src/kernel/stop.js +16 -4
  322. package/esm/src/kernel/system-parts.js +6 -6
  323. package/esm/src/kernel/tools/activity-label.d.ts +12 -6
  324. package/esm/src/kernel/tools/activity-label.js +258 -32
  325. package/esm/src/kernel/tools/agent.d.ts +66 -0
  326. package/esm/src/kernel/tools/agent.js +212 -0
  327. package/esm/src/kernel/tools/coordinate.d.ts +4 -0
  328. package/esm/src/kernel/tools/coordinate.js +165 -0
  329. package/esm/src/kernel/tools/events.d.ts +21 -6
  330. package/esm/src/kernel/tools/events.js +53 -18
  331. package/esm/src/kernel/tools/execute.d.ts +47 -11
  332. package/esm/src/kernel/tools/execute.js +508 -136
  333. package/esm/src/kernel/tools/gate-answer.d.ts +12 -2
  334. package/esm/src/kernel/tools/gate-answer.js +17 -6
  335. package/esm/src/kernel/tools/handler-events.d.ts +45 -0
  336. package/esm/src/kernel/tools/handler-events.js +106 -0
  337. package/esm/src/kernel/tools/harness.d.ts +1 -0
  338. package/esm/src/kernel/tools/harness.js +2 -1
  339. package/esm/src/kernel/tools/http-limit.d.ts +27 -0
  340. package/esm/src/kernel/tools/http-limit.js +85 -0
  341. package/esm/src/kernel/tools/invoke.d.ts +27 -5
  342. package/esm/src/kernel/tools/invoke.js +223 -70
  343. package/esm/src/kernel/tools/mcp-sessions.d.ts +4 -1
  344. package/esm/src/kernel/tools/mcp-sessions.js +13 -8
  345. package/esm/src/kernel/tools/mod.d.ts +4 -3
  346. package/esm/src/kernel/tools/mod.js +3 -2
  347. package/esm/src/kernel/tools/model-text.d.ts +10 -5
  348. package/esm/src/kernel/tools/model-text.js +18 -12
  349. package/esm/src/kernel/tools/operation.d.ts +76 -0
  350. package/esm/src/kernel/tools/operation.js +100 -0
  351. package/esm/src/kernel/tools/page-answer.d.ts +8 -0
  352. package/esm/src/kernel/tools/page-answer.js +19 -0
  353. package/esm/src/kernel/tools/permission.d.ts +11 -2
  354. package/esm/src/kernel/tools/permission.js +12 -12
  355. package/esm/src/kernel/tools/project.d.ts +4 -1
  356. package/esm/src/kernel/tools/project.js +32 -2
  357. package/esm/src/kernel/tools/registry.d.ts +9 -2
  358. package/esm/src/kernel/tools/registry.js +69 -10
  359. package/esm/src/kernel/tools/remote.d.ts +40 -6
  360. package/esm/src/kernel/tools/remote.js +219 -92
  361. package/esm/src/kernel/tools/resolve.d.ts +3 -0
  362. package/esm/src/kernel/tools/resolve.js +12 -4
  363. package/esm/src/kernel/tools/run.d.ts +28 -0
  364. package/esm/src/kernel/tools/run.js +86 -0
  365. package/esm/src/kernel/tools/schema.d.ts +3 -3
  366. package/esm/src/kernel/tools/schema.js +21 -100
  367. package/esm/src/kernel/tools/signed-in-fetch.d.ts +2 -1
  368. package/esm/src/kernel/tools/signed-in-fetch.js +3 -3
  369. package/esm/src/kernel/tools/stage-run.d.ts +27 -4
  370. package/esm/src/kernel/tools/stage-run.js +75 -17
  371. package/esm/src/kernel/tools/types.d.ts +235 -25
  372. package/esm/src/kernel/tools/unchecked-output.d.ts +14 -0
  373. package/esm/src/kernel/tools/unchecked-output.js +18 -0
  374. package/esm/src/kernel/turn-events.d.ts +208 -31
  375. package/esm/src/kernel/turn-events.js +127 -9
  376. package/esm/src/kernel/types.d.ts +302 -161
  377. package/esm/src/kernel/util/base64.d.ts +2 -0
  378. package/esm/src/kernel/util/base64.js +2 -0
  379. package/esm/src/kernel/util/partial-json.d.ts +23 -0
  380. package/esm/src/kernel/util/partial-json.js +128 -0
  381. package/esm/src/kernel/util/record.d.ts +1 -0
  382. package/esm/src/kernel/util/record.js +1 -0
  383. package/esm/src/observability/destinations.d.ts +5 -0
  384. package/esm/src/observability/destinations.js +7 -2
  385. package/esm/src/observability/jsonl.d.ts +2 -2
  386. package/esm/src/observability/jsonl.js +15 -22
  387. package/esm/src/observability/mod.d.ts +3 -3
  388. package/esm/src/observability/mod.js +2 -2
  389. package/esm/src/observability/openinference.d.ts +1 -1
  390. package/esm/src/observability/openinference.js +3 -3
  391. package/esm/src/observability/otlp.d.ts +3 -0
  392. package/esm/src/observability/otlp.js +3 -3
  393. package/esm/src/observability/phoenix.d.ts +1 -0
  394. package/esm/src/observability/policy.d.ts +3 -0
  395. package/esm/src/observability/policy.js +5 -1
  396. package/esm/src/observability/resolve-policy.js +11 -5
  397. package/esm/src/observability/spans.d.ts +8 -2
  398. package/esm/src/observability/spans.js +21 -5
  399. package/esm/src/observability/trace-catalog.d.ts +19 -2
  400. package/esm/src/observability/trace-catalog.js +128 -87
  401. package/esm/src/observability/trace-record.js +22 -17
  402. package/esm/src/observability/trace-schema.d.ts +3 -0
  403. package/esm/src/observability/trace-schema.js +1 -1
  404. package/esm/src/observability/trace-sink.d.ts +1 -0
  405. package/esm/src/observability/trace-sink.js +1 -1
  406. package/esm/src/observability/trace-span.d.ts +7 -1
  407. package/esm/src/observability/trace-span.js +3 -1
  408. package/esm/src/observability/trace.d.ts +2 -0
  409. package/esm/src/observability/trace.js +4 -2
  410. package/esm/src/observability/types.d.ts +35 -11
  411. package/esm/src/observability/types.js +1 -1
  412. package/esm/src/presets/google/speech-voices.d.ts +1 -0
  413. package/esm/src/presets/google-limits.d.ts +1 -0
  414. package/esm/src/presets/google.d.ts +27 -12
  415. package/esm/src/presets/google.js +34 -25
  416. package/esm/src/presets/local.d.ts +26 -0
  417. package/esm/src/presets/local.js +30 -0
  418. package/esm/src/presets/mod.d.ts +5 -4
  419. package/esm/src/presets/mod.js +4 -4
  420. package/esm/src/presets/openrouter.d.ts +14 -1
  421. package/esm/src/presets/openrouter.js +19 -1
  422. package/esm/src/providers/embedding-limits.d.ts +7 -0
  423. package/esm/src/providers/embedding-limits.js +12 -0
  424. package/esm/src/providers/gemini/embedding-protocol.d.ts +8 -0
  425. package/esm/src/providers/gemini/embedding-protocol.js +125 -0
  426. package/esm/src/providers/gemini/interactions-protocol.d.ts +8 -0
  427. package/esm/src/providers/gemini/interactions-protocol.js +105 -0
  428. package/esm/src/providers/gemini/live-protocol.d.ts +3 -0
  429. package/esm/src/providers/gemini/live-protocol.js +191 -0
  430. package/esm/src/providers/gemini/prices.d.ts +3 -0
  431. package/esm/src/providers/gemini/prices.js +63 -0
  432. package/esm/src/providers/gemini/provider.d.ts +7 -0
  433. package/esm/src/providers/gemini/provider.js +39 -0
  434. package/esm/src/providers/google/builtins.d.ts +14 -0
  435. package/esm/src/providers/google/builtins.js +57 -0
  436. package/esm/src/providers/google/grounding.d.ts +4 -4
  437. package/esm/src/providers/google/interactions/framing.d.ts +20 -8
  438. package/esm/src/providers/google/interactions/framing.js +85 -44
  439. package/esm/src/providers/google/interactions/steps.d.ts +5 -5
  440. package/esm/src/providers/google/interactions/steps.js +4 -4
  441. package/esm/src/providers/google/interactions/stream.d.ts +10 -11
  442. package/esm/src/providers/google/interactions/stream.js +33 -100
  443. package/esm/src/providers/google/live/framing.d.ts +15 -5
  444. package/esm/src/providers/google/live/framing.js +25 -25
  445. package/esm/src/providers/google/live/stream.d.ts +6 -44
  446. package/esm/src/providers/google/live/stream.js +3 -209
  447. package/esm/src/providers/google/urls.d.ts +1 -3
  448. package/esm/src/providers/google/urls.js +1 -3
  449. package/esm/src/providers/google/usage.js +2 -2
  450. package/esm/src/providers/live.d.ts +6 -0
  451. package/esm/src/providers/live.js +6 -0
  452. package/esm/src/providers/local/embedding-protocol.d.ts +7 -0
  453. package/esm/src/providers/local/embedding-protocol.js +60 -0
  454. package/esm/src/providers/local/provider.d.ts +7 -0
  455. package/esm/src/providers/local/provider.js +28 -0
  456. package/esm/src/providers/mod.d.ts +28 -7
  457. package/esm/src/providers/mod.js +19 -3
  458. package/esm/src/providers/open-ai/protocol.d.ts +3 -0
  459. package/esm/src/providers/open-ai/protocol.js +189 -0
  460. package/esm/src/providers/openrouter/embedding-protocol.d.ts +6 -0
  461. package/esm/src/providers/openrouter/embedding-protocol.js +86 -0
  462. package/esm/src/providers/openrouter/image.d.ts +0 -9
  463. package/esm/src/providers/openrouter/image.js +0 -153
  464. package/esm/src/providers/openrouter/images-protocol.d.ts +3 -0
  465. package/esm/src/providers/openrouter/images-protocol.js +82 -0
  466. package/esm/src/providers/openrouter/openai/compat.d.ts +2 -2
  467. package/esm/src/providers/openrouter/openai/compat.js +6 -6
  468. package/esm/src/providers/openrouter/openai/image-payload.d.ts +2 -2
  469. package/esm/src/providers/openrouter/openai/reasoning-state.d.ts +2 -0
  470. package/esm/src/providers/openrouter/openai/reasoning-state.js +31 -0
  471. package/esm/src/providers/openrouter/protocol.d.ts +8 -0
  472. package/esm/src/providers/openrouter/protocol.js +171 -0
  473. package/esm/src/providers/openrouter/provider.d.ts +10 -0
  474. package/esm/src/providers/openrouter/provider.js +50 -0
  475. package/esm/src/providers/shared/carried-tool-files.d.ts +7 -0
  476. package/esm/src/providers/shared/carried-tool-files.js +43 -0
  477. package/esm/src/providers/shared/pcm.js +2 -2
  478. package/esm/src/providers/shared/protocol-events.d.ts +8 -0
  479. package/esm/src/providers/shared/protocol-events.js +20 -0
  480. package/esm/src/providers/shared/response-identity.d.ts +2 -2
  481. package/esm/src/providers/shared/retry.d.ts +17 -0
  482. package/esm/src/providers/shared/retry.js +90 -0
  483. package/esm/src/providers/shared/sse.d.ts +0 -4
  484. package/esm/src/providers/shared/sse.js +50 -36
  485. package/esm/src/providers/shared/tool-args.d.ts +6 -7
  486. package/esm/src/providers/shared/tool-args.js +10 -6
  487. package/esm/src/providers/shared/tool-draft.d.ts +16 -0
  488. package/esm/src/providers/shared/tool-draft.js +14 -0
  489. package/esm/src/providers/shared/upstream-tap.d.ts +2 -2
  490. package/esm/src/providers/shared/upstream-tape.js +1 -1
  491. package/esm/src/providers/system-one/protocol.d.ts +8 -0
  492. package/esm/src/providers/system-one/protocol.js +93 -0
  493. package/esm/src/providers/types.d.ts +48 -16
  494. package/esm/src/providers/types.js +2 -1
  495. package/esm/src/providers/typesafe/provider.d.ts +7 -0
  496. package/esm/src/providers/typesafe/provider.js +24 -0
  497. package/esm/src/surface/formats.d.ts +19 -1
  498. package/esm/src/surface/formats.js +68 -29
  499. package/esm/src/surface/mod.d.ts +4 -2
  500. package/esm/src/surface/mod.js +4 -2
  501. package/esm/src/surface/runtime.d.ts +4 -0
  502. package/esm/src/surface/runtime.js +2 -0
  503. package/esm/src/surface/tools.d.ts +2 -8
  504. package/esm/src/surface/tools.js +4 -22
  505. package/esm/src/surface/types.d.ts +6 -0
  506. package/package.json +5 -13
  507. package/esm/src/cli/commands/egress-compile.d.ts +0 -17
  508. package/esm/src/cli/commands/egress-compile.js +0 -25
  509. package/esm/src/guardrails/egress-policy.d.ts +0 -27
  510. package/esm/src/guardrails/egress-policy.js +0 -76
  511. package/esm/src/guardrails/egress-rules.d.ts +0 -54
  512. package/esm/src/guardrails/egress-rules.js +0 -49
  513. package/esm/src/guardrails/lexicon.d.ts +0 -30
  514. package/esm/src/guardrails/lexicon.js +0 -478
  515. package/esm/src/kernel/engine/media-probe/audio.d.ts +0 -7
  516. package/esm/src/kernel/engine/media-probe/audio.js +0 -342
  517. package/esm/src/kernel/engine/media-probe/bytes.d.ts +0 -6
  518. package/esm/src/kernel/engine/media-probe/bytes.js +0 -26
  519. package/esm/src/kernel/engine/media-probe/image.d.ts +0 -5
  520. package/esm/src/kernel/engine/media-probe/image.js +0 -171
  521. package/esm/src/kernel/engine/media-probe/iso-bmff.d.ts +0 -19
  522. package/esm/src/kernel/engine/media-probe/iso-bmff.js +0 -48
  523. package/esm/src/kernel/engine/media-probe/matroska.d.ts +0 -35
  524. package/esm/src/kernel/engine/media-probe/matroska.js +0 -226
  525. package/esm/src/kernel/engine/media-probe/mp4.d.ts +0 -22
  526. package/esm/src/kernel/engine/media-probe/mp4.js +0 -279
  527. package/esm/src/kernel/engine/media-probe/opus.d.ts +0 -4
  528. package/esm/src/kernel/engine/media-probe/opus.js +0 -23
  529. package/esm/src/kernel/engine/media-probe/pdf.d.ts +0 -5
  530. package/esm/src/kernel/engine/media-probe/pdf.js +0 -117
  531. package/esm/src/kernel/engine/media-probe/video.d.ts +0 -15
  532. package/esm/src/kernel/engine/media-probe/video.js +0 -49
  533. package/esm/src/presets/typesafe.d.ts +0 -2
  534. package/esm/src/presets/typesafe.js +0 -2
  535. package/esm/src/providers/create-provider.d.ts +0 -21
  536. package/esm/src/providers/create-provider.js +0 -90
  537. package/esm/src/providers/decision/usage.d.ts +0 -3
  538. package/esm/src/providers/decision/usage.js +0 -25
  539. package/esm/src/providers/google/interactions/mod.d.ts +0 -2
  540. package/esm/src/providers/google/interactions/mod.js +0 -2
  541. package/esm/src/providers/google/keys.d.ts +0 -20
  542. package/esm/src/providers/google/keys.js +0 -87
  543. package/esm/src/providers/google/live/mod.d.ts +0 -7
  544. package/esm/src/providers/google/live/mod.js +0 -7
  545. package/esm/src/providers/google/live/openapi-schema.d.ts +0 -1
  546. package/esm/src/providers/google/live/openapi-schema.js +0 -42
  547. package/esm/src/providers/google/live/session.d.ts +0 -14
  548. package/esm/src/providers/google/live/session.js +0 -150
  549. package/esm/src/providers/local/local.d.ts +0 -12
  550. package/esm/src/providers/local/local.js +0 -186
  551. package/esm/src/providers/local/mod.d.ts +0 -8
  552. package/esm/src/providers/local/mod.js +0 -8
  553. package/esm/src/providers/openrouter/cache-control.d.ts +0 -5
  554. package/esm/src/providers/openrouter/cache-control.js +0 -4
  555. package/esm/src/providers/openrouter/chat.d.ts +0 -64
  556. package/esm/src/providers/openrouter/chat.js +0 -490
  557. package/esm/src/providers/openrouter/openai/sdk-messages.d.ts +0 -10
  558. package/esm/src/providers/openrouter/openai/sdk-messages.js +0 -99
  559. package/esm/src/providers/openrouter/resolve-api-key.d.ts +0 -3
  560. package/esm/src/providers/openrouter/resolve-api-key.js +0 -8
  561. package/esm/src/providers/openrouter/speech.d.ts +0 -18
  562. package/esm/src/providers/openrouter/speech.js +0 -109
  563. package/esm/src/providers/probe.d.ts +0 -5
  564. package/esm/src/providers/probe.js +0 -15
  565. package/esm/src/providers/shared/builtin-wire.d.ts +0 -4
  566. package/esm/src/providers/shared/builtin-wire.js +0 -9
  567. package/esm/src/providers/shared/vault.d.ts +0 -13
  568. package/esm/src/providers/shared/vault.js +0 -41
@@ -1,7 +1,7 @@
1
1
  /**
2
- * The bundled egress policy, run on a reply as it streams.
2
+ * The detectors, Theorem's and the host's own, run on a reply as it streams.
3
3
  *
4
- * The bundled checks match their patterns on the reply as written and, for
4
+ * Each matches its patterns on the reply as written and, for
5
5
  * injection phrasing, on
6
6
  * rewrites of it (typo-folded, Unicode-folded, rot13, leet, URL-decoded, read
7
7
  * backwards). The stream keeps each rewrite growing with the reply and, for
@@ -11,21 +11,20 @@
11
11
  * later starts at or after that place, so none of it has been released.
12
12
  *
13
13
  * A match whose outcome no later text can change is settled; a settled match
14
- * of the pattern itself (not the automaton) is a hit, and the reply is
15
- * blocked there. Each character is read a bounded number of times, so a long
16
- * reply costs time in proportion to its length.
14
+ * of the pattern itself (not the automaton) is a hit, and does what
15
+ * `guardrails.detect` sets (`detect-stream.ts`). Each character is read a bounded number of times, so a
16
+ * long reply costs time in proportion to its length.
17
17
  *
18
18
  * @module
19
19
  */
20
- import { DEFAULT_CHECKS, standardEgressEnforce } from './egress.js';
21
- import { FORWARD_AUTOMATON, REVERSED_AUTOMATON, REVERSED_INJECTION_PATTERNS, } from './egress-automata.js';
22
- import { EGRESS_PATTERNS } from './egress-patterns.js';
23
- import { globalPattern } from './egress-rules.js';
20
+ import { EGRESS_PATTERNS, notePattern, } from './egress-patterns.js';
24
21
  import { IMAGE_PATTERNS, imageReadings, LINK_PATTERNS, linkReadings, } from './egress-urls.js';
25
22
  import { decodeUrlRuns, INJECTION_BLOBS, TYPO_TARGETS, tryLeet, tryRot13, typoNormalize, } from './injection.js';
23
+ import { REVERSED_INJECTION_PATTERNS } from './injection-reversed.js';
26
24
  import { isEmoji, normalizeCodePoint } from './normalize.js';
27
- import { EGRESS_RULES } from './rules.js';
28
- import { cardHit } from './sensitive.js';
25
+ import { detectRule } from './rules.js';
26
+ import { cardHit, SENSITIVE_PATTERNS } from './sensitive.js';
27
+ import { namePatterns } from './tool-leak.js';
29
28
  const UNITS = 0x10000;
30
29
  function compile(data) {
31
30
  const classCount = data.classStarts.length;
@@ -48,10 +47,106 @@ function compile(data) {
48
47
  final[id] = node[1];
49
48
  edges.push(Int32Array.from(node.slice(2)));
50
49
  });
51
- return { classOf, has, pattern, final, edges, initials: data.initials, size };
50
+ return { classOf, has, pattern, final, edges, initials: data.initials, leads: data.leads, size };
52
51
  }
52
+ /** Theorem's automata, once `loadEgressAutomata` has read them. */
53
+ let bundled;
53
54
  let forward;
54
55
  let backward;
56
+ /**
57
+ * Reads Theorem's automata, the most of the kernel's size, the first time a stream needs them.
58
+ * Every gate's constructor waits for this, so an app that never streams a reply never loads them.
59
+ */
60
+ async function loadEgressAutomata() {
61
+ if (bundled)
62
+ return;
63
+ const { FORWARD_AUTOMATON, REVERSED_AUTOMATON } = await import('./egress-automata.js');
64
+ bundled = { forward: FORWARD_AUTOMATON, reversed: REVERSED_AUTOMATON };
65
+ }
66
+ function loaded() {
67
+ if (!bundled) {
68
+ throw new Error('A stream was opened before loadEgressAutomata() finished.'); // labels-exempt: developer contract / internal diagnostic — not end-user or model copy (P2)
69
+ }
70
+ return bundled;
71
+ }
72
+ /** The code units a case-insensitive regex reads as each one: ES `Canonicalize` without `u`. */
73
+ let caseUnits;
74
+ function canonicalUnit(unit) {
75
+ const upper = String.fromCharCode(unit).toUpperCase();
76
+ if (upper.length !== 1)
77
+ return unit;
78
+ const code = upper.charCodeAt(0);
79
+ return unit >= 0x80 && code < 0x80 ? unit : code;
80
+ }
81
+ function unitsLike(unit) {
82
+ if (!caseUnits) {
83
+ caseUnits = new Map();
84
+ for (let u = 0; u < UNITS; u++) {
85
+ const canon = canonicalUnit(u);
86
+ const units = caseUnits.get(canon);
87
+ if (units)
88
+ units.push(u);
89
+ else
90
+ caseUnits.set(canon, [u]);
91
+ }
92
+ }
93
+ return caseUnits.get(canonicalUnit(unit)) ?? [unit];
94
+ }
95
+ /** Class starts that give each of the sorted `units` a class of its own. */
96
+ function classStartsOf(units) {
97
+ const classStarts = [0];
98
+ for (const unit of units) {
99
+ if (classStarts.at(-1) !== unit)
100
+ classStarts.push(unit);
101
+ if (unit + 1 < UNITS)
102
+ classStarts.push(unit + 1);
103
+ }
104
+ return classStarts;
105
+ }
106
+ /** Literal automata, kept per text so each is built once. */
107
+ const literalAutomata = new Map();
108
+ /** An automaton for `text` as written, case aside, as `notePattern` reads it. */
109
+ function literalAutomaton(text) {
110
+ const cached = literalAutomata.get(text);
111
+ if (cached)
112
+ return cached;
113
+ const positions = Array.from({ length: text.length }, (_, i) => unitsLike(text.charCodeAt(i)));
114
+ const classStarts = classStartsOf([...new Set(positions.flat())].sort((a, b) => a - b));
115
+ const classOfUnit = (unit) => classStarts.indexOf(unit);
116
+ const charsets = positions.map((like) => like.map(classOfUnit));
117
+ const nodes = [...positions.map((_, i) => [0, 0, i + 1, i]), [0, 1]];
118
+ const automaton = compile({ classStarts, charsets, initials: [0], leads: [-1], nodes });
119
+ literalAutomata.set(text, automaton);
120
+ return automaton;
121
+ }
122
+ /**
123
+ * An automaton for each of `texts` as written, case and all: pattern `i` is `texts[i]`. Kept
124
+ * per list, so a profile's is built once. Each unit has a charset of its own: charset `k` is the
125
+ * class of `units[k]`.
126
+ */
127
+ function literalsAutomaton(texts) {
128
+ const key = JSON.stringify(texts);
129
+ const cached = literalAutomata.get(key);
130
+ if (cached)
131
+ return cached;
132
+ const units = [...new Set(texts.flatMap((text) => Array.from(text, (c) => c.charCodeAt(0))))];
133
+ units.sort((a, b) => a - b);
134
+ const classStarts = classStartsOf(units);
135
+ const charsets = units.map((unit) => [classStarts.indexOf(unit)]);
136
+ const nodes = [];
137
+ const initials = texts.map((text, id) => {
138
+ const first = nodes.length;
139
+ for (let i = 0; i < text.length; i++) {
140
+ nodes.push([id, 0, nodes.length + 1, units.indexOf(text.charCodeAt(i))]);
141
+ }
142
+ nodes.push([id, 1]);
143
+ return first;
144
+ });
145
+ const leads = texts.map(() => -1);
146
+ const automaton = compile({ classStarts, charsets, initials, leads, nodes });
147
+ literalAutomata.set(key, automaton);
148
+ return automaton;
149
+ }
55
150
  /** The first edges of the given patterns, per character class. */
56
151
  function startEdges(automaton, patterns) {
57
152
  const classCount = automaton.has[0]?.length ?? 0;
@@ -111,27 +206,33 @@ function unitView(source, rewrite) {
111
206
  }
112
207
  const WORD_UNIT = /\w/;
113
208
  const MAX_TARGET = Math.max(...TYPO_TARGETS.map((target) => target.length));
114
- const TARGET_FIRSTS = new Set(TYPO_TARGETS.map((target) => target[0]));
115
- /** Whether a word still being written could yet fold to a typo target. */
209
+ /** Whether a word still being written could yet fold to a typo target: a misspelling may be a letter longer. */
116
210
  function mayFold(run) {
117
- return (run.length <= MAX_TARGET &&
118
- /^[A-Za-z]*$/.test(run) &&
119
- (run.length === 0 || TARGET_FIRSTS.has(run[0]?.toLowerCase())));
211
+ return run.length <= MAX_TARGET + 1 && /^[A-Za-z]*$/.test(run);
120
212
  }
121
213
  /**
122
- * `typoNormalize` of the source. It rewrites whole words (`\w` runs) of the
123
- * same length, so a word settles when a non-word character ends it, or as soon
124
- * as it can no longer fold to a target (then the rest of it passes as is).
214
+ * `typoNormalize` of the source. It rewrites whole words (`\w` runs), so a
215
+ * word settles when a non-word character ends it, or as soon as it can no
216
+ * longer fold to a target (then the rest of it passes as is). A corrected word
217
+ * may be a letter longer or shorter than the word as written, so each
218
+ * character keeps the source index it stands for.
125
219
  */
126
220
  function typoView(source) {
127
221
  let read = 0;
128
222
  /** The word being read, while it may still fold. */
129
223
  let word;
130
224
  let inWord = false;
225
+ /** Per settled character, the source index it stands for. */
226
+ const from = [];
227
+ const put = (piece, start, length) => {
228
+ grow(view, piece);
229
+ for (let i = 0; i < piece.length; i++)
230
+ from.push(start + Math.min(i, length - 1));
231
+ };
131
232
  const view = {
132
233
  text: '',
133
234
  fresh: '',
134
- rawAt: (j) => source.rawAt(Math.min(j, view.text.length)),
235
+ rawAt: (j) => source.rawAt(j < from.length ? from[j] : read - (word?.length ?? 0)),
135
236
  update() {
136
237
  view.fresh = '';
137
238
  for (const end = source.text.length; read < end; read++) {
@@ -142,17 +243,17 @@ function typoView(source) {
142
243
  inWord = wordUnit;
143
244
  if (!wordUnit) {
144
245
  if (word !== undefined)
145
- grow(view, typoNormalize(word));
246
+ put(typoNormalize(word), read - word.length, word.length);
146
247
  word = undefined;
147
- grow(view, unit);
248
+ put(unit, read, 1);
148
249
  }
149
250
  else if (word === undefined)
150
- grow(view, unit);
251
+ put(unit, read, 1);
151
252
  else
152
253
  word += unit;
153
254
  }
154
255
  if (word !== undefined && !mayFold(word)) {
155
- grow(view, word);
256
+ put(word, read - word.length, word.length);
156
257
  word = undefined;
157
258
  }
158
259
  },
@@ -186,7 +287,7 @@ const LOW_HI = 0xdfff;
186
287
  * or in the mapped text), an emoji run after a letter until the character
187
288
  * after it, a backslash until the character after it.
188
289
  */
189
- function normalizedView(reply) {
290
+ function normalizedReplyView(reply) {
190
291
  let read = 0;
191
292
  /** Mapped text the emoji pass has not read: at most a trailing high surrogate. */
192
293
  let mapped = '';
@@ -291,7 +392,7 @@ function urlView(reply) {
291
392
  }
292
393
  continue;
293
394
  }
294
- // Inside a run: complete escapes end at runStart + 3k.
395
+ // why: Inside a run: complete escapes end at runStart + 3k.
295
396
  const offset = (read - runStart) % 3;
296
397
  const fits = offset === 0 ? unit === '%' : URL_HEX.test(unit);
297
398
  if (fits) {
@@ -299,7 +400,7 @@ function urlView(reply) {
299
400
  continue;
300
401
  }
301
402
  endRun(read - offset);
302
- // The broken escape's text is literal; `read` rereads from its end.
403
+ // why: The broken escape's text is literal; `read` rereads from its end.
303
404
  for (let i = read - offset; i < read; i++)
304
405
  append(view, String.fromCharCode(unitAt(reply, i)), i);
305
406
  }
@@ -311,32 +412,6 @@ function urlView(reply) {
311
412
  }
312
413
  return view;
313
414
  }
314
- const BLOB_HITS = new Map(INJECTION_BLOBS.map(({ pattern, hit }) => [pattern, hit]));
315
- /** The bundled rule a pattern kind trips, with `collectEgressHits`' severity. */
316
- const KIND_RULES = {
317
- injection: { rule: EGRESS_RULES.injection, severity: 'medium' },
318
- base64: { rule: EGRESS_RULES.injection, severity: 'medium' },
319
- hex: { rule: EGRESS_RULES.injection, severity: 'medium' },
320
- spaced: { rule: EGRESS_RULES.injection, severity: 'medium' },
321
- pipe: { rule: EGRESS_RULES.injection, severity: 'medium' },
322
- sensitive: { rule: EGRESS_RULES.sensitive, severity: 'high' },
323
- card: { rule: EGRESS_RULES.sensitive, severity: 'high' },
324
- boundary: { rule: EGRESS_RULES.boundary, severity: 'medium' },
325
- image: { rule: EGRESS_RULES.image, severity: 'high' },
326
- link: { rule: EGRESS_RULES.link, severity: 'high' },
327
- };
328
- /** How a settled match of `pattern` is read: a test of the match, or a finder in place of the regex. */
329
- function patternReading(kind, pattern, urls) {
330
- if (kind === 'card')
331
- return { hit: cardHit };
332
- if (kind === 'image' || kind === 'link') {
333
- const index = (kind === 'image' ? IMAGE_PATTERNS : LINK_PATTERNS).indexOf(pattern);
334
- const reading = urls[kind][index];
335
- return 'find' in reading ? { find: reading.find } : { hit: reading.test };
336
- }
337
- const hit = BLOB_HITS.get(pattern);
338
- return hit ? { hit } : {};
339
- }
340
415
  const INJECTION_KINDS = new Set([
341
416
  'injection',
342
417
  'base64',
@@ -344,35 +419,57 @@ const INJECTION_KINDS = new Set([
344
419
  'spaced',
345
420
  'pipe',
346
421
  ]);
347
- /** Whether `checks` runs the check a pattern belongs to. */
348
- function runs({ kind, group }, checks) {
422
+ const BLOB_HITS = new Map(INJECTION_BLOBS.map(({ pattern, hit }) => [pattern, hit]));
423
+ const SENSITIVE_HITS = new Map(SENSITIVE_PATTERNS.flatMap(({ pattern, hit }) => (hit ? [[pattern, hit]] : [])));
424
+ /** What a match of `detector`, or of the host's own by its id, reports, with `detectAt`'s severity. */
425
+ function detectorRule(detector) {
426
+ return { rule: detectRule(detector), severity: 'high', detector };
427
+ }
428
+ const INJECTION_RULE = detectorRule('injection');
429
+ const MARKER_RULE = detectorRule('marker_leak');
430
+ const TOOL_RULE = detectorRule('tool_leak');
431
+ /** What a pattern's match reports: its detector's rule. */
432
+ function patternRule({ kind, group }) {
349
433
  if (INJECTION_KINDS.has(kind))
350
- return checks.injection;
434
+ return INJECTION_RULE;
351
435
  switch (kind) {
352
436
  case 'sensitive':
353
437
  case 'card':
354
- return group !== undefined && checks.sensitive[group];
438
+ return group === undefined ? undefined : detectorRule(group);
355
439
  case 'boundary':
356
- return checks.boundary;
440
+ return MARKER_RULE;
357
441
  case 'image':
358
- return checks.images !== undefined;
442
+ return detectorRule('ungiven_images');
359
443
  default:
360
- return checks.links !== undefined;
444
+ return detectorRule('ungiven_links');
361
445
  }
362
446
  }
363
- /** The patterns `checks` runs on the reply as written. */
364
- function forwardPatterns(checks, given) {
447
+ /** How a settled match of `pattern` is read: a test of the match, or a finder in place of the regex. */
448
+ function patternReading(kind, pattern, urls) {
449
+ if (kind === 'card')
450
+ return { hit: cardHit };
451
+ if (kind === 'image' || kind === 'link') {
452
+ const index = (kind === 'image' ? IMAGE_PATTERNS : LINK_PATTERNS).indexOf(pattern);
453
+ const reading = urls[kind][index];
454
+ return 'find' in reading ? { find: reading.find } : { hit: reading.test };
455
+ }
456
+ const hit = BLOB_HITS.get(pattern) ?? SENSITIVE_HITS.get(pattern);
457
+ return hit ? { hit } : {};
458
+ }
459
+ /** The patterns of `detectors`, read on the reply as written. */
460
+ function forwardPatterns(detectors, { given, allow, skipImages }) {
365
461
  const scope = (check) => ({ ...check, ...(given ? { given } : {}) });
366
462
  const urls = {
367
- image: imageReadings(scope(checks.images)),
368
- link: linkReadings(scope(checks.links), checks.images !== undefined),
463
+ image: imageReadings(scope(allow?.ungiven_images)),
464
+ link: linkReadings(scope(allow?.ungiven_links), skipImages ?? detectors.includes('ungiven_images')),
369
465
  };
370
466
  const out = [];
371
467
  EGRESS_PATTERNS.forEach((entry, id) => {
372
- if (!runs(entry, checks))
468
+ const rule = patternRule(entry);
469
+ if (!(rule?.detector && detectors.includes(rule.detector)))
373
470
  return;
374
471
  out.push({
375
- ...KIND_RULES[entry.kind],
472
+ ...rule,
376
473
  id,
377
474
  regex: new RegExp(entry.pattern.source, entry.pattern.flags),
378
475
  ...patternReading(entry.kind, entry.pattern, urls),
@@ -388,7 +485,7 @@ function injectionPatterns() {
388
485
  return;
389
486
  const hit = BLOB_HITS.get(pattern);
390
487
  out.push({
391
- ...KIND_RULES.injection,
488
+ ...INJECTION_RULE,
392
489
  id,
393
490
  regex: new RegExp(pattern.source, pattern.flags),
394
491
  ...(hit ? { hit } : {}),
@@ -398,7 +495,7 @@ function injectionPatterns() {
398
495
  }
399
496
  function reversedPatterns() {
400
497
  return REVERSED_INJECTION_PATTERNS.map((pattern, id) => ({
401
- ...KIND_RULES.injection,
498
+ ...INJECTION_RULE,
402
499
  id,
403
500
  regex: new RegExp(pattern.source, pattern.flags),
404
501
  }));
@@ -407,7 +504,10 @@ function reversedPatterns() {
407
504
  * One view scanned for some patterns: the automata, run one character at a
408
505
  * time, give where each pattern could still be matching; the pattern's own
409
506
  * regex, run only where the automaton reached a match, finds the match and
410
- * whether it has settled. A pattern whose matches nest (tags inside tags) is
507
+ * whether it has settled. A pattern opened by an optional repeat of one class
508
+ * has no thread for the repeat: a thread of it starts where the run of that
509
+ * class it is in started, and the run the text ends in is still under way.
510
+ * A pattern whose matches nest (tags inside tags) is
411
511
  * read instead by its finder, once over each stretch that settles.
412
512
  */
413
513
  function createScan(view, automaton, patterns) {
@@ -440,6 +540,11 @@ function createScan(view, automaton, patterns) {
440
540
  */
441
541
  const openedFrom = new Int32Array(patterns.length).fill(-1);
442
542
  const lastOpened = new Int32Array(patterns.length).fill(-1);
543
+ const leadOf = Int32Array.from(patterns, (p) => automaton.leads[p.id] ?? -1);
544
+ const leads = [...new Set(leadOf)].filter((lead) => lead >= 0);
545
+ const led = patterns.flatMap((_, p) => (leadOf[p] < 0 ? [] : [p]));
546
+ /** Per lead charset: where the run of it the text ends in started, or -1. */
547
+ const runFrom = new Int32Array(automaton.has.length).fill(-1);
443
548
  function feed() {
444
549
  const { text, fresh } = view;
445
550
  const base = freshFrom(view);
@@ -475,14 +580,23 @@ function createScan(view, automaton, patterns) {
475
580
  const first = starts[cls];
476
581
  for (let k = 0; k < first.length; k++) {
477
582
  const target = first[k];
478
- add(target, fed);
479
583
  const p = local[pattern[target]];
584
+ const lead = leadOf[p];
585
+ const run = lead < 0 ? -1 : runFrom[lead];
586
+ const start = run < 0 ? fed : run;
587
+ add(target, start);
480
588
  if (finds[p]) {
481
589
  lastOpened[p] = fed;
482
590
  if (openedFrom[p] < 0)
483
- openedFrom[p] = fed;
591
+ openedFrom[p] = start;
484
592
  }
485
593
  }
594
+ for (const lead of leads) {
595
+ if (!has[lead][cls])
596
+ runFrom[lead] = -1;
597
+ else if (runFrom[lead] < 0)
598
+ runFrom[lead] = fed;
599
+ }
486
600
  [nodes, next] = [next, nodes];
487
601
  [from, nextFrom] = [nextFrom, from];
488
602
  count = size;
@@ -505,19 +619,35 @@ function createScan(view, automaton, patterns) {
505
619
  if (start < earliest)
506
620
  earliest = start;
507
621
  }
622
+ for (const p of led) {
623
+ const run = runFrom[leadOf[p]];
624
+ if (run < 0)
625
+ continue;
626
+ if (run < liveFrom[p])
627
+ liveFrom[p] = run;
628
+ if (run < earliest)
629
+ earliest = run;
630
+ }
508
631
  return earliest;
509
632
  }
510
633
  /** A finder's hit up to `settledTo`, run only on a stretch its automaton opened a thread in. */
511
634
  function found(p, settledTo) {
512
635
  const opened = openedFrom[p];
513
636
  const from = resume[p];
514
- resume[p] = settledTo;
515
- if (opened < 0 || opened >= settledTo)
637
+ if (opened < 0 || opened >= settledTo) {
638
+ resume[p] = settledTo;
516
639
  return undefined;
517
- openedFrom[p] = lastOpened[p] >= settledTo ? settledTo : -1;
518
- const { find, rule, severity } = patterns[p];
640
+ }
641
+ const { find, rule, severity, detector } = patterns[p];
519
642
  const at = find?.(view.text, from, settledTo);
520
- return at === undefined ? undefined : { rule, severity, start: view.rawAt(at) };
643
+ if (at === undefined) {
644
+ resume[p] = settledTo;
645
+ openedFrom[p] = lastOpened[p] >= settledTo ? settledTo : -1;
646
+ return undefined;
647
+ }
648
+ // why: A detector's match need not end the reply, so the next call finds the one after it.
649
+ resume[p] = Math.max(from, at) + 1;
650
+ return { rule, severity, start: view.rawAt(at), detector };
521
651
  }
522
652
  /** A regex pattern's hit up to `settledTo`. */
523
653
  function matched(p, settledTo) {
@@ -527,7 +657,7 @@ function createScan(view, automaton, patterns) {
527
657
  }
528
658
  reached[p] = 0;
529
659
  const text = view.text;
530
- const { regex, hit, rule, severity } = patterns[p];
660
+ const { regex, hit, rule, severity, detector } = patterns[p];
531
661
  regex.lastIndex = resume[p];
532
662
  for (;;) {
533
663
  const match = regex.exec(text);
@@ -538,7 +668,10 @@ function createScan(view, automaton, patterns) {
538
668
  }
539
669
  const [blob] = match;
540
670
  if (blob && (!hit || hit(blob, text, match.index))) {
541
- return { rule, severity, start: view.rawAt(match.index) };
671
+ // why: The scan reads on from the end of the match, so the next call finds the one after it.
672
+ resume[p] = regex.lastIndex;
673
+ recheck[p] = 1;
674
+ return { rule, severity, start: view.rawAt(match.index), detector };
542
675
  }
543
676
  if (!blob)
544
677
  regex.lastIndex++;
@@ -557,25 +690,27 @@ function createScan(view, automaton, patterns) {
557
690
  return undefined;
558
691
  }
559
692
  return {
560
- /** Read what the view settled; a hit, or the reply index to hold from. */
561
- run() {
693
+ /** Read what the view settled into `hits`; the reply index to hold from. */
694
+ run(hits) {
562
695
  feed();
563
696
  const earliest = live();
564
- return detect() ?? view.rawAt(earliest);
697
+ for (let hit = detect(); hit; hit = detect())
698
+ hits.push(hit);
699
+ return view.rawAt(earliest);
565
700
  },
566
701
  };
567
702
  }
568
703
  /** Compiled host automata, kept per table so each is built once. */
569
704
  const hostAutomata = new WeakMap();
570
- function hostPatterns({ rules }) {
571
- return rules.map(({ rule, severity, pattern }, id) => ({
572
- rule,
573
- severity,
574
- id,
575
- regex: globalPattern(pattern),
576
- }));
705
+ function hostAutomaton(data) {
706
+ let automaton = hostAutomata.get(data);
707
+ if (!automaton) {
708
+ automaton = compile(data);
709
+ hostAutomata.set(data, automaton);
710
+ }
711
+ return automaton;
577
712
  }
578
- /** Scans the bundled egress policy's patterns, and any host rules, as a reply streams. */
713
+ /** Scans the detectors' patterns, Theorem's and the host's own, as a reply streams. */
579
714
  function createEgressStream(options = {}) {
580
715
  const reply = { text: '', fresh: '' };
581
716
  const raw = rawView(reply);
@@ -586,26 +721,37 @@ function createEgressStream(options = {}) {
586
721
  return createScan(view, automaton, patterns);
587
722
  };
588
723
  const scans = [];
589
- const checks = options.checks ?? DEFAULT_CHECKS;
590
- const forwardScan = forwardPatterns(checks, options.given);
724
+ const detectors = options.detect ?? [];
725
+ const forwardScan = forwardPatterns(detectors, options);
591
726
  if (forwardScan.length > 0) {
592
- forward ??= compile(FORWARD_AUTOMATON);
727
+ forward ??= compile(loaded().forward);
593
728
  scans.push(scan(raw, forward, forwardScan));
594
729
  }
595
- if (checks.injection) {
596
- forward ??= compile(FORWARD_AUTOMATON);
597
- backward ??= compile(REVERSED_AUTOMATON);
598
- const normalized = normalizedView(reply);
730
+ if (detectors.includes('injection')) {
731
+ forward ??= compile(loaded().forward);
732
+ backward ??= compile(loaded().reversed);
733
+ const normalized = normalizedReplyView(reply);
599
734
  const injection = injectionPatterns();
600
735
  scans.push(scan(raw, backward, reversedPatterns()), scan(typoView(raw), forward, injection), scan(normalized, forward, injection), scan(typoView(normalized), forward, injection), scan(unitView(raw, tryRot13), forward, injection), scan(unitView(raw, (text) => tryLeet(text) ?? text), forward, injection), scan(urlView(reply), forward, injection));
601
736
  }
602
- if (options.host) {
603
- let automaton = hostAutomata.get(options.host.automaton);
604
- if (!automaton) {
605
- automaton = compile(options.host.automaton);
606
- hostAutomata.set(options.host.automaton, automaton);
737
+ if (detectors.includes('marker_leak') && options.note) {
738
+ const regex = notePattern(options.note);
739
+ scans.push(scan(raw, literalAutomaton(options.note), [{ ...MARKER_RULE, id: 0, regex }]));
740
+ }
741
+ if (detectors.includes('tool_leak') && options.tools) {
742
+ const names = namePatterns(options.tools);
743
+ const patterns = names.map(({ regex }, id) => ({ ...TOOL_RULE, id, regex }));
744
+ if (names.length > 0) {
745
+ scans.push(scan(raw, literalsAutomaton(names.map(({ literal }) => literal)), patterns));
607
746
  }
608
- scans.push(scan(raw, automaton, hostPatterns(options.host)));
747
+ }
748
+ for (const { detector, compiled, matchers } of options.own ?? []) {
749
+ const patterns = matchers.map(({ regex }, id) => ({
750
+ ...detectorRule(detector),
751
+ id,
752
+ regex: new RegExp(regex.source, regex.flags),
753
+ }));
754
+ scans.push(scan(raw, hostAutomaton(compiled.automaton), patterns));
609
755
  }
610
756
  let hold = 0;
611
757
  return {
@@ -614,32 +760,15 @@ function createEgressStream(options = {}) {
614
760
  reply.fresh = chunk;
615
761
  for (const view of views)
616
762
  view.update();
763
+ const hits = [];
617
764
  let from = reply.text.length;
618
765
  for (const s of scans) {
619
- const result = s.run();
620
- if (typeof result !== 'number')
621
- return result;
622
- from = Math.min(from, result);
766
+ from = Math.min(from, s.run(hits));
623
767
  }
624
768
  hold = from;
625
- return undefined;
769
+ return hits;
626
770
  },
627
771
  holdFrom: () => hold,
628
772
  };
629
773
  }
630
- /** Streaming plans for the policies whose checks the stream runs itself. */
631
- const STREAM_PLANS = new WeakMap([
632
- [
633
- standardEgressEnforce,
634
- (context) => createEgressStream(context.givenUrls ? { given: context.givenUrls } : {}),
635
- ],
636
- ]);
637
- /** The streaming plan for `enforce`, when the stream knows its checks. */
638
- function streamPlanOf(enforce) {
639
- return STREAM_PLANS.get(enforce);
640
- }
641
- /** Tell the gate `enforce` runs exactly the checks `plan` streams. */
642
- function registerStreamPlan(enforce, plan) {
643
- STREAM_PLANS.set(enforce, plan);
644
- }
645
- export { createEgressStream, normalizedView, registerStreamPlan, streamPlanOf, typoView, urlView };
774
+ export { createEgressStream, loadEgressAutomata, normalizedReplyView, typoView, urlView };
@@ -15,9 +15,10 @@
15
15
  * @module
16
16
  */
17
17
  import type { TurnHistoryMessage } from '../kernel/turn-events.js';
18
- import type { ProviderCompleteRequest } from '../kernel/types.js';
18
+ import type { ModelRequest } from '../kernel/types.js';
19
+ /** The URLs a request already contains, split by who controls them: those from the system prompt, user, and host history, and those from tool results. */
19
20
  interface GivenUrls {
20
- /** From the system prompt, the user and host history. */
21
+ /** From the system prompt, the user, and host history. */
21
22
  request: ReadonlySet<string>;
22
23
  /** From tool results, which whoever wrote them controls. */
23
24
  tools: ReadonlySet<string>;
@@ -25,6 +26,8 @@ interface GivenUrls {
25
26
  interface GivenUrlSets extends GivenUrls {
26
27
  request: Set<string>;
27
28
  tools: Set<string>;
29
+ /** A request's input, or a message, that quotes the model's own words: a URL in it was not given. */
30
+ own: WeakSet<object>;
28
31
  }
29
32
  declare function givenUrlSets(): GivenUrlSets;
30
33
  interface UrlScope {
@@ -41,7 +44,7 @@ interface UrlScope {
41
44
  /** Adds every absolute URL in `text`, as a reader of it could have copied it. */
42
45
  declare function addSeenUrls(seen: Set<string>, text: string): void;
43
46
  declare function addHistoryUrls(given: GivenUrlSets, messages: readonly TurnHistoryMessage[]): void;
44
- declare function addRequestUrls(given: GivenUrlSets, request: Pick<ProviderCompleteRequest, 'system' | 'input' | 'history' | 'continuation'>): void;
47
+ declare function addRequestUrls(given: GivenUrlSets, request: Pick<ModelRequest, 'system' | 'input' | 'history'>): void;
45
48
  type Span = {
46
49
  start: number;
47
50
  end: number;