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
@@ -0,0 +1,2 @@
1
+ /** ES2022-safe replacement for `Array.prototype.findLast`. */
2
+ export declare function findLast<T>(items: readonly T[], predicate: (item: T) => boolean): T | undefined;
@@ -0,0 +1,10 @@
1
+ /** ES2022-safe replacement for `Array.prototype.findLast`. */
2
+ export function findLast(items, predicate) {
3
+ for (let i = items.length - 1; i >= 0; i -= 1) {
4
+ const item = items[i];
5
+ if (item !== undefined && predicate(item)) {
6
+ return item;
7
+ }
8
+ }
9
+ return undefined;
10
+ }
@@ -0,0 +1,31 @@
1
+ /**
2
+ * Host-registered trace destinations for profile `observability.writeTo` ids.
3
+ *
4
+ * THEORUM does not invent filesystem roots. Hosts register a named destination
5
+ * once per process; profiles reference it by id.
6
+ *
7
+ * @module
8
+ */
9
+ import type { TraceSink } from './trace-sink.js';
10
+ /** JSONL directory destination — retention comes from profile policy at resolve time. */
11
+ export interface JsonlTraceDestination {
12
+ readonly kind: 'jsonl';
13
+ readonly dir: string;
14
+ }
15
+ /** Something a host may register under a destination id. */
16
+ export type TraceDestination = TraceSink | JsonlTraceDestination;
17
+ /** Build a JSONL destination descriptor for `registerTraceDestination`. */
18
+ declare function jsonlDestination(dir: string): JsonlTraceDestination;
19
+ declare function isJsonlTraceDestination(value: TraceDestination): value is JsonlTraceDestination;
20
+ declare function isTraceSink(value: TraceDestination): value is TraceSink;
21
+ /** Register a named destination for profile `observability.writeTo`. */
22
+ declare function registerTraceDestination(id: string, destination: TraceDestination): void;
23
+ /** Look up a registered destination; undefined when missing. */
24
+ declare function getTraceDestination(id: string): TraceDestination | undefined;
25
+ /** Require a registered destination or throw. */
26
+ declare function requireTraceDestination(id: string): TraceDestination;
27
+ /** List registered destination ids (stable sort). */
28
+ declare function listTraceDestinationIds(): string[];
29
+ /** Clear the destination registry (tests). */
30
+ declare function clearTraceDestinations(): void;
31
+ export { clearTraceDestinations, getTraceDestination, isJsonlTraceDestination, isTraceSink, jsonlDestination, listTraceDestinationIds, registerTraceDestination, requireTraceDestination, };
@@ -0,0 +1,67 @@
1
+ /**
2
+ * Host-registered trace destinations for profile `observability.writeTo` ids.
3
+ *
4
+ * THEORUM does not invent filesystem roots. Hosts register a named destination
5
+ * once per process; profiles reference it by id.
6
+ *
7
+ * @module
8
+ */
9
+ import { TheorumError } from '../guardrails/error.js';
10
+ const destinations = new Map();
11
+ /** Build a JSONL destination descriptor for `registerTraceDestination`. */
12
+ function jsonlDestination(dir) {
13
+ const trimmed = dir.trim();
14
+ if (!trimmed) {
15
+ throw new TheorumError('jsonlDestination requires a non-empty directory');
16
+ }
17
+ return { kind: 'jsonl', dir: trimmed };
18
+ }
19
+ function isJsonlTraceDestination(value) {
20
+ return (typeof value === 'object' &&
21
+ value !== null &&
22
+ 'kind' in value &&
23
+ value.kind === 'jsonl' &&
24
+ typeof value.dir === 'string');
25
+ }
26
+ function isTraceSink(value) {
27
+ return (typeof value === 'object' && value !== null && typeof value.write === 'function');
28
+ }
29
+ /** Register a named destination for profile `observability.writeTo`. */
30
+ function registerTraceDestination(id, destination) {
31
+ const key = id.trim();
32
+ if (!key) {
33
+ throw new TheorumError('registerTraceDestination requires a non-empty id');
34
+ }
35
+ if (isJsonlTraceDestination(destination)) {
36
+ if (!destination.dir.trim()) {
37
+ throw new TheorumError(`Trace destination '${key}' jsonl dir must be non-empty`);
38
+ }
39
+ destinations.set(key, { kind: 'jsonl', dir: destination.dir.trim() });
40
+ return;
41
+ }
42
+ if (!isTraceSink(destination)) {
43
+ throw new TheorumError(`Trace destination '${key}' must be a TraceSink or jsonl destination`);
44
+ }
45
+ destinations.set(key, destination);
46
+ }
47
+ /** Look up a registered destination; undefined when missing. */
48
+ function getTraceDestination(id) {
49
+ return destinations.get(id);
50
+ }
51
+ /** Require a registered destination or throw. */
52
+ function requireTraceDestination(id) {
53
+ const found = getTraceDestination(id);
54
+ if (!found) {
55
+ throw new TheorumError(`Trace destination '${id}' is not registered`);
56
+ }
57
+ return found;
58
+ }
59
+ /** List registered destination ids (stable sort). */
60
+ function listTraceDestinationIds() {
61
+ return [...destinations.keys()].sort();
62
+ }
63
+ /** Clear the destination registry (tests). */
64
+ function clearTraceDestinations() {
65
+ destinations.clear();
66
+ }
67
+ export { clearTraceDestinations, getTraceDestination, isJsonlTraceDestination, isTraceSink, jsonlDestination, listTraceDestinationIds, registerTraceDestination, requireTraceDestination, };
@@ -1,12 +1,19 @@
1
1
  /**
2
- * Trace sinks and trace record helpers for THEORUM.
2
+ * Trace sinks, destination registry, and profile observability policy.
3
3
  *
4
4
  * THEORUM does not own a database or environment variable. Host applications
5
- * choose a sink and pass it into `runTurn`, or use the noop sink for tests.
5
+ * register named destinations, declare `profile.observability`, and/or pass a
6
+ * sink into `runTurn`.
6
7
  *
7
8
  * @module
8
9
  */
