theorum 0.1.15 → 1.1.3

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 (305) hide show
  1. package/README.md +241 -98
  2. package/esm/mod.d.ts +57 -28
  3. package/esm/mod.js +43 -23
  4. package/esm/src/cli/commands/bench.js +18 -18
  5. package/esm/src/cli/commands/fuzz-canary.d.ts +13 -0
  6. package/esm/src/cli/commands/fuzz-canary.js +191 -0
  7. package/esm/src/cli/commands/fuzz-guardrails.d.ts +3 -5
  8. package/esm/src/cli/commands/fuzz-guardrails.js +4 -581
  9. package/esm/src/cli/commands/guardrails-eval.d.ts +14 -0
  10. package/esm/src/cli/commands/guardrails-eval.js +15 -0
  11. package/esm/src/cli/commands/profile.js +35 -15
  12. package/esm/src/cli/commands/run.d.ts +3 -0
  13. package/esm/src/cli/commands/run.js +23 -32
  14. package/esm/src/cli/commands/test.d.ts +10 -1
  15. package/esm/src/cli/commands/test.js +34 -34
  16. package/esm/src/cli/event-log.d.ts +19 -0
  17. package/esm/src/cli/event-log.js +147 -0
  18. package/esm/src/cli/index.js +57 -11
  19. package/esm/src/cli/matrix/synthesizer.d.ts +10 -12
  20. package/esm/src/cli/matrix/synthesizer.js +45 -118
  21. package/esm/src/guardrails/canary-gate.d.ts +21 -0
  22. package/esm/src/guardrails/canary-gate.js +32 -0
  23. package/esm/src/guardrails/canary.d.ts +34 -0
  24. package/esm/src/guardrails/canary.js +150 -0
  25. package/esm/src/guardrails/corpus/canary-egress-attacks.d.ts +17 -0
  26. package/esm/src/guardrails/corpus/canary-egress-attacks.js +151 -0
  27. package/esm/src/guardrails/corpus/fuzz-inbound.d.ts +11 -0
  28. package/esm/src/guardrails/corpus/fuzz-inbound.js +213 -0
  29. package/esm/src/guardrails/corpus/inbound-payloads.d.ts +10 -0
  30. package/esm/src/guardrails/corpus/inbound-payloads.js +125 -0
  31. package/esm/src/guardrails/corpus/live-attacks.d.ts +20 -0
  32. package/esm/src/guardrails/corpus/live-attacks.js +231 -0
  33. package/esm/src/guardrails/corpus/mod.d.ts +14 -0
  34. package/esm/src/guardrails/corpus/mod.js +11 -0
  35. package/esm/src/guardrails/corpus/secrets.d.ts +17 -0
  36. package/esm/src/guardrails/corpus/secrets.js +17 -0
  37. package/esm/src/guardrails/corpus/strings.d.ts +28 -0
  38. package/esm/src/guardrails/corpus/strings.js +34 -0
  39. package/esm/src/guardrails/corpus/types.d.ts +38 -0
  40. package/esm/src/guardrails/corpus/types.js +6 -0
  41. package/esm/src/guardrails/egress.d.ts +32 -0
  42. package/esm/src/guardrails/egress.js +87 -0
  43. package/esm/src/guardrails/error.d.ts +14 -23
  44. package/esm/src/guardrails/error.js +87 -76
  45. package/esm/src/guardrails/eval/corpus.d.ts +108 -0
  46. package/esm/src/guardrails/eval/corpus.js +978 -0
  47. package/esm/src/guardrails/eval/mod.d.ts +51 -0
  48. package/esm/src/guardrails/eval/mod.js +133 -0
  49. package/esm/src/guardrails/eval/score.d.ts +66 -0
  50. package/esm/src/guardrails/eval/score.js +114 -0
  51. package/esm/src/guardrails/events.d.ts +25 -0
  52. package/esm/src/guardrails/events.js +56 -0
  53. package/esm/src/guardrails/hits.d.ts +24 -0
  54. package/esm/src/guardrails/hits.js +45 -0
  55. package/esm/src/guardrails/injection.js +28 -5
  56. package/esm/src/guardrails/lexicon.d.ts +39 -0
  57. package/esm/src/guardrails/lexicon.js +200 -0
  58. package/esm/src/guardrails/live-outbound-gate.d.ts +41 -0
  59. package/esm/src/guardrails/live-outbound-gate.js +222 -0
  60. package/esm/src/guardrails/mod.d.ts +30 -6
  61. package/esm/src/guardrails/mod.js +20 -5
  62. package/esm/src/guardrails/network.d.ts +19 -0
  63. package/esm/src/guardrails/network.js +234 -0
  64. package/esm/src/guardrails/policy.d.ts +35 -0
  65. package/esm/src/guardrails/policy.js +50 -0
  66. package/esm/src/guardrails/progressive-yield.d.ts +51 -0
  67. package/esm/src/guardrails/progressive-yield.js +98 -0
  68. package/esm/src/guardrails/quota.d.ts +17 -3
  69. package/esm/src/guardrails/quota.js +18 -4
  70. package/esm/src/guardrails/sanitize.d.ts +45 -19
  71. package/esm/src/guardrails/sanitize.js +177 -94
  72. package/esm/src/guardrails/sensitive.js +2 -1
  73. package/esm/src/guardrails/serialize.d.ts +35 -0
  74. package/esm/src/guardrails/serialize.js +58 -0
  75. package/esm/src/guardrails/testing.d.ts +17 -0
  76. package/esm/src/guardrails/testing.js +13 -0
  77. package/esm/src/guardrails/theorum-error.d.ts +12 -0
  78. package/esm/src/guardrails/theorum-error.js +15 -0
  79. package/esm/src/guardrails/tool-directives.d.ts +48 -0
  80. package/esm/src/guardrails/tool-directives.js +124 -0
  81. package/esm/src/guardrails/tool-result.d.ts +93 -0
  82. package/esm/src/guardrails/tool-result.js +276 -0
  83. package/esm/src/guardrails/types.d.ts +291 -0
  84. package/esm/src/guardrails/types.js +72 -0
  85. package/esm/src/host/client-turn.d.ts +19 -0
  86. package/esm/src/host/client-turn.js +36 -0
  87. package/esm/src/host/mint-trace.d.ts +1 -1
  88. package/esm/src/host/mod.d.ts +5 -3
  89. package/esm/src/host/mod.js +4 -3
  90. package/esm/src/kernel/auth/crypto.d.ts +42 -0
  91. package/esm/src/kernel/auth/crypto.js +106 -0
  92. package/esm/src/kernel/auth/mod.d.ts +11 -0
  93. package/esm/src/kernel/auth/mod.js +11 -0
  94. package/esm/src/kernel/auth/oauth.d.ts +47 -0
  95. package/esm/src/kernel/auth/oauth.js +278 -0
  96. package/esm/src/kernel/auth/types.d.ts +133 -0
  97. package/esm/src/kernel/auth/types.js +13 -0
  98. package/esm/src/kernel/engine/delta.d.ts +24 -2
  99. package/esm/src/kernel/engine/delta.js +478 -39
  100. package/esm/src/kernel/engine/live-inbound.d.ts +21 -0
  101. package/esm/src/kernel/engine/live-inbound.js +31 -0
  102. package/esm/src/kernel/engine/live-ingress.d.ts +19 -0
  103. package/esm/src/kernel/engine/live-ingress.js +47 -0
  104. package/esm/src/kernel/engine/repair.js +13 -12
  105. package/esm/src/kernel/engine/runner/gates.d.ts +1 -1
  106. package/esm/src/kernel/engine/runner/gates.js +130 -43
  107. package/esm/src/kernel/engine/runner/mod.d.ts +6 -4
  108. package/esm/src/kernel/engine/runner/mod.js +192 -53
  109. package/esm/src/kernel/engine/runner/schema-validation.js +3 -3
  110. package/esm/src/kernel/engine/runner/stages.d.ts +39 -0
  111. package/esm/src/kernel/engine/runner/stages.js +89 -0
  112. package/esm/src/kernel/engine/runner/state.d.ts +31 -0
  113. package/esm/src/kernel/engine/runner/steps.d.ts +1 -1
  114. package/esm/src/kernel/engine/runner/steps.js +244 -43
  115. package/esm/src/kernel/engine/runner/stream.d.ts +9 -3
  116. package/esm/src/kernel/engine/runner/stream.js +140 -44
  117. package/esm/src/kernel/engine/session/mod.d.ts +25 -0
  118. package/esm/src/kernel/engine/session/mod.js +557 -0
  119. package/esm/src/kernel/interaction-parts.d.ts +14 -0
  120. package/esm/src/kernel/interaction-parts.js +23 -0
  121. package/esm/src/kernel/mod.d.ts +21 -10
  122. package/esm/src/kernel/mod.js +11 -8
  123. package/esm/src/kernel/profile-graph.d.ts +159 -0
  124. package/esm/src/kernel/profile-graph.js +156 -0
  125. package/esm/src/kernel/registry/attachments.d.ts +12 -10
  126. package/esm/src/kernel/registry/attachments.js +33 -27
  127. package/esm/src/kernel/registry/catalog.d.ts +25 -24
  128. package/esm/src/kernel/registry/catalog.js +60 -101
  129. package/esm/src/kernel/registry/ingress.d.ts +9 -4
  130. package/esm/src/kernel/registry/ingress.js +97 -75
  131. package/esm/src/kernel/registry/profile-outputs.d.ts +4 -0
  132. package/esm/src/kernel/registry/profile-outputs.js +8 -0
  133. package/esm/src/kernel/registry/profiles.d.ts +55 -12
  134. package/esm/src/kernel/registry/profiles.js +413 -73
  135. package/esm/src/kernel/registry/provider-request.js +13 -7
  136. package/esm/src/kernel/registry/resolve.d.ts +8 -8
  137. package/esm/src/kernel/registry/resolve.js +169 -154
  138. package/esm/src/kernel/registry/schemas.js +1 -1
  139. package/esm/src/kernel/registry/sole-model.d.ts +8 -0
  140. package/esm/src/kernel/registry/sole-model.js +10 -0
  141. package/esm/src/kernel/registry/system-prompt.d.ts +10 -0
  142. package/esm/src/kernel/registry/system-prompt.js +40 -0
  143. package/esm/src/kernel/registry/system-role.d.ts +8 -0
  144. package/esm/src/kernel/registry/system-role.js +14 -0
  145. package/esm/src/kernel/registry/vault.d.ts +12 -7
  146. package/esm/src/kernel/registry/vault.js +32 -10
  147. package/esm/src/kernel/schema.d.ts +231 -0
  148. package/esm/src/kernel/schema.js +607 -0
  149. package/esm/src/kernel/stages.d.ts +175 -0
  150. package/esm/src/kernel/stages.js +476 -0
  151. package/esm/src/kernel/stop.d.ts +78 -19
  152. package/esm/src/kernel/stop.js +51 -16
  153. package/esm/src/kernel/tools/events.d.ts +41 -0
  154. package/esm/src/kernel/tools/events.js +71 -0
  155. package/esm/src/kernel/tools/execute.d.ts +84 -0
  156. package/esm/src/kernel/tools/execute.js +614 -0
  157. package/esm/src/kernel/tools/harness.d.ts +8 -0
  158. package/esm/src/kernel/tools/harness.js +46 -0
  159. package/esm/src/kernel/tools/invoke.d.ts +10 -0
  160. package/esm/src/kernel/tools/invoke.js +101 -0
  161. package/esm/src/kernel/tools/mod.d.ts +13 -0
  162. package/esm/src/kernel/tools/mod.js +11 -0
  163. package/esm/src/kernel/tools/permission.d.ts +15 -0
  164. package/esm/src/kernel/tools/permission.js +47 -0
  165. package/esm/src/kernel/tools/project.d.ts +12 -0
  166. package/esm/src/kernel/tools/project.js +36 -0
  167. package/esm/src/kernel/tools/registry.d.ts +23 -0
  168. package/esm/src/kernel/tools/registry.js +81 -0
  169. package/esm/src/kernel/tools/remote.d.ts +94 -0
  170. package/esm/src/kernel/tools/remote.js +577 -0
  171. package/esm/src/kernel/tools/resolve.d.ts +39 -0
  172. package/esm/src/kernel/tools/resolve.js +283 -0
  173. package/esm/src/kernel/tools/schema.d.ts +15 -0
  174. package/esm/src/kernel/tools/schema.js +176 -0
  175. package/esm/src/kernel/tools/stage-run.d.ts +105 -0
  176. package/esm/src/kernel/tools/stage-run.js +155 -0
  177. package/esm/src/kernel/tools/types.d.ts +394 -0
  178. package/esm/src/kernel/tools/types.js +9 -0
  179. package/esm/src/kernel/types.d.ts +540 -256
  180. package/esm/src/kernel/util/find-last.d.ts +2 -0
  181. package/esm/src/kernel/util/find-last.js +10 -0
  182. package/esm/src/observability/destinations.d.ts +31 -0
  183. package/esm/src/observability/destinations.js +67 -0
  184. package/esm/src/observability/mod.d.ts +10 -3
  185. package/esm/src/observability/mod.js +6 -2
  186. package/esm/src/observability/policy.d.ts +27 -0
  187. package/esm/src/observability/policy.js +80 -0
  188. package/esm/src/observability/resolve-policy.d.ts +16 -0
  189. package/esm/src/observability/resolve-policy.js +64 -0
  190. package/esm/src/observability/trace-attach.d.ts +8 -4
  191. package/esm/src/observability/trace-attach.js +50 -29
  192. package/esm/src/observability/trace-record.d.ts +23 -13
  193. package/esm/src/observability/trace-record.js +96 -39
  194. package/esm/src/observability/trace-sink.d.ts +19 -0
  195. package/esm/src/observability/trace-sink.js +10 -0
  196. package/esm/src/observability/trace-usage.d.ts +10 -3
  197. package/esm/src/observability/trace-usage.js +70 -17
  198. package/esm/src/observability/trace.d.ts +18 -7
  199. package/esm/src/observability/trace.js +34 -17
  200. package/esm/src/observability/types.d.ts +113 -0
  201. package/esm/src/observability/types.js +11 -0
  202. package/esm/src/presets/google/speech-voices.d.ts +11 -0
  203. package/esm/src/presets/google/speech-voices.js +41 -0
  204. package/esm/src/presets/google.d.ts +36 -24
  205. package/esm/src/presets/google.js +50 -63
  206. package/esm/src/presets/mod.d.ts +2 -2
  207. package/esm/src/presets/mod.js +1 -1
  208. package/esm/src/providers/create-provider.d.ts +20 -17
  209. package/esm/src/providers/create-provider.js +72 -26
  210. package/esm/src/providers/google/interactions/framing.d.ts +23 -0
  211. package/esm/src/providers/google/interactions/framing.js +269 -0
  212. package/esm/src/providers/google/interactions/mod.d.ts +7 -0
  213. package/esm/src/providers/google/interactions/mod.js +7 -0
  214. package/esm/src/providers/google/interactions/stream.d.ts +83 -0
  215. package/esm/src/providers/google/interactions/stream.js +588 -0
  216. package/esm/src/providers/google/keys.d.ts +26 -0
  217. package/esm/src/providers/{keys.js → google/keys.js} +19 -31
  218. package/esm/src/providers/google/live/framing.d.ts +49 -0
  219. package/esm/src/providers/google/live/framing.js +552 -0
  220. package/esm/src/providers/google/live/openapi-schema.d.ts +6 -0
  221. package/esm/src/providers/google/live/openapi-schema.js +46 -0
  222. package/esm/src/providers/google/live/session.d.ts +25 -0
  223. package/esm/src/providers/google/live/session.js +134 -0
  224. package/esm/src/providers/google/live/stream.d.ts +45 -0
  225. package/esm/src/providers/google/live/stream.js +214 -0
  226. package/esm/src/providers/google/urls.d.ts +6 -0
  227. package/esm/src/providers/google/urls.js +6 -0
  228. package/esm/src/providers/local/local.d.ts +30 -0
  229. package/esm/src/providers/{local.js → local/local.js} +66 -126
  230. package/esm/src/providers/local/mod.d.ts +9 -0
  231. package/esm/src/providers/local/mod.js +9 -0
  232. package/esm/src/providers/mod.d.ts +6 -3
  233. package/esm/src/providers/mod.js +3 -1
  234. package/esm/src/providers/openrouter/cache-control.d.ts +24 -0
  235. package/esm/src/providers/openrouter/cache-control.js +23 -0
  236. package/esm/src/providers/openrouter/chat.d.ts +107 -0
  237. package/esm/src/providers/{openrouter.js → openrouter/chat.js} +117 -231
  238. package/esm/src/providers/openrouter/image.d.ts +34 -0
  239. package/esm/src/providers/openrouter/image.js +275 -0
  240. package/esm/src/providers/openrouter/openai/chat-payload.d.ts +24 -0
  241. package/esm/src/providers/openrouter/openai/chat-payload.js +82 -0
  242. package/esm/src/providers/openrouter/openai/compat.d.ts +53 -0
  243. package/esm/src/providers/openrouter/openai/compat.js +213 -0
  244. package/esm/src/providers/openrouter/openai/image-payload.d.ts +18 -0
  245. package/esm/src/providers/openrouter/openai/image-payload.js +90 -0
  246. package/esm/src/providers/openrouter/openai/sdk-messages.d.ts +22 -0
  247. package/esm/src/providers/openrouter/openai/sdk-messages.js +122 -0
  248. package/esm/src/providers/openrouter/resolve-api-key.d.ts +9 -0
  249. package/esm/src/providers/openrouter/resolve-api-key.js +24 -0
  250. package/esm/src/providers/openrouter/speech.d.ts +23 -0
  251. package/esm/src/providers/{speech.js → openrouter/speech.js} +32 -55
  252. package/esm/src/providers/probe.d.ts +1 -0
  253. package/esm/src/providers/probe.js +22 -0
  254. package/esm/src/providers/shared/pcm.d.ts +12 -0
  255. package/esm/src/providers/{pcm.js → shared/pcm.js} +16 -3
  256. package/esm/src/providers/shared/sse.d.ts +18 -0
  257. package/esm/src/providers/shared/sse.js +87 -0
  258. package/esm/src/providers/shared/tool-args.d.ts +17 -0
  259. package/esm/src/providers/shared/tool-args.js +45 -0
  260. package/esm/src/providers/shared/upstream-tap.d.ts +5 -0
  261. package/esm/src/providers/{google-tap.js → shared/upstream-tap.js} +4 -7
  262. package/esm/src/providers/shared/upstream-tape.d.ts +6 -0
  263. package/esm/src/providers/{gemini-tape.js → shared/upstream-tape.js} +12 -22
  264. package/esm/src/providers/types.d.ts +27 -0
  265. package/esm/src/providers/types.js +1 -0
  266. package/package.json +11 -7
  267. package/docs/cli.md +0 -97
  268. package/docs/guardrails.md +0 -178
  269. package/docs/host.md +0 -97
  270. package/docs/kernel.md +0 -404
  271. package/docs/observability.md +0 -105
  272. package/docs/openrouter.md +0 -125
  273. package/docs/presets-google.md +0 -91
  274. package/docs/presets.md +0 -88
  275. package/docs/providers.md +0 -202
  276. package/docs/streaming.md +0 -96
  277. package/esm/src/kernel/engine/boundary.d.ts +0 -10
  278. package/esm/src/kernel/engine/boundary.js +0 -55
  279. package/esm/src/kernel/engine/runner/tools.d.ts +0 -13
  280. package/esm/src/kernel/engine/runner/tools.js +0 -198
  281. package/esm/src/kernel/registry/tools.d.ts +0 -12
  282. package/esm/src/kernel/registry/tools.js +0 -36
  283. package/esm/src/providers/expose-for-tests.d.ts +0 -1
  284. package/esm/src/providers/expose-for-tests.js +0 -25
  285. package/esm/src/providers/gemini-tape.d.ts +0 -2
  286. package/esm/src/providers/google-tap.d.ts +0 -3
  287. package/esm/src/providers/interactions.d.ts +0 -5
  288. package/esm/src/providers/interactions.js +0 -169
  289. package/esm/src/providers/keys.d.ts +0 -19
  290. package/esm/src/providers/local.d.ts +0 -29
  291. package/esm/src/providers/openrouter-mod.d.ts +0 -13
  292. package/esm/src/providers/openrouter-mod.js +0 -12
  293. package/esm/src/providers/openrouter-payload.d.ts +0 -39
  294. package/esm/src/providers/openrouter-payload.js +0 -195
  295. package/esm/src/providers/openrouter.d.ts +0 -15
  296. package/esm/src/providers/pcm.d.ts +0 -7
  297. package/esm/src/providers/provider.d.ts +0 -15
  298. package/esm/src/providers/provider.js +0 -202
  299. package/esm/src/providers/speech.d.ts +0 -23
  300. package/esm/src/providers/sse.d.ts +0 -7
  301. package/esm/src/providers/sse.js +0 -55
  302. package/esm/src/streaming/mod.d.ts +0 -9
  303. package/esm/src/streaming/mod.js +0 -8
  304. /package/esm/src/{streaming → host}/readStreamingJsonStringField.d.ts +0 -0
  305. /package/esm/src/{streaming → host}/readStreamingJsonStringField.js +0 -0
