@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,63 +1,36 @@
1
1
  import { canaryOpeningFrom, createCanaryScanner, promptLeakCarry, RELEASED_LOOKBACK, } from './canary.js';
2
- import { CANARY_HIT, promptEchoHits, runEnforcer } from './egress.js';
3
- import { streamPlanOf } from './egress-stream.js';
4
- import { TheoremError } from './error.js';
2
+ import { detectReads, scopeOf } from './detect-at.js';
3
+ import { createDetectStream } from './detect-stream.js';
4
+ import { promptEchoHits } from './egress.js';
5
+ import { loadEgressAutomata } from './egress-stream.js';
6
+ import { CANARY_HIT } from './hits.js';
5
7
  import { promptEchoHoldFrom, promptEchoScanFrom } from './prompt-echo.js';
6
- import { EGRESS_RULES } from './rules.js';
7
- /** Default lookback under a host `egress.enforce` the gate cannot read. */
8
- const DEFAULT_HOLDBACK = 256;
9
- /**
10
- * Default lookback on Live under a host policy the gate cannot read, where the
11
- * held transcript holds back audio too: the shortest that shows the host no
12
- * character of any egress corpus match however the transcript is chunked
13
- * (88), with a margin.
14
- */
15
- const LIVE_DEFAULT_HOLDBACK = 96;
16
- const PEM_BEGIN = '-----BEGIN';
17
- /**
18
- * Fixed lookback for a host policy the gate cannot read: `holdback`, or
19
- * `DEFAULT_HOLDBACK`. The canary, the prompt echo and the bundled policy need
20
- * none — each holds exactly the tail that could still start a match.
21
- */
22
- function resolveHoldback(options, exact) {
23
- if (exact) {
24
- if (options.holdback !== undefined) {
25
- throw new TheoremError('config', 'holdback applies only to a host egress.enforce; the bundled policy holds exactly');
26
- }
27
- return 0;
28
- }
29
- return options.holdback ?? (options.enforce ? DEFAULT_HOLDBACK : 0);
30
- }
31
- function holdbackForWindow(window, base) {
32
- // Incomplete PEM bodies can be large; do not release past BEGIN until END/flush.
33
- const begin = window.lastIndexOf(PEM_BEGIN);
34
- if (begin < 0)
35
- return base;
36
- const fromBegin = window.slice(begin);
37
- if (/-----END (?:RSA )?PRIVATE KEY-----/.test(fromBegin))
38
- return base;
39
- return Math.max(base, window.length - begin);
40
- }
41
- /**
42
- * The verdict for a match the stream settled: the policy's own, run on the
43
- * window. The stream only ever settles a match the policy finds, so a policy
44
- * that does not block here is out of step with it: blocked anyway.
45
- */
46
- async function streamHitVerdict(enforce, hit, window, context) {
47
- const verdict = await runEnforcer(enforce, { text: window }, context);
48
- if ((verdict.action === 'block' || verdict.action === 'redact') && verdict.hits.length > 0) {
49
- return verdict.hits;
50
- }
51
- return [{ rule: hit.rule, severity: hit.severity }];
52
- }
53
8
  /** Call `flush` when the stream ends to release the held tail. */
