@theoremjs/agents 0.0.0-stage → 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 (588) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +545 -2
  3. package/esm/_dnt.polyfills.d.ts +66 -0
  4. package/esm/_dnt.polyfills.js +51 -0
  5. package/esm/mod.d.ts +79 -0
  6. package/esm/mod.js +49 -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 +480 -0
  12. package/esm/src/cli/commands/detect-compile.d.ts +17 -0
  13. package/esm/src/cli/commands/detect-compile.js +22 -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 +241 -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 +26 -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 +67 -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 +5 -0
  35. package/esm/src/evals/attachments.js +55 -0
  36. package/esm/src/evals/breakdown.d.ts +30 -0
  37. package/esm/src/evals/breakdown.js +69 -0
  38. package/esm/src/evals/graders/answer.d.ts +16 -0
  39. package/esm/src/evals/graders/answer.js +134 -0
  40. package/esm/src/evals/graders/code.d.ts +40 -0
  41. package/esm/src/evals/graders/code.js +184 -0
  42. package/esm/src/evals/graders/judge.d.ts +24 -0
  43. package/esm/src/evals/graders/judge.js +367 -0
  44. package/esm/src/evals/graders/latency.d.ts +6 -0
  45. package/esm/src/evals/graders/latency.js +82 -0
  46. package/esm/src/evals/graders/live.d.ts +14 -0
  47. package/esm/src/evals/graders/live.js +42 -0
  48. package/esm/src/evals/graders/media.d.ts +18 -0
  49. package/esm/src/evals/graders/media.js +91 -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 +19 -0
  53. package/esm/src/evals/graders/transcript.js +202 -0
  54. package/esm/src/evals/mod.d.ts +34 -0
  55. package/esm/src/evals/mod.js +22 -0
  56. package/esm/src/evals/record.d.ts +41 -0
  57. package/esm/src/evals/record.js +107 -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 +75 -0
  67. package/esm/src/evals/run.js +418 -0
  68. package/esm/src/evals/suite.d.ts +28 -0
  69. package/esm/src/evals/suite.js +97 -0
  70. package/esm/src/evals/summary.d.ts +35 -0
  71. package/esm/src/evals/summary.js +31 -0
  72. package/esm/src/evals/trial.d.ts +14 -0
  73. package/esm/src/evals/trial.js +135 -0
  74. package/esm/src/evals/types.d.ts +169 -0
  75. package/esm/src/evals/types.js +113 -0
  76. package/esm/src/evals/verdict.d.ts +23 -0
  77. package/esm/src/evals/verdict.js +48 -0
  78. package/esm/src/guardrails/boundaries.d.ts +41 -0
  79. package/esm/src/guardrails/boundaries.js +103 -0
  80. package/esm/src/guardrails/canary-gate.d.ts +22 -0
  81. package/esm/src/guardrails/canary-gate.js +40 -0
  82. package/esm/src/guardrails/canary.d.ts +146 -0
  83. package/esm/src/guardrails/canary.js +974 -0
  84. package/esm/src/guardrails/compile-egress.d.ts +12 -0
  85. package/esm/src/guardrails/compile-egress.js +12 -0
  86. package/esm/src/guardrails/corpus/canary-egress-attacks.d.ts +24 -0
  87. package/esm/src/guardrails/corpus/canary-egress-attacks.js +305 -0
  88. package/esm/src/guardrails/corpus/fuzz-inbound.d.ts +5 -0
  89. package/esm/src/guardrails/corpus/fuzz-inbound.js +199 -0
  90. package/esm/src/guardrails/corpus/inbound-payloads.d.ts +5 -0
  91. package/esm/src/guardrails/corpus/inbound-payloads.js +120 -0
  92. package/esm/src/guardrails/corpus/live-attacks.d.ts +15 -0
  93. package/esm/src/guardrails/corpus/live-attacks.js +229 -0
  94. package/esm/src/guardrails/corpus/mod.d.ts +7 -0
  95. package/esm/src/guardrails/corpus/mod.js +4 -0
  96. package/esm/src/guardrails/corpus/secrets.d.ts +12 -0
  97. package/esm/src/guardrails/corpus/secrets.js +16 -0
  98. package/esm/src/guardrails/corpus/strings.d.ts +23 -0
  99. package/esm/src/guardrails/corpus/strings.js +29 -0
  100. package/esm/src/guardrails/corpus/types.d.ts +36 -0
  101. package/esm/src/guardrails/corpus/types.js +1 -0
  102. package/esm/src/guardrails/credential-rules.d.ts +36 -0
  103. package/esm/src/guardrails/credential-rules.js +3001 -0
  104. package/esm/src/guardrails/credential-scan.d.ts +45 -0
  105. package/esm/src/guardrails/credential-scan.js +172 -0
  106. package/esm/src/guardrails/destinations.d.ts +45 -0
  107. package/esm/src/guardrails/destinations.js +234 -0
  108. package/esm/src/guardrails/detect-at.d.ts +107 -0
  109. package/esm/src/guardrails/detect-at.js +434 -0
  110. package/esm/src/guardrails/detect-reply.d.ts +61 -0
  111. package/esm/src/guardrails/detect-reply.js +95 -0
  112. package/esm/src/guardrails/detect-stream.d.ts +33 -0
  113. package/esm/src/guardrails/detect-stream.js +77 -0
  114. package/esm/src/guardrails/detectors.d.ts +216 -0
  115. package/esm/src/guardrails/detectors.js +503 -0
  116. package/esm/src/guardrails/egress-automata.d.ts +12 -0
  117. package/esm/src/guardrails/egress-automata.js +25582 -0
  118. package/esm/src/guardrails/egress-compiler.d.ts +55 -0
  119. package/esm/src/guardrails/egress-compiler.js +431 -0
  120. package/esm/src/guardrails/egress-patterns.d.ts +26 -0
  121. package/esm/src/guardrails/egress-patterns.js +36 -0
  122. package/esm/src/guardrails/egress-stream.d.ts +123 -0
  123. package/esm/src/guardrails/egress-stream.js +774 -0
  124. package/esm/src/guardrails/egress-urls.d.ts +86 -0
  125. package/esm/src/guardrails/egress-urls.js +909 -0
  126. package/esm/src/guardrails/egress.d.ts +46 -0
  127. package/esm/src/guardrails/egress.js +124 -0
  128. package/esm/src/guardrails/error.d.ts +31 -0
  129. package/esm/src/guardrails/error.js +96 -0
  130. package/esm/src/guardrails/event-schemas.d.ts +100 -0
  131. package/esm/src/guardrails/event-schemas.js +48 -0
  132. package/esm/src/guardrails/events.d.ts +13 -0
  133. package/esm/src/guardrails/events.js +45 -0
  134. package/esm/src/guardrails/hints.d.ts +14 -0
  135. package/esm/src/guardrails/hints.js +57 -0
  136. package/esm/src/guardrails/hits.d.ts +14 -0
  137. package/esm/src/guardrails/hits.js +30 -0
  138. package/esm/src/guardrails/host-patterns.d.ts +85 -0
  139. package/esm/src/guardrails/host-patterns.js +173 -0
  140. package/esm/src/guardrails/injection-patterns.d.ts +20 -0
  141. package/esm/src/guardrails/injection-patterns.js +126 -0
  142. package/esm/src/guardrails/injection-reversed.d.ts +9 -0
  143. package/esm/src/guardrails/injection-reversed.js +49 -0
  144. package/esm/src/guardrails/injection.d.ts +30 -0
  145. package/esm/src/guardrails/injection.js +460 -0
  146. package/esm/src/guardrails/labels.d.ts +40 -0
  147. package/esm/src/guardrails/labels.js +874 -0
  148. package/esm/src/guardrails/live-outbound-gate.d.ts +55 -0
  149. package/esm/src/guardrails/live-outbound-gate.js +298 -0
  150. package/esm/src/guardrails/mod.d.ts +54 -0
  151. package/esm/src/guardrails/mod.js +34 -0
  152. package/esm/src/guardrails/network.d.ts +46 -0
  153. package/esm/src/guardrails/network.js +330 -0
  154. package/esm/src/guardrails/normalize.d.ts +20 -0
  155. package/esm/src/guardrails/normalize.js +165 -0
  156. package/esm/src/guardrails/policy.d.ts +4 -0
  157. package/esm/src/guardrails/policy.js +21 -0
  158. package/esm/src/guardrails/progressive-yield.d.ts +110 -0
  159. package/esm/src/guardrails/progressive-yield.js +281 -0
  160. package/esm/src/guardrails/prompt-echo.d.ts +40 -0
  161. package/esm/src/guardrails/prompt-echo.js +306 -0
  162. package/esm/src/guardrails/quota.d.ts +21 -0
  163. package/esm/src/guardrails/quota.js +80 -0
  164. package/esm/src/guardrails/rules.d.ts +47 -0
  165. package/esm/src/guardrails/rules.js +47 -0
  166. package/esm/src/guardrails/sanitize.d.ts +40 -0
  167. package/esm/src/guardrails/sanitize.js +160 -0
  168. package/esm/src/guardrails/sensitive-groups.d.ts +21 -0
  169. package/esm/src/guardrails/sensitive-groups.js +12 -0
  170. package/esm/src/guardrails/sensitive.d.ts +22 -0
  171. package/esm/src/guardrails/sensitive.js +234 -0
  172. package/esm/src/guardrails/serialize.d.ts +15 -0
  173. package/esm/src/guardrails/serialize.js +37 -0
  174. package/esm/src/guardrails/testing.d.ts +11 -0
  175. package/esm/src/guardrails/testing.js +10 -0
  176. package/esm/src/guardrails/theorem-error.d.ts +21 -0
  177. package/esm/src/guardrails/theorem-error.js +54 -0
  178. package/esm/src/guardrails/thought-guard.d.ts +76 -0
  179. package/esm/src/guardrails/thought-guard.js +664 -0
  180. package/esm/src/guardrails/tool-directives.d.ts +38 -0
  181. package/esm/src/guardrails/tool-directives.js +195 -0
  182. package/esm/src/guardrails/tool-leak.d.ts +26 -0
  183. package/esm/src/guardrails/tool-leak.js +45 -0
  184. package/esm/src/guardrails/tool-result.d.ts +92 -0
  185. package/esm/src/guardrails/tool-result.js +272 -0
  186. package/esm/src/guardrails/types.d.ts +250 -0
  187. package/esm/src/guardrails/types.js +58 -0
  188. package/esm/src/host/client-turn.d.ts +36 -0
  189. package/esm/src/host/client-turn.js +80 -0
  190. package/esm/src/host/mint-trace.d.ts +29 -0
  191. package/esm/src/host/mint-trace.js +60 -0
  192. package/esm/src/host/mod.d.ts +13 -0
  193. package/esm/src/host/mod.js +11 -0
  194. package/esm/src/host/readStreamingJsonStringField.d.ts +2 -0
  195. package/esm/src/host/readStreamingJsonStringField.js +27 -0
  196. package/esm/src/host/reply.d.ts +13 -0
  197. package/esm/src/host/reply.js +41 -0
  198. package/esm/src/interface/blocks.d.ts +11 -0
  199. package/esm/src/interface/blocks.js +283 -0
  200. package/esm/src/interface/composer-actions.d.ts +24 -0
  201. package/esm/src/interface/composer-actions.js +33 -0
  202. package/esm/src/interface/draft.d.ts +20 -0
  203. package/esm/src/interface/draft.js +39 -0
  204. package/esm/src/interface/from-profile.d.ts +24 -0
  205. package/esm/src/interface/from-profile.js +179 -0
  206. package/esm/src/interface/history.d.ts +46 -0
  207. package/esm/src/interface/history.js +278 -0
  208. package/esm/src/interface/inputs.d.ts +11 -0
  209. package/esm/src/interface/inputs.js +67 -0
  210. package/esm/src/interface/mod.d.ts +33 -0
  211. package/esm/src/interface/mod.js +22 -0
  212. package/esm/src/interface/models.d.ts +26 -0
  213. package/esm/src/interface/models.js +50 -0
  214. package/esm/src/interface/pending.d.ts +57 -0
  215. package/esm/src/interface/pending.js +152 -0
  216. package/esm/src/interface/profile-interface.d.ts +4 -0
  217. package/esm/src/interface/profile-interface.js +237 -0
  218. package/esm/src/interface/session.d.ts +71 -0
  219. package/esm/src/interface/session.js +128 -0
  220. package/esm/src/interface/stop.d.ts +13 -0
  221. package/esm/src/interface/stop.js +28 -0
  222. package/esm/src/interface/tool-calls.d.ts +32 -0
  223. package/esm/src/interface/tool-calls.js +127 -0
  224. package/esm/src/interface/tool-invoke.d.ts +6 -0
  225. package/esm/src/interface/tool-invoke.js +22 -0
  226. package/esm/src/interface/tool-media.d.ts +11 -0
  227. package/esm/src/interface/tool-media.js +113 -0
  228. package/esm/src/interface/types.d.ts +278 -0
  229. package/esm/src/interface/types.js +5 -0
  230. package/esm/src/kernel/api-catalog.d.ts +85 -0
  231. package/esm/src/kernel/api-catalog.js +229 -0
  232. package/esm/src/kernel/auth/credential-source.d.ts +23 -0
  233. package/esm/src/kernel/auth/credential-source.js +11 -0
  234. package/esm/src/kernel/auth/crypto.d.ts +56 -0
  235. package/esm/src/kernel/auth/crypto.js +163 -0
  236. package/esm/src/kernel/auth/mod.d.ts +5 -0
  237. package/esm/src/kernel/auth/mod.js +5 -0
  238. package/esm/src/kernel/auth/oauth.d.ts +18 -0
  239. package/esm/src/kernel/auth/oauth.js +439 -0
  240. package/esm/src/kernel/auth/scope-refusal.d.ts +9 -0
  241. package/esm/src/kernel/auth/scope-refusal.js +8 -0
  242. package/esm/src/kernel/auth/typed-secret.d.ts +13 -0
  243. package/esm/src/kernel/auth/typed-secret.js +23 -0
  244. package/esm/src/kernel/auth/types.d.ts +152 -0
  245. package/esm/src/kernel/auth/types.js +1 -0
  246. package/esm/src/kernel/checkpoint.d.ts +43 -0
  247. package/esm/src/kernel/checkpoint.js +58 -0
  248. package/esm/src/kernel/default-scope.d.ts +72 -0
  249. package/esm/src/kernel/default-scope.js +121 -0
  250. package/esm/src/kernel/engine/call-trace.d.ts +19 -0
  251. package/esm/src/kernel/engine/call-trace.js +29 -0
  252. package/esm/src/kernel/engine/compaction.d.ts +71 -0
  253. package/esm/src/kernel/engine/compaction.js +203 -0
  254. package/esm/src/kernel/engine/decision.d.ts +43 -0
  255. package/esm/src/kernel/engine/decision.js +439 -0
  256. package/esm/src/kernel/engine/embedding.d.ts +8 -0
  257. package/esm/src/kernel/engine/embedding.js +118 -0
  258. package/esm/src/kernel/engine/hash.d.ts +6 -0
  259. package/esm/src/kernel/engine/hash.js +22 -0
  260. package/esm/src/kernel/engine/live-inbound.d.ts +19 -0
  261. package/esm/src/kernel/engine/live-inbound.js +44 -0
  262. package/esm/src/kernel/engine/live-ingress.d.ts +15 -0
  263. package/esm/src/kernel/engine/live-ingress.js +42 -0
  264. package/esm/src/kernel/engine/record.d.ts +3 -0
  265. package/esm/src/kernel/engine/record.js +11 -0
  266. package/esm/src/kernel/engine/repair.d.ts +7 -0
  267. package/esm/src/kernel/engine/repair.js +36 -0
  268. package/esm/src/kernel/engine/runner/gates.d.ts +5 -0
  269. package/esm/src/kernel/engine/runner/gates.js +508 -0
  270. package/esm/src/kernel/engine/runner/mod.d.ts +29 -0
  271. package/esm/src/kernel/engine/runner/mod.js +625 -0
  272. package/esm/src/kernel/engine/runner/nested.d.ts +32 -0
  273. package/esm/src/kernel/engine/runner/nested.js +134 -0
  274. package/esm/src/kernel/engine/runner/schema-validation.d.ts +35 -0
  275. package/esm/src/kernel/engine/runner/schema-validation.js +179 -0
  276. package/esm/src/kernel/engine/runner/stages.d.ts +28 -0
  277. package/esm/src/kernel/engine/runner/stages.js +41 -0
  278. package/esm/src/kernel/engine/runner/state.d.ts +97 -0
  279. package/esm/src/kernel/engine/runner/state.js +50 -0
  280. package/esm/src/kernel/engine/runner/step-order.d.ts +27 -0
  281. package/esm/src/kernel/engine/runner/step-order.js +165 -0
  282. package/esm/src/kernel/engine/runner/steps.d.ts +14 -0
  283. package/esm/src/kernel/engine/runner/steps.js +519 -0
  284. package/esm/src/kernel/engine/runner/stream.d.ts +71 -0
  285. package/esm/src/kernel/engine/runner/stream.js +376 -0
  286. package/esm/src/kernel/engine/runner/usage.d.ts +45 -0
  287. package/esm/src/kernel/engine/runner/usage.js +148 -0
  288. package/esm/src/kernel/engine/session/mod.d.ts +33 -0
  289. package/esm/src/kernel/engine/session/mod.js +1182 -0
  290. package/esm/src/kernel/engine/session/session-trace.d.ts +115 -0
  291. package/esm/src/kernel/engine/session/session-trace.js +500 -0
  292. package/esm/src/kernel/engine/token-estimate.d.ts +23 -0
  293. package/esm/src/kernel/engine/token-estimate.js +38 -0
  294. package/esm/src/kernel/engine/tool-trace.d.ts +58 -0
  295. package/esm/src/kernel/engine/tool-trace.js +132 -0
  296. package/esm/src/kernel/engine/tree.d.ts +2 -0
  297. package/esm/src/kernel/engine/tree.js +17 -0
  298. package/esm/src/kernel/engine/turn-trace.d.ts +119 -0
  299. package/esm/src/kernel/engine/turn-trace.js +855 -0
  300. package/esm/src/kernel/engine/usage.d.ts +36 -0
  301. package/esm/src/kernel/engine/usage.js +151 -0
  302. package/esm/src/kernel/interaction-parts.d.ts +13 -0
  303. package/esm/src/kernel/interaction-parts.js +40 -0
  304. package/esm/src/kernel/json.d.ts +10 -0
  305. package/esm/src/kernel/json.js +3 -0
  306. package/esm/src/kernel/mod.d.ts +74 -0
  307. package/esm/src/kernel/mod.js +45 -0
  308. package/esm/src/kernel/profile-graph.d.ts +145 -0
  309. package/esm/src/kernel/profile-graph.js +158 -0
  310. package/esm/src/kernel/profile-presence.d.ts +18 -0
  311. package/esm/src/kernel/profile-presence.js +158 -0
  312. package/esm/src/kernel/profile-scope.d.ts +40 -0
  313. package/esm/src/kernel/profile-scope.js +274 -0
  314. package/esm/src/kernel/protocols/binding.d.ts +65 -0
  315. package/esm/src/kernel/protocols/binding.js +125 -0
  316. package/esm/src/kernel/protocols/limits.d.ts +15 -0
  317. package/esm/src/kernel/protocols/limits.js +28 -0
  318. package/esm/src/kernel/protocols/mod.d.ts +5 -0
  319. package/esm/src/kernel/protocols/mod.js +5 -0
  320. package/esm/src/kernel/protocols/prices.d.ts +36 -0
  321. package/esm/src/kernel/protocols/prices.js +37 -0
  322. package/esm/src/kernel/protocols/protocol.d.ts +253 -0
  323. package/esm/src/kernel/protocols/protocol.js +253 -0
  324. package/esm/src/kernel/protocols/provider.d.ts +108 -0
  325. package/esm/src/kernel/protocols/provider.js +143 -0
  326. package/esm/src/kernel/protocols/runtime.d.ts +55 -0
  327. package/esm/src/kernel/protocols/runtime.js +534 -0
  328. package/esm/src/kernel/provider-budget.d.ts +32 -0
  329. package/esm/src/kernel/provider-budget.js +262 -0
  330. package/esm/src/kernel/provider-dispatch.d.ts +13 -0
  331. package/esm/src/kernel/provider-dispatch.js +36 -0
  332. package/esm/src/kernel/provider-live.d.ts +7 -0
  333. package/esm/src/kernel/provider-live.js +189 -0
  334. package/esm/src/kernel/provider-runtime.d.ts +57 -0
  335. package/esm/src/kernel/provider-runtime.js +524 -0
  336. package/esm/src/kernel/registry/attachments.d.ts +46 -0
  337. package/esm/src/kernel/registry/attachments.js +220 -0
  338. package/esm/src/kernel/registry/catalog.d.ts +25 -0
  339. package/esm/src/kernel/registry/catalog.js +85 -0
  340. package/esm/src/kernel/registry/embedding-rules.d.ts +28 -0
  341. package/esm/src/kernel/registry/embedding-rules.js +66 -0
  342. package/esm/src/kernel/registry/ingress.d.ts +12 -0
  343. package/esm/src/kernel/registry/ingress.js +179 -0
  344. package/esm/src/kernel/registry/kernel-registry.d.ts +15 -0
  345. package/esm/src/kernel/registry/kernel-registry.js +15 -0
  346. package/esm/src/kernel/registry/profile-outputs.d.ts +3 -0
  347. package/esm/src/kernel/registry/profile-outputs.js +10 -0
  348. package/esm/src/kernel/registry/profiles.d.ts +116 -0
  349. package/esm/src/kernel/registry/profiles.js +773 -0
  350. package/esm/src/kernel/registry/provider-request.d.ts +6 -0
  351. package/esm/src/kernel/registry/provider-request.js +34 -0
  352. package/esm/src/kernel/registry/resolve.d.ts +17 -0
  353. package/esm/src/kernel/registry/resolve.js +238 -0
  354. package/esm/src/kernel/registry/schemas.d.ts +12 -0
  355. package/esm/src/kernel/registry/schemas.js +27 -0
  356. package/esm/src/kernel/registry/slot-fill.d.ts +7 -0
  357. package/esm/src/kernel/registry/slot-fill.js +22 -0
  358. package/esm/src/kernel/registry/sole-model.d.ts +2 -0
  359. package/esm/src/kernel/registry/sole-model.js +4 -0
  360. package/esm/src/kernel/registry/system-prompt.d.ts +8 -0
  361. package/esm/src/kernel/registry/system-prompt.js +32 -0
  362. package/esm/src/kernel/registry/system-role.d.ts +3 -0
  363. package/esm/src/kernel/registry/system-role.js +9 -0
  364. package/esm/src/kernel/registry/vault.d.ts +14 -0
  365. package/esm/src/kernel/registry/vault.js +1 -0
  366. package/esm/src/kernel/schema.d.ts +226 -0
  367. package/esm/src/kernel/schema.js +895 -0
  368. package/esm/src/kernel/scope.d.ts +29 -0
  369. package/esm/src/kernel/scope.js +45 -0
  370. package/esm/src/kernel/stages.d.ts +176 -0
  371. package/esm/src/kernel/stages.js +431 -0
  372. package/esm/src/kernel/stop.d.ts +116 -0
  373. package/esm/src/kernel/stop.js +137 -0
  374. package/esm/src/kernel/system-parts.d.ts +26 -0
  375. package/esm/src/kernel/system-parts.js +98 -0
  376. package/esm/src/kernel/tools/activity-label.d.ts +22 -0
  377. package/esm/src/kernel/tools/activity-label.js +435 -0
  378. package/esm/src/kernel/tools/agent.d.ts +66 -0
  379. package/esm/src/kernel/tools/agent.js +212 -0
  380. package/esm/src/kernel/tools/coordinate.d.ts +4 -0
  381. package/esm/src/kernel/tools/coordinate.js +165 -0
  382. package/esm/src/kernel/tools/events.d.ts +66 -0
  383. package/esm/src/kernel/tools/events.js +184 -0
  384. package/esm/src/kernel/tools/execute.d.ts +100 -0
  385. package/esm/src/kernel/tools/execute.js +1173 -0
  386. package/esm/src/kernel/tools/gate-answer.d.ts +60 -0
  387. package/esm/src/kernel/tools/gate-answer.js +65 -0
  388. package/esm/src/kernel/tools/handler-events.d.ts +45 -0
  389. package/esm/src/kernel/tools/handler-events.js +106 -0
  390. package/esm/src/kernel/tools/harness.d.ts +17 -0
  391. package/esm/src/kernel/tools/harness.js +43 -0
  392. package/esm/src/kernel/tools/http-limit.d.ts +27 -0
  393. package/esm/src/kernel/tools/http-limit.js +85 -0
  394. package/esm/src/kernel/tools/invoke.d.ts +32 -0
  395. package/esm/src/kernel/tools/invoke.js +282 -0
  396. package/esm/src/kernel/tools/mcp-sessions.d.ts +23 -0
  397. package/esm/src/kernel/tools/mcp-sessions.js +69 -0
  398. package/esm/src/kernel/tools/mod.d.ts +10 -0
  399. package/esm/src/kernel/tools/mod.js +7 -0
  400. package/esm/src/kernel/tools/model-text.d.ts +16 -0
  401. package/esm/src/kernel/tools/model-text.js +31 -0
  402. package/esm/src/kernel/tools/operation.d.ts +76 -0
  403. package/esm/src/kernel/tools/operation.js +100 -0
  404. package/esm/src/kernel/tools/page-answer.d.ts +8 -0
  405. package/esm/src/kernel/tools/page-answer.js +19 -0
  406. package/esm/src/kernel/tools/permission.d.ts +15 -0
  407. package/esm/src/kernel/tools/permission.js +38 -0
  408. package/esm/src/kernel/tools/project.d.ts +11 -0
  409. package/esm/src/kernel/tools/project.js +55 -0
  410. package/esm/src/kernel/tools/registry.d.ts +27 -0
  411. package/esm/src/kernel/tools/registry.js +143 -0
  412. package/esm/src/kernel/tools/remote.d.ts +144 -0
  413. package/esm/src/kernel/tools/remote.js +1125 -0
  414. package/esm/src/kernel/tools/resolve.d.ts +31 -0
  415. package/esm/src/kernel/tools/resolve.js +267 -0
  416. package/esm/src/kernel/tools/run.d.ts +28 -0
  417. package/esm/src/kernel/tools/run.js +86 -0
  418. package/esm/src/kernel/tools/schema.d.ts +10 -0
  419. package/esm/src/kernel/tools/schema.js +95 -0
  420. package/esm/src/kernel/tools/signed-in-fetch.d.ts +19 -0
  421. package/esm/src/kernel/tools/signed-in-fetch.js +45 -0
  422. package/esm/src/kernel/tools/stage-run.d.ts +116 -0
  423. package/esm/src/kernel/tools/stage-run.js +198 -0
  424. package/esm/src/kernel/tools/types.d.ts +497 -0
  425. package/esm/src/kernel/tools/types.js +1 -0
  426. package/esm/src/kernel/tools/unchecked-output.d.ts +14 -0
  427. package/esm/src/kernel/tools/unchecked-output.js +18 -0
  428. package/esm/src/kernel/turn-events.d.ts +776 -0
  429. package/esm/src/kernel/turn-events.js +543 -0
  430. package/esm/src/kernel/types.d.ts +1025 -0
  431. package/esm/src/kernel/types.js +1 -0
  432. package/esm/src/kernel/util/base64.d.ts +4 -0
  433. package/esm/src/kernel/util/base64.js +15 -0
  434. package/esm/src/kernel/util/exact-type.d.ts +31 -0
  435. package/esm/src/kernel/util/exact-type.js +1 -0
  436. package/esm/src/kernel/util/find-last.d.ts +3 -0
  437. package/esm/src/kernel/util/find-last.js +9 -0
  438. package/esm/src/kernel/util/mime.d.ts +2 -0
  439. package/esm/src/kernel/util/mime.js +4 -0
  440. package/esm/src/kernel/util/partial-json.d.ts +23 -0
  441. package/esm/src/kernel/util/partial-json.js +128 -0
  442. package/esm/src/kernel/util/record.d.ts +2 -0
  443. package/esm/src/kernel/util/record.js +4 -0
  444. package/esm/src/observability/destinations.d.ts +14 -0
  445. package/esm/src/observability/destinations.js +43 -0
  446. package/esm/src/observability/jsonl.d.ts +18 -0
  447. package/esm/src/observability/jsonl.js +110 -0
  448. package/esm/src/observability/mod.d.ts +22 -0
  449. package/esm/src/observability/mod.js +16 -0
  450. package/esm/src/observability/openinference.d.ts +11 -0
  451. package/esm/src/observability/openinference.js +205 -0
  452. package/esm/src/observability/otlp.d.ts +71 -0
  453. package/esm/src/observability/otlp.js +98 -0
  454. package/esm/src/observability/phoenix.d.ts +30 -0
  455. package/esm/src/observability/phoenix.js +71 -0
  456. package/esm/src/observability/policy.d.ts +17 -0
  457. package/esm/src/observability/policy.js +73 -0
  458. package/esm/src/observability/resolve-policy.d.ts +8 -0
  459. package/esm/src/observability/resolve-policy.js +64 -0
  460. package/esm/src/observability/spans.d.ts +22 -0
  461. package/esm/src/observability/spans.js +72 -0
  462. package/esm/src/observability/trace-catalog.d.ts +128 -0
  463. package/esm/src/observability/trace-catalog.js +906 -0
  464. package/esm/src/observability/trace-record.d.ts +23 -0
  465. package/esm/src/observability/trace-record.js +228 -0
  466. package/esm/src/observability/trace-schema.d.ts +57 -0
  467. package/esm/src/observability/trace-schema.js +59 -0
  468. package/esm/src/observability/trace-sink.d.ts +14 -0
  469. package/esm/src/observability/trace-sink.js +3 -0
  470. package/esm/src/observability/trace-span.d.ts +98 -0
  471. package/esm/src/observability/trace-span.js +201 -0
  472. package/esm/src/observability/trace.d.ts +13 -0
  473. package/esm/src/observability/trace.js +37 -0
  474. package/esm/src/observability/types.d.ts +109 -0
  475. package/esm/src/observability/types.js +3 -0
  476. package/esm/src/presets/google/speech-voices.d.ts +9 -0
  477. package/esm/src/presets/google/speech-voices.js +38 -0
  478. package/esm/src/presets/google-limits.d.ts +13 -0
  479. package/esm/src/presets/google-limits.js +18 -0
  480. package/esm/src/presets/google.d.ts +119 -0
  481. package/esm/src/presets/google.js +197 -0
  482. package/esm/src/presets/local.d.ts +26 -0
  483. package/esm/src/presets/local.js +30 -0
  484. package/esm/src/presets/mod.d.ts +11 -0
  485. package/esm/src/presets/mod.js +9 -0
  486. package/esm/src/presets/openrouter.d.ts +26 -0
  487. package/esm/src/presets/openrouter.js +31 -0
  488. package/esm/src/providers/embedding-limits.d.ts +7 -0
  489. package/esm/src/providers/embedding-limits.js +12 -0
  490. package/esm/src/providers/gemini/embedding-protocol.d.ts +8 -0
  491. package/esm/src/providers/gemini/embedding-protocol.js +125 -0
  492. package/esm/src/providers/gemini/interactions-protocol.d.ts +8 -0
  493. package/esm/src/providers/gemini/interactions-protocol.js +105 -0
  494. package/esm/src/providers/gemini/live-protocol.d.ts +3 -0
  495. package/esm/src/providers/gemini/live-protocol.js +191 -0
  496. package/esm/src/providers/gemini/prices.d.ts +3 -0
  497. package/esm/src/providers/gemini/prices.js +63 -0
  498. package/esm/src/providers/gemini/provider.d.ts +7 -0
  499. package/esm/src/providers/gemini/provider.js +39 -0
  500. package/esm/src/providers/google/api-error.d.ts +8 -0
  501. package/esm/src/providers/google/api-error.js +123 -0
  502. package/esm/src/providers/google/builtins.d.ts +14 -0
  503. package/esm/src/providers/google/builtins.js +57 -0
  504. package/esm/src/providers/google/grounding.d.ts +5 -0
  505. package/esm/src/providers/google/grounding.js +226 -0
  506. package/esm/src/providers/google/interactions/framing.d.ts +27 -0
  507. package/esm/src/providers/google/interactions/framing.js +304 -0
  508. package/esm/src/providers/google/interactions/steps.d.ts +12 -0
  509. package/esm/src/providers/google/interactions/steps.js +200 -0
  510. package/esm/src/providers/google/interactions/stream.d.ts +23 -0
  511. package/esm/src/providers/google/interactions/stream.js +230 -0
  512. package/esm/src/providers/google/live/framing.d.ts +61 -0
  513. package/esm/src/providers/google/live/framing.js +597 -0
  514. package/esm/src/providers/google/live/stream.d.ts +13 -0
  515. package/esm/src/providers/google/live/stream.js +57 -0
  516. package/esm/src/providers/google/thinking.d.ts +3 -0
  517. package/esm/src/providers/google/thinking.js +8 -0
  518. package/esm/src/providers/google/urls.d.ts +4 -0
  519. package/esm/src/providers/google/urls.js +4 -0
  520. package/esm/src/providers/google/usage.d.ts +7 -0
  521. package/esm/src/providers/google/usage.js +49 -0
  522. package/esm/src/providers/live.d.ts +6 -0
  523. package/esm/src/providers/live.js +6 -0
  524. package/esm/src/providers/local/embedding-protocol.d.ts +7 -0
  525. package/esm/src/providers/local/embedding-protocol.js +60 -0
  526. package/esm/src/providers/local/provider.d.ts +7 -0
  527. package/esm/src/providers/local/provider.js +28 -0
  528. package/esm/src/providers/mod.d.ts +32 -0
  529. package/esm/src/providers/mod.js +23 -0
  530. package/esm/src/providers/open-ai/protocol.d.ts +3 -0
  531. package/esm/src/providers/open-ai/protocol.js +189 -0
  532. package/esm/src/providers/openrouter/embedding-protocol.d.ts +6 -0
  533. package/esm/src/providers/openrouter/embedding-protocol.js +86 -0
  534. package/esm/src/providers/openrouter/image.d.ts +15 -0
  535. package/esm/src/providers/openrouter/image.js +34 -0
  536. package/esm/src/providers/openrouter/images-protocol.d.ts +3 -0
  537. package/esm/src/providers/openrouter/images-protocol.js +82 -0
  538. package/esm/src/providers/openrouter/openai/compat.d.ts +19 -0
  539. package/esm/src/providers/openrouter/openai/compat.js +162 -0
  540. package/esm/src/providers/openrouter/openai/image-payload.d.ts +9 -0
  541. package/esm/src/providers/openrouter/openai/image-payload.js +115 -0
  542. package/esm/src/providers/openrouter/openai/reasoning-state.d.ts +2 -0
  543. package/esm/src/providers/openrouter/openai/reasoning-state.js +31 -0
  544. package/esm/src/providers/openrouter/openai/usage.d.ts +8 -0
  545. package/esm/src/providers/openrouter/openai/usage.js +56 -0
  546. package/esm/src/providers/openrouter/protocol.d.ts +8 -0
  547. package/esm/src/providers/openrouter/protocol.js +171 -0
  548. package/esm/src/providers/openrouter/provider.d.ts +10 -0
  549. package/esm/src/providers/openrouter/provider.js +50 -0
  550. package/esm/src/providers/shared/carried-tool-files.d.ts +7 -0
  551. package/esm/src/providers/shared/carried-tool-files.js +43 -0
  552. package/esm/src/providers/shared/pcm.d.ts +14 -0
  553. package/esm/src/providers/shared/pcm.js +78 -0
  554. package/esm/src/providers/shared/protocol-events.d.ts +8 -0
  555. package/esm/src/providers/shared/protocol-events.js +20 -0
  556. package/esm/src/providers/shared/response-identity.d.ts +11 -0
  557. package/esm/src/providers/shared/response-identity.js +12 -0
  558. package/esm/src/providers/shared/retry.d.ts +17 -0
  559. package/esm/src/providers/shared/retry.js +90 -0
  560. package/esm/src/providers/shared/sse.d.ts +6 -0
  561. package/esm/src/providers/shared/sse.js +93 -0
  562. package/esm/src/providers/shared/structured-output.d.ts +4 -0
  563. package/esm/src/providers/shared/structured-output.js +11 -0
  564. package/esm/src/providers/shared/tool-args.d.ts +24 -0
  565. package/esm/src/providers/shared/tool-args.js +88 -0
  566. package/esm/src/providers/shared/tool-draft.d.ts +16 -0
  567. package/esm/src/providers/shared/tool-draft.js +14 -0
  568. package/esm/src/providers/shared/upstream-tap.d.ts +8 -0
  569. package/esm/src/providers/shared/upstream-tap.js +85 -0
  570. package/esm/src/providers/shared/upstream-tape.d.ts +6 -0
  571. package/esm/src/providers/shared/upstream-tape.js +88 -0
  572. package/esm/src/providers/system-one/protocol.d.ts +8 -0
  573. package/esm/src/providers/system-one/protocol.js +93 -0
  574. package/esm/src/providers/types.d.ts +51 -0
  575. package/esm/src/providers/types.js +2 -0
  576. package/esm/src/providers/typesafe/provider.d.ts +7 -0
  577. package/esm/src/providers/typesafe/provider.js +24 -0
  578. package/esm/src/surface/formats.d.ts +46 -0
  579. package/esm/src/surface/formats.js +178 -0
  580. package/esm/src/surface/mod.d.ts +16 -0
  581. package/esm/src/surface/mod.js +12 -0
  582. package/esm/src/surface/runtime.d.ts +44 -0
  583. package/esm/src/surface/runtime.js +441 -0
  584. package/esm/src/surface/tools.d.ts +9 -0
  585. package/esm/src/surface/tools.js +62 -0
  586. package/esm/src/surface/types.d.ts +110 -0
  587. package/esm/src/surface/types.js +4 -0
  588. package/package.json +100 -4
