@burdenoff/fe-libs 2026.904.2 → 2026.904.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/shared/assistant/attachments.d.ts +340 -0
- package/dist/shared/assistant/attachments.d.ts.map +1 -0
- package/dist/shared/assistant/attachments.js +370 -0
- package/dist/shared/assistant/conversation.d.ts +153 -0
- package/dist/shared/assistant/conversation.d.ts.map +1 -0
- package/dist/shared/assistant/documentText.d.ts +261 -0
- package/dist/shared/assistant/documentText.d.ts.map +1 -0
- package/dist/shared/assistant/documentText.js +235 -0
- package/dist/shared/assistant/gatewayLimits.d.ts +25 -0
- package/dist/shared/assistant/gatewayLimits.d.ts.map +1 -0
- package/dist/shared/assistant/gatewayLimits.js +4 -0
- package/dist/shared/assistant/index.d.ts +6 -0
- package/dist/shared/assistant/index.d.ts.map +1 -1
- package/dist/shared/assistant/store.d.ts +114 -0
- package/dist/shared/assistant/store.d.ts.map +1 -0
- package/dist/shared/assistant/store.js +198 -0
- package/dist/shared/assistant/turnState.d.ts +16 -0
- package/dist/shared/assistant/turnState.d.ts.map +1 -0
- package/dist/shared/assistant/turnState.js +6 -0
- package/dist/shared/config/authBridgeUrls.d.ts.map +1 -1
- package/dist/shared/config/authBridgeUrls.js +16 -15
- package/dist/shared/config/gatewayUrls.d.ts +29 -0
- package/dist/shared/config/gatewayUrls.d.ts.map +1 -1
- package/dist/shared/config/gatewayUrls.js +44 -20
- package/dist/shared/config/index.d.ts.map +1 -1
- package/dist/shared/native/capacitor.d.ts +49 -0
- package/dist/shared/native/capacitor.d.ts.map +1 -0
- package/dist/shared/native/capacitor.js +31 -0
- package/dist/shared/native/index.d.ts +2 -0
- package/dist/shared/native/index.d.ts.map +1 -1
- package/dist/shared/providers/shell/MultiGatewayProvider.d.ts.map +1 -1
- package/dist/shared/providers/shell/MultiGatewayProvider.js +101 -100
- package/dist/shared/utils/authCookie.d.ts.map +1 -1
- package/dist/shared/utils/authCookie.js +35 -34
- package/dist/shared/utils/gatewayFetchRewrite.d.ts.map +1 -1
- package/dist/shared/utils/gatewayFetchRewrite.js +95 -87
- package/dist/shared-assistant.js +6 -1
- package/dist/shared-config.js +9 -1
- package/dist/shared-native.js +23 -22
- package/dist/shared.js +124 -123
- package/package.json +2 -2
|
@@ -0,0 +1,370 @@
|
|
|
1
|
+
import { MAX_REQUEST_BODY_BYTES as e } from "./gatewayLimits.js";
|
|
2
|
+
import { formatPageRanges as t, isMostlyImagePages as n, truncatePagesForInline as r } from "./documentText.js";
|
|
3
|
+
//#region src/shared/assistant/attachments.ts
|
|
4
|
+
var i = 5, a = 10 * 1024 * 1024, o = 8e3, s = 2e4, c = class extends Error {
|
|
5
|
+
constructor(e) {
|
|
6
|
+
super(e), this.reason = e, this.name = "AttachmentRejectedError";
|
|
7
|
+
}
|
|
8
|
+
};
|
|
9
|
+
function l(e) {
|
|
10
|
+
return {
|
|
11
|
+
id: e.id,
|
|
12
|
+
filename: e.filename,
|
|
13
|
+
mimeType: e.mimeType,
|
|
14
|
+
size: e.size,
|
|
15
|
+
kind: e.kind,
|
|
16
|
+
fileId: e.fileId
|
|
17
|
+
};
|
|
18
|
+
}
|
|
19
|
+
var u = new Set([
|
|
20
|
+
"txt",
|
|
21
|
+
"md",
|
|
22
|
+
"markdown",
|
|
23
|
+
"csv",
|
|
24
|
+
"tsv",
|
|
25
|
+
"json",
|
|
26
|
+
"yaml",
|
|
27
|
+
"yml",
|
|
28
|
+
"xml",
|
|
29
|
+
"log",
|
|
30
|
+
"sql",
|
|
31
|
+
"html",
|
|
32
|
+
"css",
|
|
33
|
+
"js",
|
|
34
|
+
"ts",
|
|
35
|
+
"tsx",
|
|
36
|
+
"jsx",
|
|
37
|
+
"py",
|
|
38
|
+
"sh",
|
|
39
|
+
"ini",
|
|
40
|
+
"toml",
|
|
41
|
+
"conf"
|
|
42
|
+
]);
|
|
43
|
+
function d(e) {
|
|
44
|
+
let t = e.lastIndexOf(".");
|
|
45
|
+
return t >= 0 ? e.slice(t + 1).toLowerCase() : "";
|
|
46
|
+
}
|
|
47
|
+
function f(e, t) {
|
|
48
|
+
return e.startsWith("image/") ? "image" : e.startsWith("text/") || e === "application/json" || e === "application/xml" || e === "application/x-yaml" || u.has(d(t)) ? "text" : "document";
|
|
49
|
+
}
|
|
50
|
+
var p = {
|
|
51
|
+
"application/pdf": "pdf",
|
|
52
|
+
"application/x-pdf": "pdf",
|
|
53
|
+
"application/vnd.openxmlformats-officedocument.wordprocessingml.document": "docx",
|
|
54
|
+
"application/vnd.openxmlformats-officedocument.spreadsheetml.sheet": "xlsx"
|
|
55
|
+
}, m = {
|
|
56
|
+
pdf: "pdf",
|
|
57
|
+
docx: "docx",
|
|
58
|
+
xlsx: "xlsx"
|
|
59
|
+
};
|
|
60
|
+
function h(e, t) {
|
|
61
|
+
return p[e.toLowerCase()] ?? m[d(t)] ?? null;
|
|
62
|
+
}
|
|
63
|
+
var g = [
|
|
64
|
+
"image/*",
|
|
65
|
+
"text/*",
|
|
66
|
+
...[...u].map((e) => `.${e}`),
|
|
67
|
+
...Object.keys(m).map((e) => `.${e}`)
|
|
68
|
+
].join(",");
|
|
69
|
+
function _(e) {
|
|
70
|
+
return e < 1024 ? `${e} B` : e < 1024 * 1024 ? `${(e / 1024).toFixed(1)} KB` : `${(e / (1024 * 1024)).toFixed(1)} MB`;
|
|
71
|
+
}
|
|
72
|
+
function v(e, t) {
|
|
73
|
+
return e > 0 || t.some((e) => e.status === "pending" || e.status === "uploading");
|
|
74
|
+
}
|
|
75
|
+
function y(e) {
|
|
76
|
+
return e.filter((e) => e.status === "ready");
|
|
77
|
+
}
|
|
78
|
+
function b(e, t) {
|
|
79
|
+
return v(e, t) ? "in-flight" : t.some((e) => e.status === "error") ? "failed" : null;
|
|
80
|
+
}
|
|
81
|
+
function x(e, t) {
|
|
82
|
+
return t >= 5 ? "too-many" : e.size === 0 ? "empty" : e.size > 10485760 && !e.type.startsWith("image/") ? "too-large" : null;
|
|
83
|
+
}
|
|
84
|
+
function S(e, t) {
|
|
85
|
+
if (e.length <= t) return {
|
|
86
|
+
text: e,
|
|
87
|
+
truncated: !1
|
|
88
|
+
};
|
|
89
|
+
let n = e.slice(0, t), r = n.lastIndexOf("\n");
|
|
90
|
+
return {
|
|
91
|
+
text: r > t * .5 ? n.slice(0, r) : n,
|
|
92
|
+
truncated: !0
|
|
93
|
+
};
|
|
94
|
+
}
|
|
95
|
+
function C(e) {
|
|
96
|
+
return [
|
|
97
|
+
" ```",
|
|
98
|
+
...e.split("\n").map((e) => ` ${e}`),
|
|
99
|
+
" ```"
|
|
100
|
+
];
|
|
101
|
+
}
|
|
102
|
+
function w(e) {
|
|
103
|
+
return e?.pageNumbers?.length ? e.pageNumbers : e?.pagesIncluded ? Array.from({ length: e.pagesIncluded }, (e, t) => t + 1) : [];
|
|
104
|
+
}
|
|
105
|
+
function T(e) {
|
|
106
|
+
let n = e.extraction, r = [];
|
|
107
|
+
if (n?.pageCount) {
|
|
108
|
+
let e = w(n);
|
|
109
|
+
e.length >= n.pageCount ? r.push(`${n.pageCount} page${n.pageCount === 1 ? "" : "s"}`) : e.length === 1 ? r.push(`page ${e[0]} of ${n.pageCount}`) : r.push(`pages ${t(e)} of ${n.pageCount}`);
|
|
110
|
+
}
|
|
111
|
+
if (n?.sheetNames?.length && r.push(`sheets: ${n.sheetNames.join(", ")}`), e.textTruncated && e.textContent) {
|
|
112
|
+
let t = n?.sourceChars;
|
|
113
|
+
r.push(t && t > e.textContent.length ? `first ${e.textContent.length} characters of ${t}; truncated` : `first ${e.textContent.length} characters; truncated`);
|
|
114
|
+
}
|
|
115
|
+
return r.length > 0 ? ` (${r.join("; ")})` : "";
|
|
116
|
+
}
|
|
117
|
+
var E = " Do NOT guess at, summarise or characterise its contents — you have not seen them.", D = [" Fetch the URL above if you can; otherwise ask the user to paste the relevant section as text.", E];
|
|
118
|
+
function O(e) {
|
|
119
|
+
let n = e.extraction;
|
|
120
|
+
if (!n?.pageCount) return [];
|
|
121
|
+
let r = new Set(w(n)), i = new Set(n.imagePages ?? []), a = [...i].filter((e) => !r.has(e)).sort((e, t) => e - t), o = [];
|
|
122
|
+
if (a.length > 0) {
|
|
123
|
+
let e = a.length === 1 ? `Page ${a[0]}` : `Pages ${t(a)}`;
|
|
124
|
+
o.push(` ${e} of this document contain no extractable text — they are images.`, " Nothing about those pages is available to you.");
|
|
125
|
+
}
|
|
126
|
+
let s = [];
|
|
127
|
+
for (let e = 1; e <= n.pageCount; e += 1) !r.has(e) && !i.has(e) && s.push(e);
|
|
128
|
+
if (s.length > 0) {
|
|
129
|
+
let e = s.length === 1 ? `Page ${s[0]}` : `Pages ${t(s)}`;
|
|
130
|
+
o.push(` ${e} of this document ${s.length === 1 ? "was" : "were"} not read at all.`);
|
|
131
|
+
}
|
|
132
|
+
return o.length > 0 && o.push(E), o;
|
|
133
|
+
}
|
|
134
|
+
function k(e) {
|
|
135
|
+
let t = e.extraction;
|
|
136
|
+
if (!t || t.status === "unsupported") return [" Binary file — contents not inlined. Fetch the URL above if you can; otherwise ask the user", " to paste the relevant section as text."];
|
|
137
|
+
if (t.status === "no-text") return t.format === "docx" || t.format === "xlsx" ? [
|
|
138
|
+
" NO TEXT AVAILABLE — this document holds no readable text; it is either empty or contains only",
|
|
139
|
+
" images, charts or drawings, none of which carry text. No text could be extracted.",
|
|
140
|
+
...D
|
|
141
|
+
] : [
|
|
142
|
+
` NO TEXT AVAILABLE — this document appears to be scanned images; no text could be extracted${t.pagesScanned && t.pageCount && t.pagesScanned < t.pageCount ? ` (the first ${t.pagesScanned} of ${t.pageCount} pages were checked)` : ""}.`,
|
|
143
|
+
" There is no text layer to read, so nothing about its contents is available to you.",
|
|
144
|
+
...D
|
|
145
|
+
];
|
|
146
|
+
if (t.status === "encrypted") return [
|
|
147
|
+
" NO TEXT AVAILABLE — this document is encrypted or password-protected; it could not be opened",
|
|
148
|
+
" and no text could be extracted.",
|
|
149
|
+
...D
|
|
150
|
+
];
|
|
151
|
+
if (t.status === "corrupt") return [` NO TEXT AVAILABLE — this file could not be read${t.detail ? ` (${t.detail})` : ""}; no text could be extracted.`, ...D];
|
|
152
|
+
if (!e.textContent) return [
|
|
153
|
+
" Text WAS extracted from this document but is omitted because this turn ran out of inline budget,",
|
|
154
|
+
" not because it is unavailable. Ask the user which part matters so they can re-send just that",
|
|
155
|
+
" section, or fetch the URL above if you can.",
|
|
156
|
+
E
|
|
157
|
+
];
|
|
158
|
+
let r = t.pagesScanned ?? t.pageCount ?? 0, i = t.textPageCount;
|
|
159
|
+
if (t.pageCount && i !== void 0 && n(i, r)) {
|
|
160
|
+
let n = r - i;
|
|
161
|
+
return [
|
|
162
|
+
` NOT READ — this document is mostly images. Only ${i} of its ${t.pageCount} page${t.pageCount === 1 ? "" : "s"} carr${i === 1 ? "ies" : "y"} a text layer;`,
|
|
163
|
+
` the other ${n} contain no extractable text at all. Treat this as a document you have NOT`,
|
|
164
|
+
" read: the fragment below is the whole of what was available, not a summary of the document.",
|
|
165
|
+
...O(e),
|
|
166
|
+
` The only extractable text${T(e)}:`,
|
|
167
|
+
...C(e.textContent)
|
|
168
|
+
];
|
|
169
|
+
}
|
|
170
|
+
return [
|
|
171
|
+
` Extracted text${T(e)}:`,
|
|
172
|
+
...C(e.textContent),
|
|
173
|
+
...O(e)
|
|
174
|
+
];
|
|
175
|
+
}
|
|
176
|
+
function A(e, t, n = j) {
|
|
177
|
+
let r = [`[${t + 1}] ${e.filename} — ${e.mimeType}, ${_(e.size)}`];
|
|
178
|
+
return e.downloadUrl && r.push(` URL: ${e.downloadUrl}`), e.kind === "text" && e.textContent ? r.push(e.textTruncated ? ` Contents (first ${e.textContent.length} characters of ${_(e.size)}; truncated):` : " Contents:", ...C(e.textContent)) : e.kind === "document" ? r.push(...k(e)) : e.kind === "image" ? n.has(e.id) ? r.push(" NOT VIEWABLE IN THIS MESSAGE — this image did not fit the request-size budget, so only its URL", " travelled; its pixels are NOT attached. Fetch the URL above if you can; otherwise ask the user", " to describe it.", E) : r.push(" If this image is attached to the message as an image you can view, answer from what you see in it.", " If you cannot view attached images, say so plainly and ask the user to describe it — never guess.") : e.kind === "text" ? r.push(" Text file — contents omitted because this turn ran out of inline budget, not because they are", " unavailable. Fetch the URL above if you can; otherwise ask the user which part matters so they", " can re-send just that section.") : r.push(" Binary file — contents not inlined. Fetch the URL above if you can; otherwise ask the user", " to paste the relevant section as text."), r.join("\n");
|
|
179
|
+
}
|
|
180
|
+
var j = /* @__PURE__ */ new Set();
|
|
181
|
+
function M(e, t) {
|
|
182
|
+
let n = s, i = t, a = [...e], c = (e) => {
|
|
183
|
+
let t = !!e.extraction, a = Math.min(n, o, t ? i : Infinity);
|
|
184
|
+
if (a <= 0) return {
|
|
185
|
+
...e,
|
|
186
|
+
textContent: void 0,
|
|
187
|
+
textTruncated: !0
|
|
188
|
+
};
|
|
189
|
+
if (e.documentPages?.length) {
|
|
190
|
+
let t = r(e.documentPages, a);
|
|
191
|
+
return t.text === "" ? {
|
|
192
|
+
...e,
|
|
193
|
+
textContent: void 0,
|
|
194
|
+
textTruncated: !0
|
|
195
|
+
} : (n -= t.text.length, i -= t.text.length, {
|
|
196
|
+
...e,
|
|
197
|
+
textContent: t.text,
|
|
198
|
+
textTruncated: e.textTruncated || t.truncated,
|
|
199
|
+
...e.extraction ? { extraction: {
|
|
200
|
+
...e.extraction,
|
|
201
|
+
pagesIncluded: t.pagesIncluded,
|
|
202
|
+
pageNumbers: t.pageNumbers
|
|
203
|
+
} } : {}
|
|
204
|
+
});
|
|
205
|
+
}
|
|
206
|
+
let { text: s, truncated: c } = S(e.textContent ?? "", a);
|
|
207
|
+
return n -= s.length, t && (i -= s.length), {
|
|
208
|
+
...e,
|
|
209
|
+
textContent: s,
|
|
210
|
+
textTruncated: e.textTruncated || c
|
|
211
|
+
};
|
|
212
|
+
};
|
|
213
|
+
for (let t of [!1, !0]) e.forEach((e, n) => {
|
|
214
|
+
e.textContent && !!e.extraction === t && (a[n] = c(e));
|
|
215
|
+
});
|
|
216
|
+
return a;
|
|
217
|
+
}
|
|
218
|
+
function N(e, t, n) {
|
|
219
|
+
let r = M(e, t);
|
|
220
|
+
return [
|
|
221
|
+
"",
|
|
222
|
+
`--- Attachments (${e.length}) ---`,
|
|
223
|
+
"The user attached the following file(s) to this message.",
|
|
224
|
+
...r.map((e, t) => A(e, t, n)),
|
|
225
|
+
"--- End attachments ---"
|
|
226
|
+
].join("\n");
|
|
227
|
+
}
|
|
228
|
+
var P = 2048;
|
|
229
|
+
function F(e, t) {
|
|
230
|
+
let n = Z(e);
|
|
231
|
+
if (n.length === 0) return {
|
|
232
|
+
documentChars: s,
|
|
233
|
+
demotedImageIds: j
|
|
234
|
+
};
|
|
235
|
+
let r = (r, i, a) => {
|
|
236
|
+
let o = new Set(n.slice(0, r).map((e) => e.id)), s = N(e, i, a), c = t ? `${t}\n${s}` : s.trimStart(), { media: l } = Q(e, o);
|
|
237
|
+
return q(c, [{
|
|
238
|
+
type: "text",
|
|
239
|
+
text: c
|
|
240
|
+
}, ...l]) + P <= H;
|
|
241
|
+
};
|
|
242
|
+
for (let e = n.length; e >= 0; --e) {
|
|
243
|
+
let t = new Set(n.slice(e).map((e) => e.id));
|
|
244
|
+
if (r(e, 2e4, t)) return {
|
|
245
|
+
documentChars: s,
|
|
246
|
+
demotedImageIds: t
|
|
247
|
+
};
|
|
248
|
+
if (!r(e, 0, t)) continue;
|
|
249
|
+
let i = 0, a = s;
|
|
250
|
+
for (; i < a;) {
|
|
251
|
+
let n = Math.ceil((i + a) / 2);
|
|
252
|
+
r(e, n, t) ? i = n : a = n - 1;
|
|
253
|
+
}
|
|
254
|
+
return {
|
|
255
|
+
documentChars: i,
|
|
256
|
+
demotedImageIds: t
|
|
257
|
+
};
|
|
258
|
+
}
|
|
259
|
+
return {
|
|
260
|
+
documentChars: s,
|
|
261
|
+
demotedImageIds: new Set(n.map((e) => e.id))
|
|
262
|
+
};
|
|
263
|
+
}
|
|
264
|
+
function I(e, t = "") {
|
|
265
|
+
let n = y(e);
|
|
266
|
+
if (n.length === 0) return "";
|
|
267
|
+
let r = F(n, t);
|
|
268
|
+
return N(n, r.documentChars, r.demotedImageIds);
|
|
269
|
+
}
|
|
270
|
+
function L(e, t) {
|
|
271
|
+
let n = I(t, e);
|
|
272
|
+
return n ? e ? `${e}\n${n}` : n.trimStart() : e;
|
|
273
|
+
}
|
|
274
|
+
var R = 3, z = 15e5, B = e, V = 32768, H = B - V, U = 768, W = .6, G = typeof TextEncoder == "function" ? new TextEncoder() : null;
|
|
275
|
+
function K(e) {
|
|
276
|
+
return G ? G.encode(e).length : e.length;
|
|
277
|
+
}
|
|
278
|
+
function q(e, t) {
|
|
279
|
+
return K(JSON.stringify({
|
|
280
|
+
prompt: e,
|
|
281
|
+
parts: t ?? []
|
|
282
|
+
}));
|
|
283
|
+
}
|
|
284
|
+
function J(e) {
|
|
285
|
+
return y(e).filter((e) => e.kind === "image" && !!(e.inlineDataUrl ?? e.previewUrl)).length;
|
|
286
|
+
}
|
|
287
|
+
function Y(e) {
|
|
288
|
+
return (e ?? []).filter((e) => e.type === "image" && !!e.data).length;
|
|
289
|
+
}
|
|
290
|
+
function X(e) {
|
|
291
|
+
let t = /^data:([a-z0-9.+/-]+);base64,(.*)$/i.exec(e);
|
|
292
|
+
return t ? {
|
|
293
|
+
mimeType: t[1],
|
|
294
|
+
base64: t[2]
|
|
295
|
+
} : null;
|
|
296
|
+
}
|
|
297
|
+
function Z(e) {
|
|
298
|
+
let t = [], n = 0;
|
|
299
|
+
for (let r of e) {
|
|
300
|
+
if (r.kind !== "image") continue;
|
|
301
|
+
let e = r.inlineDataUrl ?? r.previewUrl, i = e ? X(e) : null;
|
|
302
|
+
i && (t.length >= 3 || n + i.base64.length > 15e5 || (t.push(r), n += i.base64.length));
|
|
303
|
+
}
|
|
304
|
+
return t;
|
|
305
|
+
}
|
|
306
|
+
function Q(e, t) {
|
|
307
|
+
let n = [], r = [];
|
|
308
|
+
for (let i of e) {
|
|
309
|
+
if (i.kind === "image") {
|
|
310
|
+
let e = i.inlineDataUrl ?? i.previewUrl, a = e ? X(e) : null;
|
|
311
|
+
if (a && t.has(i.id)) {
|
|
312
|
+
r.push(n.length), n.push({
|
|
313
|
+
type: "image",
|
|
314
|
+
mimeType: a.mimeType,
|
|
315
|
+
data: a.base64,
|
|
316
|
+
...i.downloadUrl ? { url: i.downloadUrl } : {},
|
|
317
|
+
name: i.filename
|
|
318
|
+
});
|
|
319
|
+
continue;
|
|
320
|
+
}
|
|
321
|
+
i.downloadUrl && n.push({
|
|
322
|
+
type: "image",
|
|
323
|
+
mimeType: i.mimeType,
|
|
324
|
+
url: i.downloadUrl,
|
|
325
|
+
name: i.filename
|
|
326
|
+
});
|
|
327
|
+
continue;
|
|
328
|
+
}
|
|
329
|
+
i.downloadUrl && n.push({
|
|
330
|
+
type: "file",
|
|
331
|
+
mimeType: i.mimeType,
|
|
332
|
+
url: i.downloadUrl,
|
|
333
|
+
name: i.filename
|
|
334
|
+
});
|
|
335
|
+
}
|
|
336
|
+
return {
|
|
337
|
+
media: n,
|
|
338
|
+
inlinedIndices: r
|
|
339
|
+
};
|
|
340
|
+
}
|
|
341
|
+
function $(e, t) {
|
|
342
|
+
let n = y(t);
|
|
343
|
+
if (n.length === 0) return;
|
|
344
|
+
let { media: r, inlinedIndices: i } = Q(n, new Set(Z(n).map((e) => e.id)));
|
|
345
|
+
if (r.length !== 0) {
|
|
346
|
+
for (; i.length > 0 && q(e, [{
|
|
347
|
+
type: "text",
|
|
348
|
+
text: e
|
|
349
|
+
}, ...r]) > H;) {
|
|
350
|
+
let e = i.pop();
|
|
351
|
+
if (e === void 0) break;
|
|
352
|
+
let t = r[e];
|
|
353
|
+
!t || t.type === "text" || (t.url ? r[e] = {
|
|
354
|
+
type: t.type,
|
|
355
|
+
mimeType: t.mimeType,
|
|
356
|
+
url: t.url,
|
|
357
|
+
name: t.name
|
|
358
|
+
} : r.splice(e, 1));
|
|
359
|
+
}
|
|
360
|
+
if (r.length !== 0 && !(q(e, [{
|
|
361
|
+
type: "text",
|
|
362
|
+
text: e
|
|
363
|
+
}, ...r]) > H)) return [{
|
|
364
|
+
type: "text",
|
|
365
|
+
text: e
|
|
366
|
+
}, ...r];
|
|
367
|
+
}
|
|
368
|
+
}
|
|
369
|
+
//#endregion
|
|
370
|
+
export { g as ATTACHMENT_ACCEPT, c as AttachmentRejectedError, U as INLINE_IMAGE_MAX_DIM, W as INLINE_IMAGE_QUALITY, i as MAX_ATTACHMENTS, a as MAX_FILE_BYTES, o as MAX_INLINE_CHARS_PER_FILE, s as MAX_INLINE_CHARS_TOTAL, z as MAX_INLINE_IMAGE_BASE64_CHARS, R as MAX_INLINE_IMAGE_PARTS, H as MAX_INLINE_TURN_BODY_BYTES, B as MAX_TURN_BODY_BYTES, P as PROMPT_ENVELOPE_RESERVE_BYTES, V as TURN_BODY_HEADROOM_BYTES, I as buildAttachmentPromptBlock, $ as buildPromptParts, L as buildPromptWithAttachments, f as classifyAttachment, J as countInlineImageCandidates, Y as countInlinedImageParts, h as detectDocumentFormat, q as estimateTurnBodyBytes, _ as formatBytes, b as getAttachmentSendBlocker, d as getExtension, y as getSendableAttachments, v as hasAttachmentWorkInFlight, X as parseDataUrl, l as toMessageAttachment, S as truncateForInline, x as validateFile };
|
|
@@ -0,0 +1,153 @@
|
|
|
1
|
+
import { PendingWrite } from './pendingWrite';
|
|
2
|
+
import { AssistantMessageAttachment } from './attachments';
|
|
3
|
+
import { AssistantMode } from './types';
|
|
4
|
+
export type AssistantSandboxStatus = "none" | "provisioning" | "running" | "stopping" | "error";
|
|
5
|
+
export type AssistantConversationStatus = "idle" | "provisioning" | "connecting" | "streaming" | "complete" | "error";
|
|
6
|
+
/**
|
|
7
|
+
* ★ `AssistantPanelArtifact`, not `AssistantArtifact`. The transport already
|
|
8
|
+
* exports an `AssistantArtifact` in `./types` and the two genuinely differ —
|
|
9
|
+
* this one narrows `type` to a union and makes `downloadPath` optional. They
|
|
10
|
+
* were never reconciled, and reconciling them here would be a silent behaviour
|
|
11
|
+
* change smuggled into a move. Two identically-named exports would also make
|
|
12
|
+
* `export *` drop the name from the barrel with no error at all.
|
|
13
|
+
*
|
|
14
|
+
* The product re-exports this under its historical name, so no call site changes.
|
|
15
|
+
*/
|
|
16
|
+
export interface AssistantPanelArtifact {
|
|
17
|
+
name: string;
|
|
18
|
+
path: string;
|
|
19
|
+
type: "file" | "directory";
|
|
20
|
+
size: number;
|
|
21
|
+
downloadPath?: string;
|
|
22
|
+
}
|
|
23
|
+
export interface AssistantMessageMetadata {
|
|
24
|
+
artifacts?: AssistantPanelArtifact[];
|
|
25
|
+
mode?: AssistantMode;
|
|
26
|
+
sandboxId?: string;
|
|
27
|
+
sessionId?: string;
|
|
28
|
+
/**
|
|
29
|
+
* Files the user attached to this turn. Deliberately the SLIM descriptor —
|
|
30
|
+
* conversations are persisted to localStorage, so preview data URLs and
|
|
31
|
+
* inlined text content must never land here (see AssistantMessageAttachment).
|
|
32
|
+
*/
|
|
33
|
+
attachments?: AssistantMessageAttachment[];
|
|
34
|
+
/**
|
|
35
|
+
* The language this turn was generated under (BOFF-7108), as an assistant
|
|
36
|
+
* language code.
|
|
37
|
+
*
|
|
38
|
+
* Fixed at send time, because it is a property of the TURN and not of the
|
|
39
|
+
* current preference. `resolveSpeechLocale` cannot tell English from Spanish
|
|
40
|
+
* or French — they share a script — so it falls back to whatever language is
|
|
41
|
+
* selected NOW. Without this, a French reply starts being read by a Spanish
|
|
42
|
+
* voice the moment the user switches, even with the right voice installed.
|
|
43
|
+
*/
|
|
44
|
+
lang?: string;
|
|
45
|
+
/**
|
|
46
|
+
* This turn happened inside a live VOICE session, not in the chat panel.
|
|
47
|
+
*
|
|
48
|
+
* ★ The two surfaces share one conversation and one backend session — voice
|
|
49
|
+
* was built as an overlay over the chat thread, so `submitVoiceTurn` calls
|
|
50
|
+
* the same `handleSend` the composer does. Without a marker there is no way
|
|
51
|
+
* to tell a spoken turn from a typed one once it is in the store, and every
|
|
52
|
+
* voice exchange therefore appeared in the normal chat: the operator's own
|
|
53
|
+
* report, "I see the same chat in the normal conversation tab, both are
|
|
54
|
+
* separate, don't confuse".
|
|
55
|
+
*
|
|
56
|
+
* Stamped at send time and persisted, so the distinction survives a reload —
|
|
57
|
+
* the chat transcript is never rehydrated from the backend, so the store is
|
|
58
|
+
* the only source of truth for what the panel shows.
|
|
59
|
+
*/
|
|
60
|
+
voice?: boolean;
|
|
61
|
+
/**
|
|
62
|
+
* WHICH live voice session produced this turn.
|
|
63
|
+
*
|
|
64
|
+
* ★ Not the same thing as `sessionId` above, which is the BACKEND session and
|
|
65
|
+
* is shared with the typed thread. This one identifies a single
|
|
66
|
+
* microphone-on-to-End, so the transcript can say where one spoken exchange
|
|
67
|
+
* stopped and the next began.
|
|
68
|
+
*
|
|
69
|
+
* `voice: true` alone could never do that: it is a boolean, so a second voice
|
|
70
|
+
* session was indistinguishable from the first and the transcript silently ran
|
|
71
|
+
* them together. Two comments claimed the transcript was scoped to "this
|
|
72
|
+
* session" while it was in fact showing the conversation's entire spoken
|
|
73
|
+
* history.
|
|
74
|
+
*
|
|
75
|
+
* ★ OPTIONAL, and it has to stay optional. Every spoken turn recorded before
|
|
76
|
+
* this field existed has `voice: true` and no id, and those conversations are
|
|
77
|
+
* in users' localStorage right now. Anything that REQUIRED an id would erase
|
|
78
|
+
* their history — so an absent id means "some earlier session", which is
|
|
79
|
+
* exactly what it is, and never "not a voice turn".
|
|
80
|
+
*/
|
|
81
|
+
voiceSessionId?: string;
|
|
82
|
+
/**
|
|
83
|
+
* A write this turn asked permission for, read from the refusal the sandbox
|
|
84
|
+
* returned rather than from the model's description of it.
|
|
85
|
+
*
|
|
86
|
+
* ★ Never contains the confirmation token. The token is the capability — a
|
|
87
|
+
* write goes through if it is echoed back — so it must not be persisted to
|
|
88
|
+
* localStorage or rendered. See `utils/pendingWrite`.
|
|
89
|
+
*/
|
|
90
|
+
pendingWrite?: PendingWrite;
|
|
91
|
+
[key: string]: unknown;
|
|
92
|
+
}
|
|
93
|
+
export interface Message {
|
|
94
|
+
id: string;
|
|
95
|
+
role: "user" | "assistant" | "system";
|
|
96
|
+
content: string;
|
|
97
|
+
timestamp: string;
|
|
98
|
+
tokens?: {
|
|
99
|
+
input: number;
|
|
100
|
+
output: number;
|
|
101
|
+
};
|
|
102
|
+
metadata?: AssistantMessageMetadata;
|
|
103
|
+
}
|
|
104
|
+
export interface Conversation {
|
|
105
|
+
id: string;
|
|
106
|
+
title: string;
|
|
107
|
+
mode: AssistantMode;
|
|
108
|
+
/**
|
|
109
|
+
* EVERY turn, both surfaces — typed and spoken.
|
|
110
|
+
*
|
|
111
|
+
* ★ `readonly` on purpose, and it is load-bearing rather than hygiene. Voice
|
|
112
|
+
* and chat share this one array; what separates them is `metadata.voice` plus
|
|
113
|
+
* a filter at every reader, so the failure mode is a new reader that renders
|
|
114
|
+
* the array as-is and silently spills spoken content into the typed thread.
|
|
115
|
+
* Nothing about that is a type error, and it stays green in CI.
|
|
116
|
+
*
|
|
117
|
+
* Being readonly makes it one: components take `Message[]`, so handing them
|
|
118
|
+
* this field directly no longer compiles. The way through is `chatTurns()` or
|
|
119
|
+
* `voiceTurnsOnly()` (see `utils/voiceTurnVisibility`), both of which return a
|
|
120
|
+
* fresh mutable array — which means picking a surface is now a step you cannot
|
|
121
|
+
* skip by accident.
|
|
122
|
+
*
|
|
123
|
+
* Counting is still fine: `.length` answers "is this conversation used at
|
|
124
|
+
* all", which is a question about the conversation and not about either
|
|
125
|
+
* surface.
|
|
126
|
+
*/
|
|
127
|
+
messages: readonly Message[];
|
|
128
|
+
createdAt: string;
|
|
129
|
+
updatedAt: string;
|
|
130
|
+
/** Backend session ID for this conversation */
|
|
131
|
+
backendSessionId?: string | null;
|
|
132
|
+
}
|
|
133
|
+
export interface AssistantSandboxRuntime {
|
|
134
|
+
sandboxId: string;
|
|
135
|
+
status: AssistantSandboxStatus;
|
|
136
|
+
}
|
|
137
|
+
export interface AssistantConversationProcessing {
|
|
138
|
+
status: AssistantConversationStatus;
|
|
139
|
+
messageId: string | null;
|
|
140
|
+
error?: string | null;
|
|
141
|
+
updatedAt: string;
|
|
142
|
+
}
|
|
143
|
+
export interface AssistantModeConfig {
|
|
144
|
+
id: AssistantMode;
|
|
145
|
+
label: string;
|
|
146
|
+
description: string;
|
|
147
|
+
suggestions: readonly string[];
|
|
148
|
+
/** Only offered to a global Owner/Admin (see useAssistantApiAccess). */
|
|
149
|
+
requiresAdmin?: boolean;
|
|
150
|
+
/** Executes mutations on live data → triggers the confirm-before-mutate guard. */
|
|
151
|
+
writeCapable?: boolean;
|
|
152
|
+
}
|
|
153
|
+
//# sourceMappingURL=conversation.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"conversation.d.ts","sourceRoot":"","sources":["../../../src/shared/assistant/conversation.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;GAUG;AAIH,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,gBAAgB,CAAC;AACnD,OAAO,KAAK,EAAE,0BAA0B,EAAE,MAAM,eAAe,CAAC;AAIhE,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,SAAS,CAAC;AAE7C,MAAM,MAAM,sBAAsB,GAC9B,MAAM,GACN,cAAc,GACd,SAAS,GACT,UAAU,GACV,OAAO,CAAC;AAEZ,MAAM,MAAM,2BAA2B,GACnC,MAAM,GACN,cAAc,GACd,YAAY,GACZ,WAAW,GACX,UAAU,GACV,OAAO,CAAC;AAEZ;;;;;;;;;GASG;AACH,MAAM,WAAW,sBAAsB;IACrC,IAAI,EAAE,MAAM,CAAC;IACb,IAAI,EAAE,MAAM,CAAC;IACb,IAAI,EAAE,MAAM,GAAG,WAAW,CAAC;IAC3B,IAAI,EAAE,MAAM,CAAC;IACb,YAAY,CAAC,EAAE,MAAM,CAAC;CACvB;AAED,MAAM,WAAW,wBAAwB;IACvC,SAAS,CAAC,EAAE,sBAAsB,EAAE,CAAC;IACrC,IAAI,CAAC,EAAE,aAAa,CAAC;IACrB,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB;;;;OAIG;IACH,WAAW,CAAC,EAAE,0BAA0B,EAAE,CAAC;IAC3C;;;;;;;;;OASG;IACH,IAAI,CAAC,EAAE,MAAM,CAAC;IACd;;;;;;;;;;;;;;OAcG;IACH,KAAK,CAAC,EAAE,OAAO,CAAC;IAChB;;;;;;;;;;;;;;;;;;;OAmBG;IACH,cAAc,CAAC,EAAE,MAAM,CAAC;IACxB;;;;;;;OAOG;IACH,YAAY,CAAC,EAAE,YAAY,CAAC;IAC5B,CAAC,GAAG,EAAE,MAAM,GAAG,OAAO,CAAC;CACxB;AAED,MAAM,WAAW,OAAO;IACtB,EAAE,EAAE,MAAM,CAAC;IACX,IAAI,EAAE,MAAM,GAAG,WAAW,GAAG,QAAQ,CAAC;IACtC,OAAO,EAAE,MAAM,CAAC;IAChB,SAAS,EAAE,MAAM,CAAC;IAClB,MAAM,CAAC,EAAE;QAAE,KAAK,EAAE,MAAM,CAAC;QAAC,MAAM,EAAE,MAAM,CAAA;KAAE,CAAC;IAC3C,QAAQ,CAAC,EAAE,wBAAwB,CAAC;CACrC;AAED,MAAM,WAAW,YAAY;IAC3B,EAAE,EAAE,MAAM,CAAC;IACX,KAAK,EAAE,MAAM,CAAC;IACd,IAAI,EAAE,aAAa,CAAC;IACpB;;;;;;;;;;;;;;;;;;OAkBG;IACH,QAAQ,EAAE,SAAS,OAAO,EAAE,CAAC;IAC7B,SAAS,EAAE,MAAM,CAAC;IAClB,SAAS,EAAE,MAAM,CAAC;IAClB,+CAA+C;IAC/C,gBAAgB,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;CAClC;AAED,MAAM,WAAW,uBAAuB;IACtC,SAAS,EAAE,MAAM,CAAC;IAClB,MAAM,EAAE,sBAAsB,CAAC;CAChC;AAED,MAAM,WAAW,+BAA+B;IAC9C,MAAM,EAAE,2BAA2B,CAAC;IACpC,SAAS,EAAE,MAAM,GAAG,IAAI,CAAC;IACzB,KAAK,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;IACtB,SAAS,EAAE,MAAM,CAAC;CACnB;AAED,MAAM,WAAW,mBAAmB;IAClC,EAAE,EAAE,aAAa,CAAC;IAClB,KAAK,EAAE,MAAM,CAAC;IACd,WAAW,EAAE,MAAM,CAAC;IACpB,WAAW,EAAE,SAAS,MAAM,EAAE,CAAC;IAC/B,wEAAwE;IACxE,aAAa,CAAC,EAAE,OAAO,CAAC;IACxB,kFAAkF;IAClF,YAAY,CAAC,EAAE,OAAO,CAAC;CACxB"}
|