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
@@ -0,0 +1,576 @@
1
+ /**
2
+ * Shared type contracts for THEORUM profiles, turns, provider adapters, tools,
3
+ * guardrails, and stream events.
4
+ *
5
+ * Import from `jsr:@theorum/core/kernel` or `theorum/kernel` when a host app needs types without
6
+ * importing provider implementations.
7
+ *
8
+ * @module
9
+ */
10
+
11
+ /** Model reasoning effort level normalized across provider adapters. */
12
+ export type ThinkingLevel = 'none' | 'minimal' | 'low' | 'medium' | 'high' | 'xhigh' | 'max';
13
+
14
+ /** Any host-declared model id. */
15
+ export type ModelId = string;
16
+
17
+ /** Provider-projected builtin tool id (registered by presets/adapters). */
18
+ export type BuiltinToolId = string;
19
+ /** Harness custom tool that ships with THEORUM. */
20
+ export type HarnessToolId = 'askUser';
21
+ /** Host-owned or harness custom tool id. */
22
+ export type CustomToolId = HarnessToolId | (string & {});
23
+ /** Any tool id accepted by profile allowlists and per-turn gates. */
24
+ export type ToolId = BuiltinToolId | CustomToolId;
25
+
26
+ /** Id of a host-registered structured output schema. */
27
+ export type StructuredSchemaId = string;
28
+
29
+ /** Interactions inline part types Gemini accepts besides text. */
30
+ export type GeminiInputKind = 'image' | 'audio' | 'video' | 'document';
31
+
32
+ /** Host-owned profile identifier. */
33
+ export type ProfileId = string;
34
+
35
+ /** Named Gemini key bucket used by host-provided transports. */
36
+ export type GeminiBucket = 'freeA' | 'freeB' | 'freeC' | 'paid';
37
+ /** Gemini bucket that may overflow to the paid bucket after quota backoff. */
38
+ export type GeminiFreeBucket = Exclude<GeminiBucket, 'paid'>;
39
+
40
+ /** Message role accepted by provider history mappers. */
41
+ export type ChatRole = 'system' | 'user' | 'assistant';
42
+ /** Profile-level control a caller may toggle at turn time. */
43
+ export type ControlId = 'thinking';
44
+
45
+ /**
46
+ * Image-role output pins owned by the host profile.
47
+ * The image model itself lives in `model.allow` / `model.config`.
48
+ * Aspect/size/mime values are host strings (presets/apps own the vocabularies).
49
+ */
50
+ export interface ProfileImageSpec {
51
+ /** Default aspect ratio when the turn does not set `slots.aspectRatio`. */
52
+ aspectRatio?: string;
53
+ /** Default size / resolution when the turn does not set `slots.size`. */
54
+ size?: string;
55
+ /** Output MIME for generated images. */
56
+ mimeType?: string;
57
+ /** When false, grounding builtins are rejected on this profile. */
58
+ allowsGrounding?: boolean;
59
+ /** Cap on reference images in one turn. */
60
+ maxInputImages?: number;
61
+ }
62
+
63
+ /** Public event types emitted by `runTurn` and provider adapters. */
64
+ export type TurnEventType =
65
+ | 'thought'
66
+ | 'text'
67
+ | 'tool'
68
+ | 'structured'
69
+ | 'media'
70
+ | 'grounding'
71
+ | 'evidence'
72
+ | 'tokens'
73
+ | 'done'
74
+ | 'error';
75
+
76
+ /** Provider thinking levels used when a boolean thinking control is on or off. */
77
+ export interface ThinkingMap {
78
+ on: ThinkingLevel;
79
+ off: ThinkingLevel;
80
+ }
81
+
82
+ /** Provider summary behavior used when a boolean thinking control is on or off. */
83
+ export interface SummaryMap {
84
+ on: 'auto' | 'none';
85
+ off: 'auto' | 'none';
86
+ }
87
+
88
+ /** Host-declared metadata THEORUM needs to call a model safely. */
89
+ export interface ModelSpec {
90
+ apiId: string;
91
+ /** Provider-native id for OpenRouter-compatible gateways. Defaults to `google/${apiId}`. */
92
+ openRouterId?: string;
93
+ thinking: ThinkingMap;
94
+ /** Levels this model accepts. Illegal values are clamped via `thinkingLevels`. */
95
+ thinkingLevels: ThinkingLevel[];
96
+ summaries: SummaryMap;
97
+ maxOutputTokens: number;
98
+ temperature: number;
99
+ /**
100
+ * Builtins that may use `profile.model.key`.
101
+ * Any other enabled builtin selects the overflow vault slot (`paid`).
102
+ * Host-owned policy — THEORUM does not infer tool pricing.
103
+ */
104
+ keyBuiltins: BuiltinToolId[];
105
+ /**
106
+ * Optional vault slot for this model. When set, overrides `profile.model.key`
107
+ * (and builtin routing). Host-owned — e.g. pin image models to `paid`.
108
+ */
109
+ key?: GeminiBucket;
110
+ }
111
+
112
+ /** Static metadata for harness, preset, and host-registered tools. */
113
+ export interface ToolCatalogEntry {
114
+ kind: 'builtin' | 'custom';
115
+ ui: boolean;
116
+ schema?: Record<string, unknown>;
117
+ /** Interactions API `tools[].type` when this builtin is projected. */
118
+ interactionsType?: string;
119
+ /** OpenRouter plugin id enabled when this builtin is on. */
120
+ openRouterPlugin?: string;
121
+ /** Drop this builtin when any listed sibling builtin is also requested. */
122
+ conflictsWith?: ToolId[];
123
+ }
124
+
125
+ /** Host-registered structured output schema and enforcement mode. */
126
+ export interface StructuredSpec {
127
+ enforced: 'responseFormat' | 'prompt';
128
+ jsonSchema?: Record<string, unknown>;
129
+ }
130
+
131
+ /** In-memory tool catalog shape. */
132
+ export interface Catalog {
133
+ tools: Record<ToolId, ToolCatalogEntry>;
134
+ }
135
+
136
+ /** Per-turn file, byte, and MIME-specific input limits. */
137
+ export interface MediaLimits {
138
+ maxFiles: number;
139
+ maxBytes: number;
140
+ maxTurnBytes: number;
141
+ limitsByMime?: Record<string, number>;
142
+ }
143
+
144
+ /** Input media declaration used by attachment and voice sanitizers. */
145
+ export interface MimeInputs extends Partial<MediaLimits> {
146
+ text?: boolean;
147
+ attachments?: { accept: string[] };
148
+ voice?: { accept: string[] };
149
+ }
150
+
151
+ /** Structured schema selector driven by an input slot. */
152
+ export interface StructuredBySlot {
153
+ by: string;
154
+ map: Record<string, string>;
155
+ fallback: string;
156
+ }
157
+
158
+ /** Result returned by a profile output validator. */
159
+ export interface ValidationResult {
160
+ isValid: boolean;
161
+ error?: string;
162
+ finding?: string;
163
+ data?: Record<string, unknown>;
164
+ }
165
+
166
+ /** Host-owned validator for structured output candidates. */
167
+ export type ProfileValidator = (
168
+ candidate: unknown,
169
+ slots?: Record<string, string>,
170
+ ) => ValidationResult | Promise<ValidationResult>;
171
+
172
+ /** Profile output validation and deterministic repair configuration. */
173
+ export interface ProfileValidationSpec {
174
+ extract?: (structured: unknown) => unknown;
175
+ validate: ProfileValidator;
176
+ maxRetries?: number;
177
+ repairGuidance?: string;
178
+ }
179
+
180
+ /**
181
+ * Audio container for speech generation output.
182
+ * - `openAi` speech (`/audio/speech`): sent as wire `response_format`.
183
+ * - `geminiInteractions`: only `pcm` (or omit). Google returns PCM; THEORUM emits WAV.
184
+ * `mp3` is rejected at resolve.
185
+ */
186
+ export type SpeechAudioFormat = 'pcm' | 'mp3';
187
+
188
+ /**
189
+ * Speech-role output pins owned by the host profile.
190
+ * The speech model itself lives in `model.allow` / `model.config`.
191
+ * Namespaced under `outputs.speech` so `voice` here is the TTS voice id,
192
+ * not ingress audio (`inputs.voice`).
193
+ */
194
+ export interface ProfileSpeechSpec {
195
+ voice?: string;
196
+ /**
197
+ * Output container. `pcm` (default) → WAV media on both transports.
198
+ * `mp3` requires `protocol: 'openAi'` speech; rejected on Interactions.
199
+ */
200
+ format?: SpeechAudioFormat;
201
+ }
202
+
203
+ /** Stream delivery controls enforced by the kernel. */
204
+ export interface ProfileStreamingSpec {
205
+ mode?: 'sse' | 'buffered';
206
+ streamThoughts?: boolean;
207
+ gateMedia?: boolean;
208
+ }
209
+
210
+ /** Context passed to a host-owned outbound disclosure guard. */
211
+ export interface EgressContext {
212
+ text: string;
213
+ canary?: string;
214
+ slots?: Record<string, string>;
215
+ profile: Profile;
216
+ role?: string;
217
+ }
218
+
219
+ /** Decision returned by an egress guard. */
220
+ export interface EgressEnforcementResult {
221
+ blocked: boolean;
222
+ text: string;
223
+ hits?: string[];
224
+ rejectionMessage?: string | null;
225
+ }
226
+
227
+ /** Function that evaluates candidate user-visible output before release. */
228
+ export type EgressEnforcer = (
229
+ context: EgressContext,
230
+ ) => EgressEnforcementResult | Promise<EgressEnforcementResult>;
231
+
232
+ /** Profile egress policy for rejection, retry, or refusal behavior. */
233
+ export interface ProfileEgressSpec {
234
+ enforce: EgressEnforcer;
235
+ onBlock?: 'reject_to_agent' | 'refuse_to_user';
236
+ maxRetries?: number;
237
+ repairGuidance?: string;
238
+ }
239
+
240
+ /** Profile guardrail switches enforced by the kernel. */
241
+ export interface ProfileGuardrailsSpec {
242
+ /** Optional daily turn quota; omitted means quota enforcement is not configured. */
243
+ quota?: { perDay: number };
244
+ canary?: boolean;
245
+ sanitizeInput?: boolean;
246
+ redactSensitive?: boolean;
247
+ egress?: ProfileEgressSpec;
248
+ }
249
+
250
+ /** Model, provider, thinking, and step bounds for a profile. */
251
+ export interface ProfileModelSpec {
252
+ protocol: 'geminiInteractions' | 'openAi';
253
+ provider: 'google' | 'openrouter';
254
+ /** Ids this profile may select. Each id must exist in `config`. */
255
+ allow: ModelId[];
256
+ /** Host-owned wire config keyed by the same ids used in `allow` / `select`. */
257
+ config: Record<ModelId, ModelSpec>;
258
+ select?: Record<string, ModelId>;
259
+ thinking?: ThinkingLevel | Record<string, ThinkingLevel>;
260
+ controls?: ControlId[];
261
+ maxSteps?: number;
262
+ key?: GeminiFreeBucket;
263
+ }
264
+
265
+ /** Text, attachment, voice, slot, and size rules for a profile. */
266
+ export interface ProfileInputsSpec {
267
+ text?: boolean;
268
+ attachments?: { accept: string[] };
269
+ voice?: { accept: string[] };
270
+ maxFiles?: number;
271
+ maxBytes?: number;
272
+ maxTurnBytes?: number;
273
+ limitsByMime?: Record<string, number>;
274
+ slots?: Record<string, string[]>;
275
+ }
276
+
277
+ /** Output schema, image, speech, validation, and stream rules for a profile. */
278
+ export interface ProfileOutputsSpec {
279
+ structured?: StructuredSchemaId | StructuredBySlot | null;
280
+ /** Pins for an image-role profile. Model id is on `model`. */
281
+ image?: ProfileImageSpec;
282
+ /** Pins for a speech-role profile (`voice` / `format`). Model id is on `model`. */
283
+ speech?: ProfileSpeechSpec;
284
+ validation?: ProfileValidationSpec;
285
+ streaming?: ProfileStreamingSpec;
286
+ }
287
+
288
+ /** Complete host-owned agent contract consumed by the kernel. */
289
+ export interface Profile {
290
+ id: ProfileId;
291
+ identity: {
292
+ handle: string;
293
+ chat?: boolean;
294
+ system?: string;
295
+ systemByRole?: Record<string, string>;
296
+ };
297
+ model: ProfileModelSpec;
298
+ tools: { allow: ToolId[] };
299
+ inputs: ProfileInputsSpec;
300
+ outputs: ProfileOutputsSpec;
301
+ guardrails: ProfileGuardrailsSpec;
302
+ }
303
+
304
+ /** Text part sent to provider adapters after input normalization. */
305
+ export interface InteractionTextPart {
306
+ type: 'text';
307
+ text: string;
308
+ }
309
+
310
+ /** Inline media part sent to provider adapters after MIME validation. */
311
+ export interface InteractionMediaPart {
312
+ type: GeminiInputKind;
313
+ mimeType: string;
314
+ data: string;
315
+ }
316
+
317
+ /** Any provider input part accepted by THEORUM's provider contract. */
318
+ export type InteractionPart = InteractionTextPart | InteractionMediaPart;
319
+
320
+ /** Native image response request passed to image-capable providers. */
321
+ export interface ImageResponseFormat {
322
+ type: 'image';
323
+ mimeType: string;
324
+ aspectRatio: string;
325
+ /** Authoring / kernel name; adapters map to provider wire keys (e.g. Google `imageSize`). */
326
+ size: string;
327
+ }
328
+
329
+ /** Base64-encoded blob supplied by a host turn request. */
330
+ export interface TurnBlob {
331
+ mimeType: string;
332
+ data: string;
333
+ }
334
+
335
+ /** Provider-neutral history message preserving text, parts, tools, and metadata. */
336
+ export interface TurnHistoryMessage {
337
+ role: 'system' | 'user' | 'assistant' | 'tool';
338
+ content?: string;
339
+ parts?: InteractionPart[];
340
+ tool_calls?: Array<{
341
+ id: string;
342
+ type: 'function';
343
+ function: { name: string; arguments: string };
344
+ thoughtSignature?: string;
345
+ }>;
346
+ tool_call_id?: string;
347
+ name?: string;
348
+ metadata?: Record<string, unknown>;
349
+ }
350
+
351
+ /** Tool visibility tier used by host dynamic-loading strategies. */
352
+ export type ToolLoadTier = 'T0' | 'T1' | 'T2';
353
+ /** Execution authorization tier for dynamic tools. */
354
+ export type ToolPermissionTier = 'auto' | 'session_consent' | 'always_confirm';
355
+
356
+ /** Context supplied to a dynamic tool authorization hook. */
357
+ export interface DynamicToolExecutionContext {
358
+ args: Record<string, unknown>;
359
+ profile: Profile;
360
+ sessionPermissions?: string[];
361
+ }
362
+
363
+ /** Context supplied to a host dynamic tool schema loader. */
364
+ export interface DynamicToolLoadContext {
365
+ name: string;
366
+ args: Record<string, unknown>;
367
+ profile: Profile;
368
+ currentTools: DynamicToolDeclaration[];
369
+ sessionPermissions?: string[];
370
+ }
371
+
372
+ /** Host function that loads more tool declarations during a turn. */
373
+ export type DynamicToolLoader = (
374
+ context: DynamicToolLoadContext,
375
+ ) => DynamicToolDeclaration[] | Promise<DynamicToolDeclaration[]>;
376
+
377
+ /** Runtime tool schema and execution policy supplied by the host app. */
378
+ export interface DynamicToolDeclaration {
379
+ name: string;
380
+ description?: string;
381
+ parameters?: Record<string, unknown>;
382
+ loadTier?: ToolLoadTier;
383
+ permissionTier?: ToolPermissionTier;
384
+ category?: string;
385
+ /** Marks this declaration as a schema-loader tool for T2 expansion. */
386
+ loadsDynamicTools?: boolean;
387
+ handler?: (args: Record<string, unknown>) => ToolEnvelope | Promise<ToolEnvelope>;
388
+ canExecute?: (
389
+ context: DynamicToolExecutionContext,
390
+ ) => boolean | Promise<boolean> | ToolEnvelope | Promise<ToolEnvelope>;
391
+ }
392
+
393
+ /** Generic repair request used for validation and egress retry turns. */
394
+ export interface TurnRepairRequest {
395
+ previousOutput: string;
396
+ rejection: string;
397
+ guidance?: string;
398
+ }
399
+
400
+ /** User, media, history, and repair payload for a turn. */
401
+ export interface TurnInput {
402
+ text?: string;
403
+ role?: string;
404
+ slots?: Record<string, string>;
405
+ attachments?: TurnBlob[];
406
+ voice?: TurnBlob[];
407
+ history?: TurnHistoryMessage[];
408
+ repair?: TurnRepairRequest;
409
+ }
410
+
411
+ /** Host request after kernel ingress normalization. */
412
+ export type NormalizedTurnRequest = TurnRequest & { input: TurnInput };
413
+
414
+ /** Host request for a single deterministic agent turn. */
415
+ export interface TurnRequest {
416
+ profile: ProfileId;
417
+ /** Caller project id when one exists. Omitted on some HTTP hosts. */
418
+ projectId?: string;
419
+ /** Google Interactions server-side conversation state. Omit for stateless/manual history. */
420
+ previousInteractionId?: string;
421
+ /** Optional Interactions storage override. Omit to let provider/project policy decide. */
422
+ store?: boolean;
423
+ select?: string;
424
+ thinking?: boolean;
425
+ /** Host-provided dynamic system prompt combined with profile persona */
426
+ system?: string;
427
+ /** Session permissions granted for this conversation turn */
428
+ sessionPermissions?: string[];
429
+ /** Opt-in gates. Profile `allow` is the ceiling; a tool is off until `tools[id]` is true. */
430
+ tools?: Partial<Record<ToolId, boolean>>;
431
+ /** Runtime tool declarations (e.g. load_when_needed strategy) */
432
+ dynamicTools?: DynamicToolDeclaration[];
433
+ /** Generic host-owned loader for T2 dynamic tool schema expansion. */
434
+ dynamicToolLoader?: DynamicToolLoader;
435
+ /** Host-owned metadata preserved for traces; the kernel does not interpret it. */
436
+ metadata?: Record<string, unknown>;
437
+ input?: TurnInput;
438
+ toolInvoke?: { name: CustomToolId; arguments: Record<string, unknown> };
439
+ }
440
+
441
+ /** Safe profile projection suitable for UI or host inspection. */
442
+ export interface ProjectedProfile {
443
+ id: string;
444
+ handle: string;
445
+ chat: boolean;
446
+ maxSteps: number;
447
+ models: ModelId[];
448
+ select: Record<string, ModelId> | null;
449
+ controls: ControlId[];
450
+ tools: Array<ToolCatalogEntry & { name: ToolId }>;
451
+ inputs: Profile['inputs'];
452
+ slots: Record<string, string[]>;
453
+ outputs: Profile['outputs'];
454
+ image?: ProfileImageSpec | null;
455
+ }
456
+
457
+ /** Provider selection and generation knobs shared before and after resolution. */
458
+ export interface ProviderGenerationConfig {
459
+ model: ModelId;
460
+ /** Provider-native model id taken from the profile model spec. */
461
+ apiId: string;
462
+ openRouterId?: string;
463
+ previousInteractionId?: string;
464
+ store?: boolean;
465
+ thinking: ThinkingLevel;
466
+ summaries: 'auto' | 'none';
467
+ maxOutputTokens: number;
468
+ temperature: number;
469
+ builtins: BuiltinToolId[];
470
+ }
471
+
472
+ /** Fully-resolved provider request state created from a `TurnRequest`. */
473
+ export interface ResolvedGeneration extends ProviderGenerationConfig {
474
+ custom: CustomToolId[];
475
+ dynamicTools?: DynamicToolDeclaration[];
476
+ dynamicToolLoader?: DynamicToolLoader;
477
+ sessionPermissions?: string[];
478
+ history?: TurnHistoryMessage[];
479
+ maxSteps: number;
480
+ structured: StructuredSchemaId | null;
481
+ image: ImageResponseFormat | null;
482
+ speech?: ProfileSpeechSpec;
483
+ input: InteractionPart[];
484
+ /**
485
+ * Gemini vault slot for Google Interactions transport only.
486
+ * Omitted for non-Google providers; never sent on the wire.
487
+ */
488
+ geminiBucket?: GeminiBucket;
489
+ canary: string;
490
+ }
491
+
492
+ /** Tool execution status returned to the model and stream. */
493
+ export type ToolStatus = 'ok' | 'error' | 'pause';
494
+
495
+ /** Structured result envelope returned by deterministic tool handlers. */
496
+ export interface ToolEnvelope {
497
+ status: ToolStatus;
498
+ finding?: string;
499
+ data?: Record<string, unknown>;
500
+ }
501
+
502
+ /** Token accounting emitted by providers or fallback estimation. */
503
+ export interface TurnTokens {
504
+ input: number;
505
+ output: number;
506
+ thinking?: number;
507
+ toolUse?: number;
508
+ total: number;
509
+ }
510
+
511
+ /** Normalized citation or place source surfaced from a provider. */
512
+ export interface GroundingSource {
513
+ title: string;
514
+ uri: string;
515
+ type: 'maps' | 'web';
516
+ }
517
+
518
+ /** Google grounding metadata normalized into a stream event. */
519
+ export interface GroundingEvent {
520
+ metadata?: Record<string, unknown>;
521
+ chunks?: unknown[];
522
+ searchHtml?: string;
523
+ sources: GroundingSource[];
524
+ }
525
+
526
+ /** Provider evidence such as OpenRouter citations or annotations. */
527
+ export interface ProviderEvidenceEvent {
528
+ provider: 'openrouter' | 'google' | string;
529
+ raw?: Record<string, unknown>;
530
+ citations?: string[];
531
+ annotations?: unknown[];
532
+ sources?: GroundingSource[];
533
+ }
534
+
535
+ /** Public event yielded by providers and by `runTurn`. */
536
+ export interface TurnEvent {
537
+ type: TurnEventType;
538
+ text?: string;
539
+ tool?: {
540
+ name: string;
541
+ arguments?: Record<string, unknown>;
542
+ result?: ToolEnvelope;
543
+ id?: string;
544
+ };
545
+ structured?: unknown;
546
+ media?: { mimeType: string; data: string };
547
+ grounding?: GroundingEvent;
548
+ evidence?: ProviderEvidenceEvent;
549
+ tokens?: TurnTokens;
550
+ interactionId?: string;
551
+ error?: string;
552
+ }
553
+
554
+ /** Provider-neutral request object sent from the kernel to a model adapter. */
555
+ export interface ProviderCompleteRequest extends ProviderGenerationConfig {
556
+ system: string;
557
+ input: InteractionPart[];
558
+ history?: TurnHistoryMessage[];
559
+ dynamicTools?: DynamicToolDeclaration[];
560
+ dynamicToolLoader?: DynamicToolLoader;
561
+ structured: StructuredSchemaId | null;
562
+ image: ImageResponseFormat | null;
563
+ speech?: ProfileSpeechSpec;
564
+ /**
565
+ * Gemini vault slot for Google Interactions transport only.
566
+ * Required when completing via Google Interactions.
567
+ */
568
+ geminiBucket?: GeminiBucket;
569
+ /** Scrubbed SSE / HTTP rows for traces. */
570
+ tapGemini?: (row: Record<string, unknown>) => void;
571
+ }
572
+
573
+ /** Minimal adapter contract every model provider must implement. */
574
+ export interface ModelProvider {
575
+ complete: (req: ProviderCompleteRequest) => AsyncIterable<TurnEvent>;
576
+ }
@@ -6,5 +6,14 @@
6
6
  *
