theorum 0.1.14 → 1.0.0

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 (229) hide show
  1. package/README.md +178 -89
  2. package/esm/mod.d.ts +21 -11
  3. package/esm/mod.js +15 -8
  4. package/esm/src/cli/commands/bench.js +6 -3
  5. package/esm/src/cli/commands/fuzz-canary.d.ts +13 -0
  6. package/esm/src/cli/commands/fuzz-canary.js +195 -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/profile.js +25 -14
  10. package/esm/src/cli/commands/run.d.ts +3 -0
  11. package/esm/src/cli/commands/run.js +22 -30
  12. package/esm/src/cli/commands/test.d.ts +10 -1
  13. package/esm/src/cli/commands/test.js +31 -31
  14. package/esm/src/cli/event-log.d.ts +19 -0
  15. package/esm/src/cli/event-log.js +147 -0
  16. package/esm/src/cli/index.js +45 -11
  17. package/esm/src/cli/matrix/synthesizer.d.ts +7 -9
  18. package/esm/src/cli/matrix/synthesizer.js +32 -106
  19. package/esm/src/guardrails/canary-gate.d.ts +20 -0
  20. package/esm/src/guardrails/canary-gate.js +31 -0
  21. package/esm/src/guardrails/canary.d.ts +26 -0
  22. package/esm/src/guardrails/canary.js +139 -0
  23. package/esm/src/guardrails/corpus/canary-egress-attacks.d.ts +16 -0
  24. package/esm/src/guardrails/corpus/canary-egress-attacks.js +151 -0
  25. package/esm/src/guardrails/corpus/fuzz-inbound.d.ts +11 -0
  26. package/esm/src/guardrails/corpus/fuzz-inbound.js +216 -0
  27. package/esm/src/guardrails/corpus/inbound-payloads.d.ts +10 -0
  28. package/esm/src/guardrails/corpus/inbound-payloads.js +124 -0
  29. package/esm/src/guardrails/corpus/live-attacks.d.ts +20 -0
  30. package/esm/src/guardrails/corpus/live-attacks.js +232 -0
  31. package/esm/src/guardrails/corpus/mod.d.ts +13 -0
  32. package/esm/src/guardrails/corpus/mod.js +11 -0
  33. package/esm/src/guardrails/corpus/secrets.d.ts +16 -0
  34. package/esm/src/guardrails/corpus/secrets.js +16 -0
  35. package/esm/src/guardrails/corpus/strings.d.ts +27 -0
  36. package/esm/src/guardrails/corpus/strings.js +33 -0
  37. package/esm/src/guardrails/corpus/types.d.ts +37 -0
  38. package/esm/src/guardrails/corpus/types.js +6 -0
  39. package/esm/src/guardrails/egress.d.ts +9 -0
  40. package/esm/src/guardrails/egress.js +36 -0
  41. package/esm/src/guardrails/error.js +6 -4
  42. package/esm/src/guardrails/injection.js +28 -5
  43. package/esm/src/guardrails/live-outbound-gate.d.ts +39 -0
  44. package/esm/src/guardrails/live-outbound-gate.js +180 -0
  45. package/esm/src/guardrails/mod.d.ts +13 -4
  46. package/esm/src/guardrails/mod.js +10 -4
  47. package/esm/src/guardrails/quota.js +1 -1
  48. package/esm/src/guardrails/sanitize.d.ts +11 -15
  49. package/esm/src/guardrails/sanitize.js +40 -49
  50. package/esm/src/guardrails/sensitive.js +2 -1
  51. package/esm/src/guardrails/testing.d.ts +10 -0
  52. package/esm/src/guardrails/testing.js +9 -0
  53. package/esm/src/host/client-turn.d.ts +19 -0
  54. package/esm/src/host/client-turn.js +32 -0
  55. package/esm/src/host/mod.d.ts +5 -3
  56. package/esm/src/host/mod.js +4 -3
  57. package/esm/src/interface/blocks.d.ts +20 -0
  58. package/esm/src/interface/blocks.js +180 -0
  59. package/esm/src/interface/from-profile.d.ts +14 -0
  60. package/esm/src/interface/from-profile.js +104 -0
  61. package/esm/src/interface/inputs.d.ts +8 -0
  62. package/esm/src/interface/inputs.js +127 -0
  63. package/esm/src/interface/mod.d.ts +10 -0
  64. package/esm/src/interface/mod.js +9 -0
  65. package/esm/src/interface/types.d.ts +153 -0
  66. package/esm/src/interface/types.js +13 -0
  67. package/esm/src/kernel/engine/delta.d.ts +24 -2
  68. package/esm/src/kernel/engine/delta.js +519 -29
  69. package/esm/src/kernel/engine/live-inbound.d.ts +9 -0
  70. package/esm/src/kernel/engine/live-inbound.js +17 -0
  71. package/esm/src/kernel/engine/repair.js +1 -1
  72. package/esm/src/kernel/engine/runner/gates.d.ts +1 -1
  73. package/esm/src/kernel/engine/runner/gates.js +7 -7
  74. package/esm/src/kernel/engine/runner/mod.js +13 -13
  75. package/esm/src/kernel/engine/runner/state.d.ts +7 -0
  76. package/esm/src/kernel/engine/runner/steps.d.ts +1 -1
  77. package/esm/src/kernel/engine/runner/steps.js +171 -37
  78. package/esm/src/kernel/engine/runner/stream.d.ts +1 -2
  79. package/esm/src/kernel/engine/runner/stream.js +66 -29
  80. package/esm/src/kernel/engine/session/mod.d.ts +23 -0
  81. package/esm/src/kernel/engine/session/mod.js +205 -0
  82. package/esm/src/kernel/mod.d.ts +9 -10
  83. package/esm/src/kernel/mod.js +6 -8
  84. package/esm/src/kernel/registry/attachments.d.ts +4 -2
  85. package/esm/src/kernel/registry/attachments.js +6 -3
  86. package/esm/src/kernel/registry/catalog.d.ts +3 -16
  87. package/esm/src/kernel/registry/catalog.js +5 -81
  88. package/esm/src/kernel/registry/ingress.d.ts +9 -4
  89. package/esm/src/kernel/registry/ingress.js +73 -63
  90. package/esm/src/kernel/registry/profiles.d.ts +35 -12
  91. package/esm/src/kernel/registry/profiles.js +159 -66
  92. package/esm/src/kernel/registry/provider-request.js +11 -7
  93. package/esm/src/kernel/registry/resolve.d.ts +5 -6
  94. package/esm/src/kernel/registry/resolve.js +100 -70
  95. package/esm/src/kernel/registry/vault.d.ts +12 -7
  96. package/esm/src/kernel/registry/vault.js +30 -8
  97. package/esm/src/kernel/schema.d.ts +145 -0
  98. package/esm/src/kernel/schema.js +462 -0
  99. package/esm/src/kernel/stop.d.ts +15 -10
  100. package/esm/src/kernel/stop.js +5 -5
  101. package/esm/src/kernel/tools/execute.d.ts +45 -0
  102. package/esm/src/kernel/tools/execute.js +363 -0
  103. package/esm/src/kernel/tools/harness.d.ts +8 -0
  104. package/esm/src/kernel/tools/harness.js +44 -0
  105. package/esm/src/kernel/tools/invoke.d.ts +10 -0
  106. package/esm/src/kernel/tools/invoke.js +83 -0
  107. package/esm/src/kernel/tools/mod.d.ts +11 -0
  108. package/esm/src/kernel/tools/mod.js +10 -0
  109. package/esm/src/kernel/tools/project.d.ts +12 -0
  110. package/esm/src/kernel/tools/project.js +34 -0
  111. package/esm/src/kernel/tools/registry.d.ts +23 -0
  112. package/esm/src/kernel/tools/registry.js +71 -0
  113. package/esm/src/kernel/tools/resolve.d.ts +29 -0
  114. package/esm/src/kernel/tools/resolve.js +262 -0
  115. package/esm/src/kernel/tools/schema.d.ts +13 -0
  116. package/esm/src/kernel/tools/schema.js +159 -0
  117. package/esm/src/kernel/tools/types.d.ts +216 -0
  118. package/esm/src/kernel/tools/types.js +9 -0
  119. package/esm/src/kernel/types.d.ts +338 -193
  120. package/esm/src/observability/trace-attach.d.ts +6 -4
  121. package/esm/src/observability/trace-attach.js +39 -25
  122. package/esm/src/observability/trace-record.d.ts +11 -9
  123. package/esm/src/observability/trace-record.js +36 -23
  124. package/esm/src/observability/trace-usage.d.ts +10 -3
  125. package/esm/src/observability/trace-usage.js +70 -17
  126. package/esm/src/observability/trace.d.ts +9 -1
  127. package/esm/src/observability/trace.js +11 -3
  128. package/esm/src/presets/google/speech-voices.d.ts +11 -0
  129. package/esm/src/presets/google/speech-voices.js +41 -0
  130. package/esm/src/presets/google.d.ts +36 -24
  131. package/esm/src/presets/google.js +50 -63
  132. package/esm/src/presets/mod.d.ts +2 -2
  133. package/esm/src/presets/mod.js +1 -1
  134. package/esm/src/providers/create-provider.d.ts +14 -14
  135. package/esm/src/providers/create-provider.js +55 -23
  136. package/esm/src/providers/google/interactions/framing.d.ts +15 -0
  137. package/esm/src/providers/google/interactions/framing.js +208 -0
  138. package/esm/src/providers/google/interactions/mod.d.ts +7 -0
  139. package/esm/src/providers/google/interactions/mod.js +7 -0
  140. package/esm/src/providers/google/interactions/stream.d.ts +83 -0
  141. package/esm/src/providers/google/interactions/stream.js +588 -0
  142. package/esm/src/providers/google/keys.d.ts +26 -0
  143. package/esm/src/providers/{keys.js → google/keys.js} +19 -31
  144. package/esm/src/providers/google/live/framing.d.ts +46 -0
  145. package/esm/src/providers/google/live/framing.js +515 -0
  146. package/esm/src/providers/google/live/openapi-schema.d.ts +6 -0
  147. package/esm/src/providers/google/live/openapi-schema.js +45 -0
  148. package/esm/src/providers/google/live/session.d.ts +25 -0
  149. package/esm/src/providers/google/live/session.js +134 -0
  150. package/esm/src/providers/google/live/stream.d.ts +36 -0
  151. package/esm/src/providers/google/live/stream.js +201 -0
  152. package/esm/src/providers/google/urls.d.ts +6 -0
  153. package/esm/src/providers/google/urls.js +6 -0
  154. package/esm/src/providers/local/local.d.ts +30 -0
  155. package/esm/src/providers/{local.js → local/local.js} +66 -126
  156. package/esm/src/providers/local/mod.d.ts +9 -0
  157. package/esm/src/providers/local/mod.js +9 -0
  158. package/esm/src/providers/mod.d.ts +6 -3
  159. package/esm/src/providers/mod.js +3 -1
  160. package/esm/src/providers/openrouter/chat.d.ts +87 -0
  161. package/esm/src/providers/{openrouter.js → openrouter/chat.js} +70 -229
  162. package/esm/src/providers/openrouter/image.d.ts +34 -0
  163. package/esm/src/providers/openrouter/image.js +286 -0
  164. package/esm/src/providers/openrouter/openai/chat-payload.d.ts +24 -0
  165. package/esm/src/providers/openrouter/openai/chat-payload.js +60 -0
  166. package/esm/src/providers/openrouter/openai/compat.d.ts +47 -0
  167. package/esm/src/providers/openrouter/openai/compat.js +194 -0
  168. package/esm/src/providers/openrouter/openai/image-payload.d.ts +18 -0
  169. package/esm/src/providers/openrouter/openai/image-payload.js +84 -0
  170. package/esm/src/providers/openrouter/openai/sdk-messages.d.ts +22 -0
  171. package/esm/src/providers/openrouter/openai/sdk-messages.js +95 -0
  172. package/esm/src/providers/openrouter/resolve-api-key.d.ts +9 -0
  173. package/esm/src/providers/openrouter/resolve-api-key.js +24 -0
  174. package/esm/src/providers/openrouter/speech.d.ts +23 -0
  175. package/esm/src/providers/{speech.js → openrouter/speech.js} +32 -55
  176. package/esm/src/providers/probe.d.ts +1 -0
  177. package/esm/src/providers/probe.js +22 -0
  178. package/esm/src/providers/shared/pcm.d.ts +12 -0
  179. package/esm/src/providers/{pcm.js → shared/pcm.js} +16 -3
  180. package/esm/src/providers/shared/sse.d.ts +18 -0
  181. package/esm/src/providers/shared/sse.js +87 -0
  182. package/esm/src/providers/shared/tool-args.d.ts +17 -0
  183. package/esm/src/providers/shared/tool-args.js +45 -0
  184. package/esm/src/providers/shared/upstream-tap.d.ts +5 -0
  185. package/esm/src/providers/{google-tap.js → shared/upstream-tap.js} +4 -7
  186. package/esm/src/providers/shared/upstream-tape.d.ts +6 -0
  187. package/esm/src/providers/{gemini-tape.js → shared/upstream-tape.js} +12 -22
  188. package/esm/src/providers/types.d.ts +27 -0
  189. package/esm/src/providers/types.js +1 -0
  190. package/package.json +11 -7
  191. package/docs/cli.md +0 -97
  192. package/docs/guardrails.md +0 -178
  193. package/docs/host.md +0 -97
  194. package/docs/kernel.md +0 -404
  195. package/docs/observability.md +0 -105
  196. package/docs/openrouter.md +0 -125
  197. package/docs/presets-google.md +0 -91
  198. package/docs/presets.md +0 -88
  199. package/docs/providers.md +0 -201
  200. package/docs/streaming.md +0 -96
  201. package/esm/src/kernel/engine/boundary.d.ts +0 -10
  202. package/esm/src/kernel/engine/boundary.js +0 -55
  203. package/esm/src/kernel/engine/runner/tools.d.ts +0 -13
  204. package/esm/src/kernel/engine/runner/tools.js +0 -198
  205. package/esm/src/kernel/registry/tools.d.ts +0 -12
  206. package/esm/src/kernel/registry/tools.js +0 -36
  207. package/esm/src/providers/expose-for-tests.d.ts +0 -1
  208. package/esm/src/providers/expose-for-tests.js +0 -25
  209. package/esm/src/providers/gemini-tape.d.ts +0 -2
  210. package/esm/src/providers/google-tap.d.ts +0 -3
  211. package/esm/src/providers/interactions.d.ts +0 -5
  212. package/esm/src/providers/interactions.js +0 -169
  213. package/esm/src/providers/keys.d.ts +0 -19
  214. package/esm/src/providers/local.d.ts +0 -29
  215. package/esm/src/providers/openrouter-mod.d.ts +0 -13
  216. package/esm/src/providers/openrouter-mod.js +0 -12
  217. package/esm/src/providers/openrouter-payload.d.ts +0 -39
  218. package/esm/src/providers/openrouter-payload.js +0 -195
  219. package/esm/src/providers/openrouter.d.ts +0 -15
  220. package/esm/src/providers/pcm.d.ts +0 -7
  221. package/esm/src/providers/provider.d.ts +0 -15
  222. package/esm/src/providers/provider.js +0 -176
  223. package/esm/src/providers/speech.d.ts +0 -23
  224. package/esm/src/providers/sse.d.ts +0 -7
  225. package/esm/src/providers/sse.js +0 -55
  226. package/esm/src/streaming/mod.d.ts +0 -9
  227. package/esm/src/streaming/mod.js +0 -8
  228. /package/esm/src/{streaming → host}/readStreamingJsonStringField.d.ts +0 -0
  229. /package/esm/src/{streaming → host}/readStreamingJsonStringField.js +0 -0
