@slopus/happy-agent-client 0.0.116 → 0.0.119

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.
@@ -0,0 +1,316 @@
1
+ /**
2
+ * Media layout HTML: the small subset of HTML and CSS an agent writes to arrange media it showed,
3
+ * either as `present_files`' `layout` argument or as a block in its Markdown reply. This one
4
+ * parser turns it into the typed tree clients render, so the daemon and every client agree on
5
+ * exactly what a layout means. No HTML ever reaches a renderer.
6
+ */
7
+ import { html as htmlSpec, parse } from "parse5";
8
+ import { parseMediaLayoutHtmlStyle } from "./mediaLayoutHtmlStyle.js";
9
+ /** The most layout HTML that is read, in UTF-16 code units; a longer layout is not used. */
10
+ export const MAX_MEDIA_LAYOUT_HTML_LENGTH = 32 * 1024;
11
+ const MAX_DEPTH = 12;
12
+ const MAX_NODES = 500;
13
+ const MAX_TEXT = 8000;
14
+ const MAX_ALT = 1000;
15
+ const ELEMENT_TAGS = {
16
+ div: "div",
17
+ section: "section",
18
+ figure: "figure",
19
+ figcaption: "figcaption",
20
+ p: "p",
21
+ span: "span",
22
+ strong: "strong",
23
+ em: "em",
24
+ code: "code",
25
+ };
26
+ const BLOCK_TAGS = new Set(["div", "section", "figure", "figcaption", "p"]);
27
+ /**
28
+ * Tags left out together with everything inside them: they run code, load or embed something,
29
+ * take input, or hold styling and metadata rather than content.
30
+ */
31
+ const DROPPED_TAGS = new Set([
32
+ "applet",
33
+ "area",
34
+ "audio",
35
+ "base",
36
+ "button",
37
+ "canvas",
38
+ "dialog",
39
+ "embed",
40
+ "form",
41
+ "frame",
42
+ "frameset",
43
+ "head",
44
+ "iframe",
45
+ "input",
46
+ "link",
47
+ "map",
48
+ "math",
49
+ "meta",
50
+ "noscript",
51
+ "object",
52
+ "option",
53
+ "portal",
54
+ "script",
55
+ "select",
56
+ "slot",
57
+ "source",
58
+ "style",
59
+ "svg",
60
+ "template",
61
+ "textarea",
62
+ "title",
63
+ "track",
64
+ "video",
65
+ ]);
66
+ /**
67
+ * Turn media layout HTML into the typed tree a client renders.
68
+ *
69
+ * The HTML is parsed by parse5, a spec-compliant parser, so tags, attributes, and entities mean
70
+ * what a browser would take them to mean, and malformed markup is repaired the way a browser
71
+ * repairs it. The tree is then rebuilt from what the subset allows, and nothing fails: a tag the
72
+ * subset lacks is unwrapped and its content kept, a tag that runs, loads, or embeds something is
73
+ * left out with its content, other attributes and declarations are left out, and an image whose
74
+ * `src` the resolver does not know, or whose item is already placed, is left out. Everything left
75
+ * out is reported. Deciding what a layout that places nothing means is the caller's.
76
+ */
77
+ export function parseMediaLayoutHtml(source, resolve) {
78
+ if (source.length > MAX_MEDIA_LAYOUT_HTML_LENGTH) {
79
+ return {
80
+ root: [],
81
+ placed: [],
82
+ ignored: [
83
+ `the whole layout, which is longer than ${String(MAX_MEDIA_LAYOUT_HTML_LENGTH)} characters`,
84
+ ],
85
+ truncated: true,
86
+ };
87
+ }
88
+ const document = parse(source);
89
+ const walk = {
90
+ resolve,
91
+ placed: [],
92
+ ignored: [],
93
+ nodes: 0,
94
+ text: 0,
95
+ truncated: false,
96
+ };
97
+ for (const node of document.childNodes) {
98
+ if (node.nodeName === "#comment")
99
+ note(walk, "comments");
100
+ }
101
+ const html = document.childNodes.find((node) => "tagName" in node && node.tagName === "html");
102
+ const body = html?.childNodes.find((node) => "tagName" in node && node.tagName === "body");
103
+ for (const part of html?.childNodes ?? []) {
104
+ if (part.nodeName === "#comment")
105
+ note(walk, "comments");
106
+ if ("tagName" in part && part.tagName === "head") {
107
+ for (const child of part.childNodes) {
108
+ if ("tagName" in child)
109
+ note(walk, `<${child.tagName}> and its contents`);
110
+ }
111
+ }
112
+ }
113
+ const root = body === undefined ? [] : children(body.childNodes, false, 0, walk);
114
+ return { root, placed: walk.placed, ignored: walk.ignored, truncated: walk.truncated };
115
+ }
116
+ function children(nodes, ignoresWhitespace, depth, walk) {
117
+ const converted = [];
118
+ for (const node of nodes)
119
+ convert(node, depth, walk, converted);
120
+ return tidyWhitespace(converted, ignoresWhitespace);
121
+ }
122
+ function convert(node, depth, walk, into) {
123
+ if (node.nodeName === "#text" && "value" in node) {
124
+ const text = node.value.replaceAll(/[\t\n\f\r ]+/gu, " ");
125
+ const room = MAX_TEXT - walk.text;
126
+ if (room <= 0 || !count(walk)) {
127
+ truncate(walk, `text beyond ${String(MAX_TEXT)} characters`);
128
+ return;
129
+ }
130
+ if (text.length > room)
131
+ truncate(walk, `text beyond ${String(MAX_TEXT)} characters`);
132
+ const kept = text.slice(0, room);
133
+ walk.text += kept.length;
134
+ into.push({ type: "text", text: kept });
135
+ return;
136
+ }
137
+ if (node.nodeName === "#comment") {
138
+ note(walk, "comments");
139
+ return;
140
+ }
141
+ if (!("tagName" in node))
142
+ return;
143
+ const element = node;
144
+ const tag = element.tagName;
145
+ if (element.namespaceURI !== htmlSpec.NS.HTML || DROPPED_TAGS.has(tag)) {
146
+ note(walk, `<${tag}> and its contents`);
147
+ return;
148
+ }
149
+ if (tag === "img") {
150
+ const item = imageItem(element, walk);
151
+ if (item !== undefined)
152
+ into.push(item);
153
+ return;
154
+ }
155
+ if (tag === "br") {
156
+ attributes(element, [], walk);
157
+ if (count(walk))
158
+ into.push({ type: "break" });
159
+ return;
160
+ }
161
+ const elementTag = ELEMENT_TAGS[tag];
162
+ if (elementTag === undefined || depth >= MAX_DEPTH) {
163
+ if (elementTag === undefined) {
164
+ if (tag !== "html" && tag !== "body")
165
+ note(walk, `<${tag}> (its content is kept)`);
166
+ }
167
+ else {
168
+ note(walk, `elements nested more than ${String(MAX_DEPTH)} deep (their content is kept)`);
169
+ }
170
+ for (const child of element.childNodes)
171
+ convert(child, depth, walk, into);
172
+ return;
173
+ }
174
+ if (!count(walk))
175
+ return;
176
+ const style = elementStyle(element, [], walk);
177
+ const display = style?.display ?? "";
178
+ const flowIgnoresWhitespace = /flex|grid/u.test(display);
179
+ into.push({
180
+ type: "element",
181
+ tag: elementTag,
182
+ ...(style === undefined ? {} : { style }),
183
+ children: children(element.childNodes, flowIgnoresWhitespace, depth + 1, walk),
184
+ });
185
+ }
186
+ function imageItem(element, walk) {
187
+ const src = element.attrs.find((attribute) => attribute.name === "src")?.value;
188
+ if (src === undefined) {
189
+ note(walk, "<img> without src");
190
+ return undefined;
191
+ }
192
+ const index = walk.resolve(src);
193
+ if (index === undefined || !Number.isSafeInteger(index) || index < 0) {
194
+ note(walk, `<img src=${quote(shorten(src))}>, which names none of the files`);
195
+ return undefined;
196
+ }
197
+ if (walk.placed.includes(index)) {
198
+ note(walk, `a second <img src=${quote(shorten(src))}>`);
199
+ return undefined;
200
+ }
201
+ if (!count(walk))
202
+ return undefined;
203
+ walk.placed.push(index);
204
+ const style = elementStyle(element, ["src", "alt"], walk);
205
+ const alt = element.attrs
206
+ .find((attribute) => attribute.name === "alt")
207
+ ?.value.replaceAll(/[\t\n\f\r ]+/gu, " ")
208
+ .trim()
209
+ .slice(0, Math.max(0, Math.min(MAX_ALT, MAX_TEXT - walk.text)));
210
+ walk.text += alt?.length ?? 0;
211
+ return {
212
+ type: "item",
213
+ index,
214
+ ...(alt === undefined || alt === "" ? {} : { alt }),
215
+ ...(style === undefined ? {} : { style }),
216
+ };
217
+ }
218
+ /** The element's parsed style; every other attribute but `kept` is noted and left out. */
219
+ function elementStyle(element, kept, walk) {
220
+ attributes(element, ["style", ...kept], walk);
221
+ const source = element.attrs.find((attribute) => attribute.name === "style")?.value;
222
+ if (source === undefined)
223
+ return undefined;
224
+ const parsed = parseMediaLayoutHtmlStyle(source, element.tagName);
225
+ for (const ignored of parsed.ignored)
226
+ note(walk, ignored);
227
+ return parsed.style;
228
+ }
229
+ function attributes(element, kept, walk) {
230
+ for (const attribute of element.attrs) {
231
+ if (kept.includes(attribute.name) && attribute.namespace === undefined)
232
+ continue;
233
+ note(walk, `the attribute ${shorten(attribute.name)} on <${element.tagName}>`);
234
+ }
235
+ }
236
+ /**
237
+ * Join neighbouring text, and drop whitespace that only separates blocks, starts or ends a list,
238
+ * or sits between the items of a flex or grid container, where a browser would not show it.
239
+ */
240
+ function tidyWhitespace(nodes, ignoresWhitespace) {
241
+ const joined = [];
242
+ for (const node of nodes) {
243
+ const last = joined[joined.length - 1];
244
+ if (node.type === "text" && last?.type === "text") {
245
+ joined[joined.length - 1] = {
246
+ type: "text",
247
+ text: `${last.text}${node.text}`.replaceAll(/ {2,}/gu, " "),
248
+ };
249
+ }
250
+ else {
251
+ joined.push(node);
252
+ }
253
+ }
254
+ return joined.filter((node, position) => {
255
+ if (node.type !== "text")
256
+ return true;
257
+ if (node.text !== " ")
258
+ return true;
259
+ return !(ignoresWhitespace ||
260
+ position === 0 ||
261
+ position === joined.length - 1 ||
262
+ isBlock(joined[position - 1]) ||
263
+ isBlock(joined[position + 1]));
264
+ });
265
+ }
266
+ function isBlock(node) {
267
+ return node?.type === "element" && BLOCK_TAGS.has(node.tag);
268
+ }
269
+ /** Count one more node, or say there is no room for it. */
270
+ function count(walk) {
271
+ if (walk.nodes >= MAX_NODES) {
272
+ truncate(walk, `nodes beyond ${String(MAX_NODES)}`);
273
+ return false;
274
+ }
275
+ walk.nodes += 1;
276
+ return true;
277
+ }
278
+ function note(walk, ignored) {
279
+ if (!walk.ignored.includes(ignored))
280
+ walk.ignored.push(ignored);
281
+ }
282
+ function truncate(walk, ignored) {
283
+ walk.truncated = true;
284
+ note(walk, ignored);
285
+ }
286
+ function shorten(text) {
287
+ return text.length > 60 ? `${text.slice(0, 60)}…` : text;
288
+ }
289
+ /** Quote text for a note, with controls and bidirectional overrides made visible. */
290
+ function quote(value) {
291
+ let visible = "";
292
+ for (const character of value) {
293
+ const codePoint = character.codePointAt(0) ?? 0;
294
+ if (character === "\\")
295
+ visible += "\\\\";
296
+ else if (character === '"')
297
+ visible += '\\"';
298
+ else if (character === "\n")
299
+ visible += "\\n";
300
+ else if (character === "\r")
301
+ visible += "\\r";
302
+ else if (character === "\t")
303
+ visible += "\\t";
304
+ else if (codePoint < 0x20 ||
305
+ codePoint === 0x7f ||
306
+ (codePoint >= 0x202a && codePoint <= 0x202e) ||
307
+ (codePoint >= 0x2066 && codePoint <= 0x2069)) {
308
+ visible += `\\u{${codePoint.toString(16).padStart(4, "0")}}`;
309
+ }
310
+ else {
311
+ visible += character;
312
+ }
313
+ }
314
+ return `"${visible}"`;
315
+ }
316
+ //# sourceMappingURL=mediaLayoutHtml.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"mediaLayoutHtml.js","sourceRoot":"","sources":["../sources/mediaLayoutHtml.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,16 @@
1
+ import { type MediaLayoutStyle } from "./protocol/mediaLayoutStyle.js";
2
+ /** What one `style` attribute keeps, and what of it was ignored, in the agent's terms. */
3
+ export interface ParsedMediaLayoutStyle {
4
+ readonly style: MediaLayoutStyle | undefined;
5
+ readonly ignored: readonly string[];
6
+ }
7
+ /**
8
+ * Keep the declarations of one `style` attribute that the layout subset allows, and name the
9
+ * rest. Nothing here fails: a declaration outside the subset is simply left out.
10
+ *
11
+ * Comments are read as the whitespace CSS reads them as. An attribute holding a backslash or a
12
+ * quote is left out whole, because escapes and strings are how a value hides what it is, and no
13
+ * allowed value needs either. Later declarations replace earlier ones, as in CSS.
14
+ */
15
+ export declare function parseMediaLayoutHtmlStyle(source: string, tag: string): ParsedMediaLayoutStyle;
16
+ //# sourceMappingURL=mediaLayoutHtmlStyle.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"mediaLayoutHtmlStyle.d.ts","sourceRoot":"","sources":["../sources/mediaLayoutHtmlStyle.ts"],"names":[],"mappings":"AAAA,OAAO,EAGH,KAAK,gBAAgB,EACxB,MAAM,gCAAgC,CAAC;AAExC,0FAA0F;AAC1F,MAAM,WAAW,sBAAsB;IACnC,QAAQ,CAAC,KAAK,EAAE,gBAAgB,GAAG,SAAS,CAAC;IAC7C,QAAQ,CAAC,OAAO,EAAE,SAAS,MAAM,EAAE,CAAC;CACvC;AAED;;;;;;;GAOG;AACH,wBAAgB,yBAAyB,CAAC,MAAM,EAAE,MAAM,EAAE,GAAG,EAAE,MAAM,GAAG,sBAAsB,CA4B7F"}
@@ -0,0 +1,44 @@
1
+ import { mediaLayoutStyleKey, mediaLayoutStyleValue, } from "./protocol/mediaLayoutStyle.js";
2
+ /**
3
+ * Keep the declarations of one `style` attribute that the layout subset allows, and name the
4
+ * rest. Nothing here fails: a declaration outside the subset is simply left out.
5
+ *
6
+ * Comments are read as the whitespace CSS reads them as. An attribute holding a backslash or a
7
+ * quote is left out whole, because escapes and strings are how a value hides what it is, and no
8
+ * allowed value needs either. Later declarations replace earlier ones, as in CSS.
9
+ */
10
+ export function parseMediaLayoutHtmlStyle(source, tag) {
11
+ if (/[\\"']/u.test(source)) {
12
+ return { style: undefined, ignored: [`style with escapes or quotes on <${tag}>`] };
13
+ }
14
+ const style = {};
15
+ const ignored = [];
16
+ for (const declaration of source.replaceAll(/\/\*[\s\S]*?(\*\/|$)/gu, " ").split(";")) {
17
+ const text = declaration.trim();
18
+ if (text === "")
19
+ continue;
20
+ const colon = text.indexOf(":");
21
+ const property = (colon < 0 ? text : text.slice(0, colon)).trim().toLowerCase();
22
+ const value = colon < 0 ? "" : text.slice(colon + 1).trim();
23
+ const key = mediaLayoutStyleKey(property);
24
+ if (key === undefined) {
25
+ ignored.push(`${shorten(property)} on <${tag}>`);
26
+ continue;
27
+ }
28
+ const normalized = mediaLayoutStyleValue(key, value);
29
+ if (normalized === undefined) {
30
+ ignored.push(`${property}: ${shorten(value)} on <${tag}>`);
31
+ continue;
32
+ }
33
+ style[key] = normalized;
34
+ }
35
+ return {
36
+ style: Object.keys(style).length === 0 ? undefined : style,
37
+ ignored,
38
+ };
39
+ }
40
+ function shorten(text) {
41
+ const single = text.replaceAll(/\s+/gu, " ");
42
+ return single.length > 40 ? `${single.slice(0, 40)}…` : single;
43
+ }
44
+ //# sourceMappingURL=mediaLayoutHtmlStyle.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"mediaLayoutHtmlStyle.js","sourceRoot":"","sources":["../sources/mediaLayoutHtmlStyle.ts"],"names":[],"mappings":"AAAA,OAAO,EACH,mBAAmB,EACnB,qBAAqB,GAExB,MAAM,gCAAgC,CAAC;AAQxC;;;;;;;GAOG;AACH,MAAM,UAAU,yBAAyB,CAAC,MAAc,EAAE,GAAW;IACjE,IAAI,SAAS,CAAC,IAAI,CAAC,MAAM,CAAC,EAAE,CAAC;QACzB,OAAO,EAAE,KAAK,EAAE,SAAS,EAAE,OAAO,EAAE,CAAC,oCAAoC,GAAG,GAAG,CAAC,EAAE,CAAC;IACvF,CAAC;IACD,MAAM,KAAK,GAA2B,EAAE,CAAC;IACzC,MAAM,OAAO,GAAa,EAAE,CAAC;IAC7B,KAAK,MAAM,WAAW,IAAI,MAAM,CAAC,UAAU,CAAC,wBAAwB,EAAE,GAAG,CAAC,CAAC,KAAK,CAAC,GAAG,CAAC,EAAE,CAAC;QACpF,MAAM,IAAI,GAAG,WAAW,CAAC,IAAI,EAAE,CAAC;QAChC,IAAI,IAAI,KAAK,EAAE;YAAE,SAAS;QAC1B,MAAM,KAAK,GAAG,IAAI,CAAC,OAAO,CAAC,GAAG,CAAC,CAAC;QAChC,MAAM,QAAQ,GAAG,CAAC,KAAK,GAAG,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC,EAAE,KAAK,CAAC,CAAC,CAAC,IAAI,EAAE,CAAC,WAAW,EAAE,CAAC;QAChF,MAAM,KAAK,GAAG,KAAK,GAAG,CAAC,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,IAAI,CAAC,KAAK,CAAC,KAAK,GAAG,CAAC,CAAC,CAAC,IAAI,EAAE,CAAC;QAC5D,MAAM,GAAG,GAAG,mBAAmB,CAAC,QAAQ,CAAC,CAAC;QAC1C,IAAI,GAAG,KAAK,SAAS,EAAE,CAAC;YACpB,OAAO,CAAC,IAAI,CAAC,GAAG,OAAO,CAAC,QAAQ,CAAC,QAAQ,GAAG,GAAG,CAAC,CAAC;YACjD,SAAS;QACb,CAAC;QACD,MAAM,UAAU,GAAG,qBAAqB,CAAC,GAAG,EAAE,KAAK,CAAC,CAAC;QACrD,IAAI,UAAU,KAAK,SAAS,EAAE,CAAC;YAC3B,OAAO,CAAC,IAAI,CAAC,GAAG,QAAQ,KAAK,OAAO,CAAC,KAAK,CAAC,QAAQ,GAAG,GAAG,CAAC,CAAC;YAC3D,SAAS;QACb,CAAC;QACD,KAAK,CAAC,GAAG,CAAC,GAAG,UAAU,CAAC;IAC5B,CAAC;IACD,OAAO;QACH,KAAK,EAAE,MAAM,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC,MAAM,KAAK,CAAC,CAAC,CAAC,CAAC,SAAS,CAAC,CAAC,CAAE,KAA0B;QAChF,OAAO;KACV,CAAC;AACN,CAAC;AAED,SAAS,OAAO,CAAC,IAAY;IACzB,MAAM,MAAM,GAAG,IAAI,CAAC,UAAU,CAAC,OAAO,EAAE,GAAG,CAAC,CAAC;IAC7C,OAAO,MAAM,CAAC,MAAM,GAAG,EAAE,CAAC,CAAC,CAAC,GAAG,MAAM,CAAC,KAAK,CAAC,CAAC,EAAE,EAAE,CAAC,GAAG,CAAC,CAAC,CAAC,MAAM,CAAC;AACnE,CAAC"}
@@ -169,6 +169,17 @@ export declare const agentSpawnPresentationSchema: import("@sinclair/typebox").T
169
169
  }>;