@@ -6,45 +6,67 @@
6
6
  *
7
7
  * @module
8
8
  */
9
+ import { OMIT_CANARY } from '../guardrails/canary.js';
9
10
  import { isAbortError, publicError } from '../guardrails/error.js';
10
- import { redactSensitiveOnly, sanitizeText, sanitizeTurnRequest } from '../guardrails/sanitize.js';
11
- import { OMIT_CANARY } from '../kernel/engine/boundary.js';
11
+ import { projectGuardrailEvent } from '../guardrails/hits.js';
12
+ import { redactSensitiveOnly, sanitizeText, sanitizeTurnRequestForTrace, } from '../guardrails/sanitize.js';
12
13
  import { sha256 } from '../kernel/engine/hash.js';
14
+ import { resolveObservabilityPolicy } from './resolve-policy.js';
13
15
  import { attachResolved, attachTape, attachUsage } from './trace-attach.js';
14
- import { completedInteraction } from './trace-usage.js';
16
+ import { completedInteraction, stopKindFromEvents } from './trace-usage.js';
15
17
  const TRACE_VERSION = 2;
16
18
  const TITLE_MAX = 80;
17
19
  function hashBlobs(blobs) {
18
20
  if (!blobs) {
19
21
  return Promise.resolve([]);
20
22
  }
21
- return Promise.all(blobs.map(async (blob) => ({
22
- mimeType: blob.mimeType,
23
- sha256: await sha256(blob.data),
24
- })));
23
+ return Promise.all(blobs.map(async (blob) => 'uri' in blob
24
+ ? { mimeType: blob.mimeType, uri: blob.uri }
25
+ : { mimeType: blob.mimeType, sha256: await sha256(blob.data) }));
25
26
  }