@@ -0,0 +1,205 @@
1
+ /**
2
+ * `runSession` — long-lived live profile execution.
3
+ *
4
+ * Shares resolve / tools / canary / system / outbound gate with `runTurn`.
5
+ * Does not use `ModelProvider.complete()` — live is a session, not one turn.
6
+ *
7
+ * @module
8
+ */
9
+ import { bindCanary } from '../../../guardrails/canary.js';
10
+ import { publicError, TheorumError, throwIfAborted, toErrorEvent, } from '../../../guardrails/error.js';
11
+ import { abortLiveOutboundTurn, createLiveOutboundGateSession, finalizeLiveOutboundTurn, processLiveOutboundBatch, } from '../../../guardrails/live-outbound-gate.js';
12
+ import { sanitizeTurnRequest } from '../../../guardrails/sanitize.js';
13
+ import { buildGeminiLiveRealtimeInput, buildGeminiLiveRealtimeText, buildGeminiLiveToolResponse, buildGeminiLiveToolResponses, } from '../../../providers/google/live/framing.js';
14
+ import { openGoogleLiveSession } from '../../../providers/google/live/session.js';
15
+ import { providerCompleteRequest } from '../../registry/provider-request.js';
16
+ import { pickSystemRole, resolveTurn } from '../../registry/resolve.js';
17
+ import { expandT1Policy } from '../../tools/resolve.js';
18
+ import { prepareLiveInboundText } from '../live-inbound.js';
19
+ import { systemFromProfile } from '../runner/stream.js';
20
+ function assertLiveProfile(profile) {
21
+ if (profile.type !== 'live') {
22
+ throw new TheorumError(`runSession requires profile.type 'live' (got '${profile.type}' for ${profile.id})`);
23
+ }
24
+ }
25
+ function toTurnRequest(req) {
26
+ return {
27
+ profile: req.profile,
28
+ system: req.system,
29
+ path: req.path,
30
+ sessionPermissions: req.sessionPermissions,
31
+ sessionResumptionHandle: req.sessionResumptionHandle,
32
+ signal: req.signal,
33
+ metadata: req.metadata,
34
+ input: {
35
+ text: '',
36
+ history: req.history,
37
+ sessionResumptionHandle: req.sessionResumptionHandle,
38
+ },
39
+ };
40
+ }
41
+ function applyVoiceOverride(generation, voice) {
42
+ if (!voice || !generation.live) {
43
+ return generation;
44
+ }
45
+ return {
46
+ ...generation,
47
+ live: {
48
+ ...generation.live,
49
+ voice,
50
+ },
51
+ };
52
+ }
53
+ function applyInitialInput(generation, input) {
54
+ if (!input || input.length === 0) {
55
+ return generation;
56
+ }
57
+ return { ...generation, input };
58
+ }
59
+ async function applyOutbound(gate, events, turnPhase, onWithhold) {
60
+ if (turnPhase === 'abort') {
61
+ abortLiveOutboundTurn(gate);
62
+ // Keep tool calls + interrupted marker; drop buffered speech via abortLiveOutboundTurn.
63
+ return events.filter((ev) => ev.type === 'tool' ||
64
+ ev.type === 'session' ||
65
+ (ev.type === 'done' && ev.interrupted === true));
66
+ }
67
+ const batch = processLiveOutboundBatch(gate, events);
68
+ const out = [];
69
+ if (batch.action === 'withhold') {
70
+ onWithhold(batch.error);
71
+ return [{ type: 'error', error: batch.error }];
72
+ }
73
+ if (batch.action === 'emit') {
74
+ out.push(...batch.events);
75
+ }
76
+ if (turnPhase === 'complete') {
77
+ const finalized = await finalizeLiveOutboundTurn(gate);
78
+ if (finalized.action === 'withhold') {
79
+ onWithhold(finalized.error);
80
+ return [...out, { type: 'error', error: finalized.error }];
81
+ }
82
+ if (finalized.action === 'emit') {
83
+ out.push(...finalized.events);
84
+ }
85
+ // Conversational turn boundary — session stays open.
86
+ out.push({ type: 'done', stop: { kind: 'completed' } });
87
+ }
88
+ return out;
89
+ }
90
+ function buildLiveSession(args) {
91
+ const { profile, canary, connection, gate, signal } = args;
92
+ let closed = false;
93
+ let withholdClose;
94
+ const sendJson = (payload) => {
95
+ if (closed) {
96
+ throw new TheorumError('Live session is closed');
97
+ }
98
+ connection.send(JSON.stringify(payload));
99
+ };
100
+ return {
101
+ profileId: profile.id,
102
+ canary,
103
+ async *events() {
104
+ try {
105
+ for await (const item of connection.batches()) {
106
+ throwIfAborted(signal);
107
+ if (item.type === 'closed') {
108
+ break;
109
+ }
110
+ if (item.type === 'error') {
111
+ yield toErrorEvent(item.error);
112
+ break;
113
+ }
114
+ const gated = await applyOutbound(gate, item.events, item.turnPhase, (error) => {
115
+ withholdClose = error;
116
+ });
117
+ for (const ev of gated) {
118
+ if (ev.type === 'error') {
119
+ yield {
120
+ ...ev,
121
+ error: publicError(ev.error ?? withholdClose ?? 'guardrail withheld'),
122
+ };
123
+ }
124
+ else {
125
+ yield ev;
126
+ }
127
+ }
128
+ if (withholdClose) {
129
+ connection.close(1011, 'guardrail withheld');
130
+ break;
131
+ }
132
+ }
133
+ }
134
+ finally {
135
+ closed = true;
136
+ connection.close();
137
+ }
138
+ },
139
+ sendAudio(audio) {
140
+ sendJson(buildGeminiLiveRealtimeInput({
141
+ type: 'audio',
142
+ mimeType: audio.mimeType ?? 'audio/pcm;rate=16000',
143
+ data: audio.data,
144
+ }));
145
+ },
146
+ sendVideo(video) {
147
+ sendJson(buildGeminiLiveRealtimeInput({
148
+ type: 'video',
149
+ mimeType: video.mimeType ?? 'image/jpeg',
150
+ data: video.data,
151
+ }));
152
+ },
153
+ sendText(text) {
154
+ const safeText = prepareLiveInboundText(profile, text);
155
+ sendJson(buildGeminiLiveRealtimeText(safeText));
156
+ },
157
+ sendToolResponse(id, name, output) {
158
+ sendJson(buildGeminiLiveToolResponse(id, name, output));
159
+ },
160
+ sendToolResponses(responses) {
161
+ sendJson(buildGeminiLiveToolResponses(responses));
162
+ },
163
+ close(reason = 'session-closed') {
164
+ if (closed)
165
+ return Promise.resolve();
166
+ closed = true;
167
+ connection.close(1000, reason);
168
+ return Promise.resolve();
169
+ },
170
+ };
171
+ }
172
+ /**
173
+ * Open a gated Gemini Live session for a `type: 'live'` profile.
174
+ *
175
+ * Hosts bridge browser sockets and tool dispatch; THEORUM owns Gemini WS,
176
+ * framing, inbound prep, and outbound canary/egress gates.
177
+ */
178
+ export async function runSession(req, options) {
179
+ const turnReq = toTurnRequest(req);
180
+ const safe = sanitizeTurnRequest(turnReq);
181
+ throwIfAborted(safe.signal);
182
+ const { profile, generation: gen0 } = resolveTurn(safe);
183
+ assertLiveProfile(profile);
184
+ await expandT1Policy(gen0.tools, profile, safe);
185
+ gen0.builtins = gen0.tools.builtins;
186
+ let generation = applyVoiceOverride(gen0, req.voice);
187
+ generation = applyInitialInput(generation, req.input);
188
+ const role = pickSystemRole(profile, safe.input?.role);
189
+ const combinedSys = [systemFromProfile(profile, role), safe.system].filter(Boolean).join('\n\n');
190
+ const system = bindCanary(combinedSys, generation.canary);
191
+ const completeReq = {
192
+ ...providerCompleteRequest(generation, system),
193
+ ...(req.wireTools ? { wireTools: req.wireTools } : {}),
194
+ signal: safe.signal,
195
+ };
196
+ const gate = createLiveOutboundGateSession(profile, generation.canary || undefined);
197
+ const connection = await openGoogleLiveSession(completeReq, options.gemini, options.openWebSocket);
198
+ return buildLiveSession({
199
+ profile,
200
+ canary: generation.canary,
201
+ connection,
202
+ gate,
203
+ signal: safe.signal,
204
+ });
205
+ }
@@ -1,22 +1,21 @@
1
1
  /**
2
2
  * Profile, turn, tool, provider, egress, and event contracts for THEORUM.
3
3
  *
4
- * This entrypoint is type-first. Host applications import from here when they
5
- * want to declare profiles, tool schemas, provider adapters, turn requests, or
6
- * trace-safe event handlers without importing provider implementations.
7
- *
8
4
  * @module
9
5
  */