170
170
  /** Sub-agent creation; the enclosing tool status owns its lifecycle. */
171
171
  export type AgentSpawnPresentation = Static<typeof agentSpawnPresentationSchema>;
172
+ /**
173
+ * Where an item came from on the agent's machine: `path` exactly as the agent wrote it, such as a
174
+ * read's `file_path`, and `absolutePath`, the file it named. A layout block in the agent's text
175
+ * names the item by either one.
176
+ */
177
+ export declare const mediaItemSourceSchema: import("@sinclair/typebox").TObject<{
178
+ path: import("@sinclair/typebox").TString;
179
+ absolutePath: import("@sinclair/typebox").TString;
180
+ }>;
181
+ /** Where an item came from on the agent's machine. */
182
+ export type MediaItemSource = Static<typeof mediaItemSourceSchema>;
172
183
  /** A decoded picture: always measured, with a ThumbHash to show until its bytes load. */
173
184
  export declare const mediaImageItemSchema: import("@sinclair/typebox").TObject<{
174
185
  kind: import("@sinclair/typebox").TLiteral<"image">;
@@ -188,6 +199,11 @@ export declare const mediaImageItemSchema: import("@sinclair/typebox").TObject<{
188
199
  * 1. An image's natural size is its pixel size divided by this.
189
200
  */
190
201
  scale: import("@sinclair/typebox").TOptional<import("@sinclair/typebox").TNumber>;
202
+ /** The file it was read, presented, or generated as; absent on older daemons. */
203
+ source: import("@sinclair/typebox").TOptional<import("@sinclair/typebox").TObject<{
204
+ path: import("@sinclair/typebox").TString;
205
+ absolutePath: import("@sinclair/typebox").TString;
206
+ }>>;
191
207
  }>;
192
208
  /** A decoded picture: always measured, with a ThumbHash to show until its bytes load. */
193
209
  export type MediaImageItem = Static<typeof mediaImageItemSchema>;
@@ -205,6 +221,11 @@ export declare const mediaFileItemSchema: import("@sinclair/typebox").TObject<{
205
221
  height: import("@sinclair/typebox").TOptional<import("@sinclair/typebox").TInteger>;
206
222
  /** Not currently supplied for these kinds; tolerated when present. */
207
223
  thumbhash: import("@sinclair/typebox").TOptional<import("@sinclair/typebox").TString>;
224
+ /** The file it was presented as; absent on older daemons. */
225
+ source: import("@sinclair/typebox").TOptional<import("@sinclair/typebox").TObject<{
226
+ path: import("@sinclair/typebox").TString;
227
+ absolutePath: import("@sinclair/typebox").TString;
228
+ }>>;
208
229
  }>;
209
230
  /** A video, a PDF document, or any other file; clients render an unknown kind as a file. */
210
231
  export type MediaFileItem = Static<typeof mediaFileItemSchema>;
@@ -227,6 +248,11 @@ export declare const mediaItemSchema: import("@sinclair/typebox").TUnion<[import
227
248
  * 1. An image's natural size is its pixel size divided by this.
228
249
  */
229
250
  scale: import("@sinclair/typebox").TOptional<import("@sinclair/typebox").TNumber>;
251
+ /** The file it was read, presented, or generated as; absent on older daemons. */
252
+ source: import("@sinclair/typebox").TOptional<import("@sinclair/typebox").TObject<{
253
+ path: import("@sinclair/typebox").TString;
254
+ absolutePath: import("@sinclair/typebox").TString;
255
+ }>>;
230
256
  }>, import("@sinclair/typebox").TObject<{
231
257
  kind: import("@sinclair/typebox").TUnion<[import("@sinclair/typebox").TLiteral<"video">, import("@sinclair/typebox").TLiteral<"document">, import("@sinclair/typebox").TLiteral<"file">]>;
232
258
  /** The file's base name, for display and downloads only. */
@@ -240,6 +266,11 @@ export declare const mediaItemSchema: import("@sinclair/typebox").TUnion<[import
240
266
  height: import("@sinclair/typebox").TOptional<import("@sinclair/typebox").TInteger>;
241
267
  /** Not currently supplied for these kinds; tolerated when present. */
242
268
  thumbhash: import("@sinclair/typebox").TOptional<import("@sinclair/typebox").TString>;
269
+ /** The file it was presented as; absent on older daemons. */
270
+ source: import("@sinclair/typebox").TOptional<import("@sinclair/typebox").TObject<{
271
+ path: import("@sinclair/typebox").TString;
272
+ absolutePath: import("@sinclair/typebox").TString;
273
+ }>>;
243
274
  }>]>;
244
275
  /** One item a call showed inline; its bytes are served by its index. */
245
276
  export type MediaItem = Static<typeof mediaItemSchema>;
@@ -583,6 +614,11 @@ export declare const mediaPresentationSchema: import("@sinclair/typebox").TObjec
583
614
  * 1. An image's natural size is its pixel size divided by this.
584
615
  */
585
616
  scale: import("@sinclair/typebox").TOptional<import("@sinclair/typebox").TNumber>;
617
+ /** The file it was read, presented, or generated as; absent on older daemons. */
618
+ source: import("@sinclair/typebox").TOptional<import("@sinclair/typebox").TObject<{
619
+ path: import("@sinclair/typebox").TString;
620
+ absolutePath: import("@sinclair/typebox").TString;
621
+ }>>;
586
622
  }>, import("@sinclair/typebox").TObject<{
587
623
  kind: import("@sinclair/typebox").TUnion<[import("@sinclair/typebox").TLiteral<"video">, import("@sinclair/typebox").TLiteral<"document">, import("@sinclair/typebox").TLiteral<"file">]>;
588
624
  /** The file's base name, for display and downloads only. */
@@ -596,6 +632,11 @@ export declare const mediaPresentationSchema: import("@sinclair/typebox").TObjec
596
632
  height: import("@sinclair/typebox").TOptional<import("@sinclair/typebox").TInteger>;
597
633
  /** Not currently supplied for these kinds; tolerated when present. */
598
634
  thumbhash: import("@sinclair/typebox").TOptional<import("@sinclair/typebox").TString>;
635
+ /** The file it was presented as; absent on older daemons. */
636
+ source: import("@sinclair/typebox").TOptional<import("@sinclair/typebox").TObject<{
637
+ path: import("@sinclair/typebox").TString;
638
+ absolutePath: import("@sinclair/typebox").TString;
639
+ }>>;
599
640
  }>]>>;
