theorum 0.1.2 → 0.1.4

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 (150) hide show
  1. package/README.md +83 -27
  2. package/deno.json +57 -0
  3. package/deno.lock +469 -0
  4. package/docs/AGENT_PROFILE_CONTRACT.md +45 -18
  5. package/docs/CLI_SPEC.md +2 -2
  6. package/docs/SECRETS.md +27 -22
  7. package/mod.ts +95 -0
  8. package/package.json +37 -29
  9. package/src/cli/commands/profile.ts +57 -0
  10. package/src/cli/commands/run.ts +66 -0
  11. package/src/cli/commands/test.ts +195 -0
  12. package/src/cli/index.ts +161 -0
  13. package/src/cli/matrix/fixtures.ts +96 -0
  14. package/src/cli/matrix/synthesizer.ts +240 -0
  15. package/src/guardrails/error.ts +142 -0
  16. package/src/guardrails/injection.ts +254 -0
  17. package/src/guardrails/mod.ts +40 -0
  18. package/src/guardrails/quota.ts +87 -0
  19. package/src/guardrails/sanitize.ts +165 -0
  20. package/src/guardrails/sensitive.ts +96 -0
  21. package/src/host/mint-trace.ts +54 -0
  22. package/src/host/mod.ts +20 -0
  23. package/src/host/reply.ts +32 -0
  24. package/src/kernel/engine/assert.ts +29 -0
  25. package/src/kernel/engine/boundary.ts +75 -0
  26. package/src/kernel/engine/delta.ts +440 -0
  27. package/src/kernel/engine/hash.ts +11 -0
  28. package/src/kernel/engine/record.ts +8 -0
  29. package/src/kernel/engine/repair.ts +56 -0
  30. package/src/kernel/engine/runner/gates.ts +338 -0
  31. package/src/kernel/engine/runner/mod.ts +135 -0
  32. package/src/kernel/engine/runner/state.ts +31 -0
  33. package/src/kernel/engine/runner/steps.ts +183 -0
  34. package/src/kernel/engine/runner/stream.ts +83 -0
  35. package/src/kernel/engine/runner/tokens.ts +47 -0
  36. package/src/kernel/engine/runner/tools.ts +266 -0
  37. package/src/kernel/engine/runner.ts +7 -0
  38. package/src/kernel/engine/tree.ts +18 -0
  39. package/src/kernel/mod.ts +39 -0
  40. package/src/kernel/registry/attachments.ts +195 -0
  41. package/src/kernel/registry/catalog.ts +181 -0
  42. package/src/kernel/registry/ingress.ts +223 -0
  43. package/src/kernel/registry/profiles.ts +165 -0
  44. package/src/kernel/registry/provider-request.ts +31 -0
  45. package/src/kernel/registry/resolve.ts +290 -0
  46. package/src/kernel/registry/schemas.ts +29 -0
  47. package/src/kernel/registry/tools.ts +45 -0
  48. package/src/kernel/registry/vault.ts +26 -0
  49. package/src/kernel/types.ts +576 -0
  50. package/{esm/src/observability/mod.js → src/observability/mod.ts} +11 -2
  51. package/src/observability/spans.ts +70 -0
  52. package/src/observability/trace-attach.ts +96 -0
  53. package/src/observability/trace-record.ts +254 -0
  54. package/src/observability/trace-usage.ts +36 -0
  55. package/src/observability/trace.ts +143 -0
  56. package/src/presets/google.ts +147 -0
  57. package/src/presets/mod.ts +24 -0
  58. package/src/providers/create-provider.ts +64 -0
  59. package/src/providers/gemini-tape.ts +59 -0
  60. package/src/providers/google-tap.ts +57 -0
  61. package/src/providers/interactions.ts +182 -0
  62. package/src/providers/keys.ts +182 -0
  63. package/src/providers/mod.ts +12 -0
  64. package/src/providers/openrouter-mod.ts +16 -0
  65. package/src/providers/openrouter-payload.ts +232 -0
  66. package/src/providers/openrouter.ts +758 -0
  67. package/src/providers/pcm.ts +37 -0
  68. package/src/providers/provider.ts +206 -0
  69. package/src/providers/speech.ts +180 -0
  70. package/src/providers/sse.ts +59 -0
  71. package/esm/_dnt.polyfills.d.ts +0 -11
  72. package/esm/_dnt.polyfills.js +0 -15
  73. package/esm/_dnt.shims.d.ts +0 -5
  74. package/esm/_dnt.shims.js +0 -61
  75. package/esm/mod.d.ts +0 -37
  76. package/esm/mod.js +0 -35
  77. package/esm/package.json +0 -3
  78. package/esm/src/guardrails/error.d.ts +0 -35
  79. package/esm/src/guardrails/error.js +0 -116
  80. package/esm/src/guardrails/injection.d.ts +0 -12
  81. package/esm/src/guardrails/injection.js +0 -220
  82. package/esm/src/guardrails/keys.d.ts +0 -12
  83. package/esm/src/guardrails/keys.js +0 -132
  84. package/esm/src/guardrails/mod.d.ts +0 -14
  85. package/esm/src/guardrails/mod.js +0 -14
  86. package/esm/src/guardrails/sanitize.d.ts +0 -22
  87. package/esm/src/guardrails/sanitize.js +0 -133
  88. package/esm/src/guardrails/sensitive.d.ts +0 -12
  89. package/esm/src/guardrails/sensitive.js +0 -88
  90. package/esm/src/kernel/engine/boundary.d.ts +0 -10
  91. package/esm/src/kernel/engine/boundary.js +0 -55
  92. package/esm/src/kernel/engine/delta.d.ts +0 -8
  93. package/esm/src/kernel/engine/delta.js +0 -362
  94. package/esm/src/kernel/engine/hash.d.ts +0 -1
  95. package/esm/src/kernel/engine/hash.js +0 -9
  96. package/esm/src/kernel/engine/record.d.ts +0 -2
  97. package/esm/src/kernel/engine/record.js +0 -7
  98. package/esm/src/kernel/engine/repair.d.ts +0 -9
  99. package/esm/src/kernel/engine/repair.js +0 -38
  100. package/esm/src/kernel/engine/runner.d.ts +0 -14
  101. package/esm/src/kernel/engine/runner.js +0 -731
  102. package/esm/src/kernel/engine/tree.d.ts +0 -2
  103. package/esm/src/kernel/engine/tree.js +0 -17
  104. package/esm/src/kernel/mod.d.ts +0 -16
  105. package/esm/src/kernel/mod.js +0 -15
  106. package/esm/src/kernel/registry/catalog.d.ts +0 -24
  107. package/esm/src/kernel/registry/catalog.js +0 -213
  108. package/esm/src/kernel/registry/profiles.d.ts +0 -36
  109. package/esm/src/kernel/registry/profiles.js +0 -111
  110. package/esm/src/kernel/registry/resolve.d.ts +0 -20
  111. package/esm/src/kernel/registry/resolve.js +0 -235
  112. package/esm/src/kernel/registry/schemas.d.ts +0 -14
  113. package/esm/src/kernel/registry/schemas.js +0 -23
  114. package/esm/src/kernel/registry/tools.d.ts +0 -12
  115. package/esm/src/kernel/registry/tools.js +0 -36
  116. package/esm/src/kernel/types.d.ts +0 -497
  117. package/esm/src/kernel/types.js +0 -10
  118. package/esm/src/observability/mod.d.ts +0 -12
  119. package/esm/src/observability/spans.d.ts +0 -16
  120. package/esm/src/observability/spans.js +0 -56
  121. package/esm/src/observability/trace-attach.d.ts +0 -16
  122. package/esm/src/observability/trace-attach.js +0 -81
  123. package/esm/src/observability/trace-record.d.ts +0 -112
  124. package/esm/src/observability/trace-record.js +0 -140
  125. package/esm/src/observability/trace-usage.d.ts +0 -3
  126. package/esm/src/observability/trace-usage.js +0 -32
  127. package/esm/src/observability/trace.d.ts +0 -23
  128. package/esm/src/observability/trace.js +0 -121
  129. package/esm/src/providers/attachments.d.ts +0 -17
  130. package/esm/src/providers/attachments.js +0 -156
  131. package/esm/src/providers/gemini-tape.d.ts +0 -3
  132. package/esm/src/providers/gemini-tape.js +0 -46
  133. package/esm/src/providers/google-tap.d.ts +0 -3
  134. package/esm/src/providers/google-tap.js +0 -48
  135. package/esm/src/providers/interactions.d.ts +0 -5
  136. package/esm/src/providers/interactions.js +0 -127
  137. package/esm/src/providers/media.d.ts +0 -5
  138. package/esm/src/providers/media.js +0 -125
  139. package/esm/src/providers/mod.d.ts +0 -15
  140. package/esm/src/providers/mod.js +0 -13
  141. package/esm/src/providers/openrouter-payload.d.ts +0 -24
  142. package/esm/src/providers/openrouter-payload.js +0 -177
  143. package/esm/src/providers/openrouter.d.ts +0 -17
  144. package/esm/src/providers/openrouter.js +0 -332
  145. package/esm/src/providers/provider.d.ts +0 -13
  146. package/esm/src/providers/provider.js +0 -123
  147. package/esm/src/providers/sse.d.ts +0 -7
  148. package/esm/src/providers/sse.js +0 -53
  149. package/esm/src/providers/tts.d.ts +0 -24
  150. package/esm/src/providers/tts.js +0 -144