10
6
  import "../../_dnt.polyfills.js";
11
7
  export type { CompactionSplit, CompactionTokens } from './engine/compaction.js';
12
8
  export { compactionMeter, compactionNeeded, estimateHistoryTokens, HISTORY_MEDIA_TOKENS, HISTORY_TEXT_ENCODING, resolveCompactionTokens, resolveHistoryTokens, shouldCompact, splitForCompaction, } from './engine/compaction.js';
13
9
  export { runTurn } from './engine/runner.js';
14
- export { CATALOG, clampThinkingLevel, clampThinkingLevelForApiId, getTool, listBuiltinIds, mediaKindForMime, mimeAllowed, mimeEssence, modelEntryByApiId, registerTools, requireModelSpec, resetTools, } from './registry/catalog.js';
15
- export type { ProfileDefinition } from './registry/profiles.js';
10
+ export type { RunSessionOptions } from './engine/session/mod.js';
11
+ export { runSession } from './engine/session/mod.js';
12
+ export { clampThinkingLevel, clampThinkingLevelForApiId, mediaKindForMime, mimeAllowed, mimeEssence, modelEntryByApiId, requireModelSpec, } from './registry/catalog.js';
13
+ export type { ImageProfileDefinition, LiveProfileDefinition, ProfileDefinition, ProfileDefinitionBase, SpeechProfileDefinition, TextProfileDefinition, } from './registry/profiles.js';
16
14
  export { clearProfiles, defineProfile, getProfile, hasProfile, listProfiles, registerProfile, registerProfiles, } from './registry/profiles.js';
