@theoremjs/agents 0.0.0-stage → 0.3.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (514) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +1264 -2
  3. package/esm/_dnt.polyfills.d.ts +66 -0
  4. package/esm/_dnt.polyfills.js +51 -0
  5. package/esm/mod.d.ts +65 -0
  6. package/esm/mod.js +42 -0
  7. package/esm/package.json +3 -0
  8. package/esm/src/cli/bin.d.ts +7 -0
  9. package/esm/src/cli/bin.js +9 -0
  10. package/esm/src/cli/commands/bench.d.ts +6 -0
  11. package/esm/src/cli/commands/bench.js +458 -0
  12. package/esm/src/cli/commands/egress-compile.d.ts +17 -0
  13. package/esm/src/cli/commands/egress-compile.js +25 -0
  14. package/esm/src/cli/commands/eval.d.ts +37 -0
  15. package/esm/src/cli/commands/eval.js +190 -0
  16. package/esm/src/cli/commands/fuzz-canary.d.ts +15 -0
  17. package/esm/src/cli/commands/fuzz-canary.js +202 -0
  18. package/esm/src/cli/commands/fuzz-guardrails.d.ts +2 -0
  19. package/esm/src/cli/commands/fuzz-guardrails.js +5 -0
  20. package/esm/src/cli/commands/profile.d.ts +2 -0
  21. package/esm/src/cli/commands/profile.js +80 -0
  22. package/esm/src/cli/commands/run.d.ts +13 -0
  23. package/esm/src/cli/commands/run.js +45 -0
  24. package/esm/src/cli/commands/test.d.ts +25 -0
  25. package/esm/src/cli/commands/test.js +143 -0
  26. package/esm/src/cli/event-log.d.ts +15 -0
  27. package/esm/src/cli/event-log.js +136 -0
  28. package/esm/src/cli/index.d.ts +10 -0
  29. package/esm/src/cli/index.js +267 -0
  30. package/esm/src/cli/matrix/fixtures.d.ts +10 -0
  31. package/esm/src/cli/matrix/fixtures.js +72 -0
  32. package/esm/src/cli/matrix/synthesizer.d.ts +18 -0
  33. package/esm/src/cli/matrix/synthesizer.js +103 -0
  34. package/esm/src/evals/attachments.d.ts +4 -0
  35. package/esm/src/evals/attachments.js +53 -0
  36. package/esm/src/evals/breakdown.d.ts +28 -0
  37. package/esm/src/evals/breakdown.js +68 -0
  38. package/esm/src/evals/graders/answer.d.ts +13 -0
  39. package/esm/src/evals/graders/answer.js +133 -0
  40. package/esm/src/evals/graders/code.d.ts +64 -0
  41. package/esm/src/evals/graders/code.js +205 -0
  42. package/esm/src/evals/graders/judge.d.ts +20 -0
  43. package/esm/src/evals/graders/judge.js +365 -0
  44. package/esm/src/evals/graders/latency.d.ts +5 -0
  45. package/esm/src/evals/graders/latency.js +81 -0
  46. package/esm/src/evals/graders/live.d.ts +11 -0
  47. package/esm/src/evals/graders/live.js +40 -0
  48. package/esm/src/evals/graders/media.d.ts +18 -0
  49. package/esm/src/evals/graders/media.js +92 -0
  50. package/esm/src/evals/graders/shared.d.ts +11 -0
  51. package/esm/src/evals/graders/shared.js +62 -0
  52. package/esm/src/evals/graders/transcript.d.ts +17 -0
  53. package/esm/src/evals/graders/transcript.js +200 -0
  54. package/esm/src/evals/mod.d.ts +42 -0
  55. package/esm/src/evals/mod.js +30 -0
  56. package/esm/src/evals/record.d.ts +35 -0
  57. package/esm/src/evals/record.js +105 -0
  58. package/esm/src/evals/rubrics/catalog.d.ts +148 -0
  59. package/esm/src/evals/rubrics/catalog.js +846 -0
  60. package/esm/src/evals/rubrics/mod.d.ts +24 -0
  61. package/esm/src/evals/rubrics/mod.js +55 -0
  62. package/esm/src/evals/rubrics/mustache.d.ts +23 -0
  63. package/esm/src/evals/rubrics/mustache.js +154 -0
  64. package/esm/src/evals/rubrics/types.d.ts +54 -0
  65. package/esm/src/evals/rubrics/types.js +74 -0
  66. package/esm/src/evals/run.d.ts +118 -0
  67. package/esm/src/evals/run.js +452 -0
  68. package/esm/src/evals/suite.d.ts +19 -0
  69. package/esm/src/evals/suite.js +92 -0
  70. package/esm/src/evals/summary.d.ts +32 -0
  71. package/esm/src/evals/summary.js +30 -0
  72. package/esm/src/evals/trial.d.ts +27 -0
  73. package/esm/src/evals/trial.js +158 -0
  74. package/esm/src/evals/types.d.ts +260 -0
  75. package/esm/src/evals/types.js +126 -0
  76. package/esm/src/evals/verdict.d.ts +18 -0
  77. package/esm/src/evals/verdict.js +45 -0
  78. package/esm/src/guardrails/canary-gate.d.ts +21 -0
  79. package/esm/src/guardrails/canary-gate.js +40 -0
  80. package/esm/src/guardrails/canary.d.ts +112 -0
  81. package/esm/src/guardrails/canary.js +901 -0
  82. package/esm/src/guardrails/compile-egress.d.ts +11 -0
  83. package/esm/src/guardrails/compile-egress.js +11 -0
  84. package/esm/src/guardrails/corpus/canary-egress-attacks.d.ts +22 -0
  85. package/esm/src/guardrails/corpus/canary-egress-attacks.js +303 -0
  86. package/esm/src/guardrails/corpus/fuzz-inbound.d.ts +5 -0
  87. package/esm/src/guardrails/corpus/fuzz-inbound.js +202 -0
  88. package/esm/src/guardrails/corpus/inbound-payloads.d.ts +3 -0
  89. package/esm/src/guardrails/corpus/inbound-payloads.js +118 -0
  90. package/esm/src/guardrails/corpus/live-attacks.d.ts +13 -0
  91. package/esm/src/guardrails/corpus/live-attacks.js +224 -0
  92. package/esm/src/guardrails/corpus/mod.d.ts +7 -0
  93. package/esm/src/guardrails/corpus/mod.js +4 -0
  94. package/esm/src/guardrails/corpus/secrets.d.ts +12 -0
  95. package/esm/src/guardrails/corpus/secrets.js +16 -0
  96. package/esm/src/guardrails/corpus/strings.d.ts +23 -0
  97. package/esm/src/guardrails/corpus/strings.js +29 -0
  98. package/esm/src/guardrails/corpus/types.d.ts +32 -0
  99. package/esm/src/guardrails/corpus/types.js +1 -0
  100. package/esm/src/guardrails/egress-automata.d.ts +14 -0
  101. package/esm/src/guardrails/egress-automata.js +6059 -0
  102. package/esm/src/guardrails/egress-compiler.d.ts +33 -0
  103. package/esm/src/guardrails/egress-compiler.js +237 -0
  104. package/esm/src/guardrails/egress-patterns.d.ts +24 -0
  105. package/esm/src/guardrails/egress-patterns.js +32 -0
  106. package/esm/src/guardrails/egress-policy.d.ts +27 -0
  107. package/esm/src/guardrails/egress-policy.js +76 -0
  108. package/esm/src/guardrails/egress-rules.d.ts +54 -0
  109. package/esm/src/guardrails/egress-rules.js +49 -0
  110. package/esm/src/guardrails/egress-stream.d.ts +105 -0
  111. package/esm/src/guardrails/egress-stream.js +645 -0
  112. package/esm/src/guardrails/egress-urls.d.ts +83 -0
  113. package/esm/src/guardrails/egress-urls.js +917 -0
  114. package/esm/src/guardrails/egress.d.ts +106 -0
  115. package/esm/src/guardrails/egress.js +374 -0
  116. package/esm/src/guardrails/error.d.ts +26 -0
  117. package/esm/src/guardrails/error.js +91 -0
  118. package/esm/src/guardrails/event-schemas.d.ts +57 -0
  119. package/esm/src/guardrails/event-schemas.js +41 -0
  120. package/esm/src/guardrails/events.d.ts +9 -0
  121. package/esm/src/guardrails/events.js +42 -0
  122. package/esm/src/guardrails/hits.d.ts +8 -0
  123. package/esm/src/guardrails/hits.js +19 -0
  124. package/esm/src/guardrails/injection-patterns.d.ts +15 -0
  125. package/esm/src/guardrails/injection-patterns.js +94 -0
  126. package/esm/src/guardrails/injection.d.ts +14 -0
  127. package/esm/src/guardrails/injection.js +237 -0
  128. package/esm/src/guardrails/lexicon.d.ts +30 -0
  129. package/esm/src/guardrails/lexicon.js +478 -0
  130. package/esm/src/guardrails/live-outbound-gate.d.ts +54 -0
  131. package/esm/src/guardrails/live-outbound-gate.js +305 -0
  132. package/esm/src/guardrails/mod.d.ts +46 -0
  133. package/esm/src/guardrails/mod.js +29 -0
  134. package/esm/src/guardrails/network.d.ts +42 -0
  135. package/esm/src/guardrails/network.js +328 -0
  136. package/esm/src/guardrails/normalize.d.ts +6 -0
  137. package/esm/src/guardrails/normalize.js +132 -0
  138. package/esm/src/guardrails/policy.d.ts +19 -0
  139. package/esm/src/guardrails/policy.js +50 -0
  140. package/esm/src/guardrails/progressive-yield.d.ts +69 -0
  141. package/esm/src/guardrails/progressive-yield.js +237 -0
  142. package/esm/src/guardrails/prompt-echo.d.ts +38 -0
  143. package/esm/src/guardrails/prompt-echo.js +225 -0
  144. package/esm/src/guardrails/quota.d.ts +20 -0
  145. package/esm/src/guardrails/quota.js +80 -0
  146. package/esm/src/guardrails/rules.d.ts +56 -0
  147. package/esm/src/guardrails/rules.js +54 -0
  148. package/esm/src/guardrails/sanitize.d.ts +23 -0
  149. package/esm/src/guardrails/sanitize.js +184 -0
  150. package/esm/src/guardrails/sensitive.d.ts +29 -0
  151. package/esm/src/guardrails/sensitive.js +113 -0
  152. package/esm/src/guardrails/serialize.d.ts +14 -0
  153. package/esm/src/guardrails/serialize.js +37 -0
  154. package/esm/src/guardrails/testing.d.ts +9 -0
  155. package/esm/src/guardrails/testing.js +8 -0
  156. package/esm/src/guardrails/theorem-error.d.ts +18 -0
  157. package/esm/src/guardrails/theorem-error.js +53 -0
  158. package/esm/src/guardrails/thought-guard.d.ts +55 -0
  159. package/esm/src/guardrails/thought-guard.js +464 -0
  160. package/esm/src/guardrails/tool-directives.d.ts +19 -0
  161. package/esm/src/guardrails/tool-directives.js +109 -0
  162. package/esm/src/guardrails/tool-result.d.ts +61 -0
  163. package/esm/src/guardrails/tool-result.js +248 -0
  164. package/esm/src/guardrails/types.d.ts +242 -0
  165. package/esm/src/guardrails/types.js +54 -0
  166. package/esm/src/host/client-turn.d.ts +9 -0
  167. package/esm/src/host/client-turn.js +38 -0
  168. package/esm/src/host/mint-trace.d.ts +28 -0
  169. package/esm/src/host/mint-trace.js +59 -0
  170. package/esm/src/host/mod.d.ts +13 -0
  171. package/esm/src/host/mod.js +11 -0
  172. package/esm/src/host/readStreamingJsonStringField.d.ts +2 -0
  173. package/esm/src/host/readStreamingJsonStringField.js +68 -0
  174. package/esm/src/host/reply.d.ts +7 -0
  175. package/esm/src/host/reply.js +35 -0
  176. package/esm/src/interface/blocks.d.ts +8 -0
  177. package/esm/src/interface/blocks.js +213 -0
  178. package/esm/src/interface/composer-actions.d.ts +20 -0
  179. package/esm/src/interface/composer-actions.js +31 -0
  180. package/esm/src/interface/draft.d.ts +14 -0
  181. package/esm/src/interface/draft.js +28 -0
  182. package/esm/src/interface/from-profile.d.ts +12 -0
  183. package/esm/src/interface/from-profile.js +144 -0
  184. package/esm/src/interface/history.d.ts +40 -0
  185. package/esm/src/interface/history.js +269 -0
  186. package/esm/src/interface/inputs.d.ts +10 -0
  187. package/esm/src/interface/inputs.js +64 -0
  188. package/esm/src/interface/mod.d.ts +31 -0
  189. package/esm/src/interface/mod.js +21 -0
  190. package/esm/src/interface/models.d.ts +19 -0
  191. package/esm/src/interface/models.js +45 -0
  192. package/esm/src/interface/pending.d.ts +48 -0
  193. package/esm/src/interface/pending.js +146 -0
  194. package/esm/src/interface/profile-interface.d.ts +4 -0
  195. package/esm/src/interface/profile-interface.js +223 -0
  196. package/esm/src/interface/session.d.ts +64 -0
  197. package/esm/src/interface/session.js +121 -0
  198. package/esm/src/interface/tool-calls.d.ts +20 -0
  199. package/esm/src/interface/tool-calls.js +73 -0
  200. package/esm/src/interface/tool-invoke.d.ts +4 -0
  201. package/esm/src/interface/tool-invoke.js +20 -0
  202. package/esm/src/interface/tool-media.d.ts +9 -0
  203. package/esm/src/interface/tool-media.js +112 -0
  204. package/esm/src/interface/types.d.ts +213 -0
  205. package/esm/src/interface/types.js +4 -0
  206. package/esm/src/kernel/auth/credential-source.d.ts +23 -0
  207. package/esm/src/kernel/auth/credential-source.js +11 -0
  208. package/esm/src/kernel/auth/crypto.d.ts +51 -0
  209. package/esm/src/kernel/auth/crypto.js +161 -0
  210. package/esm/src/kernel/auth/mod.d.ts +5 -0
  211. package/esm/src/kernel/auth/mod.js +5 -0
  212. package/esm/src/kernel/auth/oauth.d.ts +17 -0
  213. package/esm/src/kernel/auth/oauth.js +438 -0
  214. package/esm/src/kernel/auth/scope-refusal.d.ts +9 -0
  215. package/esm/src/kernel/auth/scope-refusal.js +8 -0
  216. package/esm/src/kernel/auth/typed-secret.d.ts +13 -0
  217. package/esm/src/kernel/auth/typed-secret.js +23 -0
  218. package/esm/src/kernel/auth/types.d.ts +139 -0
  219. package/esm/src/kernel/auth/types.js +1 -0
  220. package/esm/src/kernel/default-scope.d.ts +34 -0
  221. package/esm/src/kernel/default-scope.js +72 -0
  222. package/esm/src/kernel/engine/compaction.d.ts +70 -0
  223. package/esm/src/kernel/engine/compaction.js +202 -0
  224. package/esm/src/kernel/engine/decision.d.ts +41 -0
  225. package/esm/src/kernel/engine/decision.js +412 -0
  226. package/esm/src/kernel/engine/hash.d.ts +6 -0
  227. package/esm/src/kernel/engine/hash.js +22 -0
  228. package/esm/src/kernel/engine/live-inbound.d.ts +9 -0
  229. package/esm/src/kernel/engine/live-inbound.js +19 -0
  230. package/esm/src/kernel/engine/live-ingress.d.ts +9 -0
  231. package/esm/src/kernel/engine/live-ingress.js +37 -0
  232. package/esm/src/kernel/engine/media-probe/audio.d.ts +7 -0
  233. package/esm/src/kernel/engine/media-probe/audio.js +342 -0
  234. package/esm/src/kernel/engine/media-probe/bytes.d.ts +6 -0
  235. package/esm/src/kernel/engine/media-probe/bytes.js +26 -0
  236. package/esm/src/kernel/engine/media-probe/image.d.ts +5 -0
  237. package/esm/src/kernel/engine/media-probe/image.js +171 -0
  238. package/esm/src/kernel/engine/media-probe/iso-bmff.d.ts +19 -0
  239. package/esm/src/kernel/engine/media-probe/iso-bmff.js +48 -0
  240. package/esm/src/kernel/engine/media-probe/matroska.d.ts +35 -0
  241. package/esm/src/kernel/engine/media-probe/matroska.js +226 -0
  242. package/esm/src/kernel/engine/media-probe/mp4.d.ts +22 -0
  243. package/esm/src/kernel/engine/media-probe/mp4.js +279 -0
  244. package/esm/src/kernel/engine/media-probe/opus.d.ts +4 -0
  245. package/esm/src/kernel/engine/media-probe/opus.js +23 -0
  246. package/esm/src/kernel/engine/media-probe/pdf.d.ts +5 -0
  247. package/esm/src/kernel/engine/media-probe/pdf.js +117 -0
  248. package/esm/src/kernel/engine/media-probe/video.d.ts +15 -0
  249. package/esm/src/kernel/engine/media-probe/video.js +49 -0
  250. package/esm/src/kernel/engine/record.d.ts +3 -0
  251. package/esm/src/kernel/engine/record.js +11 -0
  252. package/esm/src/kernel/engine/repair.d.ts +7 -0
  253. package/esm/src/kernel/engine/repair.js +36 -0
  254. package/esm/src/kernel/engine/runner/gates.d.ts +5 -0
  255. package/esm/src/kernel/engine/runner/gates.js +322 -0
  256. package/esm/src/kernel/engine/runner/mod.d.ts +15 -0
  257. package/esm/src/kernel/engine/runner/mod.js +574 -0
  258. package/esm/src/kernel/engine/runner/schema-validation.d.ts +14 -0
  259. package/esm/src/kernel/engine/runner/schema-validation.js +105 -0
  260. package/esm/src/kernel/engine/runner/stages.d.ts +28 -0
  261. package/esm/src/kernel/engine/runner/stages.js +48 -0
  262. package/esm/src/kernel/engine/runner/state.d.ts +76 -0
  263. package/esm/src/kernel/engine/runner/state.js +40 -0
  264. package/esm/src/kernel/engine/runner/steps.d.ts +14 -0
  265. package/esm/src/kernel/engine/runner/steps.js +360 -0
  266. package/esm/src/kernel/engine/runner/stream.d.ts +40 -0
  267. package/esm/src/kernel/engine/runner/stream.js +225 -0
  268. package/esm/src/kernel/engine/runner/usage.d.ts +45 -0
  269. package/esm/src/kernel/engine/runner/usage.js +150 -0
  270. package/esm/src/kernel/engine/session/mod.d.ts +31 -0
  271. package/esm/src/kernel/engine/session/mod.js +951 -0
  272. package/esm/src/kernel/engine/session/session-trace.d.ts +115 -0
  273. package/esm/src/kernel/engine/session/session-trace.js +489 -0
  274. package/esm/src/kernel/engine/token-estimate.d.ts +77 -0
  275. package/esm/src/kernel/engine/token-estimate.js +218 -0
  276. package/esm/src/kernel/engine/tool-trace.d.ts +58 -0
  277. package/esm/src/kernel/engine/tool-trace.js +131 -0
  278. package/esm/src/kernel/engine/tree.d.ts +2 -0
  279. package/esm/src/kernel/engine/tree.js +17 -0
  280. package/esm/src/kernel/engine/turn-trace.d.ts +118 -0
  281. package/esm/src/kernel/engine/turn-trace.js +863 -0
  282. package/esm/src/kernel/engine/usage.d.ts +30 -0
  283. package/esm/src/kernel/engine/usage.js +134 -0
  284. package/esm/src/kernel/interaction-parts.d.ts +10 -0
  285. package/esm/src/kernel/interaction-parts.js +22 -0
  286. package/esm/src/kernel/mod.d.ts +47 -0
  287. package/esm/src/kernel/mod.js +30 -0
  288. package/esm/src/kernel/profile-graph.d.ts +140 -0
  289. package/esm/src/kernel/profile-graph.js +151 -0
  290. package/esm/src/kernel/profile-presence.d.ts +9 -0
  291. package/esm/src/kernel/profile-presence.js +143 -0
  292. package/esm/src/kernel/profile-scope.d.ts +36 -0
  293. package/esm/src/kernel/profile-scope.js +262 -0
  294. package/esm/src/kernel/registry/attachments.d.ts +35 -0
  295. package/esm/src/kernel/registry/attachments.js +211 -0
  296. package/esm/src/kernel/registry/catalog.d.ts +19 -0
  297. package/esm/src/kernel/registry/catalog.js +78 -0
  298. package/esm/src/kernel/registry/ingress.d.ts +8 -0
  299. package/esm/src/kernel/registry/ingress.js +134 -0
  300. package/esm/src/kernel/registry/kernel-registry.d.ts +12 -0
  301. package/esm/src/kernel/registry/kernel-registry.js +8 -0
  302. package/esm/src/kernel/registry/profile-outputs.d.ts +3 -0
  303. package/esm/src/kernel/registry/profile-outputs.js +7 -0
  304. package/esm/src/kernel/registry/profiles.d.ts +92 -0
  305. package/esm/src/kernel/registry/profiles.js +698 -0
  306. package/esm/src/kernel/registry/provider-request.d.ts +6 -0
  307. package/esm/src/kernel/registry/provider-request.js +42 -0
  308. package/esm/src/kernel/registry/resolve.d.ts +14 -0
  309. package/esm/src/kernel/registry/resolve.js +237 -0
  310. package/esm/src/kernel/registry/schemas.d.ts +9 -0
  311. package/esm/src/kernel/registry/schemas.js +25 -0
  312. package/esm/src/kernel/registry/sole-model.d.ts +2 -0
  313. package/esm/src/kernel/registry/sole-model.js +4 -0
  314. package/esm/src/kernel/registry/system-prompt.d.ts +8 -0
  315. package/esm/src/kernel/registry/system-prompt.js +33 -0
  316. package/esm/src/kernel/registry/system-role.d.ts +3 -0
  317. package/esm/src/kernel/registry/system-role.js +9 -0
  318. package/esm/src/kernel/registry/vault.d.ts +13 -0
  319. package/esm/src/kernel/registry/vault.js +14 -0
  320. package/esm/src/kernel/schema.d.ts +172 -0
  321. package/esm/src/kernel/schema.js +653 -0
  322. package/esm/src/kernel/scope.d.ts +22 -0
  323. package/esm/src/kernel/scope.js +25 -0
  324. package/esm/src/kernel/stages.d.ts +141 -0
  325. package/esm/src/kernel/stages.js +388 -0
  326. package/esm/src/kernel/stop.d.ts +93 -0
  327. package/esm/src/kernel/stop.js +125 -0
  328. package/esm/src/kernel/system-parts.d.ts +26 -0
  329. package/esm/src/kernel/system-parts.js +98 -0
  330. package/esm/src/kernel/tools/activity-label.d.ts +16 -0
  331. package/esm/src/kernel/tools/activity-label.js +209 -0
  332. package/esm/src/kernel/tools/events.d.ts +51 -0
  333. package/esm/src/kernel/tools/events.js +149 -0
  334. package/esm/src/kernel/tools/execute.d.ts +64 -0
  335. package/esm/src/kernel/tools/execute.js +801 -0
  336. package/esm/src/kernel/tools/gate-answer.d.ts +50 -0
  337. package/esm/src/kernel/tools/gate-answer.js +54 -0
  338. package/esm/src/kernel/tools/harness.d.ts +16 -0
  339. package/esm/src/kernel/tools/harness.js +42 -0
  340. package/esm/src/kernel/tools/invoke.d.ts +10 -0
  341. package/esm/src/kernel/tools/invoke.js +129 -0
  342. package/esm/src/kernel/tools/mcp-sessions.d.ts +20 -0
  343. package/esm/src/kernel/tools/mcp-sessions.js +64 -0
  344. package/esm/src/kernel/tools/mod.d.ts +9 -0
  345. package/esm/src/kernel/tools/mod.js +6 -0
  346. package/esm/src/kernel/tools/model-text.d.ts +11 -0
  347. package/esm/src/kernel/tools/model-text.js +25 -0
  348. package/esm/src/kernel/tools/permission.d.ts +6 -0
  349. package/esm/src/kernel/tools/permission.js +38 -0
  350. package/esm/src/kernel/tools/project.d.ts +8 -0
  351. package/esm/src/kernel/tools/project.js +25 -0
  352. package/esm/src/kernel/tools/registry.d.ts +20 -0
  353. package/esm/src/kernel/tools/registry.js +84 -0
  354. package/esm/src/kernel/tools/remote.d.ts +110 -0
  355. package/esm/src/kernel/tools/remote.js +998 -0
  356. package/esm/src/kernel/tools/resolve.d.ts +28 -0
  357. package/esm/src/kernel/tools/resolve.js +259 -0
  358. package/esm/src/kernel/tools/schema.d.ts +10 -0
  359. package/esm/src/kernel/tools/schema.js +174 -0
  360. package/esm/src/kernel/tools/signed-in-fetch.d.ts +18 -0
  361. package/esm/src/kernel/tools/signed-in-fetch.js +45 -0
  362. package/esm/src/kernel/tools/stage-run.d.ts +93 -0
  363. package/esm/src/kernel/tools/stage-run.js +140 -0
  364. package/esm/src/kernel/tools/types.d.ts +287 -0
  365. package/esm/src/kernel/tools/types.js +1 -0
  366. package/esm/src/kernel/turn-events.d.ts +599 -0
  367. package/esm/src/kernel/turn-events.js +425 -0
  368. package/esm/src/kernel/types.d.ts +884 -0
  369. package/esm/src/kernel/types.js +1 -0
  370. package/esm/src/kernel/util/base64.d.ts +2 -0
  371. package/esm/src/kernel/util/base64.js +13 -0
  372. package/esm/src/kernel/util/exact-type.d.ts +31 -0
  373. package/esm/src/kernel/util/exact-type.js +1 -0
  374. package/esm/src/kernel/util/find-last.d.ts +3 -0
  375. package/esm/src/kernel/util/find-last.js +9 -0
  376. package/esm/src/kernel/util/mime.d.ts +2 -0
  377. package/esm/src/kernel/util/mime.js +4 -0
  378. package/esm/src/kernel/util/record.d.ts +1 -0
  379. package/esm/src/kernel/util/record.js +3 -0
  380. package/esm/src/observability/destinations.d.ts +9 -0
  381. package/esm/src/observability/destinations.js +38 -0
  382. package/esm/src/observability/jsonl.d.ts +18 -0
  383. package/esm/src/observability/jsonl.js +117 -0
  384. package/esm/src/observability/mod.d.ts +22 -0
  385. package/esm/src/observability/mod.js +16 -0
  386. package/esm/src/observability/openinference.d.ts +11 -0
  387. package/esm/src/observability/openinference.js +205 -0
  388. package/esm/src/observability/otlp.d.ts +68 -0
  389. package/esm/src/observability/otlp.js +98 -0
  390. package/esm/src/observability/phoenix.d.ts +29 -0
  391. package/esm/src/observability/phoenix.js +71 -0
  392. package/esm/src/observability/policy.d.ts +14 -0
  393. package/esm/src/observability/policy.js +69 -0
  394. package/esm/src/observability/resolve-policy.d.ts +8 -0
  395. package/esm/src/observability/resolve-policy.js +58 -0
  396. package/esm/src/observability/spans.d.ts +16 -0
  397. package/esm/src/observability/spans.js +56 -0
  398. package/esm/src/observability/trace-catalog.d.ts +111 -0
  399. package/esm/src/observability/trace-catalog.js +865 -0
  400. package/esm/src/observability/trace-record.d.ts +23 -0
  401. package/esm/src/observability/trace-record.js +223 -0
  402. package/esm/src/observability/trace-schema.d.ts +54 -0
  403. package/esm/src/observability/trace-schema.js +59 -0
  404. package/esm/src/observability/trace-sink.d.ts +13 -0
  405. package/esm/src/observability/trace-sink.js +3 -0
  406. package/esm/src/observability/trace-span.d.ts +92 -0
  407. package/esm/src/observability/trace-span.js +199 -0
  408. package/esm/src/observability/trace.d.ts +11 -0
  409. package/esm/src/observability/trace.js +35 -0
  410. package/esm/src/observability/types.d.ts +85 -0
  411. package/esm/src/observability/types.js +3 -0
  412. package/esm/src/presets/google/speech-voices.d.ts +8 -0
  413. package/esm/src/presets/google/speech-voices.js +38 -0
  414. package/esm/src/presets/google-limits.d.ts +12 -0
  415. package/esm/src/presets/google-limits.js +18 -0
  416. package/esm/src/presets/google.d.ts +104 -0
  417. package/esm/src/presets/google.js +188 -0
  418. package/esm/src/presets/mod.d.ts +10 -0
  419. package/esm/src/presets/mod.js +9 -0
  420. package/esm/src/presets/openrouter.d.ts +13 -0
  421. package/esm/src/presets/openrouter.js +13 -0
  422. package/esm/src/presets/typesafe.d.ts +2 -0
  423. package/esm/src/presets/typesafe.js +2 -0
  424. package/esm/src/providers/create-provider.d.ts +21 -0
  425. package/esm/src/providers/create-provider.js +90 -0
  426. package/esm/src/providers/decision/usage.d.ts +3 -0
  427. package/esm/src/providers/decision/usage.js +25 -0
  428. package/esm/src/providers/google/api-error.d.ts +8 -0
  429. package/esm/src/providers/google/api-error.js +123 -0
  430. package/esm/src/providers/google/grounding.d.ts +5 -0
  431. package/esm/src/providers/google/grounding.js +226 -0
  432. package/esm/src/providers/google/interactions/framing.d.ts +15 -0
  433. package/esm/src/providers/google/interactions/framing.js +263 -0
  434. package/esm/src/providers/google/interactions/mod.d.ts +2 -0
  435. package/esm/src/providers/google/interactions/mod.js +2 -0
  436. package/esm/src/providers/google/interactions/steps.d.ts +12 -0
  437. package/esm/src/providers/google/interactions/steps.js +200 -0
  438. package/esm/src/providers/google/interactions/stream.d.ts +24 -0
  439. package/esm/src/providers/google/interactions/stream.js +297 -0
  440. package/esm/src/providers/google/keys.d.ts +20 -0
  441. package/esm/src/providers/google/keys.js +87 -0
  442. package/esm/src/providers/google/live/framing.d.ts +51 -0
  443. package/esm/src/providers/google/live/framing.js +597 -0
  444. package/esm/src/providers/google/live/mod.d.ts +7 -0
  445. package/esm/src/providers/google/live/mod.js +7 -0
  446. package/esm/src/providers/google/live/openapi-schema.d.ts +1 -0
  447. package/esm/src/providers/google/live/openapi-schema.js +42 -0
  448. package/esm/src/providers/google/live/session.d.ts +14 -0
  449. package/esm/src/providers/google/live/session.js +150 -0
  450. package/esm/src/providers/google/live/stream.d.ts +51 -0
  451. package/esm/src/providers/google/live/stream.js +263 -0
  452. package/esm/src/providers/google/thinking.d.ts +3 -0
  453. package/esm/src/providers/google/thinking.js +8 -0
  454. package/esm/src/providers/google/urls.d.ts +6 -0
  455. package/esm/src/providers/google/urls.js +6 -0
  456. package/esm/src/providers/google/usage.d.ts +7 -0
  457. package/esm/src/providers/google/usage.js +49 -0
  458. package/esm/src/providers/local/local.d.ts +12 -0
  459. package/esm/src/providers/local/local.js +186 -0
  460. package/esm/src/providers/local/mod.d.ts +8 -0
  461. package/esm/src/providers/local/mod.js +8 -0
  462. package/esm/src/providers/mod.d.ts +11 -0
  463. package/esm/src/providers/mod.js +7 -0
  464. package/esm/src/providers/openrouter/cache-control.d.ts +5 -0
  465. package/esm/src/providers/openrouter/cache-control.js +4 -0
  466. package/esm/src/providers/openrouter/chat.d.ts +64 -0
  467. package/esm/src/providers/openrouter/chat.js +490 -0
  468. package/esm/src/providers/openrouter/image.d.ts +24 -0
  469. package/esm/src/providers/openrouter/image.js +187 -0
  470. package/esm/src/providers/openrouter/openai/compat.d.ts +19 -0
  471. package/esm/src/providers/openrouter/openai/compat.js +162 -0
  472. package/esm/src/providers/openrouter/openai/image-payload.d.ts +9 -0
  473. package/esm/src/providers/openrouter/openai/image-payload.js +115 -0
  474. package/esm/src/providers/openrouter/openai/sdk-messages.d.ts +10 -0
  475. package/esm/src/providers/openrouter/openai/sdk-messages.js +99 -0
  476. package/esm/src/providers/openrouter/openai/usage.d.ts +8 -0
  477. package/esm/src/providers/openrouter/openai/usage.js +56 -0
  478. package/esm/src/providers/openrouter/resolve-api-key.d.ts +3 -0
  479. package/esm/src/providers/openrouter/resolve-api-key.js +8 -0
  480. package/esm/src/providers/openrouter/speech.d.ts +18 -0
  481. package/esm/src/providers/openrouter/speech.js +109 -0
  482. package/esm/src/providers/probe.d.ts +5 -0
  483. package/esm/src/providers/probe.js +15 -0
  484. package/esm/src/providers/shared/builtin-wire.d.ts +4 -0
  485. package/esm/src/providers/shared/builtin-wire.js +9 -0
  486. package/esm/src/providers/shared/pcm.d.ts +14 -0
  487. package/esm/src/providers/shared/pcm.js +78 -0
  488. package/esm/src/providers/shared/response-identity.d.ts +11 -0
  489. package/esm/src/providers/shared/response-identity.js +12 -0
  490. package/esm/src/providers/shared/sse.d.ts +10 -0
  491. package/esm/src/providers/shared/sse.js +79 -0
  492. package/esm/src/providers/shared/structured-output.d.ts +4 -0
  493. package/esm/src/providers/shared/structured-output.js +11 -0
  494. package/esm/src/providers/shared/tool-args.d.ts +25 -0
  495. package/esm/src/providers/shared/tool-args.js +84 -0
  496. package/esm/src/providers/shared/upstream-tap.d.ts +8 -0
  497. package/esm/src/providers/shared/upstream-tap.js +85 -0
  498. package/esm/src/providers/shared/upstream-tape.d.ts +6 -0
  499. package/esm/src/providers/shared/upstream-tape.js +88 -0
  500. package/esm/src/providers/shared/vault.d.ts +13 -0
  501. package/esm/src/providers/shared/vault.js +41 -0
  502. package/esm/src/providers/types.d.ts +19 -0
  503. package/esm/src/providers/types.js +1 -0
  504. package/esm/src/surface/formats.d.ts +28 -0
  505. package/esm/src/surface/formats.js +139 -0
  506. package/esm/src/surface/mod.d.ts +14 -0
  507. package/esm/src/surface/mod.js +10 -0
  508. package/esm/src/surface/runtime.d.ts +40 -0
  509. package/esm/src/surface/runtime.js +439 -0
  510. package/esm/src/surface/tools.d.ts +15 -0
  511. package/esm/src/surface/tools.js +80 -0
  512. package/esm/src/surface/types.d.ts +104 -0
  513. package/esm/src/surface/types.js +4 -0
  514. package/package.json +108 -4