26
- async function snapshotEvent(event) {
27
+ function scrubStoredText(text, scrub) {
28
+ if (scrub.sensitive && scrub.injection) {
29
+ return sanitizeText(text);
30
+ }
31
+ if (scrub.sensitive) {
32
+ return redactSensitiveOnly(text);
33
+ }
34
+ if (scrub.injection) {
35
+ return sanitizeText(text, { sanitizeInput: true, redactSensitive: false });
36
+ }
37
+ return text;
38
+ }
39
+ async function snapshotEvent(event, include, scrub) {
27
40
  const row = { type: event.type };
28
41
  if (event.text) {
29
- row.text = redactSensitiveOnly(event.text);
42
+ row.text = scrubStoredText(event.text, scrub);
30
43
  }
31
44
  if (event.error) {
32
45
  row.error = event.error;
33
46
  }
34
47
  if (event.errorInternal) {
35
- row.errorInternal = redactSensitiveOnly(event.errorInternal);
48
+ row.errorInternal = scrubStoredText(event.errorInternal, scrub);
36
49
  }
37
50
  if (event.structured !== undefined) {
38
51
  row.structured = event.structured;
39
52
  }
40
53
  if (event.tool) {
41
- const { name, arguments: args, result } = event.tool;
54
+ const { name, arguments: args, output, phase, failure } = event.tool;
42
55
  row.tool = { name, arguments: args };
43
- if (result) {
56
+ if (output !== undefined && phase === 'complete') {
57
+ const data = typeof output === 'object' && output !== null
58
+ ? output
59
+ : { value: output };
60
+ row.tool.result = {
61
+ status: 'ok',
62
+ ...(typeof data.finding === 'string' ? { finding: data.finding } : {}),
63
+ data,
64
+ };
65
+ }
66
+ else if (phase === 'error' && failure) {
44
67
  row.tool.result = {
45
- status: result.status,
46
- ...(result.finding ? { finding: result.finding } : {}),
47
- ...(result.data ? { data: result.data } : {}),
68
+ status: 'error',
69
+ finding: failure.message,
48
70
  };
49
71
  }
50
72
  }
@@ -57,18 +79,16 @@ async function snapshotEvent(event) {
57
79
  if (event.grounding) {
58
80
  row.grounding = event.grounding;
59
81
  }
60
- if (event.evidence) {
82
+ if (include.evidenceRaw && event.evidence) {
61
83
  row.evidence = event.evidence;
62
84
  }
85
+ if (event.guardrail) {
86
+ row.guardrail = projectGuardrailEvent(event.guardrail, include.guardrailMatchPreview);
87
+ }
63
88
  return row;
64
89
  }
65
90
  function requestForTrace(req) {
66
- try {
67
- return sanitizeTurnRequest(req);
68
- }
69
- catch {
70
- return { profile: req.profile, input: {} };
71
- }
91
+ return sanitizeTurnRequestForTrace(req);
72
92
  }
73
93
  function internalError(err) {
74
94
  if (typeof err === 'string') {
@@ -89,56 +109,93 @@ function titleFrom(text) {
89
109
  }
90
110
  return trimmed.slice(0, TITLE_MAX);
91
111
  }
92
- function attachFailure(record, thrown, lastErr, canary) {
112
+ function attachFailure(record, thrown, lastErr, canary, scrub) {
93
113
  if (!record.ok) {
94
114
  record.error = publicError(thrown ?? lastErr?.error);
95
115
  const inside = internalError(thrown) ?? lastErr?.errorInternal ?? lastErr?.error;
96
116
  if (inside) {
97
- record.errorInternal = inside;
117
+ record.errorInternal = scrubStoredText(inside, scrub);
98
118
  }
99
119
  }
100
- if (canary && JSON.stringify(record).includes(canary)) {
120
+ if (scrub.canary && canary && JSON.stringify(record).includes(canary)) {
101
121
  record.errorInternal = OMIT_CANARY;
102
122
  }
103
123
  }
124
+ function eventsForTrace(events, include) {
125
+ if (include.guardrailDecisions) {
126
+ return events;
127
+ }
128
+ return events.filter((event) => event.type !== 'guardrail');
129
+ }
130
+ function asResolvedPolicy(value) {
131
+ if (value &&
132
+ typeof value === 'object' &&
133
+ 'record' in value &&
134
+ typeof value.record === 'boolean') {
135
+ return value;
136
+ }
137
+ return resolveObservabilityPolicy(value);
138
+ }
104
139
  async function buildRecord(args) {
105
- const { req, events, started, model, bucket, thrown, gemini, canary, system, generation } = args;
106
- const safe = args.sanitizedReq ?? requestForTrace(req);
140
+ const { req, events, started, model, keySlot, thrown, upstreamLog, canary, system, generation } = args;
141
+ const protocol = args.protocol;
142
+ const policy = asResolvedPolicy(args.observability);
143
+ const { include, scrub } = policy;
144
+ const traced = args.sanitizedReq ? { request: args.sanitizedReq } : requestForTrace(req);
145
+ const safe = traced.request;
107
146
  const input = safe.input ?? {};
108
- const snapped = await Promise.all(events.map((event) => snapshotEvent(event)));
147
+ const traceEvents = eventsForTrace(events, include);
148
+ const snapped = await Promise.all(traceEvents.map((event) => snapshotEvent(event, include, scrub)));
109
149
  const lastErr = [...snapped].reverse().find((row) => row.type === 'error');
110
- const done = completedInteraction(gemini);
111
- const status = done?.status;
112
150
  const aborted = isAbortError(thrown);
113
- const ok = !(thrown || lastErr) && status !== 'cancelled' && !aborted;
151
+ const stopKind = stopKindFromEvents(events);
152
+ const done = completedInteraction(upstreamLog);
153
+ const interactionStatus = done?.status;
154
+ const cancelled = aborted ||
155
+ stopKind === 'cancelled' ||
156
+ (protocol === 'geminiInteractions' && interactionStatus === 'cancelled');
157
+ const ok = !(thrown || lastErr) && !cancelled;
114
158
  const record = {
115
159
  v: TRACE_VERSION,
116
160
  id: crypto.randomUUID(),
117
161
  ts: started,
118
162
  ms: Date.now() - started,
119
163
  streamed: true,
120
- cancelled: status === 'cancelled' || aborted,
164
+ cancelled,
121
165
  previousInteractionId: safe.previousInteractionId ?? null,
122
166
  store: safe.store ?? null,
123
167
  profile: safe.profile,
124
168
  input: {
125
- text: input.text,
169
+ text: input.text !== undefined ? scrubStoredText(input.text, scrub) : undefined,
126
170
  role: input.role,
127
- slots: input.slots,
171
+ slots: input.slots
172
+ ? Object.fromEntries(Object.entries(input.slots).map(([key, value]) => [key, scrubStoredText(value, scrub)]))
173
+ : undefined,
128
174
  attachments: await hashBlobs(input.attachments),
129
175
  voice: await hashBlobs(input.voice),
130
176
  },
131
177
  events: snapped,
132
178
  ok,
133
179
  };
134
- const title = titleFrom(input.text);
180
+ const title = titleFrom(record.input.text);
135
181
  if (title) {
136
182
  record.title = title;
137
183
  }
138
- await attachTape(record, { gemini, canary, system, generation });
139
- attachUsage(record, gemini, done);
140
- attachResolved(record, { safe, model, bucket, generation });
141
- attachFailure(record, thrown, lastErr, canary);
184
+ const tapeCanary = scrub.canary ? canary : undefined;
185
+ await attachTape(record, {
186
+ upstream: upstreamLog,
187
+ canary: tapeCanary,
188
+ system,
189
+ generation,
190
+ protocol,
191
+ include,
192
+ });
193
+ attachUsage(record, upstreamLog, done, events, include);
194
+ attachResolved(record, { safe, model, keySlot, generation });
195
+ attachFailure(record, thrown, lastErr, canary, scrub);
196
+ if (traced.sanitizeError && !record.errorInternal) {
197
+ record.errorInternal = scrubStoredText(`request sanitize for trace failed: ${traced.sanitizeError}`, scrub);
198
+ }
142
199
  return record;
143
200
  }
144
201
  export { buildRecord };
@@ -0,0 +1,19 @@
1
+ /**
2
+ * Trace sink contract.
3
+ *
4
+ * Type-only so hosts that consume kernel types under a non-Deno TypeScript
5
+ * program (browser bundles, Workers) never pull the JSONL file sink and its
6
+ * `Deno` calls into their type graph. Implementations live in `trace.ts`.
7
+ *
8
+ * @module
9
+ */
10
+ import type { TraceRecord } from './trace-record.js';
11
+ /** Minimal async destination for completed turn trace records. */
12
+ export interface TraceSink {
13
+ write: (record: TraceRecord) => Promise<void>;
14
+ /**
15
+ * Optional host hook when `writeTrace` catches record-build or write failures.
16
+ * Must not throw; tracing never fails the turn.
17
+ */
18
+ onError?: (err: unknown) => void;
19
+ }
@@ -0,0 +1,10 @@
1
+ /**
2
+ * Trace sink contract.
3
+ *
4
+ * Type-only so hosts that consume kernel types under a non-Deno TypeScript
5
+ * program (browser bundles, Workers) never pull the JSONL file sink and its
6
+ * `Deno` calls into their type graph. Implementations live in `trace.ts`.
7
+ *
8
+ * @module
9
+ */
10
+ export {};
@@ -1,3 +1,10 @@
1
- declare function completedInteraction(gemini: unknown): Record<string, unknown> | undefined;
2
- declare function httpStatus(gemini: unknown): unknown;
3
- export { completedInteraction, httpStatus };
1
+ import type { TurnEvent, TurnTokens } from '../kernel/types.js';
2
+ declare function completedInteraction(upstream: unknown): Record<string, unknown> | undefined;
3
+ /** Extract the terminal stop kind from the TurnEvent stream (protocol-agnostic). */
4
+ declare function stopKindFromEvents(events: TurnEvent[]): string | undefined;
5
+ /** Extract the last tokens snapshot from the TurnEvent stream. */
6
+ declare function tokensFromEvents(events: TurnEvent[]): TurnTokens | undefined;
7
+ /** Extract finish_reason from OpenAI-compat upstream tap rows. */
8
+ declare function openAiFinishReason(upstream: unknown): string | undefined;
9
+ declare function httpStatus(upstream: unknown): unknown;
10
+ export { completedInteraction, httpStatus, openAiFinishReason, stopKindFromEvents, tokensFromEvents, };
@@ -2,31 +2,84 @@ import { asRecord } from '../kernel/engine/record.js';
2
2
  function eventName(row) {
3
3
  return String(row.event_type ?? row.eventType ?? '');
4
4
  }
5
- function completedInteraction(gemini) {
6
- if (!Array.isArray(gemini)) {
7
- return undefined;
5
+ function upstreamRows(upstream) {
6
+ if (!Array.isArray(upstream)) {
7
+ return [];
8
8
  }
9
- for (let i = gemini.length - 1; i >= 0; i -= 1) {
10
- const row = asRecord(gemini[i]);
11
- if (row) {
12
- const name = eventName(row);
13
- if (name === 'interaction.completed' || name === 'interaction.complete') {
14
- return asRecord(row.interaction) ?? row;
15
- }
9
+ return upstream
10
+ .map((item) => asRecord(item))
11
+ .filter((row) => row != null);
12
+ }
13
+ function lastUpstreamRow(upstream, pred) {
14
+ const rows = upstreamRows(upstream);
15
+ for (let i = rows.length - 1; i >= 0; i -= 1) {
16
+ if (pred(rows[i])) {
17
+ return rows[i];
18
+ }
19
+ }
20
+ return undefined;
21
+ }
22
+ function firstUpstreamRow(upstream, pred) {
23
+ for (const row of upstreamRows(upstream)) {
24
+ if (pred(row)) {
25
+ return row;
16
26
  }
17
27
  }
18
28
  return undefined;
19
29
  }
20
- function httpStatus(gemini) {
21
- if (!Array.isArray(gemini)) {
30
+ function completedInteraction(upstream) {
31
+ const row = lastUpstreamRow(upstream, (r) => {
32
+ const name = eventName(r);
33
+ return name === 'interaction.completed' || name === 'interaction.complete';
34
+ });
35
+ return row ? (asRecord(row.interaction) ?? row) : undefined;
36
+ }
37
+ /** Extract the terminal stop kind from the TurnEvent stream (protocol-agnostic). */
38
+ function stopKindFromEvents(events) {
39
+ for (let i = events.length - 1; i >= 0; i -= 1) {
40
+ const ev = events[i];
41
+ if (ev?.type === 'done' && ev.stop) {
42
+ return ev.stop.kind;
43
+ }
44
+ }
45
+ return undefined;
46
+ }
47
+ /** Extract the last tokens snapshot from the TurnEvent stream. */
48
+ function tokensFromEvents(events) {
49
+ for (let i = events.length - 1; i >= 0; i -= 1) {
50
+ const ev = events[i];
51
+ if (ev?.type === 'tokens' && ev.tokens) {
52
+ return ev.tokens;
53
+ }
54
+ }
55
+ return undefined;
56
+ }
57
+ /** Extract finish_reason from OpenAI-compat upstream tap rows. */
58
+ function openAiFinishReason(upstream) {
59
+ const row = lastUpstreamRow(upstream, (r) => {
60
+ const choices = r.choices;
61
+ if (!Array.isArray(choices)) {
62
+ return false;
63
+ }
64
+ return choices.some((choice) => asRecord(choice)?.finish_reason != null);
65
+ });
66
+ if (!row) {
67
+ return undefined;
68
+ }
69
+ const choices = row.choices;
70
+ if (!Array.isArray(choices)) {
22
71
  return undefined;
23
72
  }
24
- for (const item of gemini) {
25
- const row = asRecord(item);
26
- if (row && eventName(row) === 'http_response') {
27
- return row.status;
73
+ for (const choice of choices) {
74
+ const c = asRecord(choice);
75
+ if (c?.finish_reason != null) {
76
+ return String(c.finish_reason);
28
77
  }
29
78
  }
30
79
  return undefined;
31
80
  }
32
- export { completedInteraction, httpStatus };
81
+ function httpStatus(upstream) {
82
+ const row = firstUpstreamRow(upstream, (r) => eventName(r) === 'http_response');
83
+ return row?.status;
84
+ }
85
+ export { completedInteraction, httpStatus, openAiFinishReason, stopKindFromEvents, tokensFromEvents, };
@@ -1,16 +1,27 @@
1
1
  import type { TraceRecord } from './trace-record.js';
2
- /** Minimal async destination for completed turn trace records. */
3
- interface TraceSink {
4
- write: (record: TraceRecord) => Promise<void>;
2
+ import type { TraceSink } from './trace-sink.js';
3
+ /** Options for daily rotating JSONL sinks. */
4
+ interface JsonlSinkOptions {
5
+ retainForDays?: number;
6
+ rotateAfterMiB?: number;
7
+ now?: () => number;
5
8
  }
6
- /** Write a trace record without allowing trace failures to fail the turn. */
9
+ /**
10
+ * Write a trace record without allowing trace failures to fail the turn.
11
+ * Build/write errors are forwarded to `sink.onError` when provided.
12
+ */
7
13
  declare function writeTrace(sink: TraceSink, record: Promise<TraceRecord>): Promise<void>;
8
14
  /** Trace sink that drops records. */
9
15
  declare function noopSink(): TraceSink;
10
16
  /** Trace sink that appends records to a caller-owned array. */
11
17
  declare function memorySink(into: TraceRecord[]): TraceSink;
12
- /** Trace sink that writes daily rotating JSONL files under a host-selected directory. */
13
- declare function jsonlSink(dir: string, now?: () => number): TraceSink;
18
+ /**
19
+ * Trace sink that writes daily rotating JSONL files under a host-selected directory.
20
+ *
21
+ * @param dir - Absolute host-chosen directory
22
+ * @param optionsOrNow - Retention/rotate options, or a `now` clock (legacy)
23
+ */
24
+ declare function jsonlSink(dir: string, optionsOrNow?: JsonlSinkOptions | (() => number)): TraceSink;
14
25
  /** Resolve a trace directory while refusing relative paths or paths inside the clone. */
15
26
  declare function resolveTraceDir(args: {
16
27
  dir?: string;
@@ -19,5 +30,5 @@ declare function resolveTraceDir(args: {
19
30
  }): string | undefined;
20
31
  /** Build a JSONL sink from a host-supplied directory or return a noop sink. */
21
32
  declare function sinkFromDir(dir?: string, fallbackDir?: string): TraceSink;
22
- export type { TraceSink };
33
+ export type { JsonlSinkOptions };
23
34
  export { jsonlSink, memorySink, noopSink, resolveTraceDir, sinkFromDir, writeTrace };
@@ -2,30 +2,37 @@
2
2
  * Trace sink primitives for THEORUM.
3
3
  *
4
4
  * Tracing is host-injected: the kernel can write to a provided sink, a memory
5
- * sink, a JSONL directory, or a noop sink. It does not read environment
6
- * variables or own a database destination.
5
+ * sink, a JSONL directory, or a noop sink. Profiles declare policy via
6
+ * `observability`; hosts register named destinations. THEORUM does not read
7
+ * environment variables or own a database destination.
7
8
  *
8
9
  * @module
9
10
  */
10
11
  import * as dntShim from "../../_dnt.shims.js";
11
- const RETAIN_DAYS = 14;
12
+ const DEFAULT_RETAIN_DAYS = 14;
12
13
  const HOURS_PER_DAY = 24;
13
14
  const MIN_PER_HOUR = 60;
14
15
  const SEC_PER_MIN = 60;
15
16
  const MS_PER_SEC = 1000;
16
- const RETAIN_MS = RETAIN_DAYS * HOURS_PER_DAY * MIN_PER_HOUR * SEC_PER_MIN * MS_PER_SEC;
17
17
  const KIB = 1024;
18
18
  const MIB = KIB * KIB;
19
- const ROTATE_MIB = 32;
20
- const ROTATE_BYTES = ROTATE_MIB * MIB;
19
+ const DEFAULT_ROTATE_MIB = 32;
21
20
  const FILE_DAY = /^turns-(\d{4}-\d{2}-\d{2})(?:-\d+)?\.jsonl$/;
22
- /** Write a trace record without allowing trace failures to fail the turn. */
21
+ /**
22
+ * Write a trace record without allowing trace failures to fail the turn.
23
+ * Build/write errors are forwarded to `sink.onError` when provided.
24
+ */
23
25
  async function writeTrace(sink, record) {
24
26
  try {
25
27
  await sink.write(await record);
26
28
  }
27
- catch {
28
- // Tracing must not fail the turn.
29
+ catch (err) {
30
+ try {
31
+ sink.onError?.(err);
32
+ }
33
+ catch {
34
+ // Host onError must not fail the turn.
35
+ }
29
36
  }
30
37
  }
31
38
  /** Trace sink that drops records. */
@@ -47,8 +54,9 @@ function dayStamp(ms) {
47
54
  function fileDay(name) {
48
55
  return FILE_DAY.exec(name)?.[1];
49
56
  }
50
- async function pruneTraces(dir, now) {
51
- const cutoff = now - RETAIN_MS;
57
+ async function pruneTraces(dir, now, retainForDays) {
58
+ const retainMs = retainForDays * HOURS_PER_DAY * MIN_PER_HOUR * SEC_PER_MIN * MS_PER_SEC;
59
+ const cutoff = now - retainMs;
52
60
  for await (const entry of dntShim.Deno.readDir(dir)) {
53
61
  const day = fileDay(entry.name);
54
62
  if (day && Date.parse(`${day}T00:00:00.000Z`) < cutoff) {
@@ -56,12 +64,12 @@ async function pruneTraces(dir, now) {
56
64
  }
57
65
  }
58
66
  }
59
- async function pickFile(dir, now) {
67
+ async function pickFile(dir, now, rotateBytes) {
60
68
  const day = dayStamp(now);
61
69
  const base = `${dir}/turns-${day}.jsonl`;
62
70
  try {
63
71
  const info = await dntShim.Deno.stat(base);
64
- if ((info.size ?? 0) < ROTATE_BYTES) {
72
+ if ((info.size ?? 0) < rotateBytes) {
65
73
  return base;
66
74
  }
67
75
  }
@@ -70,14 +78,23 @@ async function pickFile(dir, now) {
70
78
  }
71
79
  return `${dir}/turns-${day}-${now}.jsonl`;
72
80
  }
73
- /** Trace sink that writes daily rotating JSONL files under a host-selected directory. */
74
- function jsonlSink(dir, now = Date.now) {
81
+ /**
82
+ * Trace sink that writes daily rotating JSONL files under a host-selected directory.
83
+ *
84
+ * @param dir - Absolute host-chosen directory
85
+ * @param optionsOrNow - Retention/rotate options, or a `now` clock (legacy)
86
+ */
87
+ function jsonlSink(dir, optionsOrNow) {
88
+ const options = typeof optionsOrNow === 'function' ? { now: optionsOrNow } : (optionsOrNow ?? {});
89
+ const now = options.now ?? Date.now;
90
+ const retainForDays = options.retainForDays ?? DEFAULT_RETAIN_DAYS;
91
+ const rotateBytes = (options.rotateAfterMiB ?? DEFAULT_ROTATE_MIB) * MIB;
75
92
  return {
76
93
  write: async (record) => {
77
94
  const at = now();
78
95
  await dntShim.Deno.mkdir(dir, { recursive: true });
79
- await pruneTraces(dir, at);
80
- const path = await pickFile(dir, at);
96
+ await pruneTraces(dir, at, retainForDays);
97
+ const path = await pickFile(dir, at, rotateBytes);
81
98
  await dntShim.Deno.writeTextFile(path, `${JSON.stringify(record)}\n`, { append: true });
82
99
  },
83
100
  };
@@ -0,0 +1,113 @@
1
+ /**
2
+ * Profile observability vocabulary — destination, scrub, and include policy.
3
+ *
4
+ * This module is the single source of truth for observability profile types. It
5
+ * must not import from `src/kernel/`: the kernel type-imports
6
+ * `ProfileObservabilitySpec` for `ProfileCommon.observability`, and that edge
7
+ * stays one-directional.
8
+ *
9
+ * @module
10
+ */
11
+ import type { TraceSink } from './trace-sink.js';
12
+ /** Which payloads land in each TraceRecord. Omitted keys use resolved defaults. */
13
+ export interface TraceIncludeSpec {
14
+ /** Scrubbed provider HTTP/SSE rows. Default: true. */
15
+ upstreamLog?: boolean;
16
+ /** Scrubbed outbound request body. Default: false. */
17
+ outboundWire?: boolean;
18
+ /** Verbatim provider step JSON (`events[].evidence.raw`). Default: false. */
19
+ evidenceRaw?: boolean;
20
+ /** Token / usage fields. Default: true. */
21
+ usage?: boolean;
22
+ /**
23
+ * Persist `{ type: 'guardrail' }` decisions into the TraceRecord. Default: true.
24
+ */
25
+ guardrailDecisions?: boolean;
26
+ /**
27
+ * Keep `GuardrailHit.match` (exact matched substring, capped) on guardrail
28
+ * events in the live stream and TraceRecord. Default: false — debugging only;
29
+ * treat like server logs when enabled.
30
+ */
31
+ guardrailMatchPreview?: boolean;
32
+ }
33
+ /**
34
+ * Scrubbing of what is written — independent of turn-path `profile.guardrails`.
35
+ * Defaults are safe for a host-confidential store.
36
+ */
37
+ export interface TraceScrubSpec {
38
+ /** Strip credentials / PII spans in stored text. Default: true. */
39
+ sensitive?: boolean;
40
+ /** Strip injection spans in the stored request copy. Default: true. */
41
+ injection?: boolean;
42
+ /** Never persist the canary token. Default: true. */
43
+ canary?: boolean;
44
+ }
45
+ /**
46
+ * Profile observability — what to record, and where.
47
+ *
48
+ * Omit the whole block → no tracing (noop). Prefer `writeTo: '<registered-id>'`
49
+ * in shared profiles; pass a TraceSink only for tests / custom exporters.
50
+ */
51
+ export interface ProfileObservabilitySpec {
52
+ /**
53
+ * Destination for completed turn records.
54
+ *
55
+ * - `false` — explicitly off
56
+ * - `string` — host-registered destination id (`registerTraceDestination`)
57
+ * - `TraceSink` — inline writer (tests, OTEL bridge, etc.)
58
+ *
59
+ * `runTurn(..., sink)` still overrides this for one call.
60
+ */
61
+ writeTo?: false | string | TraceSink;
62
+ /**
63
+ * Fraction of turns to record, 0–1 inclusive.
64
+ * Omitted → 1 (every turn). `0` means record none.
65
+ */
66
+ sampleRate?: number;
67
+ /** Which payloads land in each TraceRecord. */
68
+ include?: TraceIncludeSpec;
69
+ /**
70
+ * Scrubbing of stored records — independent of turn-path guardrails.
71
+ * Defaults stay on even when `guardrails.redactSensitive` is false.
72
+ */
73
+ scrub?: TraceScrubSpec;
74
+ /** JSONL retention days when the resolved destination is JSONL. Default: 14. */
75
+ retainForDays?: number;
76
+ /** JSONL rotate threshold in MiB when the resolved destination is JSONL. Default: 32. */
77
+ rotateAfterMiB?: number;
78
+ /**
79
+ * Called when record build or destination write fails.
80
+ * Must not throw; tracing never fails the turn.
81
+ */
82
+ onWriteError?: (err: unknown) => void;
83
+ }
84
+ /** Resolved include flags after defaults. */
85
+ export interface ResolvedTraceInclude {
86
+ upstreamLog: boolean;
87
+ outboundWire: boolean;
88
+ evidenceRaw: boolean;
89
+ usage: boolean;
90
+ guardrailDecisions: boolean;
91
+ guardrailMatchPreview: boolean;
92
+ }
93
+ /** Resolved scrub flags after defaults. */
94
+ export interface ResolvedTraceScrub {
95
+ sensitive: boolean;
96
+ injection: boolean;
97
+ canary: boolean;
98
+ }
99
+ /**
100
+ * Observability policy with defaults applied.
101
+ * Every path resolves through `resolveObservabilityPolicy`.
102
+ */
103
+ export interface ResolvedObservabilityPolicy {
104
+ /** False when omitted, `writeTo: false`, or sampleRate drops the turn. */
105
+ record: boolean;
106
+ writeTo: false | string | TraceSink | undefined;
107
+ sampleRate: number;
108
+ include: ResolvedTraceInclude;
109
+ scrub: ResolvedTraceScrub;
110
+ retainForDays: number;
111
+ rotateAfterMiB: number;
112
+ onWriteError?: (err: unknown) => void;
113
+ }
@@ -0,0 +1,11 @@
1
+ /**
2
+ * Profile observability vocabulary — destination, scrub, and include policy.
3
+ *
4
+ * This module is the single source of truth for observability profile types. It
5
+ * must not import from `src/kernel/`: the kernel type-imports
6
+ * `ProfileObservabilitySpec` for `ProfileCommon.observability`, and that edge
7
+ * stays one-directional.
8
+ *
9
+ * @module
10
+ */
11
+ export {};
@@ -0,0 +1,11 @@
1
+ /**
2
+ * Google Gemini TTS voice names for `speech.voice`.
3
+ *
4
+ * Standalone preset vocabulary — no kernel registry imports so docs UIs can
5
+ * import this file without pulling provider wiring.
6
+ *
7
+ * @module
8
+ */
9
+ /** Common Gemini TTS voice names. */
10
+ export declare const GOOGLE_SPEECH_VOICES: readonly ["Zephyr", "Puck", "Charon", "Kore", "Fenrir", "Leda", "Orus", "Aoede", "Callirrhoe", "Autonoe", "Enceladus", "Iapetus", "Umbriel", "Algieba", "Despina", "Erinome", "Algenib", "Rasalgethi", "Laomedeia", "Achernar", "Alnilam", "Schedar", "Gacrux", "Pulcherrima", "Achird", "Zubenelgenubi", "Vindemiatrix", "Sadachbia", "Sadaltager", "Sulafat"];
11
+ export type GoogleSpeechVoice = (typeof GOOGLE_SPEECH_VOICES)[number];