9
10
  import "../../_dnt.polyfills.js";
10
- export type { TraceSink } from './trace.js';
11
+ export type { JsonlTraceDestination, TraceDestination, } from './destinations.js';
12
+ export { clearTraceDestinations, getTraceDestination, isJsonlTraceDestination, isTraceSink, jsonlDestination, listTraceDestinationIds, registerTraceDestination, requireTraceDestination, } from './destinations.js';
13
+ export { resolveTraceWriter } from './policy.js';
14
+ export { resolveObservabilityPolicy } from './resolve-policy.js';
15
+ export type { JsonlSinkOptions } from './trace.js';
11
16
  export { jsonlSink, memorySink, noopSink, resolveTraceDir, sinkFromDir, writeTrace, } from './trace.js';
12
17
  export type { TraceRecord } from './trace-record.js';
18
+ export type { TraceSink } from './trace-sink.js';
19
+ export type { ProfileObservabilitySpec, ResolvedObservabilityPolicy, ResolvedTraceInclude, ResolvedTraceScrub, TraceIncludeSpec, TraceScrubSpec, } from './types.js';
@@ -1,10 +1,14 @@
1
1
  /**
2
- * Trace sinks and trace record helpers for THEORUM.
2
+ * Trace sinks, destination registry, and profile observability policy.
3
3
  *
4
4
  * THEORUM does not own a database or environment variable. Host applications
5
- * choose a sink and pass it into `runTurn`, or use the noop sink for tests.
5
+ * register named destinations, declare `profile.observability`, and/or pass a
6
+ * sink into `runTurn`.
6
7
  *
7
8
  * @module
8
9
  */
9
10
  import "../../_dnt.polyfills.js";
11
+ export { clearTraceDestinations, getTraceDestination, isJsonlTraceDestination, isTraceSink, jsonlDestination, listTraceDestinationIds, registerTraceDestination, requireTraceDestination, } from './destinations.js';
12
+ export { resolveTraceWriter } from './policy.js';
13
+ export { resolveObservabilityPolicy } from './resolve-policy.js';
10
14
  export { jsonlSink, memorySink, noopSink, resolveTraceDir, sinkFromDir, writeTrace, } from './trace.js';