54
- function createProgressiveYieldGate(options) {
9
+ async function createProgressiveYieldGate(options) {
10
+ if (options.detect)
11
+ await loadEgressAutomata();
12
+ return progressiveYieldGate(options);
13
+ }
14
+ /** `createProgressiveYieldGate`, once the automata are loaded: a Live cycle opens its next gate mid-stream. */
15
+ function progressiveYieldGate(options) {
55
16
  const { context } = options;
56
- const stream = options.enforce
57
- ? streamPlanOf(options.enforce)?.(context)
17
+ const reads = options.detect;
18
+ const detecting = reads
19
+ ? createDetectStream(reads.boundary, reads.matrix, reads.scope)
58
20
  : undefined;
59
- const baseHoldback = resolveHoldback(options, stream !== undefined);
60
- const carry = context.canary ? (options.carry ?? '') : '';
21
+ /** What a match of one of ours does at this gate's boundary. A gate given no matrix stops on it. */
22
+ const ours = (detector) => reads ? reads.matrix[detector][reads.boundary] : 'block';
23
+ const canaryAction = ours('canary_leak');
24
+ const promptAction = ours('prompt_leak');
25
+ /** The canary a reply must not repeat: none when it was given (`canaryGiven`), or not read here. */
26
+ const token = context.canaryGiven || canaryAction === 'ignore' ? undefined : context.canary;
27
+ /** The private system instruction a reply must not repeat: none when not read here. */
28
+ const privateSystem = promptAction === 'ignore' ? undefined : context.privateSystem;
29
+ const guarded = token !== undefined || privateSystem !== undefined;
30
+ const carry = guarded ? (options.carry ?? '') : '';
31
+ /** The leaks set to `flag` found since the last release, and the rules already reported. */
32
+ let noted = [];
33
+ const reported = new Set();
61
34
  let accumulated = '';
62
35
  let emitted = 0;
63
36
  /** The window from `emitted` on. Each piece of the reply is kept apart, so no step rereads the whole. */
@@ -78,71 +51,65 @@ function createProgressiveYieldGate(options) {
78
51
  let openingBase = 0;
79
52
  let openingFrom = 0;
80
53
  /** Reads the carry, then the window as it grows. */
81
- const scanner = context.canary ? createCanaryScanner(context.canary) : undefined;
54
+ const scanner = token ? createCanaryScanner(token) : undefined;
82
55
  scanner?.push(carry);
83
56
  /**
84
- * The system-prompt leak hits (canary, prompt echo) in the carry and this
85
- * window. The canary scan reads each character once (`createCanaryScanner`)
86
- * and the echo check rereads only its own short lookback
87
- * (`promptEchoScanFrom`), so a long reply costs time in proportion to its
88
- * length, not its square.
89
- */
90
- function canaryWindowHits(fresh) {
91
- const scanned = echoed.length;
92
- echoed += fresh;
93
- const from = promptEchoScanFrom(echoed, scanned);
94
- echoed = echoed.slice(from);
95
- echoedFrom += from;
96
- return [
97
- ...(scanner?.push(fresh) ? [CANARY_HIT] : []),
98
- ...(context.privateSystem
99
- ? promptEchoHits(echoed, context.privateSystem, context.canary)
100
- : []),
101
- ];
102
- }
103
- /**
104
- * The host policy's hits on the window. The bundled policy reads only the
105
- * new fragment (`egress-stream.ts`) and runs whole only when a match
106
- * settles; a policy the gate cannot read runs whole at every step. At the
107
- * end (`fragment` unset) every policy runs whole.
57
+ * The leaks of what is ours (canary, prompt echo) in the carry and this
58
+ * window that stop the reply. One set to `flag` is noted for the next
59
+ * release instead, once. The canary scan reads each character once
60
+ * (`createCanaryScanner`) and the echo check rereads only its own short
61
+ * lookback (`promptEchoScanFrom`), so a long reply costs time in proportion
62
+ * to its length, not its square.
108
63
  */
109
- async function policyHits(window, fragment) {
110
- if (!options.enforce) {
111
- return null;
112
- }
113
- if (stream && fragment !== undefined) {
114
- const hit = stream.push(fragment);
115
- return hit ? await streamHitVerdict(options.enforce, hit, window, context) : null;
64
+ function leakStops(fresh) {
65
+ const found = [];
66
+ if (scanner?.push(fresh))
67
+ found.push([canaryAction, CANARY_HIT]);
68
+ if (privateSystem) {
69
+ const scanned = echoed.length;
70
+ echoed += fresh;
71
+ const from = promptEchoScanFrom(echoed, scanned);
72
+ echoed = echoed.slice(from);
73
+ echoedFrom += from;
74
+ const [hit] = promptEchoHits(echoed, privateSystem, context.canary);
75
+ if (hit)
76
+ found.push([promptAction, hit]);
116
77
  }
117
- // Mid-stream the gate can only release or stop: emitted prefixes cannot be
118
- // rewritten, so `redact` stops here and end-of-attempt egress applies the
119
- // full verdict. `flag` is advisory and keeps the stream flowing.
120
- const verdict = await runEnforcer(options.enforce, { text: window }, context);
121
- if (verdict.action === 'block' || verdict.action === 'redact') {
122
- return verdict.hits.length > 0
123
- ? verdict.hits
124
- : [{ rule: EGRESS_RULES.blocked, severity: 'high' }];
78
+ for (const [action, hit] of found) {
79
+ if (action !== 'flag' || reported.has(hit.rule))
80
+ continue;
81
+ reported.add(hit.rule);
82
+ noted.push(hit);
125
83
  }
126
- return null;
84
+ return found.filter(([action]) => action !== 'flag').map(([, hit]) => hit);
127
85
  }
128
- async function scan(window, fragment) {
129
- // The system-prompt leak checks always run, under a host policy too: it adds
130
- // checks, it never replaces these (the guardrail invariant).
131
- const leaks = context.canary ? canaryWindowHits(fragment ?? '') : [];
132
- if (leaks.length > 0) {
133
- return leaks;
134
- }
135
- return await policyHits(window, fragment);
86
+ /** What stops the reply at this step: a leak of ours, read at the gate's boundary. */
87
+ function scan(fragment) {
88
+ const leaks = guarded ? leakStops(fragment ?? '') : [];
89
+ if (fragment)
90
+ detecting?.push(fragment);
91
+ if (leaks.length === 0)
92
+ return null;
93
+ return { hits: leaks, ...(reads ? { boundary: reads.boundary } : {}) };
136
94
  }
137
- /** Where the leak checks hold from: a canary opening, or words a prompt echo could grow from. */
95
+ /**
96
+ * Where the leak checks hold from: a canary opening, or words a prompt echo
97
+ * could grow from. A leak set to `flag` holds nothing: it is shown.
98
+ */
138
99
  function leakHoldFrom() {
139
- if (!context.canary) {
140
- return accumulated.length;
141
- }
142
- const echo = context.privateSystem
143
- ? echoHoldFrom(context.privateSystem, context.canary)
100
+ const canary = token && canaryAction !== 'flag' ? canaryFrom(token) : held.length;
101
+ const echo = privateSystem && promptAction !== 'flag'
102
+ ? echoHoldFrom(privateSystem, context.canary)
144
103
  : held.length;
145
- return emitted + Math.min(canaryFrom(context.canary), echo);
104
+ return emitted + Math.min(canary, echo);
105
+ }
106
+ /** `result` with the leaks noted since the last release reported in it. */
107
+ function withNoted(result) {
108
+ if (noted.length === 0)
109
+ return result;
110
+ const hits = [...noted, ...(result.found?.hits ?? [])];
111
+ noted = [];
112
+ return { ...result, found: { action: result.found?.action ?? 'flag', hits } };
146
113
  }
147
114
  /** `canaryHoldFrom` on the held text, read from where an opening could start. */
148
115
  function canaryFrom(canary) {
@@ -151,7 +118,7 @@ function createProgressiveYieldGate(options) {
151
118
  const lead = Math.max(openingBase, from - RELEASED_LOOKBACK);
152
119
  let at = lead + canaryOpeningFrom(opening.slice(lead - openingBase), canary);
153
120
  if (at < from && from > shownTo) {
154
- // An opening the bound rules out: read the held text whole, and from there on.
121
+ // why: An opening the bound rules out: read the held text whole, and from there on.
155
122
  opening = released + held;
156
123
  openingBase = shownTo - released.length;
157
124
  at = openingBase + canaryOpeningFrom(opening, canary);
@@ -164,74 +131,151 @@ function createProgressiveYieldGate(options) {
164
131
  }
165
132
  /** `promptEchoHoldFrom` on the held text, read from its last few words. */
166
133
  function echoHoldFrom(privateSystem, canary) {
167
- // Until this window releases anything, its opening may continue the carry.
134
+ // why: Until this window releases anything, its opening may continue the carry.
168
135
  const lead = emitted === 0 ? carry : '';
169
136
  const leadFrom = carry.length + emitted - lead.length;
170
137
  const [text, from] = echoedFrom >= leadFrom ? [echoed, echoedFrom] : [lead + held, leadFrom];
171
138
  return Math.max(0, from + promptEchoHoldFrom(text, privateSystem, canary) - carry.length - emitted);
172
139
  }
173
- /** Where the host policy holds from: exactly for the bundled one, a fixed lookback otherwise. */
174
- function policyHoldFrom() {
175
- if (stream) {
176
- return stream.holdFrom();
140
+ function release(fragment) {
141
+ const stop = scan(fragment);
142
+ if (stop) {
143
+ return { blocked: true, ...stop };
177
144
  }
178
- const hold = options.enforce ? holdbackForWindow(accumulated, baseHoldback) : baseHoldback;
179
- return accumulated.length - hold;
180
- }
181
- async function release(fragment) {
182
- const hits = await scan(accumulated, fragment);
183
- if (hits) {
184
- return { blocked: true, hits };
145
+ const ended = fragment === undefined;
146
+ const end = ended
147
+ ? accumulated.length
148
+ : Math.min(leakHoldFrom(), detecting?.holdFrom() ?? accumulated.length);
149
+ const length = Math.max(0, end - emitted);
150
+ if (!(reads && detecting)) {
151
+ return withNoted({ blocked: false, emit: take(length) });
152
+ }
153
+ const read = detecting.take(emitted, emitted + length, ended);
154
+ if (read.action === 'block' || (read.action === 'redact' && !reads.rewrite)) {
155
+ return { blocked: true, hits: read.hits, boundary: reads.boundary };
185
156
  }
186
- const end = fragment === undefined ? accumulated.length : Math.min(leakHoldFrom(), policyHoldFrom());
187
- const emit = take(Math.max(0, end - emitted));
188
- return { blocked: false, emit };
157
+ take(read.taken);
158
+ return withNoted({
159
+ blocked: false,
160
+ emit: read.text ?? '',
161
+ ...(read.action === 'allow' ? {} : { found: { action: read.action, hits: read.hits } }),
162
+ });
189
163
  }
190
- /** Release the first `length` characters held. */
164
+ /** Release the first `length` characters held, as written. */
191
165
  function take(length) {
192
166
  const emit = held.slice(0, length);
193
167
  held = held.slice(length);
194
168
  emitted += emit.length;
195
- if (context.canary)
169
+ if (guarded)
196
170
  released = (released + emit).slice(-RELEASED_LOOKBACK);
197
171
  return emit;
198
172
  }
199
173
  return {
200
- async process(fragment) {
174
+ process(fragment) {
201
175
  if (!fragment) {
202
176
  return { blocked: false, emit: '' };
203
177
  }
204
178
  accumulated += fragment;
205
179
  held += fragment;
206
- if (context.canary)
180
+ if (guarded)
207
181
  opening += fragment;
208
- return await release(fragment);
209
- },
210
- async flush() {
211
- return await release();
182
+ return release(fragment);
212
183
  },
184
+ flush: () => release(),
213
185
  accumulated: () => accumulated,
214
186
  unreleased: () => held,
215
187
  drainUnreleased: () => take(held.length),
216
- carryOut: () => context.canary
217
- ? promptLeakCarry(carry + accumulated, context.canary, context.privateSystem)
218
- : '',
188
+ carryOut: () => (guarded ? promptLeakCarry(carry + accumulated, token, privateSystem) : ''),
219
189
  };
220
190
  }
221
191
  /**
222
- * Shared constructor for runTurn + Live: gate when canary and/or egress.enforce
223
- * is active. `context.canary` is set only when the profile enabled canary minting.
192
+ * Whether a reply read at `boundaries` gets a verdict once it has ended: a
193
+ * detector reads one of them. A gate that stops such a reply withholds it for
194
+ * that verdict.
195
+ */
196
+ function replyIsJudged(policy, boundaries, scope) {
197
+ return detectReads(boundaries, policy.detect, scope);
198
+ }
199
+ /**
200
+ * Shared constructor for runTurn + Live: a gate when a detector reads
201
+ * `boundary`. `context.canary` is set only while `canary_leak` is above
202
+ * `ignore` somewhere, and `context.privateSystem` while `prompt_leak` is.
224
203
  */
225
- function createOutboundProgressiveGate(policy, context, carry) {
226
- const egress = policy.egress;
227
- if (!egress?.enforce && !context.canary) {
204
+ async function createOutboundProgressiveGate(policy, context, boundary, carry) {
205
+ if (!replyIsJudged(policy, [boundary], context))
206
+ return null;
207
+ await loadEgressAutomata();
208
+ return outboundProgressiveGate(policy, context, boundary, carry);
209
+ }
210
+ /** `createOutboundProgressiveGate`, once the automata are loaded. */
211
+ function outboundProgressiveGate(policy, context, boundary, carry) {
212
+ if (!replyIsJudged(policy, [boundary], context)) {
228
213
  return null;
229
214
  }
230
- return createProgressiveYieldGate({
215
+ return progressiveYieldGate({
231
216
  context,
232
- ...(egress?.enforce ? { enforce: egress.enforce } : {}),
233
- ...(egress?.holdback === undefined ? {} : { holdback: egress.holdback }),
217
+ detect: {
218
+ matrix: policy.detect,
219
+ boundary,
220
+ rewrite: boundary === 'reply',
221
+ scope: scopeOf(policy, context),
222
+ },
234
223
  ...(carry ? { carry } : {}),
235
224
  });
236
225
  }
237
- export { createOutboundProgressiveGate, createProgressiveYieldGate, DEFAULT_HOLDBACK, LIVE_DEFAULT_HOLDBACK, };
226
+ /**
227
+ * A gate for a draft read at `boundary`, where the whole it previews is read before the host sees
228
+ * it: a tool call the model is still writing, a tool's output as the tool writes it, or a
229
+ * structured reply's JSON as the model writes it. It never
230
+ * rewrites: a match the whole's check would replace or stop stops the draft instead, because the
231
+ * host gets the whole only as that check leaves it. `scope` is what that check reads against;
232
+ * left out, the turn's (`scopeOf`).
233
+ */
234
+ async function createDraftGate(policy, context, boundary, scope) {
235
+ if (!replyIsJudged(policy, [boundary], scope ?? context))
236
+ return null;
237
+ await loadEgressAutomata();
238
+ return progressiveYieldGate({
239
+ context,
240
+ detect: {
241
+ matrix: policy.detect,
242
+ boundary,
243
+ rewrite: false,
244
+ scope: scope ?? scopeOf(policy, context),
245
+ },
246
+ });
247
+ }
248
+ /**
249
+ * One stream of drafts read through one draft gate, opened on the first draft. A match stops
250
+ * the rest of the stream; with no gate (nothing is judged there), every draft passes as is.
251
+ */
252
+ class DraftReader {
253
+ open;
254
+ gate;
255
+ constructor(open) {
256
+ this.open = open;
257
+ }
258
+ /** What of `text` may be shown now: empty while the gate holds it, or once a match stopped the stream. */
259
+ async read(text) {
260
+ if (this.gate === undefined)
261
+ this.gate = await this.open();
262
+ if (this.gate === 'stopped')
263
+ return '';
264
+ if (!this.gate)
265
+ return text;
266
+ const result = this.gate.process(text);
267
+ if (result.blocked) {
268
+ this.gate = 'stopped';
269
+ return '';
270
+ }
271
+ return result.emit;
272
+ }
273
+ /** The tail the gate still holds, once the stream has ended. */
274
+ end() {
275
+ if (!this.gate || this.gate === 'stopped')
276
+ return '';
277
+ const result = this.gate.flush();
278
+ return result.blocked ? '' : result.emit;
279
+ }
280
+ }
281
+ export { createDraftGate, createOutboundProgressiveGate, createProgressiveYieldGate, DraftReader, outboundProgressiveGate, replyIsJudged, };
@@ -8,8 +8,10 @@
8
8
  * not read, and no run reaches across it. Words are
9
9
  * compared case-folded after Unicode compatibility folding, punctuation and
10
10
  * markup between them ignored, and bare numbers skipped, so reformatting a
11
- * dump as a numbered or bulleted list does not hide it. Where the prompt has
12
- * the canary, any one word or none continues a run: a model told to hide the
11
+ * dump as a numbered or bulleted list does not hide it. Nor does encoding it:
12
+ * the prompt is also read backwards and in rot13, and both it and the reply
13
+ * with leetspeak decoded. Where the prompt has
14
+ * the canary, any one word, or none continues a run: a model told to hide the
13
15
  * canary echoes the prompt around a stand-in for it. A streamed reply holds
14
16
  * the words an echo could still grow from (`promptEchoHoldFrom`), so none of
15
17
  * an echo reaches the host.
@@ -8,14 +8,17 @@
8
8
  * not read, and no run reaches across it. Words are
9
9
  * compared case-folded after Unicode compatibility folding, punctuation and
10
10
  * markup between them ignored, and bare numbers skipped, so reformatting a
11
- * dump as a numbered or bulleted list does not hide it. Where the prompt has
12
- * the canary, any one word or none continues a run: a model told to hide the
11
+ * dump as a numbered or bulleted list does not hide it. Nor does encoding it:
12
+ * the prompt is also read backwards and in rot13, and both it and the reply
13
+ * with leetspeak decoded. Where the prompt has
14
+ * the canary, any one word, or none continues a run: a model told to hide the
13
15
  * canary echoes the prompt around a stand-in for it. A streamed reply holds
14
16
  * the words an echo could still grow from (`promptEchoHoldFrom`), so none of
15
17
  * an echo reaches the host.
16
18
  *
17
19
  * @module
18
20
  */
21
+ import { LEET_MAP, tryRot13 } from './injection.js';
19
22
  /** Consecutive system-prompt words that make a reply an echo of it. */
20
23
  const PROMPT_ECHO_WORDS = 12;
21
24
  /** Words a scan rereads before new text: an echo run ending in it starts no earlier. */
@@ -40,10 +43,30 @@ function echoWords(text) {
40
43
  /** Where the canary stood in the prompt's words: any one word or none matches it. */
41
44
  const SLOT = '\u0000';
42
45
  /**
43
- * The private stretches' words as a run can repeat them: as written, with the
44
- * canary left out, and with the canary as `SLOT`.
46
+ * The prompt as a reply can encode it: written backwards, by code point, in
47
+ * rot13, or as the decoded leetspeak reply reads it.
48
+ */
49
+ const PROMPT_VIEWS = [
50
+ (text) => text,
51
+ (text) => [...text].reverse().join(''),
52
+ tryRot13,
53
+ decodeLeet,
54
+ ];
55
+ /**
56
+ * The private stretches' words as a run can repeat them, in each of
57
+ * `PROMPT_VIEWS`: as written, with the canary left out, and with the canary
58
+ * as `SLOT`.
45
59
  */
46
60
  function promptReadings(stretches, canary) {
61
+ const readings = { plain: [], slotted: [] };
62
+ for (const view of PROMPT_VIEWS) {
63
+ const read = viewReadings(stretches.map(view), canary === undefined ? undefined : view(canary));
64
+ readings.plain.push(...read.plain);
65
+ readings.slotted.push(...read.slotted);
66
+ }
67
+ return readings;
68
+ }
69
+ function viewReadings(stretches, canary) {
47
70
  const token = canary ? echoWords(canary).map((entry) => entry.word) : [];
48
71
  const readings = { plain: [], slotted: [] };
49
72
  for (const stretch of stretches) {
@@ -71,7 +94,7 @@ function promptReadings(stretches, canary) {
71
94
  }
72
95
  /** A run with a slot, keyed by where the slot is and the words around it. */
73
96
  function slotKey(run, slot) {
74
- // Bare numbers are never words here, so the slot's index leads unambiguously.
97
+ // why: Bare numbers are never words here, so the slot's index leads unambiguously.
75
98
  return [slot, ...run.filter((_, k) => k !== slot)].join(' ');
76
99
  }
77
100
  /** A run may not start on the canary's place unless `leading`: a stand-in for it is not prompt text. */
@@ -164,7 +187,20 @@ function mayBecomePromptWord(partial, shape) {
164
187
  * word. Any echo that completes later starts there or after.
165
188
  */
166
189
  function promptEchoHoldFrom(text, stretches, canary) {
190
+ for (let reach = TAIL_REACH;; reach *= 2) {
191
+ const start = decodableFrom(text, text.length - reach);
192
+ const holds = replyViews(text.slice(start)).map((view) => holdFrom(view, stretches, canary));
193
+ if (start === 0 || holds.every(({ tail }) => tail > 0)) {
194
+ return start + Math.min(...holds.map(({ hold }) => hold));
195
+ }
196
+ }
197
+ }
198
+ /** The hold in `text`, and where the words it was read from start: at 0, `text` may be too short a tail. */
199
+ function holdFrom(text, stretches, canary) {
167
200
  const tail = promptEchoScanFrom(text, text.length);
201
+ return { hold: holdIn(text, tail, stretches, canary), tail };
202
+ }
203
+ function holdIn(text, tail, stretches, canary) {
168
204
  const words = echoWords(text.slice(tail));
169
205
  let writing = text.length;
170
206
  while (writing > 0 && WORD_CHAR.test(text.charAt(writing - 1)))
@@ -180,8 +216,39 @@ function promptEchoHoldFrom(text, stretches, canary) {
180
216
  }
181
217
  return hold;
182
218
  }
219
+ /** A leetspeak letter, or a list number that stays one; `!` only before a word goes on. */
220
+ const LEET = /(?<=^|\n)[ \t]*\p{N}+[.)]|[0-9@]|!(?=[\p{L}\p{N}@])/gu;
221
+ /** How far back a tail is first read from; a tail with too few words in it is doubled. */
222
+ const TAIL_REACH = 512;
223
+ const LIST_NUMBER_CHAR = /[ \t\p{N}]/u;
224
+ const NUMBER_CHAR = /\p{N}/u;
225
+ /**
226
+ * A start at or before `at` from which `text` decodes as it does whole: a
227
+ * list number is one from its line's start, so the start is no later than the
228
+ * character before the blanks and digits leading up to `at`.
229
+ */
230
+ function decodableFrom(text, at) {
231
+ let start = Math.max(0, at);
232
+ while (start > 0 && LIST_NUMBER_CHAR.test(text.charAt(start - 1)))
233
+ start--;
234
+ return Math.max(0, start - 1);
235
+ }
236
+ /** `text` with its leetspeak decoded, letter for letter, so offsets keep. */
237
+ function decodeLeet(text) {
238
+ return text.replace(LEET, (match) => (match.length === 1 ? (LEET_MAP[match] ?? match) : match));
239
+ }
240
+ /** The reply as written and with its leetspeak decoded. */
241
+ function replyViews(text) {
242
+ const decoded = decodeLeet(text);
243
+ return decoded === text ? [text] : [text, decoded];
244
+ }
183
245
  /** Offsets `[start, end)` of `text` that repeat a private stretch, ordered by start. */
184
246
  function promptEchoRanges(text, stretches, canary) {
247
+ return replyViews(text)
248
+ .flatMap((view) => echoRanges(view, stretches, canary))
249
+ .sort((a, b) => a[0] - b[0]);
250
+ }
251
+ function echoRanges(text, stretches, canary) {
185
252
  const grams = promptGrams(stretches, canary);
186
253
  if (!text || grams.plain.size === 0) {
187
254
  return [];
@@ -193,7 +260,7 @@ function promptEchoRanges(text, stretches, canary) {
193
260
  const slot = matchRun(grams, run);
194
261
  if (slot === undefined)
195
262
  continue;
196
- // A stand-in for the canary at either end is the model's, not the prompt's.
263
+ // why: A stand-in for the canary at either end is the model's, not the prompt's.
197
264
  const first = slot === 0 ? from + 1 : from;
198
265
  const last = slot === PROMPT_ECHO_WORDS - 1 ? from + slot - 1 : from + PROMPT_ECHO_WORDS - 1;
199
266
  ranges.push([words[first]?.at ?? 0, words[last]?.to ?? 0]);
@@ -210,6 +277,20 @@ function scanTextForPromptEcho(text, stretches, canary) {
210
277
  * start in.
211
278
  */
212
279
  function promptEchoScanFrom(text, from) {
280
+ const end = Math.min(from, text.length);
281
+ for (let reach = TAIL_REACH;; reach *= 2) {
282
+ const start = decodableFrom(text, end - reach);
283
+ // why: What follows `end` decides how the tail's last characters read: a `!` by the next one, digits by the list number they may be.
284
+ let stop = end;
285
+ while (stop < text.length && NUMBER_CHAR.test(text.charAt(stop)))
286
+ stop++;
287
+ const tail = text.slice(start, stop + 1);
288
+ const at = Math.min(...replyViews(tail).map((view) => scanFrom(view, end - start)));
289
+ if (start === 0 || at > 0)
290
+ return start + at;
291
+ }
292
+ }
293
+ function scanFrom(text, from) {
213
294
  let at = Math.min(from, text.length);
214
295
  for (let counted = 0; counted < ECHO_LOOKBACK_WORDS && at > 0;) {
215
296
  while (at > 0 && !WORD_CHAR.test(text.charAt(at - 1)))
@@ -1,5 +1,6 @@
1
1
  import type { Profile } from '../kernel/types.js';
2
2
  import { TheoremError } from './theorem-error.js';
3
+ /** What taking a quota slot returned: `ok` (reserved), `busy` (a turn already holds the slot), `quota` (the day's limit is used) or `not_configured` (the profile sets no quota). */
3
4
  type QuotaSlotStatus = 'ok' | 'busy' | 'quota' | 'not_configured';
4
5
  /** Returns whether a local request lacks the proxy header needed for quota identity. */
5
6
  declare function skipQuota(peer: string, req: Request): boolean;
@@ -70,7 +70,7 @@ function quotaExhausted(profile) {
70
70
  if (!quota) {
71
71
  return undefined;
72
72
  }
73
- return new TheoremError('rate_limit', `${profile.id} used its daily quota of ${quota.perDay} turns`, // lexicon-exempt: internal diagnostic; the user reads the copy key
73
+ return new TheoremError('rate_limit', `${profile.id} used its daily quota of ${quota.perDay} turns`, // labels-exempt: internal diagnostic; the user reads the copy key
74
74
  { copy: { key: 'quota.exhausted', params: { perDay: quota.perDay } } });
75
75
  }
76
76
  /** Clears all process-local quota counters; intended for tests or host resets. */