@noodleseed/assistant 1.18.0 → 1.20.0
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 +68 -0
- package/dist/{chunk-RIKRQFKS.js → chunk-52XT7BLR.js} +10 -4
- package/dist/{chunk-RIKRQFKS.js.map → chunk-52XT7BLR.js.map} +1 -1
- package/dist/{chunk-MZNENVFY.js → chunk-DLUINP4W.js} +165 -13
- package/dist/chunk-DLUINP4W.js.map +1 -0
- package/dist/{client-BQ30Fq-c.d.cts → client-7o7n2nqw.d.cts} +6 -4
- package/dist/{client-B6pnBmF8.d.ts → client-CysBQBdd.d.ts} +6 -4
- package/dist/client.cjs +8 -3
- package/dist/client.cjs.map +1 -1
- package/dist/client.d.cts +1 -1
- package/dist/client.d.ts +1 -1
- package/dist/client.js +1 -1
- package/dist/embed.global.js +57 -57
- package/dist/index.cjs +283 -127
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +2 -2
- package/dist/index.d.ts +2 -2
- package/dist/index.js +2 -2
- package/dist/react/client.cjs +8 -3
- package/dist/react/client.cjs.map +1 -1
- package/dist/react/client.d.cts +1 -1
- package/dist/react/client.d.ts +1 -1
- package/dist/react/client.js +1 -1
- package/dist/react.cjs +283 -127
- package/dist/react.cjs.map +1 -1
- package/dist/react.d.cts +1 -1
- package/dist/react.d.ts +1 -1
- package/dist/react.js +2 -2
- package/dist/server.cjs +47 -1
- package/dist/server.cjs.map +1 -1
- package/dist/server.d.cts +60 -7
- package/dist/server.d.ts +60 -7
- package/dist/server.js +45 -1
- package/dist/server.js.map +1 -1
- package/package.json +1 -1
- package/dist/chunk-MZNENVFY.js.map +0 -1
package/dist/index.cjs
CHANGED
|
@@ -22567,7 +22567,122 @@ function radiusValue(radius) {
|
|
|
22567
22567
|
return 14;
|
|
22568
22568
|
}
|
|
22569
22569
|
|
|
22570
|
+
// src/model-context.ts
|
|
22571
|
+
var MAX_BYTES = 16 * 1024;
|
|
22572
|
+
var MAX_DEPTH = 8;
|
|
22573
|
+
var MAX_ENTRIES = 128;
|
|
22574
|
+
var SENSITIVE_KEY = /(?:secret|token|api[-_]?key|password|credential|authorization|cookie)/i;
|
|
22575
|
+
var CREDENTIAL_SHAPED_TEXT = /(?:-----BEGIN [A-Z ]*PRIVATE KEY-----|\bsk-[A-Za-z0-9_-]{20,}\b|\b(?:bearer|basic)\s+[A-Za-z0-9._~+/=-]{20,}\b|\b[A-Za-z0-9_-]{16,}\.[A-Za-z0-9_-]{16,}\.[A-Za-z0-9_-]{16,}\b)/i;
|
|
22576
|
+
function copyAssistantModelContext(update) {
|
|
22577
|
+
const copied = copyJsonValue(update, "$", 0, /* @__PURE__ */ new Set());
|
|
22578
|
+
assertModelContextShape(copied);
|
|
22579
|
+
const encoded = JSON.stringify(copied);
|
|
22580
|
+
if (new TextEncoder().encode(encoded).byteLength > MAX_BYTES) {
|
|
22581
|
+
throw new Error("Model context must not exceed 16 KiB");
|
|
22582
|
+
}
|
|
22583
|
+
return copied;
|
|
22584
|
+
}
|
|
22585
|
+
function copyAssistantPageContext(context) {
|
|
22586
|
+
const copied = copyJsonValue(context, "$", 0, /* @__PURE__ */ new Set());
|
|
22587
|
+
if (typeof copied !== "object" || copied === null || Array.isArray(copied)) {
|
|
22588
|
+
throw new Error("Page context must be a JSON object");
|
|
22589
|
+
}
|
|
22590
|
+
const encoded = JSON.stringify(copied);
|
|
22591
|
+
if (new TextEncoder().encode(encoded).byteLength > MAX_BYTES) {
|
|
22592
|
+
throw new Error("Page context must not exceed 16 KiB");
|
|
22593
|
+
}
|
|
22594
|
+
return copied;
|
|
22595
|
+
}
|
|
22596
|
+
function assertModelContextShape(value) {
|
|
22597
|
+
if (!isPlainRecord(value)) throw new Error("Model context must be a JSON object");
|
|
22598
|
+
for (const key of Object.keys(value)) {
|
|
22599
|
+
if (key !== "content" && key !== "structuredContent") {
|
|
22600
|
+
throw new Error(`Model context contains unknown field ${key}`);
|
|
22601
|
+
}
|
|
22602
|
+
}
|
|
22603
|
+
if (value.content !== void 0) {
|
|
22604
|
+
if (!Array.isArray(value.content)) throw new Error("Model context content must be an array");
|
|
22605
|
+
for (const part of value.content) {
|
|
22606
|
+
if (!isPlainRecord(part) || Object.keys(part).some((key) => key !== "type" && key !== "text") || part.type !== "text" || typeof part.text !== "string") {
|
|
22607
|
+
throw new Error("Model context content supports text parts only");
|
|
22608
|
+
}
|
|
22609
|
+
}
|
|
22610
|
+
}
|
|
22611
|
+
if (value.structuredContent !== void 0 && !isPlainRecord(value.structuredContent)) {
|
|
22612
|
+
throw new Error("Model context structuredContent must be an object");
|
|
22613
|
+
}
|
|
22614
|
+
}
|
|
22615
|
+
function copyJsonValue(value, path, depth, ancestors) {
|
|
22616
|
+
if (depth > MAX_DEPTH) throw new Error(`Model context exceeds maximum depth at ${path}`);
|
|
22617
|
+
if (typeof value === "string") {
|
|
22618
|
+
if (CREDENTIAL_SHAPED_TEXT.test(value)) {
|
|
22619
|
+
throw new Error(`Model context contains credential-shaped text at ${path}`);
|
|
22620
|
+
}
|
|
22621
|
+
return value;
|
|
22622
|
+
}
|
|
22623
|
+
if (value === null || typeof value === "boolean" || typeof value === "number" && Number.isFinite(value)) {
|
|
22624
|
+
return value;
|
|
22625
|
+
}
|
|
22626
|
+
if (typeof value !== "object") throw new Error(`Model context contains non-JSON data at ${path}`);
|
|
22627
|
+
if (hasToJsonProperty(value)) {
|
|
22628
|
+
throw new Error(`Model context must not define or inherit toJSON at ${path}`);
|
|
22629
|
+
}
|
|
22630
|
+
const prototype = Object.getPrototypeOf(value);
|
|
22631
|
+
if (Array.isArray(value)) {
|
|
22632
|
+
if (prototype !== Array.prototype) {
|
|
22633
|
+
throw new Error(`Model context contains a non-JSON object at ${path}`);
|
|
22634
|
+
}
|
|
22635
|
+
} else if (prototype !== Object.prototype && prototype !== null) {
|
|
22636
|
+
throw new Error(`Model context contains a non-JSON object at ${path}`);
|
|
22637
|
+
}
|
|
22638
|
+
if (ancestors.has(value)) throw new Error(`Model context contains a cycle at ${path}`);
|
|
22639
|
+
if (Array.isArray(value)) {
|
|
22640
|
+
if (value.length > MAX_ENTRIES) {
|
|
22641
|
+
throw new Error(`Model context has more than 128 entries at ${path}`);
|
|
22642
|
+
}
|
|
22643
|
+
const copy2 = [];
|
|
22644
|
+
ancestors.add(value);
|
|
22645
|
+
for (let index = 0; index < value.length; index += 1) {
|
|
22646
|
+
const entry = Object.hasOwn(value, index) ? value[index] : null;
|
|
22647
|
+
copy2.push(copyJsonValue(entry, `${path}.${index}`, depth + 1, ancestors));
|
|
22648
|
+
}
|
|
22649
|
+
ancestors.delete(value);
|
|
22650
|
+
return copy2;
|
|
22651
|
+
}
|
|
22652
|
+
const entries2 = Object.entries(value);
|
|
22653
|
+
if (entries2.length > MAX_ENTRIES) {
|
|
22654
|
+
throw new Error(`Model context has more than 128 entries at ${path}`);
|
|
22655
|
+
}
|
|
22656
|
+
const copy = /* @__PURE__ */ Object.create(null);
|
|
22657
|
+
ancestors.add(value);
|
|
22658
|
+
for (const [key, entry] of entries2) {
|
|
22659
|
+
if (SENSITIVE_KEY.test(key)) {
|
|
22660
|
+
throw new Error(`Model context contains sensitive key ${path}.${key}`);
|
|
22661
|
+
}
|
|
22662
|
+
copy[key] = copyJsonValue(entry, `${path}.${key}`, depth + 1, ancestors);
|
|
22663
|
+
}
|
|
22664
|
+
ancestors.delete(value);
|
|
22665
|
+
return copy;
|
|
22666
|
+
}
|
|
22667
|
+
function isPlainRecord(value) {
|
|
22668
|
+
if (typeof value !== "object" || value === null || Array.isArray(value)) return false;
|
|
22669
|
+
const prototype = Object.getPrototypeOf(value);
|
|
22670
|
+
return prototype === Object.prototype || prototype === null;
|
|
22671
|
+
}
|
|
22672
|
+
function hasToJsonProperty(value) {
|
|
22673
|
+
let current = value;
|
|
22674
|
+
const visited = /* @__PURE__ */ new Set();
|
|
22675
|
+
while (current !== null && !visited.has(current)) {
|
|
22676
|
+
visited.add(current);
|
|
22677
|
+
if (Object.getOwnPropertyDescriptor(current, "toJSON") !== void 0) return true;
|
|
22678
|
+
current = Object.getPrototypeOf(current);
|
|
22679
|
+
}
|
|
22680
|
+
return false;
|
|
22681
|
+
}
|
|
22682
|
+
|
|
22570
22683
|
// src/browser-context.ts
|
|
22684
|
+
var PAGE_MARKDOWN_MAX_BYTES = 12 * 1024;
|
|
22685
|
+
var PAGE_MARKDOWN_TIMEOUT_MS = 2e3;
|
|
22571
22686
|
function browserClientContext() {
|
|
22572
22687
|
let timeZone;
|
|
22573
22688
|
try {
|
|
@@ -22580,6 +22695,108 @@ function browserClientContext() {
|
|
|
22580
22695
|
...timeZone ? { timeZone } : {}
|
|
22581
22696
|
};
|
|
22582
22697
|
}
|
|
22698
|
+
function browserPageUrl() {
|
|
22699
|
+
try {
|
|
22700
|
+
const location = globalThis.location;
|
|
22701
|
+
if (!location) return void 0;
|
|
22702
|
+
const url2 = new URL(location.href);
|
|
22703
|
+
if (url2.origin === "null") return void 0;
|
|
22704
|
+
return `${url2.origin}${url2.pathname}`;
|
|
22705
|
+
} catch {
|
|
22706
|
+
return void 0;
|
|
22707
|
+
}
|
|
22708
|
+
}
|
|
22709
|
+
async function browserPageContext(url2) {
|
|
22710
|
+
let urlOnly;
|
|
22711
|
+
try {
|
|
22712
|
+
urlOnly = copyAssistantPageContext({ page: { url: url2 } });
|
|
22713
|
+
} catch {
|
|
22714
|
+
return void 0;
|
|
22715
|
+
}
|
|
22716
|
+
const controller = new AbortController();
|
|
22717
|
+
const timeout = globalThis.setTimeout(() => controller.abort(), PAGE_MARKDOWN_TIMEOUT_MS);
|
|
22718
|
+
try {
|
|
22719
|
+
const response = await fetch(url2, {
|
|
22720
|
+
headers: { Accept: "text/markdown" },
|
|
22721
|
+
credentials: "omit",
|
|
22722
|
+
cache: "no-store",
|
|
22723
|
+
redirect: "error",
|
|
22724
|
+
referrerPolicy: "no-referrer",
|
|
22725
|
+
signal: controller.signal
|
|
22726
|
+
});
|
|
22727
|
+
if (!response.ok || !isSameOrigin(response, url2) || !isMarkdown(response)) return urlOnly;
|
|
22728
|
+
const { content, truncated } = await readBoundedUtf8(response);
|
|
22729
|
+
const page = {
|
|
22730
|
+
page: {
|
|
22731
|
+
url: url2,
|
|
22732
|
+
contentType: "text/markdown",
|
|
22733
|
+
content,
|
|
22734
|
+
...truncated ? { truncated: true } : {}
|
|
22735
|
+
}
|
|
22736
|
+
};
|
|
22737
|
+
return copyAssistantPageContext(page);
|
|
22738
|
+
} catch {
|
|
22739
|
+
return urlOnly;
|
|
22740
|
+
} finally {
|
|
22741
|
+
globalThis.clearTimeout(timeout);
|
|
22742
|
+
}
|
|
22743
|
+
}
|
|
22744
|
+
function isSameOrigin(response, url2) {
|
|
22745
|
+
try {
|
|
22746
|
+
return response.url !== "" && new URL(response.url).origin === new URL(url2).origin;
|
|
22747
|
+
} catch {
|
|
22748
|
+
return false;
|
|
22749
|
+
}
|
|
22750
|
+
}
|
|
22751
|
+
function isMarkdown(response) {
|
|
22752
|
+
return response.headers.get("content-type")?.split(";", 1)[0]?.trim().toLowerCase() === "text/markdown";
|
|
22753
|
+
}
|
|
22754
|
+
async function readBoundedUtf8(response) {
|
|
22755
|
+
const reader = response.body?.getReader();
|
|
22756
|
+
if (!reader) throw new Error("Markdown response has no readable body");
|
|
22757
|
+
const chunks = [];
|
|
22758
|
+
let byteLength = 0;
|
|
22759
|
+
let truncated = false;
|
|
22760
|
+
try {
|
|
22761
|
+
while (true) {
|
|
22762
|
+
const { done, value } = await reader.read();
|
|
22763
|
+
if (done) break;
|
|
22764
|
+
const remaining = PAGE_MARKDOWN_MAX_BYTES - byteLength;
|
|
22765
|
+
if (value.byteLength > remaining) {
|
|
22766
|
+
if (remaining > 0) chunks.push(value.slice(0, remaining));
|
|
22767
|
+
truncated = true;
|
|
22768
|
+
await reader.cancel();
|
|
22769
|
+
break;
|
|
22770
|
+
}
|
|
22771
|
+
chunks.push(value);
|
|
22772
|
+
byteLength += value.byteLength;
|
|
22773
|
+
}
|
|
22774
|
+
} finally {
|
|
22775
|
+
reader.releaseLock();
|
|
22776
|
+
}
|
|
22777
|
+
const bytes = new Uint8Array(chunks.reduce((size, chunk) => size + chunk.byteLength, 0));
|
|
22778
|
+
let offset = 0;
|
|
22779
|
+
for (const chunk of chunks) {
|
|
22780
|
+
bytes.set(chunk, offset);
|
|
22781
|
+
offset += chunk.byteLength;
|
|
22782
|
+
}
|
|
22783
|
+
return { content: decodeUtf8(bytes, truncated), truncated };
|
|
22784
|
+
}
|
|
22785
|
+
function decodeUtf8(bytes, truncated) {
|
|
22786
|
+
const decoder = new TextDecoder("utf-8", { fatal: true });
|
|
22787
|
+
let content;
|
|
22788
|
+
try {
|
|
22789
|
+
content = decoder.decode(bytes, { stream: true });
|
|
22790
|
+
} catch {
|
|
22791
|
+
throw new Error("Markdown response is not valid UTF-8");
|
|
22792
|
+
}
|
|
22793
|
+
try {
|
|
22794
|
+
return content + decoder.decode();
|
|
22795
|
+
} catch {
|
|
22796
|
+
if (truncated) return content;
|
|
22797
|
+
throw new Error("Markdown response is not valid UTF-8");
|
|
22798
|
+
}
|
|
22799
|
+
}
|
|
22583
22800
|
|
|
22584
22801
|
// ../../node_modules/.pnpm/@ai-sdk+provider@3.0.10/node_modules/@ai-sdk/provider/dist/index.mjs
|
|
22585
22802
|
var marker = "vercel.ai.error";
|
|
@@ -27092,11 +27309,16 @@ function toAssistantClientEvent(event) {
|
|
|
27092
27309
|
return event;
|
|
27093
27310
|
}
|
|
27094
27311
|
break;
|
|
27095
|
-
case "auth_requested":
|
|
27096
|
-
|
|
27097
|
-
|
|
27312
|
+
case "auth_requested": {
|
|
27313
|
+
const signInTicket = typeof value.signInTicket === "string" ? value.signInTicket : typeof value.continuation === "string" ? value.continuation : void 0;
|
|
27314
|
+
if (hasString(value, "id") && hasString(value, "tool") && signInTicket !== void 0 && hasString(value, "expiresAt") && hasOptionalTurnId(value)) {
|
|
27315
|
+
return {
|
|
27316
|
+
event: "auth_requested",
|
|
27317
|
+
data: { ...value, signInTicket }
|
|
27318
|
+
};
|
|
27098
27319
|
}
|
|
27099
27320
|
break;
|
|
27321
|
+
}
|
|
27100
27322
|
case "interaction_resolved":
|
|
27101
27323
|
if (hasString(value, "id") && (value.action === void 0 || isInteractionAction(value.action)) && hasOptionalTurnId(value)) {
|
|
27102
27324
|
return event;
|
|
@@ -27168,119 +27390,6 @@ function isRecord2(value) {
|
|
|
27168
27390
|
return typeof value === "object" && value !== null && !Array.isArray(value);
|
|
27169
27391
|
}
|
|
27170
27392
|
|
|
27171
|
-
// src/model-context.ts
|
|
27172
|
-
var MAX_BYTES = 16 * 1024;
|
|
27173
|
-
var MAX_DEPTH = 8;
|
|
27174
|
-
var MAX_ENTRIES = 128;
|
|
27175
|
-
var SENSITIVE_KEY = /(?:secret|token|api[-_]?key|password|credential|authorization|cookie)/i;
|
|
27176
|
-
var CREDENTIAL_SHAPED_TEXT = /(?:-----BEGIN [A-Z ]*PRIVATE KEY-----|\bsk-[A-Za-z0-9_-]{20,}\b|\b(?:bearer|basic)\s+[A-Za-z0-9._~+/=-]{20,}\b|\b[A-Za-z0-9_-]{16,}\.[A-Za-z0-9_-]{16,}\.[A-Za-z0-9_-]{16,}\b)/i;
|
|
27177
|
-
function copyAssistantModelContext(update) {
|
|
27178
|
-
const copied = copyJsonValue(update, "$", 0, /* @__PURE__ */ new Set());
|
|
27179
|
-
assertModelContextShape(copied);
|
|
27180
|
-
const encoded = JSON.stringify(copied);
|
|
27181
|
-
if (new TextEncoder().encode(encoded).byteLength > MAX_BYTES) {
|
|
27182
|
-
throw new Error("Model context must not exceed 16 KiB");
|
|
27183
|
-
}
|
|
27184
|
-
return copied;
|
|
27185
|
-
}
|
|
27186
|
-
function copyAssistantPageContext(context) {
|
|
27187
|
-
const copied = copyJsonValue(context, "$", 0, /* @__PURE__ */ new Set());
|
|
27188
|
-
if (typeof copied !== "object" || copied === null || Array.isArray(copied)) {
|
|
27189
|
-
throw new Error("Page context must be a JSON object");
|
|
27190
|
-
}
|
|
27191
|
-
const encoded = JSON.stringify(copied);
|
|
27192
|
-
if (new TextEncoder().encode(encoded).byteLength > MAX_BYTES) {
|
|
27193
|
-
throw new Error("Page context must not exceed 16 KiB");
|
|
27194
|
-
}
|
|
27195
|
-
return copied;
|
|
27196
|
-
}
|
|
27197
|
-
function assertModelContextShape(value) {
|
|
27198
|
-
if (!isPlainRecord(value)) throw new Error("Model context must be a JSON object");
|
|
27199
|
-
for (const key of Object.keys(value)) {
|
|
27200
|
-
if (key !== "content" && key !== "structuredContent") {
|
|
27201
|
-
throw new Error(`Model context contains unknown field ${key}`);
|
|
27202
|
-
}
|
|
27203
|
-
}
|
|
27204
|
-
if (value.content !== void 0) {
|
|
27205
|
-
if (!Array.isArray(value.content)) throw new Error("Model context content must be an array");
|
|
27206
|
-
for (const part of value.content) {
|
|
27207
|
-
if (!isPlainRecord(part) || Object.keys(part).some((key) => key !== "type" && key !== "text") || part.type !== "text" || typeof part.text !== "string") {
|
|
27208
|
-
throw new Error("Model context content supports text parts only");
|
|
27209
|
-
}
|
|
27210
|
-
}
|
|
27211
|
-
}
|
|
27212
|
-
if (value.structuredContent !== void 0 && !isPlainRecord(value.structuredContent)) {
|
|
27213
|
-
throw new Error("Model context structuredContent must be an object");
|
|
27214
|
-
}
|
|
27215
|
-
}
|
|
27216
|
-
function copyJsonValue(value, path, depth, ancestors) {
|
|
27217
|
-
if (depth > MAX_DEPTH) throw new Error(`Model context exceeds maximum depth at ${path}`);
|
|
27218
|
-
if (typeof value === "string") {
|
|
27219
|
-
if (CREDENTIAL_SHAPED_TEXT.test(value)) {
|
|
27220
|
-
throw new Error(`Model context contains credential-shaped text at ${path}`);
|
|
27221
|
-
}
|
|
27222
|
-
return value;
|
|
27223
|
-
}
|
|
27224
|
-
if (value === null || typeof value === "boolean" || typeof value === "number" && Number.isFinite(value)) {
|
|
27225
|
-
return value;
|
|
27226
|
-
}
|
|
27227
|
-
if (typeof value !== "object") throw new Error(`Model context contains non-JSON data at ${path}`);
|
|
27228
|
-
if (hasToJsonProperty(value)) {
|
|
27229
|
-
throw new Error(`Model context must not define or inherit toJSON at ${path}`);
|
|
27230
|
-
}
|
|
27231
|
-
const prototype = Object.getPrototypeOf(value);
|
|
27232
|
-
if (Array.isArray(value)) {
|
|
27233
|
-
if (prototype !== Array.prototype) {
|
|
27234
|
-
throw new Error(`Model context contains a non-JSON object at ${path}`);
|
|
27235
|
-
}
|
|
27236
|
-
} else if (prototype !== Object.prototype && prototype !== null) {
|
|
27237
|
-
throw new Error(`Model context contains a non-JSON object at ${path}`);
|
|
27238
|
-
}
|
|
27239
|
-
if (ancestors.has(value)) throw new Error(`Model context contains a cycle at ${path}`);
|
|
27240
|
-
if (Array.isArray(value)) {
|
|
27241
|
-
if (value.length > MAX_ENTRIES) {
|
|
27242
|
-
throw new Error(`Model context has more than 128 entries at ${path}`);
|
|
27243
|
-
}
|
|
27244
|
-
const copy2 = [];
|
|
27245
|
-
ancestors.add(value);
|
|
27246
|
-
for (let index = 0; index < value.length; index += 1) {
|
|
27247
|
-
const entry = Object.hasOwn(value, index) ? value[index] : null;
|
|
27248
|
-
copy2.push(copyJsonValue(entry, `${path}.${index}`, depth + 1, ancestors));
|
|
27249
|
-
}
|
|
27250
|
-
ancestors.delete(value);
|
|
27251
|
-
return copy2;
|
|
27252
|
-
}
|
|
27253
|
-
const entries2 = Object.entries(value);
|
|
27254
|
-
if (entries2.length > MAX_ENTRIES) {
|
|
27255
|
-
throw new Error(`Model context has more than 128 entries at ${path}`);
|
|
27256
|
-
}
|
|
27257
|
-
const copy = /* @__PURE__ */ Object.create(null);
|
|
27258
|
-
ancestors.add(value);
|
|
27259
|
-
for (const [key, entry] of entries2) {
|
|
27260
|
-
if (SENSITIVE_KEY.test(key)) {
|
|
27261
|
-
throw new Error(`Model context contains sensitive key ${path}.${key}`);
|
|
27262
|
-
}
|
|
27263
|
-
copy[key] = copyJsonValue(entry, `${path}.${key}`, depth + 1, ancestors);
|
|
27264
|
-
}
|
|
27265
|
-
ancestors.delete(value);
|
|
27266
|
-
return copy;
|
|
27267
|
-
}
|
|
27268
|
-
function isPlainRecord(value) {
|
|
27269
|
-
if (typeof value !== "object" || value === null || Array.isArray(value)) return false;
|
|
27270
|
-
const prototype = Object.getPrototypeOf(value);
|
|
27271
|
-
return prototype === Object.prototype || prototype === null;
|
|
27272
|
-
}
|
|
27273
|
-
function hasToJsonProperty(value) {
|
|
27274
|
-
let current = value;
|
|
27275
|
-
const visited = /* @__PURE__ */ new Set();
|
|
27276
|
-
while (current !== null && !visited.has(current)) {
|
|
27277
|
-
visited.add(current);
|
|
27278
|
-
if (Object.getOwnPropertyDescriptor(current, "toJSON") !== void 0) return true;
|
|
27279
|
-
current = Object.getPrototypeOf(current);
|
|
27280
|
-
}
|
|
27281
|
-
return false;
|
|
27282
|
-
}
|
|
27283
|
-
|
|
27284
27393
|
// src/session-source.ts
|
|
27285
27394
|
var NOODLE_CLOUD_URL = "https://cloud.noodleseed.dev";
|
|
27286
27395
|
var PUBLIC_SESSION_PATH = "/v1/assistant/public-sessions";
|
|
@@ -31166,11 +31275,11 @@ var AssistantElementEventController = class {
|
|
|
31166
31275
|
);
|
|
31167
31276
|
return;
|
|
31168
31277
|
}
|
|
31169
|
-
if (name21 === "auth_requested" && typeof data.
|
|
31278
|
+
if (name21 === "auth_requested" && typeof data.signInTicket === "string") {
|
|
31170
31279
|
this.#appendSignInRequest(
|
|
31171
31280
|
String(data.id ?? ""),
|
|
31172
31281
|
String(data.tool ?? "this"),
|
|
31173
|
-
data.
|
|
31282
|
+
data.signInTicket,
|
|
31174
31283
|
String(data.expiresAt ?? "")
|
|
31175
31284
|
);
|
|
31176
31285
|
return;
|
|
@@ -31263,15 +31372,15 @@ var AssistantElementEventController = class {
|
|
|
31263
31372
|
/**
|
|
31264
31373
|
* The host application owns the login. This renders the prompt and raises
|
|
31265
31374
|
* `assistant-sign-in-requested`; the page signs the visitor in however it already does, then its
|
|
31266
|
-
* backend spends the
|
|
31375
|
+
* backend spends the sign-in ticket. Nothing here talks to an identity provider.
|
|
31267
31376
|
*/
|
|
31268
|
-
#appendSignInRequest(id, tool,
|
|
31377
|
+
#appendSignInRequest(id, tool, signInTicket, expiresAt) {
|
|
31269
31378
|
const messages = this.#host.messages();
|
|
31270
31379
|
if (!messages) return;
|
|
31271
31380
|
this.#proposalCards.get(id)?.remove();
|
|
31272
31381
|
const card = createSignInCard({
|
|
31273
31382
|
tool,
|
|
31274
|
-
|
|
31383
|
+
signInTicket,
|
|
31275
31384
|
expiresAt,
|
|
31276
31385
|
labels: {
|
|
31277
31386
|
heading: "Sign in to continue",
|
|
@@ -31279,7 +31388,7 @@ var AssistantElementEventController = class {
|
|
|
31279
31388
|
},
|
|
31280
31389
|
onSignIn: () => this.#host.element.dispatchEvent(
|
|
31281
31390
|
new CustomEvent("assistant-sign-in-requested", {
|
|
31282
|
-
detail: { id, tool,
|
|
31391
|
+
detail: { id, tool, signInTicket, expiresAt },
|
|
31283
31392
|
bubbles: true,
|
|
31284
31393
|
composed: true
|
|
31285
31394
|
})
|
|
@@ -31290,7 +31399,7 @@ var AssistantElementEventController = class {
|
|
|
31290
31399
|
this.#host.revealLatest();
|
|
31291
31400
|
this.#host.element.dispatchEvent(
|
|
31292
31401
|
new CustomEvent("assistant-sign-in-required", {
|
|
31293
|
-
detail: { id, tool,
|
|
31402
|
+
detail: { id, tool, signInTicket, expiresAt }
|
|
31294
31403
|
})
|
|
31295
31404
|
);
|
|
31296
31405
|
}
|
|
@@ -31365,6 +31474,46 @@ function queryRequired(root, selector) {
|
|
|
31365
31474
|
return element;
|
|
31366
31475
|
}
|
|
31367
31476
|
|
|
31477
|
+
// src/element-page-context-controller.ts
|
|
31478
|
+
var AssistantElementPageContextController = class {
|
|
31479
|
+
#snapshot;
|
|
31480
|
+
#load;
|
|
31481
|
+
#isEnabled;
|
|
31482
|
+
constructor(isEnabled) {
|
|
31483
|
+
this.#isEnabled = isEnabled;
|
|
31484
|
+
}
|
|
31485
|
+
current() {
|
|
31486
|
+
const url2 = browserPageUrl();
|
|
31487
|
+
if (!url2 || this.#snapshot?.url !== url2) {
|
|
31488
|
+
this.#snapshot = void 0;
|
|
31489
|
+
return void 0;
|
|
31490
|
+
}
|
|
31491
|
+
return this.#snapshot.context;
|
|
31492
|
+
}
|
|
31493
|
+
async refresh() {
|
|
31494
|
+
while (true) {
|
|
31495
|
+
const url2 = browserPageUrl();
|
|
31496
|
+
if (!url2) return;
|
|
31497
|
+
if (this.#snapshot?.url === url2) return;
|
|
31498
|
+
this.#snapshot = void 0;
|
|
31499
|
+
let load = this.#load;
|
|
31500
|
+
if (!load || load.url !== url2) {
|
|
31501
|
+
const promise2 = browserPageContext(url2).then((context) => {
|
|
31502
|
+
if (this.#isEnabled() && browserPageUrl() === url2) {
|
|
31503
|
+
this.#snapshot = { url: url2, context };
|
|
31504
|
+
}
|
|
31505
|
+
}).finally(() => {
|
|
31506
|
+
if (this.#load?.promise === promise2) this.#load = void 0;
|
|
31507
|
+
});
|
|
31508
|
+
load = { url: url2, promise: promise2 };
|
|
31509
|
+
this.#load = load;
|
|
31510
|
+
}
|
|
31511
|
+
await load.promise;
|
|
31512
|
+
if (browserPageUrl() === url2) return;
|
|
31513
|
+
}
|
|
31514
|
+
}
|
|
31515
|
+
};
|
|
31516
|
+
|
|
31368
31517
|
// src/element-scroll-controller.ts
|
|
31369
31518
|
var AssistantElementScrollController = class {
|
|
31370
31519
|
#region;
|
|
@@ -32105,6 +32254,9 @@ var NoodleAssistantElement = class extends HTMLElementBase {
|
|
|
32105
32254
|
#context;
|
|
32106
32255
|
#modelContext;
|
|
32107
32256
|
#pageContext;
|
|
32257
|
+
#automaticPageContext = new AssistantElementPageContextController(
|
|
32258
|
+
() => !this.#pageContext
|
|
32259
|
+
);
|
|
32108
32260
|
#pendingUserEcho;
|
|
32109
32261
|
#sessionState = "idle";
|
|
32110
32262
|
#startOpenApplied = false;
|
|
@@ -32183,10 +32335,10 @@ var NoodleAssistantElement = class extends HTMLElementBase {
|
|
|
32183
32335
|
if (this.hasAttribute("start-open")) {
|
|
32184
32336
|
this.setAttribute("open", "");
|
|
32185
32337
|
this.#startOpenApplied = true;
|
|
32186
|
-
this.#primeSession();
|
|
32187
32338
|
} else if (!this.embedId) {
|
|
32188
32339
|
this.#primeSession();
|
|
32189
32340
|
}
|
|
32341
|
+
this.#syncOpenState();
|
|
32190
32342
|
}
|
|
32191
32343
|
disconnectedCallback() {
|
|
32192
32344
|
this.#conversationGeneration += 1;
|
|
@@ -32208,7 +32360,6 @@ var NoodleAssistantElement = class extends HTMLElementBase {
|
|
|
32208
32360
|
}
|
|
32209
32361
|
open() {
|
|
32210
32362
|
this.setAttribute("open", "");
|
|
32211
|
-
this.#primeSession();
|
|
32212
32363
|
this.dispatchEvent(new CustomEvent("assistant-open"));
|
|
32213
32364
|
}
|
|
32214
32365
|
close() {
|
|
@@ -32302,6 +32453,8 @@ var NoodleAssistantElement = class extends HTMLElementBase {
|
|
|
32302
32453
|
try {
|
|
32303
32454
|
await this.#sessionBootstrap;
|
|
32304
32455
|
if (generation !== this.#conversationGeneration) return;
|
|
32456
|
+
if (this.embedId && !this.#pageContext) await this.#automaticPageContext.refresh();
|
|
32457
|
+
if (generation !== this.#conversationGeneration) return;
|
|
32305
32458
|
await this.#ensureClient().sendMessage(message);
|
|
32306
32459
|
} catch (error51) {
|
|
32307
32460
|
if (generation !== this.#conversationGeneration) return;
|
|
@@ -32359,7 +32512,7 @@ var NoodleAssistantElement = class extends HTMLElementBase {
|
|
|
32359
32512
|
const behavior = {
|
|
32360
32513
|
...this.#context ? { context: this.#context } : {},
|
|
32361
32514
|
clientContext: browserClientContext,
|
|
32362
|
-
...this.#pageContext ? { pageContext: this.#pageContext } : {},
|
|
32515
|
+
...this.#pageContext ? { pageContext: this.#pageContext } : this.embedId ? { pageContext: () => this.#automaticPageContext.current() } : {},
|
|
32363
32516
|
...this.#modelContext ? { modelContext: this.#modelContext } : {}
|
|
32364
32517
|
};
|
|
32365
32518
|
const client = this.embedId ? createAssistantClient({
|
|
@@ -32377,6 +32530,7 @@ var NoodleAssistantElement = class extends HTMLElementBase {
|
|
|
32377
32530
|
#primeSession() {
|
|
32378
32531
|
if (!this.sessionEndpoint && !this.embedId) return;
|
|
32379
32532
|
if (this.#sessionBootstrap || this.#client?.hasSession()) return;
|
|
32533
|
+
if (this.embedId && !this.#pageContext) void this.#automaticPageContext.refresh();
|
|
32380
32534
|
const client = this.#ensureClient();
|
|
32381
32535
|
const generation = this.#conversationGeneration;
|
|
32382
32536
|
this.#setSessionState("loading");
|
|
@@ -32560,7 +32714,9 @@ var NoodleAssistantElement = class extends HTMLElementBase {
|
|
|
32560
32714
|
syncAssistantSessionVisualState(this, this.shadowRoot, state, this.#appearance);
|
|
32561
32715
|
}
|
|
32562
32716
|
#syncOpenState() {
|
|
32563
|
-
|
|
32717
|
+
const open = this.hasAttribute("open");
|
|
32718
|
+
this.shadowRoot?.querySelector(".launcher")?.setAttribute("aria-expanded", String(open));
|
|
32719
|
+
if (open && this.isConnected) this.#primeSession();
|
|
32564
32720
|
}
|
|
32565
32721
|
#closeAndRestoreFocus() {
|
|
32566
32722
|
this.close();
|