@noodleseed/assistant 1.28.0 → 1.30.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/dist/{app-view-element-mXHvcAXc.d.ts → app-view-element-kR8eqhyD.d.cts} +1 -1
- package/dist/{app-view-element-BjRkwNN1.d.cts → app-view-element-nY1svwHT.d.ts} +1 -1
- package/dist/app-view.d.cts +3 -3
- package/dist/app-view.d.ts +3 -3
- package/dist/{chunk-WJV4MJUR.js → chunk-5EVZFPTD.js} +120 -10
- package/dist/chunk-5EVZFPTD.js.map +1 -0
- package/dist/{chunk-QH7PL3GU.js → chunk-T4PS6P2W.js} +259 -54
- package/dist/chunk-T4PS6P2W.js.map +1 -0
- package/dist/{client-CPFw8tfo.d.ts → client-contract-Bw9dtrhw.d.cts} +26 -35
- package/dist/{client-_xivfs4q.d.cts → client-contract-DjU9qsoP.d.ts} +26 -35
- package/dist/client.cjs +122 -9
- package/dist/client.cjs.map +1 -1
- package/dist/client.d.cts +12 -2
- package/dist/client.d.ts +12 -2
- package/dist/client.js +1 -1
- package/dist/embed.global.js +46 -46
- package/dist/index.cjs +376 -61
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +3 -3
- package/dist/index.d.ts +3 -3
- package/dist/index.js +2 -2
- package/dist/react/client.cjs +122 -9
- package/dist/react/client.cjs.map +1 -1
- package/dist/react/client.d.cts +2 -2
- package/dist/react/client.d.ts +2 -2
- package/dist/react/client.js +1 -1
- package/dist/react.cjs +376 -61
- package/dist/react.cjs.map +1 -1
- package/dist/react.d.cts +3 -3
- package/dist/react.d.ts +3 -3
- package/dist/react.js +2 -2
- package/dist/server-CMqlAnxs.d.cts +270 -0
- package/dist/server-CMqlAnxs.d.ts +270 -0
- package/dist/server.cjs.map +1 -1
- package/dist/server.d.cts +1 -121
- package/dist/server.d.ts +1 -121
- package/dist/server.js.map +1 -1
- package/package.json +1 -1
- package/dist/appearance-BpVu3lpk.d.cts +0 -146
- package/dist/appearance-BpVu3lpk.d.ts +0 -146
- package/dist/chunk-QH7PL3GU.js.map +0 -1
- package/dist/chunk-WJV4MJUR.js.map +0 -1
package/dist/react.cjs
CHANGED
|
@@ -22485,11 +22485,8 @@ var DEFAULT_APPEARANCE = {
|
|
|
22485
22485
|
composer: { leadingIcon: "none", sendIcon: "arrow-up", shape: "pill" },
|
|
22486
22486
|
messages: { userStyle: "bubble", assistantStyle: "plain" }
|
|
22487
22487
|
},
|
|
22488
|
-
suggestedPrompts: [
|
|
22489
|
-
|
|
22490
|
-
"Tell me about your business",
|
|
22491
|
-
"How can I get in touch?"
|
|
22492
|
-
],
|
|
22488
|
+
suggestedPrompts: [],
|
|
22489
|
+
suggestedPromptsSource: "model",
|
|
22493
22490
|
locale: "en",
|
|
22494
22491
|
direction: "auto"
|
|
22495
22492
|
};
|
|
@@ -22522,11 +22519,8 @@ function resolveAppearance(input = {}) {
|
|
|
22522
22519
|
...assistant?.labels
|
|
22523
22520
|
},
|
|
22524
22521
|
presentation: resolvePresentation(assistant?.presentation),
|
|
22525
|
-
suggestedPrompts: assistant?.suggestedPrompts ??
|
|
22526
|
-
|
|
22527
|
-
`Tell me about ${branding.name}`,
|
|
22528
|
-
"How can I get in touch?"
|
|
22529
|
-
] : DEFAULT_APPEARANCE.suggestedPrompts),
|
|
22522
|
+
suggestedPrompts: assistant?.suggestedPrompts ?? [],
|
|
22523
|
+
suggestedPromptsSource: assistant?.suggestedPrompts === void 0 ? "model" : "configured",
|
|
22530
22524
|
...assistant?.privacyUrl ? { privacyUrl: assistant.privacyUrl } : {},
|
|
22531
22525
|
...assistant?.termsUrl ? { termsUrl: assistant.termsUrl } : {},
|
|
22532
22526
|
locale: assistant?.locale ?? DEFAULT_APPEARANCE.locale,
|
|
@@ -27075,6 +27069,7 @@ var AssistantChatStateStore = class {
|
|
|
27075
27069
|
#messages = [];
|
|
27076
27070
|
#status = "ready";
|
|
27077
27071
|
#error;
|
|
27072
|
+
#suggestions;
|
|
27078
27073
|
#operation;
|
|
27079
27074
|
#nextId = 0;
|
|
27080
27075
|
subscribe(listener) {
|
|
@@ -27086,20 +27081,24 @@ var AssistantChatStateStore = class {
|
|
|
27086
27081
|
return structuredClone({
|
|
27087
27082
|
status: this.#status,
|
|
27088
27083
|
messages: this.#messages,
|
|
27084
|
+
...this.#suggestions ? { suggestions: this.#suggestions } : {},
|
|
27089
27085
|
...this.#error ? { error: this.#error } : {}
|
|
27090
27086
|
});
|
|
27091
27087
|
}
|
|
27092
27088
|
handle(event) {
|
|
27093
27089
|
switch (event.event) {
|
|
27094
27090
|
case "message_started":
|
|
27091
|
+
this.#suggestions = void 0;
|
|
27095
27092
|
this.#beginMessage(event.data.message);
|
|
27096
27093
|
return;
|
|
27097
27094
|
case "interaction_started":
|
|
27095
|
+
this.#suggestions = void 0;
|
|
27098
27096
|
this.#beginInteraction(event.data.id);
|
|
27099
27097
|
return;
|
|
27100
27098
|
case "resume_started":
|
|
27101
27099
|
this.#status = "submitted";
|
|
27102
27100
|
this.#error = void 0;
|
|
27101
|
+
this.#suggestions = void 0;
|
|
27103
27102
|
this.#startOperation();
|
|
27104
27103
|
this.#notify();
|
|
27105
27104
|
return;
|
|
@@ -27132,6 +27131,13 @@ var AssistantChatStateStore = class {
|
|
|
27132
27131
|
case "view_available":
|
|
27133
27132
|
this.#writeData("view", event.data.id, event.data);
|
|
27134
27133
|
return;
|
|
27134
|
+
case "suggested_prompts":
|
|
27135
|
+
this.#suggestions = {
|
|
27136
|
+
phase: event.data.phase,
|
|
27137
|
+
prompts: [...event.data.prompts]
|
|
27138
|
+
};
|
|
27139
|
+
this.#notify();
|
|
27140
|
+
return;
|
|
27135
27141
|
case "message_completed":
|
|
27136
27142
|
this.#closeOperation("ready");
|
|
27137
27143
|
return;
|
|
@@ -27172,6 +27178,7 @@ var AssistantChatStateStore = class {
|
|
|
27172
27178
|
this.#messages = [...this.#messages, userMessage];
|
|
27173
27179
|
this.#status = "submitted";
|
|
27174
27180
|
this.#error = void 0;
|
|
27181
|
+
this.#suggestions = void 0;
|
|
27175
27182
|
this.#startOperation();
|
|
27176
27183
|
this.#notify();
|
|
27177
27184
|
}
|
|
@@ -27501,7 +27508,8 @@ var assistantUiSchema = external_exports.object({
|
|
|
27501
27508
|
privacyUrl: httpsUrlSchema.optional(),
|
|
27502
27509
|
termsUrl: httpsUrlSchema.optional(),
|
|
27503
27510
|
locale: external_exports.string().trim().min(2).max(35).optional(),
|
|
27504
|
-
direction: external_exports.enum(["ltr", "rtl", "auto"]).optional()
|
|
27511
|
+
direction: external_exports.enum(["ltr", "rtl", "auto"]).optional(),
|
|
27512
|
+
webmcp: external_exports.object({ enabled: external_exports.boolean().optional() }).strict().optional()
|
|
27505
27513
|
}).strict();
|
|
27506
27514
|
var assistantConfigurationSchema = external_exports.object({ branding: brandingSchema.optional(), assistant: assistantUiSchema.optional() }).strict();
|
|
27507
27515
|
function parseAssistantConfiguration(value) {
|
|
@@ -27563,7 +27571,8 @@ function parseSession(value) {
|
|
|
27563
27571
|
const apps = value.endpoints.apps;
|
|
27564
27572
|
const sandbox = value.endpoints.sandbox;
|
|
27565
27573
|
const transcript = value.endpoints.transcript;
|
|
27566
|
-
|
|
27574
|
+
const suggestions = value.endpoints.suggestions;
|
|
27575
|
+
if (typeof value.token !== "string" || typeof value.expiresAt !== "string" || typeof value.endpoints.turns !== "string" || typeof value.endpoints.toolConfirmations !== "string" || interactions !== void 0 && typeof interactions !== "string" || apps !== void 0 && typeof apps !== "string" || sandbox !== void 0 && typeof sandbox !== "string" || transcript !== void 0 && typeof transcript !== "string" || suggestions !== void 0 && typeof suggestions !== "string") {
|
|
27567
27576
|
throw clientError("session_failed", "Assistant session response is invalid", true);
|
|
27568
27577
|
}
|
|
27569
27578
|
const configuration = parseAssistantConfiguration(value.configuration);
|
|
@@ -27576,7 +27585,8 @@ function parseSession(value) {
|
|
|
27576
27585
|
...typeof interactions === "string" ? { interactions } : {},
|
|
27577
27586
|
...typeof apps === "string" ? { apps } : {},
|
|
27578
27587
|
...typeof sandbox === "string" ? { sandbox } : {},
|
|
27579
|
-
...typeof transcript === "string" ? { transcript } : {}
|
|
27588
|
+
...typeof transcript === "string" ? { transcript } : {},
|
|
27589
|
+
...typeof suggestions === "string" ? { suggestions } : {}
|
|
27580
27590
|
},
|
|
27581
27591
|
...configuration === void 0 ? {} : { configuration },
|
|
27582
27592
|
...isRecord2(value.resume) && typeof value.resume.tool === "string" ? { resume: { tool: value.resume.tool } } : {}
|
|
@@ -27660,6 +27670,10 @@ function toAssistantClientEvent(event) {
|
|
|
27660
27670
|
return event;
|
|
27661
27671
|
}
|
|
27662
27672
|
break;
|
|
27673
|
+
case "suggested_prompts":
|
|
27674
|
+
if (isSuggestedPromptsDetail(value))
|
|
27675
|
+
return event;
|
|
27676
|
+
break;
|
|
27663
27677
|
case "done":
|
|
27664
27678
|
if (hasOptionalTurnId(value)) return event;
|
|
27665
27679
|
break;
|
|
@@ -27671,6 +27685,12 @@ function toAssistantClientEvent(event) {
|
|
|
27671
27685
|
}
|
|
27672
27686
|
return { event: "unrecognized", data: { name: event.event, payload: value } };
|
|
27673
27687
|
}
|
|
27688
|
+
function isSuggestedPromptsDetail(value) {
|
|
27689
|
+
if (!isRecord3(value)) return false;
|
|
27690
|
+
return (value.phase === "initial" || value.phase === "follow_up") && Array.isArray(value.prompts) && value.prompts.length <= 3 && value.prompts.every(
|
|
27691
|
+
(prompt) => typeof prompt === "string" && prompt.trim().length > 0 && prompt.length <= 240
|
|
27692
|
+
) && hasOptionalTurnId(value);
|
|
27693
|
+
}
|
|
27674
27694
|
function isViewAvailableDetail(value) {
|
|
27675
27695
|
return hasString(value, "id") && hasString(value, "tool") && typeof value.resourceUri === "string" && value.resourceUri.startsWith("ui://") && hasOptionalString(value.title) && (value.replayed === void 0 || value.replayed === true) && isJsonValue(value.result, 0) && hasOptionalJson(value.arguments) && hasOptionalString(value.html) && (value.resourceMeta === void 0 || isRecord3(value.resourceMeta)) && (value.allowedOpenDomains === void 0 || Array.isArray(value.allowedOpenDomains) && value.allowedOpenDomains.every(isHttpsUrl2)) && hasOptionalTurnId(value);
|
|
27676
27696
|
}
|
|
@@ -27749,6 +27769,11 @@ function parseTranscriptEntries(value) {
|
|
|
27749
27769
|
}
|
|
27750
27770
|
return parsed;
|
|
27751
27771
|
}
|
|
27772
|
+
function parseTranscriptSuggestions(value) {
|
|
27773
|
+
if (typeof value !== "object" || value === null) return void 0;
|
|
27774
|
+
const suggestions = value.suggestions;
|
|
27775
|
+
return isSuggestedPromptsDetail(suggestions) && suggestions.phase === "follow_up" ? { phase: suggestions.phase, prompts: suggestions.prompts } : void 0;
|
|
27776
|
+
}
|
|
27752
27777
|
function transcriptReplayEvents(entries2) {
|
|
27753
27778
|
const events = [];
|
|
27754
27779
|
let open = false;
|
|
@@ -27899,6 +27924,32 @@ function isAbortError2(error51) {
|
|
|
27899
27924
|
return error51 instanceof DOMException && error51.name === "AbortError";
|
|
27900
27925
|
}
|
|
27901
27926
|
|
|
27927
|
+
// src/visitor-id.ts
|
|
27928
|
+
var STORAGE_PREFIX = "noodleseed.assistant.visitor.";
|
|
27929
|
+
function randomVisitorId() {
|
|
27930
|
+
try {
|
|
27931
|
+
return globalThis.crypto.randomUUID();
|
|
27932
|
+
} catch {
|
|
27933
|
+
return void 0;
|
|
27934
|
+
}
|
|
27935
|
+
}
|
|
27936
|
+
function visitorIdForSource(sourceKey) {
|
|
27937
|
+
const key = `${STORAGE_PREFIX}${sourceKey}`;
|
|
27938
|
+
try {
|
|
27939
|
+
const stored = globalThis.localStorage?.getItem(key);
|
|
27940
|
+
if (typeof stored === "string" && stored.length > 0) return stored;
|
|
27941
|
+
} catch {
|
|
27942
|
+
return void 0;
|
|
27943
|
+
}
|
|
27944
|
+
const created = randomVisitorId();
|
|
27945
|
+
if (created === void 0) return void 0;
|
|
27946
|
+
try {
|
|
27947
|
+
globalThis.localStorage?.setItem(key, created);
|
|
27948
|
+
} catch {
|
|
27949
|
+
}
|
|
27950
|
+
return created;
|
|
27951
|
+
}
|
|
27952
|
+
|
|
27902
27953
|
// src/client.ts
|
|
27903
27954
|
var DefaultAssistantClient = class {
|
|
27904
27955
|
#source;
|
|
@@ -27911,6 +27962,7 @@ var DefaultAssistantClient = class {
|
|
|
27911
27962
|
#context;
|
|
27912
27963
|
#modelContext;
|
|
27913
27964
|
#active;
|
|
27965
|
+
#initialSuggestions;
|
|
27914
27966
|
#pendingAppInteractions = /* @__PURE__ */ new Map();
|
|
27915
27967
|
constructor(options) {
|
|
27916
27968
|
this.#source = resolveSessionSource(options);
|
|
@@ -27972,10 +28024,13 @@ var DefaultAssistantClient = class {
|
|
|
27972
28024
|
"turn_failed"
|
|
27973
28025
|
);
|
|
27974
28026
|
if (!response.ok) return;
|
|
27975
|
-
|
|
28027
|
+
const value = await response.json();
|
|
28028
|
+
for (const event of transcriptReplayEvents(parseTranscriptEntries(value))) {
|
|
27976
28029
|
this.#emit(event);
|
|
27977
28030
|
if (event.event === "message_completed") await this.#chat.flush();
|
|
27978
28031
|
}
|
|
28032
|
+
const suggestions = parseTranscriptSuggestions(value);
|
|
28033
|
+
if (suggestions) this.#emit({ event: "suggested_prompts", data: suggestions });
|
|
27979
28034
|
}
|
|
27980
28035
|
/** POST the one-shot resume trigger; a 409 means nothing was pending, which renders as silence. */
|
|
27981
28036
|
async #resumeTurn(session, signal) {
|
|
@@ -27984,7 +28039,10 @@ var DefaultAssistantClient = class {
|
|
|
27984
28039
|
{
|
|
27985
28040
|
method: "POST",
|
|
27986
28041
|
headers: authorizedHeaders(session.token, "text/event-stream"),
|
|
27987
|
-
body: JSON.stringify({
|
|
28042
|
+
body: JSON.stringify({
|
|
28043
|
+
resume: true,
|
|
28044
|
+
...session.endpoints.suggestions ? { suggestions: true } : {}
|
|
28045
|
+
}),
|
|
27988
28046
|
signal
|
|
27989
28047
|
},
|
|
27990
28048
|
"turn_failed"
|
|
@@ -28007,6 +28065,7 @@ var DefaultAssistantClient = class {
|
|
|
28007
28065
|
async sendMessage(text3) {
|
|
28008
28066
|
const message = text3.trim();
|
|
28009
28067
|
if (!message) return;
|
|
28068
|
+
this.#cancelInitialSuggestions();
|
|
28010
28069
|
await this.#singleFlight(async (signal) => {
|
|
28011
28070
|
await this.#runChatOperation(
|
|
28012
28071
|
signal,
|
|
@@ -28014,10 +28073,42 @@ var DefaultAssistantClient = class {
|
|
|
28014
28073
|
);
|
|
28015
28074
|
});
|
|
28016
28075
|
}
|
|
28076
|
+
async loadInitialSuggestions() {
|
|
28077
|
+
if (!this.#session) await this.connect();
|
|
28078
|
+
const session = this.#session;
|
|
28079
|
+
if (!session?.endpoints.suggestions) return;
|
|
28080
|
+
if (this.#initialSuggestions) return this.#initialSuggestions.promise;
|
|
28081
|
+
const controller = new AbortController();
|
|
28082
|
+
const clientContext = this.#resolveClientContext();
|
|
28083
|
+
const pageContext = this.#resolvePageContext();
|
|
28084
|
+
const promise2 = this.#request(
|
|
28085
|
+
session.endpoints.suggestions,
|
|
28086
|
+
{
|
|
28087
|
+
method: "POST",
|
|
28088
|
+
headers: authorizedHeaders(session.token, "text/event-stream"),
|
|
28089
|
+
body: JSON.stringify({
|
|
28090
|
+
...clientContext ? { clientContext } : {},
|
|
28091
|
+
...pageContext === void 0 ? {} : { pageContext },
|
|
28092
|
+
...this.#modelContext ? { modelContext: this.#modelContext } : {}
|
|
28093
|
+
}),
|
|
28094
|
+
signal: controller.signal
|
|
28095
|
+
},
|
|
28096
|
+
"turn_failed"
|
|
28097
|
+
).then(async (response) => {
|
|
28098
|
+
if (response.ok) await this.#consume(response);
|
|
28099
|
+
}).finally(() => {
|
|
28100
|
+
if (this.#initialSuggestions?.controller === controller) {
|
|
28101
|
+
this.#initialSuggestions = void 0;
|
|
28102
|
+
}
|
|
28103
|
+
});
|
|
28104
|
+
this.#initialSuggestions = { controller, promise: promise2 };
|
|
28105
|
+
return promise2;
|
|
28106
|
+
}
|
|
28017
28107
|
async respond(id, resolution) {
|
|
28018
28108
|
if (!id) {
|
|
28019
28109
|
throw clientError("invalid_request", "interaction id is required", false);
|
|
28020
28110
|
}
|
|
28111
|
+
this.#cancelInitialSuggestions();
|
|
28021
28112
|
await this.#singleFlight(async (signal) => {
|
|
28022
28113
|
await this.#runChatOperation(signal, async () => {
|
|
28023
28114
|
const pendingApp = this.#pendingAppInteractions.get(id);
|
|
@@ -28037,6 +28128,7 @@ var DefaultAssistantClient = class {
|
|
|
28037
28128
|
const body = modernEndpoint ? {
|
|
28038
28129
|
id,
|
|
28039
28130
|
action: resolution.action,
|
|
28131
|
+
...session.endpoints.suggestions ? { suggestions: true } : {},
|
|
28040
28132
|
...resolution.action === "accept" && resolution.content !== void 0 ? { content: resolution.content } : {}
|
|
28041
28133
|
} : { id };
|
|
28042
28134
|
this.#emit({ event: "interaction_started", data: { id, action: resolution.action } });
|
|
@@ -28115,7 +28207,7 @@ var DefaultAssistantClient = class {
|
|
|
28115
28207
|
this.#modelContext = copyAssistantModelContext(update);
|
|
28116
28208
|
this.#emit({ event: "model_context_changed", data: { modelContext: this.#modelContext } });
|
|
28117
28209
|
}
|
|
28118
|
-
async requestApp(method, params) {
|
|
28210
|
+
async requestApp(method, params, options) {
|
|
28119
28211
|
const session = this.#session;
|
|
28120
28212
|
if (!session?.endpoints.apps) {
|
|
28121
28213
|
throw clientError(
|
|
@@ -28129,7 +28221,11 @@ var DefaultAssistantClient = class {
|
|
|
28129
28221
|
{
|
|
28130
28222
|
method: "POST",
|
|
28131
28223
|
headers: authorizedHeaders(session.token, "application/json"),
|
|
28132
|
-
body: JSON.stringify({
|
|
28224
|
+
body: JSON.stringify({
|
|
28225
|
+
...options?.bridge ? { bridge: options.bridge } : {},
|
|
28226
|
+
method,
|
|
28227
|
+
params
|
|
28228
|
+
})
|
|
28133
28229
|
},
|
|
28134
28230
|
"app_request_failed"
|
|
28135
28231
|
);
|
|
@@ -28144,6 +28240,7 @@ var DefaultAssistantClient = class {
|
|
|
28144
28240
|
const value = await response.json();
|
|
28145
28241
|
const interaction = parseAppInteraction(value);
|
|
28146
28242
|
if (!interaction) return value;
|
|
28243
|
+
options?.onSuspended?.();
|
|
28147
28244
|
return new Promise((resolve2, reject) => {
|
|
28148
28245
|
const id = interaction.data.id;
|
|
28149
28246
|
const replaced = this.#pendingAppInteractions.get(id);
|
|
@@ -28161,6 +28258,7 @@ var DefaultAssistantClient = class {
|
|
|
28161
28258
|
return this.#session?.endpoints.sandbox;
|
|
28162
28259
|
}
|
|
28163
28260
|
resetSession() {
|
|
28261
|
+
this.#cancelInitialSuggestions();
|
|
28164
28262
|
this.#rejectPendingAppInteractions(
|
|
28165
28263
|
clientError("confirmation_expired", "assistant session is not active", false)
|
|
28166
28264
|
);
|
|
@@ -28169,6 +28267,7 @@ var DefaultAssistantClient = class {
|
|
|
28169
28267
|
}
|
|
28170
28268
|
abort() {
|
|
28171
28269
|
this.#active?.abort();
|
|
28270
|
+
this.#cancelInitialSuggestions();
|
|
28172
28271
|
}
|
|
28173
28272
|
async #sendTurn(message, mayRetry, signal, modelContext) {
|
|
28174
28273
|
const session = this.#session ?? await this.#createSession(signal);
|
|
@@ -28184,7 +28283,8 @@ var DefaultAssistantClient = class {
|
|
|
28184
28283
|
message,
|
|
28185
28284
|
...clientContext ? { clientContext } : {},
|
|
28186
28285
|
...pageContext === void 0 ? {} : { pageContext },
|
|
28187
|
-
...modelContext ? { modelContext } : {}
|
|
28286
|
+
...modelContext ? { modelContext } : {},
|
|
28287
|
+
...session.endpoints.suggestions ? { suggestions: true } : {}
|
|
28188
28288
|
}),
|
|
28189
28289
|
signal
|
|
28190
28290
|
},
|
|
@@ -28244,11 +28344,12 @@ var DefaultAssistantClient = class {
|
|
|
28244
28344
|
}
|
|
28245
28345
|
async #createSession(signal) {
|
|
28246
28346
|
const source = this.#source;
|
|
28347
|
+
const visitorId = source.kind === "public" ? visitorIdForSource(sessionSourceKey({ embedId: source.embedId, serviceUrl: source.url })) : void 0;
|
|
28247
28348
|
const response = await this.#requestSession(source, {
|
|
28248
28349
|
method: "POST",
|
|
28249
28350
|
headers: { Accept: "application/json", "Content-Type": "application/json" },
|
|
28250
28351
|
body: JSON.stringify(
|
|
28251
|
-
source.kind === "public" ? { embedId: source.embedId } : this.#context ? { context: this.#context } : {}
|
|
28352
|
+
source.kind === "public" ? { embedId: source.embedId, ...visitorId ? { visitorId } : {} } : this.#context ? { context: this.#context } : {}
|
|
28252
28353
|
),
|
|
28253
28354
|
credentials: source.kind === "public" ? "omit" : "same-origin",
|
|
28254
28355
|
signal
|
|
@@ -28373,6 +28474,9 @@ var DefaultAssistantClient = class {
|
|
|
28373
28474
|
this.#active = void 0;
|
|
28374
28475
|
}
|
|
28375
28476
|
}
|
|
28477
|
+
#cancelInitialSuggestions() {
|
|
28478
|
+
this.#initialSuggestions?.controller.abort();
|
|
28479
|
+
}
|
|
28376
28480
|
async #runChatOperation(signal, operation) {
|
|
28377
28481
|
try {
|
|
28378
28482
|
await operation();
|
|
@@ -28453,6 +28557,22 @@ function appendConversationRecovery(input) {
|
|
|
28453
28557
|
input.revealLatest();
|
|
28454
28558
|
}
|
|
28455
28559
|
|
|
28560
|
+
// src/element-error-recovery.ts
|
|
28561
|
+
function renderConversationError(options) {
|
|
28562
|
+
const { appearance, error: error51 } = options;
|
|
28563
|
+
const detail = error51 instanceof AssistantClientError ? error51.detail : { code: options.fallbackCode, retryable: false };
|
|
28564
|
+
const startNewConversation = detail.serviceCode === "session_turn_budget_exhausted";
|
|
28565
|
+
const reconnect = detail.retryable !== false || detail.serviceCode === void 0;
|
|
28566
|
+
const recoveryAction = startNewConversation ? { label: appearance.labels.newConversation, run: () => options.startNewConversation() } : reconnect ? { label: appearance.labels.reconnect, run: () => options.reconnect() } : void 0;
|
|
28567
|
+
appendConversationRecovery({
|
|
28568
|
+
messages: options.messages,
|
|
28569
|
+
message: detail.code === "session_expired" ? appearance.labels.sessionExpired : appearance.labels.unavailable,
|
|
28570
|
+
...recoveryAction === void 0 ? {} : { action: recoveryAction },
|
|
28571
|
+
revealLatest: () => options.revealLatest()
|
|
28572
|
+
});
|
|
28573
|
+
return detail;
|
|
28574
|
+
}
|
|
28575
|
+
|
|
28456
28576
|
// src/input-request-card.ts
|
|
28457
28577
|
function createInputRequestCard(options) {
|
|
28458
28578
|
const card = document.createElement("section");
|
|
@@ -32626,6 +32746,59 @@ var ASSISTANT_ELEMENT_STYLES = `<style>
|
|
|
32626
32746
|
@media (max-width: 560px) { :host([data-mode="floating"]:not([open])) { bottom: 20px; } :host([open]:not([mobile-fullscreen])) .panel { width: calc(100vw - 40px); max-height: calc(100dvh - 40px); } }
|
|
32627
32747
|
</style>`;
|
|
32628
32748
|
|
|
32749
|
+
// src/element-suggestions-controller.ts
|
|
32750
|
+
var AssistantElementSuggestionsController = class {
|
|
32751
|
+
#host;
|
|
32752
|
+
#initialRequested = false;
|
|
32753
|
+
#dynamic;
|
|
32754
|
+
constructor(host) {
|
|
32755
|
+
this.#host = host;
|
|
32756
|
+
}
|
|
32757
|
+
reset() {
|
|
32758
|
+
this.#initialRequested = false;
|
|
32759
|
+
this.clear();
|
|
32760
|
+
}
|
|
32761
|
+
clear() {
|
|
32762
|
+
this.#dynamic = void 0;
|
|
32763
|
+
this.render();
|
|
32764
|
+
}
|
|
32765
|
+
handle(event) {
|
|
32766
|
+
if (event.event === "message_started" || event.event === "interaction_started") {
|
|
32767
|
+
this.clear();
|
|
32768
|
+
return;
|
|
32769
|
+
}
|
|
32770
|
+
if (event.event !== "suggested_prompts") return;
|
|
32771
|
+
this.#dynamic = event.data;
|
|
32772
|
+
this.render();
|
|
32773
|
+
}
|
|
32774
|
+
maybeLoadInitial() {
|
|
32775
|
+
const appearance = this.#host.appearance();
|
|
32776
|
+
if (this.#initialRequested || appearance.suggestedPromptsSource !== "model" || this.#host.hasMessages() || !this.#host.isOpen()) {
|
|
32777
|
+
return;
|
|
32778
|
+
}
|
|
32779
|
+
const client = this.#host.client();
|
|
32780
|
+
if (!client?.loadInitialSuggestions) return;
|
|
32781
|
+
this.#initialRequested = true;
|
|
32782
|
+
void client.loadInitialSuggestions().catch(() => {
|
|
32783
|
+
});
|
|
32784
|
+
}
|
|
32785
|
+
render() {
|
|
32786
|
+
const container = this.#host.root()?.querySelector(".suggested-prompts");
|
|
32787
|
+
if (!container) return;
|
|
32788
|
+
const appearance = this.#host.appearance();
|
|
32789
|
+
const hasMessages = this.#host.hasMessages();
|
|
32790
|
+
const prompts = (this.#dynamic?.phase === "follow_up" || !hasMessages ? this.#dynamic?.prompts : void 0) ?? (!hasMessages && appearance.suggestedPromptsSource === "configured" ? appearance.suggestedPrompts : []);
|
|
32791
|
+
container.replaceChildren();
|
|
32792
|
+
for (const prompt of prompts) {
|
|
32793
|
+
const button2 = document.createElement("button");
|
|
32794
|
+
button2.type = "button";
|
|
32795
|
+
button2.textContent = prompt;
|
|
32796
|
+
button2.addEventListener("click", () => this.#host.send(prompt));
|
|
32797
|
+
container.append(button2);
|
|
32798
|
+
}
|
|
32799
|
+
}
|
|
32800
|
+
};
|
|
32801
|
+
|
|
32629
32802
|
// src/host-appearance.ts
|
|
32630
32803
|
var ROLE_VARIABLES = {
|
|
32631
32804
|
canvas: "--ns-assistant-canvas",
|
|
@@ -32934,6 +33107,147 @@ function applyAssistantElementTheme(input) {
|
|
|
32934
33107
|
return warnings;
|
|
32935
33108
|
}
|
|
32936
33109
|
|
|
33110
|
+
// src/webmcp-bridge.ts
|
|
33111
|
+
var INERT = { registeredToolNames: [], stop: () => {
|
|
33112
|
+
} };
|
|
33113
|
+
async function startWebMcpBridge(ports) {
|
|
33114
|
+
const { client, modelContext, enabled } = ports;
|
|
33115
|
+
if (!enabled || !modelContext) return INERT;
|
|
33116
|
+
let listed;
|
|
33117
|
+
try {
|
|
33118
|
+
listed = await client.requestApp("tools/list", {});
|
|
33119
|
+
} catch {
|
|
33120
|
+
return INERT;
|
|
33121
|
+
}
|
|
33122
|
+
const registrations = [];
|
|
33123
|
+
for (const tool of projectableTools(listed)) {
|
|
33124
|
+
registrations.push({
|
|
33125
|
+
name: tool.name,
|
|
33126
|
+
handle: modelContext.registerTool({
|
|
33127
|
+
name: tool.name,
|
|
33128
|
+
...tool.description === void 0 ? {} : { description: tool.description },
|
|
33129
|
+
...tool.inputSchema === void 0 ? {} : { inputSchema: tool.inputSchema },
|
|
33130
|
+
// Passed through, never inferred: an agent may use `readOnlyHint` to decide it can call
|
|
33131
|
+
// without asking, so a hint this bridge invented would be a hint nobody authored.
|
|
33132
|
+
...tool.annotations === void 0 ? {} : { annotations: tool.annotations },
|
|
33133
|
+
execute: (args) => executeThroughAssistant(client, tool.name, args)
|
|
33134
|
+
})
|
|
33135
|
+
});
|
|
33136
|
+
}
|
|
33137
|
+
let stopped = false;
|
|
33138
|
+
return {
|
|
33139
|
+
get registeredToolNames() {
|
|
33140
|
+
return stopped ? [] : registrations.map((entry) => entry.name);
|
|
33141
|
+
},
|
|
33142
|
+
stop() {
|
|
33143
|
+
if (stopped) return;
|
|
33144
|
+
stopped = true;
|
|
33145
|
+
for (const entry of registrations) entry.handle?.unregister?.();
|
|
33146
|
+
}
|
|
33147
|
+
};
|
|
33148
|
+
}
|
|
33149
|
+
function projectableTools(listed) {
|
|
33150
|
+
const tools = isRecord7(listed) && Array.isArray(listed.tools) ? listed.tools : [];
|
|
33151
|
+
const projectable = [];
|
|
33152
|
+
for (const tool of tools) {
|
|
33153
|
+
if (!isRecord7(tool) || typeof tool.name !== "string" || tool.name.length === 0) continue;
|
|
33154
|
+
const visibility = readVisibility(tool);
|
|
33155
|
+
if (visibility !== void 0 && !(visibility.includes("app") && visibility.includes("model"))) {
|
|
33156
|
+
continue;
|
|
33157
|
+
}
|
|
33158
|
+
projectable.push({
|
|
33159
|
+
name: tool.name,
|
|
33160
|
+
description: typeof tool.description === "string" ? tool.description : void 0,
|
|
33161
|
+
inputSchema: isRecord7(tool.inputSchema) ? tool.inputSchema : void 0,
|
|
33162
|
+
annotations: isRecord7(tool.annotations) ? tool.annotations : void 0
|
|
33163
|
+
});
|
|
33164
|
+
}
|
|
33165
|
+
return projectable;
|
|
33166
|
+
}
|
|
33167
|
+
function readVisibility(tool) {
|
|
33168
|
+
const meta3 = isRecord7(tool._meta) ? tool._meta : void 0;
|
|
33169
|
+
const ui = meta3 && isRecord7(meta3.ui) ? meta3.ui : void 0;
|
|
33170
|
+
const visibility = ui?.visibility;
|
|
33171
|
+
return Array.isArray(visibility) ? visibility.filter((entry) => typeof entry === "string") : void 0;
|
|
33172
|
+
}
|
|
33173
|
+
async function executeThroughAssistant(client, name21, args) {
|
|
33174
|
+
let suspend;
|
|
33175
|
+
const suspended = new Promise((resolve2) => {
|
|
33176
|
+
suspend = resolve2;
|
|
33177
|
+
});
|
|
33178
|
+
try {
|
|
33179
|
+
const call = client.requestApp(
|
|
33180
|
+
"tools/call",
|
|
33181
|
+
{ name: name21, arguments: args },
|
|
33182
|
+
// Attribution only: anyone holding the session token could send this, and it selects a
|
|
33183
|
+
// *narrower* budget than the unmarked path, so declaring it can only cost the declarer.
|
|
33184
|
+
{ bridge: "webmcp", onSuspended: suspend }
|
|
33185
|
+
);
|
|
33186
|
+
void call.catch(() => {
|
|
33187
|
+
});
|
|
33188
|
+
const outcome = await Promise.race([
|
|
33189
|
+
call.then((value) => ({ kind: "result", value })),
|
|
33190
|
+
suspended.then(() => ({ kind: "confirmation" }))
|
|
33191
|
+
]);
|
|
33192
|
+
return outcome.kind === "confirmation" ? CONFIRMATION_REQUIRED : toToolResult(outcome.value);
|
|
33193
|
+
} catch (error51) {
|
|
33194
|
+
return textResult(error51 instanceof Error ? error51.message : "tool call failed", true);
|
|
33195
|
+
}
|
|
33196
|
+
}
|
|
33197
|
+
var CONFIRMATION_REQUIRED = {
|
|
33198
|
+
content: [
|
|
33199
|
+
{
|
|
33200
|
+
type: "text",
|
|
33201
|
+
text: "confirmation required: open the assistant panel on this page to approve this action"
|
|
33202
|
+
}
|
|
33203
|
+
],
|
|
33204
|
+
isError: true
|
|
33205
|
+
};
|
|
33206
|
+
function toToolResult(value) {
|
|
33207
|
+
if (isRecord7(value) && Array.isArray(value.content)) return value;
|
|
33208
|
+
return textResult(JSON.stringify(value ?? null), false);
|
|
33209
|
+
}
|
|
33210
|
+
function textResult(text3, isError) {
|
|
33211
|
+
return { content: [{ type: "text", text: text3 }], isError };
|
|
33212
|
+
}
|
|
33213
|
+
function isRecord7(value) {
|
|
33214
|
+
return typeof value === "object" && value !== null && !Array.isArray(value);
|
|
33215
|
+
}
|
|
33216
|
+
|
|
33217
|
+
// src/element-webmcp-controller.ts
|
|
33218
|
+
var AssistantElementWebMcpController = class {
|
|
33219
|
+
#enabled = false;
|
|
33220
|
+
#bridge;
|
|
33221
|
+
/** Guards against a late `startWebMcpBridge` resolving after the session it belonged to is gone. */
|
|
33222
|
+
#generation = 0;
|
|
33223
|
+
/** Called when resolved configuration arrives; the deployment's opt-in is the only source. */
|
|
33224
|
+
configure(enabled) {
|
|
33225
|
+
this.#enabled = enabled;
|
|
33226
|
+
if (!enabled) this.stop();
|
|
33227
|
+
}
|
|
33228
|
+
start(client) {
|
|
33229
|
+
if (!this.#enabled || !client) return;
|
|
33230
|
+
const modelContext = browserModelContext();
|
|
33231
|
+
if (!modelContext) return;
|
|
33232
|
+
this.stop();
|
|
33233
|
+
const generation = ++this.#generation;
|
|
33234
|
+
void startWebMcpBridge({ client, modelContext, enabled: true }).then((bridge) => {
|
|
33235
|
+
if (generation === this.#generation) this.#bridge = bridge;
|
|
33236
|
+
else bridge.stop();
|
|
33237
|
+
});
|
|
33238
|
+
}
|
|
33239
|
+
stop() {
|
|
33240
|
+
this.#generation += 1;
|
|
33241
|
+
this.#bridge?.stop();
|
|
33242
|
+
this.#bridge = void 0;
|
|
33243
|
+
}
|
|
33244
|
+
};
|
|
33245
|
+
function browserModelContext() {
|
|
33246
|
+
if (typeof document === "undefined") return void 0;
|
|
33247
|
+
const host = document;
|
|
33248
|
+
return typeof host.modelContext?.registerTool === "function" ? host.modelContext : void 0;
|
|
33249
|
+
}
|
|
33250
|
+
|
|
32937
33251
|
// src/presentation-styles.ts
|
|
32938
33252
|
var presentationStyles = `<style>
|
|
32939
33253
|
:host([data-mode="floating"]) {
|
|
@@ -33177,9 +33491,18 @@ var NoodleAssistantElement = class extends HTMLElementBase {
|
|
|
33177
33491
|
#turnInFlight = false;
|
|
33178
33492
|
#fetch;
|
|
33179
33493
|
#hostAppearance;
|
|
33494
|
+
#webmcp = new AssistantElementWebMcpController();
|
|
33180
33495
|
#appearanceWarningKeys = /* @__PURE__ */ new Set();
|
|
33181
33496
|
#appearanceStyleSnapshot = /* @__PURE__ */ new Map();
|
|
33182
33497
|
#scroll = new AssistantElementScrollController();
|
|
33498
|
+
#suggestions = new AssistantElementSuggestionsController({
|
|
33499
|
+
root: () => this.shadowRoot,
|
|
33500
|
+
appearance: () => this.#appearance,
|
|
33501
|
+
client: () => this.#client,
|
|
33502
|
+
hasMessages: () => this.hasAttribute("has-messages"),
|
|
33503
|
+
isOpen: () => this.hasAttribute("open"),
|
|
33504
|
+
send: (prompt) => this.#sendGuarded(prompt)
|
|
33505
|
+
});
|
|
33183
33506
|
sessionEndpoint = "";
|
|
33184
33507
|
/** Public mount: the non-secret embed id `noodle deploy` printed. Mutually exclusive with the above. */
|
|
33185
33508
|
embedId = "";
|
|
@@ -33291,6 +33614,7 @@ var NoodleAssistantElement = class extends HTMLElementBase {
|
|
|
33291
33614
|
this.#launcher.disconnect();
|
|
33292
33615
|
this.#setBusy(false);
|
|
33293
33616
|
this.#environment.disconnect();
|
|
33617
|
+
this.#webmcp.stop();
|
|
33294
33618
|
}
|
|
33295
33619
|
attributeChangedCallback(name21) {
|
|
33296
33620
|
if (name21 === "theme") this.#applyTheme();
|
|
@@ -33324,6 +33648,7 @@ var NoodleAssistantElement = class extends HTMLElementBase {
|
|
|
33324
33648
|
}
|
|
33325
33649
|
resetSession() {
|
|
33326
33650
|
this.#conversationGeneration += 1;
|
|
33651
|
+
this.#webmcp.stop();
|
|
33327
33652
|
this.#client?.abort();
|
|
33328
33653
|
this.#unsubscribeClient?.();
|
|
33329
33654
|
this.#client = void 0;
|
|
@@ -33333,12 +33658,14 @@ var NoodleAssistantElement = class extends HTMLElementBase {
|
|
|
33333
33658
|
this.#events.resetConversation();
|
|
33334
33659
|
this.#pendingUserEcho = void 0;
|
|
33335
33660
|
this.removeAttribute("has-messages");
|
|
33661
|
+
this.#suggestions.reset();
|
|
33336
33662
|
this.#setBusy(false);
|
|
33337
33663
|
this.#setSessionState("idle");
|
|
33338
33664
|
}
|
|
33339
33665
|
/** Re-establish the session without replaying a message or interaction decision. */
|
|
33340
33666
|
reconnect() {
|
|
33341
33667
|
this.#conversationGeneration += 1;
|
|
33668
|
+
this.#webmcp.stop();
|
|
33342
33669
|
this.#client?.abort();
|
|
33343
33670
|
this.#unsubscribeClient?.();
|
|
33344
33671
|
this.#client = void 0;
|
|
@@ -33396,6 +33723,7 @@ var NoodleAssistantElement = class extends HTMLElementBase {
|
|
|
33396
33723
|
this.#turnInFlight = true;
|
|
33397
33724
|
this.#pendingUserEcho = message;
|
|
33398
33725
|
this.#appendMessage("user", message);
|
|
33726
|
+
this.#suggestions.clear();
|
|
33399
33727
|
this.#setBusy(true);
|
|
33400
33728
|
if (this.#sessionState !== "ready") this.#setSessionState("loading");
|
|
33401
33729
|
try {
|
|
@@ -33415,12 +33743,7 @@ var NoodleAssistantElement = class extends HTMLElementBase {
|
|
|
33415
33743
|
if (generation === this.#conversationGeneration) this.#setBusy(false);
|
|
33416
33744
|
}
|
|
33417
33745
|
}
|
|
33418
|
-
/**
|
|
33419
|
-
* Every listener the element attaches to its own DOM must go through this guard: internal UI
|
|
33420
|
-
* failures surface as `assistant-error` events (already dispatched by the failing path) and must
|
|
33421
|
-
* never escape as unhandled rejections into the embedding page. Programmatic callers use
|
|
33422
|
-
* `sendMessage`/`confirmTool` directly and keep the rejection.
|
|
33423
|
-
*/
|
|
33746
|
+
/** DOM listeners swallow after the failing path dispatches its typed assistant-error event. */
|
|
33424
33747
|
#sendGuarded(text3) {
|
|
33425
33748
|
void this.sendMessage(text3).catch(() => {
|
|
33426
33749
|
});
|
|
@@ -33472,13 +33795,21 @@ var NoodleAssistantElement = class extends HTMLElementBase {
|
|
|
33472
33795
|
}
|
|
33473
33796
|
#primeSession() {
|
|
33474
33797
|
if (!this.sessionEndpoint && !this.embedId) return;
|
|
33475
|
-
if (this.#sessionBootstrap
|
|
33798
|
+
if (this.#sessionBootstrap) return;
|
|
33799
|
+
if (this.#client?.hasSession()) {
|
|
33800
|
+
this.#suggestions.maybeLoadInitial();
|
|
33801
|
+
return;
|
|
33802
|
+
}
|
|
33476
33803
|
if (this.#client?.isBusy?.() === true) return;
|
|
33477
33804
|
if (this.embedId && !this.#pageContext) void this.#automaticPageContext.refresh();
|
|
33478
33805
|
const client = this.#ensureClient();
|
|
33479
33806
|
const generation = this.#conversationGeneration;
|
|
33480
33807
|
this.#setSessionState("loading");
|
|
33481
|
-
const bootstrap = client.connect().
|
|
33808
|
+
const bootstrap = client.connect().then(() => {
|
|
33809
|
+
if (generation === this.#conversationGeneration && this.#client === client) {
|
|
33810
|
+
this.#suggestions.maybeLoadInitial();
|
|
33811
|
+
}
|
|
33812
|
+
}).catch((error51) => {
|
|
33482
33813
|
if (generation !== this.#conversationGeneration || this.#client !== client) return;
|
|
33483
33814
|
this.#dispatchClientError(error51, "session_failed");
|
|
33484
33815
|
this.#presentationGate.reveal();
|
|
@@ -33490,15 +33821,18 @@ var NoodleAssistantElement = class extends HTMLElementBase {
|
|
|
33490
33821
|
#handleClientEvent(event) {
|
|
33491
33822
|
this.dispatchEvent(new CustomEvent("assistant-event", { detail: event }));
|
|
33492
33823
|
this.#events.handle(event);
|
|
33824
|
+
this.#suggestions.handle(event);
|
|
33493
33825
|
if (event.event === "session_started") {
|
|
33494
33826
|
this.#publicConfiguration.disconnect();
|
|
33495
33827
|
this.removeAttribute("data-public-configuration-loading");
|
|
33496
33828
|
this.#presentationGate.reveal();
|
|
33497
33829
|
this.#setSessionState("ready");
|
|
33498
33830
|
this.#messages?.querySelector(".conversation-error")?.remove();
|
|
33831
|
+
this.#webmcp.start(this.#client);
|
|
33499
33832
|
}
|
|
33500
33833
|
if (event.event === "session_expired" || event.event === "session_reset") {
|
|
33501
33834
|
this.#setSessionState("idle");
|
|
33835
|
+
this.#webmcp.stop();
|
|
33502
33836
|
}
|
|
33503
33837
|
if (event.event === "tool_proposed" || event.event === "interaction_proposed" || event.event === "input_requested") {
|
|
33504
33838
|
this.#removeThinking();
|
|
@@ -33602,23 +33936,17 @@ var NoodleAssistantElement = class extends HTMLElementBase {
|
|
|
33602
33936
|
if (error51 instanceof AssistantClientError && error51.detail.code === "session_failed") {
|
|
33603
33937
|
this.#setSessionState("error");
|
|
33604
33938
|
}
|
|
33605
|
-
|
|
33606
|
-
|
|
33607
|
-
|
|
33608
|
-
|
|
33609
|
-
|
|
33610
|
-
|
|
33611
|
-
|
|
33612
|
-
|
|
33613
|
-
|
|
33614
|
-
|
|
33615
|
-
|
|
33616
|
-
// open tab trying is exactly the load the cap was set to refuse — so the button goes, not just
|
|
33617
|
-
// the alarming words. A spent *session* keeps it: reconnect mints a fresh one, which is the fix.
|
|
33618
|
-
...recoveryAction === void 0 ? {} : { action: recoveryAction },
|
|
33619
|
-
revealLatest: () => this.#revealLatest()
|
|
33620
|
-
});
|
|
33621
|
-
this.#dispatchError(detail);
|
|
33939
|
+
this.#dispatchError(
|
|
33940
|
+
renderConversationError({
|
|
33941
|
+
messages: this.#messages,
|
|
33942
|
+
appearance: this.#appearance,
|
|
33943
|
+
error: error51,
|
|
33944
|
+
fallbackCode,
|
|
33945
|
+
startNewConversation: () => this.#startNewConversation(),
|
|
33946
|
+
reconnect: () => this.reconnect(),
|
|
33947
|
+
revealLatest: () => this.#revealLatest()
|
|
33948
|
+
})
|
|
33949
|
+
);
|
|
33622
33950
|
}
|
|
33623
33951
|
#startNewConversation() {
|
|
33624
33952
|
this.resetSession();
|
|
@@ -33651,7 +33979,9 @@ var NoodleAssistantElement = class extends HTMLElementBase {
|
|
|
33651
33979
|
}
|
|
33652
33980
|
}
|
|
33653
33981
|
#applyConfiguration(configuration) {
|
|
33982
|
+
this.#webmcp.configure(configuration.assistant?.webmcp?.enabled === true);
|
|
33654
33983
|
this.#appearance = resolveAppearance(configuration);
|
|
33984
|
+
this.#suggestions.render();
|
|
33655
33985
|
this.#syncAppearance();
|
|
33656
33986
|
this.#applyStartOpenPolicy();
|
|
33657
33987
|
}
|
|
@@ -33696,15 +34026,7 @@ var NoodleAssistantElement = class extends HTMLElementBase {
|
|
|
33696
34026
|
"aria-label",
|
|
33697
34027
|
appearance.labels.close
|
|
33698
34028
|
);
|
|
33699
|
-
|
|
33700
|
-
prompts.replaceChildren();
|
|
33701
|
-
for (const prompt of appearance.suggestedPrompts) {
|
|
33702
|
-
const button2 = document.createElement("button");
|
|
33703
|
-
button2.type = "button";
|
|
33704
|
-
button2.textContent = prompt;
|
|
33705
|
-
button2.addEventListener("click", () => this.#sendGuarded(prompt));
|
|
33706
|
-
prompts.append(button2);
|
|
33707
|
-
}
|
|
34029
|
+
this.#suggestions.render();
|
|
33708
34030
|
queryRequired(this.shadowRoot, "header").hidden = !appearance.behavior.showHeader;
|
|
33709
34031
|
const legal = queryRequired(this.shadowRoot, ".legal");
|
|
33710
34032
|
legal.replaceChildren();
|
|
@@ -33742,14 +34064,7 @@ var NoodleAssistantElement = class extends HTMLElementBase {
|
|
|
33742
34064
|
textarea.placeholder = appearance.labels.composerPlaceholder;
|
|
33743
34065
|
textarea.setAttribute("aria-label", appearance.labels.composerPlaceholder);
|
|
33744
34066
|
queryRequired(this.shadowRoot, ".send").textContent = appearance.labels.send;
|
|
33745
|
-
|
|
33746
|
-
for (const prompt of appearance.suggestedPrompts) {
|
|
33747
|
-
const button2 = document.createElement("button");
|
|
33748
|
-
button2.type = "button";
|
|
33749
|
-
button2.textContent = prompt;
|
|
33750
|
-
button2.addEventListener("click", () => this.#sendGuarded(prompt));
|
|
33751
|
-
prompts.append(button2);
|
|
33752
|
-
}
|
|
34067
|
+
this.#suggestions.render();
|
|
33753
34068
|
if (!appearance.behavior.showLauncher)
|
|
33754
34069
|
queryRequired(this.shadowRoot, ".launcher").hidden = true;
|
|
33755
34070
|
if (!appearance.behavior.showHeader)
|