@@ -0,0 +1,464 @@
1
+ /**
2
+ * Thought guarding. A host that renders `thought` events shows the user what
3
+ * they say and loads what they link, as it does a reply: the canary, the
4
+ * system prompt and the user-data markers leak through a thought, and a URL
5
+ * the model was not given carries data out. Nothing in a thought stops a turn
6
+ * (`isGuardedOutput`); each leak is omitted and the rest of the thought
7
+ * released.
8
+ *
9
+ * @module
10
+ */
11
+ import { CANARY_LEAK_REACH, canaryHoldFrom, canaryLeakRanges, canaryOpeningFrom, createCanaryScanner, promptLeakCarry, RELEASED_LOOKBACK, wordStartAcross, } from './canary.js';
12
+ import { CANARY_HIT, egressChecksOf, NO_CHECKS, PROMPT_ECHO_HIT, } from './egress.js';
13
+ import { SYSTEM_BOUNDARY } from './egress-patterns.js';
14
+ import { createEgressStream } from './egress-stream.js';
15
+ import { imageLeakSpans, linkLeakSpans } from './egress-urls.js';
16
+ import { lexiconText } from './lexicon.js';
17
+ import { promptEchoHoldFrom, promptEchoRanges, promptEchoScanFrom } from './prompt-echo.js';
18
+ import { EGRESS_RULES } from './rules.js';
19
+ const OMIT_KEYS = {
20
+ image: 'thought.omitted_image',
21
+ link: 'thought.omitted_link',
22
+ instructions: 'thought.omitted_instructions',
23
+ };
24
+ const IMAGE_HIT = { rule: EGRESS_RULES.image, severity: 'high' };
25
+ const LINK_HIT = { rule: EGRESS_RULES.link, severity: 'high' };
26
+ const BOUNDARY_HIT = { rule: EGRESS_RULES.boundary, severity: 'medium' };
27
+ /** Where `raw`, an offset into `view.text`, stands in the thought: a placeholder's start, or with `end` its end. */
28
+ function shownAt(view, raw, end = false) {
29
+ let piece = view.pieces[0];
30
+ for (const next of view.pieces) {
31
+ if (next.raw > raw || (end && next.raw === raw && raw > 0))
32
+ break;
33
+ piece = next;
34
+ }
35
+ if (!piece)
36
+ return raw;
37
+ if (piece.mark)
38
+ return end ? piece.mark.end : piece.mark.start;
39
+ return piece.shown + raw - piece.raw;
40
+ }
41
+ /** The checks of `checks` a thought runs: what it would load, and the markers it would show. */
42
+ function thoughtChecks(checks) {
43
+ if (!(checks.images || checks.links || checks.boundary))
44
+ return undefined;
45
+ return {
46
+ ...NO_CHECKS,
47
+ boundary: checks.boundary,
48
+ ...(checks.images ? { images: checks.images } : {}),
49
+ ...(checks.links ? { links: checks.links } : {}),
50
+ };
51
+ }
52
+ /** Sorted, with overlapping leaks as one: an image's URL is a bare link too. */
53
+ function merged(spans) {
54
+ const out = [];
55
+ for (const span of [...spans].sort((a, b) => a.start - b.start)) {
56
+ const last = out.at(-1);
57
+ if (last && span.start < last.end)
58
+ last.end = Math.max(last.end, span.end);
59
+ else
60
+ out.push({ ...span });
61
+ }
62
+ return out;
63
+ }
64
+ /** Omitting one leak can join what was around it into another; past this many rounds, the rest goes. */
65
+ const MAX_ROUNDS = 8;
66
+ /** Each leak rereads the thought; a thought still writing them past this many loses the rest. */
67
+ const MAX_LEAKS = 16;
68
+ /**
69
+ * The guard reads the thought as it will be shown, placeholders in: text
70
+ * released is final, and what is held changes only by omission. The canary
71
+ * and prompt echo are read a second time with each placeholder as the text it
72
+ * replaced, so a leak running on past one, or across one longer than its
73
+ * text, is omitted too.
74
+ */
75
+ function createThoughtGuard(options) {
76
+ const { checks, canary, given, lexicon } = options;
77
+ const privateSystem = canary ? options.privateSystem : undefined;
78
+ const scope = (check) => ({ ...check, ...(given ? { given } : {}) });
79
+ /** The placeholder for `kind` after `before`, without a second space. */
80
+ function placeholder(kind, before) {
81
+ const text = lexiconText(OMIT_KEYS[kind], {}, lexicon);
82
+ return /\s$/.test(before) ? text.trimStart() : text;
83
+ }
84
+ let out = canary ? (options.carry ?? '') : '';
85
+ let held = '';
86
+ let stream;
87
+ let scanner;
88
+ /** How far the prompt echo has read `out + held` clean. */
89
+ let echoed = 0;
90
+ /** How much of `out + held` the readers have read. */
91
+ let readTo = 0;
92
+ /** Where a leak still growing at the end of the held text starts; held until it ends. */
93
+ let open;
94
+ /** The placeholders in `out + held` a leak reaching the held text could run through, in order. */
95
+ let marks = [];
96
+ /**
97
+ * No canary opening starts in `out + held` before this while the held text
98
+ * only grows and is released: a point further back than `RELEASED_LOOKBACK`
99
+ * that is no opening cannot become one. An omission rewrites the held text,
100
+ * and the hold is read whole again.
101
+ */
102
+ let openingFrom = 0;
103
+ /** Set once the rest of the thought is omitted: nothing more is read until the flush. */
104
+ let cut = false;
105
+ let leaks = 0;
106
+ let hits = new Map();
107
+ /** Fresh readers over `text`, as if it had streamed: true when it already holds a leak. */
108
+ function restart(text) {
109
+ stream = checks ? createEgressStream({ checks, ...(given ? { given } : {}) }) : undefined;
110
+ scanner = canary ? createCanaryScanner(canary) : undefined;
111
+ echoed = 0;
112
+ readTo = 0;
113
+ return read(text);
114
+ }
115
+ /** Read `text`, what follows the read part of `out + held`; true when a leak has settled. */
116
+ function read(text) {
117
+ readTo += text.length;
118
+ const urlHit = stream?.push(text) !== undefined;
119
+ const canaryHit = scanner?.push(text) ?? false;
120
+ let echoHit = false;
121
+ if (privateSystem) {
122
+ const whole = (out + held).slice(0, readTo);
123
+ const from = promptEchoScanFrom(whole, echoed);
124
+ echoHit = promptEchoRanges(whole.slice(from), privateSystem, canary).length > 0;
125
+ echoed = whole.length;
126
+ }
127
+ return urlHit || canaryHit || echoHit;
128
+ }
129
+ function leakSpans(text) {
130
+ const spans = [];
131
+ if (checks?.images) {
132
+ for (const span of imageLeakSpans(text, scope(checks.images))) {
133
+ spans.push({ ...span, kind: 'image', hit: IMAGE_HIT });
134
+ }
135
+ }
136
+ if (checks?.links) {
137
+ for (const span of linkLeakSpans(text, scope(checks.links), checks.images !== undefined)) {
138
+ spans.push({ ...span, kind: 'link', hit: LINK_HIT });
139
+ }
140
+ }
141
+ if (checks?.boundary) {
142
+ for (const match of text.matchAll(new RegExp(SYSTEM_BOUNDARY.source, 'gi'))) {
143
+ const start = match.index;
144
+ spans.push({
145
+ start,
146
+ end: start + match[0].length,
147
+ kind: 'instructions',
148
+ hit: BOUNDARY_HIT,
149
+ });
150
+ }
151
+ }
152
+ if (canary) {
153
+ for (const [start, end] of canaryLeakRanges(text, canary)) {
154
+ spans.push({ start, end, kind: 'instructions', hit: CANARY_HIT });
155
+ }
156
+ }
157
+ if (privateSystem) {
158
+ for (const [start, end] of promptEchoRanges(text, privateSystem, canary)) {
159
+ spans.push({ start, end, kind: 'instructions', hit: PROMPT_ECHO_HIT });
160
+ }
161
+ }
162
+ return spans;
163
+ }
164
+ /** The mark `at` falls inside, if any. */
165
+ function markAt(at) {
166
+ return marks.find((mark) => mark.start < at && at < mark.end);
167
+ }
168
+ /** `out + held` from `from` to `to`, mark boundaries both, each placeholder as the text it replaced. */
169
+ function rawOf(from, to) {
170
+ const whole = out + held;
171
+ let text = '';
172
+ let at = from;
173
+ for (const mark of marks) {
174
+ if (mark.end <= from || mark.start >= to)
175
+ continue;
176
+ text += whole.slice(at, mark.start) + mark.raw;
177
+ at = mark.end;
178
+ }
179
+ return text + whole.slice(at, to);
180
+ }
181
+ /**
182
+ * The thought from far enough back that a leak reaching the held text
183
+ * starts inside, placeholders read as what they replaced; none when no
184
+ * placeholder is that close, as it then reads as the thought does.
185
+ */
186
+ function rawView() {
187
+ const whole = out + held;
188
+ for (let reach = CANARY_LEAK_REACH;; reach *= 2) {
189
+ let from = out.length;
190
+ let length = 0;
191
+ for (let i = marks.length - 1; from > 0 && length < reach;) {
192
+ const mark = marks[i];
193
+ if (mark && mark.end > from) {
194
+ i--;
195
+ }
196
+ else if (mark && mark.end === from) {
197
+ length += mark.raw.length;
198
+ from = mark.start;
199
+ i--;
200
+ }
201
+ else {
202
+ const stop = Math.max(mark?.end ?? 0, from - (reach - length));
203
+ length += from - stop;
204
+ from = stop;
205
+ }
206
+ }
207
+ marks = marks.filter((mark) => mark.end > from);
208
+ if (marks.length === 0)
209
+ return undefined;
210
+ const view = { text: '', held: 0, pieces: [] };
211
+ let at = from;
212
+ for (const mark of [...marks, undefined]) {
213
+ const plain = mark ? mark.start : whole.length;
214
+ if (plain > at)
215
+ view.pieces.push({ raw: view.text.length, shown: at });
216
+ if (at <= out.length && out.length <= plain)
217
+ view.held = view.text.length + out.length - at;
218
+ view.text += whole.slice(at, plain);
219
+ if (!mark)
220
+ break;
221
+ view.pieces.push({ raw: view.text.length, shown: mark.start, mark });
222
+ view.text += mark.raw;
223
+ at = mark.end;
224
+ }
225
+ // An echo run is counted in words: read back until it fits, or the thought starts.
226
+ if (!privateSystem || from === 0 || promptEchoScanFrom(view.text, view.held) > 0)
227
+ return view;
228
+ }
229
+ }
230
+ /** The leaks the raw view finds that leave something held still shown, as spans of the thought. */
231
+ function rawLeaks() {
232
+ const view = rawView();
233
+ if (!view)
234
+ return [];
235
+ const ranges = [];
236
+ if (canary) {
237
+ for (const [start, end] of canaryLeakRanges(view.text, canary)) {
238
+ ranges.push([start, end, CANARY_HIT]);
239
+ }
240
+ }
241
+ if (privateSystem) {
242
+ for (const [start, end] of promptEchoRanges(view.text, privateSystem, canary)) {
243
+ ranges.push([start, end, PROMPT_ECHO_HIT]);
244
+ }
245
+ }
246
+ const spans = [];
247
+ for (const [rawStart, rawEnd, hit] of ranges) {
248
+ if (rawEnd <= view.held)
249
+ continue;
250
+ const start = shownAt(view, rawStart);
251
+ const end = shownAt(view, rawEnd, true);
252
+ let shows = false;
253
+ for (let at = Math.max(start, out.length); at < end && !shows; at++) {
254
+ shows = !marks.some((mark) => mark.start <= at && at < mark.end);
255
+ }
256
+ if (shows)
257
+ spans.push({ start, end, kind: 'instructions', hit });
258
+ }
259
+ return spans;
260
+ }
261
+ /** Every leak in the thought, as shown and as written, overlapping ones as one. */
262
+ function allLeaks() {
263
+ return merged([...leakSpans(out + held), ...rawLeaks()]);
264
+ }
265
+ /** The leaks reaching into the held text, in order. */
266
+ function heldLeaks() {
267
+ return allLeaks().filter(({ end }) => end > out.length);
268
+ }
269
+ /** `at` moved off the inside of a placeholder: back to its start, or with `end` on to its end. */
270
+ function offMark(at, end = false) {
271
+ const mark = markAt(at);
272
+ return mark ? (end ? mark.end : mark.start) : at;
273
+ }
274
+ /**
275
+ * Replace each leak reaching into the held text with its placeholder, but
276
+ * for one reaching its end, which the next chunk could continue: that one is
277
+ * held whole (`open`) unless the thought has ended. False when nothing was replaced.
278
+ */
279
+ function omitHeld(ended) {
280
+ const spans = heldLeaks();
281
+ const whole = out + held;
282
+ const tail = spans.at(-1);
283
+ const growing = !ended && tail !== undefined && tail.end >= whole.length ? tail : undefined;
284
+ const closed = growing ? spans.slice(0, -1) : spans;
285
+ const kept = marks.filter((mark) => mark.end <= out.length);
286
+ let next = '';
287
+ let at = out.length;
288
+ /** Copy `whole` up to `to`, and the marks in it. */
289
+ const copy = (to) => {
290
+ const shift = out.length + next.length - at;
291
+ for (const mark of marks) {
292
+ if (mark.start >= at && mark.end <= to) {
293
+ kept.push({ ...mark, start: mark.start + shift, end: mark.end + shift });
294
+ }
295
+ }
296
+ next += whole.slice(at, Math.max(at, to));
297
+ at = Math.max(at, to);
298
+ };
299
+ for (const { start, end, kind, hit } of closed) {
300
+ copy(offMark(start));
301
+ const to = Math.max(at, offMark(end, true));
302
+ const text = placeholder(kind, out + next);
303
+ const begin = out.length + next.length;
304
+ kept.push({ start: begin, end: begin + text.length, raw: rawOf(at, to) });
305
+ next += text;
306
+ hits.set(hit.rule, hit);
307
+ at = to;
308
+ }
309
+ open = undefined;
310
+ if (growing) {
311
+ copy(offMark(growing.start));
312
+ open = out.length + next.length;
313
+ }
314
+ copy(whole.length);
315
+ marks = kept;
316
+ held = next;
317
+ openingFrom = 0;
318
+ return closed.length > 0;
319
+ }
320
+ /** Omit the held text from the first leak on; all of it when the leak is in what was shown. */
321
+ function cutRest() {
322
+ const first = allLeaks()[0];
323
+ const from = first ? Math.max(0, offMark(first.start) - out.length) : 0;
324
+ const kept = held.slice(0, from);
325
+ const text = placeholder(first?.kind ?? 'instructions', out + kept);
326
+ const begin = out.length + from;
327
+ const raw = rawOf(begin, out.length + held.length);
328
+ marks = marks.filter((mark) => mark.end <= begin);
329
+ marks.push({ start: begin, end: begin + text.length, raw });
330
+ held = kept + text;
331
+ openingFrom = 0;
332
+ if (first)
333
+ hits.set(first.hit.rule, first.hit);
334
+ open = undefined;
335
+ cut = true;
336
+ }
337
+ /** What the readers read: the thought up to a leak still growing. */
338
+ function readable() {
339
+ const whole = out + held;
340
+ return open === undefined ? whole : whole.slice(0, open);
341
+ }
342
+ /** Omit leaks until fresh readers over the thought settle none; failing that, the rest. */
343
+ function settle() {
344
+ for (let round = 0; round < MAX_ROUNDS; round++) {
345
+ if (leaks >= MAX_LEAKS)
346
+ break;
347
+ const before = new Set(marks.map((mark) => mark.start));
348
+ if (!omitHeld(false)) {
349
+ // A leak the readers settled that no span covers is cut, not shown.
350
+ if (open === undefined)
351
+ break;
352
+ return;
353
+ }
354
+ // A leak running on past its placeholder only grows it.
355
+ if (marks.some((mark) => !before.has(mark.start)))
356
+ leaks++;
357
+ if (!restart(readable()))
358
+ return;
359
+ }
360
+ cutRest();
361
+ }
362
+ /** The earliest index of `out + held` a leak could still start at, moved back to the start of a word it cuts. */
363
+ function holdFrom() {
364
+ const end = out.length + held.length;
365
+ const url = stream ? stream.holdFrom() : end;
366
+ const leak = canary ? canaryFrom(canary) : end;
367
+ const echo = privateSystem ? out.length + promptEchoHoldFrom(held, privateSystem, canary) : end;
368
+ const from = Math.min(url, leak, echo, rawHoldFrom() ?? end, open ?? end);
369
+ return offMark(from < out.length ? from : out.length + wordStartAcross(held, from - out.length));
370
+ }
371
+ /** `canaryHoldFrom` on the held text, as an index of `out + held`, read from where an opening could start. */
372
+ function canaryFrom(canary) {
373
+ const from = Math.max(out.length, openingFrom);
374
+ const lead = Math.max(0, from - RELEASED_LOOKBACK);
375
+ let at = lead + canaryOpeningFrom(textFrom(lead), canary);
376
+ if (at < from && from > out.length) {
377
+ // An opening the bound rules out: read the held text whole.
378
+ const whole = Math.max(0, out.length - RELEASED_LOOKBACK);
379
+ at = whole + canaryOpeningFrom(textFrom(whole), canary);
380
+ }
381
+ openingFrom = Math.min(at, out.length + held.length - RELEASED_LOOKBACK);
382
+ return Math.max(out.length, at);
383
+ }
384
+ /** `out + held` from `from` on. */
385
+ function textFrom(from) {
386
+ return from < out.length ? out.slice(from) + held : held.slice(from - out.length);
387
+ }
388
+ /** The hold as the raw view reads it: an opening a placeholder spent may not be spent. */
389
+ function rawHoldFrom() {
390
+ const view = rawView();
391
+ if (!view)
392
+ return undefined;
393
+ const rest = view.text.slice(view.held);
394
+ const leak = canary ? canaryHoldFrom(rest, canary, view.text.slice(0, view.held)) : rest.length;
395
+ const echo = privateSystem ? promptEchoHoldFrom(rest, privateSystem, canary) : rest.length;
396
+ return shownAt(view, view.held + Math.min(leak, echo));
397
+ }
398
+ function release(text) {
399
+ const shown = { text, hits: [...hits.values()] };
400
+ hits = new Map();
401
+ return shown;
402
+ }
403
+ restart(out);
404
+ return {
405
+ push(text) {
406
+ if (cut || !text)
407
+ return release('');
408
+ held += text;
409
+ if (open !== undefined || read(text) || rawLeaks().length > 0)
410
+ settle();
411
+ if (cut)
412
+ return release('');
413
+ const clear = Math.max(0, holdFrom() - out.length);
414
+ const shown = held.slice(0, clear);
415
+ out += shown;
416
+ held = held.slice(clear);
417
+ return release(shown);
418
+ },
419
+ flush() {
420
+ if (!cut) {
421
+ for (let round = 0; round < MAX_ROUNDS && omitHeld(true); round++)
422
+ ;
423
+ // A leak left is one the text shown already takes part in, such as a definition an image opener held here could use.
424
+ if (held && (leakSpans(out + held).length > 0 || rawLeaks().length > 0))
425
+ cutRest();
426
+ }
427
+ const shown = held;
428
+ const whole = out + held;
429
+ out = canary ? promptLeakCarry(whole, canary, privateSystem) : '';
430
+ const shift = out.length - whole.length;
431
+ marks = marks
432
+ .filter((mark) => mark.start + shift >= 0)
433
+ .map((mark) => ({ ...mark, start: mark.start + shift, end: mark.end + shift }));
434
+ held = '';
435
+ openingFrom = 0;
436
+ open = undefined;
437
+ cut = false;
438
+ leaks = 0;
439
+ restart(out);
440
+ return release(shown);
441
+ },
442
+ carryOut: () => out,
443
+ };
444
+ }
445
+ /**
446
+ * A guard for a turn's thoughts: the canary and prompt echo whenever the turn
447
+ * binds a canary, and the URL and boundary checks `enforce` runs.
448
+ */
449
+ function thoughtGuardFor(enforce, context, carry) {
450
+ const known = egressChecksOf(enforce);
451
+ const checks = known ? thoughtChecks(known) : undefined;
452
+ const { canary, privateSystem, givenUrls, lexicon } = context;
453
+ if (!(checks || canary))
454
+ return undefined;
455
+ return createThoughtGuard({
456
+ ...(checks ? { checks } : {}),
457
+ ...(canary ? { canary } : {}),
458
+ ...(privateSystem ? { privateSystem } : {}),
459
+ ...(givenUrls ? { given: givenUrls } : {}),
460
+ ...(lexicon ? { lexicon } : {}),
461
+ ...(carry ? { carry } : {}),
462
+ });
463
+ }
464
+ export { createThoughtGuard, thoughtGuardFor };
@@ -0,0 +1,19 @@
1
+ import type { AdvisoryLevel, GuardrailHit } from './types.js';
2
+ /**
3
+ * Real indirect injection rarely names what it attacks, so this looks for content that behaves
4
+ * like an instruction. Hits raise the turn's taint rather than rewriting the text: a page
5
+ * documenting an email API legitimately says "call send_email", and being wrong should cost a
6
+ * refused write, not silently damaged input.
7
+ *
8
+ * `callableTools` is the set the model can invoke this turn. A result naming one is the
9
+ * highest-precision signal: ordinary data has no reason to, and no generic filter can check it
10
+ * without the turn's registry.
11
+ */
12
+ declare function directiveHits(text: string, callableTools?: readonly string[]): GuardrailHit[];
13
+ declare function looksDirective(hits: GuardrailHit[]): boolean;
14
+ /**
15
+ * Naming a tool the model can call is the sharpest signal available, so it alone
16
+ * reaches `high`; so does agreement between two different signal kinds.
17
+ */
18
+ declare function advisoryLevel(hits: GuardrailHit[]): AdvisoryLevel;
19
+ export { advisoryLevel, directiveHits, looksDirective };
@@ -0,0 +1,109 @@
1
+ import { normalizeForDetection } from './normalize.js';
2
+ import { DIRECTIVE_RULES } from './rules.js';
3
+ /**
4
+ * Imperatives aimed at an agent rather than a reader.
5
+ *
6
+ * Bounded quantifiers throughout: tool results can be large, and an unbounded
7
+ * scanner on attacker-controlled bytes is a denial-of-service surface.
8
+ */
9
+ const IMPERATIVES = [
10
+ /\b(?:next|final|remaining)\s+steps?\s*[:—-]/gi,
11
+ /\byou\s+(?:must|should|need\s+to|are\s+required\s+to)\s+(?:now\s+)?\w{2,20}/gi,
12
+ /\bto\s+(?:complete|finish|fulfil|fulfill)\s+(?:this|the)\s+\w{2,20}/gi,
13
+ /\b(?:call|invoke|run|execute)\s+(?:the\s+)?[\w.-]{2,40}\s+(?:tool|function)\b/gi,
14
+ /\b(?:send|forward|email|transfer|upload|post)\s+(?:the\s+|all\s+|your\s+)?[\w\s]{2,40}\s+to\s+\S{3,80}/gi,
15
+ /\b(?:delete|remove|drop|purge)\s+(?:the\s+|all\s+)?[\w\s]{2,40}\b/gi,
16
+ ];
17
+ /**
18
+ * A concrete external destination — the thing exfiltration needs and ordinary
19
+ * process prose almost never carries.
20
+ *
21
+ * This is the discriminator. Directive language on its own is everywhere in
22
+ * legitimate tool output: documentation says "you must be an admin", support
23
+ * articles say "to remove a user", status reports say "the user has approved".
24
+ * Measured on a benign sample, directive signals alone produced false positives
25
+ * on most of it. Pairing a signal with a destination removed all of them.
26
+ */
27
+ const EXFIL_TARGET = /\b[\w.+-]{1,64}@[\w-]{1,63}(?:\.[\w-]{1,63}){1,4}\b|\bhttps?:\/\/\S{4,120}/i;
28
+ /** Claims of permission or provenance the content cannot actually hold. */
29
+ const AUTHORITY = [
30
+ /\b(?:the\s+)?user\s+has\s+(?:already\s+)?(?:approved|authorised|authorized|confirmed|requested)\b/gi,
31
+ /\b(?:system|admin|operator)\s+(?:note|notice|message|override|instruction)s?\s*[:—-]/gi,
32
+ /\bon\s+behalf\s+of\s+the\s+(?:user|operator|admin)\b/gi,
33
+ /\bthis\s+(?:is|was)\s+(?:pre-?)?(?:approved|authorised|authorized)\b/gi,
34
+ ];
35
+ function matches(patterns, text) {
36
+ return patterns.some((pattern) => {
37
+ pattern.lastIndex = 0;
38
+ return pattern.test(text);
39
+ });
40
+ }
41
+ function isToolNameBoundary(ch) {
42
+ return ch === undefined || !/[a-z0-9_-]/i.test(ch);
43
+ }
44
+ /** Word-boundary match for a tool name without compiling registry input as a pattern. */
45
+ function mentionsTool(text, tool) {
46
+ if (tool.length < 3) {
47
+ return false;
48
+ }
49
+ const haystack = text.toLowerCase();
50
+ const needle = tool.toLowerCase();
51
+ let at = haystack.indexOf(needle);
52
+ while (at >= 0) {
53
+ const before = haystack[at - 1];
54
+ const after = haystack[at + needle.length];
55
+ if (isToolNameBoundary(before) && isToolNameBoundary(after)) {
56
+ return true;
57
+ }
58
+ at = haystack.indexOf(needle, at + needle.length);
59
+ }
60
+ return false;
61
+ }
62
+ /**
63
+ * Real indirect injection rarely names what it attacks, so this looks for content that behaves
64
+ * like an instruction. Hits raise the turn's taint rather than rewriting the text: a page
65
+ * documenting an email API legitimately says "call send_email", and being wrong should cost a
66
+ * refused write, not silently damaged input.
67
+ *
68
+ * `callableTools` is the set the model can invoke this turn. A result naming one is the
69
+ * highest-precision signal: ordinary data has no reason to, and no generic filter can check it
70
+ * without the turn's registry.
71
+ */
72
+ function directiveHits(text, callableTools = []) {
73
+ if (!text || !EXFIL_TARGET.test(text)) {
74
+ // No destination, no exfiltration. Action-shaped attacks that carry no target
75
+ // are left to the taint gate, which does not depend on reading the content.
76
+ return [];
77
+ }
78
+ const normalized = normalizeForDetection(text);
79
+ const hits = [];
80
+ // One hit per named tool — several names is a stronger signal than one.
81
+ for (const _tool of callableTools.filter((tool) => mentionsTool(normalized, tool))) {
82
+ hits.push({ rule: DIRECTIVE_RULES.toolName, severity: 'high' });
83
+ }
84
+ if (matches(IMPERATIVES, normalized)) {
85
+ hits.push({ rule: DIRECTIVE_RULES.imperative, severity: 'medium' });
86
+ }
87
+ if (matches(AUTHORITY, normalized)) {
88
+ hits.push({ rule: DIRECTIVE_RULES.authority, severity: 'medium' });
89
+ }
90
+ return hits;
91
+ }
92
+ function looksDirective(hits) {
93
+ return hits.length > 0;
94
+ }
95
+ /**
96
+ * Naming a tool the model can call is the sharpest signal available, so it alone
97
+ * reaches `high`; so does agreement between two different signal kinds.
98
+ */
99
+ function advisoryLevel(hits) {
100
+ if (hits.length === 0) {
101
+ return 'none';
102
+ }
103
+ const kinds = new Set(hits.map((hit) => hit.rule));
104
+ if (kinds.has(DIRECTIVE_RULES.toolName) || kinds.size > 1) {
105
+ return 'high';
106
+ }
107
+ return 'elevated';
108
+ }
109
+ export { advisoryLevel, directiveHits, looksDirective };
@@ -0,0 +1,61 @@
1
+ import { type LexiconOverrides } from './lexicon.js';
2
+ import type { AdvisoryLevel, GuardrailEvent, GuardrailHit, Provenance, ResolvedGuardrailPolicy, ToolOrigin, TurnTaint, Verdict } from './types.js';
3
+ declare const TOOL_CLOSE = "</tool_data>";
4
+ declare function isRemoteOrigin(origin: ToolOrigin): boolean;
5
+ /**
6
+ * The origin is on the tag rather than in prose so a result cannot claim a
7
+ * friendlier provenance than it has by writing one into its own body.
8
+ */
9
+ declare function wrapToolData(text: string, provenance: Provenance, advisory?: AdvisoryLevel, lexicon?: LexiconOverrides): string;
10
+ export interface GuardedToolText {
11
+ text: string;
12
+ /** Emitted when the guard did anything worth recording. */
13
+ event?: GuardrailEvent;
14
+ /**
15
+ * Reported, never redacted: legitimate tool output is frequently
16
+ * instruction-shaped, so rewriting on this signal would corrupt real data.
17
+ * These raise the turn's taint instead.
18
+ */
19
+ suspicious?: GuardrailHit[];
20
+ }
21
+ /**
22
+ * `finding` is the tool's summary and `data` its structured payload; both reach
23
+ * the model, so both are guarded together rather than only the prose half.
24
+ */
25
+ declare function composeToolText(finding: string, data: unknown): string;
26
+ /**
27
+ * Local host tools are still detected — a host tool reading a database returns
28
+ * data the host did not write — but only remote origins are fenced, because
29
+ * fencing a local tool's output would change prompts hosts have already tuned.
30
+ */
31
+ declare function guardToolResult(finding: string, data: unknown, provenance: Provenance, policy: ResolvedGuardrailPolicy, callableTools?: readonly string[], lexicon?: LexiconOverrides): GuardedToolText;
32
+ /**
33
+ * A remote server authors its own error strings, so an unguarded failure message
34
+ * is the cleanest injection path across this boundary: it reaches the model
35
+ * verbatim and is framed by the kernel as a system report.
36
+ */
37
+ declare function guardToolFailureText(message: string, provenance: Provenance, policy: ResolvedGuardrailPolicy): GuardedToolText;
38
+ /**
39
+ * Arguments are model-authored, so the risk is not instruction smuggling but
40
+ * exfiltration: a credential lifted from context and posted outward as a
41
+ * parameter. Detection reports rather than rewrites — silently altering a tool
42
+ * argument would make the call succeed against something the model did not ask
43
+ * for.
44
+ */
45
+ declare function inspectToolArguments(args: unknown, policy: ResolvedGuardrailPolicy): Verdict;
46
+ declare function toolCallEvent(verdict: Verdict, provenance: Provenance): GuardrailEvent | undefined;
47
+ /**
48
+ * Only remote origins taint: a local host tool returns bytes the host's own code
49
+ * produced, and treating those as attacker-influenceable would make the gate
50
+ * useless in practice.
51
+ */
52
+ declare function recordTaint(taint: TurnTaint | undefined, provenance: Provenance, suspicious?: GuardrailHit[]): TurnTaint;
53
+ declare function isTainted(taint: TurnTaint | undefined): boolean;
54
+ declare function isSuspicious(taint: TurnTaint | undefined): boolean;
55
+ /**
56
+ * A `flag` says the call is happening on a tainted turn and is worth recording; a
57
+ * `block` says the profile asked for it to be refused. Reporting happens whether
58
+ * or not enforcement is configured, so the risk is visible before a host opts in.
59
+ */
60
+ declare function checkTaintGate(taint: TurnTaint | undefined, access: string, policy: ResolvedGuardrailPolicy, lexicon?: LexiconOverrides): Verdict;
61
+ export { checkTaintGate, composeToolText, guardToolFailureText, guardToolResult, inspectToolArguments, isRemoteOrigin, isSuspicious, isTainted, recordTaint, TOOL_CLOSE, toolCallEvent, wrapToolData, };