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.
- package/README.md +241 -98
- package/esm/mod.d.ts +57 -28
- package/esm/mod.js +43 -23
- package/esm/src/cli/commands/bench.js +18 -18
- package/esm/src/cli/commands/fuzz-canary.d.ts +13 -0
- package/esm/src/cli/commands/fuzz-canary.js +191 -0
- package/esm/src/cli/commands/fuzz-guardrails.d.ts +3 -5
- package/esm/src/cli/commands/fuzz-guardrails.js +4 -581
- package/esm/src/cli/commands/guardrails-eval.d.ts +14 -0
- package/esm/src/cli/commands/guardrails-eval.js +15 -0
- package/esm/src/cli/commands/profile.js +35 -15
- package/esm/src/cli/commands/run.d.ts +3 -0
- package/esm/src/cli/commands/run.js +23 -32
- package/esm/src/cli/commands/test.d.ts +10 -1
- package/esm/src/cli/commands/test.js +34 -34
- package/esm/src/cli/event-log.d.ts +19 -0
- package/esm/src/cli/event-log.js +147 -0
- package/esm/src/cli/index.js +57 -11
- package/esm/src/cli/matrix/synthesizer.d.ts +10 -12
- package/esm/src/cli/matrix/synthesizer.js +45 -118
- package/esm/src/guardrails/canary-gate.d.ts +21 -0
- package/esm/src/guardrails/canary-gate.js +32 -0
- package/esm/src/guardrails/canary.d.ts +34 -0
- package/esm/src/guardrails/canary.js +150 -0
- package/esm/src/guardrails/corpus/canary-egress-attacks.d.ts +17 -0
- package/esm/src/guardrails/corpus/canary-egress-attacks.js +151 -0
- package/esm/src/guardrails/corpus/fuzz-inbound.d.ts +11 -0
- package/esm/src/guardrails/corpus/fuzz-inbound.js +213 -0
- package/esm/src/guardrails/corpus/inbound-payloads.d.ts +10 -0
- package/esm/src/guardrails/corpus/inbound-payloads.js +125 -0
- package/esm/src/guardrails/corpus/live-attacks.d.ts +20 -0
- package/esm/src/guardrails/corpus/live-attacks.js +231 -0
- package/esm/src/guardrails/corpus/mod.d.ts +14 -0
- package/esm/src/guardrails/corpus/mod.js +11 -0
- package/esm/src/guardrails/corpus/secrets.d.ts +17 -0
- package/esm/src/guardrails/corpus/secrets.js +17 -0
- package/esm/src/guardrails/corpus/strings.d.ts +28 -0
- package/esm/src/guardrails/corpus/strings.js +34 -0
- package/esm/src/guardrails/corpus/types.d.ts +38 -0
- package/esm/src/guardrails/corpus/types.js +6 -0
- package/esm/src/guardrails/egress.d.ts +32 -0
- package/esm/src/guardrails/egress.js +87 -0
- package/esm/src/guardrails/error.d.ts +14 -23
- package/esm/src/guardrails/error.js +87 -76
- package/esm/src/guardrails/eval/corpus.d.ts +108 -0
- package/esm/src/guardrails/eval/corpus.js +978 -0
- package/esm/src/guardrails/eval/mod.d.ts +51 -0
- package/esm/src/guardrails/eval/mod.js +133 -0
- package/esm/src/guardrails/eval/score.d.ts +66 -0
- package/esm/src/guardrails/eval/score.js +114 -0
- package/esm/src/guardrails/events.d.ts +25 -0
- package/esm/src/guardrails/events.js +56 -0
- package/esm/src/guardrails/hits.d.ts +24 -0
- package/esm/src/guardrails/hits.js +45 -0
- package/esm/src/guardrails/injection.js +28 -5
- package/esm/src/guardrails/lexicon.d.ts +39 -0
- package/esm/src/guardrails/lexicon.js +200 -0
- package/esm/src/guardrails/live-outbound-gate.d.ts +41 -0
- package/esm/src/guardrails/live-outbound-gate.js +222 -0
- package/esm/src/guardrails/mod.d.ts +30 -6
- package/esm/src/guardrails/mod.js +20 -5
- package/esm/src/guardrails/network.d.ts +19 -0
- package/esm/src/guardrails/network.js +234 -0
- package/esm/src/guardrails/policy.d.ts +35 -0
- package/esm/src/guardrails/policy.js +50 -0
- package/esm/src/guardrails/progressive-yield.d.ts +51 -0
- package/esm/src/guardrails/progressive-yield.js +98 -0
- package/esm/src/guardrails/quota.d.ts +17 -3
- package/esm/src/guardrails/quota.js +18 -4
- package/esm/src/guardrails/sanitize.d.ts +45 -19
- package/esm/src/guardrails/sanitize.js +177 -94
- package/esm/src/guardrails/sensitive.js +2 -1
- package/esm/src/guardrails/serialize.d.ts +35 -0
- package/esm/src/guardrails/serialize.js +58 -0
- package/esm/src/guardrails/testing.d.ts +17 -0
- package/esm/src/guardrails/testing.js +13 -0
- package/esm/src/guardrails/theorum-error.d.ts +12 -0
- package/esm/src/guardrails/theorum-error.js +15 -0
- package/esm/src/guardrails/tool-directives.d.ts +48 -0
- package/esm/src/guardrails/tool-directives.js +124 -0
- package/esm/src/guardrails/tool-result.d.ts +93 -0
- package/esm/src/guardrails/tool-result.js +276 -0
- package/esm/src/guardrails/types.d.ts +291 -0
- package/esm/src/guardrails/types.js +72 -0
- package/esm/src/host/client-turn.d.ts +19 -0
- package/esm/src/host/client-turn.js +36 -0
- package/esm/src/host/mint-trace.d.ts +1 -1
- package/esm/src/host/mod.d.ts +5 -3
- package/esm/src/host/mod.js +4 -3
- package/esm/src/kernel/auth/crypto.d.ts +42 -0
- package/esm/src/kernel/auth/crypto.js +106 -0
- package/esm/src/kernel/auth/mod.d.ts +11 -0
- package/esm/src/kernel/auth/mod.js +11 -0
- package/esm/src/kernel/auth/oauth.d.ts +47 -0
- package/esm/src/kernel/auth/oauth.js +278 -0
- package/esm/src/kernel/auth/types.d.ts +133 -0
- package/esm/src/kernel/auth/types.js +13 -0
- package/esm/src/kernel/engine/delta.d.ts +24 -2
- package/esm/src/kernel/engine/delta.js +478 -39
- package/esm/src/kernel/engine/live-inbound.d.ts +21 -0
- package/esm/src/kernel/engine/live-inbound.js +31 -0
- package/esm/src/kernel/engine/live-ingress.d.ts +19 -0
- package/esm/src/kernel/engine/live-ingress.js +47 -0
- package/esm/src/kernel/engine/repair.js +13 -12
- package/esm/src/kernel/engine/runner/gates.d.ts +1 -1
- package/esm/src/kernel/engine/runner/gates.js +130 -43
- package/esm/src/kernel/engine/runner/mod.d.ts +6 -4
- package/esm/src/kernel/engine/runner/mod.js +192 -53
- package/esm/src/kernel/engine/runner/schema-validation.js +3 -3
- package/esm/src/kernel/engine/runner/stages.d.ts +39 -0
- package/esm/src/kernel/engine/runner/stages.js +89 -0
- package/esm/src/kernel/engine/runner/state.d.ts +31 -0
- package/esm/src/kernel/engine/runner/steps.d.ts +1 -1
- package/esm/src/kernel/engine/runner/steps.js +244 -43
- package/esm/src/kernel/engine/runner/stream.d.ts +9 -3
- package/esm/src/kernel/engine/runner/stream.js +140 -44
- package/esm/src/kernel/engine/session/mod.d.ts +25 -0
- package/esm/src/kernel/engine/session/mod.js +557 -0
- package/esm/src/kernel/interaction-parts.d.ts +14 -0
- package/esm/src/kernel/interaction-parts.js +23 -0
- package/esm/src/kernel/mod.d.ts +21 -10
- package/esm/src/kernel/mod.js +11 -8
- package/esm/src/kernel/profile-graph.d.ts +159 -0
- package/esm/src/kernel/profile-graph.js +156 -0
- package/esm/src/kernel/registry/attachments.d.ts +12 -10
- package/esm/src/kernel/registry/attachments.js +33 -27
- package/esm/src/kernel/registry/catalog.d.ts +25 -24
- package/esm/src/kernel/registry/catalog.js +60 -101
- package/esm/src/kernel/registry/ingress.d.ts +9 -4
- package/esm/src/kernel/registry/ingress.js +97 -75
- package/esm/src/kernel/registry/profile-outputs.d.ts +4 -0
- package/esm/src/kernel/registry/profile-outputs.js +8 -0
- package/esm/src/kernel/registry/profiles.d.ts +55 -12
- package/esm/src/kernel/registry/profiles.js +413 -73
- package/esm/src/kernel/registry/provider-request.js +13 -7
- package/esm/src/kernel/registry/resolve.d.ts +8 -8
- package/esm/src/kernel/registry/resolve.js +169 -154
- package/esm/src/kernel/registry/schemas.js +1 -1
- package/esm/src/kernel/registry/sole-model.d.ts +8 -0
- package/esm/src/kernel/registry/sole-model.js +10 -0
- package/esm/src/kernel/registry/system-prompt.d.ts +10 -0
- package/esm/src/kernel/registry/system-prompt.js +40 -0
- package/esm/src/kernel/registry/system-role.d.ts +8 -0
- package/esm/src/kernel/registry/system-role.js +14 -0
- package/esm/src/kernel/registry/vault.d.ts +12 -7
- package/esm/src/kernel/registry/vault.js +32 -10
- package/esm/src/kernel/schema.d.ts +231 -0
- package/esm/src/kernel/schema.js +607 -0
- package/esm/src/kernel/stages.d.ts +175 -0
- package/esm/src/kernel/stages.js +476 -0
- package/esm/src/kernel/stop.d.ts +78 -19
- package/esm/src/kernel/stop.js +51 -16
- package/esm/src/kernel/tools/events.d.ts +41 -0
- package/esm/src/kernel/tools/events.js +71 -0
- package/esm/src/kernel/tools/execute.d.ts +84 -0
- package/esm/src/kernel/tools/execute.js +614 -0
- package/esm/src/kernel/tools/harness.d.ts +8 -0
- package/esm/src/kernel/tools/harness.js +46 -0
- package/esm/src/kernel/tools/invoke.d.ts +10 -0
- package/esm/src/kernel/tools/invoke.js +101 -0
- package/esm/src/kernel/tools/mod.d.ts +13 -0
- package/esm/src/kernel/tools/mod.js +11 -0
- package/esm/src/kernel/tools/permission.d.ts +15 -0
- package/esm/src/kernel/tools/permission.js +47 -0
- package/esm/src/kernel/tools/project.d.ts +12 -0
- package/esm/src/kernel/tools/project.js +36 -0
- package/esm/src/kernel/tools/registry.d.ts +23 -0
- package/esm/src/kernel/tools/registry.js +81 -0
- package/esm/src/kernel/tools/remote.d.ts +94 -0
- package/esm/src/kernel/tools/remote.js +577 -0
- package/esm/src/kernel/tools/resolve.d.ts +39 -0
- package/esm/src/kernel/tools/resolve.js +283 -0
- package/esm/src/kernel/tools/schema.d.ts +15 -0
- package/esm/src/kernel/tools/schema.js +176 -0
- package/esm/src/kernel/tools/stage-run.d.ts +105 -0
- package/esm/src/kernel/tools/stage-run.js +155 -0
- package/esm/src/kernel/tools/types.d.ts +394 -0
- package/esm/src/kernel/tools/types.js +9 -0
- package/esm/src/kernel/types.d.ts +540 -256
- package/esm/src/kernel/util/find-last.d.ts +2 -0
- package/esm/src/kernel/util/find-last.js +10 -0
- package/esm/src/observability/destinations.d.ts +31 -0
- package/esm/src/observability/destinations.js +67 -0
- package/esm/src/observability/mod.d.ts +10 -3
- package/esm/src/observability/mod.js +6 -2
- package/esm/src/observability/policy.d.ts +27 -0
- package/esm/src/observability/policy.js +80 -0
- package/esm/src/observability/resolve-policy.d.ts +16 -0
- package/esm/src/observability/resolve-policy.js +64 -0
- package/esm/src/observability/trace-attach.d.ts +8 -4
- package/esm/src/observability/trace-attach.js +50 -29
- package/esm/src/observability/trace-record.d.ts +23 -13
- package/esm/src/observability/trace-record.js +96 -39
- package/esm/src/observability/trace-sink.d.ts +19 -0
- package/esm/src/observability/trace-sink.js +10 -0
- package/esm/src/observability/trace-usage.d.ts +10 -3
- package/esm/src/observability/trace-usage.js +70 -17
- package/esm/src/observability/trace.d.ts +18 -7
- package/esm/src/observability/trace.js +34 -17
- package/esm/src/observability/types.d.ts +113 -0
- package/esm/src/observability/types.js +11 -0
- package/esm/src/presets/google/speech-voices.d.ts +11 -0
- package/esm/src/presets/google/speech-voices.js +41 -0
- package/esm/src/presets/google.d.ts +36 -24
- package/esm/src/presets/google.js +50 -63
- package/esm/src/presets/mod.d.ts +2 -2
- package/esm/src/presets/mod.js +1 -1
- package/esm/src/providers/create-provider.d.ts +20 -17
- package/esm/src/providers/create-provider.js +72 -26
- package/esm/src/providers/google/interactions/framing.d.ts +23 -0
- package/esm/src/providers/google/interactions/framing.js +269 -0
- package/esm/src/providers/google/interactions/mod.d.ts +7 -0
- package/esm/src/providers/google/interactions/mod.js +7 -0
- package/esm/src/providers/google/interactions/stream.d.ts +83 -0
- package/esm/src/providers/google/interactions/stream.js +588 -0
- package/esm/src/providers/google/keys.d.ts +26 -0
- package/esm/src/providers/{keys.js → google/keys.js} +19 -31
- package/esm/src/providers/google/live/framing.d.ts +49 -0
- package/esm/src/providers/google/live/framing.js +552 -0
- package/esm/src/providers/google/live/openapi-schema.d.ts +6 -0
- package/esm/src/providers/google/live/openapi-schema.js +46 -0
- package/esm/src/providers/google/live/session.d.ts +25 -0
- package/esm/src/providers/google/live/session.js +134 -0
- package/esm/src/providers/google/live/stream.d.ts +45 -0
- package/esm/src/providers/google/live/stream.js +214 -0
- package/esm/src/providers/google/urls.d.ts +6 -0
- package/esm/src/providers/google/urls.js +6 -0
- package/esm/src/providers/local/local.d.ts +30 -0
- package/esm/src/providers/{local.js → local/local.js} +66 -126
- package/esm/src/providers/local/mod.d.ts +9 -0
- package/esm/src/providers/local/mod.js +9 -0
- package/esm/src/providers/mod.d.ts +6 -3
- package/esm/src/providers/mod.js +3 -1
- package/esm/src/providers/openrouter/cache-control.d.ts +24 -0
- package/esm/src/providers/openrouter/cache-control.js +23 -0
- package/esm/src/providers/openrouter/chat.d.ts +107 -0
- package/esm/src/providers/{openrouter.js → openrouter/chat.js} +117 -231
- package/esm/src/providers/openrouter/image.d.ts +34 -0
- package/esm/src/providers/openrouter/image.js +275 -0
- package/esm/src/providers/openrouter/openai/chat-payload.d.ts +24 -0
- package/esm/src/providers/openrouter/openai/chat-payload.js +82 -0
- package/esm/src/providers/openrouter/openai/compat.d.ts +53 -0
- package/esm/src/providers/openrouter/openai/compat.js +213 -0
- package/esm/src/providers/openrouter/openai/image-payload.d.ts +18 -0
- package/esm/src/providers/openrouter/openai/image-payload.js +90 -0
- package/esm/src/providers/openrouter/openai/sdk-messages.d.ts +22 -0
- package/esm/src/providers/openrouter/openai/sdk-messages.js +122 -0
- package/esm/src/providers/openrouter/resolve-api-key.d.ts +9 -0
- package/esm/src/providers/openrouter/resolve-api-key.js +24 -0
- package/esm/src/providers/openrouter/speech.d.ts +23 -0
- package/esm/src/providers/{speech.js → openrouter/speech.js} +32 -55
- package/esm/src/providers/probe.d.ts +1 -0
- package/esm/src/providers/probe.js +22 -0
- package/esm/src/providers/shared/pcm.d.ts +12 -0
- package/esm/src/providers/{pcm.js → shared/pcm.js} +16 -3
- package/esm/src/providers/shared/sse.d.ts +18 -0
- package/esm/src/providers/shared/sse.js +87 -0
- package/esm/src/providers/shared/tool-args.d.ts +17 -0
- package/esm/src/providers/shared/tool-args.js +45 -0
- package/esm/src/providers/shared/upstream-tap.d.ts +5 -0
- package/esm/src/providers/{google-tap.js → shared/upstream-tap.js} +4 -7
- package/esm/src/providers/shared/upstream-tape.d.ts +6 -0
- package/esm/src/providers/{gemini-tape.js → shared/upstream-tape.js} +12 -22
- package/esm/src/providers/types.d.ts +27 -0
- package/esm/src/providers/types.js +1 -0
- package/package.json +11 -7
- package/docs/cli.md +0 -97
- package/docs/guardrails.md +0 -178
- package/docs/host.md +0 -97
- package/docs/kernel.md +0 -404
- package/docs/observability.md +0 -105
- package/docs/openrouter.md +0 -125
- package/docs/presets-google.md +0 -91
- package/docs/presets.md +0 -88
- package/docs/providers.md +0 -202
- package/docs/streaming.md +0 -96
- package/esm/src/kernel/engine/boundary.d.ts +0 -10
- package/esm/src/kernel/engine/boundary.js +0 -55
- package/esm/src/kernel/engine/runner/tools.d.ts +0 -13
- package/esm/src/kernel/engine/runner/tools.js +0 -198
- package/esm/src/kernel/registry/tools.d.ts +0 -12
- package/esm/src/kernel/registry/tools.js +0 -36
- package/esm/src/providers/expose-for-tests.d.ts +0 -1
- package/esm/src/providers/expose-for-tests.js +0 -25
- package/esm/src/providers/gemini-tape.d.ts +0 -2
- package/esm/src/providers/google-tap.d.ts +0 -3
- package/esm/src/providers/interactions.d.ts +0 -5
- package/esm/src/providers/interactions.js +0 -169
- package/esm/src/providers/keys.d.ts +0 -19
- package/esm/src/providers/local.d.ts +0 -29
- package/esm/src/providers/openrouter-mod.d.ts +0 -13
- package/esm/src/providers/openrouter-mod.js +0 -12
- package/esm/src/providers/openrouter-payload.d.ts +0 -39
- package/esm/src/providers/openrouter-payload.js +0 -195
- package/esm/src/providers/openrouter.d.ts +0 -15
- package/esm/src/providers/pcm.d.ts +0 -7
- package/esm/src/providers/provider.d.ts +0 -15
- package/esm/src/providers/provider.js +0 -202
- package/esm/src/providers/speech.d.ts +0 -23
- package/esm/src/providers/sse.d.ts +0 -7
- package/esm/src/providers/sse.js +0 -55
- package/esm/src/streaming/mod.d.ts +0 -9
- package/esm/src/streaming/mod.js +0 -8
- /package/esm/src/{streaming → host}/readStreamingJsonStringField.d.ts +0 -0
- /package/esm/src/{streaming → host}/readStreamingJsonStringField.js +0 -0
package/README.md
CHANGED
|
@@ -10,11 +10,18 @@
|
|
|
10
10
|
|
|
11
11
|
# THEORUM: The Flat Agent Kernel
|
|
12
12
|
|
|
13
|
-
**Current release: `
|
|
13
|
+
**Current release: `1.1.3`** (`jsr:@theorum/core` / npm `theorum`).
|
|
14
|
+
|
|
15
|
+
> ⚠️ **Package Migration Notice:**
|
|
16
|
+
> Starting with version 2.0, the package and scope are officially rebranded from `theorum` / `@theorum/core` to **`@theoremai/agents`** on both **npm** and **JSR**.
|
|
17
|
+
> - **npm**: `npm install @theoremai/agents` (deprecating `theorum`)
|
|
18
|
+
> - **JSR**: `deno add jsr:@theoremai/agents` (deprecating `jsr:@theorum/core`)
|
|
19
|
+
>
|
|
20
|
+
> All legacy `theorum` / `jsr:@theorum/core` v1.x releases are deprecated in favor of `@theoremai/agents`.
|
|
14
21
|
|
|
15
22
|
> **"Profiles describe the contract. Providers move bytes. The runner enforces the turn."**
|
|
16
23
|
|
|
17
|
-
THEORUM is a compact TypeScript agent kernel for apps that need deterministic agent execution without embedding product logic inside the runtime. It gives a host application one runner, typed profiles, multimodal input normalization,
|
|
24
|
+
THEORUM is a compact TypeScript agent kernel for apps that need deterministic agent execution without embedding product logic inside the runtime. It gives a host application one runner, typed profiles, multimodal input normalization, a registered tool system with per-turn gating, provider adapters, trace sinks, and guardrail hooks.
|
|
18
25
|
|
|
19
26
|
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.
|
|
20
27
|
|
|
@@ -29,9 +36,9 @@ OpenRouter chat transport is powered by Vercel AI SDK Core under the adapter. TH
|
|
|
29
36
|
profiles = "Host-owned declarations for model, inputs, outputs, tools, and guardrails"
|
|
30
37
|
runner = "Single deterministic execution path for one agent turn"
|
|
31
38
|
providers = "createProvider routes protocol/provider; adapters stay internal"
|
|
32
|
-
tools = "Profile allowlist ceiling plus per-turn
|
|
39
|
+
tools = "Profile allowlist ceiling plus per-turn opt-in gates"
|
|
33
40
|
egress = "Typed host hook for outbound disclosure checks and repair loops"
|
|
34
|
-
traces = "
|
|
41
|
+
traces = "Profile observability + host-registered destinations; no env vars or bundled DB"
|
|
35
42
|
|
|
36
43
|
[non_goals]
|
|
37
44
|
app_profiles = "No bundled assistants, demos, product personas, or business tasks"
|
|
@@ -40,6 +47,10 @@ realtime_voice = "Not included yet; persistent duplex sessions stay host-owned"
|
|
|
40
47
|
product_copy = "No channel wording, refusal copy, iMessage/Alexa/Web policy, or UX defaults"
|
|
41
48
|
```
|
|
42
49
|
|
|
50
|
+
React UI and the headless interface projection remain repo-private under [`react/`](./react/)
|
|
51
|
+
and `src/interface/` while their public contracts are being designed. They are excluded from
|
|
52
|
+
the JSR and npm packages.
|
|
53
|
+
|
|
43
54
|
---
|
|
44
55
|
|
|
45
56
|
## Architecture
|
|
@@ -61,7 +72,7 @@ flowchart TD
|
|
|
61
72
|
Resolve["resolveTurn"]
|
|
62
73
|
Guard["sanitize + canary + egress"]
|
|
63
74
|
Runner["runTurn"]
|
|
64
|
-
ToolLoop["
|
|
75
|
+
ToolLoop["registered tool loop"]
|
|
65
76
|
Repair["repair attempts"]
|
|
66
77
|
end
|
|
67
78
|
|
|
@@ -84,27 +95,66 @@ flowchart TD
|
|
|
84
95
|
Runner --> TraceSink
|
|
85
96
|
```
|
|
86
97
|
|
|
87
|
-
Hosts bind transports with `createProvider(profile, { gemini,
|
|
98
|
+
Hosts bind transports with `createProvider(profile, { gemini, openAiGateway })`. One door; protocol/provider (and speech role) pick the adapter.
|
|
88
99
|
|
|
89
|
-
### Turn
|
|
100
|
+
### Turn execution and tools
|
|
101
|
+
|
|
102
|
+
One turn is a single pipeline. Tools share `executeRegisteredTool` with `invokeTool`; compaction,
|
|
103
|
+
guardrails, and streaming attach at different layers.
|
|
90
104
|
|
|
91
105
|
```mermaid
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
+
flowchart TD
|
|
107
|
+
subgraph Host["Host application"]
|
|
108
|
+
REG["registerTool at startup"]
|
|
109
|
+
REQ["TurnRequest<br/>(tools gate · continueFrom · …)"]
|
|
110
|
+
UI["Pause UI"]
|
|
111
|
+
INV["invokeTool(resume)"]
|
|
112
|
+
end
|
|
113
|
+
|
|
114
|
+
subgraph Ingress["runTurn ingress"]
|
|
115
|
+
SAN["sanitizeTurnRequest"]
|
|
116
|
+
RES["resolveTurn → TurnToolSnapshot"]
|
|
117
|
+
CB{"timing: before<br/>compact history?"}
|
|
118
|
+
SYS["system + canary<br/>(+ CONTINUE_INSTRUCTION if continueFrom)"]
|
|
119
|
+
end
|
|
120
|
+
|
|
121
|
+
subgraph Attempt["Attempt (egress / validation retries)"]
|
|
122
|
+
subgraph Steps["maxSteps loop"]
|
|
123
|
+
PL["provider.complete<br/>(wire schemas + history)"]
|
|
124
|
+
TE["executeRegisteredTool"]
|
|
125
|
+
HK["formatToolResult → history<br/>or Interactions continuation"]
|
|
126
|
+
end
|
|
127
|
+
EG["egress + validation<br/>(assistant text in attempt)"]
|
|
128
|
+
end
|
|
129
|
+
|
|
130
|
+
OUT["done<br/>(stop · tokens · compaction signal?)"]
|
|
131
|
+
TR["trace record"]
|
|
132
|
+
|
|
133
|
+
REG -.-> TE
|
|
134
|
+
REQ --> SAN --> RES --> CB --> SYS --> Steps
|
|
135
|
+
PL -->|model tool calls| TE
|
|
136
|
+
TE -->|complete| HK --> PL
|
|
137
|
+
TE -->|pause · exit step loop| EG
|
|
138
|
+
UI --> INV --> TE
|
|
139
|
+
Steps -->|loop ends| EG
|
|
140
|
+
EG -->|repair retry| SAN
|
|
141
|
+
EG --> OUT --> TR
|
|
142
|
+
|
|
143
|
+
INV -.->|separate entry · no provider| TE
|
|
106
144
|
```
|
|
107
145
|
|
|
146
|
+
**How the verticals meet tools:**
|
|
147
|
+
|
|
148
|
+
| Vertical | Where it runs | Tool interaction |
|
|
149
|
+
| --- | --- | --- |
|
|
150
|
+
| **Compaction** | Before turn (`timing: 'before'`) or signal on `done` (`timing: 'after'`) | Summarizes `TurnHistoryMessage` history — including `tool_calls` and `role: 'tool'` rows — not the live registry or mid-turn wire snapshot |
|
|
151
|
+
| **Guardrails** | Ingress sanitize; egress/validation after the step loop | Sanitizes user text and history content; tool catalog descriptions and model-emitted arguments are host/registration concerns. Egress inspects assistant **text** in the attempt, not tool progress events |
|
|
152
|
+
| **Streaming** | Provider stream + tool handler generators | Provider tool-call events buffer until execution; handler `progress` / `trace` / `artifact` / `warning` phases stream during `executeRegisteredTool`. `streamThoughts: false` filters thoughts only |
|
|
153
|
+
| **Resumption** | Two paths — do not mix | **`stop.kind: 'tool'`** → host UI → `invokeTool` with `resume` (skips turn gate). **`length` / `stream_incomplete` / …** → new `runTurn` with `continueFrom` (+ `CONTINUE_INSTRUCTION` in system); host must re-gate tools |
|
|
154
|
+
|
|
155
|
+
On tool pause the `maxSteps` loop exits (`stop.kind: 'tool'`), egress may still evaluate
|
|
156
|
+
buffered assistant text from that attempt, then the turn emits terminal `done`.
|
|
157
|
+
|
|
108
158
|
---
|
|
109
159
|
|
|
110
160
|
## Install
|
|
@@ -145,6 +195,7 @@ import {
|
|
|
145
195
|
} from "jsr:@theorum/core";
|
|
146
196
|
|
|
147
197
|
const profile = defineProfile({
|
|
198
|
+
type: "text",
|
|
148
199
|
id: "assistant.basic",
|
|
149
200
|
identity: {
|
|
150
201
|
handle: "assistant",
|
|
@@ -157,18 +208,19 @@ const profile = defineProfile({
|
|
|
157
208
|
config: {
|
|
158
209
|
hostFastModel: {
|
|
159
210
|
apiId: "perplexity/sonar",
|
|
160
|
-
openRouterId: "perplexity/sonar",
|
|
161
211
|
thinking: { on: "high", off: "minimal" },
|
|
162
212
|
thinkingLevels: ["minimal", "low", "medium", "high"],
|
|
163
213
|
summaries: { on: "auto", off: "none" },
|
|
164
214
|
maxOutputTokens: 8192,
|
|
165
215
|
temperature: 1,
|
|
166
|
-
|
|
216
|
+
builtInTools: [],
|
|
167
217
|
},
|
|
168
218
|
},
|
|
169
219
|
thinking: "minimal",
|
|
170
220
|
maxSteps: 1,
|
|
171
221
|
},
|
|
222
|
+
tools: { allow: [] },
|
|
223
|
+
inputs: { text: true },
|
|
172
224
|
outputs: {
|
|
173
225
|
streaming: { streamThoughts: false },
|
|
174
226
|
},
|
|
@@ -197,38 +249,52 @@ for await (const event of runTurn(
|
|
|
197
249
|
|
|
198
250
|
---
|
|
199
251
|
|
|
200
|
-
##
|
|
252
|
+
## Registered Tools
|
|
201
253
|
|
|
202
|
-
THEORUM separates tool concerns into
|
|
254
|
+
THEORUM separates tool concerns into four layers.
|
|
203
255
|
|
|
204
256
|
| Layer | Owner | Purpose |
|
|
205
257
|
| :--- | :--- | :--- |
|
|
206
|
-
| **
|
|
207
|
-
| **
|
|
208
|
-
| **
|
|
258
|
+
| **Catalog** | Host (startup) | `registerTool` — schema, handler, access, loadTier, permission |
|
|
259
|
+
| **Allow** | Profile | Custom: `tools.allow`. Builtins: `models.*.builtInTools` |
|
|
260
|
+
| **Visibility** | Registry + profile | `loadTier` on tool; T1 via `tools.t1Policy`; T2 via `tools.t2Loader`. Live (`runSession`) wires every allowed tool at setup; `host` profiles execute every allowed tool via `invokeTool`. |
|
|
261
|
+
| **Permission** | Host app | `auto`, `session_consent`, and `always_confirm` determine whether execution pauses |
|
|
209
262
|
|
|
210
263
|
```ts
|
|
211
|
-
|
|
212
|
-
|
|
213
|
-
|
|
214
|
-
|
|
215
|
-
|
|
216
|
-
|
|
217
|
-
|
|
218
|
-
|
|
219
|
-
|
|
220
|
-
|
|
221
|
-
|
|
222
|
-
|
|
223
|
-
|
|
224
|
-
|
|
225
|
-
|
|
226
|
-
}
|
|
227
|
-
},
|
|
228
|
-
|
|
264
|
+
import { z } from 'zod';
|
|
265
|
+
import { registerTool, invokeTool, runTurn } from 'theorum';
|
|
266
|
+
|
|
267
|
+
registerTool({
|
|
268
|
+
type: 'function',
|
|
269
|
+
name: 'lookup_order',
|
|
270
|
+
description: 'Fetch order state from the host application.',
|
|
271
|
+
category: 'operations',
|
|
272
|
+
access: 'read-only',
|
|
273
|
+
paths: ['*'],
|
|
274
|
+
loadTier: 'T0',
|
|
275
|
+
permission: 'session_consent',
|
|
276
|
+
input: z.object({ orderId: z.string() }),
|
|
277
|
+
output: z.object({ finding: z.string() }),
|
|
278
|
+
handler: async (input) => ({
|
|
279
|
+
finding: `Order ${input.orderId} is in transit.`,
|
|
280
|
+
}),
|
|
281
|
+
});
|
|
282
|
+
|
|
283
|
+
// Profile allow
|
|
284
|
+
tools: { allow: ['lookup_order', 'load_tools'] }
|
|
285
|
+
|
|
286
|
+
runTurn({ profile, input: { text: '…' } }, provider);
|
|
287
|
+
|
|
288
|
+
// Gate resume (permission / confirm / auth) — ask_user completes awaiting; answer is a new user turn
|
|
289
|
+
invokeTool({ profile, name: 'risky_tool', input: {…}, resume: { granted: true }, snapshot, turnInput });
|
|
229
290
|
```
|
|
230
291
|
|
|
231
|
-
The host owns
|
|
292
|
+
The host owns handlers and authorization state. The kernel enforces the declared contract
|
|
293
|
+
via shared `executeRegisteredTool` for model tool calls and `invokeTool` for host resumes.
|
|
294
|
+
|
|
295
|
+
Function tools require **Zod** input/output schemas at registration time.
|
|
296
|
+
|
|
297
|
+
**Migration:** [`docs/MIGRATION-tool-system.md`](docs/MIGRATION-tool-system.md) (breaking changes from `dynamicTools` / `ToolEnvelope`).
|
|
232
298
|
|
|
233
299
|
---
|
|
234
300
|
|
|
@@ -238,22 +304,28 @@ Inbound and outbound safety are generic kernel hooks.
|
|
|
238
304
|
|
|
239
305
|
```ts
|
|
240
306
|
const guardedProfile = defineProfile({
|
|
307
|
+
type: "text",
|
|
241
308
|
id: "assistant.guarded",
|
|
309
|
+
identity: { handle: "guarded", system: "You are a careful assistant." },
|
|
242
310
|
model: {
|
|
311
|
+
protocol: "openAi",
|
|
312
|
+
provider: "openrouter",
|
|
243
313
|
allow: ["hostFastModel"],
|
|
244
314
|
config: {
|
|
245
315
|
hostFastModel: {
|
|
246
316
|
apiId: "perplexity/sonar",
|
|
247
|
-
openRouterId: "perplexity/sonar",
|
|
248
317
|
thinking: { on: "high", off: "minimal" },
|
|
249
318
|
thinkingLevels: ["minimal", "low", "medium", "high"],
|
|
250
319
|
summaries: { on: "auto", off: "none" },
|
|
251
320
|
maxOutputTokens: 8192,
|
|
252
321
|
temperature: 1,
|
|
253
|
-
|
|
322
|
+
builtInTools: [],
|
|
254
323
|
},
|
|
255
324
|
},
|
|
325
|
+
thinking: "minimal",
|
|
256
326
|
},
|
|
327
|
+
tools: { allow: [] },
|
|
328
|
+
inputs: { text: true },
|
|
257
329
|
guardrails: {
|
|
258
330
|
egress: {
|
|
259
331
|
onBlock: "reject_to_agent",
|
|
@@ -289,7 +361,7 @@ import { createProvider, runTurn } from "jsr:@theorum/core";
|
|
|
289
361
|
|
|
290
362
|
const provider = createProvider(profile, {
|
|
291
363
|
gemini: { vault: hostGeminiKeyVault, fetch },
|
|
292
|
-
|
|
364
|
+
openAiGateway: { apiKey: hostSecrets.openRouterApiKey },
|
|
293
365
|
// openAi + local — optional; default baseUrl http://127.0.0.1:11434
|
|
294
366
|
local: { baseUrl: hostResolvedLocalBaseUrl },
|
|
295
367
|
});
|
|
@@ -299,7 +371,7 @@ for await (const event of runTurn({ profile: profile.id, input: { text: "…" }
|
|
|
299
371
|
}
|
|
300
372
|
```
|
|
301
373
|
|
|
302
|
-
`createProvider` routes from `profile.model.protocol` / `provider`. Speech roles use the same call — Interactions when Google, `/audio/speech` when openAi/openrouter (same `
|
|
374
|
+
`createProvider` routes from `profile.model.protocol` / `provider`. Speech roles use the same call — Interactions when Google, `/audio/speech` when openAi/openrouter (same `openAiGateway` credentials).
|
|
303
375
|
|
|
304
376
|
| Profile | Transport |
|
|
305
377
|
| :--- | :--- |
|
|
@@ -310,17 +382,14 @@ for await (const event of runTurn({ profile: profile.id, input: { text: "…" }
|
|
|
310
382
|
|
|
311
383
|
Local adapters take an optional `baseUrl` (default `http://127.0.0.1:11434`). THEORUM does not read `OLLAMA_HOST`; hosts that honor that env should resolve it and pass `local.baseUrl`. History `parts` (including images) are mapped on the wire; `done` events include a normalized `stop` from the OpenAI `finish_reason`.
|
|
312
384
|
|
|
313
|
-
OpenRouter uses Vercel AI SDK Core inside THEORUM's provider adapter.
|
|
314
|
-
|
|
315
|
-
not when importing THEORUM
|
|
316
|
-
|
|
317
|
-
|
|
318
|
-
|
|
319
|
-
|
|
320
|
-
|
|
321
|
-
to wire the OpenRouter adapter directly. Direct local construction is also available
|
|
322
|
-
as `createLocalProvider` from the main / providers entrypoints. Importing
|
|
323
|
-
`theorum/openrouter` loads the Vercel SDK immediately.
|
|
385
|
+
OpenRouter uses Vercel AI SDK Core inside THEORUM's provider adapter. Provider
|
|
386
|
+
adapters load **lazily on the first `complete` call** for the selected transport —
|
|
387
|
+
not when importing THEORUM. Importing `createProvider` alone does not pull in
|
|
388
|
+
Google Interactions, OpenRouter/AI SDK, speech, or local adapter graphs.
|
|
389
|
+
The OpenRouter adapter still emits THEORUM `TurnEvent` values and preserves raw
|
|
390
|
+
provider evidence for citations/provenance where the normalized SDK stream does
|
|
391
|
+
not expose enough detail. Use `createProvider` for all turns; adapter modules
|
|
392
|
+
stay internal to the providers package.
|
|
324
393
|
|
|
325
394
|
---
|
|
326
395
|
|
|
@@ -328,16 +397,21 @@ as `createLocalProvider` from the main / providers entrypoints. Importing
|
|
|
328
397
|
|
|
329
398
|
| Entrypoint | Purpose |
|
|
330
399
|
| :--- | :--- |
|
|
331
|
-
| `jsr:@theorum/core` / `theorum` | Main kernel API: profiles, schemas, runner, core types, provider constructors. |
|
|
332
|
-
| `jsr:@theorum/core/kernel` / `theorum/kernel` | Profile/turn types, tool catalog, `
|
|
333
|
-
| `jsr:@theorum/core/providers` / `theorum/providers` | `createProvider` + Gemini vault types. |
|
|
334
|
-
| `jsr:@theorum/core/
|
|
335
|
-
| `jsr:@theorum/core/guardrails` / `theorum/guardrails` | Sanitization, public error mapping, inbound injection/sensitive-data primitives. |
|
|
400
|
+
| `jsr:@theorum/core` / `theorum` | Main kernel API: profiles, schemas, runner, core types, provider constructors, declarative HTTP/MCP tool execution. |
|
|
401
|
+
| `jsr:@theorum/core/kernel` / `theorum/kernel` | Profile/turn types, tool catalog, `requireModelBinding`, thinking clamps over host model maps. |
|
|
402
|
+
| `jsr:@theorum/core/providers` / `theorum/providers` | `createProvider` + Gemini vault types + host option bags. |
|
|
403
|
+
| `jsr:@theorum/core/providers/local` / `theorum/providers/local` | Direct local OpenAI-compat adapter (`createLocalProvider`, `DEFAULT_LOCAL_BASE_URL`). |
|
|
404
|
+
| `jsr:@theorum/core/guardrails` / `theorum/guardrails` | Sanitization, canary/egress gates, public error mapping, inbound injection/sensitive-data primitives. |
|
|
405
|
+
| `jsr:@theorum/core/guardrails/testing` / `theorum/guardrails/testing` | Adversarial corpus + fuzz helpers (test/harness only). |
|
|
336
406
|
| `jsr:@theorum/core/observability` / `theorum/observability` | Trace sinks and trace record helpers. |
|
|
337
407
|
| `jsr:@theorum/core/host` / `theorum/host` | Optional Deno HTTP helpers (`json`, status mapping, cutout mint flush). |
|
|
338
408
|
| `jsr:@theorum/core/cli` / `theorum/cli` | Profile inspection and stress-test CLI (`theorum` binary on npm). |
|
|
339
409
|
| `jsr:@theorum/core/presets` / `theorum/presets` | Optional convenience packs (`registerGooglePreset`, …). |
|
|
340
|
-
| `jsr:@theorum/core/presets/google` / `theorum/presets/google` | Google builtins (search/maps/urlContext) + Interactions/OpenRouter wire metadata. |
|
|
410
|
+
| `jsr:@theorum/core/presets/google` / `theorum/presets/google` | Google builtins (search/maps/urlContext/codeExecution) + Interactions/OpenRouter wire metadata. |
|
|
411
|
+
|
|
412
|
+
Demo fixtures (travel concierge seeds, local handlers) live in the **repo-private**
|
|
413
|
+
`@theorum/playground` package under `playground/` — never published with the kernel.
|
|
414
|
+
Hosts that need them link `file:../theorum/playground`.
|
|
341
415
|
|
|
342
416
|
Internal files remain present in source for maintainability, but package consumers should use the public entrypoints above.
|
|
343
417
|
|
|
@@ -348,39 +422,63 @@ Named exports from the root barrel (same symbols hosts get from `theorum` /
|
|
|
348
422
|
|
|
349
423
|
| Group | Symbols |
|
|
350
424
|
| --- | --- |
|
|
351
|
-
| Guardrails errors | `describeError`, `isAbortError`, `publicError`, `TheorumError`, `throwIfAborted`, `toErrorEvent` |
|
|
352
|
-
|
|
|
353
|
-
|
|
|
425
|
+
| Guardrails errors | `describeError`, `isAbortError`, `publicError`, `TheorumError`, `throwIfAborted`, `toErrorEvent`, `PUBLIC_CANARY` |
|
|
426
|
+
| Network guardrails | `assertSafeUrl`, `isLocalhostName`, `isPrivateOrLocalAddress` |
|
|
427
|
+
| Guardrail vocabulary | `AdvisoryLevel`, `TrustLevel`, `GuardrailStage`, `Severity`, `GuardrailHit`, `Verdict`, `GuardrailAction`, `GuardrailContext`, `GuardrailEvent`, `OutboundPayload`, `Provenance`, `ToolOrigin`, `ScanText`, `EgressEnforcer`, `EgressOnBlock`, `ProfileEgressSpec`, `ProfileGuardrailsSpec`, `HostGuardrailsSpec`, `NetworkGuardrailSpec`, `CanaryGuardrailSpec`, `QuotaGuardrailSpec`, `ResolvedGuardrailPolicy`, `DetectionOptions`, `GuardedToolText`, `TurnTaint`, `TaintGate`, `TaintGuardrailSpec`, `TRUST_LEVELS`, `GUARDRAIL_STAGES`, `SEVERITIES`, `TOOL_ORIGINS`, `EGRESS_ON_BLOCK` |
|
|
428
|
+
| Guardrail policy | `resolveGuardrailPolicy`, `detectionForTrust`, `detectionForProfile`, `collectEgressHits`, `hitRules`, `EGRESS_RULES`, `runEnforcer` |
|
|
429
|
+
| Tool boundary | `guardToolResult`, `guardToolFailureText`, `inspectToolArguments`, `toolCallEvent`, `wrapToolData`, `isRemoteOrigin`, `composeToolText`, `checkTaintGate`, `recordTaint`, `isTainted`, `isSuspicious`, `directiveHits`, `looksDirective`, `advisoryLevel`, `DIRECTIVE_RULES`, `ADVISORY_LEVELS`, `TOOL_CLOSE`, `TOOL_ORIGINS`, `TAINT_GATES`, `textForScan`, `scanTextOf` |
|
|
430
|
+
| Quota | `QuotaSlotStatus`, `QuotaExhausted`, `clientIp`, `quotaExhausted`, `releaseSlot`, `resetSlots`, `skipQuota`, `takeSlot` |
|
|
431
|
+
| Lexicon | `LEXICON_KEYS`, `LexiconKey`, `LexiconOverrides`, `LexiconParams`, `lexiconDefault`, `lexiconText`, `overrideLexicon`, `resetLexicon` |
|
|
432
|
+
| Sanitize | `PROJECT_ID_MAX`, `sanitizeProjectId`, `sanitizeText`, `detectText`, `sanitizeTurnRequest`, `sanitizeTurnRequestWithEvents`, `sanitizeTurnRequestForTrace`, `redactSensitiveOnly`, `guardrailFromHits`, `guardrailFromVerdict`, `guardrailTurnEvent`, `projectGuardrailTurnEvent`, `hitFromSpan`, `matchPreview`, `projectGuardrailEvent`, `GUARDRAIL_MATCH_PREVIEW_MAX` |
|
|
433
|
+
| Canary / egress | `mintCanary`, `bindCanary`, `wrapUserData`, `scanTextForCanaryLeak`, `redactCanary`, `OMIT_CANARY`, `createCanaryStreamGate`, `eventHasCanary`, `createCanaryGateSession`, `filterCanaryGatedEvents`, `CanaryGateResult`, `CanaryGateSession`, `CanaryStreamGate`, `standardEgressEnforce`, `createOutboundProgressiveGate`, `createProgressiveYieldGate`, `DEFAULT_HOLDBACK`, `createLiveOutboundGateSession`, `processLiveOutboundBatch`, `finalizeLiveOutboundTurn`, `LiveOutboundBatchResult`, `LiveOutboundGateSession`, `ProgressiveYieldGate`, `ProgressiveYieldGateOptions`, `ProgressiveYieldResult` |
|
|
354
434
|
| Compaction | `CompactionSplit`, `CompactionTokens`, `compactionMeter`, `compactionNeeded`, `estimateHistoryTokens`, `HISTORY_MEDIA_TOKENS`, `HISTORY_TEXT_ENCODING`, `resolveCompactionTokens`, `resolveHistoryTokens`, `shouldCompact`, `splitForCompaction` |
|
|
355
|
-
| Runner | `runTurn` |
|
|
356
|
-
|
|
|
357
|
-
|
|
|
358
|
-
|
|
|
359
|
-
|
|
|
360
|
-
|
|
|
361
|
-
|
|
|
435
|
+
| Runner | `runTurn`, `runSession`, `RunSessionOptions`, `prepareLiveInboundText`, `liveIngressEnabled`, `liveIngressEnabledFromSpec`, `liveIngressChannelDefault`, `hasAnyLiveIngress`, `assertLiveIngress`, `assertLiveIngressConfigured`, `LiveIngressChannel` |
|
|
436
|
+
| Attachments | `assertAttachmentLimits`, `maxBytesForMime`, `requireMediaLimits`, `resolveMediaLimits`, `sanitizeCsvText`, `sanitizeTurnBlobs`, `sanitizeTurnBlobsForProfile` |
|
|
437
|
+
| Catalog | `clampThinkingLevel`, `clampThinkingLevelForApiId`, `mediaChannelForMime`, `MediaInputChannel`, `mediaKindForMime`, `mimeAllowed`, `mimeEssence`, `modelEntryByApiId`, `requireModelBinding` |
|
|
438
|
+
| Schema | `PROFILE_FIELDS`, `PROFILE_GRAPH`, `PROFILE_TYPES`, `PROFILE_TYPE_PROTOCOLS`, `protocolsForProfileType`, `isValidProfileProtocol`, `EXTRA_FIELDS`, `fieldMeta`, `catalogPathFor`, `DYNAMIC_FIELD_PARENTS`, `spineFacetsForProfileType`, `profileGraphFacet`, `ProfileGraphFacet`, `ProfileGraphFacetId`, `ProfileGraphEditor`, `ProfileGraphRole`, `PROTOCOLS`, `PROVIDERS`, `PROTOCOL_PROVIDERS`, `providersFor`, `protocolsFor`, `isValidPair`, `coerceProvider`, `coerceProtocol`, `coerceSpeechFormat`, `isSpeechFormatAllowedForProtocol`, `speechFormatsForProtocol`, `THINKING_LEVELS`, `KEY_SLOTS`, `OVERFLOW_KEY_SLOTS`, `MEDIA_INPUT_KINDS`, `MEDIA_INPUT_KIND_VALUES`, `MEDIA_WILDCARDS`, `ATTACHMENT_ACCEPT_MIMES`, `VOICE_ACCEPT_MIMES`, `SUMMARY_MODES`, `STREAM_MODES`, `SPEECH_AUDIO_FORMATS`, `SCHEMA_ENFORCEMENTS`, `COMPACTION_METERS`, `COMPACTION_TIMINGS`, `CACHE_MODES`, `CACHE_TTLS`, `TURN_STAGES`, `TURN_INJECT_STAGES`, `TURN_STOP_KINDS`, `CONTINUE_STOP_KINDS`, `TOOL_GATE_KINDS`, `AWAITING_USER_INPUT_KINDS`, `AWAITING_USER_INPUT_STATUS`, `TOOL_LOAD_TIERS`, `TOOL_ACCESS`, `TOOL_PERMISSION`, `TOOL_TYPES`, `AUTH_UNAUTHENTICATED_POLICIES`, `HTTP_METHODS`, `PLAYGROUND_AUTH_TYPES`, `TOOL_AUTH_TYPES`, `AuthUnauthenticatedPolicy`, `CustomToolType`, `HttpMethod`, `PlaygroundAuthType`, `ToolAccess`, `ToolAuthType`, `ToolPermission`, `ToolType`, `LIVE_ACTIVITY_HANDLINGS`, `LIVE_CONTEXT_COMPRESSIONS`, `LIVE_SPEECH_SENSITIVITIES`, `EGRESS_ON_BLOCK`, `EgressOnBlock` |
|
|
439
|
+
| Profiles | `ProfileDefinition`, `ProfileDefinitionBase`, `TextProfileDefinition`, `ImageProfileDefinition`, `SpeechProfileDefinition`, `LiveProfileDefinition`, `HostProfileDefinition`, `clearProfiles`, `defineProfile`, `getProfile`, `hasProfile`, `listProfiles`, `registerProfile`, `registerProfiles`, `projectProfile`, `resolveTurn`, `pickModel` |
|
|
440
|
+
| Tools | `registerTool`, `registerTools`, `invokeTool`, `registerHarnessTools`, `getTool`, `hasTool`, `requireTool`, `listTools`, `listBuiltinIds`, `listFunctionIds`, `resetTools`, `formatToolResult`, `prepareTurnToolSnapshot`, `buildHttpToolTarget`, `executeHttpTool`, `executeMcpTool`, `parseMcpRpcResponse`, `isUnsupportedMcpProtocolError`, `MCP_PROTOCOL_VERSIONS`, `McpProtocolVersion`, `resolveToolAuth` |
|
|
441
|
+
| Structured | `getStructured`, `registerStructured` |
|
|
442
|
+
| Stop / resume | `ProfileTurnBehaviourSpec`, `ProfileTurnResumptionSpec`, `TurnContinueFrom`, `TurnStop`, `TurnStopKind`, `ContinueStopKind`, `CONTINUE_STOP_KINDS`, `AUTO_CONTINUE_DELAY_MS`, `CONTINUE_INSTRUCTION`, `DEFAULT_ALLOW_CONTINUE`, `DEFAULT_AUTO_CONTINUE`, `GenerationStopError`, `isContinueStopKind`, `isGenerationStopError`, `isResumeableStop`, `isUserCancelledStop`, `profileAllowsSteering`, `profileAllowsInject`, `profileTurnResumption`, `shouldAutoContinue`, `turnStopFromClientStreamEnd`, `turnStopFromInteractionStatus`, `turnStopFromOpenAiFinishReason` |
|
|
443
|
+
| Stages (target foundation) | `TURN_STAGES`, `TURN_INJECT_STAGES`, `STAGE_AFFORDANCES`, `STAGE_AFFORDANCE_MATRIX`, `TOOL_GATE_KINDS`, `AWAITING_USER_INPUT_KINDS`, `AWAITING_USER_INPUT_STATUS`, `applyStageResult`, `parseAwaitingUserInput`, `parseToolGate`, `isTurnStage`, `isTurnInjectStage`, `isToolGateKind`, `isAwaitingUserInput`, `stageAllowsAffordance`, `stageEventFields`, `profileAllowsInject`, `StageAffordance`, `StageContext`, `StageResult`, `StageMutate`, `StageHandler`, `StageApplyInput`, `StageApplyOutput`, `StageApplyWarning`, `StageApplyWarningCode`, `StageEventExtra`, `AwaitingUserInput`, `ToolGate` — contract [`docs/contracts/stages.md`](docs/contracts/stages.md) |
|
|
444
|
+
| Observability | `jsonlSink`, `memorySink`, `noopSink`, `resolveTraceDir`, `sinkFromDir`, `writeTrace`, `registerTraceDestination`, `jsonlDestination`, `requireTraceDestination`, `getTraceDestination`, `listTraceDestinationIds`, `clearTraceDestinations`, `isJsonlTraceDestination`, `isTraceSink`, `resolveTraceWriter`, `resolveObservabilityPolicy`, `TraceRecord`, `TraceSink`, `JsonlSinkOptions`, `JsonlTraceDestination`, `TraceDestination`, `ProfileObservabilitySpec`, `ResolvedObservabilityPolicy`, `ResolvedTraceInclude`, `ResolvedTraceScrub`, `TraceIncludeSpec`, `TraceScrubSpec` |
|
|
445
|
+
| Providers | `CreateProviderOptions`, `GeminiTransport`, `KeyVault`, `LocalProviderConfig`, `OpenAiGatewayConfig`, `createProvider` (local: `theorum/providers/local` → `createLocalProvider`, `DEFAULT_LOCAL_BASE_URL`) |
|
|
362
446
|
|
|
363
447
|
Kernel types re-exported through this barrel follow `export type *` from
|
|
364
|
-
`src/kernel/types.ts` (
|
|
448
|
+
`src/kernel/types.ts` (behavioral detail for contributors: repo
|
|
449
|
+
`docs/contracts/kernel.md`).
|
|
365
450
|
|
|
366
451
|
---
|
|
367
452
|
|
|
368
453
|
## Documentation
|
|
369
454
|
|
|
370
|
-
|
|
455
|
+
THEORUM keeps **package docs** and **repo contracts** separate.
|
|
456
|
+
|
|
457
|
+
| Surface | What it is | In the published package? |
|
|
458
|
+
| --- | --- | --- |
|
|
459
|
+
| **This README** | How hosts use THEORUM (API, boundaries, examples) | Yes |
|
|
460
|
+
| **Repo contracts** (`docs/contracts/*.md`) | Maintainer ownership + behavioral specs for docs-truth | **No** — GitHub / clone only |
|
|
461
|
+
| **Docs-truth** (`docs/DOCS_TRUTH.md`, `docs/_map.mjs`) | Lint graph that enforces those contracts | **No** |
|
|
371
462
|
|
|
372
|
-
|
|
463
|
+
On GitHub, module contracts:
|
|
464
|
+
|
|
465
|
+
| Doc (repo only) | Export |
|
|
373
466
|
| :--- | :--- |
|
|
374
|
-
| [`
|
|
375
|
-
| [`
|
|
376
|
-
| [`
|
|
377
|
-
| [`
|
|
378
|
-
| [`
|
|
379
|
-
| [`
|
|
380
|
-
| [`
|
|
381
|
-
| [`
|
|
382
|
-
| [`
|
|
383
|
-
| [`
|
|
467
|
+
| [`docs/contracts/kernel.md`](docs/contracts/kernel.md) | `theorum/kernel` |
|
|
468
|
+
| [`docs/contracts/stages.md`](docs/contracts/stages.md) | Turn stages — slices 1–3 landed on branch; release cut when docs match product |
|
|
469
|
+
| [`docs/contracts/providers.md`](docs/contracts/providers.md) | `theorum/providers` |
|
|
470
|
+
| [`docs/contracts/guardrails.md`](docs/contracts/guardrails.md) | `theorum/guardrails` |
|
|
471
|
+
| [`docs/contracts/observability.md`](docs/contracts/observability.md) | `theorum/observability` |
|
|
472
|
+
| [`docs/contracts/host.md`](docs/contracts/host.md) | `theorum/host` |
|
|
473
|
+
| [`docs/contracts/kernel.md`](docs/contracts/kernel.md) (repo-private headless interface) | `src/interface/` |
|
|
474
|
+
| [`docs/contracts/cli.md`](docs/contracts/cli.md) | `theorum/cli` |
|
|
475
|
+
| [`docs/contracts/presets.md`](docs/contracts/presets.md) | `theorum/presets` |
|
|
476
|
+
| [`docs/contracts/presets-google.md`](docs/contracts/presets-google.md) | `theorum/presets/google` |
|
|
477
|
+
|
|
478
|
+
Migrating from per-turn `dynamicTools`? See
|
|
479
|
+
[`docs/MIGRATION-tool-system.md`](docs/MIGRATION-tool-system.md).
|
|
480
|
+
Ownership-boundary cut (playground out of package, quota/lexicon/composer)? See
|
|
481
|
+
[`docs/MIGRATION-boundary.md`](docs/MIGRATION-boundary.md).
|
|
384
482
|
|
|
385
483
|
Document health is enforced by `npm run lint:docs` — the **first** step of
|
|
386
484
|
`npm run lint` / `deno task lint` (`docs/_map.mjs`):
|
|
@@ -389,6 +487,9 @@ Document health is enforced by `npm run lint:docs` — the **first** step of
|
|
|
389
487
|
- Export parity with `package.json` and export-drift vs entry `mod.ts` files
|
|
390
488
|
- Doc + **section** freshness on every code change (no Export-only gaming)
|
|
391
489
|
- Behavioral sections require `contract_test` evidence (≥2 supports each)
|
|
490
|
+
- Publish gates keep `docs/` and `src/**/*.md` out of npm/JSR (`verify-publish-bundle`)
|
|
491
|
+
- Freshness diffs use a 32 MiB `git` buffer so large `origin/main...HEAD` patches
|
|
492
|
+
are not silently dropped (`ENOBUFS`)
|
|
392
493
|
- Pre-commit runs `lint:docs` automatically (`prepare` installs the hook on `npm install`)
|
|
393
494
|
|
|
394
495
|
---
|
|
@@ -399,9 +500,22 @@ Document health is enforced by `npm run lint:docs` — the **first** step of
|
|
|
399
500
|
npm install
|
|
400
501
|
npm run test
|
|
401
502
|
npm run lint
|
|
402
|
-
deno
|
|
503
|
+
deno install
|
|
504
|
+
deno publish --dry-run
|
|
505
|
+
npm run build:npm
|
|
506
|
+
cd npm && npm pack
|
|
403
507
|
```
|
|
404
508
|
|
|
509
|
+
To dry-run npm publish when the current version is already on the registry, bump to an ephemeral prerelease first (CI does this automatically):
|
|
510
|
+
|
|
511
|
+
```bash
|
|
512
|
+
cd npm
|
|
513
|
+
npm version 0.0.0-pr.local --no-git-tag-version
|
|
514
|
+
npm publish --dry-run --access public --tag ci-validate
|
|
515
|
+
```
|
|
516
|
+
|
|
517
|
+
PR CI runs JSR and npm dry-run checks in the required `publish-dry-run` job.
|
|
518
|
+
|
|
405
519
|
Run the packaged CLI locally:
|
|
406
520
|
|
|
407
521
|
```bash
|
|
@@ -418,16 +532,16 @@ cd npm
|
|
|
418
532
|
npm pack
|
|
419
533
|
```
|
|
420
534
|
|
|
421
|
-
Run
|
|
535
|
+
Run an OpenRouter provider smoke test with a host-resolved key. The key is passed as an argument and is never read from a Theorum `.env` file.
|
|
422
536
|
|
|
423
537
|
```bash
|
|
424
|
-
deno run --allow-net scripts/verify-
|
|
538
|
+
deno run --allow-net scripts/verify-provider-smoke.ts --api-key "$OPENROUTER_API_KEY"
|
|
425
539
|
```
|
|
426
540
|
|
|
427
|
-
The default
|
|
541
|
+
The default smoke uses `perplexity/sonar` because it is broadly available on OpenRouter. Hosts can override both the profile-facing model id and provider-native id:
|
|
428
542
|
|
|
429
543
|
```bash
|
|
430
|
-
deno run --allow-net scripts/verify-
|
|
544
|
+
deno run --allow-net scripts/verify-provider-smoke.ts \
|
|
431
545
|
--api-key "$OPENROUTER_API_KEY" \
|
|
432
546
|
--model hostFastModel \
|
|
433
547
|
--api-id perplexity/sonar
|
|
@@ -441,15 +555,42 @@ THEORUM is ready for host applications when these statements stay true:
|
|
|
441
555
|
|
|
442
556
|
```toml
|
|
443
557
|
[boundary]
|
|
558
|
+
# Rule: "Host decides, Theorum runs."
|
|
444
559
|
profiles_in_package = false
|
|
560
|
+
demos_in_package = false
|
|
445
561
|
env_files_in_package = false
|
|
446
562
|
ambient_secret_reads = false
|
|
447
563
|
business_logic_in_kernel = false
|
|
564
|
+
unownable_user_or_model_copy = false
|
|
448
565
|
provider_keys_host_owned = true
|
|
566
|
+
provider_adapters_lazy = true
|
|
449
567
|
trace_sinks_host_injected = true
|
|
450
568
|
realtime_duplex_voice = "out of scope"
|
|
451
569
|
```
|
|
452
570
|
|
|
571
|
+
**Facts vs policy.** Provider facts may ship (model capabilities, wire shapes,
|
|
572
|
+
protocol metadata — e.g. `theorum/presets/google`). Product policy may not
|
|
573
|
+
(prompts, personas, end-user copy, demo apps, channel behavior). Every
|
|
574
|
+
user- or model-visible string is either host-supplied or an overridable
|
|
575
|
+
registered default in the kernel lexicon (`overrideLexicon`). Behavioral
|
|
576
|
+
defaults live as typed profile-schema fields. Optional packages
|
|
577
|
+
(`playground/`) are inert extras: deleting them changes no kernel behavior.
|
|
578
|
+
|
|
579
|
+
Invariant properties (machine-checked where noted):
|
|
580
|
+
|
|
581
|
+
| Id | Property | Check |
|
|
582
|
+
| --- | --- | --- |
|
|
583
|
+
| P1 | No ambient authority — construct with every Deno permission denied | `tests/kernel/zero-permission-import.test.ts` |
|
|
584
|
+
| P2 | No unownable words — user/model-visible strings are host-suppliable or lexicon defaults | lexicon + full-tree `scripts/docs-truth/copy-lint.mjs` + two-hosts test |
|
|
585
|
+
| P3 | No buried policy — behavioral defaults are declared profile-schema fields | `PROFILE_FIELDS` / schema |
|
|
586
|
+
| P4 | Inert extras — optional entrypoints removable without behavior change | publish-bundle gate excludes `playground/` |
|
|
587
|
+
|
|
588
|
+
Provider adapters load **lazily** on the first `complete` for that transport —
|
|
589
|
+
`createProvider` and `theorum/providers` stay a thin barrel (`src/providers/mod.ts`);
|
|
590
|
+
implementation modules (e.g. `google/interactions/`, `openrouter/`, `local/`) are
|
|
591
|
+
not pulled in at import time. `trace-attach` lazy-loads Interactions wire helpers
|
|
592
|
+
only for `geminiInteractions` traces.
|
|
593
|
+
|
|
453
594
|
If an app needs domain rules, platform delivery policy, product copy, database access, or session memory, that belongs outside THEORUM.
|
|
454
595
|
|
|
455
596
|
---
|
|
@@ -487,8 +628,10 @@ MIT License. Copyright (c) ORCHID AI LLC.
|
|
|
487
628
|
},
|
|
488
629
|
"Package Boundary": {
|
|
489
630
|
"supports": [
|
|
490
|
-
{ "kind": "source", "path": "src/providers/
|
|
491
|
-
{ "kind": "
|
|
631
|
+
{ "kind": "source", "path": "src/providers/mod.ts" },
|
|
632
|
+
{ "kind": "source", "path": "src/guardrails/lexicon.ts" },
|
|
633
|
+
{ "kind": "contract_test", "path": "tests/kernel/two-hosts-boundary.test.ts" },
|
|
634
|
+
{ "kind": "contract_test", "path": "tests/kernel/zero-permission-import.test.ts" }
|
|
492
635
|
]
|
|
493
636
|
}
|
|
494
637
|
}
|