17
- export { projectProfile, resolveTurn } from './registry/resolve.js';
15
+ export { projectProfile, projectProfileObject, resolveTurn } from './registry/resolve.js';
18
16
  export { getStructured, registerStructured } from './registry/schemas.js';
19
- export { executeTool } from './registry/tools.js';
20
- export type { ProfileResumeSpec, TurnContinueFrom, TurnStop, TurnStopKind } from './stop.js';
21
- export { AUTO_CONTINUE_DELAY_MS, CONTINUE_INSTRUCTION, DEFAULT_AUTO_CONTINUE, GenerationStopError, isGenerationStopError, isResumeableStop, isUserCancelledStop, shouldAutoContinue, turnStopFromClientStreamEnd, turnStopFromInteractionStatus, turnStopFromOpenRouter, } from './stop.js';
17
+ export { ATTACHMENT_ACCEPT_MIMES, COMPACTION_METERS, COMPACTION_TIMINGS, CONTROL_IDS, catalogPathFor, coerceProtocol, coerceProvider, EGRESS_ON_BLOCK, EXTRA_FIELDS, fieldMeta, isValidPair, isValidProfileProtocol, KEY_SLOTS, MEDIA_INPUT_KIND_VALUES, MEDIA_INPUT_KINDS, MEDIA_WILDCARDS, OVERFLOW_KEY_SLOTS, PROFILE_FIELDS, PROFILE_TYPE_PROTOCOLS, PROFILE_TYPES, PROTOCOL_PROVIDERS, PROTOCOLS, PROVIDERS, protocolsFor, protocolsForProfileType, providersFor, SCHEMA_ENFORCEMENTS, SPEECH_AUDIO_FORMATS, STREAM_MODES, SUMMARY_MODES, THINKING_LEVELS, TOOL_ACCESS, TOOL_LOAD_TIERS, TOOL_PERMISSION, TOOL_TYPES, TURN_STOP_KINDS, VOICE_ACCEPT_MIMES, } from './schema.js';
18
+ export type { ProfileTurnResumptionSpec, TurnContinueFrom, TurnStop } from './stop.js';
19
+ export { AUTO_CONTINUE_DELAY_MS, CONTINUE_INSTRUCTION, DEFAULT_AUTO_CONTINUE, GenerationStopError, isGenerationStopError, isResumeableStop, isUserCancelledStop, shouldAutoContinue, turnStopFromClientStreamEnd, turnStopFromInteractionStatus, turnStopFromOpenAiFinishReason, } from './stop.js';
20
+ export { formatToolResult, getTool, hasTool, invokeTool, listBuiltinIds, listFunctionIds, listTools, prepareTurnToolSnapshot, registerHarnessTools, registerTool, registerTools, requireTool, resetTools, } from './tools/mod.js';
22
21
  export type * from './types.js';
