@hanzo/ui 8.27.3 → 8.27.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.
- package/dist/backdrop/Backdrop.cjs +420 -0
- package/dist/backdrop/Backdrop.d.ts +53 -0
- package/dist/backdrop/Backdrop.d.ts.map +1 -0
- package/dist/backdrop/Backdrop.js +418 -0
- package/dist/backdrop/Backdrop.js.map +1 -0
- package/dist/backdrop/index.cjs +50 -0
- package/dist/backdrop/index.d.ts +29 -0
- package/dist/backdrop/index.d.ts.map +1 -0
- package/dist/backdrop/index.js +29 -0
- package/dist/backdrop/index.js.map +1 -0
- package/dist/backdrop/scene.cjs +439 -0
- package/dist/backdrop/scene.d.ts +235 -0
- package/dist/backdrop/scene.d.ts.map +1 -0
- package/dist/backdrop/scene.js +423 -0
- package/dist/backdrop/scene.js.map +1 -0
- package/dist/chat/Chat.cjs +23 -1
- package/dist/chat/Chat.d.ts +6 -3
- package/dist/chat/Chat.d.ts.map +1 -1
- package/dist/chat/Chat.js +23 -1
- package/dist/chat/Chat.js.map +1 -1
- package/dist/chat/Inspector.cjs +51 -0
- package/dist/chat/Inspector.d.ts +49 -0
- package/dist/chat/Inspector.d.ts.map +1 -0
- package/dist/chat/Inspector.js +49 -0
- package/dist/chat/Inspector.js.map +1 -0
- package/dist/chat/Message.cjs +3 -1
- package/dist/chat/Message.d.ts +3 -1
- package/dist/chat/Message.d.ts.map +1 -1
- package/dist/chat/Message.js +3 -1
- package/dist/chat/Message.js.map +1 -1
- package/dist/chat/Parts.cjs +159 -0
- package/dist/chat/Parts.d.ts +186 -0
- package/dist/chat/Parts.d.ts.map +1 -0
- package/dist/chat/Parts.js +153 -0
- package/dist/chat/Parts.js.map +1 -0
- package/dist/chat/Persona.cjs +34 -0
- package/dist/chat/Persona.d.ts +37 -0
- package/dist/chat/Persona.d.ts.map +1 -0
- package/dist/chat/Persona.js +30 -0
- package/dist/chat/Persona.js.map +1 -0
- package/dist/chat/Preview.cjs +42 -0
- package/dist/chat/Preview.d.ts +36 -0
- package/dist/chat/Preview.d.ts.map +1 -0
- package/dist/chat/Preview.js +40 -0
- package/dist/chat/Preview.js.map +1 -0
- package/dist/chat/directive.cjs +272 -0
- package/dist/chat/directive.d.ts +167 -0
- package/dist/chat/directive.d.ts.map +1 -0
- package/dist/chat/directive.js +266 -0
- package/dist/chat/directive.js.map +1 -0
- package/dist/chat/index.cjs +59 -4
- package/dist/chat/index.d.ts +31 -3
- package/dist/chat/index.d.ts.map +1 -1
- package/dist/chat/index.js +31 -3
- package/dist/chat/index.js.map +1 -1
- package/dist/gallery.html +4 -4
- package/dist/styles.css +3 -3
- package/dist/theme.css +3 -3
- package/package.json +7 -1
|
@@ -0,0 +1,272 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.made = exports.EMPTY = exports.answer = exports.TOOLS = void 0;
|
|
4
|
+
exports.read = read;
|
|
5
|
+
exports.stage = stage;
|
|
6
|
+
/** The moods a persona can be asked for — `Emotion`, as a schema enum. */
|
|
7
|
+
const MOODS = [
|
|
8
|
+
'idle',
|
|
9
|
+
'listening',
|
|
10
|
+
'thinking',
|
|
11
|
+
'speaking',
|
|
12
|
+
'happy',
|
|
13
|
+
'sad',
|
|
14
|
+
'surprised',
|
|
15
|
+
];
|
|
16
|
+
const KINDS = ['canvas', 'code', 'view'];
|
|
17
|
+
/**
|
|
18
|
+
* The three tools, ready to pass to `messages.stream`.
|
|
19
|
+
*
|
|
20
|
+
* Descriptions say WHEN to call, not just what the tool is: a model reaches for
|
|
21
|
+
* a tool on its trigger condition, and a description that only names the tool
|
|
22
|
+
* is the common way to get a tool that never fires.
|
|
23
|
+
*/
|
|
24
|
+
exports.TOOLS = [
|
|
25
|
+
{
|
|
26
|
+
name: 'feel',
|
|
27
|
+
description: 'Set the mood of the on-screen persona. Call it when what you are doing changes — before a long piece of work, when you reach an answer, when something goes wrong. The mood holds until you change it, so call it again rather than leaving a stale one.',
|
|
28
|
+
input_schema: {
|
|
29
|
+
type: 'object',
|
|
30
|
+
properties: {
|
|
31
|
+
emotion: { type: 'string', enum: MOODS, description: 'The mood to hold.' },
|
|
32
|
+
},
|
|
33
|
+
required: ['emotion'],
|
|
34
|
+
},
|
|
35
|
+
},
|
|
36
|
+
{
|
|
37
|
+
name: 'show',
|
|
38
|
+
description: 'Render an interface inline for the person to look at. Call it whenever a layout, a screen, a chart or a mockup would answer better than prose. `markup` is a self-contained HTML document including its own <style>; it is displayed with scripting disabled, so write markup and CSS, never script.',
|
|
39
|
+
input_schema: {
|
|
40
|
+
type: 'object',
|
|
41
|
+
properties: {
|
|
42
|
+
title: { type: 'string', description: 'A short name for the thing.' },
|
|
43
|
+
kind: {
|
|
44
|
+
type: 'string',
|
|
45
|
+
enum: KINDS,
|
|
46
|
+
description: 'view for a rendered interface, canvas for a document, code for source.',
|
|
47
|
+
},
|
|
48
|
+
markup: { type: 'string', description: 'A self-contained HTML document.' },
|
|
49
|
+
},
|
|
50
|
+
required: ['title', 'kind', 'markup'],
|
|
51
|
+
},
|
|
52
|
+
},
|
|
53
|
+
{
|
|
54
|
+
name: 'report',
|
|
55
|
+
description: 'Fill the side panel with an account of this run. Call it once you know what the run did: a one-paragraph summary, what you were given, and what you produced. The panel is what the person reads to check your work, so name real values rather than describing them.',
|
|
56
|
+
input_schema: {
|
|
57
|
+
type: 'object',
|
|
58
|
+
properties: {
|
|
59
|
+
summary: { type: 'string', description: 'One paragraph: what happened.' },
|
|
60
|
+
inputs: { type: 'object', description: 'Name to value, what the run was given.' },
|
|
61
|
+
outputs: { type: 'object', description: 'Name to value, what the run produced.' },
|
|
62
|
+
},
|
|
63
|
+
required: ['summary'],
|
|
64
|
+
},
|
|
65
|
+
},
|
|
66
|
+
];
|
|
67
|
+
/* -------------------------------------------------------------------- reading */
|
|
68
|
+
/** One field off an untrusted object. The wire is a boundary; nothing below
|
|
69
|
+
* trusts a shape it has not checked. */
|
|
70
|
+
const str = (value, key) => {
|
|
71
|
+
const x = value?.[key];
|
|
72
|
+
return typeof x === 'string' ? x : undefined;
|
|
73
|
+
};
|
|
74
|
+
const facts = (value, key) => {
|
|
75
|
+
const x = value?.[key];
|
|
76
|
+
return x != null && typeof x === 'object' && !Array.isArray(x) ? x : undefined;
|
|
77
|
+
};
|
|
78
|
+
const one = (value, key, set) => {
|
|
79
|
+
const x = str(value, key);
|
|
80
|
+
return set.includes(x) ? x : undefined;
|
|
81
|
+
};
|
|
82
|
+
/**
|
|
83
|
+
* A tool call, narrowed to a directive — or `undefined` for anything else.
|
|
84
|
+
*
|
|
85
|
+
* `undefined` is not a failure. Most tool calls in a turn are the caller's own
|
|
86
|
+
* tools, and those belong in the transcript as steps; this answers only "is
|
|
87
|
+
* this one of ours, and is it well-formed". A directive missing a required
|
|
88
|
+
* field is not ours either — a half-read `show` would draw an empty frame.
|
|
89
|
+
*/
|
|
90
|
+
function read(name, id, input) {
|
|
91
|
+
switch (name) {
|
|
92
|
+
case 'feel': {
|
|
93
|
+
const emotion = one(input, 'emotion', MOODS);
|
|
94
|
+
return emotion ? { name, id, emotion } : undefined;
|
|
95
|
+
}
|
|
96
|
+
case 'show': {
|
|
97
|
+
const title = str(input, 'title');
|
|
98
|
+
const markup = str(input, 'markup');
|
|
99
|
+
const kind = one(input, 'kind', KINDS) ?? 'view';
|
|
100
|
+
return title && markup ? { name, id, title, kind, markup } : undefined;
|
|
101
|
+
}
|
|
102
|
+
case 'report': {
|
|
103
|
+
const summary = str(input, 'summary');
|
|
104
|
+
return summary
|
|
105
|
+
? { name, id, summary, inputs: facts(input, 'inputs'), outputs: facts(input, 'outputs') }
|
|
106
|
+
: undefined;
|
|
107
|
+
}
|
|
108
|
+
default:
|
|
109
|
+
return undefined;
|
|
110
|
+
}
|
|
111
|
+
}
|
|
112
|
+
/** What a directive is answered with. Drawing IS the execution, so the result
|
|
113
|
+
* is a confirmation — but it has to be sent, or the turn never continues. */
|
|
114
|
+
const answer = (directive) => ({
|
|
115
|
+
type: 'tool_result',
|
|
116
|
+
tool_use_id: directive.id,
|
|
117
|
+
content: SAID[directive.name],
|
|
118
|
+
});
|
|
119
|
+
exports.answer = answer;
|
|
120
|
+
const SAID = {
|
|
121
|
+
feel: 'The persona is showing it.',
|
|
122
|
+
show: 'Rendered for the person to see.',
|
|
123
|
+
report: 'The panel is showing it.',
|
|
124
|
+
};
|
|
125
|
+
/** A stage with nothing on it. The starting value for a turn. */
|
|
126
|
+
exports.EMPTY = { emotion: 'idle', parts: [], ran: [], open: {} };
|
|
127
|
+
/** Adjacent prose, kept as one part. `join` does this at render time too, but
|
|
128
|
+
* a fold that appends per delta would hand it thousands of fragments. */
|
|
129
|
+
const add = (parts, part) => {
|
|
130
|
+
const last = parts[parts.length - 1];
|
|
131
|
+
if ((part.type === 'text' || part.type === 'reasoning') && last?.type === part.type) {
|
|
132
|
+
return [...parts.slice(0, -1), { type: part.type, text: last.text + part.text }];
|
|
133
|
+
}
|
|
134
|
+
return [...parts, part];
|
|
135
|
+
};
|
|
136
|
+
/** The mood the stream implies, unless the model has fixed one. */
|
|
137
|
+
const move = (prev, emotion) => prev.held ?? emotion;
|
|
138
|
+
/** Apply a directive. */
|
|
139
|
+
const apply = (prev, d) => {
|
|
140
|
+
const ran = [...prev.ran, d];
|
|
141
|
+
switch (d.name) {
|
|
142
|
+
case 'feel':
|
|
143
|
+
return { ...prev, ran, held: d.emotion, emotion: d.emotion };
|
|
144
|
+
case 'show':
|
|
145
|
+
return {
|
|
146
|
+
...prev,
|
|
147
|
+
ran,
|
|
148
|
+
parts: add(prev.parts, {
|
|
149
|
+
type: 'artifact',
|
|
150
|
+
title: d.title,
|
|
151
|
+
kind: d.kind,
|
|
152
|
+
id: d.id,
|
|
153
|
+
markup: d.markup,
|
|
154
|
+
}),
|
|
155
|
+
};
|
|
156
|
+
case 'report':
|
|
157
|
+
return {
|
|
158
|
+
...prev,
|
|
159
|
+
ran,
|
|
160
|
+
report: { summary: d.summary, inputs: d.inputs, outputs: d.outputs },
|
|
161
|
+
};
|
|
162
|
+
}
|
|
163
|
+
};
|
|
164
|
+
/**
|
|
165
|
+
* The stream, folded into what is on screen.
|
|
166
|
+
*
|
|
167
|
+
* Pure, and total over the wire: an event this does not recognise returns the
|
|
168
|
+
* stage unchanged rather than throwing, because a stream carries `ping` and
|
|
169
|
+
* `message_delta` and whatever it gains next.
|
|
170
|
+
*/
|
|
171
|
+
function stage(prev, frame) {
|
|
172
|
+
switch (frame.type) {
|
|
173
|
+
// A new turn reads fresh. Only the held mood clears — the parts and the
|
|
174
|
+
// report belong to whoever is keeping them.
|
|
175
|
+
case 'message_start':
|
|
176
|
+
return { ...prev, held: undefined, emotion: 'thinking' };
|
|
177
|
+
case 'content_block_start': {
|
|
178
|
+
const kind = str(frame.content_block, 'type');
|
|
179
|
+
if (kind === 'tool_use') {
|
|
180
|
+
const id = str(frame.content_block, 'id') ?? '';
|
|
181
|
+
const name = str(frame.content_block, 'name') ?? '';
|
|
182
|
+
return {
|
|
183
|
+
...prev,
|
|
184
|
+
emotion: move(prev, 'thinking'),
|
|
185
|
+
open: { ...prev.open, [frame.index ?? 0]: { id, name, json: '' } },
|
|
186
|
+
};
|
|
187
|
+
}
|
|
188
|
+
if (kind === 'thinking')
|
|
189
|
+
return { ...prev, emotion: move(prev, 'thinking') };
|
|
190
|
+
if (kind === 'text')
|
|
191
|
+
return { ...prev, emotion: move(prev, 'speaking') };
|
|
192
|
+
return prev;
|
|
193
|
+
}
|
|
194
|
+
case 'content_block_delta': {
|
|
195
|
+
const kind = str(frame.delta, 'type');
|
|
196
|
+
if (kind === 'text_delta') {
|
|
197
|
+
const text = str(frame.delta, 'text') ?? '';
|
|
198
|
+
return {
|
|
199
|
+
...prev,
|
|
200
|
+
emotion: move(prev, 'speaking'),
|
|
201
|
+
parts: add(prev.parts, { type: 'text', text }),
|
|
202
|
+
};
|
|
203
|
+
}
|
|
204
|
+
if (kind === 'thinking_delta') {
|
|
205
|
+
const text = str(frame.delta, 'thinking') ?? '';
|
|
206
|
+
return {
|
|
207
|
+
...prev,
|
|
208
|
+
emotion: move(prev, 'thinking'),
|
|
209
|
+
parts: add(prev.parts, { type: 'reasoning', text }),
|
|
210
|
+
};
|
|
211
|
+
}
|
|
212
|
+
if (kind === 'input_json_delta') {
|
|
213
|
+
const at = frame.index ?? 0;
|
|
214
|
+
const call = prev.open[at];
|
|
215
|
+
if (!call)
|
|
216
|
+
return prev;
|
|
217
|
+
const json = call.json + (str(frame.delta, 'partial_json') ?? '');
|
|
218
|
+
return { ...prev, open: { ...prev.open, [at]: { ...call, json } } };
|
|
219
|
+
}
|
|
220
|
+
return prev;
|
|
221
|
+
}
|
|
222
|
+
case 'content_block_stop': {
|
|
223
|
+
const at = frame.index ?? 0;
|
|
224
|
+
const call = prev.open[at];
|
|
225
|
+
if (!call)
|
|
226
|
+
return prev;
|
|
227
|
+
const { [at]: _closed, ...open } = prev.open;
|
|
228
|
+
const next = { ...prev, open };
|
|
229
|
+
const directive = read(call.name, call.id, parse(call.json));
|
|
230
|
+
if (directive)
|
|
231
|
+
return apply(next, directive);
|
|
232
|
+
// Somebody else's tool. It belongs in the transcript as a step.
|
|
233
|
+
return {
|
|
234
|
+
...next,
|
|
235
|
+
parts: add(next.parts, {
|
|
236
|
+
type: 'toolCall',
|
|
237
|
+
name: call.name,
|
|
238
|
+
id: call.id,
|
|
239
|
+
args: parse(call.json),
|
|
240
|
+
}),
|
|
241
|
+
};
|
|
242
|
+
}
|
|
243
|
+
// The turn is over. The mood the model chose survives it — a turn that
|
|
244
|
+
// ended happy rests happy; one that said nothing rests idle.
|
|
245
|
+
case 'message_stop':
|
|
246
|
+
return { ...prev, emotion: prev.held ?? 'idle' };
|
|
247
|
+
case 'error':
|
|
248
|
+
return { ...prev, emotion: move(prev, 'sad') };
|
|
249
|
+
default:
|
|
250
|
+
return prev;
|
|
251
|
+
}
|
|
252
|
+
}
|
|
253
|
+
/** A tool's arguments. An empty block sends no deltas at all, and a truncated
|
|
254
|
+
* turn leaves a fragment; neither should take the page down. */
|
|
255
|
+
const parse = (json) => {
|
|
256
|
+
if (!json)
|
|
257
|
+
return undefined;
|
|
258
|
+
try {
|
|
259
|
+
return JSON.parse(json);
|
|
260
|
+
}
|
|
261
|
+
catch {
|
|
262
|
+
return undefined;
|
|
263
|
+
}
|
|
264
|
+
};
|
|
265
|
+
/**
|
|
266
|
+
* What the turn produced, for the panel.
|
|
267
|
+
*
|
|
268
|
+
* Prose is the answer and belongs in the thread; everything else is evidence —
|
|
269
|
+
* what ran, what came back, what was made — and that is what the panel is for.
|
|
270
|
+
*/
|
|
271
|
+
const made = (from) => from.parts.filter((part) => part.type !== 'text' && part.type !== 'reasoning');
|
|
272
|
+
exports.made = made;
|
|
@@ -0,0 +1,167 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* The control channel: three tools the model calls to drive the interface.
|
|
3
|
+
*
|
|
4
|
+
* A model already knows how to call a tool, so generative UI needs no second
|
|
5
|
+
* protocol beside tool use. `TOOLS` are ordinary Anthropic tools a caller hands
|
|
6
|
+
* to `messages.stream`; the client executes them by DRAWING rather than by
|
|
7
|
+
* computing, and answers each with a `tool_result` exactly as it would any
|
|
8
|
+
* other. That is the whole design — no new wire, no parallel channel, nothing
|
|
9
|
+
* for a model to learn.
|
|
10
|
+
*
|
|
11
|
+
* feel({ emotion }) the persona's mood
|
|
12
|
+
* show({ title, kind, markup }) a generated interface, rendered
|
|
13
|
+
* report({ summary, inputs, outputs }) the run, in the side panel
|
|
14
|
+
*
|
|
15
|
+
* ONE WORD EACH, and no dots. A tool name is `[a-zA-Z0-9_-]` — `persona.set`
|
|
16
|
+
* is rejected by the API before the model ever sees it — so a namespace has to
|
|
17
|
+
* be spelled some other way or not at all. Not at all: three verbs the model
|
|
18
|
+
* reads without a legend beat three compounds that only look organised.
|
|
19
|
+
*
|
|
20
|
+
* `stage` is the fold from the stream to what is on screen. It takes the raw
|
|
21
|
+
* `content_block_*` events, so the persona moves even in a turn that calls
|
|
22
|
+
* nothing — thinking while the model thinks, speaking on the first word — and a
|
|
23
|
+
* `feel` directive overrides that reading until the model changes its mind.
|
|
24
|
+
* One fold, one state, three components read it.
|
|
25
|
+
*
|
|
26
|
+
* Nothing here imports `@hanzo/ai`. `Frame` is structural and open, the way
|
|
27
|
+
* `words`'s `Part` is open: it reads the wire, and the wire is not ours to
|
|
28
|
+
* close. An `AnthropicStreamEvent` satisfies it with no dependency in either
|
|
29
|
+
* direction, and `directive.test.ts` pins that assignability both ways.
|
|
30
|
+
*/
|
|
31
|
+
import type { ArtifactKind } from '../agents/Pane.js';
|
|
32
|
+
import type { MessagePart } from './Parts.js';
|
|
33
|
+
import type { Emotion } from './Persona.js';
|
|
34
|
+
/** What the model asked the interface to do. `name` is the tool it called, so
|
|
35
|
+
* the discriminant and the wire are the same word. */
|
|
36
|
+
export type Directive =
|
|
37
|
+
/** Move the persona. Holds until the model says otherwise. */
|
|
38
|
+
{
|
|
39
|
+
name: 'feel';
|
|
40
|
+
id: string;
|
|
41
|
+
emotion: Emotion;
|
|
42
|
+
}
|
|
43
|
+
/** Draw an interface the model wrote. `markup` is HTML, rendered inert. */
|
|
44
|
+
| {
|
|
45
|
+
name: 'show';
|
|
46
|
+
id: string;
|
|
47
|
+
title: string;
|
|
48
|
+
kind: ArtifactKind;
|
|
49
|
+
markup: string;
|
|
50
|
+
}
|
|
51
|
+
/** Fill the side panel with the run's own account of itself. */
|
|
52
|
+
| {
|
|
53
|
+
name: 'report';
|
|
54
|
+
id: string;
|
|
55
|
+
summary: string;
|
|
56
|
+
inputs?: Facts;
|
|
57
|
+
outputs?: Facts;
|
|
58
|
+
};
|
|
59
|
+
/** Name → value. What a run was given, and what it produced. */
|
|
60
|
+
export type Facts = Record<string, unknown>;
|
|
61
|
+
/** A `report` directive's payload, without the envelope. */
|
|
62
|
+
export interface Report {
|
|
63
|
+
summary: string;
|
|
64
|
+
inputs?: Facts;
|
|
65
|
+
outputs?: Facts;
|
|
66
|
+
}
|
|
67
|
+
/**
|
|
68
|
+
* A tool definition, structurally.
|
|
69
|
+
*
|
|
70
|
+
* A `type` alias and not an `interface` on purpose: only a type literal gets an
|
|
71
|
+
* implicit index signature, and without one this is NOT assignable to
|
|
72
|
+
* `AnthropicTool` (which carries `[key: string]: unknown`). An interface here
|
|
73
|
+
* would typecheck in this package and fail at every call site.
|
|
74
|
+
*/
|
|
75
|
+
export type Tool = {
|
|
76
|
+
name: string;
|
|
77
|
+
description: string;
|
|
78
|
+
input_schema: {
|
|
79
|
+
type: 'object';
|
|
80
|
+
properties: Record<string, unknown>;
|
|
81
|
+
required?: string[];
|
|
82
|
+
};
|
|
83
|
+
};
|
|
84
|
+
/**
|
|
85
|
+
* The three tools, ready to pass to `messages.stream`.
|
|
86
|
+
*
|
|
87
|
+
* Descriptions say WHEN to call, not just what the tool is: a model reaches for
|
|
88
|
+
* a tool on its trigger condition, and a description that only names the tool
|
|
89
|
+
* is the common way to get a tool that never fires.
|
|
90
|
+
*/
|
|
91
|
+
export declare const TOOLS: Tool[];
|
|
92
|
+
/**
|
|
93
|
+
* A tool call, narrowed to a directive — or `undefined` for anything else.
|
|
94
|
+
*
|
|
95
|
+
* `undefined` is not a failure. Most tool calls in a turn are the caller's own
|
|
96
|
+
* tools, and those belong in the transcript as steps; this answers only "is
|
|
97
|
+
* this one of ours, and is it well-formed". A directive missing a required
|
|
98
|
+
* field is not ours either — a half-read `show` would draw an empty frame.
|
|
99
|
+
*/
|
|
100
|
+
export declare function read(name: string, id: string, input: unknown): Directive | undefined;
|
|
101
|
+
/** What a directive is answered with. Drawing IS the execution, so the result
|
|
102
|
+
* is a confirmation — but it has to be sent, or the turn never continues. */
|
|
103
|
+
export declare const answer: (directive: Directive) => {
|
|
104
|
+
type: 'tool_result';
|
|
105
|
+
tool_use_id: string;
|
|
106
|
+
content: string;
|
|
107
|
+
};
|
|
108
|
+
/**
|
|
109
|
+
* One event off the model's stream.
|
|
110
|
+
*
|
|
111
|
+
* Open, and `type` is the only field it insists on — which is also what keeps
|
|
112
|
+
* every `@hanzo/ai` event assignable to it. `content_block` and `delta` are
|
|
113
|
+
* `unknown` deliberately: their shape varies per block and per provider, a
|
|
114
|
+
* narrower spelling makes half the union unassignable, and this is a boundary
|
|
115
|
+
* where reading defensively is the correct habit anyway.
|
|
116
|
+
*/
|
|
117
|
+
export interface Frame {
|
|
118
|
+
type: string;
|
|
119
|
+
/** Which content block, on the three events that name one. */
|
|
120
|
+
index?: number;
|
|
121
|
+
/** `content_block_start`'s block. */
|
|
122
|
+
content_block?: unknown;
|
|
123
|
+
/** `content_block_delta`'s delta. */
|
|
124
|
+
delta?: unknown;
|
|
125
|
+
}
|
|
126
|
+
/** A tool call still arriving. Its `input` is JSON split across deltas and is
|
|
127
|
+
* not parseable until the block stops. */
|
|
128
|
+
interface Call {
|
|
129
|
+
id: string;
|
|
130
|
+
name: string;
|
|
131
|
+
json: string;
|
|
132
|
+
}
|
|
133
|
+
/** What the model has made of the interface. */
|
|
134
|
+
export interface Stage {
|
|
135
|
+
/** What the persona is doing — the mood to draw. */
|
|
136
|
+
emotion: Emotion;
|
|
137
|
+
/** The mood a `feel` directive fixed. While set, the stream does not move the
|
|
138
|
+
* persona; the model's word outranks the reading. */
|
|
139
|
+
held?: Emotion;
|
|
140
|
+
/** The turn, as parts. Directives that draw produce one; the rest do not. */
|
|
141
|
+
parts: readonly MessagePart[];
|
|
142
|
+
/** The side panel's content, once `report` has landed. */
|
|
143
|
+
report?: Report;
|
|
144
|
+
/** Every directive this turn, in order. `ran.map(answer)` is the reply. */
|
|
145
|
+
ran: readonly Directive[];
|
|
146
|
+
/** Tool blocks still arriving, by index. */
|
|
147
|
+
open: Readonly<Record<number, Call>>;
|
|
148
|
+
}
|
|
149
|
+
/** A stage with nothing on it. The starting value for a turn. */
|
|
150
|
+
export declare const EMPTY: Stage;
|
|
151
|
+
/**
|
|
152
|
+
* The stream, folded into what is on screen.
|
|
153
|
+
*
|
|
154
|
+
* Pure, and total over the wire: an event this does not recognise returns the
|
|
155
|
+
* stage unchanged rather than throwing, because a stream carries `ping` and
|
|
156
|
+
* `message_delta` and whatever it gains next.
|
|
157
|
+
*/
|
|
158
|
+
export declare function stage(prev: Stage, frame: Frame): Stage;
|
|
159
|
+
/**
|
|
160
|
+
* What the turn produced, for the panel.
|
|
161
|
+
*
|
|
162
|
+
* Prose is the answer and belongs in the thread; everything else is evidence —
|
|
163
|
+
* what ran, what came back, what was made — and that is what the panel is for.
|
|
164
|
+
*/
|
|
165
|
+
export declare const made: (from: Stage) => MessagePart[];
|
|
166
|
+
export {};
|
|
167
|
+
//# sourceMappingURL=directive.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"directive.d.ts","sourceRoot":"","sources":["../../src/chat/directive.ts"],"names":[],"mappings":"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"}
|