package/README.md CHANGED
@@ -16,6 +16,8 @@ THEORUM is a compact TypeScript agent kernel for apps that need deterministic ag
16
16
 
17
17
  The package is intentionally **not** an agent product. It ships no app profiles, no prompts, no secrets, no database policy, no business rules, and no channel-specific UX. Those belong in the host application.
18
18
 
19
+ OpenRouter chat transport is powered by Vercel AI SDK Core under the adapter. THEORUM keeps the runner contract, guardrails, tool permissions, egress, media buffering, and trace event shape; AI SDK handles the OpenRouter request/stream/tool-call normalization layer.
20
+
19
21
  ---
20
22
 
21
23
  ## Core Principles
@@ -24,7 +26,7 @@ The package is intentionally **not** an agent product. It ships no app profiles,
24
26
  [kernel_contract]
25
27
  profiles = "Host-owned declarations for model, inputs, outputs, tools, and guardrails"
26
28
  runner = "Single deterministic execution path for one agent turn"
27
- providers = "Adapters for OpenRouter-compatible chat and Google Interactions"
29
+ providers = "createProvider routes protocol/provider; adapters stay internal"
28
30
  tools = "Profile allowlist ceiling plus per-turn dynamic declarations"
29
31
  egress = "Typed host hook for outbound disclosure checks and repair loops"