@@ -1,18 +1,16 @@
1
1
  /**
2
2
  * Profile, turn, tool, provider, egress, and event contracts for THEORUM.
3
3
  *
4
- * This entrypoint is type-first. Host applications import from here when they
5
- * want to declare profiles, tool schemas, provider adapters, turn requests, or
6
- * trace-safe event handlers without importing provider implementations.
7
- *
8
4
  * @module
9
5
  */
10
6
  import "../../_dnt.polyfills.js";
11
7
  export { compactionMeter, compactionNeeded, estimateHistoryTokens, HISTORY_MEDIA_TOKENS, HISTORY_TEXT_ENCODING, resolveCompactionTokens, resolveHistoryTokens, shouldCompact, splitForCompaction, } from './engine/compaction.js';
12
8
  export { runTurn } from './engine/runner.js';
13
- export { CATALOG, clampThinkingLevel, clampThinkingLevelForApiId, getTool, listBuiltinIds, mediaKindForMime, mimeAllowed, mimeEssence, modelEntryByApiId, registerTools, requireModelSpec, resetTools, } from './registry/catalog.js';
9
+ export { runSession } from './engine/session/mod.js';
10
+ export { clampThinkingLevel, clampThinkingLevelForApiId, mediaKindForMime, mimeAllowed, mimeEssence, modelEntryByApiId, requireModelSpec, } from './registry/catalog.js';
14
11
  export { clearProfiles, defineProfile, getProfile, hasProfile, listProfiles, registerProfile, registerProfiles, } from './registry/profiles.js';