600
641
  /** How to arrange the items; absent on older daemons and for the automatic layout. */
601
642
  layout: import("@sinclair/typebox").TOptional<import("@sinclair/typebox").TUnion<[import("@sinclair/typebox").TObject<{
@@ -788,6 +829,45 @@ export declare const pagePresentationSchema: import("@sinclair/typebox").TObject
788
829
  }>;
789
830
  /** A legacy inline web page. New live pages use `ArtifactPresentation` and the artifact's `live`. */
790
831
  export type PagePresentation = Static<typeof pagePresentationSchema>;
832
+ /** One question a `request_user_input` call asked, as the person was shown it. */
833
+ export declare const userInputPresentationQuestionSchema: import("@sinclair/typebox").TObject<{
834
+ id: import("@sinclair/typebox").TString;
835
+ header: import("@sinclair/typebox").TString;
836
+ question: import("@sinclair/typebox").TString;
837
+ multiSelect: import("@sinclair/typebox").TBoolean;
838
+ /** Possibly empty, and then the question was answered in free text. */
839
+ options: import("@sinclair/typebox").TArray<import("@sinclair/typebox").TObject<{
840
+ label: import("@sinclair/typebox").TString;
841
+ description: import("@sinclair/typebox").TString;
842
+ }>>;
843
+ }>;
844
+ /** One question a `request_user_input` call asked, as the person was shown it. */
845
+ export type UserInputPresentationQuestion = Static<typeof userInputPresentationQuestionSchema>;
846
+ /**
847
+ * The questions a completed `request_user_input` call asked and the answers the person gave, so
848
+ * a conversation keeps both where the call was made.
849
+ */
850
+ export declare const userInputPresentationSchema: import("@sinclair/typebox").TObject<{
851
+ type: import("@sinclair/typebox").TLiteral<"user_input">;
852
+ questions: import("@sinclair/typebox").TArray<import("@sinclair/typebox").TObject<{
853
+ id: import("@sinclair/typebox").TString;
854
+ header: import("@sinclair/typebox").TString;
855
+ question: import("@sinclair/typebox").TString;
856
+ multiSelect: import("@sinclair/typebox").TBoolean;
857
+ /** Possibly empty, and then the question was answered in free text. */
858
+ options: import("@sinclair/typebox").TArray<import("@sinclair/typebox").TObject<{
859
+ label: import("@sinclair/typebox").TString;
860
+ description: import("@sinclair/typebox").TString;
861
+ }>>;
862
+ }>>;
863
+ /**
864
+ * Each question ID mapped to the person's values, in the shape a question's `answers` take:
865
+ * a value matching an option label is a selection, and any other is free text.
866
+ */
867
+ answers: import("@sinclair/typebox").TRecord<import("@sinclair/typebox").TString, import("@sinclair/typebox").TArray<import("@sinclair/typebox").TString>>;
868
+ }>;
869
+ /** The questions a completed `request_user_input` call asked and the answers it was given. */
870
+ export type UserInputPresentation = Static<typeof userInputPresentationSchema>;
791
871
  /** Every display-ready tool-call presentation the client understands. */
792
872
  export declare const toolPresentationSchema: import("@sinclair/typebox").TUnion<[import("@sinclair/typebox").TObject<{
793
873
  operations: import("@sinclair/typebox").TArray<import("@sinclair/typebox").TUnion<[import("@sinclair/typebox").TObject<{
@@ -878,6 +958,11 @@ export declare const toolPresentationSchema: import("@sinclair/typebox").TUnion<
878
958
  * 1. An image's natural size is its pixel size divided by this.
879
959
  */
880
960
  scale: import("@sinclair/typebox").TOptional<import("@sinclair/typebox").TNumber>;
961
+ /** The file it was read, presented, or generated as; absent on older daemons. */
962
+ source: import("@sinclair/typebox").TOptional<import("@sinclair/typebox").TObject<{
963
+ path: import("@sinclair/typebox").TString;
964
+ absolutePath: import("@sinclair/typebox").TString;
965
+ }>>;
881
966
  }>, import("@sinclair/typebox").TObject<{
882
967
  kind: import("@sinclair/typebox").TUnion<[import("@sinclair/typebox").TLiteral<"video">, import("@sinclair/typebox").TLiteral<"document">, import("@sinclair/typebox").TLiteral<"file">]>;
883
968
  /** The file's base name, for display and downloads only. */
@@ -891,6 +976,11 @@ export declare const toolPresentationSchema: import("@sinclair/typebox").TUnion<
891
976
  height: import("@sinclair/typebox").TOptional<import("@sinclair/typebox").TInteger>;
892
977
  /** Not currently supplied for these kinds; tolerated when present. */
893
978
  thumbhash: import("@sinclair/typebox").TOptional<import("@sinclair/typebox").TString>;
979
+ /** The file it was presented as; absent on older daemons. */
980
+ source: import("@sinclair/typebox").TOptional<import("@sinclair/typebox").TObject<{
981
+ path: import("@sinclair/typebox").TString;
982
+ absolutePath: import("@sinclair/typebox").TString;
983
+ }>>;
894
984
  }>]>>;
895
985
  /** How to arrange the items; absent on older daemons and for the automatic layout. */
896
986
  layout: import("@sinclair/typebox").TOptional<import("@sinclair/typebox").TUnion<[import("@sinclair/typebox").TObject<{
@@ -1059,6 +1149,24 @@ export declare const toolPresentationSchema: import("@sinclair/typebox").TUnion<
1059
1149
  url: import("@sinclair/typebox").TString;
1060
1150
  title: import("@sinclair/typebox").TString;
1061
1151
  display: import("@sinclair/typebox").TUnion<[import("@sinclair/typebox").TUnion<[import("@sinclair/typebox").TLiteral<"inline_compact">, import("@sinclair/typebox").TLiteral<"inline_expanded">, import("@sinclair/typebox").TLiteral<"side">]>, import("@sinclair/typebox").TNull]>;
1152
+ }>, import("@sinclair/typebox").TObject<{
1153
+ type: import("@sinclair/typebox").TLiteral<"user_input">;
1154
+ questions: import("@sinclair/typebox").TArray<import("@sinclair/typebox").TObject<{
1155
+ id: import("@sinclair/typebox").TString;
1156
+ header: import("@sinclair/typebox").TString;
1157
+ question: import("@sinclair/typebox").TString;
1158
+ multiSelect: import("@sinclair/typebox").TBoolean;
1159
+ /** Possibly empty, and then the question was answered in free text. */
1160
+ options: import("@sinclair/typebox").TArray<import("@sinclair/typebox").TObject<{
1161
+ label: import("@sinclair/typebox").TString;
1162
+ description: import("@sinclair/typebox").TString;
1163
+ }>>;
1164
+ }>>;
1165
+ /**
1166
+ * Each question ID mapped to the person's values, in the shape a question's `answers` take:
1167
+ * a value matching an option label is a selection, and any other is free text.
1168
+ */
1169
+ answers: import("@sinclair/typebox").TRecord<import("@sinclair/typebox").TString, import("@sinclair/typebox").TArray<import("@sinclair/typebox").TString>>;
1062
1170
  }>]>;
1063
1171
  /** Every display-ready tool-call presentation the client understands. */
1064
1172
  export type ToolPresentation = Static<typeof toolPresentationSchema>;
@@ -1070,6 +1178,11 @@ export declare const messageMetadataSchema: import("@sinclair/typebox").TObject<
1070
1178
  modelId: import("@sinclair/typebox").TOptional<import("@sinclair/typebox").TString>;
1071
1179
  /** The agent that sent this system-generated message, when one identified itself. */
1072
1180
  senderAgentId: import("@sinclair/typebox").TOptional<import("@sinclair/typebox").TString>;
1181
+ /**
1182
+ * That agent's one-line account of what the message is, for a client to show beside the
1183
+ * sender until the message is opened. Present only when the sender gave one.
1184
+ */
1185
+ senderAgentExplanation: import("@sinclair/typebox").TOptional<import("@sinclair/typebox").TString>;
1073
1186
  /**
1074
1187
  * The local Happy user ID of the person who wrote a user message: the authenticated team member
1075
1188
  * who submitted it, or the exported-bot guest who wrote it.