@@ -0,0 +1,27 @@
1
+ /**
2
+ * Trace writer resolution — a resolved observability policy becomes a sink.
3
+ *
4
+ * Policy defaults live in `resolve-policy.ts` (pure); this module owns the
5
+ * writer precedence and needs the sink implementations.
6
+ *
7
+ * @module
8
+ */
9
+ import type { TraceSink } from './trace-sink.js';
10
+ import type { ProfileObservabilitySpec, ResolvedObservabilityPolicy } from './types.js';
11
+ /**
12
+ * Resolve the TraceSink for one turn.
13
+ *
14
+ * Precedence: explicit `override` (runTurn third arg) → profile `writeTo` → noop.
15
+ * An explicit override always records (sampleRate does not apply) so tests and
16
+ * one-off capture are deterministic.
17
+ */
18
+ declare function resolveTraceWriter(args: {
19
+ override?: TraceSink;
20
+ observability?: ProfileObservabilitySpec;
21
+ /** Injectable for deterministic sampleRate tests. */
22
+ random?: () => number;
23
+ }): {
24
+ sink: TraceSink;
25
+ policy: ResolvedObservabilityPolicy;
26
+ };
27
+ export { resolveTraceWriter };
@@ -0,0 +1,80 @@
1
+ /**
2
+ * Trace writer resolution — a resolved observability policy becomes a sink.
3
+ *
4
+ * Policy defaults live in `resolve-policy.ts` (pure); this module owns the
5
+ * writer precedence and needs the sink implementations.
6
+ *
7
+ * @module
8
+ */
9
+ import { TheorumError } from '../guardrails/error.js';
10
+ import { isJsonlTraceDestination, isTraceSink, requireTraceDestination } from './destinations.js';
11
+ import { resolveObservabilityPolicy } from './resolve-policy.js';
12
+ import { jsonlSink, noopSink } from './trace.js';
13
+ function bindOnWriteError(sink, onWriteError) {
14
+ if (!onWriteError && !sink.onError) {
15
+ return sink;
16
+ }
17
+ return {
18
+ write: (record) => sink.write(record),
19
+ onError: sink.onError ?? onWriteError,
20
+ };
21
+ }
22
+ function withSampleRate(sink, sampleRate, random) {
23
+ if (sampleRate >= 1) {
24
+ return sink;
25
+ }
26
+ if (sampleRate <= 0) {
27
+ return noopSink();
28
+ }
29
+ return {
30
+ write: async (record) => {
31
+ if (random() < sampleRate) {
32
+ await sink.write(record);
33
+ }
34
+ },
35
+ onError: sink.onError,
36
+ };
37
+ }
38
+ function sinkFromWriteTo(writeTo, policy) {
39
+ if (writeTo === undefined || writeTo === false) {
40
+ return noopSink();
41
+ }
42
+ if (typeof writeTo !== 'string') {
43
+ return bindOnWriteError(writeTo, policy.onWriteError);
44
+ }
45
+ const destination = requireTraceDestination(writeTo);
46
+ if (isJsonlTraceDestination(destination)) {
47
+ return bindOnWriteError(jsonlSink(destination.dir, {
48
+ retainForDays: policy.retainForDays,
49
+ rotateAfterMiB: policy.rotateAfterMiB,
50
+ }), policy.onWriteError);
51
+ }
52
+ if (!isTraceSink(destination)) {
53
+ throw new TheorumError(`Trace destination '${writeTo}' is not a usable writer`);
54
+ }
55
+ return bindOnWriteError(destination, policy.onWriteError);
56
+ }
57
+ /**
58
+ * Resolve the TraceSink for one turn.
59
+ *
60
+ * Precedence: explicit `override` (runTurn third arg) → profile `writeTo` → noop.
61
+ * An explicit override always records (sampleRate does not apply) so tests and
62
+ * one-off capture are deterministic.
63
+ */
64
+ function resolveTraceWriter(args) {
65
+ const policy = resolveObservabilityPolicy(args.observability);
66
+ if (args.override) {
67
+ return {
68
+ policy,
69
+ sink: bindOnWriteError(args.override, policy.onWriteError),
70
+ };
71
+ }
72
+ if (!policy.record) {
73
+ return { policy, sink: noopSink() };
74
+ }
75
+ return {
76
+ policy,
77
+ sink: withSampleRate(sinkFromWriteTo(policy.writeTo, policy), policy.sampleRate, args.random ?? Math.random),
78
+ };
79
+ }
80
+ export { resolveTraceWriter };
@@ -0,0 +1,16 @@
1
+ /**
2
+ * Observability policy resolution — profile switches become resolved defaults.
3
+ *
4
+ * Pure: no sinks, no file system. `policy.ts` builds the writer on top of this
5
+ * so type consumers of the kernel never pull the JSONL sink into their graph.
6
+ *
7
+ * @module
8
+ */
9
+ import type { ProfileObservabilitySpec, ResolvedObservabilityPolicy } from './types.js';
10
+ /**
11
+ * Apply defaults to a profile's observability block.
12
+ *
13
+ * Omitted block → record false (noop). Explicit `writeTo: false` → record false.
14
+ * A writeTo target with sampleRate 0 still resolves record false at write time.
15
+ */
16
+ export declare function resolveObservabilityPolicy(spec: ProfileObservabilitySpec | undefined): ResolvedObservabilityPolicy;
@@ -0,0 +1,64 @@
1
+ /**
2
+ * Observability policy resolution — profile switches become resolved defaults.
3
+ *
4
+ * Pure: no sinks, no file system. `policy.ts` builds the writer on top of this
5
+ * so type consumers of the kernel never pull the JSONL sink into their graph.
6
+ *
7
+ * @module
8
+ */
9
+ import { TheorumError } from '../guardrails/error.js';
10
+ const DEFAULT_RETAIN_DAYS = 14;
11
+ const DEFAULT_ROTATE_MIB = 32;
12
+ function resolveInclude(spec) {
13
+ // When no observability block is authored, preserve historical buildRecord
14
+ // behavior (wire + evidence included). Authored blocks default those off.
15
+ const authored = spec !== undefined;
16
+ return {
17
+ upstreamLog: spec?.include?.upstreamLog ?? true,
18
+ outboundWire: spec?.include?.outboundWire ?? !authored,
19
+ evidenceRaw: spec?.include?.evidenceRaw ?? !authored,
20
+ usage: spec?.include?.usage ?? true,
21
+ guardrailDecisions: spec?.include?.guardrailDecisions ?? true,
22
+ guardrailMatchPreview: spec?.include?.guardrailMatchPreview ?? false,
23
+ };
24
+ }
25
+ function resolveScrub(spec) {
26
+ return {
27
+ sensitive: spec?.scrub?.sensitive ?? true,
28
+ injection: spec?.scrub?.injection ?? true,
29
+ canary: spec?.scrub?.canary ?? true,
30
+ };
31
+ }
32
+ function clampSampleRate(value) {
33
+ if (value === undefined) {
34
+ return 1;
35
+ }
36
+ if (!Number.isFinite(value)) {
37
+ throw new TheorumError('observability.sampleRate must be a finite number');
38
+ }
39
+ if (value < 0 || value > 1) {
40
+ throw new TheorumError('observability.sampleRate must be between 0 and 1 inclusive');
41
+ }
42
+ return value;
43
+ }
44
+ /**
45
+ * Apply defaults to a profile's observability block.
46
+ *
47
+ * Omitted block → record false (noop). Explicit `writeTo: false` → record false.
48
+ * A writeTo target with sampleRate 0 still resolves record false at write time.
49
+ */
50
+ export function resolveObservabilityPolicy(spec) {
51
+ const writeTo = spec?.writeTo;
52
+ const sampleRate = clampSampleRate(spec?.sampleRate);
53
+ const record = spec !== undefined && writeTo !== false && writeTo !== undefined;
54
+ return {
55
+ record,
56
+ writeTo,
57
+ sampleRate,
58
+ include: resolveInclude(spec),
59
+ scrub: resolveScrub(spec),
60
+ retainForDays: spec?.retainForDays ?? DEFAULT_RETAIN_DAYS,
61
+ rotateAfterMiB: spec?.rotateAfterMiB ?? DEFAULT_ROTATE_MIB,
62
+ onWriteError: spec?.onWriteError,
63
+ };
64
+ }
@@ -1,16 +1,20 @@
1
- import type { ResolvedGeneration, TurnRequest } from '../kernel/types.js';
1
+ import type { Protocol } from '../kernel/schema.js';
2
+ import type { ResolvedGeneration, TurnEvent, TurnRequest } from '../kernel/types.js';
2
3
  import type { TraceRecord } from './trace-record.js';