30
32
  traces = "Host-injected sinks; no environment variables or bundled destinations"
@@ -62,9 +64,9 @@ flowchart TD
62
64
  end
63
65
 
64
66
  subgraph Providers["Provider adapters"]
65
- OR["OpenRouter"]
67
+ OR["OpenRouter chat via Vercel AI SDK Core"]
66
68
  GI["Google Interactions"]
67
- TTS["OpenRouter TTS"]
69
+ Speech["Speech (Interactions or /audio/speech)"]
68
70
  end
69
71
 
70
72
  Profile --> Resolve
@@ -80,6 +82,8 @@ flowchart TD
80
82
  Runner --> TraceSink
81
83
  ```
82
84
 
85
+ Hosts bind transports with `createProvider(profile, { gemini, openRouter })`. One door; protocol/provider (and speech role) pick the adapter.
86
+
83
87
  ### Turn Lifecycle
84
88
 
85
89
  ```mermaid
@@ -147,7 +151,19 @@ const profile = defineProfile({
147
151
  model: {
148
152
  protocol: "openAi",
149
153
  provider: "openrouter",
150
- allow: ["gemini35FlashLite"],
154
+ allow: ["hostFastModel"],
155
+ config: {
156
+ hostFastModel: {
157
+ apiId: "perplexity/sonar",
158
+ openRouterId: "perplexity/sonar",
159
+ thinking: { on: "high", off: "minimal" },
160
+ thinkingLevels: ["minimal", "low", "medium", "high"],
161
+ summaries: { on: "auto", off: "none" },
162
+ maxOutputTokens: 8192,
163
+ temperature: 1,
164
+ keyBuiltins: [],
165
+ },
166
+ },
151
167
  thinking: "minimal",
152
168
  maxSteps: 1,
153
169
  },
@@ -221,7 +237,21 @@ Inbound and outbound safety are generic kernel hooks.
221
237
  ```ts
222
238
  const guardedProfile = defineProfile({
223
239
  id: "assistant.guarded",
224
- model: { allow: ["gemini35FlashLite"] },
240
+ model: {
241
+ allow: ["hostFastModel"],
242
+ config: {
243
+ hostFastModel: {
244
+ apiId: "perplexity/sonar",
245
+ openRouterId: "perplexity/sonar",
246
+ thinking: { on: "high", off: "minimal" },
247
+ thinkingLevels: ["minimal", "low", "medium", "high"],
248
+ summaries: { on: "auto", off: "none" },
249
+ maxOutputTokens: 8192,
250
+ temperature: 1,
251
+ keyBuiltins: [],
252
+ },
253
+ },
254
+ },
225
255
  guardrails: {
226
256
  egress: {
227
257
  onBlock: "reject_to_agent",
@@ -250,33 +280,32 @@ Quota is optional. If a profile omits `guardrails.quota`, the quota helper retur
250
280
 
251
281
  ## Provider Adapters
252
282
 
253
- THEORUM includes provider adapters but does not own credentials.
283
+ THEORUM includes provider adapters but does not own credentials. Bind them with one door:
254
284
 
255
285
  ```ts
256
- import { createOpenRouterProvider } from "jsr:@theorum/core/openrouter";
286
+ import { createProvider, runTurn } from "jsr:@theorum/core";
257
287
 
258
- const provider = createOpenRouterProvider({
259
- apiKey: hostSecrets.openRouterApiKey,
260
- siteName: "Your app",
261
- siteUrl: "https://example.com",
288
+ const provider = createProvider(profile, {
289
+ gemini: { vault: hostGeminiKeyVault, fetch },
290
+ openRouter: { apiKey: hostSecrets.openRouterApiKey },
262
291
  });
292
+
293
+ for await (const event of runTurn({ profile: profile.id, input: { text: "…" } }, provider)) {
294
+ // …
295
+ }
263
296
  ```
264
297
 
265
- ```ts
266
- import { createInteractionsProvider } from "jsr:@theorum/core/providers";
298
+ `createProvider` routes from `profile.model.protocol` / `provider`. Speech roles use the same call — Interactions when Google, `/audio/speech` when openAi/openrouter (same `openRouter` credentials).
267
299
 
268
- const provider = createInteractionsProvider({
269
- keys: hostGeminiKeyVault,
270
- fetch,
271
- });
272
- ```
300
+ | Profile | Transport |
301
+ | :--- | :--- |
302
+ | `geminiInteractions` + `google` | Google Interactions (chat, image, speech) |
303
+ | `openAi` + `openrouter` (chat) | OpenRouter chat completions |
304
+ | `openAi` + `openrouter` (speech role) | OpenRouter `/audio/speech` |
273
305
 
274
- Provider support is intentionally split by wire protocol:
306
+ OpenRouter uses Vercel AI SDK Core inside THEORUM's provider adapter. The adapter still emits THEORUM `TurnEvent` values and preserves raw provider evidence for citations/provenance where the normalized SDK stream does not expose enough detail.
275
307
 
276
- | Provider | Protocol | Use |
277
- | :--- | :--- | :--- |
278
- | OpenRouter | `openAi` | Chat completions, reasoning streams, tool calls, structured output, TTS gateway. |
279
- | Google Interactions | `geminiInteractions` | Native Google Interactions streaming, image response format, interaction continuity, grounding metadata. |
308
+ Advanced OpenRouter exports live under `theorum/openrouter` (`createOpenRouterProvider`, `toOpenRouterPayload`, …). Prefer `createProvider` for turns unless the host needs to wire the OpenRouter adapter directly.
280
309
 
281
310
  ---
282
311
 
@@ -285,11 +314,15 @@ Provider support is intentionally split by wire protocol:
285
314
  | Entrypoint | Purpose |
286
315
  | :--- | :--- |
287
316
  | `jsr:@theorum/core` / `theorum` | Main kernel API: profiles, schemas, runner, core types, provider constructors. |
288
- | `jsr:@theorum/core/kernel` / `theorum/kernel` | Profile, turn, event, tool, egress, provider, and schema types. |
289
- | `jsr:@theorum/core/providers` / `theorum/providers` | Provider constructors and provider utility types. |
290
- | `jsr:@theorum/core/openrouter` / `theorum/openrouter` | OpenRouter payload and streaming adapter. |
317
+ | `jsr:@theorum/core/kernel` / `theorum/kernel` | Profile/turn types, tool catalog, `requireModelSpec`, thinking clamps over host model maps. |
318
+ | `jsr:@theorum/core/providers` / `theorum/providers` | `createProvider` + Gemini vault types. |
319
+ | `jsr:@theorum/core/openrouter` / `theorum/openrouter` | Direct OpenRouter provider adapter and payload helpers (advanced). |
291
320
  | `jsr:@theorum/core/guardrails` / `theorum/guardrails` | Sanitization, public error mapping, inbound injection/sensitive-data primitives. |
292
321
  | `jsr:@theorum/core/observability` / `theorum/observability` | Trace sinks and trace record helpers. |
322
+ | `jsr:@theorum/core/host` / `theorum/host` | Optional Deno HTTP helpers (`json`, status mapping, cutout mint flush). |
323
+ | `jsr:@theorum/core/cli` / `theorum/cli` | Profile inspection and stress-test CLI (`theorum` binary on npm). |
324
+ | `jsr:@theorum/core/presets` / `theorum/presets` | Optional convenience packs (`registerGooglePreset`, …). |
325
+ | `jsr:@theorum/core/presets/google` / `theorum/presets/google` | Google builtins (search/maps/urlContext) + Interactions/OpenRouter wire metadata. |
293
326
 
294
327
  Internal files remain present in source for maintainability, but package consumers should use the public entrypoints above.
295
328
 
@@ -304,7 +337,15 @@ npm run lint
304
337
  deno publish --dry-run --allow-dirty
305
338
  ```
306
339
 
307
- Build the npm package from the Deno source:
340
+ Run the packaged CLI locally:
341
+
342
+ ```bash
343
+ deno task theorum --help
344
+ # or after npm install -g / npx:
345
+ # npx theorum --help
346
+ ```
347
+
348
+ Build the npm package from the Deno source (publish only from `npm/`):
308
349
 
309
350
  ```bash
310
351
  npm run build:npm
@@ -312,6 +353,21 @@ cd npm
312
353
  npm pack
313
354
  ```
314
355
 
356
+ Run a live OpenRouter smoke test with a host-resolved key. The key is passed as an argument and is never read from a Theorum `.env` file.
357
+
358
+ ```bash
359
+ deno run --allow-net scripts/verify-live.ts --api-key "$OPENROUTER_API_KEY"
360
+ ```
361
+
362
+ The default live verifier uses `perplexity/sonar` because it is broadly available on OpenRouter. Hosts can override both the profile-facing model id and provider-native id:
363
+
364
+ ```bash
365
+ deno run --allow-net scripts/verify-live.ts \
366
+ --api-key "$OPENROUTER_API_KEY" \
367
+ --model hostFastModel \
368
+ --api-id perplexity/sonar
369
+ ```
370
+
315
371
  ---
316
372
 
317
373
  ## Package Boundary
package/deno.json ADDED
@@ -0,0 +1,57 @@
1
+ {
2
+ "name": "@theorum/core",
3
+ "version": "0.1.4",
4
+ "description": "A flat TypeScript agent kernel for typed profiles, deterministic turn execution, dynamic tools, provider adapters, guardrails, and host-injected traces.",
5
+ "license": "MIT",
6
+ "keywords": [
7
+ "agent",
8
+ "ai",
9
+ "kernel",
10
+ "llm",
11
+ "typescript",
12
+ "deno",
13
+ "node",
14
+ "openrouter",
15
+ "gemini"
16
+ ],
17
+ "exports": {
18
+ ".": "./mod.ts",
19
+ "./kernel": "./src/kernel/mod.ts",
20
+ "./providers": "./src/providers/mod.ts",
21
+ "./openrouter": "./src/providers/openrouter-mod.ts",
22
+ "./guardrails": "./src/guardrails/mod.ts",
23
+ "./observability": "./src/observability/mod.ts",
24
+ "./host": "./src/host/mod.ts",
25
+ "./cli": "./src/cli/index.ts",
26
+ "./presets": "./src/presets/mod.ts",
27
+ "./presets/google": "./src/presets/google.ts"
28
+ },
29
+ "publish": {
30
+ "exclude": [
31
+ ".fallow/",
32
+ ".fallowrc.jsonc",
33
+ ".github/",
34
+ "ast-grep-rules/",
35
+ "biome.json",
36
+ "coverage/",
37
+ "node_modules/",
38
+ "npm/",
39
+ "package-lock.json",
40
+ "scripts/",
41
+ "sgconfig.yml",
42
+ "tests/"
43
+ ]
44
+ },
45
+ "imports": {
46
+ "@openrouter/ai-sdk-provider": "npm:@openrouter/ai-sdk-provider@1.5.4",
47
+ "ai": "npm:ai@5.0.244",
48
+ "@std/assert": "jsr:@std/assert@^1.0.0"
49
+ },
50
+ "tasks": {
51
+ "theorum": "deno run --allow-read --allow-write --allow-net src/cli/index.ts",
52
+ "test": "deno test --allow-read --allow-write --allow-net tests/",
53
+ "check": "deno check mod.ts",
54
+ "lint": "npm run lint",
55
+ "verify:live": "deno run --allow-net scripts/verify-live.ts"
56
+ }
57
+ }