15
- export { projectProfile, resolveTurn } from './registry/resolve.js';
12
+ export { projectProfile, projectProfileObject, resolveTurn } from './registry/resolve.js';
16
13
  export { getStructured, registerStructured } from './registry/schemas.js';
17
- export { executeTool } from './registry/tools.js';
18
- export { AUTO_CONTINUE_DELAY_MS, CONTINUE_INSTRUCTION, DEFAULT_AUTO_CONTINUE, GenerationStopError, isGenerationStopError, isResumeableStop, isUserCancelledStop, shouldAutoContinue, turnStopFromClientStreamEnd, turnStopFromInteractionStatus, turnStopFromOpenRouter, } from './stop.js';
14
+ export { ATTACHMENT_ACCEPT_MIMES, COMPACTION_METERS, COMPACTION_TIMINGS, CONTROL_IDS, catalogPathFor, coerceProtocol, coerceProvider, EGRESS_ON_BLOCK, EXTRA_FIELDS, fieldMeta, isValidPair, isValidProfileProtocol, KEY_SLOTS, MEDIA_INPUT_KIND_VALUES, MEDIA_INPUT_KINDS, MEDIA_WILDCARDS, OVERFLOW_KEY_SLOTS, PROFILE_FIELDS, PROFILE_TYPE_PROTOCOLS, PROFILE_TYPES, PROTOCOL_PROVIDERS, PROTOCOLS, PROVIDERS, protocolsFor, protocolsForProfileType, providersFor, SCHEMA_ENFORCEMENTS, SPEECH_AUDIO_FORMATS, STREAM_MODES, SUMMARY_MODES, THINKING_LEVELS, TOOL_ACCESS, TOOL_LOAD_TIERS, TOOL_PERMISSION, TOOL_TYPES, TURN_STOP_KINDS, VOICE_ACCEPT_MIMES, } from './schema.js';
15
+ export { AUTO_CONTINUE_DELAY_MS, CONTINUE_INSTRUCTION, DEFAULT_AUTO_CONTINUE, GenerationStopError, isGenerationStopError, isResumeableStop, isUserCancelledStop, shouldAutoContinue, turnStopFromClientStreamEnd, turnStopFromInteractionStatus, turnStopFromOpenAiFinishReason, } from './stop.js';
16
+ export { formatToolResult, getTool, hasTool, invokeTool, listBuiltinIds, listFunctionIds, listTools, prepareTurnToolSnapshot, registerHarnessTools, registerTool, registerTools, requireTool, resetTools, } from './tools/mod.js';
@@ -1,7 +1,9 @@
1
- import type { MediaLimits, Profile, TurnBlob } from '../types.js';
1
+ import type { MediaLimits, MimeInputs, Profile, TurnBlob } from '../types.js';
2
2
  declare function tooManyFilesMessage(maxFiles: number): string;
3
3
  declare function fileTooLargeMessage(maxBytes: number): string;
4
4
  declare function turnTooLargeMessage(maxTurnBytes: number): string;
5
+ declare function resolveMediaLimits(inputs: MimeInputs): MediaLimits | undefined;
6
+ declare function maxBytesForMime(mimeType: string, limits: MediaLimits): number;
5
7
  declare function requireMediaLimits(profile: Profile): MediaLimits;
6
8
  declare function sanitizeCsvText(text: string): string;
7
9
  declare function assertAttachmentLimits(blobs: TurnBlob[], limits: MediaLimits): void;
@@ -13,4 +15,4 @@ declare function sanitizeTurnBlobsForProfile(profileId: string, attachments: Tur
13
15
  attachments?: TurnBlob[];
14
16
  voice?: TurnBlob[];
15
17
  };
