theorum 0.1.2
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/LICENSE +21 -0
- package/README.md +338 -0
- package/docs/AGENT_PROFILE_CONTRACT.md +161 -0
- package/docs/CLI_SPEC.md +183 -0
- package/docs/SECRETS.md +55 -0
- package/esm/_dnt.polyfills.d.ts +11 -0
- package/esm/_dnt.polyfills.js +15 -0
- package/esm/_dnt.shims.d.ts +5 -0
- package/esm/_dnt.shims.js +61 -0
- package/esm/mod.d.ts +37 -0
- package/esm/mod.js +35 -0
- package/esm/package.json +3 -0
- package/esm/src/guardrails/error.d.ts +35 -0
- package/esm/src/guardrails/error.js +116 -0
- package/esm/src/guardrails/injection.d.ts +12 -0
- package/esm/src/guardrails/injection.js +220 -0
- package/esm/src/guardrails/keys.d.ts +12 -0
- package/esm/src/guardrails/keys.js +132 -0
- package/esm/src/guardrails/mod.d.ts +14 -0
- package/esm/src/guardrails/mod.js +14 -0
- package/esm/src/guardrails/sanitize.d.ts +22 -0
- package/esm/src/guardrails/sanitize.js +133 -0
- package/esm/src/guardrails/sensitive.d.ts +12 -0
- package/esm/src/guardrails/sensitive.js +88 -0
- package/esm/src/kernel/engine/boundary.d.ts +10 -0
- package/esm/src/kernel/engine/boundary.js +55 -0
- package/esm/src/kernel/engine/delta.d.ts +8 -0
- package/esm/src/kernel/engine/delta.js +362 -0
- package/esm/src/kernel/engine/hash.d.ts +1 -0
- package/esm/src/kernel/engine/hash.js +9 -0
- package/esm/src/kernel/engine/record.d.ts +2 -0
- package/esm/src/kernel/engine/record.js +7 -0
- package/esm/src/kernel/engine/repair.d.ts +9 -0
- package/esm/src/kernel/engine/repair.js +38 -0
- package/esm/src/kernel/engine/runner.d.ts +14 -0
- package/esm/src/kernel/engine/runner.js +731 -0
- package/esm/src/kernel/engine/tree.d.ts +2 -0
- package/esm/src/kernel/engine/tree.js +17 -0
- package/esm/src/kernel/mod.d.ts +16 -0
- package/esm/src/kernel/mod.js +15 -0
- package/esm/src/kernel/registry/catalog.d.ts +24 -0
- package/esm/src/kernel/registry/catalog.js +213 -0
- package/esm/src/kernel/registry/profiles.d.ts +36 -0
- package/esm/src/kernel/registry/profiles.js +111 -0
- package/esm/src/kernel/registry/resolve.d.ts +20 -0
- package/esm/src/kernel/registry/resolve.js +235 -0
- package/esm/src/kernel/registry/schemas.d.ts +14 -0
- package/esm/src/kernel/registry/schemas.js +23 -0
- package/esm/src/kernel/registry/tools.d.ts +12 -0
- package/esm/src/kernel/registry/tools.js +36 -0
- package/esm/src/kernel/types.d.ts +497 -0
- package/esm/src/kernel/types.js +10 -0
- package/esm/src/observability/mod.d.ts +12 -0
- package/esm/src/observability/mod.js +10 -0
- package/esm/src/observability/spans.d.ts +16 -0
- package/esm/src/observability/spans.js +56 -0
- package/esm/src/observability/trace-attach.d.ts +16 -0
- package/esm/src/observability/trace-attach.js +81 -0
- package/esm/src/observability/trace-record.d.ts +112 -0
- package/esm/src/observability/trace-record.js +140 -0
- package/esm/src/observability/trace-usage.d.ts +3 -0
- package/esm/src/observability/trace-usage.js +32 -0
- package/esm/src/observability/trace.d.ts +23 -0
- package/esm/src/observability/trace.js +121 -0
- package/esm/src/providers/attachments.d.ts +17 -0
- package/esm/src/providers/attachments.js +156 -0
- package/esm/src/providers/gemini-tape.d.ts +3 -0
- package/esm/src/providers/gemini-tape.js +46 -0
- package/esm/src/providers/google-tap.d.ts +3 -0
- package/esm/src/providers/google-tap.js +48 -0
- package/esm/src/providers/interactions.d.ts +5 -0
- package/esm/src/providers/interactions.js +127 -0
- package/esm/src/providers/media.d.ts +5 -0
- package/esm/src/providers/media.js +125 -0
- package/esm/src/providers/mod.d.ts +15 -0
- package/esm/src/providers/mod.js +13 -0
- package/esm/src/providers/openrouter-payload.d.ts +24 -0
- package/esm/src/providers/openrouter-payload.js +177 -0
- package/esm/src/providers/openrouter.d.ts +17 -0
- package/esm/src/providers/openrouter.js +332 -0
- package/esm/src/providers/provider.d.ts +13 -0
- package/esm/src/providers/provider.js +123 -0
- package/esm/src/providers/sse.d.ts +7 -0
- package/esm/src/providers/sse.js +53 -0
- package/esm/src/providers/tts.d.ts +24 -0
- package/esm/src/providers/tts.js +144 -0
- package/package.json +48 -0
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
function mapStrings(value, map) {
|
|
2
|
+
if (typeof value === 'string') {
|
|
3
|
+
return map(value);
|
|
4
|
+
}
|
|
5
|
+
if (Array.isArray(value)) {
|
|
6
|
+
return value.map((item) => mapStrings(item, map));
|
|
7
|
+
}
|
|
8
|
+
if (value && typeof value === 'object') {
|
|
9
|
+
const out = {};
|
|
10
|
+
for (const [key, nested] of Object.entries(value)) {
|
|
11
|
+
out[key] = mapStrings(nested, map);
|
|
12
|
+
}
|
|
13
|
+
return out;
|
|
14
|
+
}
|
|
15
|
+
return value;
|
|
16
|
+
}
|
|
17
|
+
export { mapStrings };
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Profile, turn, tool, provider, egress, and event contracts for THEORUM.
|
|
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
|
+
* @module
|
|
9
|
+
*/
|
|
10
|
+
import "../../_dnt.polyfills.js";
|
|
11
|
+
export { runTurn } from './engine/runner.js';
|
|
12
|
+
export { defineProfile, getProfile, hasProfile, listProfiles, registerProfile, registerProfiles, } from './registry/profiles.js';
|
|
13
|
+
export { projectProfile, resolveTurn } from './registry/resolve.js';
|
|
14
|
+
export { getStructured, registerStructured } from './registry/schemas.js';
|
|
15
|
+
export { executeTool } from './registry/tools.js';
|
|
16
|
+
export type * from './types.js';
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Profile, turn, tool, provider, egress, and event contracts for THEORUM.
|
|
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
|
+
* @module
|
|
9
|
+
*/
|
|
10
|
+
import "../../_dnt.polyfills.js";
|
|
11
|
+
export { runTurn } from './engine/runner.js';
|
|
12
|
+
export { defineProfile, getProfile, hasProfile, listProfiles, registerProfile, registerProfiles, } from './registry/profiles.js';
|
|
13
|
+
export { projectProfile, resolveTurn } from './registry/resolve.js';
|
|
14
|
+
export { getStructured, registerStructured } from './registry/schemas.js';
|
|
15
|
+
export { executeTool } from './registry/tools.js';
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
import type { Catalog, GeminiInputKind, ImageAspectRatio, ImageSize, ModelCatalogEntry, ThinkingLevel } from '../types.js';
|
|
2
|
+
declare const IMAGE_INPUT_MIMES: string[];
|
|
3
|
+
declare const VOICE_INPUT_MIMES: string[];
|
|
4
|
+
/** Default chat media caps. Host profiles may copy or override these limits. */
|
|
5
|
+
declare const CHAT_MEDIA_LIMITS: {
|
|
6
|
+
readonly maxFiles: 10;
|
|
7
|
+
readonly maxBytes: number;
|
|
8
|
+
readonly maxTurnBytes: number;
|
|
9
|
+
};
|
|
10
|
+
/** Gemini Interactions inline MIME → part type. Profiles allowlist from this set. */
|
|
11
|
+
declare const GEMINI_INPUT_KINDS: Record<string, GeminiInputKind>;
|
|
12
|
+
declare function mimeEssence(mime: string): string;
|
|
13
|
+
declare function mimeAllowed(accept: string[], mime: string): boolean;
|
|
14
|
+
declare function geminiKindForMime(mime: string): GeminiInputKind | undefined;
|
|
15
|
+
declare const IMAGE_FLASH_LITE_ASPECT_RATIOS: ImageAspectRatio[];
|
|
16
|
+
declare const IMAGE_FLASH_LITE_SIZES: ImageSize[];
|
|
17
|
+
declare const CATALOG: Catalog;
|
|
18
|
+
export { CATALOG, CHAT_MEDIA_LIMITS, GEMINI_INPUT_KINDS, geminiKindForMime, IMAGE_FLASH_LITE_ASPECT_RATIOS, IMAGE_FLASH_LITE_SIZES, IMAGE_INPUT_MIMES, mimeAllowed, mimeEssence, VOICE_INPUT_MIMES, };
|
|
19
|
+
export declare const MODEL_CATALOG: Record<import("../types.js").ModelId, ModelCatalogEntry>;
|
|
20
|
+
export declare function modelEntry(modelId: string): ModelCatalogEntry;
|
|
21
|
+
/** Clamp a requested thinking level to what the selected model accepts. */
|
|
22
|
+
export declare function clampThinkingLevel(modelId: string, level: ThinkingLevel): ThinkingLevel;
|
|
23
|
+
export declare function modelEntryByApiId(apiId: string): ModelCatalogEntry | undefined;
|
|
24
|
+
export declare function clampThinkingLevelForApiId(apiId: string, level: ThinkingLevel): ThinkingLevel;
|
|
@@ -0,0 +1,213 @@
|
|
|
1
|
+
const ASK_USER_SCHEMA = {
|
|
2
|
+
type: 'object',
|
|
3
|
+
properties: {
|
|
4
|
+
kind: { type: 'string', enum: ['confirm', 'choice', 'text'] },
|
|
5
|
+
prompt: { type: 'string' },
|
|
6
|
+
options: { type: 'array', items: { type: 'string' } },
|
|
7
|
+
},
|
|
8
|
+
required: ['kind', 'prompt'],
|
|
9
|
+
};
|
|
10
|
+
const DEFAULT_TEMPERATURE = 1;
|
|
11
|
+
const FLASH_LITE_MAX_OUTPUT_TOKENS = 8192;
|
|
12
|
+
const PRO_PREVIEW_MAX_OUTPUT_TOKENS = 64_000;
|
|
13
|
+
const IMAGE_FLASH_LITE_MAX_OUTPUT_TOKENS = 4096;
|
|
14
|
+
const TTS_FLASH_MAX_OUTPUT_TOKENS = 2048;
|
|
15
|
+
const SONAR_MAX_OUTPUT_TOKENS = 8192;
|
|
16
|
+
const IMAGE_INPUT_MIMES = ['image/png', 'image/jpeg', 'image/webp', 'image/heic', 'image/heif'];
|
|
17
|
+
const VOICE_INPUT_MIMES = ['audio/webm', 'audio/wav', 'audio/mpeg', 'audio/mp4'];
|
|
18
|
+
const KIB = 1024;
|
|
19
|
+
const MIB = KIB * KIB;
|
|
20
|
+
/** Default chat media caps. Host profiles may copy or override these limits. */
|
|
21
|
+
const CHAT_MEDIA_LIMITS = {
|
|
22
|
+
maxFiles: 10,
|
|
23
|
+
maxBytes: 8 * MIB,
|
|
24
|
+
maxTurnBytes: 32 * MIB,
|
|
25
|
+
};
|
|
26
|
+
/** Gemini Interactions inline MIME → part type. Profiles allowlist from this set. */
|
|
27
|
+
const GEMINI_INPUT_KINDS = {
|
|
28
|
+
'image/png': 'image',
|
|
29
|
+
'image/jpeg': 'image',
|
|
30
|
+
'image/jpg': 'image',
|
|
31
|
+
'image/webp': 'image',
|
|
32
|
+
'image/heic': 'image',
|
|
33
|
+
'image/heif': 'image',
|
|
34
|
+
'audio/wav': 'audio',
|
|
35
|
+
'audio/x-wav': 'audio',
|
|
36
|
+
'audio/mpeg': 'audio',
|
|
37
|
+
'audio/mp3': 'audio',
|
|
38
|
+
'audio/aiff': 'audio',
|
|
39
|
+
'audio/aac': 'audio',
|
|
40
|
+
'audio/ogg': 'audio',
|
|
41
|
+
'audio/flac': 'audio',
|
|
42
|
+
'audio/webm': 'audio',
|
|
43
|
+
'audio/mp4': 'audio',
|
|
44
|
+
'audio/pcm': 'audio',
|
|
45
|
+
'video/mp4': 'video',
|
|
46
|
+
'video/mpeg': 'video',
|
|
47
|
+
'video/quicktime': 'video',
|
|
48
|
+
'video/x-msvideo': 'video',
|
|
49
|
+
'video/x-flv': 'video',
|
|
50
|
+
'video/mpg': 'video',
|
|
51
|
+
'video/webm': 'video',
|
|
52
|
+
'video/wmv': 'video',
|
|
53
|
+
'video/x-ms-wmv': 'video',
|
|
54
|
+
'video/3gpp': 'video',
|
|
55
|
+
'application/pdf': 'document',
|
|
56
|
+
'text/plain': 'document',
|
|
57
|
+
'text/csv': 'document',
|
|
58
|
+
'text/markdown': 'document',
|
|
59
|
+
'text/html': 'document',
|
|
60
|
+
'application/json': 'document',
|
|
61
|
+
};
|
|
62
|
+
function mimeEssence(mime) {
|
|
63
|
+
const [base] = mime.split(';');
|
|
64
|
+
return (base ?? '').trim().toLowerCase();
|
|
65
|
+
}
|
|
66
|
+
function mimeAllowed(accept, mime) {
|
|
67
|
+
const actual = mimeEssence(mime);
|
|
68
|
+
return accept.some((rule) => {
|
|
69
|
+
const allowed = mimeEssence(rule);
|
|
70
|
+
if (allowed.endsWith('/*')) {
|
|
71
|
+
return actual.startsWith(allowed.slice(0, -1));
|
|
72
|
+
}
|
|
73
|
+
return allowed === actual;
|
|
74
|
+
});
|
|
75
|
+
}
|
|
76
|
+
function geminiKindForMime(mime) {
|
|
77
|
+
return GEMINI_INPUT_KINDS[mimeEssence(mime)];
|
|
78
|
+
}
|
|
79
|
+
const IMAGE_FLASH_LITE_ASPECT_RATIOS = [
|
|
80
|
+
'1:1',
|
|
81
|
+
'3:2',
|
|
82
|
+
'2:3',
|
|
83
|
+
'3:4',
|
|
84
|
+
'4:3',
|
|
85
|
+
'4:5',
|
|
86
|
+
'5:4',
|
|
87
|
+
'9:16',
|
|
88
|
+
'16:9',
|
|
89
|
+
'21:9',
|
|
90
|
+
];
|
|
91
|
+
const IMAGE_FLASH_LITE_SIZES = ['1K'];
|
|
92
|
+
const FLASH_LITE_THINKING_LEVELS = ['minimal', 'low', 'medium', 'high'];
|
|
93
|
+
const PRO_PREVIEW_THINKING_LEVELS = ['low', 'medium', 'high'];
|
|
94
|
+
const IMAGE_FLASH_LITE_THINKING_LEVELS = ['minimal', 'high'];
|
|
95
|
+
const TTS_THINKING_LEVELS = ['minimal'];
|
|
96
|
+
const OPENROUTER_SEARCH_THINKING_LEVELS = ['low', 'medium', 'high'];
|
|
97
|
+
const GENERIC_MODEL_ENTRY = {
|
|
98
|
+
apiId: '',
|
|
99
|
+
thinking: { on: 'high', off: 'low' },
|
|
100
|
+
thinkingLevels: ['low', 'medium', 'high'],
|
|
101
|
+
summaries: { on: 'auto', off: 'none' },
|
|
102
|
+
maxOutputTokens: FLASH_LITE_MAX_OUTPUT_TOKENS,
|
|
103
|
+
temperature: DEFAULT_TEMPERATURE,
|
|
104
|
+
freeBuiltins: [],
|
|
105
|
+
};
|
|
106
|
+
const CATALOG = {
|
|
107
|
+
models: {
|
|
108
|
+
gemini31FlashLite: {
|
|
109
|
+
apiId: 'gemini-3.1-flash-lite',
|
|
110
|
+
thinking: { on: 'high', off: 'minimal' },
|
|
111
|
+
thinkingLevels: FLASH_LITE_THINKING_LEVELS,
|
|
112
|
+
summaries: { on: 'auto', off: 'none' },
|
|
113
|
+
maxOutputTokens: FLASH_LITE_MAX_OUTPUT_TOKENS,
|
|
114
|
+
temperature: DEFAULT_TEMPERATURE,
|
|
115
|
+
freeBuiltins: ['googleMaps', 'urlContext'],
|
|
116
|
+
},
|
|
117
|
+
gemini31ProPreview: {
|
|
118
|
+
apiId: 'gemini-3.1-pro-preview',
|
|
119
|
+
thinking: { on: 'high', off: 'low' },
|
|
120
|
+
thinkingLevels: PRO_PREVIEW_THINKING_LEVELS,
|
|
121
|
+
summaries: { on: 'auto', off: 'none' },
|
|
122
|
+
maxOutputTokens: PRO_PREVIEW_MAX_OUTPUT_TOKENS,
|
|
123
|
+
temperature: DEFAULT_TEMPERATURE,
|
|
124
|
+
freeBuiltins: [],
|
|
125
|
+
},
|
|
126
|
+
gemini35FlashLite: {
|
|
127
|
+
apiId: 'gemini-3.5-flash-lite',
|
|
128
|
+
thinking: { on: 'high', off: 'minimal' },
|
|
129
|
+
thinkingLevels: FLASH_LITE_THINKING_LEVELS,
|
|
130
|
+
summaries: { on: 'auto', off: 'none' },
|
|
131
|
+
maxOutputTokens: FLASH_LITE_MAX_OUTPUT_TOKENS,
|
|
132
|
+
temperature: DEFAULT_TEMPERATURE,
|
|
133
|
+
freeBuiltins: ['googleMaps', 'urlContext'],
|
|
134
|
+
},
|
|
135
|
+
gemini31FlashLiteImage: {
|
|
136
|
+
apiId: 'gemini-3.1-flash-lite-image',
|
|
137
|
+
thinking: { on: 'high', off: 'minimal' },
|
|
138
|
+
thinkingLevels: IMAGE_FLASH_LITE_THINKING_LEVELS,
|
|
139
|
+
summaries: { on: 'none', off: 'none' },
|
|
140
|
+
maxOutputTokens: IMAGE_FLASH_LITE_MAX_OUTPUT_TOKENS,
|
|
141
|
+
temperature: DEFAULT_TEMPERATURE,
|
|
142
|
+
freeBuiltins: [],
|
|
143
|
+
image: {
|
|
144
|
+
maxInputImages: 14,
|
|
145
|
+
inputMimes: IMAGE_INPUT_MIMES,
|
|
146
|
+
sizes: IMAGE_FLASH_LITE_SIZES,
|
|
147
|
+
aspectRatios: IMAGE_FLASH_LITE_ASPECT_RATIOS,
|
|
148
|
+
outputMime: 'image/jpeg',
|
|
149
|
+
allowsGrounding: false,
|
|
150
|
+
},
|
|
151
|
+
},
|
|
152
|
+
gemini31FlashTts: {
|
|
153
|
+
apiId: 'gemini-3.1-flash-tts-preview',
|
|
154
|
+
thinking: { on: 'minimal', off: 'minimal' },
|
|
155
|
+
thinkingLevels: TTS_THINKING_LEVELS,
|
|
156
|
+
summaries: { on: 'none', off: 'none' },
|
|
157
|
+
maxOutputTokens: TTS_FLASH_MAX_OUTPUT_TOKENS,
|
|
158
|
+
temperature: DEFAULT_TEMPERATURE,
|
|
159
|
+
freeBuiltins: [],
|
|
160
|
+
},
|
|
161
|
+
sonar: {
|
|
162
|
+
apiId: 'sonar',
|
|
163
|
+
openRouterId: 'perplexity/sonar',
|
|
164
|
+
thinking: { on: 'high', off: 'low' },
|
|
165
|
+
thinkingLevels: OPENROUTER_SEARCH_THINKING_LEVELS,
|
|
166
|
+
summaries: { on: 'none', off: 'none' },
|
|
167
|
+
maxOutputTokens: SONAR_MAX_OUTPUT_TOKENS,
|
|
168
|
+
temperature: DEFAULT_TEMPERATURE,
|
|
169
|
+
freeBuiltins: [],
|
|
170
|
+
},
|
|
171
|
+
},
|
|
172
|
+
// Off until the turn sets tools[id]. Profile allow is only the ceiling.
|
|
173
|
+
tools: {
|
|
174
|
+
googleSearch: { kind: 'builtin', ui: true },
|
|
175
|
+
googleMaps: { kind: 'builtin', ui: true },
|
|
176
|
+
urlContext: { kind: 'builtin', ui: true },
|
|
177
|
+
askUser: { kind: 'custom', ui: true, schema: ASK_USER_SCHEMA },
|
|
178
|
+
},
|
|
179
|
+
};
|
|
180
|
+
export { CATALOG, CHAT_MEDIA_LIMITS, GEMINI_INPUT_KINDS, geminiKindForMime, IMAGE_FLASH_LITE_ASPECT_RATIOS, IMAGE_FLASH_LITE_SIZES, IMAGE_INPUT_MIMES, mimeAllowed, mimeEssence, VOICE_INPUT_MIMES, };
|
|
181
|
+
export const MODEL_CATALOG = CATALOG.models;
|
|
182
|
+
export function modelEntry(modelId) {
|
|
183
|
+
return (MODEL_CATALOG[modelId] ?? {
|
|
184
|
+
...GENERIC_MODEL_ENTRY,
|
|
185
|
+
apiId: modelId,
|
|
186
|
+
openRouterId: modelId,
|
|
187
|
+
});
|
|
188
|
+
}
|
|
189
|
+
function clampLevels(entry, level) {
|
|
190
|
+
if (!entry?.thinkingLevels || entry.thinkingLevels.length === 0) {
|
|
191
|
+
return level;
|
|
192
|
+
}
|
|
193
|
+
if (entry.thinkingLevels.includes(level)) {
|
|
194
|
+
return level;
|
|
195
|
+
}
|
|
196
|
+
const fallback = entry.thinking.off;
|
|
197
|
+
if (entry.thinkingLevels.includes(fallback)) {
|
|
198
|
+
return fallback;
|
|
199
|
+
}
|
|
200
|
+
const first = entry.thinkingLevels[0];
|
|
201
|
+
return first ?? level;
|
|
202
|
+
}
|
|
203
|
+
/** Clamp a requested thinking level to what the selected model accepts. */
|
|
204
|
+
export function clampThinkingLevel(modelId, level) {
|
|
205
|
+
return clampLevels(modelEntry(modelId), level);
|
|
206
|
+
}
|
|
207
|
+
export function modelEntryByApiId(apiId) {
|
|
208
|
+
return Object.values(MODEL_CATALOG).find((m) => m.apiId === apiId);
|
|
209
|
+
}
|
|
210
|
+
export function clampThinkingLevelForApiId(apiId, level) {
|
|
211
|
+
const entry = modelEntryByApiId(apiId);
|
|
212
|
+
return clampLevels(entry, level);
|
|
213
|
+
}
|
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Runtime profile registry for host-owned THEORUM profiles.
|
|
3
|
+
*
|
|
4
|
+
* THEORUM ships profile types and defaults, not application profiles. Host apps
|
|
5
|
+
* register their profiles at process startup or test setup.
|
|
6
|
+
*
|
|
7
|
+
* @module
|
|
8
|
+
*/
|
|
9
|
+
import type { Profile } from '../types.js';
|
|
10
|
+
/** Host-authored profile definition, with defaults applied to omitted sections. */
|
|
11
|
+
export type ProfileDefinition = {
|
|
12
|
+
id: Profile['id'];
|
|
13
|
+
identity?: Partial<Profile['identity']>;
|
|
14
|
+
model: Partial<Profile['model']> & Pick<Profile['model'], 'allow'>;
|
|
15
|
+
tools?: Partial<Profile['tools']>;
|
|
16
|
+
inputs?: Partial<Profile['inputs']>;
|
|
17
|
+
outputs?: Partial<Profile['outputs']>;
|
|
18
|
+
guardrails?: Partial<Profile['guardrails']>;
|
|
19
|
+
};
|
|
20
|
+
/** Backwards-compatible alias for callers using the older name. */
|
|
21
|
+
export type DefineProfileInput = ProfileDefinition;
|
|
22
|
+
/** Define a typed profile with stable defaults for optional properties. */
|
|
23
|
+
declare function defineProfile(input: DefineProfileInput): Profile;
|
|
24
|
+
/** Register one host-owned profile in the process-local registry. */
|
|
25
|
+
declare function registerProfile(profileInput: Profile | ProfileDefinition): void;
|
|
26
|
+
/** Register several host-owned profiles in order. */
|
|
27
|
+
declare function registerProfiles(profilesList: Array<Profile | ProfileDefinition>): void;
|
|
28
|
+
/** Return whether a profile id is currently registered. */
|
|
29
|
+
declare function hasProfile(id: string): boolean;
|
|
30
|
+
/** List all currently registered profiles. */
|
|
31
|
+
declare function listProfiles(): Profile[];
|
|
32
|
+
/** Clear the process-local registry; intended for tests and host reloads. */
|
|
33
|
+
declare function clearProfiles(): void;
|
|
34
|
+
/** Fetch a registered profile or throw a `TheorumError`. */
|
|
35
|
+
declare function getProfile(id: string): Profile;
|
|
36
|
+
export { clearProfiles, defineProfile, getProfile, hasProfile, listProfiles, registerProfile, registerProfiles, };
|
|
@@ -0,0 +1,111 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Runtime profile registry for host-owned THEORUM profiles.
|
|
3
|
+
*
|
|
4
|
+
* THEORUM ships profile types and defaults, not application profiles. Host apps
|
|
5
|
+
* register their profiles at process startup or test setup.
|
|
6
|
+
*
|
|
7
|
+
* @module
|
|
8
|
+
*/
|
|
9
|
+
import { TheorumError } from '../../guardrails/error.js';
|
|
10
|
+
const profiles = new Map();
|
|
11
|
+
function buildDefaultIdentity(id, identity) {
|
|
12
|
+
return {
|
|
13
|
+
handle: identity?.handle ?? id,
|
|
14
|
+
chat: identity?.chat,
|
|
15
|
+
system: identity?.system,
|
|
16
|
+
systemByRole: identity?.systemByRole,
|
|
17
|
+
};
|
|
18
|
+
}
|
|
19
|
+
function buildDefaultModel(model) {
|
|
20
|
+
return {
|
|
21
|
+
protocol: model.protocol ?? 'geminiInteractions',
|
|
22
|
+
provider: model.provider ?? 'google',
|
|
23
|
+
allow: model.allow,
|
|
24
|
+
thinking: model.thinking ?? 'minimal',
|
|
25
|
+
controls: model.controls ?? [],
|
|
26
|
+
maxSteps: model.maxSteps ?? 1,
|
|
27
|
+
key: model.key ?? 'freeA',
|
|
28
|
+
select: model.select,
|
|
29
|
+
override: model.override,
|
|
30
|
+
};
|
|
31
|
+
}
|
|
32
|
+
function buildDefaultInputs(inputs) {
|
|
33
|
+
return {
|
|
34
|
+
text: inputs?.text ?? true,
|
|
35
|
+
attachments: inputs?.attachments,
|
|
36
|
+
voice: inputs?.voice,
|
|
37
|
+
maxFiles: inputs?.maxFiles,
|
|
38
|
+
maxBytes: inputs?.maxBytes,
|
|
39
|
+
maxTurnBytes: inputs?.maxTurnBytes,
|
|
40
|
+
limitsByMime: inputs?.limitsByMime,
|
|
41
|
+
slots: inputs?.slots,
|
|
42
|
+
};
|
|
43
|
+
}
|
|
44
|
+
function buildDefaultOutputs(outputs) {
|
|
45
|
+
return {
|
|
46
|
+
structured: outputs?.structured ?? null,
|
|
47
|
+
media: outputs?.media ?? false,
|
|
48
|
+
voice: outputs?.voice,
|
|
49
|
+
validation: outputs?.validation,
|
|
50
|
+
streaming: outputs?.streaming,
|
|
51
|
+
};
|
|
52
|
+
}
|
|
53
|
+
function buildDefaultGuardrails(guardrails) {
|
|
54
|
+
return {
|
|
55
|
+
quota: guardrails?.quota,
|
|
56
|
+
canary: guardrails?.canary ?? true,
|
|
57
|
+
sanitizeInput: guardrails?.sanitizeInput ?? true,
|
|
58
|
+
redactSensitive: guardrails?.redactSensitive ?? true,
|
|
59
|
+
egress: guardrails?.egress,
|
|
60
|
+
};
|
|
61
|
+
}
|
|
62
|
+
/** Define a typed profile with stable defaults for optional properties. */
|
|
63
|
+
function defineProfile(input) {
|
|
64
|
+
return {
|
|
65
|
+
id: input.id,
|
|
66
|
+
identity: buildDefaultIdentity(input.id, input.identity),
|
|
67
|
+
model: buildDefaultModel(input.model),
|
|
68
|
+
tools: { allow: input.tools?.allow ?? [] },
|
|
69
|
+
inputs: buildDefaultInputs(input.inputs),
|
|
70
|
+
outputs: buildDefaultOutputs(input.outputs),
|
|
71
|
+
guardrails: buildDefaultGuardrails(input.guardrails),
|
|
72
|
+
};
|
|
73
|
+
}
|
|
74
|
+
/** Register one host-owned profile in the process-local registry. */
|
|
75
|
+
function registerProfile(profileInput) {
|
|
76
|
+
const profile = defineProfile(profileInput);
|
|
77
|
+
const { attachments, voice, maxFiles, maxBytes, maxTurnBytes } = profile.inputs;
|
|
78
|
+
if (attachments || voice) {
|
|
79
|
+
if (!(maxFiles && maxBytes && maxTurnBytes)) {
|
|
80
|
+
throw new TheorumError(`Profile ${profile.id} must set maxFiles, maxBytes, and maxTurnBytes`);
|
|
81
|
+
}
|
|
82
|
+
}
|
|
83
|
+
profiles.set(profile.id, profile);
|
|
84
|
+
}
|
|
85
|
+
/** Register several host-owned profiles in order. */
|
|
86
|
+
function registerProfiles(profilesList) {
|
|
87
|
+
for (const p of profilesList) {
|
|
88
|
+
registerProfile(p);
|
|
89
|
+
}
|
|
90
|
+
}
|
|
91
|
+
/** Return whether a profile id is currently registered. */
|
|
92
|
+
function hasProfile(id) {
|
|
93
|
+
return profiles.has(id);
|
|
94
|
+
}
|
|
95
|
+
/** List all currently registered profiles. */
|
|
96
|
+
function listProfiles() {
|
|
97
|
+
return Array.from(profiles.values());
|
|
98
|
+
}
|
|
99
|
+
/** Clear the process-local registry; intended for tests and host reloads. */
|
|
100
|
+
function clearProfiles() {
|
|
101
|
+
profiles.clear();
|
|
102
|
+
}
|
|
103
|
+
/** Fetch a registered profile or throw a `TheorumError`. */
|
|
104
|
+
function getProfile(id) {
|
|
105
|
+
const profile = profiles.get(id);
|
|
106
|
+
if (!profile) {
|
|
107
|
+
throw new TheorumError(`Unknown profile '${id}'`);
|
|
108
|
+
}
|
|
109
|
+
return profile;
|
|
110
|
+
}
|
|
111
|
+
export { clearProfiles, defineProfile, getProfile, hasProfile, listProfiles, registerProfile, registerProfiles, };
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Profile resolution for THEORUM turns.
|
|
3
|
+
*
|
|
4
|
+
* This module validates caller overrides, selects models and tools, normalizes
|
|
5
|
+
* input parts, and produces the provider request state consumed by `runTurn`.
|
|
6
|
+
*
|
|
7
|
+
* @module
|
|
8
|
+
*/
|
|
9
|
+
import type { Profile, ProjectedProfile, ResolvedGeneration, ToolId, TurnRequest } from '../types.js';
|
|
10
|
+
declare function assertToolAllowed(profile: Profile, name: ToolId): void;
|
|
11
|
+
/** Resolve a host `TurnRequest` into provider-ready generation state. */
|
|
12
|
+
declare function resolveTurn(req: TurnRequest): {
|
|
13
|
+
profile: Profile;
|
|
14
|
+
generation: ResolvedGeneration;
|
|
15
|
+
};
|
|
16
|
+
/** UI projection: catalog ∩ profile. Swatches are not included. */
|
|
17
|
+
/** Project a registered profile into a safe host/UI inspection object. */
|
|
18
|
+
declare function projectProfile(id: Profile['id']): ProjectedProfile;
|
|
19
|
+
declare function pickSystemRole(profile: Profile, requested?: string): string;
|
|
20
|
+
export { assertToolAllowed, pickSystemRole, projectProfile, resolveTurn };
|