4
+ import type { ResolvedTraceInclude } from './types.js';
3
5
  declare function attachResolved(record: TraceRecord, args: {
4
6
  safe: TurnRequest;
5
7
  model?: string;
6
- bucket?: string;
8
+ keySlot?: string;
7
9
  generation?: ResolvedGeneration;
8
10
  }): void;
9
11
  declare function attachTape(record: TraceRecord, args: {
10
- gemini?: unknown;
12
+ upstream?: unknown;
11
13
  canary?: string;
12
14
  system?: string;
13
15
  generation?: ResolvedGeneration;
16
+ protocol?: Protocol;
17
+ include: ResolvedTraceInclude;
14
18
  }): Promise<void>;
15
- declare function attachUsage(record: TraceRecord, gemini: unknown, done: Record<string, unknown> | undefined): void;
19
+ declare function attachUsage(record: TraceRecord, upstream: unknown, done: Record<string, unknown> | undefined, events: TurnEvent[] | undefined, include: ResolvedTraceInclude): void;
16
20
  export { attachResolved, attachTape, attachUsage };
@@ -1,20 +1,16 @@
1
1
  import { providerCompleteRequest } from '../kernel/registry/provider-request.js';
2
- import { tapeGemini } from '../providers/gemini-tape.js';
3
- import { toInteractionsBody } from '../providers/interactions.js';
4
- import { httpStatus } from './trace-usage.js';
2
+ import { tapeUpstream } from '../providers/shared/upstream-tape.js';
3
+ import { httpStatus, openAiFinishReason, tokensFromEvents } from './trace-usage.js';
5
4
  function attachResolved(record, args) {
6
- const { safe, model, bucket, generation } = args;
5
+ const { safe, model, keySlot, generation } = args;
7
6
  if (safe.projectId) {
8
7
  record.projectId = safe.projectId;
9
8
  }
10
- if (safe.select) {
11
- record.select = safe.select;
9
+ if (safe.model) {
10
+ record.modelSelect = safe.model;
12
11
  }
13
- if (safe.thinking !== undefined) {
14
- record.thinking = safe.thinking;
15
- }
16
- if (safe.tools) {
17
- record.tools = safe.tools;
12
+ if (safe.effort) {
13
+ record.effort = safe.effort;
18
14
  }
19
15
  if (safe.metadata) {
20
16
  record.metadata = safe.metadata;
@@ -25,43 +21,68 @@ function attachResolved(record, args) {
25
21
  apiId: generation?.apiId ?? model,
26
22
  };
27
23
  }
28
- if (bucket) {
29
- record.bucket = bucket;
24
+ if (keySlot) {
25
+ record.keySlot = keySlot;
30
26
  }
31
27
  if (generation) {
32
- record.generation = {
28
+ const traceGeneration = {
33
29
  thinking: generation.thinking,
34
30
  summaries: generation.summaries,
35
31
  temperature: generation.temperature,
36
32
  maxOutputTokens: generation.maxOutputTokens,
37
33
  builtins: generation.builtins,
38
- custom: generation.custom,
34
+ visibleTools: generation.tools.visible,
39
35
  structured: generation.structured,
40
36
  image: generation.image,
41
37
  };
38
+ record.generation = traceGeneration;
42
39
  }
43
40
  }
44
41
  async function attachTape(record, args) {
45
- const { gemini, canary, system, generation } = args;
46
- if (gemini !== undefined) {
47
- record.gemini = await tapeGemini(gemini, canary ?? '');
42
+ const { upstream, canary, system, generation, protocol, include } = args;
43
+ if (include.upstreamLog && upstream !== undefined) {
44
+ record.upstreamLog = await tapeUpstream(upstream, canary ?? '');
48
45
  }
49
- if (generation && system !== undefined) {
50
- record.wire = await tapeGemini(toInteractionsBody(providerCompleteRequest(generation, system)), canary ?? '');
46
+ if (include.outboundWire &&
47
+ generation &&
48
+ system !== undefined &&
49
+ protocol === 'geminiInteractions') {
50
+ const { toInteractionsBody } = await import('../providers/google/interactions/framing.js');
51
+ record.wire = await tapeUpstream(toInteractionsBody(providerCompleteRequest(generation, system)), canary ?? '');
51
52
  }
52
53
  }
53
- function attachUsage(record, gemini, done) {
54
+ function attachUsageTokens(record, done, events) {
54
55
  if (done?.usage !== undefined) {
55
56
  record.usage = done.usage;
57
+ return;
56
58
  }
57
- const upStatus = httpStatus(gemini);
58
- if (upStatus !== undefined || done) {
59
- record.upstream = {
60
- status: upStatus,
61
- id: done?.id,
62
- finish: done?.status,
63
- serviceTier: done?.service_tier ?? done?.serviceTier,
64
- };
59
+ if (!events) {
60
+ return;
61
+ }
62
+ const tokens = tokensFromEvents(events);
63
+ if (tokens) {
64
+ record.usage = tokens;
65
+ }
66
+ }
67
+ function attachUpstreamSummary(record, upstream, done) {
68
+ const upStatus = httpStatus(upstream);
69
+ const finishReason = openAiFinishReason(upstream);
70
+ if (upStatus === undefined && !done && finishReason === undefined) {
71
+ return;
72
+ }
73
+ record.upstream = {
74
+ status: upStatus,
75
+ id: done?.id,
76
+ finish: done?.status ?? finishReason,
77
+ serviceTier: done?.service_tier ?? done?.serviceTier,
78
+ };
79
+ }
80
+ function attachUsage(record, upstream, done, events, include) {
81
+ if (include.usage) {
82
+ attachUsageTokens(record, done, events);
83
+ }
84
+ if (include.upstreamLog) {
85
+ attachUpstreamSummary(record, upstream, done);
65
86
  }
66
87
  }
67
88
  export { attachResolved, attachTape, attachUsage };
@@ -6,11 +6,16 @@
6
6
  *
7
7
  * @module
8
8
  */
9
+ import type { Protocol } from '../kernel/schema.js';
9
10
  import type { ResolvedGeneration, TurnEvent, TurnRequest } from '../kernel/types.js';
11
+ import type { ProfileObservabilitySpec, ResolvedObservabilityPolicy } from './types.js';
10
12
  /** Hash-only image reference stored in trace records. */
11
13
  export interface TraceImage {
12
14
  mimeType: string;
13
- sha256: string;
15
+ /** Content hash for inline bytes; absent for a provider file reference. */
16
+ sha256?: string;
17
+ /** Provider file reference when the attachment was supplied by uri. */
18
+ uri?: string;
14
19
  }
15
20
  /** Trace-safe copy of a public turn event. */
16
21
  export interface TraceEvent {
@@ -29,6 +34,8 @@ export interface TraceEvent {
29
34
  media?: TraceImage;
30
35
  grounding?: TurnEvent['grounding'];
31
36
  evidence?: TurnEvent['evidence'];
37
+ /** Guardrail decision — rule identity and offsets, never matched content. */
38
+ guardrail?: TurnEvent['guardrail'];
32
39
  error?: string;
33
40
  errorInternal?: string;
34
41
  }
@@ -45,22 +52,21 @@ interface TraceRecord {
45
52
  profile: string;
46
53
  title?: string;
47
54
  projectId?: string;
48
- select?: string;
49
- thinking?: boolean;
50
- tools?: TurnRequest['tools'];
55
+ modelSelect?: string;
56
+ effort?: string;
51
57
  metadata?: Record<string, unknown>;
52
58
  model?: {
53
59
  id: string;
54
60
  apiId: string;
55
61
  };
56
- bucket?: string;
62
+ keySlot?: string;
57
63
  generation?: {
58
- thinking: string;
59
- summaries: string;
60
- temperature: number;
61
- maxOutputTokens: number;
64
+ thinking?: string;
65
+ summaries?: string;
66
+ temperature?: number;
67
+ maxOutputTokens?: number;
62
68
  builtins: string[];
63
- custom: string[];
69
+ visibleTools: string[];
64
70
  structured: string | null;
65
71
  image: unknown;
66
72
  };
@@ -75,7 +81,8 @@ interface TraceRecord {
75
81
  };
76
82
  wire?: unknown;
77
83
  events: TraceEvent[];
78
- gemini?: unknown;
84
+ /** Raw upstream tap rows (HTTP, SSE, provider events). */
85
+ upstreamLog?: unknown;
79
86
  usage?: unknown;
80
87
  upstream?: {
81
88
  status?: unknown;
@@ -102,13 +109,16 @@ declare function buildRecord(args: {
102
109
  events: TurnEvent[];
103
110
  started: number;
104
111
  model?: string;
105
- bucket?: string;
112
+ keySlot?: string;
106
113
  thrown?: unknown;
107
- gemini?: unknown;
114
+ upstreamLog?: unknown;
108
115
  canary?: string;
109
116
  system?: string;
110
117
  generation?: ResolvedGeneration;
118
+ protocol?: Protocol;
111
119
  sanitizedReq?: TurnRequest;
120
+ /** Profile observability — omit for defaults (safe scrub, standard include). */
121
+ observability?: ProfileObservabilitySpec | ResolvedObservabilityPolicy;
112
122
  }): Promise<TraceRecord>;
113
123
  export type { TraceRecord };
114
124
  export { buildRecord };