theorum 1.0.0 → 1.1.3
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +81 -25
- package/esm/mod.d.ts +48 -29
- package/esm/mod.js +37 -24
- package/esm/src/cli/commands/bench.js +13 -16
- package/esm/src/cli/commands/fuzz-canary.js +25 -29
- package/esm/src/cli/commands/guardrails-eval.d.ts +14 -0
- package/esm/src/cli/commands/guardrails-eval.js +15 -0
- package/esm/src/cli/commands/profile.js +12 -3
- package/esm/src/cli/commands/run.js +8 -9
- package/esm/src/cli/commands/test.js +8 -8
- package/esm/src/cli/event-log.d.ts +1 -1
- package/esm/src/cli/index.js +12 -0
- package/esm/src/cli/matrix/synthesizer.d.ts +6 -6
- package/esm/src/cli/matrix/synthesizer.js +23 -22
- package/esm/src/guardrails/canary-gate.d.ts +2 -1
- package/esm/src/guardrails/canary-gate.js +2 -1
- package/esm/src/guardrails/canary.d.ts +9 -1
- package/esm/src/guardrails/canary.js +21 -10
- package/esm/src/guardrails/corpus/canary-egress-attacks.d.ts +1 -0
- package/esm/src/guardrails/corpus/fuzz-inbound.js +12 -15
- package/esm/src/guardrails/corpus/inbound-payloads.js +1 -0
- package/esm/src/guardrails/corpus/live-attacks.js +0 -1
- package/esm/src/guardrails/corpus/mod.d.ts +1 -0
- package/esm/src/guardrails/corpus/secrets.d.ts +1 -0
- package/esm/src/guardrails/corpus/secrets.js +1 -0
- package/esm/src/guardrails/corpus/strings.d.ts +1 -0
- package/esm/src/guardrails/corpus/strings.js +1 -0
- package/esm/src/guardrails/corpus/types.d.ts +1 -0
- package/esm/src/guardrails/egress.d.ts +26 -3
- package/esm/src/guardrails/egress.js +69 -18
- package/esm/src/guardrails/error.d.ts +14 -23
- package/esm/src/guardrails/error.js +86 -77
- package/esm/src/guardrails/eval/corpus.d.ts +108 -0
- package/esm/src/guardrails/eval/corpus.js +978 -0
- package/esm/src/guardrails/eval/mod.d.ts +51 -0
- package/esm/src/guardrails/eval/mod.js +133 -0
- package/esm/src/guardrails/eval/score.d.ts +66 -0
- package/esm/src/guardrails/eval/score.js +114 -0
- package/esm/src/guardrails/events.d.ts +25 -0
- package/esm/src/guardrails/events.js +56 -0
- package/esm/src/guardrails/hits.d.ts +24 -0
- package/esm/src/guardrails/hits.js +45 -0
- package/esm/src/guardrails/lexicon.d.ts +39 -0
- package/esm/src/guardrails/lexicon.js +200 -0
- package/esm/src/guardrails/live-outbound-gate.d.ts +15 -13
- package/esm/src/guardrails/live-outbound-gate.js +131 -89
- package/esm/src/guardrails/mod.d.ts +19 -4
- package/esm/src/guardrails/mod.js +12 -3
- package/esm/src/guardrails/network.d.ts +19 -0
- package/esm/src/guardrails/network.js +234 -0
- package/esm/src/guardrails/policy.d.ts +35 -0
- package/esm/src/guardrails/policy.js +50 -0
- package/esm/src/guardrails/progressive-yield.d.ts +51 -0
- package/esm/src/guardrails/progressive-yield.js +98 -0
- package/esm/src/guardrails/quota.d.ts +17 -3
- package/esm/src/guardrails/quota.js +18 -4
- package/esm/src/guardrails/sanitize.d.ts +36 -6
- package/esm/src/guardrails/sanitize.js +152 -60
- package/esm/src/guardrails/serialize.d.ts +35 -0
- package/esm/src/guardrails/serialize.js +58 -0
- package/esm/src/guardrails/testing.d.ts +7 -0
- package/esm/src/guardrails/testing.js +4 -0
- package/esm/src/guardrails/theorum-error.d.ts +12 -0
- package/esm/src/guardrails/theorum-error.js +15 -0
- package/esm/src/guardrails/tool-directives.d.ts +48 -0
- package/esm/src/guardrails/tool-directives.js +124 -0
- package/esm/src/guardrails/tool-result.d.ts +93 -0
- package/esm/src/guardrails/tool-result.js +276 -0
- package/esm/src/guardrails/types.d.ts +291 -0
- package/esm/src/guardrails/types.js +72 -0
- package/esm/src/host/client-turn.js +4 -0
- package/esm/src/host/mint-trace.d.ts +1 -1
- package/esm/src/kernel/auth/crypto.d.ts +42 -0
- package/esm/src/kernel/auth/crypto.js +106 -0
- package/esm/src/kernel/auth/mod.d.ts +11 -0
- package/esm/src/kernel/auth/mod.js +11 -0
- package/esm/src/kernel/auth/oauth.d.ts +47 -0
- package/esm/src/kernel/auth/oauth.js +278 -0
- package/esm/src/kernel/auth/types.d.ts +133 -0
- package/esm/src/kernel/auth/types.js +13 -0
- package/esm/src/kernel/engine/delta.js +43 -2
- package/esm/src/kernel/engine/live-inbound.d.ts +15 -3
- package/esm/src/kernel/engine/live-inbound.js +22 -8
- package/esm/src/kernel/engine/live-ingress.d.ts +19 -0
- package/esm/src/kernel/engine/live-ingress.js +47 -0
- package/esm/src/kernel/engine/repair.js +13 -12
- package/esm/src/kernel/engine/runner/gates.js +127 -40
- package/esm/src/kernel/engine/runner/mod.d.ts +6 -4
- package/esm/src/kernel/engine/runner/mod.js +182 -43
- package/esm/src/kernel/engine/runner/schema-validation.js +3 -3
- package/esm/src/kernel/engine/runner/stages.d.ts +39 -0
- package/esm/src/kernel/engine/runner/stages.js +89 -0
- package/esm/src/kernel/engine/runner/state.d.ts +24 -0
- package/esm/src/kernel/engine/runner/steps.js +128 -61
- package/esm/src/kernel/engine/runner/stream.d.ts +9 -2
- package/esm/src/kernel/engine/runner/stream.js +114 -55
- package/esm/src/kernel/engine/session/mod.d.ts +3 -1
- package/esm/src/kernel/engine/session/mod.js +386 -34
- package/esm/src/kernel/interaction-parts.d.ts +14 -0
- package/esm/src/kernel/interaction-parts.js +23 -0
- package/esm/src/kernel/mod.d.ts +19 -7
- package/esm/src/kernel/mod.js +10 -5
- package/esm/src/kernel/profile-graph.d.ts +159 -0
- package/esm/src/kernel/profile-graph.js +156 -0
- package/esm/src/kernel/registry/attachments.d.ts +10 -10
- package/esm/src/kernel/registry/attachments.js +29 -26
- package/esm/src/kernel/registry/catalog.d.ts +25 -11
- package/esm/src/kernel/registry/catalog.js +59 -24
- package/esm/src/kernel/registry/ingress.js +34 -22
- package/esm/src/kernel/registry/profile-outputs.d.ts +4 -0
- package/esm/src/kernel/registry/profile-outputs.js +8 -0
- package/esm/src/kernel/registry/profiles.d.ts +34 -14
- package/esm/src/kernel/registry/profiles.js +306 -59
- package/esm/src/kernel/registry/provider-request.js +2 -0
- package/esm/src/kernel/registry/resolve.d.ts +7 -6
- package/esm/src/kernel/registry/resolve.js +102 -117
- package/esm/src/kernel/registry/schemas.js +1 -1
- package/esm/src/kernel/registry/sole-model.d.ts +8 -0
- package/esm/src/kernel/registry/sole-model.js +10 -0
- package/esm/src/kernel/registry/system-prompt.d.ts +10 -0
- package/esm/src/kernel/registry/system-prompt.js +40 -0
- package/esm/src/kernel/registry/system-role.d.ts +8 -0
- package/esm/src/kernel/registry/system-role.js +14 -0
- package/esm/src/kernel/registry/vault.d.ts +2 -2
- package/esm/src/kernel/registry/vault.js +4 -4
- package/esm/src/kernel/schema.d.ts +97 -11
- package/esm/src/kernel/schema.js +256 -111
- package/esm/src/kernel/stages.d.ts +175 -0
- package/esm/src/kernel/stages.js +476 -0
- package/esm/src/kernel/stop.d.ts +65 -11
- package/esm/src/kernel/stop.js +46 -11
- package/esm/src/kernel/tools/events.d.ts +41 -0
- package/esm/src/kernel/tools/events.js +71 -0
- package/esm/src/kernel/tools/execute.d.ts +63 -24
- package/esm/src/kernel/tools/execute.js +475 -224
- package/esm/src/kernel/tools/harness.js +16 -14
- package/esm/src/kernel/tools/invoke.js +26 -8
- package/esm/src/kernel/tools/mod.d.ts +3 -1
- package/esm/src/kernel/tools/mod.js +2 -1
- package/esm/src/kernel/tools/permission.d.ts +15 -0
- package/esm/src/kernel/tools/permission.js +47 -0
- package/esm/src/kernel/tools/project.js +5 -3
- package/esm/src/kernel/tools/registry.js +20 -10
- package/esm/src/kernel/tools/remote.d.ts +94 -0
- package/esm/src/kernel/tools/remote.js +577 -0
- package/esm/src/kernel/tools/resolve.d.ts +17 -7
- package/esm/src/kernel/tools/resolve.js +38 -17
- package/esm/src/kernel/tools/schema.d.ts +2 -0
- package/esm/src/kernel/tools/schema.js +23 -6
- package/esm/src/kernel/tools/stage-run.d.ts +105 -0
- package/esm/src/kernel/tools/stage-run.js +155 -0
- package/esm/src/kernel/tools/types.d.ts +198 -20
- package/esm/src/kernel/types.d.ts +253 -114
- package/esm/src/kernel/util/find-last.d.ts +2 -0
- package/esm/src/kernel/util/find-last.js +10 -0
- package/esm/src/observability/destinations.d.ts +31 -0
- package/esm/src/observability/destinations.js +67 -0
- package/esm/src/observability/mod.d.ts +10 -3
- package/esm/src/observability/mod.js +6 -2
- package/esm/src/observability/policy.d.ts +27 -0
- package/esm/src/observability/policy.js +80 -0
- package/esm/src/observability/resolve-policy.d.ts +16 -0
- package/esm/src/observability/resolve-policy.js +64 -0
- package/esm/src/observability/trace-attach.d.ts +3 -1
- package/esm/src/observability/trace-attach.js +17 -10
- package/esm/src/observability/trace-record.d.ts +12 -4
- package/esm/src/observability/trace-record.js +63 -19
- package/esm/src/observability/trace-sink.d.ts +19 -0
- package/esm/src/observability/trace-sink.js +10 -0
- package/esm/src/observability/trace.d.ts +14 -11
- package/esm/src/observability/trace.js +23 -14
- package/esm/src/observability/types.d.ts +113 -0
- package/esm/src/observability/types.js +11 -0
- package/esm/src/providers/create-provider.d.ts +7 -4
- package/esm/src/providers/create-provider.js +21 -7
- package/esm/src/providers/google/interactions/framing.d.ts +8 -0
- package/esm/src/providers/google/interactions/framing.js +74 -13
- package/esm/src/providers/google/live/framing.d.ts +5 -2
- package/esm/src/providers/google/live/framing.js +49 -12
- package/esm/src/providers/google/live/openapi-schema.js +3 -2
- package/esm/src/providers/google/live/stream.d.ts +9 -0
- package/esm/src/providers/google/live/stream.js +16 -3
- package/esm/src/providers/openrouter/cache-control.d.ts +24 -0
- package/esm/src/providers/openrouter/cache-control.js +23 -0
- package/esm/src/providers/openrouter/chat.d.ts +21 -1
- package/esm/src/providers/openrouter/chat.js +51 -6
- package/esm/src/providers/openrouter/image.js +8 -19
- package/esm/src/providers/openrouter/openai/chat-payload.js +23 -1
- package/esm/src/providers/openrouter/openai/compat.d.ts +7 -1
- package/esm/src/providers/openrouter/openai/compat.js +23 -4
- package/esm/src/providers/openrouter/openai/image-payload.js +8 -2
- package/esm/src/providers/openrouter/openai/sdk-messages.d.ts +1 -1
- package/esm/src/providers/openrouter/openai/sdk-messages.js +32 -5
- package/package.json +1 -1
- package/esm/src/interface/blocks.d.ts +0 -20
- package/esm/src/interface/blocks.js +0 -180
- package/esm/src/interface/from-profile.d.ts +0 -14
- package/esm/src/interface/from-profile.js +0 -104
- package/esm/src/interface/inputs.d.ts +0 -8
- package/esm/src/interface/inputs.js +0 -127
- package/esm/src/interface/mod.d.ts +0 -10
- package/esm/src/interface/mod.js +0 -9
- package/esm/src/interface/types.d.ts +0 -153
- package/esm/src/interface/types.js +0 -13
|
@@ -1,180 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Turn event folding — map kernel `TurnEvent` streams to transcript blocks.
|
|
3
|
-
*
|
|
4
|
-
* @module
|
|
5
|
-
*/
|
|
6
|
-
let blockCounter = 0;
|
|
7
|
-
function nextBlockId(prefix) {
|
|
8
|
-
blockCounter += 1;
|
|
9
|
-
return `${prefix}-${String(blockCounter)}`;
|
|
10
|
-
}
|
|
11
|
-
function resetBlockIds() {
|
|
12
|
-
blockCounter = 0;
|
|
13
|
-
}
|
|
14
|
-
function isAppendableTextBlock(block, kind) {
|
|
15
|
-
return block?.kind === kind;
|
|
16
|
-
}
|
|
17
|
-
function toolKey(event, index) {
|
|
18
|
-
const tool = event.tool;
|
|
19
|
-
if (!tool)
|
|
20
|
-
return `tool-${String(index)}`;
|
|
21
|
-
return tool.callId ?? tool.id ?? `${tool.name}-${String(index)}`;
|
|
22
|
-
}
|
|
23
|
-
function appendText(blocks, kind, text, idPrefix) {
|
|
24
|
-
const last = blocks.at(-1);
|
|
25
|
-
if (isAppendableTextBlock(last, kind)) {
|
|
26
|
-
last.text += text;
|
|
27
|
-
return;
|
|
28
|
-
}
|
|
29
|
-
blocks.push({
|
|
30
|
-
id: nextBlockId(idPrefix),
|
|
31
|
-
kind,
|
|
32
|
-
text,
|
|
33
|
-
});
|
|
34
|
-
}
|
|
35
|
-
function upsertToolBlock(blocks, event, key) {
|
|
36
|
-
const tool = event.tool;
|
|
37
|
-
if (!tool)
|
|
38
|
-
return;
|
|
39
|
-
const existing = blocks.find((block) => block.kind === 'tool' && block.id === `tool-${key}`);
|
|
40
|
-
const payload = { ...tool, id: tool.id ?? tool.callId };
|
|
41
|
-
if (existing && existing.kind === 'tool') {
|
|
42
|
-
existing.tool = { ...existing.tool, ...payload };
|
|
43
|
-
return;
|
|
44
|
-
}
|
|
45
|
-
blocks.push({
|
|
46
|
-
id: `tool-${key}`,
|
|
47
|
-
kind: 'tool',
|
|
48
|
-
tool: payload,
|
|
49
|
-
});
|
|
50
|
-
}
|
|
51
|
-
/** Build transcript blocks for a user-authored turn. */
|
|
52
|
-
function buildUserTurnBlocks(draft, idPrefix = 'user') {
|
|
53
|
-
resetBlockIds();
|
|
54
|
-
const blocks = [];
|
|
55
|
-
const text = draft.text?.trim();
|
|
56
|
-
if (text) {
|
|
57
|
-
blocks.push({
|
|
58
|
-
id: nextBlockId(idPrefix),
|
|
59
|
-
kind: 'user-text',
|
|
60
|
-
text,
|
|
61
|
-
});
|
|
62
|
-
}
|
|
63
|
-
for (const file of draft.attachments ?? []) {
|
|
64
|
-
blocks.push({
|
|
65
|
-
id: nextBlockId(idPrefix),
|
|
66
|
-
kind: 'user-attachment',
|
|
67
|
-
name: file.name,
|
|
68
|
-
mimeType: file.mimeType,
|
|
69
|
-
sizeBytes: file.sizeBytes,
|
|
70
|
-
});
|
|
71
|
-
}
|
|
72
|
-
for (const file of draft.voice ?? []) {
|
|
73
|
-
blocks.push({
|
|
74
|
-
id: nextBlockId(idPrefix),
|
|
75
|
-
kind: 'user-voice',
|
|
76
|
-
name: file.name,
|
|
77
|
-
mimeType: file.mimeType,
|
|
78
|
-
sizeBytes: file.sizeBytes,
|
|
79
|
-
});
|
|
80
|
-
}
|
|
81
|
-
return blocks;
|
|
82
|
-
}
|
|
83
|
-
/**
|
|
84
|
-
* Fold a single assistant turn's `TurnEvent` stream into ordered transcript blocks.
|
|
85
|
-
*
|
|
86
|
-
* Merges consecutive `text` and `thought` deltas, upserts tool calls by id, and
|
|
87
|
-
* skips kernel bookkeeping events (`tokens`, `session`) unless folded into `turn-done`.
|
|
88
|
-
*/
|
|
89
|
-
function foldTurnEvents(events, options = {}) {
|
|
90
|
-
const idPrefix = options.idPrefix ?? 'turn';
|
|
91
|
-
const showThoughts = options.showThoughts ?? true;
|
|
92
|
-
resetBlockIds();
|
|
93
|
-
const blocks = [];
|
|
94
|
-
let toolIndex = 0;
|
|
95
|
-
for (const event of events) {
|
|
96
|
-
switch (event.type) {
|
|
97
|
-
case 'thought':
|
|
98
|
-
if (showThoughts && event.text) {
|
|
99
|
-
appendText(blocks, 'thought', event.text, idPrefix);
|
|
100
|
-
}
|
|
101
|
-
break;
|
|
102
|
-
case 'text':
|
|
103
|
-
if (event.text) {
|
|
104
|
-
appendText(blocks, 'text', event.text, idPrefix);
|
|
105
|
-
}
|
|
106
|
-
break;
|
|
107
|
-
case 'tool': {
|
|
108
|
-
const key = toolKey(event, toolIndex);
|
|
109
|
-
toolIndex += 1;
|
|
110
|
-
upsertToolBlock(blocks, event, key);
|
|
111
|
-
break;
|
|
112
|
-
}
|
|
113
|
-
case 'structured':
|
|
114
|
-
blocks.push({
|
|
115
|
-
id: nextBlockId(idPrefix),
|
|
116
|
-
kind: 'structured',
|
|
117
|
-
value: event.structured,
|
|
118
|
-
});
|
|
119
|
-
break;
|
|
120
|
-
case 'media':
|
|
121
|
-
if (event.media) {
|
|
122
|
-
blocks.push({
|
|
123
|
-
id: nextBlockId(idPrefix),
|
|
124
|
-
kind: 'media',
|
|
125
|
-
mimeType: event.media.mimeType,
|
|
126
|
-
data: event.media.data,
|
|
127
|
-
});
|
|
128
|
-
}
|
|
129
|
-
break;
|
|
130
|
-
case 'grounding':
|
|
131
|
-
if (event.grounding) {
|
|
132
|
-
blocks.push({
|
|
133
|
-
id: nextBlockId(idPrefix),
|
|
134
|
-
kind: 'grounding',
|
|
135
|
-
grounding: event.grounding,
|
|
136
|
-
});
|
|
137
|
-
}
|
|
138
|
-
break;
|
|
139
|
-
case 'evidence':
|
|
140
|
-
if (event.evidence) {
|
|
141
|
-
blocks.push({
|
|
142
|
-
id: nextBlockId(idPrefix),
|
|
143
|
-
kind: 'evidence',
|
|
144
|
-
evidence: event.evidence,
|
|
145
|
-
});
|
|
146
|
-
}
|
|
147
|
-
break;
|
|
148
|
-
case 'error':
|
|
149
|
-
if (event.error) {
|
|
150
|
-
blocks.push({
|
|
151
|
-
id: nextBlockId(idPrefix),
|
|
152
|
-
kind: 'error',
|
|
153
|
-
message: event.error,
|
|
154
|
-
});
|
|
155
|
-
}
|
|
156
|
-
break;
|
|
157
|
-
case 'done':
|
|
158
|
-
blocks.push({
|
|
159
|
-
id: nextBlockId(idPrefix),
|
|
160
|
-
kind: 'turn-done',
|
|
161
|
-
stop: event.stop,
|
|
162
|
-
tokens: event.tokens,
|
|
163
|
-
interactionId: event.interactionId,
|
|
164
|
-
compaction: event.compaction !== undefined,
|
|
165
|
-
});
|
|
166
|
-
break;
|
|
167
|
-
case 'tokens':
|
|
168
|
-
case 'session':
|
|
169
|
-
break;
|
|
170
|
-
default:
|
|
171
|
-
break;
|
|
172
|
-
}
|
|
173
|
-
}
|
|
174
|
-
return blocks;
|
|
175
|
-
}
|
|
176
|
-
/** User draft blocks followed by folded assistant turn events. */
|
|
177
|
-
function foldConversationTurn(draft, assistantEvents, options = {}) {
|
|
178
|
-
return [...buildUserTurnBlocks(draft, 'user'), ...foldTurnEvents(assistantEvents, options)];
|
|
179
|
-
}
|
|
180
|
-
export { buildUserTurnBlocks, foldConversationTurn, foldTurnEvents, resetBlockIds };
|
|
@@ -1,14 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Profile → `ProfileInterface` projection.
|
|
3
|
-
*
|
|
4
|
-
* Kernel `projectProfileObject` is the single inspection projection; this module
|
|
5
|
-
* only enriches `inputs` (acceptAttr) and attaches serializable guardrails.
|
|
6
|
-
*
|
|
7
|
-
* @module
|
|
8
|
-
*/
|
|
9
|
-
import type { Profile, ProjectedProfile } from '../kernel/types.js';
|
|
10
|
-
import type { ProfileInterface, ProfileInterfaceSource } from './types.js';
|
|
11
|
-
declare function interfaceFrom(source: ProfileInterfaceSource): ProfileInterface;
|
|
12
|
-
declare function interfaceFromProfile(profile: Profile): ProfileInterface;
|
|
13
|
-
declare function interfaceFromProjected(projected: ProjectedProfile): ProfileInterface;
|
|
14
|
-
export { interfaceFrom, interfaceFromProfile, interfaceFromProjected };
|
|
@@ -1,104 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Profile → `ProfileInterface` projection.
|
|
3
|
-
*
|
|
4
|
-
* Kernel `projectProfileObject` is the single inspection projection; this module
|
|
5
|
-
* only enriches `inputs` (acceptAttr) and attaches serializable guardrails.
|
|
6
|
-
*
|
|
7
|
-
* @module
|
|
8
|
-
*/
|
|
9
|
-
import { projectProfileObject } from '../kernel/registry/resolve.js';
|
|
10
|
-
import { inputsFromSpec } from './inputs.js';
|
|
11
|
-
function guardrailsView(guardrails) {
|
|
12
|
-
if (!guardrails)
|
|
13
|
-
return undefined;
|
|
14
|
-
return {
|
|
15
|
-
quota: guardrails.quota,
|
|
16
|
-
canary: guardrails.canary,
|
|
17
|
-
sanitizeInput: guardrails.sanitizeInput,
|
|
18
|
-
redactSensitive: guardrails.redactSensitive,
|
|
19
|
-
hasEgress: Boolean(guardrails.egress),
|
|
20
|
-
};
|
|
21
|
-
}
|
|
22
|
-
function normalizeModel(model) {
|
|
23
|
-
return {
|
|
24
|
-
...model,
|
|
25
|
-
select: model.select ?? null,
|
|
26
|
-
controls: model.controls ?? [],
|
|
27
|
-
};
|
|
28
|
-
}
|
|
29
|
-
function toolsResolved(projected, profile) {
|
|
30
|
-
if (projected.type === 'speech') {
|
|
31
|
-
return { allow: [], resolved: [] };
|
|
32
|
-
}
|
|
33
|
-
if (profile && profile.type !== 'speech') {
|
|
34
|
-
return {
|
|
35
|
-
allow: profile.tools.allow,
|
|
36
|
-
t2Loader: profile.tools.t2Loader,
|
|
37
|
-
resolved: projected.tools,
|
|
38
|
-
};
|
|
39
|
-
}
|
|
40
|
-
const allow = projected.tools
|
|
41
|
-
.filter((tool) => !('type' in tool && tool.type === 'builtin'))
|
|
42
|
-
.map((tool) => tool.name);
|
|
43
|
-
return { allow, resolved: projected.tools };
|
|
44
|
-
}
|
|
45
|
-
function enrich(projected, profile) {
|
|
46
|
-
const inputs = inputsFromSpec(projected.type, projected.inputs);
|
|
47
|
-
const identity = profile?.identity ?? { handle: projected.handle };
|
|
48
|
-
const model = normalizeModel(projected.model);
|
|
49
|
-
const guardrails = profile ? guardrailsView(profile.guardrails) : undefined;
|
|
50
|
-
const outputs = projected.outputs ?? undefined;
|
|
51
|
-
const shared = { id: projected.id, identity, model, outputs, guardrails };
|
|
52
|
-
switch (projected.type) {
|
|
53
|
-
case 'text':
|
|
54
|
-
return {
|
|
55
|
-
...shared,
|
|
56
|
-
type: 'text',
|
|
57
|
-
inputs,
|
|
58
|
-
tools: toolsResolved(projected, profile),
|
|
59
|
-
turnResumption: profile?.type === 'text' ? profile.turnResumption : undefined,
|
|
60
|
-
};
|
|
61
|
-
case 'image':
|
|
62
|
-
return {
|
|
63
|
-
...shared,
|
|
64
|
-
type: 'image',
|
|
65
|
-
image: projected.image ?? {},
|
|
66
|
-
inputs,
|
|
67
|
-
tools: toolsResolved(projected, profile),
|
|
68
|
-
turnResumption: profile?.type === 'image' ? profile.turnResumption : undefined,
|
|
69
|
-
};
|
|
70
|
-
case 'speech':
|
|
71
|
-
return {
|
|
72
|
-
...shared,
|
|
73
|
-
type: 'speech',
|
|
74
|
-
speech: projected.speech ?? {},
|
|
75
|
-
inputs,
|
|
76
|
-
turnResumption: profile?.type === 'speech' ? profile.turnResumption : undefined,
|
|
77
|
-
};
|
|
78
|
-
case 'live':
|
|
79
|
-
return {
|
|
80
|
-
...shared,
|
|
81
|
-
type: 'live',
|
|
82
|
-
live: projected.live ?? {},
|
|
83
|
-
inputs,
|
|
84
|
-
tools: toolsResolved(projected, profile),
|
|
85
|
-
};
|
|
86
|
-
default: {
|
|
87
|
-
const exhaustive = projected.type;
|
|
88
|
-
return exhaustive;
|
|
89
|
-
}
|
|
90
|
-
}
|
|
91
|
-
}
|
|
92
|
-
function interfaceFrom(source) {
|
|
93
|
-
if ('identity' in source) {
|
|
94
|
-
return enrich(projectProfileObject(source), source);
|
|
95
|
-
}
|
|
96
|
-
return enrich(source);
|
|
97
|
-
}
|
|
98
|
-
function interfaceFromProfile(profile) {
|
|
99
|
-
return interfaceFrom(profile);
|
|
100
|
-
}
|
|
101
|
-
function interfaceFromProjected(projected) {
|
|
102
|
-
return interfaceFrom(projected);
|
|
103
|
-
}
|
|
104
|
-
export { interfaceFrom, interfaceFromProfile, interfaceFromProjected };
|
|
@@ -1,8 +0,0 @@
|
|
|
1
|
-
import type { ProfileInputsSpec, ProfileType } from '../kernel/types.js';
|
|
2
|
-
import type { AttachmentValidationResult, ProfileInputsInterface, UserTurnDraft } from './types.js';
|
|
3
|
-
declare function attachmentAcceptAttr(accept: string[]): string;
|
|
4
|
-
declare function inputsFromSpec(type: ProfileType, inputs: ProfileInputsSpec | null | undefined): ProfileInputsInterface;
|
|
5
|
-
/** Validate staged files against resolved profile `inputs`. */
|
|
6
|
-
declare function validateProfileInputs(inputs: ProfileInputsInterface, draft: Pick<UserTurnDraft, 'attachments' | 'voice'>): AttachmentValidationResult;
|
|
7
|
-
declare function pickMediaRecorderMime(accept?: string[]): string | undefined;
|
|
8
|
-
export { attachmentAcceptAttr, inputsFromSpec, pickMediaRecorderMime, validateProfileInputs };
|
|
@@ -1,127 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Profile `inputs` → UI affordances and validation.
|
|
3
|
-
*
|
|
4
|
-
* @module
|
|
5
|
-
*/
|
|
6
|
-
import * as dntShim from "../../_dnt.shims.js";
|
|
7
|
-
import { fileTooLargeMessage, maxBytesForMime, resolveMediaLimits, tooManyFilesMessage, turnTooLargeMessage, } from '../kernel/registry/attachments.js';
|
|
8
|
-
import { mimeAllowed } from '../kernel/registry/catalog.js';
|
|
9
|
-
const RECORDER_CANDIDATES = [
|
|
10
|
-
'audio/webm;codecs=opus',
|
|
11
|
-
'audio/webm',
|
|
12
|
-
'audio/mp4',
|
|
13
|
-
'audio/wav',
|
|
14
|
-
'audio/mpeg',
|
|
15
|
-
];
|
|
16
|
-
function attachmentAcceptAttr(accept) {
|
|
17
|
-
return accept.join(',');
|
|
18
|
-
}
|
|
19
|
-
function inputsFromSpec(type, inputs) {
|
|
20
|
-
if (type === 'speech') {
|
|
21
|
-
return { text: true, attachments: null, voice: null };
|
|
22
|
-
}
|
|
23
|
-
const accept = inputs?.attachments?.accept;
|
|
24
|
-
const voiceAccept = inputs?.voice?.accept;
|
|
25
|
-
return {
|
|
26
|
-
text: inputs?.text !== false,
|
|
27
|
-
attachments: accept?.length ? { accept, acceptAttr: attachmentAcceptAttr(accept) } : null,
|
|
28
|
-
voice: voiceAccept?.length ? { accept: voiceAccept } : null,
|
|
29
|
-
maxFiles: inputs?.maxFiles,
|
|
30
|
-
maxBytes: inputs?.maxBytes,
|
|
31
|
-
maxTurnBytes: inputs?.maxTurnBytes,
|
|
32
|
-
limitsByMime: inputs?.limitsByMime,
|
|
33
|
-
slots: inputs?.slots,
|
|
34
|
-
};
|
|
35
|
-
}
|
|
36
|
-
function toProfileInputsSpec(inputs) {
|
|
37
|
-
return {
|
|
38
|
-
text: inputs.text,
|
|
39
|
-
attachments: inputs.attachments ? { accept: inputs.attachments.accept } : undefined,
|
|
40
|
-
voice: inputs.voice ? { accept: inputs.voice.accept } : undefined,
|
|
41
|
-
maxFiles: inputs.maxFiles,
|
|
42
|
-
maxBytes: inputs.maxBytes,
|
|
43
|
-
maxTurnBytes: inputs.maxTurnBytes,
|
|
44
|
-
limitsByMime: inputs.limitsByMime,
|
|
45
|
-
slots: inputs.slots,
|
|
46
|
-
};
|
|
47
|
-
}
|
|
48
|
-
function issue(code, message, fileName) {
|
|
49
|
-
return { code, message, fileName };
|
|
50
|
-
}
|
|
51
|
-
function validateMime(accept, files, channelLabel) {
|
|
52
|
-
const issues = [];
|
|
53
|
-
for (const file of files) {
|
|
54
|
-
if (!mimeAllowed(accept, file.mimeType)) {
|
|
55
|
-
issues.push(issue('mime_not_allowed', `${file.name}: MIME '${file.mimeType}' is not accepted for ${channelLabel} input.`, file.name));
|
|
56
|
-
}
|
|
57
|
-
}
|
|
58
|
-
return issues;
|
|
59
|
-
}
|
|
60
|
-
function validateLimits(files, limits) {
|
|
61
|
-
const issues = [];
|
|
62
|
-
if (files.length > limits.maxFiles) {
|
|
63
|
-
issues.push(issue('too_many_files', tooManyFilesMessage(limits.maxFiles)));
|
|
64
|
-
return issues;
|
|
65
|
-
}
|
|
66
|
-
let total = 0;
|
|
67
|
-
for (const file of files) {
|
|
68
|
-
const maxAllowed = maxBytesForMime(file.mimeType, limits);
|
|
69
|
-
if (file.sizeBytes > maxAllowed) {
|
|
70
|
-
issues.push(issue('file_too_large', fileTooLargeMessage(maxAllowed), file.name));
|
|
71
|
-
}
|
|
72
|
-
total += file.sizeBytes;
|
|
73
|
-
}
|
|
74
|
-
if (total > limits.maxTurnBytes) {
|
|
75
|
-
issues.push(issue('turn_too_large', turnTooLargeMessage(limits.maxTurnBytes)));
|
|
76
|
-
}
|
|
77
|
-
return issues;
|
|
78
|
-
}
|
|
79
|
-
/** Validate staged files against resolved profile `inputs`. */
|
|
80
|
-
function validateProfileInputs(inputs, draft) {
|
|
81
|
-
const attachments = draft.attachments ?? [];
|
|
82
|
-
const voice = draft.voice ?? [];
|
|
83
|
-
if (attachments.length === 0 && voice.length === 0) {
|
|
84
|
-
return { ok: true, issues: [] };
|
|
85
|
-
}
|
|
86
|
-
if (attachments.length > 0 && !inputs.attachments) {
|
|
87
|
-
return {
|
|
88
|
-
ok: false,
|
|
89
|
-
issues: [issue('mime_not_allowed', 'This profile does not accept file attachments.')],
|
|
90
|
-
};
|
|
91
|
-
}
|
|
92
|
-
if (voice.length > 0 && !inputs.voice) {
|
|
93
|
-
return {
|
|
94
|
-
ok: false,
|
|
95
|
-
issues: [issue('mime_not_allowed', 'This profile does not accept voice input.')],
|
|
96
|
-
};
|
|
97
|
-
}
|
|
98
|
-
const spec = toProfileInputsSpec(inputs);
|
|
99
|
-
const issues = [];
|
|
100
|
-
if (attachments.length > 0 && inputs.attachments) {
|
|
101
|
-
issues.push(...validateMime(inputs.attachments.accept, attachments, 'attachment'));
|
|
102
|
-
}
|
|
103
|
-
if (voice.length > 0 && inputs.voice) {
|
|
104
|
-
issues.push(...validateMime(inputs.voice.accept, voice, 'voice'));
|
|
105
|
-
}
|
|
106
|
-
const limits = resolveMediaLimits(spec);
|
|
107
|
-
if (!limits) {
|
|
108
|
-
issues.push(issue('limits_unconfigured', 'This profile accepts media but does not define maxFiles, maxBytes, and maxTurnBytes.'));
|
|
109
|
-
return { ok: false, issues };
|
|
110
|
-
}
|
|
111
|
-
issues.push(...validateLimits([...attachments, ...voice], limits));
|
|
112
|
-
return { ok: issues.length === 0, issues };
|
|
113
|
-
}
|
|
114
|
-
function pickMediaRecorderMime(accept) {
|
|
115
|
-
const supported = (mime) => {
|
|
116
|
-
const recorder = dntShim.dntGlobalThis
|
|
117
|
-
.MediaRecorder;
|
|
118
|
-
return recorder === undefined || recorder.isTypeSupported(mime);
|
|
119
|
-
};
|
|
120
|
-
const fromCandidates = (pool) => pool.find(supported);
|
|
121
|
-
if (accept?.length) {
|
|
122
|
-
return (fromCandidates(RECORDER_CANDIDATES.filter((mime) => mimeAllowed(accept, mime))) ??
|
|
123
|
-
accept.find(supported));
|
|
124
|
-
}
|
|
125
|
-
return fromCandidates(RECORDER_CANDIDATES);
|
|
126
|
-
}
|
|
127
|
-
export { attachmentAcceptAttr, inputsFromSpec, pickMediaRecorderMime, validateProfileInputs };
|
|
@@ -1,10 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Headless profile-driven interface — spec, inputs, transcript folding.
|
|
3
|
-
*
|
|
4
|
-
* @module
|
|
5
|
-
*/
|
|
6
|
-
export { buildUserTurnBlocks, foldConversationTurn, foldTurnEvents, resetBlockIds, } from './blocks.js';
|
|
7
|
-
export { interfaceFrom, interfaceFromProfile, interfaceFromProjected } from './from-profile.js';
|
|
8
|
-
export { attachmentAcceptAttr, inputsFromSpec, pickMediaRecorderMime, validateProfileInputs, } from './inputs.js';
|
|
9
|
-
export type { AttachmentValidationCode, AttachmentValidationIssue, AttachmentValidationResult, FoldTurnEventsOptions, ImageProfileInterface, LiveProfileInterface, NormalizedModel, NormalizeModel, PendingAttachment, ProfileGuardrailsView, ProfileInputsInterface, ProfileInterface, ProfileInterfaceSource, ResolvedTools, SpeechProfileInterface, TextProfileInterface, TranscriptBlock, TranscriptBlockKind, UserTurnDraft, } from './types.js';
|
|
10
|
-
export { streamThoughtsEnabled } from './types.js';
|
package/esm/src/interface/mod.js
DELETED
|
@@ -1,9 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Headless profile-driven interface — spec, inputs, transcript folding.
|
|
3
|
-
*
|
|
4
|
-
* @module
|
|
5
|
-
*/
|
|
6
|
-
export { buildUserTurnBlocks, foldConversationTurn, foldTurnEvents, resetBlockIds, } from './blocks.js';
|
|
7
|
-
export { interfaceFrom, interfaceFromProfile, interfaceFromProjected } from './from-profile.js';
|
|
8
|
-
export { attachmentAcceptAttr, inputsFromSpec, pickMediaRecorderMime, validateProfileInputs, } from './inputs.js';
|
|
9
|
-
export { streamThoughtsEnabled } from './types.js';
|
|
@@ -1,153 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Headless interface contracts — profile-driven UI spec and transcript blocks.
|
|
3
|
-
*
|
|
4
|
-
* `ProfileInterface` is `Profile` with resolved `inputs`/`tools` and a serializable
|
|
5
|
-
* `guardrails` view. No parallel schema.
|
|
6
|
-
*
|
|
7
|
-
* @module
|
|
8
|
-
*/
|
|
9
|
-
import type { ProfileToolsSpec } from '../kernel/tools/types.js';
|
|
10
|
-
import type { ControlId, GroundingEvent, ImageProfile, LiveProfile, ModelId, Profile, ProfileGuardrailsSpec, ProfileModelSpec, ProfileOutputsSpec, ProjectedProfile, ProviderEvidenceEvent, RegisteredTool, SpeechProfile, TextProfile, ToolCallEvent, ToolId, TurnStop, TurnTokens } from '../kernel/types.js';
|
|
11
|
-
/** Guardrails visible to UI — egress enforcer functions are omitted. */
|
|
12
|
-
export type ProfileGuardrailsView = Pick<ProfileGuardrailsSpec, 'quota' | 'canary' | 'sanitizeInput' | 'redactSensitive'> & {
|
|
13
|
-
hasEgress: boolean;
|
|
14
|
-
};
|
|
15
|
-
/** `profile.model` with normalized `select` / `controls`. */
|
|
16
|
-
export type NormalizeModel<M extends ProfileModelSpec = ProfileModelSpec> = M & {
|
|
17
|
-
select: Record<string, ModelId> | null;
|
|
18
|
-
controls: ControlId[];
|
|
19
|
-
};
|
|
20
|
-
/** Resolved `inputs` — `ProfileInputsSpec` plus `acceptAttr` for file pickers. */
|
|
21
|
-
export interface ProfileInputsInterface {
|
|
22
|
-
text: boolean;
|
|
23
|
-
attachments: {
|
|
24
|
-
accept: string[];
|
|
25
|
-
acceptAttr: string;
|
|
26
|
-
} | null;
|
|
27
|
-
voice: {
|
|
28
|
-
accept: string[];
|
|
29
|
-
} | null;
|
|
30
|
-
maxFiles?: number;
|
|
31
|
-
maxBytes?: number;
|
|
32
|
-
maxTurnBytes?: number;
|
|
33
|
-
limitsByMime?: Record<string, number>;
|
|
34
|
-
slots?: Record<string, string[]>;
|
|
35
|
-
}
|
|
36
|
-
/** `profile.tools` plus resolved registry entries. */
|
|
37
|
-
export type ResolvedTools = ProfileToolsSpec & {
|
|
38
|
-
resolved: Array<RegisteredTool | {
|
|
39
|
-
name: ToolId;
|
|
40
|
-
missing: true;
|
|
41
|
-
}>;
|
|
42
|
-
};
|
|
43
|
-
export type NormalizedModel = NormalizeModel;
|
|
44
|
-
export type TextProfileInterface = Omit<TextProfile, 'inputs' | 'tools' | 'guardrails' | 'model'> & {
|
|
45
|
-
model: NormalizeModel<TextProfile['model']>;
|
|
46
|
-
inputs: ProfileInputsInterface;
|
|
47
|
-
tools: ResolvedTools;
|
|
48
|
-
guardrails?: ProfileGuardrailsView;
|
|
49
|
-
};
|
|
50
|
-
export type ImageProfileInterface = Omit<ImageProfile, 'inputs' | 'tools' | 'guardrails' | 'model'> & {
|
|
51
|
-
model: NormalizeModel<ImageProfile['model']>;
|
|
52
|
-
inputs: ProfileInputsInterface;
|
|
53
|
-
tools: ResolvedTools;
|
|
54
|
-
guardrails?: ProfileGuardrailsView;
|
|
55
|
-
};
|
|
56
|
-
export type SpeechProfileInterface = Omit<SpeechProfile, 'guardrails' | 'model'> & {
|
|
57
|
-
model: NormalizeModel<SpeechProfile['model']>;
|
|
58
|
-
inputs: ProfileInputsInterface;
|
|
59
|
-
guardrails?: ProfileGuardrailsView;
|
|
60
|
-
};
|
|
61
|
-
export type LiveProfileInterface = Omit<LiveProfile, 'inputs' | 'tools' | 'model' | 'guardrails'> & {
|
|
62
|
-
model: NormalizeModel<LiveProfile['model']>;
|
|
63
|
-
inputs: ProfileInputsInterface;
|
|
64
|
-
tools: ResolvedTools;
|
|
65
|
-
guardrails?: ProfileGuardrailsView;
|
|
66
|
-
};
|
|
67
|
-
export type ProfileInterface = TextProfileInterface | ImageProfileInterface | SpeechProfileInterface | LiveProfileInterface;
|
|
68
|
-
export type ProfileInterfaceSource = Profile | ProjectedProfile;
|
|
69
|
-
export type TranscriptBlockKind = 'user-text' | 'user-attachment' | 'user-voice' | 'thought' | 'text' | 'tool' | 'structured' | 'media' | 'grounding' | 'evidence' | 'error' | 'turn-done';
|
|
70
|
-
export interface TranscriptBlockBase {
|
|
71
|
-
id: string;
|
|
72
|
-
kind: TranscriptBlockKind;
|
|
73
|
-
}
|
|
74
|
-
export interface UserTextBlock extends TranscriptBlockBase {
|
|
75
|
-
kind: 'user-text';
|
|
76
|
-
text: string;
|
|
77
|
-
}
|
|
78
|
-
export interface UserAttachmentBlock extends TranscriptBlockBase {
|
|
79
|
-
kind: 'user-attachment' | 'user-voice';
|
|
80
|
-
name: string;
|
|
81
|
-
mimeType: string;
|
|
82
|
-
sizeBytes: number;
|
|
83
|
-
}
|
|
84
|
-
export interface ThoughtBlock extends TranscriptBlockBase {
|
|
85
|
-
kind: 'thought';
|
|
86
|
-
text: string;
|
|
87
|
-
}
|
|
88
|
-
export interface TextBlock extends TranscriptBlockBase {
|
|
89
|
-
kind: 'text';
|
|
90
|
-
text: string;
|
|
91
|
-
}
|
|
92
|
-
export interface ToolBlock extends TranscriptBlockBase {
|
|
93
|
-
kind: 'tool';
|
|
94
|
-
tool: ToolCallEvent & {
|
|
95
|
-
id?: string;
|
|
96
|
-
};
|
|
97
|
-
}
|
|
98
|
-
export interface StructuredBlock extends TranscriptBlockBase {
|
|
99
|
-
kind: 'structured';
|
|
100
|
-
value: unknown;
|
|
101
|
-
}
|
|
102
|
-
export interface MediaBlock extends TranscriptBlockBase {
|
|
103
|
-
kind: 'media';
|
|
104
|
-
mimeType: string;
|
|
105
|
-
data: string;
|
|
106
|
-
}
|
|
107
|
-
export interface GroundingBlock extends TranscriptBlockBase {
|
|
108
|
-
kind: 'grounding';
|
|
109
|
-
grounding: GroundingEvent;
|
|
110
|
-
}
|
|
111
|
-
export interface EvidenceBlock extends TranscriptBlockBase {
|
|
112
|
-
kind: 'evidence';
|
|
113
|
-
evidence: ProviderEvidenceEvent;
|
|
114
|
-
}
|
|
115
|
-
export interface ErrorBlock extends TranscriptBlockBase {
|
|
116
|
-
kind: 'error';
|
|
117
|
-
message: string;
|
|
118
|
-
}
|
|
119
|
-
export interface TurnDoneBlock extends TranscriptBlockBase {
|
|
120
|
-
kind: 'turn-done';
|
|
121
|
-
stop?: TurnStop;
|
|
122
|
-
tokens?: TurnTokens;
|
|
123
|
-
interactionId?: string;
|
|
124
|
-
compaction?: boolean;
|
|
125
|
-
}
|
|
126
|
-
export type TranscriptBlock = UserTextBlock | UserAttachmentBlock | ThoughtBlock | TextBlock | ToolBlock | StructuredBlock | MediaBlock | GroundingBlock | EvidenceBlock | ErrorBlock | TurnDoneBlock;
|
|
127
|
-
export interface PendingAttachment {
|
|
128
|
-
name: string;
|
|
129
|
-
mimeType: string;
|
|
130
|
-
sizeBytes: number;
|
|
131
|
-
}
|
|
132
|
-
export type AttachmentValidationCode = 'mime_not_allowed' | 'too_many_files' | 'file_too_large' | 'turn_too_large' | 'limits_unconfigured';
|
|
133
|
-
export interface AttachmentValidationIssue {
|
|
134
|
-
code: AttachmentValidationCode;
|
|
135
|
-
message: string;
|
|
136
|
-
fileName?: string;
|
|
137
|
-
}
|
|
138
|
-
export interface AttachmentValidationResult {
|
|
139
|
-
ok: boolean;
|
|
140
|
-
issues: AttachmentValidationIssue[];
|
|
141
|
-
}
|
|
142
|
-
export interface UserTurnDraft {
|
|
143
|
-
text?: string;
|
|
144
|
-
attachments?: PendingAttachment[];
|
|
145
|
-
voice?: PendingAttachment[];
|
|
146
|
-
}
|
|
147
|
-
export interface FoldTurnEventsOptions {
|
|
148
|
-
showThoughts?: boolean;
|
|
149
|
-
idPrefix?: string;
|
|
150
|
-
}
|
|
151
|
-
/** Whether `foldTurnEvents` should emit thought blocks for this profile. */
|
|
152
|
-
declare function streamThoughtsEnabled(outputs?: ProfileOutputsSpec): boolean;
|
|
153
|
-
export { streamThoughtsEnabled };
|
|
@@ -1,13 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Headless interface contracts — profile-driven UI spec and transcript blocks.
|
|
3
|
-
*
|
|
4
|
-
* `ProfileInterface` is `Profile` with resolved `inputs`/`tools` and a serializable
|
|
5
|
-
* `guardrails` view. No parallel schema.
|
|
6
|
-
*
|
|
7
|
-
* @module
|
|
8
|
-
*/
|
|
9
|
-
/** Whether `foldTurnEvents` should emit thought blocks for this profile. */
|
|
10
|
-
function streamThoughtsEnabled(outputs) {
|
|
11
|
-
return outputs?.streaming?.streamThoughts !== false;
|
|
12
|
-
}
|
|
13
|
-
export { streamThoughtsEnabled };
|