16
- export { assertAttachmentLimits, fileTooLargeMessage, requireMediaLimits, sanitizeCsvText, sanitizeTurnBlobs, sanitizeTurnBlobsForProfile, tooManyFilesMessage, turnTooLargeMessage, };
18
+ export { assertAttachmentLimits, fileTooLargeMessage, maxBytesForMime, requireMediaLimits, resolveMediaLimits, sanitizeCsvText, sanitizeTurnBlobs, sanitizeTurnBlobsForProfile, tooManyFilesMessage, turnTooLargeMessage, };
@@ -25,7 +25,7 @@ function fileTooLargeMessage(maxBytes) {
25
25
  function turnTooLargeMessage(maxTurnBytes) {
26
26
  return `Those files together are too large for one message (${formatMb(maxTurnBytes)} max).`;
27
27
  }
28
- function mediaLimits(inputs) {
28
+ function resolveMediaLimits(inputs) {
29
29
  const { maxFiles, maxBytes, maxTurnBytes, limitsByMime } = inputs;
30
30
  if (maxFiles && maxBytes && maxTurnBytes) {
31
31
  return { maxFiles, maxBytes, maxTurnBytes, limitsByMime };
@@ -47,7 +47,10 @@ function maxBytesForMime(mimeType, limits) {
47
47
  return limits.maxBytes;
48
48
  }
49
49
  function requireMediaLimits(profile) {
50
- const limits = mediaLimits(profile.inputs);
50
+ if (profile.type === 'speech') {
51
+ throw new TheorumError(`Profile ${profile.id} (speech) does not accept media input`);
52
+ }
53
+ const limits = resolveMediaLimits(profile.inputs ?? {});
51
54
  if (!limits) {
52
55
  throw new TheorumError(`Profile ${profile.id} must set maxFiles, maxBytes, and maxTurnBytes`);
53
56
  }
@@ -153,4 +156,4 @@ function sanitizeTurnBlobsForProfile(profileId, attachments, voice) {
153
156
  const limits = requireMediaLimits(getProfile(profileId));
154
157
  return sanitizeTurnBlobs(attachments, voice, limits);
155
158
  }
156
- export { assertAttachmentLimits, fileTooLargeMessage, requireMediaLimits, sanitizeCsvText, sanitizeTurnBlobs, sanitizeTurnBlobsForProfile, tooManyFilesMessage, turnTooLargeMessage, };
159
+ export { assertAttachmentLimits, fileTooLargeMessage, maxBytesForMime, requireMediaLimits, resolveMediaLimits, sanitizeCsvText, sanitizeTurnBlobs, sanitizeTurnBlobsForProfile, tooManyFilesMessage, turnTooLargeMessage, };
@@ -1,22 +1,9 @@
1
1
  /**
2
- * Tool catalog and MIME helpers.
3
- *
4
- * Model wire metadata is host-owned on `profile.model.config`. This module only
5
- * keeps builtin/custom tool descriptors and shared MIME utilities.
2
+ * MIME helpers and model spec utilities.
6
3
  *
7
4
  * @module
8
5
  */
9
- import type { BuiltinToolId, Catalog, MediaInputKind, ModelId, ModelSpec, Profile, ThinkingLevel, ToolCatalogEntry, ToolId } from '../types.js';
10
- /** Live tool catalog. Starts with harness tools; presets/hosts register more. */
11
- declare const CATALOG: Catalog;
12
- /** Register or replace tool descriptors (idempotent per id). */
13
- declare function registerTools(entries: Record<string, ToolCatalogEntry>): void;
14
- /** Look up one registered tool descriptor. */
15
- declare function getTool(id: ToolId): ToolCatalogEntry | undefined;
16
- /** Ids of all registered provider builtins. */
17
- declare function listBuiltinIds(): BuiltinToolId[];
18
- /** Restore harness-only tools (tests / host reloads). */
19
- declare function resetTools(): void;
6
+ import type { MediaInputKind, ModelId, ModelSpec, Profile, ThinkingLevel } from '../types.js';
20
7
  declare function mimeEssence(mime: string): string;
21
8
  declare function mimeAllowed(accept: string[], mime: string): boolean;
22
9
  declare function mediaKindForMime(mime: string): MediaInputKind | undefined;
@@ -28,4 +15,4 @@ declare function clampThinkingLevel(spec: ModelSpec, level: ThinkingLevel): Thin
28
15
  declare function modelEntryByApiId(specs: Record<string, ModelSpec>, apiId: string): ModelSpec | undefined;
29
16
  /** Clamp thinking level using a provider-native API id within a host specs map. */
30
17
  declare function clampThinkingLevelForApiId(specs: Record<string, ModelSpec>, apiId: string, level: ThinkingLevel): ThinkingLevel;
31
- export { CATALOG, clampThinkingLevel, clampThinkingLevelForApiId, getTool, listBuiltinIds, mediaKindForMime, mimeAllowed, mimeEssence, modelEntryByApiId, registerTools, requireModelSpec, resetTools, };
18
+ export { clampThinkingLevel, clampThinkingLevelForApiId, mediaKindForMime, mimeAllowed, mimeEssence, modelEntryByApiId, requireModelSpec, };
@@ -1,86 +1,10 @@
1
1
  /**
2
- * Tool catalog and MIME helpers.
3
- *
4
- * Model wire metadata is host-owned on `profile.model.config`. This module only
5
- * keeps builtin/custom tool descriptors and shared MIME utilities.
2
+ * MIME helpers and model spec utilities.
6
3
  *
7
4
  * @module
8
5
  */
9
6
  import { TheorumError } from '../../guardrails/error.js';
10
- const ASK_USER_SCHEMA = {
11
- type: 'object',
12
- properties: {
13
- kind: { type: 'string', enum: ['confirm', 'choice', 'text'] },
14
- prompt: { type: 'string' },
15
- options: { type: 'array', items: { type: 'string' } },
16
- },
17
- required: ['kind', 'prompt'],
18
- };
19
- /** Harness tools that always ship with THEORUM. */
20
- const HARNESS_TOOLS = {
21
- askUser: { kind: 'custom', ui: true, schema: ASK_USER_SCHEMA },
22
- };
23
- /** Live tool catalog. Starts with harness tools; presets/hosts register more. */
24
- const CATALOG = {
25
- tools: { ...HARNESS_TOOLS },
26
- };
27
- /** Register or replace tool descriptors (idempotent per id). */
28
- function registerTools(entries) {
29
- Object.assign(CATALOG.tools, entries);
30
- }
31
- /** Look up one registered tool descriptor. */
32
- function getTool(id) {
33
- return CATALOG.tools[id];
34
- }
35
- /** Ids of all registered provider builtins. */
36
- function listBuiltinIds() {
37
- return Object.entries(CATALOG.tools)
38
- .filter(([, entry]) => entry.kind === 'builtin')
39
- .map(([id]) => id);
40
- }
41
- /** Restore harness-only tools (tests / host reloads). */
42
- function resetTools() {
43
- for (const id of Object.keys(CATALOG.tools)) {
44
- delete CATALOG.tools[id];
45
- }
46
- Object.assign(CATALOG.tools, HARNESS_TOOLS);
47
- }
48
- /** MIME essence → normalized media part category (shared ingress map). */
49
- const MEDIA_INPUT_KINDS = {
50
- 'image/png': 'image',
51
- 'image/jpeg': 'image',
52
- 'image/jpg': 'image',
53
- 'image/webp': 'image',
54
- 'image/heic': 'image',
55
- 'image/heif': 'image',
56
- 'audio/wav': 'audio',
57
- 'audio/x-wav': 'audio',
58
- 'audio/mpeg': 'audio',
59
- 'audio/mp3': 'audio',
60
- 'audio/aiff': 'audio',
61
- 'audio/aac': 'audio',
62
- 'audio/ogg': 'audio',
63
- 'audio/flac': 'audio',
64
- 'audio/webm': 'audio',
65
- 'audio/mp4': 'audio',
66
- 'audio/pcm': 'audio',
67
- 'video/mp4': 'video',
68
- 'video/mpeg': 'video',
69
- 'video/quicktime': 'video',
70
- 'video/x-msvideo': 'video',
71
- 'video/x-flv': 'video',
72
- 'video/mpg': 'video',
73
- 'video/webm': 'video',
74
- 'video/wmv': 'video',
75
- 'video/x-ms-wmv': 'video',
76
- 'video/3gpp': 'video',
77
- 'application/pdf': 'document',
78
- 'text/plain': 'document',
79
- 'text/csv': 'document',
80
- 'text/markdown': 'document',
81
- 'text/html': 'document',
82
- 'application/json': 'document',
83
- };
7
+ import { MEDIA_INPUT_KINDS } from '../schema.js';
84
8
  function mimeEssence(mime) {
85
9
  const [base] = mime.split(';');
86
10
  return (base ?? '').trim().toLowerCase();
@@ -113,8 +37,8 @@ function clampLevels(entry, level) {
113
37
  if (entry.thinkingLevels.includes(level)) {
114
38
  return level;
115
39
  }
116
- const fallback = entry.thinking.off;
117
- if (entry.thinkingLevels.includes(fallback)) {
40
+ const fallback = entry.thinking?.off;
41
+ if (fallback && entry.thinkingLevels.includes(fallback)) {
118
42
  return fallback;
119
43
  }
120
44
  const first = entry.thinkingLevels[0];
@@ -132,4 +56,4 @@ function modelEntryByApiId(specs, apiId) {
132
56
  function clampThinkingLevelForApiId(specs, apiId, level) {
133
57
  return clampLevels(modelEntryByApiId(specs, apiId), level);
134
58
  }
135
- export { CATALOG, clampThinkingLevel, clampThinkingLevelForApiId, getTool, listBuiltinIds, mediaKindForMime, mimeAllowed, mimeEssence, modelEntryByApiId, registerTools, requireModelSpec, resetTools, };
59
+ export { clampThinkingLevel, clampThinkingLevelForApiId, mediaKindForMime, mimeAllowed, mimeEssence, modelEntryByApiId, requireModelSpec, };
@@ -5,9 +5,14 @@
5
5
  *
6
6
  * @module
7
7
  */
8
- import type { BuiltinToolId, ImageResponseFormat, InteractionPart, ModelId, Profile, TurnRequest } from '../types.js';
8
+ import type { ImageResponseFormat, InteractionPart, ModelId, Profile, TurnRequest } from '../types.js';
9
+ /**
10
+ * Provider wire formats (JSON schema, image, speech) are mutually exclusive.
11
+ * Typed profiles make illegal mixes unrepresentable; this remains a safety net
12
+ * for responseFormat structured on text vs accidental dual modes.
13
+ */
14
+ declare function assertOutputMode(profile: Profile, structuredId: string | null): void;
9
15
  declare function assertSpeechRole(profile: Profile): void;
10
- declare function resolveImageFormat(profile: Profile, _model: ModelId, slots?: Record<string, string>): ImageResponseFormat | null;
16
+ declare function resolveImageFormat(profile: Profile): ImageResponseFormat | null;
11
17
  declare function resolveInputParts(profile: Profile, model: ModelId, req: TurnRequest): InteractionPart[];
12
- declare function assertImageGrounding(profile: Profile, model: ModelId, builtins: BuiltinToolId[]): void;
13
- export { assertImageGrounding, assertSpeechRole, resolveImageFormat, resolveInputParts };
18
+ export { assertOutputMode, assertSpeechRole, resolveImageFormat, resolveInputParts };