7
7
  * @module
8
8
  */
9
- import "../../_dnt.polyfills.js";
10
- export { jsonlSink, memorySink, noopSink, resolveTraceDir, sinkFromDir, writeTrace, } from './trace.js';
9
+
10
+ export type { TraceSink } from './trace.ts';
11
+ export {
12
+ jsonlSink,
13
+ memorySink,
14
+ noopSink,
15
+ resolveTraceDir,
16
+ sinkFromDir,
17
+ writeTrace,
18
+ } from './trace.ts';
19
+ export type { TraceRecord } from './trace-record.ts';
@@ -0,0 +1,70 @@
1
+ const OMIT_INJECTION = '[omitted - injection]';
2
+ const OMIT_SENSITIVE = '[omitted -sensitive]';
3
+
4
+ type RedactKind = 'injection' | 'sensitive';
5
+
6
+ interface RedactSpan {
7
+ start: number;
8
+ end: number;
9
+ kind: RedactKind;
10
+ }
11
+
12
+ function tokenFor(kind: RedactKind): string {
13
+ if (kind === 'injection') {
14
+ return OMIT_INJECTION;
15
+ }
16
+ return OMIT_SENSITIVE;
17
+ }
18
+
19
+ function blobAt(match: RegExpMatchArray): { blob: string; index: number } | undefined {
20
+ const [blob] = match;
21
+ const { index } = match;
22
+ if (blob && index !== undefined) {
23
+ return { blob, index };
24
+ }
25
+ return undefined;
26
+ }
27
+
28
+ function mergeSpans(spans: RedactSpan[]): RedactSpan[] {
29
+ const sorted = [...spans].sort((left, right) => left.start - right.start || right.end - left.end);
30
+ const out: RedactSpan[] = [];
31
+ for (const span of sorted) {
32
+ if (span.end > span.start) {
33
+ const last = out.at(-1);
34
+ if (!last || span.start >= last.end) {
35
+ out.push(span);
36
+ } else if (span.end > last.end) {
37
+ last.end = span.end;
38
+ }
39
+ }
40
+ }
41
+ return out;
42
+ }
43
+
44
+ function applySpans(text: string, spans: RedactSpan[]): string {
45
+ let out = text;
46
+ const merged = mergeSpans(spans);
47
+ for (let i = merged.length - 1; i >= 0; i -= 1) {
48
+ const span = merged[i];
49
+ if (span) {
50
+ out = out.slice(0, span.start) + tokenFor(span.kind) + out.slice(span.end);
51
+ }
52
+ }
53
+ return out;
54
+ }
55
+
56
+ function spansFromPatterns(text: string, patterns: RegExp[], kind: RedactKind): RedactSpan[] {
57
+ const spans: RedactSpan[] = [];
58
+ for (const pattern of patterns) {
59
+ for (const match of text.matchAll(pattern)) {
60
+ const found = blobAt(match);
61
+ if (found) {
62
+ spans.push({ start: found.index, end: found.index + found.blob.length, kind });
63
+ }
64
+ }
65
+ }
66
+ return spans;
67
+ }
68
+
69
+ export type { RedactKind, RedactSpan };
70
+ export { applySpans, blobAt, OMIT_INJECTION, OMIT_SENSITIVE, spansFromPatterns };