@@ -0,0 +1,895 @@
1
+ /**
2
+ * Closed unions and the profile field catalog. No Deno APIs, so host UIs and docs can import it.
3
+ *
4
+ * @module
5
+ */
6
+ /** labels-exempt-file: authoring field-meta / closed unions — not runtime user or model copy (P2) */
7
+ import "../../_dnt.polyfills.js";
8
+ import { BOUNDARIES, BOUNDARY_META, recordOf } from '../guardrails/boundaries.js';
9
+ import { DETECT_ACTION_META, DETECT_ACTIONS, DETECT_DEFAULTS, DETECTOR_BOUNDARIES, DETECTOR_META, DETECTORS, } from '../guardrails/detectors.js';
10
+ import { LABEL_NOTES } from '../guardrails/labels.js';
11
+ import { BLOCKED_REPLY_ON_BLOCK, DESTINATION_GATES, TAINT_GATES, } from '../guardrails/types.js';
12
+ import { GOOGLE_SPEECH_VOICES } from '../presets/google/speech-voices.js';
13
+ import { PROFILE_FIELD_PRESENCE } from './profile-presence.js';
14
+ import { isProfileRootField, profileFieldScope } from './profile-scope.js';
15
+ export { BLOCKED_REPLY_ON_BLOCK };
16
+ /** The kinds of profile: each fixes which fields and models a profile may use. */
17
+ export const PROFILE_TYPES = [
18
+ 'text',
19
+ 'image',
20
+ 'speech',
21
+ 'live',
22
+ 'decision',
23
+ 'embedding',
24
+ 'host',
25
+ ];
26
+ /** Reasoning effort levels, lowest to highest; a model accepts only the levels its catalog row lists. */
27
+ export const THINKING_LEVELS = [
28
+ 'none',
29
+ 'minimal',
30
+ 'low',
31
+ 'medium',
32
+ 'high',
33
+ 'xhigh',
34
+ 'max',
35
+ ];
36
+ /** The longest a profile's `id` may be, in characters: room for a dotted or generated one. */
37
+ export const PROFILE_ID_MAX_CHARS = 64;
38
+ /** The longest a profile's `identity.handle` may be, in characters: it is a name people read. */
39
+ export const PROFILE_HANDLE_MAX_CHARS = 32;
40
+ /** Letters, digits, `-`, and `_`, up to 32 characters, starting with a letter or digit. */
41
+ export const KEY_SLOT_NAME = /^[A-Za-z0-9][A-Za-z0-9_-]{0,31}$/;
42
+ /** True when the value is a legal key slot name. */
43
+ export function isKeySlotName(value) {
44
+ return typeof value === 'string' && KEY_SLOT_NAME.test(value);
45
+ }
46
+ /** The kinds of media a model can take as input. */
47
+ export const MEDIA_INPUT_KIND_VALUES = ['image', 'audio', 'video', 'document'];
48
+ /** Whether thought summaries are asked for (`auto`) or not (`none`). */
49
+ export const SUMMARY_MODES = ['auto', 'none'];
50
+ /** Whether the provider call streams (`sse`) or is one buffered call. */
51
+ export const STREAM_MODES = ['sse', 'buffered'];
52
+ /** Audio encodings a speech profile can return. */
53
+ export const SPEECH_AUDIO_FORMATS = ['pcm', 'mp3'];
54
+ /** Who can send a turn its context: the browser, or the host's own code. */
55
+ /** How long a caller is away, in milliseconds, before `live.resumed.prompt` is sent, when the profile sets no `afterMs`. */
56
+ export const DEFAULT_RESUMED_AFTER_MS = 3000;
57
+ export const CONTEXT_SENDERS = ['client', 'server'];
58
+ /** What the user starting to speak does to a live model that is mid-reply. */
59
+ export const LIVE_ACTIVITY_HANDLINGS = ['START_OF_ACTIVITY_INTERRUPTS', 'NO_INTERRUPTION'];
60
+ /** How readily live voice detection decides the user has started speaking. */
61
+ export const LIVE_START_SENSITIVITIES = [
62
+ 'START_SENSITIVITY_LOW',
63
+ 'START_SENSITIVITY_HIGH',
64
+ ];
65
+ /** How readily live voice detection decides the user has stopped speaking. */
66
+ export const LIVE_END_SENSITIVITIES = ['END_SENSITIVITY_LOW', 'END_SENSITIVITY_HIGH'];
67
+ /** What compaction counts against its token limit: the stored history or the next request's input. */
68
+ export const COMPACTION_METERS = ['history', 'input'];
69
+ /** Whether compaction runs before or after a turn. */
70
+ export const COMPACTION_TIMINGS = ['before', 'after'];
71
+ /**
72
+ * - `compacted`: a summary replaced the compacted messages.
73
+ * - `deferred`: the compactor failed and the history still fits `maxTokens`, so it is kept whole.
74
+ * - `dropped`: the compactor failed over `maxTokens`, so the compacted messages were dropped.
75
+ */
76
+ export const COMPACTION_OUTCOMES = ['compacted', 'deferred', 'dropped'];
77
+ /** Which part of the prompt is cached: the whole request (`automatic`) or the system instruction only (`system`). */
78
+ export const CACHE_MODES = ['automatic', 'system'];
79
+ /** How long a provider keeps a cached prompt. */
80
+ export const CACHE_TTLS = ['5m', '1h'];
81
+ /** Why a turn stopped, as `done.stop.kind` reports it. */
82
+ export const TURN_STOP_KINDS = [
83
+ 'completed',
84
+ 'length',
85
+ /** The model called tools and the turn hands them to the host (`done.tools`). */
86
+ 'tool',
87
+ /** `pre_tool` blocked the body; the host resumes via invokeTool/executeTool, not continueFrom. */
88
+ 'gate',
89
+ 'filtered',
90
+ 'provider_error',
91
+ 'cancelled',
92
+ 'stream_incomplete',
93
+ /** The turn made its last allowed model call and that call asked for tools: there is no answer. */
94
+ 'step_limit',
95
+ 'interrupted',
96
+ /** Live: model finished generating audio/text for this utterance; turn may still be open. */
97
+ 'generation_complete',
98
+ ];
99
+ /** What a text turn's last allowed model call may do, as `turnBehaviour.atStepLimit` sets it. */
100
+ export const STEP_LIMIT_MODES = ['stop', 'answer'];
101
+ /** What happens to a list item its check refuses, as `outputs.validation.items.*.onFail` sets it. */
102
+ export const ITEM_FAIL_ACTIONS = ['drop', 'fix'];
103
+ /** Every other stop resumes by another host path, or not at all. */
104
+ export const CONTINUE_STOP_KINDS = ['length', 'stream_incomplete', 'provider_error'];
105
+ /** The points in a turn where a stage handler runs. */
106
+ export const TURN_STAGES = [
107
+ 'pre_turn',
108
+ 'pre_tool',
109
+ 'post_tool',
110
+ 'before_end',
111
+ 'post_turn',
112
+ ];
113
+ const TURN_STAGE_SET = new Set(TURN_STAGES);
114
+ /** True when the value names a turn stage. */
115
+ export function isTurnStage(value) {
116
+ return typeof value === 'string' && TURN_STAGE_SET.has(value);
117
+ }
118
+ /** Stages where an inject can land; the inject gate still applies. */
119
+ export const TURN_INJECT_STAGES = ['pre_turn', 'post_tool', 'before_end'];
120
+ const TURN_INJECT_STAGE_SET = new Set(TURN_INJECT_STAGES);
121
+ /** True when the value names a stage an inject can land in. */
122
+ export function isTurnInjectStage(value) {
123
+ return typeof value === 'string' && TURN_INJECT_STAGE_SET.has(value);
124
+ }
125
+ /** `pre_tool` gates; not `awaiting_user_input`. `page` holds a call for the page that answers it. */
126
+ export const TOOL_GATE_KINDS = ['confirmation', 'permission', 'auth', 'page'];
127
+ /** Why a refused gate settles: the user said no, walked away, or let it run out. */
128
+ export const TOOL_RESUME_CAUSES = ['declined', 'abandoned', 'expired'];
129
+ const TOOL_GATE_KIND_SET = new Set(TOOL_GATE_KINDS);
130
+ /** True when the value names a tool gate kind. */
131
+ export function isToolGateKind(value) {
132
+ return typeof value === 'string' && TOOL_GATE_KIND_SET.has(value);
133
+ }
134
+ /** The questions a turn can pause to ask the user. */
135
+ export const AWAITING_USER_INPUT_KINDS = ['confirm', 'choice', 'text'];
136
+ /** Why a stage handler's result was partly or wholly ignored. */
137
+ export const STAGE_APPLY_WARNING_CODES = [
138
+ 'affordance_not_allowed',
139
+ 'inject_not_allowed',
140
+ 'inject_rejected_max_steps',
141
+ 'inject_invalid_messages',
142
+ 'inject_id_invalid',
143
+ 'deny_invalid',
144
+ 'confirm_invalid',
145
+ 'mutate_invalid',
146
+ 'label_failed_invalid',
147
+ 'abort_invalid',
148
+ 'wait_for_invalid',
149
+ 'unknown_field',
150
+ 'result_invalid',
151
+ ];
152
+ /** The `status` of a tool output that asks the user a question. */
153
+ export const AWAITING_USER_INPUT_STATUS = 'awaiting_user_input';
154
+ /** Enforced by the kernel at resolve time. */
155
+ export const TOOL_LOAD_TIERS = ['T0', 'T2'];
156
+ /** The HTTP methods an `http` tool may use. */
157
+ export const HTTP_METHODS = ['GET', 'POST', 'PUT', 'PATCH', 'DELETE'];
158
+ /** When remote tool auth is missing or expired. */
159
+ export const AUTH_UNAUTHENTICATED_POLICIES = ['gate', 'report_to_model', 'fail'];
160
+ /** The kinds of tool a profile can list. */
161
+ export const TOOL_TYPES = ['builtin', 'function', 'http', 'mcp', 'agent'];
162
+ /** How much a tool can change: nothing, data, or irreversibly. */
163
+ export const TOOL_ACCESS = ['read-only', 'read-write', 'destructive'];
164
+ /** When the user must approve a tool call: never, once per session, or every call. */
165
+ export const TOOL_PERMISSION = ['auto', 'session_consent', 'always_confirm'];
166
+ /** The credential shapes a remote tool can authenticate with. */
167
+ export const TOOL_AUTH_TYPES = ['bearer', 'api_key', 'oauth2'];
168
+ /** Adds UI-only `none`, which omits auth at compile time. */
169
+ export const STUDIO_AUTH_TYPES = ['none', ...TOOL_AUTH_TYPES];
170
+ /**
171
+ * The package's complete media-input vocabulary: `assertMediaMime` refuses any MIME not
172
+ * here, so hosts keep no second table. Rows follow Google Interactions / Live's documented
173
+ * lists (verified 2026-09-12), the widest provider; TypeScript, `application/xml` and
174
+ * `application/rtf` are not on Google's list. OpenAI-compat adapters forward the MIME
175
+ * verbatim and add no rows. Provider alias essences (`image/jpg`, `video/mov`, …) are rows;
176
+ * `resolveInputParts` canonicalizes `image/jpg` to `image/jpeg` on the wire.
177
+ */
178
+ export const MEDIA_INPUT_KINDS = {
179
+ 'image/png': 'image',
180
+ 'image/jpeg': 'image',
181
+ 'image/jpg': 'image',
182
+ 'image/webp': 'image',
183
+ 'image/heic': 'image',
184
+ 'image/heif': 'image',
185
+ 'audio/wav': 'audio',
186
+ 'audio/x-wav': 'audio',
187
+ 'audio/mpeg': 'audio',
188
+ 'audio/mp3': 'audio',
189
+ 'audio/aiff': 'audio',
190
+ 'audio/aac': 'audio',
191
+ 'audio/ogg': 'audio',
192
+ 'audio/flac': 'audio',
193
+ 'audio/webm': 'audio',
194
+ 'audio/mp4': 'audio',
195
+ 'audio/pcm': 'audio',
196
+ 'audio/m4a': 'audio',
197
+ 'audio/opus': 'audio',
198
+ 'audio/l16': 'audio',
199
+ 'audio/alaw': 'audio',
200
+ 'audio/mulaw': 'audio',
201
+ 'video/mp4': 'video',
202
+ 'video/mpeg': 'video',
203
+ 'video/quicktime': 'video',
204
+ 'video/mov': 'video',
205
+ 'video/x-msvideo': 'video',
206
+ 'video/avi': 'video',
207
+ 'video/x-flv': 'video',
208
+ 'video/mpg': 'video',
209
+ 'video/webm': 'video',
210
+ 'video/wmv': 'video',
211
+ 'video/x-ms-wmv': 'video',
212
+ 'video/3gpp': 'video',
213
+ 'application/pdf': 'document',
214
+ 'text/plain': 'document',
215
+ 'text/csv': 'document',
216
+ 'text/markdown': 'document',
217
+ 'text/md': 'document',
218
+ 'text/html': 'document',
219
+ 'text/css': 'document',
220
+ 'text/xml': 'document',
221
+ 'text/rtf': 'document',
222
+ 'text/javascript': 'document',
223
+ 'application/x-javascript': 'document',
224
+ 'text/x-python': 'document',
225
+ 'application/x-python': 'document',
226
+ 'application/json': 'document',
227
+ };
228
+ /** Type-prefix wildcards accepted by `mimeAllowed`. */
229
+ export const MEDIA_WILDCARDS = ['image/*', 'audio/*', 'video/*'];
230
+ function mimesOf(kind) {
231
+ return Object.keys(MEDIA_INPUT_KINDS).filter((mime) => MEDIA_INPUT_KINDS[mime] === kind);
232
+ }
233
+ /** The MIME types a text profile's `accept` entries may list. */
234
+ export const ATTACHMENT_ACCEPT_MIMES = [
235
+ 'image/*',
236
+ 'video/*',
237
+ ...mimesOf('image'),
238
+ ...mimesOf('video'),
239
+ ...mimesOf('document'),
240
+ ];
241
+ /**
242
+ * The attachment `accept` values an image profile may list: images, video and
243
+ * PDF, the inputs image models document reading. Also the allowlist each of its
244
+ * `accept` entries must fall within.
245
+ */
246
+ export const IMAGE_ATTACHMENT_ACCEPT_MIMES = [
247
+ 'image/*',
248
+ 'video/*',
249
+ ...mimesOf('image'),
250
+ ...mimesOf('video'),
251
+ 'application/pdf',
252
+ ];
253
+ /** The MIME types a voice profile's `accept` entries may list. */
254
+ export const VOICE_ACCEPT_MIMES = ['audio/*', ...mimesOf('audio')];
255
+ function unionType(values) {
256
+ return values.map((value) => `'${value}'`).join(' | ');
257
+ }
258
+ function field(type, doc, options, optionDescriptionsOrNote, optionNote) {
259
+ if (options) {
260
+ if (typeof optionDescriptionsOrNote === 'object') {
261
+ return optionNote
262
+ ? { type, doc, options, optionDescriptions: optionDescriptionsOrNote, optionNote }
263
+ : { type, doc, options, optionDescriptions: optionDescriptionsOrNote };
264
+ }
265
+ if (typeof optionDescriptionsOrNote === 'string') {
266
+ return { type, doc, options, optionNote: optionDescriptionsOrNote };
267
+ }
268
+ return { type, doc, options };
269
+ }
270
+ return { type, doc };
271
+ }
272
+ /**
273
+ * Parents whose next key is a host-owned map key (model id, slot name, …).
274
+ * The annotator substitutes `*` so `models.flash.apiId` → `models.*.apiId`.
275
+ */
276
+ export const DYNAMIC_FIELD_PARENTS = new Set([
277
+ 'models',
278
+ 'models.*.efforts',
279
+ 'identity.systemByRole',
280
+ 'labels',
281
+ 'inputs.slots',
282
+ 'inputs.limitsByMime',
283
+ 'outputs.validation.fields',
284
+ 'outputs.validation.items',
285
+ ]);
286
+ /** Turns a key path into its catalog path, replacing host-chosen map keys with `*`. */
287
+ export function catalogPathFor(keys) {
288
+ const [first] = keys;
289
+ if (keys.length === 1 && first !== undefined && isProfileRootField(first))
290
+ return `profile.${first}`;
291
+ const resolved = [];
292
+ for (const key of keys) {
293
+ const prefix = resolved.join('.');
294
+ if (DYNAMIC_FIELD_PARENTS.has(prefix)) {
295
+ resolved.push('*');
296
+ }
297
+ else {
298
+ resolved.push(key);
299
+ }
300
+ }
301
+ return resolved.join('.');
302
+ }
303
+ const DETECT_ACTION_DOCS = recordOf(DETECT_ACTIONS, (action) => DETECT_ACTION_META[action].doc);
304
+ /** The `allow` rows of a detector: the URLs it lets through, or for `tool_leak` the names. */
305
+ function allowFields(path, detector) {
306
+ if (DETECTOR_META[detector].allow === 'names') {
307
+ return [
308
+ [`${path}.allow`, field('NameAllow', 'The names that are innocent in a reply.')],
309
+ [
310
+ `${path}.allow.names`,
311
+ {
312
+ ...field('string[]', 'Names of tools or parameters that are not read for, such as a tool called search.'),
313
+ unset: 'None',
314
+ },
315
+ ],
316
+ ];
317
+ }
318
+ const hosts = detector === 'ungiven_links'
319
+ ? 'Hostnames whose links pass whatever their URL; the hosts ungiven_images allows pass too.'
320
+ : 'Hostnames whose images load whatever their URL, such as your own CDN.';
321
+ return [
322
+ [
323
+ `${path}.allow`,
324
+ field('UrlAllow', 'What passes besides the URLs the model was given this turn.'),
325
+ ],
326
+ [`${path}.allow.hosts`, { ...field('string[]', hosts), unset: 'None' }],
327
+ [
328
+ `${path}.allow.fromTools`,
329
+ {
330
+ ...field('boolean', 'Whether a URL a tool returned counts as given. Off keeps only what the system prompt, the user, and history gave.'),
331
+ unset: 'On',
332
+ },
333
+ ],
334
+ ];
335
+ }
336
+ const COMPILED_DOC = 'The table your patterns compile to, from compileDetect or `agents detect-compile`. Needed whenever patterns is set.';
337
+ /** The rows of one pattern in a detector's `patterns`. */
338
+ function patternRows(path) {
339
+ const each = `${path}.patterns.*`;
340
+ return [
341
+ [`${each}.name`, field('string', 'What a match is called in the trace.')],
342
+ [
343
+ `${each}.pattern`,
344
+ field('string', 'The source of a regular expression. A pattern takes this or words.'),
345
+ ],
346
+ [
347
+ `${each}.flags`,
348
+ {
349
+ ...field('string', 'Regular-expression flags, each a letter: i ignores case, m matches ^ and $ at each line, s lets . match a line break, u reads Unicode. Not g or y: every match is always found.'),
350
+ unset: 'None',
351
+ },
352
+ ],
353
+ [
354
+ `${each}.words`,
355
+ field('string[]', 'Words to match whole, whatever their case. A space in one matches any run of whitespace.'),
356
+ ],
357
+ ];
358
+ }
359
+ /** The rows of a detector of the host's own, under a key with a dot. */
360
+ function hostDetectorFields(path) {
361
+ const action = (doc) => field('DetectAction', doc, DETECT_ACTIONS, DETECT_ACTION_DOCS);
362
+ return [
363
+ [
364
+ path,
365
+ field('HostDetectorConfig', 'Your own detector, keyed with a dot: acme.codenames. No default action.'),
366
+ ],
367
+ [`${path}.label`, field('string', 'What an editor and the trace call it.')],
368
+ [
369
+ `${path}.action`,
370
+ {
371
+ ...action('What a match does, at every boundary.'),
372
+ unset: 'Only the boundaries at names are read',
373
+ },
374
+ ],
375
+ [`${path}.at`, field('{ [boundary]: DetectAction }', 'An action per boundary, over action.')],
376
+ ...BOUNDARIES.map((boundary) => [
377
+ `${path}.at.${boundary}`,
378
+ { ...action(BOUNDARY_META[boundary].doc), unset: DETECT_ACTION_META.ignore.label },
379
+ ]),
380
+ [
381
+ `${path}.patterns`,
382
+ {
383
+ ...field('HostPattern[]', 'Its patterns, each a name and a regular expression or a list of words, read on the text as written.'),
384
+ unset: 'None',
385
+ },
386
+ ],
387
+ ...patternRows(path),
388
+ [`${path}.compiled`, field('CompiledPatterns', COMPILED_DOC)],
389
+ [
390
+ `${path}.hint`,
391
+ {
392
+ ...field('string', 'One line telling the model what to leave out, sent when this detector blocks a reply that is then retried.'),
393
+ unset: 'The labels’s detect.hint.own, which names the label',
394
+ },
395
+ ],
396
+ [
397
+ `${path}.find`,
398
+ field('HostFind', 'Its own reading, for what patterns cannot say: a function that returns where the matches start and end. It runs on every text crossing a boundary the detector reads, so it returns at once.'),
399
+ ],
400
+ ];
401
+ }
402
+ /** The rows of a detector that reads with patterns: whose it reads with. */
403
+ function patternFields(path) {
404
+ return [
405
+ [
406
+ `${path}.theorem`,
407
+ {
408
+ ...field('boolean', 'Whether Theorem’s own patterns run. Off with no patterns of your own turns the detector off.'),
409
+ unset: 'On',
410
+ },
411
+ ],
412
+ [
413
+ `${path}.patterns`,
414
+ {
415
+ ...field('HostPattern[]', 'Your own patterns, each a name and a regular expression or a list of words. A match takes this detector’s action.'),
416
+ unset: 'None',
417
+ },
418
+ ],
419
+ ...patternRows(path),
420
+ [`${path}.compiled`, field('CompiledPatterns', COMPILED_DOC)],
421
+ [
422
+ `${path}.hint`,
423
+ {
424
+ ...field('string', 'One line telling the model what to leave out, sent when this detector blocks a reply that is then retried. Set it beside patterns of your own.'),
425
+ unset: `The labels’s detect.hint line for this detector`,
426
+ },
427
+ ],
428
+ ];
429
+ }
430
+ /** The settings a detector's full form takes, as a sentence lists them. */
431
+ function settingsOf(detector) {
432
+ const { allow, patterns } = DETECTOR_META[detector];
433
+ if (allow && patterns)
434
+ return 'action, at, allow, theorem, patterns, and hint';
435
+ if (allow)
436
+ return 'action, at, and allow';
437
+ return patterns ? 'action, at, theorem, patterns, and hint' : 'action and at';
438
+ }
439
+ /** The `guardrails.detect` rows: one for the setting, one per detector, and one per detector and boundary. */
440
+ function detectFields() {
441
+ const action = (type, doc) => field(type, doc, DETECT_ACTIONS, DETECT_ACTION_DOCS);
442
+ const rows = [
443
+ [
444
+ 'guardrails.detect',
445
+ action('DetectAction | { [detector]: DetectorRule }', 'What a guardrail does when a detector matches. One action covers every detector; an object sets each detector (or one of your own) apart. Absent: each detector keeps its default action.'),
446
+ ],
447
+ ];
448
+ for (const detector of DETECTORS) {
449
+ const path = `guardrails.detect.${detector}`;
450
+ rows.push([
451
+ path,
452
+ action('DetectAction | DetectorConfig', `${DETECTOR_META[detector].doc} Set one action, or ${settingsOf(detector)}.`),
453
+ ]);
454
+ if (DETECTOR_META[detector].allow)
455
+ rows.push(...allowFields(path, detector));
456
+ if (DETECTOR_META[detector].patterns)
457
+ rows.push(...patternFields(path));
458
+ rows.push([
459
+ `${path}.action`,
460
+ {
461
+ ...action('DetectAction', 'What a match of this detector does at every boundary it reads, unless `at` names that boundary.'),
462
+ unset: 'Each boundary keeps its default',
463
+ },
464
+ ]);
465
+ rows.push([
466
+ `${path}.at`,
467
+ field('{ [boundary]: DetectAction }', 'An action per boundary, over action or the default.'),
468
+ ]);
469
+ for (const boundary of DETECTOR_BOUNDARIES[detector]) {
470
+ const unset = DETECT_ACTION_META[DETECT_DEFAULTS[detector][boundary]].label;
471
+ const meta = action('DetectAction', BOUNDARY_META[boundary].doc);
472
+ rows.push([`${path}.at.${boundary}`, { ...meta, unset }]);
473
+ }
474
+ }
475
+ rows.push(...hostDetectorFields('guardrails.detect.*'));
476
+ return Object.fromEntries(rows);
477
+ }
478
+ function withScopeAndPresence(fields) {
479
+ return Object.fromEntries(Object.entries(fields).map(([path, meta]) => {
480
+ const scope = profileFieldScope(path);
481
+ return [
482
+ path,
483
+ {
484
+ ...meta,
485
+ ...(scope ? { profileTypes: scope.profileTypes, profileTypesReason: scope.reason } : {}),
486
+ ...PROFILE_FIELD_PRESENCE[path],
487
+ },
488
+ ];
489
+ }));
490
+ }
491
+ /**
492
+ * Adding a profile field? Add it here; scope it in `PROFILE_FIELD_SCOPE` if only some types
493
+ * take it, and record it in `PROFILE_FIELD_PRESENCE` if it is required or its absence matters.
494
+ */
495
+ export const PROFILE_FIELDS = withScopeAndPresence({
496
+ 'profile.id': field('string', 'The name this profile is registered and looked up by, at most 64 characters; registering the same id again replaces it.'),
497
+ 'profile.type': field("'text' | 'image' | 'speech' | 'live' | 'decision' | 'embedding' | 'host'", 'What kind of agent this is, and so what each call gives back: text, image, speech, live, decision, embedding, or host.', PROFILE_TYPES, {
498
+ text: 'A chat or task agent. Each turn the model answers in text, or in JSON when outputs ask for a structured reply, and can call tools on the way.',
499
+ image: 'Makes pictures from a prompt, in the shape, size, and format the image block sets.',
500
+ speech: 'Gives your app a voice. Each turn reads text aloud in the voice the speech block names.',
501
+ live: 'For talking in real time. One continuous voice and video session, rather than separate turns.',
502
+ decision: 'For when your app needs a judgement, not a reply. It answers questions about a JSON state, each with a choice, a score, or a number.',
503
+ embedding: 'For when your app needs vectors from text or provider-supported media.',
504
+ host: 'A governed passthrough to your tool registry, with no model. It calls MCP, HTTP, and in-app function tools under the same permissions and traces as any agent, guarded by detect and network.',
505
+ }),
506
+ identity: field('{ handle, system?, systemByRole? }', "The agent's display name and the system instruction it is given."),
507
+ 'identity.handle': field('string', 'The name hosts and users see for this agent, at most 32 characters; the model never sees it. It is also the role a turn gets when it names none, so identity.systemByRole may hold an entry under it.'),
508
+ 'identity.system': field('string | Array<string | { private: string }>', 'The instruction the model gets on every turn unless a systemByRole entry replaces it; some providers send it for an image profile only with includeText on. Mark what must not leak as { private: text }; only that is guarded. With none, the whole prompt is.'),
509
+ 'identity.systemByRole': field('Record<string, string | Array<string | { private: string }>>', 'Other system instructions, picked by the role a turn names.'),
510
+ 'identity.systemByRole.*': field('string | Array<string | { private: string }>', 'The instruction that replaces identity.system when a turn names this role.'),
511
+ models: field('Record<ModelId, ModelBinding | DecisionModelBinding>', 'The trained AI systems that turn input into results. Each entry binds a local name to an upstream model and its call settings.'),
512
+ 'models.*': field('ModelBinding | DecisionModelBinding', 'One model: how to reach it and the settings sent with it.'),
513
+ 'models.*.protocol': field('string', 'The API shape this model is spoken to in.'),
514
+ 'models.*.provider': field('string', 'The service that runs the model or routes requests to one, such as Gemini or OpenRouter. Its registration supplies the endpoint and authentication.'),
515
+ 'models.*.keySlot': field('KeySlot', "The key slot this model's calls are signed with, instead of the provider's. Use it to bill one model to a different key. Absent: the provider's primary slot."),
516
+ 'models.*.fallbackKeySlot': field('KeySlot', "The key slot tried once after a rate limit on the primary slot, instead of the provider's fallback. Must differ from the primary slot. Absent: the provider's fallback slot, if it has one."),
517
+ 'models.*.options': field('JsonObject', "Settings only this model's protocol has, such as a task type or vector size. Each is checked when the profile loads. Any left out keep the provider's default."),
518
+ providerContinuation: field('ProviderContinuationPolicy', 'Who holds the conversation a saved provider state continues.'),
519
+ 'providerContinuation.history': field("'host' | 'stateless' | 'provider'", 'Who holds the conversation a checkpoint continues: the host passes history back, the provider keeps it and the checkpoint travels alone, or the profile is stateless and every request stands alone.', ['host', 'stateless', 'provider']),
520
+ 'models.*.apiId': field('string', "The model's id as the provider lists it, such as gemini-2.5-flash; sent on every call. The name this model has in the profile is its key in models."),
521
+ 'models.*.timeoutMs': field('number', 'How long a decision waits for its provider, in milliseconds. Omit for no timeout.'),
522
+ decision: field('{ contract: DecisionContractId }', 'Names the host decision this profile makes.'),
523
+ 'decision.contract': field('string', 'Your name for this decision, on its traces. Not sent to the model. Not checked against the questions.'),
524
+ 'models.*.efforts': field('Record<string, ThinkingLevel>', 'Named thinking levels. A turn picks one when allowEffortSelect is on. A provider refuses a level its model does not take. Speech ignores them, and so may an image profile without includeText.'),
525
+ 'models.*.efforts.*': field(unionType(THINKING_LEVELS), 'The thinking level sent to the provider for this name.', THINKING_LEVELS, {
526
+ none: 'No thinking, where the provider has that level.',
527
+ minimal: 'The least thinking.',
528
+ low: 'Light thinking.',
529
+ medium: 'Moderate thinking.',
530
+ high: 'Heavy thinking.',
531
+ xhigh: 'Heavier thinking, where the provider has that level.',
532
+ max: 'The most thinking the model supports, where the provider has that level.',
533
+ }),
534
+ 'models.*.defaultEffort': field('string', "The effort a turn gets when it doesn't pick one."),
535
+ 'models.*.allowEffortSelect': field('boolean', 'Lets a turn pick an effort; needs two or more efforts.'),
536
+ 'models.*.summaries': field('boolean', 'Asks the model for summaries of its thinking, which not every model sends; with some providers, off only hides thoughts, and others ignore it.'),
537
+ 'models.*.maxOutputTokens': field('number', 'The token limit for one reply. Some providers never send it for speech, or for image without includeText.'),
538
+ 'models.*.temperature': field('number', "How varied the model's wording is; higher is more random. Some providers never send it for speech, or for image without includeText."),
539
+ 'models.*.builtInTools': field('BuiltinToolId[]', "The provider's own tools, such as Google Search, this model may use; each must be registered as a builtin tool and declared by the provider's adapter."),
540
+ 'models.*.compaction': field('CompactionSpec', 'Summarises history past a threshold. A text agent can write the summary. Other types name a compaction profile.'),
541
+ 'models.*.compaction.maxTokens': field('number', 'The token budget compactAt is a fraction of.'),
542
+ 'models.*.compaction.trigger': field('(ctx: CompactionTriggerContext) => boolean | Promise<boolean>', 'Your function that decides when to compact, in place of compactAt and maxTokens.'),
543
+ 'models.*.compaction.compactAt': field('number', 'The fraction of maxTokens, between 0 and 1, at which compaction starts, unless trigger decides.'),
544
+ 'models.*.compaction.previousExchanges': field('number', 'How much recent history compaction keeps: a number of exchanges (1 or more), a fraction of maxTokens below compactAt, or 0 to compact it all.'),
545
+ 'models.*.compaction.profile': {
546
+ ...field('ProfileId', 'The text profile that writes the summary; register it before this one. Leave it out and a text agent summarises its own history, with its own instructions and model and no tools. Its registered model binding selects the provider independently of the calling agent.'),
547
+ unset: 'The agent itself',
548
+ },
549
+ 'models.*.compaction.timing': field(unionType(COMPACTION_TIMINGS), 'Whether the kernel compacts before the turn or tells the host to compact after it.', COMPACTION_TIMINGS, {
550
+ before: 'The kernel compacts before the turn runs.',
551
+ after: "The turn's done event says compaction is due, and the host runs it.",
552
+ }),
553
+ 'models.*.compaction.meter': field(unionType(COMPACTION_METERS), 'What the threshold counts.', COMPACTION_METERS, {
554
+ history: 'Tokens in the earlier conversation.',
555
+ input: 'The prompt tokens the provider reported for the last call, or the count the host passes in.',
556
+ }),
557
+ 'profile.defaultModel': field('ModelId', "The model a turn gets when it doesn't pick one."),
558
+ 'profile.allowModelSelect': field('boolean', 'Lets a turn name the model it runs on; a name the profile does not declare is refused.'),
559
+ 'profile.maxSteps': field('number', 'The most model calls one turn may make while using tools, counted afresh for each rewrite; 1 runs the tools asked for but never sends their results back. Live sessions ignore it.'),
560
+ tools: field('{ allow: ToolId[]; t1Policy?; t2Loader?; parallel? }', 'The registered tools this profile may use, and how they load. Built-in tools are set per model.'),
561
+ 'tools.allow': field('ToolId[]', "Your registered tools this agent may use; the provider's own tools go on the model's builtInTools instead."),
562
+ 'tools.t1Policy': field('(ctx) => ToolId[] | Promise<ToolId[]>', 'Your function that picks, at the start of each turn, which T2 tools to load up front; the rest wait for tools.t2Loader.'),
563
+ 'tools.t2Loader': field('ToolId', "The function tool that loads T2 tools. It must be in allow and return { loaded: ToolId[] }. One forbidden id fails the load. Ids off the turn path are skipped. The tools it loads can be called from the next step: a step's calls see the tools as they stood when the step began."),
564
+ 'tools.parallel': field('boolean', 'true: the calls of one step run side by side, and a call whose pre_tool answers waitFor starts its body once those calls settle. Left out or false: they run one at a time, in the order the model made them. A step is the calls the model makes together in a turn, or the calls a host runs through invokeToolStep.'),
565
+ inputs: field('ProfileInputsSpec | DecisionInputsSpec', 'What a turn may send (text, files, voice, choices), or on a decision, the state it reads.'),
566
+ 'inputs.state': field("'json'", 'A decision reads JSON state, passed on each call.', ['json']),
567
+ 'inputs.maxStateBytes': field('number', 'The largest state, in bytes, a decision call may send; larger state is refused before it leaves your process.'),
568
+ 'inputs.text': field('boolean', 'Whether a turn may send text.'),
569
+ 'inputs.attachments': field('{ accept: string[] }', 'Lets turns send files.'),
570
+ 'inputs.attachments.accept': field('string[]', 'The file types a turn may send, where type/* matches a whole family; image profiles take only images, video, and PDF.', ATTACHMENT_ACCEPT_MIMES, "Types the kernel knows; a listed type it doesn't know is refused when a turn sends it."),
571
+ 'inputs.voice': field('{ accept: string[] }', 'Lets turns send voice clips.'),
572
+ 'inputs.voice.accept': field('string[]', 'The audio types a voice clip may be; audio/* matches them all.', VOICE_ACCEPT_MIMES, 'Audio types the kernel knows.'),
573
+ 'inputs.maxFiles': field('number', 'The most files and voice clips one turn or embedding request may send, counted together.'),
574
+ 'inputs.maxBytes': field('number', 'The largest file or clip, in bytes, a turn or embedding request may send inline.'),
575
+ 'inputs.maxTurnBytes': field('number', 'The most bytes one turn or embedding request may send inline across all its files and clips.'),
576
+ 'inputs.limitsByMime': field('Record<string, number>', 'Size limits by file type that replace maxBytes for those types.'),
577
+ 'inputs.limitsByMime.*': field('number', 'The largest file of this type (or type/* family), in bytes, a turn or embedding request may send inline.'),
578
+ 'inputs.slots': field('Record<string, string[]>', 'Named choices a turn or a call can make, such as language, each with its allowed values. {name} in a prompt becomes the chosen value.'),
579
+ 'inputs.slots.*': field('string[]', 'The values a turn may choose for this slot; any other is refused.'),
580
+ 'inputs.context': field('{ from: ContextSender[]; maxChars: number }', 'Lets the page or the host send the agent one package of things to know, read at the context boundary.'),
581
+ 'inputs.context.from': field("Array<'client' | 'server'>", 'Who may send context; context from anyone else is refused.', CONTEXT_SENDERS, {
582
+ client: 'The browser. A visitor can change it, so it is untrusted.',
583
+ server: "The host's own code. It is assembled, like turn system text.",
584
+ }),
585
+ 'inputs.context.maxChars': field('number', 'The longest package, in characters of its JSON, each sender may send.'),
586
+ outputs: field('ProfileOutputsSpec', 'The shape of the reply, how it is checked, and how it streams.'),
587
+ 'outputs.structured': field('StructuredSchemaId | StructuredBySlot | null', 'The registered JSON schema the reply must follow, which can vary by slot; register it before the profile.'),
588
+ image: field('ProfileImageSpec', 'How the images this profile generates are shaped and made: size, format, quality and references. Each setting is sent only where the provider has it; one it lacks is refused or ignored, as that setting says.'),
589
+ 'image.aspectRatio': field('string', 'The shape of generated images, such as 16:9.'),
590
+ 'image.resolution': field('string', 'How detailed generated images are, such as 1K, 2K or 4K.'),
591
+ 'image.mimeType': field('string', 'The file type of generated images; a provider that takes a fixed set of types may use png for any other.'),
592
+ 'image.quality': field('string', 'How much effort the model spends on each image: auto, low, medium, or high. A provider that has no such setting refuses it.'),
593
+ 'image.background': field('string', 'The background of generated images: auto, transparent, or opaque. A provider that has no such setting refuses it.'),
594
+ 'image.n': field('number', 'How many images one request makes, where the provider takes a count.'),
595
+ 'image.seed': field('number', 'A seed for repeatable images, where the provider and the model honour it.'),
596
+ 'image.outputCompression': field('number', 'Compression from 0 to 100 for jpeg and webp images, where the provider takes it.'),
597
+ 'image.references': field('Array<TurnBlob | TurnMediaRef>', "Images sent with every turn, before the user's. Each is bytes (`data`) or a link (`uri`). Some providers take http(s) links only, and none with includeText."),
598
+ 'image.includeText': field('boolean', 'Whether the model may write text alongside its images; with some providers this also sends the system instruction and history.'),
599
+ speech: field('ProfileSpeechSpec', "How the profile's speech sounds and is delivered: voice, style, speed and audio format. A turn may replace voice, style and speed for that turn."),
600
+ 'speech.voice': field('string', "The voice the speech is read in, by the provider's own name for it; a turn's speech.voice replaces it."),
601
+ 'speech.style': field('string', "How the script is delivered, in plain words (pace, mood, accent); it is never read aloud, and a turn's speech.style replaces it. A model that takes no direction ignores it."),
602
+ 'speech.speed': field('number', "The speaking rate, where 1 is the voice's own pace; a turn's speech.speed replaces it. A provider that has no rate refuses it or ignores it."),
603
+ 'speech.format': field(unionType(SPEECH_AUDIO_FORMATS), "The audio encoding each turn's speech comes back in, and so what the host plays or stores.", SPEECH_AUDIO_FORMATS, {
604
+ pcm: 'Uncompressed audio, delivered as WAV.',
605
+ mp3: 'Compressed audio; a provider that cannot make it refuses the turn.',
606
+ }),
607
+ live: field('ProfileLiveSpec', 'How a realtime voice and video session runs: what it accepts from the user, the voice it answers in, when it hears the user start and stop, and how it resumes and trims its context.'),
608
+ 'live.ingress': field('LiveIngressSpec', 'Which channels the session accepts from the user.'),
609
+ 'live.ingress.audio': field('boolean', 'Whether the session accepts microphone audio.'),
610
+ 'live.ingress.video': field('boolean', 'Whether the session accepts camera frames.'),
611
+ 'live.ingress.text': field('boolean', 'Whether the session accepts typed text.'),
612
+ 'live.voice': field('string', 'The voice the model speaks in.', GOOGLE_SPEECH_VOICES, 'Voice names to pick from; any other name is sent as written.'),
613
+ 'live.vad': field('LiveVadSpec', 'How the session detects when the user starts and stops speaking.'),
614
+ 'live.vad.activityHandling': field(unionType(LIVE_ACTIVITY_HANDLINGS), "Whether the user speaking interrupts the model's reply.", LIVE_ACTIVITY_HANDLINGS, {
615
+ START_OF_ACTIVITY_INTERRUPTS: 'The user speaking cuts the reply off.',
616
+ NO_INTERRUPTION: 'The model finishes its reply.',
617
+ }),
618
+ 'live.vad.startSensitivity': field(unionType(LIVE_START_SENSITIVITIES), 'How readily the session decides the user has started speaking.', LIVE_START_SENSITIVITIES, {
619
+ START_SENSITIVITY_LOW: 'Detects the start of speech less often.',
620
+ START_SENSITIVITY_HIGH: 'Detects the start of speech more often.',
621
+ }),
622
+ 'live.vad.endSensitivity': field(unionType(LIVE_END_SENSITIVITIES), 'How readily the session decides the user has stopped speaking.', LIVE_END_SENSITIVITIES, {
623
+ END_SENSITIVITY_LOW: 'Ends speech less often, waiting through pauses.',
624
+ END_SENSITIVITY_HIGH: 'Ends speech more often, at shorter pauses.',
625
+ }),
626
+ 'live.vad.prefixPaddingMs': field('number', 'How long speech must last, in milliseconds, before it counts as the user starting to speak.'),
627
+ 'live.vad.silenceDurationMs': field('number', "How long a silence, in milliseconds, ends the user's speech."),
628
+ 'live.sessionResumption': field('boolean', 'Whether the provider sends resume handles, which the host can pass to a new session to carry this one on.'),
629
+ 'live.greeting': field('string', 'A prompt the call sends itself when it opens new, so the agent speaks first. The visitor does not see it. It may use {slot}.'),
630
+ 'live.resumed': field('{ prompt: string; afterMs?: number }', 'What happens when a call comes back after a drop. It needs live.sessionResumption.'),
631
+ 'live.resumed.prompt': field('string', 'A prompt the call sends itself when it resumes, so the agent says it is back. The visitor does not see it. It may use {slot}.'),
632
+ 'live.resumed.afterMs': field('number', 'The shortest time away, in milliseconds, that earns the prompt; a shorter drop resumes silently.'),
633
+ 'live.contextCompression': field('LiveContextCompressionSpec', "Trims the session's context once it grows past the trigger."),
634
+ 'live.contextCompression.triggerTokens': field('number', 'The context size, in tokens, that starts trimming.'),
635
+ 'live.contextCompression.slidingWindow': field('LiveSlidingWindowSpec', 'Trims by dropping the oldest turns; the system instruction stays.'),
636
+ 'live.contextCompression.slidingWindow.targetTokens': field('number', 'The context size, in tokens, to trim down to; below the trigger.'),
637
+ 'live.transcription': field('LiveTranscriptionSpec', "Text transcripts of the session's speech."),
638
+ 'live.transcription.input': field('boolean', "Whether the user's speech is transcribed."),
639
+ 'live.transcription.output': field('boolean', "Whether the model's speech is transcribed; always on while a detector reads live_reply, since it reads the transcript."),
640
+ 'outputs.validation': field('ProfileValidationSpec', 'Your checks on a structured reply, and how many rewrites a failure gets.'),
641
+ 'outputs.validation.fields': field('Record<string, ProfileValidator>', 'Your checks, each keyed by a dotted path into the structured reply, such as diagram.mermaid; a path no structured schema reaches is refused when the profile registers.'),
642
+ 'outputs.validation.fields.*': field('(candidate: unknown, slots?: Record<string, string>) => ValidationResult | Promise<ValidationResult>', 'Your check on this part of the reply, reached through object properties only; a failure sends its error back to the model to rewrite while retries remain.'),
643
+ 'outputs.validation.items': field('Record<string, ProfileItemRule>', 'Your checks on the items of a list, each keyed by the dotted path of that list in the structured reply, such as claims; a path no structured schema reaches as a list is refused when the profile registers.'),
644
+ 'outputs.validation.items.*': field('ProfileItemRule', 'Your check on each item of this list. A refused item never fails the reply and the rest of the reply is kept.'),
645
+ 'outputs.validation.items.*.check': field('(item: unknown, turn: ItemCheckTurn) => ValidationResult | Promise<ValidationResult>', 'Your check on one item, given what the tools of the turn returned (turn.toolResults); its error is the reason the model reads on a rewrite and the host reads on the removed item.'),
646
+ 'outputs.validation.items.*.onFail': field("'drop' | 'fix'", 'drop removes a refused item. fix first asks the model to rewrite the refused items alone, once and while retries remain, then removes any refused again. Removed items leave on the structured event as removed.', ITEM_FAIL_ACTIONS),
647
+ 'outputs.validation.maxRetries': field('number', "How many times the model may rewrite a reply that fails your checks or the schema's required keys before it goes out as it is; under sse, an attempt that gets rewritten has already streamed. A rewrite of a blocked reply (guardrails.blockedReply) counts against this too."),
648
+ 'outputs.streaming': field('ProfileStreamingSpec', 'How the reply reaches the host, and whether its thinking does.'),
649
+ 'outputs.streaming.mode': field(unionType(STREAM_MODES), 'Whether the reply reaches the host as the model writes it, or whole.', STREAM_MODES, {
650
+ sse: 'Events arrive as the model writes, so a reply that fails outputs.validation has already streamed when it is rewritten; some providers always answer image and speech in one piece.',
651
+ buffered: 'One non-streaming call, whose events arrive together; under outputs.validation, only once the reply passes or retries run out. Thinking still streams.',
652
+ }),
653
+ 'outputs.streaming.streamThoughts': field('boolean', "Whether the model's thinking reaches the host."),
654
+ turnBehaviour: field('ProfileTurnBehaviourSpec', 'Whether a reply that stopped early can be continued, and whether a running turn can be steered.'),
655
+ 'turnBehaviour.resumption': field('ProfileTurnResumptionSpec', 'Continuing a reply that stopped early; live uses sessionResumption instead.'),
656
+ 'turnBehaviour.resumption.allowContinue': field('ContinueStopKind[]', "Which early stops the host offers the user a Continue for; the kernel doesn't refuse a continue after other stops.", CONTINUE_STOP_KINDS, {
657
+ length: 'The reply hit the output token limit.',
658
+ stream_incomplete: 'The connection dropped mid-reply.',
659
+ provider_error: 'The provider returned an error or timed out.',
660
+ }),
661
+ 'turnBehaviour.resumption.autoContinue': field('ContinueStopKind[]', 'Which early stops are continued without asking, whether or not allowContinue offers a Continue for them. When set, a text turn sends a listed failed model call that gave no reply again itself; the host continues the rest.', CONTINUE_STOP_KINDS, {
662
+ length: 'The reply hit the output token limit.',
663
+ stream_incomplete: 'The connection dropped mid-reply.',
664
+ provider_error: 'The provider returned an error or timed out.',
665
+ }),
666
+ 'turnBehaviour.resumption.maxContinues': field('number', 'How many times one reply may be continued; once set, each continue must say which one it is. Also how many failed model calls one text turn sends again itself (one when unset).'),
667
+ 'turnBehaviour.allowSteering': field('boolean', 'Lets your onStage hook add messages to a running turn. Text profiles also let the user steer.'),
668
+ 'turnBehaviour.atStepLimit': field("'stop' | 'answer'", 'What happens when a turn reaches maxSteps while the model still wants tools: the turn stops with no answer, or the last call is made without tools so it answers.', STEP_LIMIT_MODES, {
669
+ stop: 'It may still call tools; if it does, they run and the turn stops as step_limit with no answer.',
670
+ answer: 'It is sent without tools, so it writes the answer from what the turn has gathered.',
671
+ }),
672
+ guardrails: field('ProfileGuardrailsSpec', 'Theorem checks what enters or leaves an agent’s context and generation against built-in or custom rules at each configured boundary.'),
673
+ 'guardrails.quota': field('QuotaGuardrailSpec', 'A daily turn limit. Your server enforces it with takeSlot.'),
674
+ 'guardrails.quota.perDay': field('number', 'Turns each client IP may run on this profile per UTC day, one at a time; counts live in the process, and a loopback caller is not counted.'),
675
+ ...detectFields(),
676
+ 'guardrails.blockedReply': field('BlockedReplySpec', 'How a reply a guardrail blocked is handled: the model rewrites it, or the user gets a refusal, and how many rewrites it gets.'),
677
+ 'guardrails.blockedReply.onBlock': field(unionType(BLOCKED_REPLY_ON_BLOCK), 'Whether the model gets to rewrite a reply a guardrail blocked, or the user gets a refusal in its place.', BLOCKED_REPLY_ON_BLOCK, {
678
+ retry: 'The model reads why and rewrites the reply, up to maxRetries times; once retries run out, the reply is withheld and the turn ends with a safety error. Live never rewrites: it withholds at once.',
679
+ refuse: 'The user sees the egress.refusal wording in place of the reply, and the turn ends.',
680
+ }),
681
+ 'guardrails.blockedReply.maxRetries': field('number', 'How many times the model may rewrite a blocked reply. Live ignores it.'),
682
+ 'guardrails.network': field('NetworkGuardrailSpec', 'Addresses HTTP and MCP tools may reach.'),
683
+ 'guardrails.network.allowPrivateNetworks': field('boolean', 'Lets tools reach localhost and private network addresses, for local development.'),
684
+ 'guardrails.network.allowedHosts': field('string[]', "Hostnames tools may reach even when they resolve to a private address; public hosts don't need listing. Names are resolved only when the host passes resolveHost."),
685
+ 'guardrails.network.allowedSchemes': field('string[]', 'The URL schemes tools may use.'),
686
+ 'guardrails.taint': field('TaintGuardrailSpec', 'Tool limits after a remote read.'),
687
+ 'guardrails.taint.afterRemoteRead': field(unionType(TAINT_GATES), "Which tool calls are refused, by each tool's access, once the turn has read a remote tool's result.", TAINT_GATES, {
688
+ off: 'None; risky calls are only logged.',
689
+ destructive: 'Destructive calls.',
690
+ write: 'Read-write and destructive calls.',
691
+ }),
692
+ 'guardrails.taint.remoteDestination': field(unionType(DESTINATION_GATES), "What happens to a tool call, read-only ones too, that sends to an email address, a link's host or a bank account number (IBAN) that only the running text of a remote tool's result named. One the user, the system prompt, or a local tool gave passes, and so does one that is a whole field of the result.", DESTINATION_GATES, {
693
+ off: 'The call runs; it is only logged.',
694
+ confirm: 'The call waits for the user to approve it; an approval runs it.',
695
+ block: 'The call is refused, and the model is told why.',
696
+ }),
697
+ 'guardrails.disclosure': field('{ enforce: DecisionDisclosureEnforcer }', 'Your check on the state before a decision sends it to the model.'),
698
+ 'guardrails.disclosure.enforce': field('(state, context) => DecisionDisclosureVerdict | Promise<DecisionDisclosureVerdict>', 'Your function that allows or blocks the state before it is sent.'),
699
+ labels: field('LabelOverrides', "This profile's own wording for error lines, notices, and notes to the model, by labels key."),
700
+ 'labels.*': field('string', 'The wording for this labels key; canary.bind_note must keep its {canary} placeholder.'),
701
+ observability: field('ProfileObservabilitySpec', "Where this profile's traces go and what they keep."),
702
+ 'observability.writeTo': field('false | string | TraceSink', 'Where traces go: a registered destination id, your own writer, or false. An unregistered id fails the turn at the start. A sink passed to runTurn replaces it.'),
703
+ 'observability.sampleRate': field('number', 'The share of traces kept, from 0 to 1, each kept or dropped whole; a sink passed straight to runTurn keeps every trace.'),
704
+ 'observability.include': field('TraceIncludeSpec', 'Which optional parts of a trace are kept.'),
705
+ 'observability.include.upstreamLog': field('boolean', 'Keeps each row the provider sent back, scrubbed, as it arrived, with media bytes replaced by their sha256.'),
706
+ 'observability.include.outboundWire': field('boolean', 'Keeps each request body sent to the provider, scrubbed.'),
707
+ 'observability.include.evidenceRaw': field('boolean', "Keeps the provider's raw payload on grounding results such as search citations; upstreamLog rows keep their own copy."),
708
+ 'observability.include.usage': field('boolean', 'Keeps token counts and other usage figures on spans; upstreamLog rows keep their own.'),
709
+ 'observability.include.guardrailDecisions': field('boolean', 'Keeps each guardrail decision.'),
710
+ 'observability.include.guardrailMatchPreview': field('boolean', "Keeps the exact text each guardrail matched, unscrubbed, on the trace and the host's event stream; for debugging only."),
711
+ 'observability.resource': field('Record<string, TraceAttributeValue>', 'Attributes stamped on every trace, such as service.name.'),
712
+ 'observability.scrub': field('TraceScrubSpec', "What is removed from stored traces, separately from the turn's guardrails."),
713
+ 'observability.scrub.sensitive': field('ScrubSwitch', "Removes what the data detectors (IDs, Financial, Network, Credentials) and your own detectors find from stored traces. On, it cleans with the patterns each reads the turn with; { theorem, host } picks Theorem's patterns, yours, or both for the trace alone."),
714
+ 'observability.scrub.injection': field('ScrubSwitch', "Removes what Injection and Tool instructions find from stored traces. On, it cleans with the patterns each reads the turn with; { theorem, host } picks Theorem's patterns, yours, or both for the trace alone."),
715
+ 'observability.scrub.canary': field('ScrubSwitch', "Removes the canary token from stored traces. The canary is Theorem's, so { theorem: false } keeps it."),
716
+ 'observability.retainForDays': field('number', 'Days a trace file is kept, by its UTC day. The next write removes old files. 0 or less keeps all.'),
717
+ 'observability.rotateAfterMiB': field('number', 'File size in MiB at which a file-based destination starts a new file, handed to every destination with the record. Default 32.'),
718
+ 'observability.onWriteError': field('(err: unknown) => void', "Your function called when a trace can't be built or written; the turn carries on, and a destination's own error handler takes priority. An unregistered writeTo id is a config error instead."),
719
+ });
720
+ const TOOL_TYPE_FIELD = field(unionType(TOOL_TYPES), 'How the tool runs.', TOOL_TYPES, {
721
+ builtin: "The provider's own tool, such as Google Search, run by the provider.",
722
+ function: 'Your handler runs it.',
723
+ http: 'The kernel calls your HTTP endpoint.',
724
+ mcp: 'The kernel calls a tool on a remote MCP server.',
725
+ agent: 'The kernel runs one turn of another registered agent and returns its reply.',
726
+ });
727
+ const CREDENTIAL_KINDS = {
728
+ bearer: 'A token; a secret typed in at the prompt becomes a bearer token.',
729
+ ['api_' + 'key']: 'An API key; a secret typed in at the prompt becomes an API key.',
730
+ oauth2: 'An OAuth sign-in; the host supplies the token.',
731
+ };
732
+ /**
733
+ * The catalog of the fields `registerTool` takes, keyed `registerTool.<field>`. The `studio.` and
734
+ * `local.` rows are the studio's own; a builder never sets them.
735
+ */
736
+ export const EXTRA_FIELDS = {
737
+ 'done.stop.kind': field('TurnStopKind', 'Why the turn ended, on the done event: its stop.kind.', TURN_STOP_KINDS, {
738
+ completed: 'The model finished its reply.',
739
+ length: 'The model reached its token limit.',
740
+ tool: 'The model called tools and the turn hands them to the host, in done.tools.',
741
+ gate: 'A pre_tool stage held a tool call. The host resumes it with invokeTool, not continueFrom.',
742
+ filtered: 'The provider filtered the reply, or the egress guardrail withheld it.',
743
+ provider_error: 'The provider failed or reported an error.',
744
+ cancelled: 'The turn was cancelled, by the user or by a stage that aborted it.',
745
+ stream_incomplete: 'The stream ended without the provider reporting a final status.',
746
+ step_limit: 'The last model call maxSteps allows asked for tools, so the turn ended with no answer.',
747
+ interrupted: 'A live utterance was cut off by an interruption.',
748
+ generation_complete: 'Live: the model finished generating audio or text for this utterance. The turn may still be open.',
749
+ }),
750
+ 'registerTool.type': TOOL_TYPE_FIELD,
751
+ /** Studio-only rows: the editor's local-model connection, and a decision's questions and images. */
752
+ 'local.baseUrl': field('string', 'Where your local model server listens, such as Ollama, llama.cpp or vLLM. The browser calls it directly.'),
753
+ 'studio.remoteTools': {
754
+ ...field('boolean', 'Whether tools that reach other hosts (HTTP and MCP) may run while a local model is in use. Off, a run with a local model reaches no host.'),
755
+ unset: 'Off',
756
+ },
757
+ 'decision.questions.id': field('string', "The question's name. Its answer comes back under it."),
758
+ 'decision.questions.type': field("'choice' | 'score' | 'noul' | 'box'", 'The kind of answer the question takes.', ['choice', 'score', 'noul', 'box'], {
759
+ choice: 'One of the named options, with a confidence and a probability for each option.',
760
+ score: 'A level on an ordered scale, with a confidence.',
761
+ noul: 'One number, which may weigh named criteria.',
762
+ box: 'Where something is in an image: its top, bottom, left and right edges, with a confidence.',
763
+ }),
764
+ 'decision.questions.instructions': field('DecisionEntry', "What to ask about the state. Name a state field in backticks, such as `photo`, and one of the decision's images by its reference, such as <ginger>. A box looks in its In image, else in the image of the first field it names."),
765
+ 'decision.questions.image': {
766
+ ...field('string', "The image a box is in: one of the decision's images, such as <ghs02>, or a state field its instructions name, such as `photo`. The model is told it in the instructions."),
767
+ unset: 'The image the instructions name',
768
+ },
769
+ 'decision.images': field('Record<string, DecisionAsset>', 'Pictures sent with every decision, beside the state. A question names one by its reference, such as <ghs02>. A PNG or JPEG.'),
770
+ 'decision.images.name': field('string', 'The reference a question writes, without its angle brackets: ghs02 is written <ghs02>. Lowercase letters, digits and _.'),
771
+ 'registerTool.name': field('string', "The tool's id, which profiles list in tools.allow (or a model's builtInTools) and the model calls a custom tool by."),
772
+ 'registerTool.description': field('string', 'Tells the model what the tool does (custom tools only).'),
773
+ 'registerTool.input': field('ZodSchema', "The Zod schema for the tool's arguments, sent to the model and checked on every call."),
774
+ 'registerTool.output': field('ZodSchema', "The Zod schema every result the tool returns must match; the kernel's own not-signed-in note is not checked."),
775
+ 'registerTool.handler': field('ToolHandler', 'Your function that runs the tool; it can also yield progress as it goes.'),
776
+ 'registerTool.endpoint': field('string', 'The URL the tool calls, with {name} placeholders for mapping.pathParams; the scheme and host must be written out.'),
777
+ 'registerTool.method': field(unionType(HTTP_METHODS), 'The HTTP method; every method but GET sends a JSON body.', HTTP_METHODS),
778
+ 'registerTool.headers': field('Record<string, string>', "Headers sent with every request to the tool's own origin, never once a redirect leaves it."),
779
+ 'registerTool.mapping': field('{ pathParams?, queryParams?, bodyParam? }', 'Where each argument goes in the request.'),
780
+ 'registerTool.mapping.pathParams': field('string[]', 'Arguments that fill the {name} placeholders in the endpoint.'),
781
+ 'registerTool.mapping.queryParams': field('string[]', 'Arguments added to the query string.'),
782
+ 'registerTool.mapping.bodyParam': field('string', 'The one argument sent as the whole JSON body; without it, a method other than GET sends every argument the path and query leave unused.'),
783
+ 'registerTool.serverUrl': field('string', "The MCP server's URL."),
784
+ 'registerTool.mcpToolName': field('string', "The tool's name on the MCP server."),
785
+ 'registerTool.profile': field('ProfileId', 'The profile this agent tool runs: text, image, or speech. Register it first. Nothing it calls may stop on a gate.'),
786
+ 'registerTool.answeredBy': {
787
+ ...field("'page'", 'Who answers a call to a function tool. With page, the page the agent is on returns the output, and the tool has no handler.', ['page']),
788
+ unset: 'Its handler',
789
+ },
790
+ 'registerTool.maxCallsPerTurn': {
791
+ ...field('number', 'How many times one turn of the calling agent may run this tool.'),
792
+ unset: 'As many as its steps allow',
793
+ },
794
+ 'registerTool.fieldText': {
795
+ ...field('Partial<Record<keyof AgentToolInput, string>>', 'What the calling model reads on a field of an agent tool input, such as text. A field the profile does not take is refused when the tool registers.'),
796
+ unset: 'The fields carry no text',
797
+ },
798
+ 'registerTool.hostFields': {
799
+ ...field('Record<string, ZodType>', 'Fields the calling model fills on an agent tool that only the host reads. onAgentCall gets them as hostInput and turns them into what the agent is sent; the agent never sees them. A name the input already has is refused when the tool registers.'),
800
+ unset: 'The input is only what the profile takes',
801
+ },
802
+ 'registerTool.hostOnly': {
803
+ ...field("Array<'attachments' | 'voice' | 'slots'>", 'Channels the called profile takes that the calling model cannot fill on an agent tool; only onAgentCall sends them. A channel the profile does not take is refused when the tool registers.'),
804
+ unset: 'The model can fill every channel the profile takes',
805
+ },
806
+ 'registerTool.auth': {
807
+ ...field('ToolAuthConfig', 'How the tool gets its credential.'),
808
+ unset: 'No credential',
809
+ },
810
+ 'registerTool.auth.type': field(unionType(TOOL_AUTH_TYPES), "The kind of credential the tool expects, shown when a turn stops to ask for one; the header follows the stored credential's own kind.", TOOL_AUTH_TYPES, CREDENTIAL_KINDS),
811
+ 'registerTool.auth.slot': field('string', 'Which of the credentials the turn passes in this tool uses.'),
812
+ 'registerTool.auth.service': field('string', 'The service the person signs in to, as they know it, named when a turn stops to ask for a credential.'),
813
+ 'registerTool.auth.headerName': {
814
+ ...field('string', "The header the credential goes in; an API key's own headerName comes first."),
815
+ unset: 'Authorization',
816
+ },
817
+ 'registerTool.auth.headerPrefix': {
818
+ ...field('string', "Text put before the credential in the header; an API key's own headerPrefix comes first."),
819
+ unset: '"Bearer " for tokens, nothing for API keys',
820
+ },
821
+ 'registerTool.auth.queryParam': {
822
+ ...field('string', 'For a service that takes its API key in the URL: the query parameter the key goes in, in place of a header.'),
823
+ unset: 'The key goes in a header',
824
+ },
825
+ 'registerTool.auth.onUnauthenticated': {
826
+ ...field(unionType(AUTH_UNAUTHENTICATED_POLICIES), "What happens when the credential is missing, expired, can't be refreshed or is refused by the service.", AUTH_UNAUTHENTICATED_POLICIES, {
827
+ gate: 'The turn stops and asks the host for a credential.',
828
+ report_to_model: "The model is told the tool isn't signed in, and the turn goes on.",
829
+ fail: 'The call fails as not signed in, for a key the host holds that no person can sign in to replace.',
830
+ }),
831
+ unset: 'gate',
832
+ },
833
+ 'registerTool.auth.scopes': field('string[]', 'The OAuth scopes the tool needs, shown when a turn stops to ask for a credential. A service asking for any other scope fails the call, with no new sign-in.'),
834
+ 'registerTool.auth.clientId': field('string', "Your OAuth client id, kept for the host's sign-in flow; the kernel doesn't read it."),
835
+ 'registerTool.auth.redirectUri': field('string', "Your OAuth redirect URI, kept for the host's sign-in flow; the kernel doesn't read it."),
836
+ 'studio.authType': field(unionType(STUDIO_AUTH_TYPES), 'The kind of credential the tool expects, or none.', STUDIO_AUTH_TYPES, { none: 'The tool sends no credential.', ...CREDENTIAL_KINDS }),
837
+ 'studio.testCredential': field('string', "A credential for this tool's connection tests, kept in the tab and never saved."),
838
+ 'studio.stubOutput': {
839
+ ...field('Record<string, unknown>', 'What a function tool returns in the studio, unless a demo handler has its name.'),
840
+ unset: 'A stand-in built from the output schema',
841
+ },
842
+ 'studio.sampleInput': field('Record<string, unknown>', 'Arguments for the connection test, never saved.'),
843
+ 'registerTool.inputSchema': field('Record<string, unknown>', "The tool's arguments as a JSON Schema, sent to the model."),
844
+ 'registerTool.outputSchema': field('Record<string, unknown>', "The tool's result as a JSON Schema, which a function tool's stand-in result is built from."),
845
+ 'registerStructured.jsonSchema': field('Record<string, unknown>', 'The JSON Schema a structured reply must follow, sent to the model as its response format.'),
846
+ 'registerTool.access': field(unionType(TOOL_ACCESS), "What the tool can change, which taint.afterRemoteRead refuses calls by after a turn reads a remote tool's result.", TOOL_ACCESS, {
847
+ 'read-only': 'Only reads.',
848
+ 'read-write': 'Creates or updates things.',
849
+ destructive: 'Deletes, charges, or does something else hard to undo.',
850
+ }),
851
+ 'registerTool.loadTier': field(unionType(TOOL_LOAD_TIERS), 'When the tool becomes available to the model; live and host profiles load every allowed tool at the start.', TOOL_LOAD_TIERS, {
852
+ T0: 'At the start of every turn.',
853
+ T2: 'On demand: when tools.t1Policy picks it at the start of a turn, or when the tools.t2Loader tool loads it mid-turn (custom tools only).',
854
+ }),
855
+ 'registerTool.permission': field(unionType(TOOL_PERMISSION), "Whether the host must approve a call before it runs; the provider's own tools never ask.", TOOL_PERMISSION, {
856
+ auto: 'Runs without asking.',
857
+ session_consent: 'Asks once; the approval lasts as long as the host keeps passing it back.',
858
+ always_confirm: 'Asks every time.',
859
+ }),
860
+ 'registerTool.category': field('string', 'A label for grouping tools; nothing reads it yet.'),
861
+ 'registerTool.labels': field('ToolLabels', "Transcript text for a call. {path} reads a value from the call. {results.0.name} reads a list item. {path|text} shows the text when the value is unusable. With no fallback, the label is dropped. A label is one line, or a list read top to bottom: the first line that fits is shown. A line fits when each {path} has a value and its condition holds, as in 'when status is archived: archiving {title}'. Neighbouring lines that open with '+ ' show together, joined in words. The last line of a list must always fit."),
862
+ 'registerTool.labels.activity': {
863
+ ...field('string | string[]', "Transcript text while a call runs, e.g. 'Saving {title} to your collection'. {path} reads the call's input."),
864
+ unset: 'The tool name, in words',
865
+ },
866
+ 'registerTool.labels.activityPast': {
867
+ ...field('string | string[]', "What the transcript says once a call completes, e.g. 'Found {results.0.name}'. Each {path} is filled from the call's input, then its output."),
868
+ unset: 'The tool name, in words',
869
+ },
870
+ 'registerTool.labels.activityFailed': {
871
+ ...field('string | string[]', "What the transcript says when a call fails or the host labels it failed, e.g. 'Couldn't save {title}'. Each {path} is filled from the call's input."),
872
+ unset: "Couldn't complete, then the tool name in words",
873
+ },
874
+ 'registerTool.labels.request': {
875
+ ...field('string | string[]', "What the approval card says the agent wants to do, e.g. 'check the weather in {city}'. Each {path} is filled from the call's input."),
876
+ unset: 'The tool name, in words',
877
+ },
878
+ 'registerTool.paths': {
879
+ ...field('string[]', 'The turn paths this tool is offered on, where * means every path; a turn with no path gets only * tools. Host profiles ignore it.'),
880
+ unset: 'Every path',
881
+ },
882
+ };
883
+ /** `labels.<key>` resolves to `labels.*` with that key's own note. */
884
+ export function fieldMeta(path) {
885
+ const meta = PROFILE_FIELDS[path] ?? EXTRA_FIELDS[path];
886
+ if (meta || !path.startsWith('labels.'))
887
+ return meta;
888
+ const key = path.slice('labels.'.length);
889
+ const wildcard = PROFILE_FIELDS['labels.*'];
890
+ if (!wildcard || !Object.hasOwn(LABEL_NOTES, key))
891
+ return undefined;
892
+ return { ...wildcard, doc: LABEL_NOTES[key] };
893
+ }
894
+ export { API_EXPORTS, REQUEST_FIELDS } from './api-catalog.js';
895
+ export { PROFILE_GRAPH, profileGraphFacet, spineFacetsForProfileType } from './profile-graph.js';