@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/index.cjs
CHANGED
|
@@ -22482,11 +22482,8 @@ var DEFAULT_APPEARANCE = {
|
|
|
22482
22482
|
composer: { leadingIcon: "none", sendIcon: "arrow-up", shape: "pill" },
|
|
22483
22483
|
messages: { userStyle: "bubble", assistantStyle: "plain" }
|
|
22484
22484
|
},
|
|
22485
|
-
suggestedPrompts: [
|
|
22486
|
-
|
|
22487
|
-
"Tell me about your business",
|
|
22488
|
-
"How can I get in touch?"
|
|
22489
|
-
],
|
|
22485
|
+
suggestedPrompts: [],
|
|
22486
|
+
suggestedPromptsSource: "model",
|
|
22490
22487
|
locale: "en",
|
|
22491
22488
|
direction: "auto"
|
|
22492
22489
|
};
|
|
@@ -22519,11 +22516,8 @@ function resolveAppearance(input = {}) {
|
|
|
22519
22516
|
...assistant?.labels
|
|
22520
22517
|
},
|
|
22521
22518
|
presentation: resolvePresentation(assistant?.presentation),
|
|
22522
|
-
suggestedPrompts: assistant?.suggestedPrompts ??
|
|
22523
|
-
|
|
22524
|
-
`Tell me about ${branding.name}`,
|
|
22525
|
-
"How can I get in touch?"
|
|
22526
|
-
] : DEFAULT_APPEARANCE.suggestedPrompts),
|
|
22519
|
+
suggestedPrompts: assistant?.suggestedPrompts ?? [],
|
|
22520
|
+
suggestedPromptsSource: assistant?.suggestedPrompts === void 0 ? "model" : "configured",
|
|
22527
22521
|
...assistant?.privacyUrl ? { privacyUrl: assistant.privacyUrl } : {},
|
|
22528
22522
|
...assistant?.termsUrl ? { termsUrl: assistant.termsUrl } : {},
|
|
22529
22523
|
locale: assistant?.locale ?? DEFAULT_APPEARANCE.locale,
|
|
@@ -27072,6 +27066,7 @@ var AssistantChatStateStore = class {
|
|
|
27072
27066
|
#messages = [];
|
|
27073
27067
|
#status = "ready";
|
|
27074
27068
|
#error;
|
|
27069
|
+
#suggestions;
|
|
27075
27070
|
#operation;
|
|
27076
27071
|
#nextId = 0;
|
|
27077
27072
|
subscribe(listener) {
|
|
@@ -27083,20 +27078,24 @@ var AssistantChatStateStore = class {
|
|
|
27083
27078
|
return structuredClone({
|
|
27084
27079
|
status: this.#status,
|
|
27085
27080
|
messages: this.#messages,
|
|
27081
|
+
...this.#suggestions ? { suggestions: this.#suggestions } : {},
|
|
27086
27082
|
...this.#error ? { error: this.#error } : {}
|
|
27087
27083
|
});
|
|
27088
27084
|
}
|
|
27089
27085
|
handle(event) {
|
|
27090
27086
|
switch (event.event) {
|
|
27091
27087
|
case "message_started":
|
|
27088
|
+
this.#suggestions = void 0;
|
|
27092
27089
|
this.#beginMessage(event.data.message);
|
|
27093
27090
|
return;
|
|
27094
27091
|
case "interaction_started":
|
|
27092
|
+
this.#suggestions = void 0;
|
|
27095
27093
|
this.#beginInteraction(event.data.id);
|
|
27096
27094
|
return;
|
|
27097
27095
|
case "resume_started":
|
|
27098
27096
|
this.#status = "submitted";
|
|
27099
27097
|
this.#error = void 0;
|
|
27098
|
+
this.#suggestions = void 0;
|
|
27100
27099
|
this.#startOperation();
|
|
27101
27100
|
this.#notify();
|
|
27102
27101
|
return;
|
|
@@ -27129,6 +27128,13 @@ var AssistantChatStateStore = class {
|
|
|
27129
27128
|
case "view_available":
|
|
27130
27129
|
this.#writeData("view", event.data.id, event.data);
|
|
27131
27130
|
return;
|
|
27131
|
+
case "suggested_prompts":
|
|
27132
|
+
this.#suggestions = {
|
|
27133
|
+
phase: event.data.phase,
|
|
27134
|
+
prompts: [...event.data.prompts]
|
|
27135
|
+
};
|
|
27136
|
+
this.#notify();
|
|
27137
|
+
return;
|
|
27132
27138
|
case "message_completed":
|
|
27133
27139
|
this.#closeOperation("ready");
|
|
27134
27140
|
return;
|
|
@@ -27169,6 +27175,7 @@ var AssistantChatStateStore = class {
|
|
|
27169
27175
|
this.#messages = [...this.#messages, userMessage];
|
|
27170
27176
|
this.#status = "submitted";
|
|
27171
27177
|
this.#error = void 0;
|
|
27178
|
+
this.#suggestions = void 0;
|
|
27172
27179
|
this.#startOperation();
|
|
27173
27180
|
this.#notify();
|
|
27174
27181
|
}
|
|
@@ -27498,7 +27505,8 @@ var assistantUiSchema = external_exports.object({
|
|
|
27498
27505
|
privacyUrl: httpsUrlSchema.optional(),
|
|
27499
27506
|
termsUrl: httpsUrlSchema.optional(),
|
|
27500
27507
|
locale: external_exports.string().trim().min(2).max(35).optional(),
|
|
27501
|
-
direction: external_exports.enum(["ltr", "rtl", "auto"]).optional()
|
|
27508
|
+
direction: external_exports.enum(["ltr", "rtl", "auto"]).optional(),
|
|
27509
|
+
webmcp: external_exports.object({ enabled: external_exports.boolean().optional() }).strict().optional()
|
|
27502
27510
|
}).strict();
|
|
27503
27511
|
var assistantConfigurationSchema = external_exports.object({ branding: brandingSchema.optional(), assistant: assistantUiSchema.optional() }).strict();
|
|
27504
27512
|
function parseAssistantConfiguration(value) {
|
|
@@ -27560,7 +27568,8 @@ function parseSession(value) {
|
|
|
27560
27568
|
const apps = value.endpoints.apps;
|
|
27561
27569
|
const sandbox = value.endpoints.sandbox;
|
|
27562
27570
|
const transcript = value.endpoints.transcript;
|
|
27563
|
-
|
|
27571
|
+
const suggestions = value.endpoints.suggestions;
|
|
27572
|
+
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") {
|
|
27564
27573
|
throw clientError("session_failed", "Assistant session response is invalid", true);
|
|
27565
27574
|
}
|
|
27566
27575
|
const configuration = parseAssistantConfiguration(value.configuration);
|
|
@@ -27573,7 +27582,8 @@ function parseSession(value) {
|
|
|
27573
27582
|
...typeof interactions === "string" ? { interactions } : {},
|
|
27574
27583
|
...typeof apps === "string" ? { apps } : {},
|
|
27575
27584
|
...typeof sandbox === "string" ? { sandbox } : {},
|
|
27576
|
-
...typeof transcript === "string" ? { transcript } : {}
|
|
27585
|
+
...typeof transcript === "string" ? { transcript } : {},
|
|
27586
|
+
...typeof suggestions === "string" ? { suggestions } : {}
|
|
27577
27587
|
},
|
|
27578
27588
|
...configuration === void 0 ? {} : { configuration },
|
|
27579
27589
|
...isRecord2(value.resume) && typeof value.resume.tool === "string" ? { resume: { tool: value.resume.tool } } : {}
|
|
@@ -27657,6 +27667,10 @@ function toAssistantClientEvent(event) {
|
|
|
27657
27667
|
return event;
|
|
27658
27668
|
}
|
|
27659
27669
|
break;
|
|
27670
|
+
case "suggested_prompts":
|
|
27671
|
+
if (isSuggestedPromptsDetail(value))
|
|
27672
|
+
return event;
|
|
27673
|
+
break;
|
|
27660
27674
|
case "done":
|
|
27661
27675
|
if (hasOptionalTurnId(value)) return event;
|
|
27662
27676
|
break;
|
|
@@ -27668,6 +27682,12 @@ function toAssistantClientEvent(event) {
|
|
|
27668
27682
|
}
|
|
27669
27683
|
return { event: "unrecognized", data: { name: event.event, payload: value } };
|
|
27670
27684
|
}
|
|
27685
|
+
function isSuggestedPromptsDetail(value) {
|
|
27686
|
+
if (!isRecord3(value)) return false;
|
|
27687
|
+
return (value.phase === "initial" || value.phase === "follow_up") && Array.isArray(value.prompts) && value.prompts.length <= 3 && value.prompts.every(
|
|
27688
|
+
(prompt) => typeof prompt === "string" && prompt.trim().length > 0 && prompt.length <= 240
|
|
27689
|
+
) && hasOptionalTurnId(value);
|
|
27690
|
+
}
|
|
27671
27691
|
function isViewAvailableDetail(value) {
|
|
27672
27692
|
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);
|
|
27673
27693
|
}
|
|
@@ -27746,6 +27766,11 @@ function parseTranscriptEntries(value) {
|
|
|
27746
27766
|
}
|
|
27747
27767
|
return parsed;
|
|
27748
27768
|
}
|
|
27769
|
+
function parseTranscriptSuggestions(value) {
|
|
27770
|
+
if (typeof value !== "object" || value === null) return void 0;
|
|
27771
|
+
const suggestions = value.suggestions;
|
|
27772
|
+
return isSuggestedPromptsDetail(suggestions) && suggestions.phase === "follow_up" ? { phase: suggestions.phase, prompts: suggestions.prompts } : void 0;
|
|
27773
|
+
}
|
|
27749
27774
|
function transcriptReplayEvents(entries2) {
|
|
27750
27775
|
const events = [];
|
|
27751
27776
|
let open = false;
|
|
@@ -27896,6 +27921,32 @@ function isAbortError2(error51) {
|
|
|
27896
27921
|
return error51 instanceof DOMException && error51.name === "AbortError";
|
|
27897
27922
|
}
|
|
27898
27923
|
|
|
27924
|
+
// src/visitor-id.ts
|
|
27925
|
+
var STORAGE_PREFIX = "noodleseed.assistant.visitor.";
|
|
27926
|
+
function randomVisitorId() {
|
|
27927
|
+
try {
|
|
27928
|
+
return globalThis.crypto.randomUUID();
|
|
27929
|
+
} catch {
|
|
27930
|
+
return void 0;
|
|
27931
|
+
}
|
|
27932
|
+
}
|
|
27933
|
+
function visitorIdForSource(sourceKey) {
|
|
27934
|
+
const key = `${STORAGE_PREFIX}${sourceKey}`;
|
|
27935
|
+
try {
|
|
27936
|
+
const stored = globalThis.localStorage?.getItem(key);
|
|
27937
|
+
if (typeof stored === "string" && stored.length > 0) return stored;
|
|
27938
|
+
} catch {
|
|
27939
|
+
return void 0;
|
|
27940
|
+
}
|
|
27941
|
+
const created = randomVisitorId();
|
|
27942
|
+
if (created === void 0) return void 0;
|
|
27943
|
+
try {
|
|
27944
|
+
globalThis.localStorage?.setItem(key, created);
|
|
27945
|
+
} catch {
|
|
27946
|
+
}
|
|
27947
|
+
return created;
|
|
27948
|
+
}
|
|
27949
|
+
|
|
27899
27950
|
// src/client.ts
|
|
27900
27951
|
var DefaultAssistantClient = class {
|
|
27901
27952
|
#source;
|
|
@@ -27908,6 +27959,7 @@ var DefaultAssistantClient = class {
|
|
|
27908
27959
|
#context;
|
|
27909
27960
|
#modelContext;
|
|
27910
27961
|
#active;
|
|
27962
|
+
#initialSuggestions;
|
|
27911
27963
|
#pendingAppInteractions = /* @__PURE__ */ new Map();
|
|
27912
27964
|
constructor(options) {
|
|
27913
27965
|
this.#source = resolveSessionSource(options);
|
|
@@ -27969,10 +28021,13 @@ var DefaultAssistantClient = class {
|
|
|
27969
28021
|
"turn_failed"
|
|
27970
28022
|
);
|
|
27971
28023
|
if (!response.ok) return;
|
|
27972
|
-
|
|
28024
|
+
const value = await response.json();
|
|
28025
|
+
for (const event of transcriptReplayEvents(parseTranscriptEntries(value))) {
|
|
27973
28026
|
this.#emit(event);
|
|
27974
28027
|
if (event.event === "message_completed") await this.#chat.flush();
|
|
27975
28028
|
}
|
|
28029
|
+
const suggestions = parseTranscriptSuggestions(value);
|
|
28030
|
+
if (suggestions) this.#emit({ event: "suggested_prompts", data: suggestions });
|
|
27976
28031
|
}
|
|
27977
28032
|
/** POST the one-shot resume trigger; a 409 means nothing was pending, which renders as silence. */
|
|
27978
28033
|
async #resumeTurn(session, signal) {
|
|
@@ -27981,7 +28036,10 @@ var DefaultAssistantClient = class {
|
|
|
27981
28036
|
{
|
|
27982
28037
|
method: "POST",
|
|
27983
28038
|
headers: authorizedHeaders(session.token, "text/event-stream"),
|
|
27984
|
-
body: JSON.stringify({
|
|
28039
|
+
body: JSON.stringify({
|
|
28040
|
+
resume: true,
|
|
28041
|
+
...session.endpoints.suggestions ? { suggestions: true } : {}
|
|
28042
|
+
}),
|
|
27985
28043
|
signal
|
|
27986
28044
|
},
|
|
27987
28045
|
"turn_failed"
|
|
@@ -28004,6 +28062,7 @@ var DefaultAssistantClient = class {
|
|
|
28004
28062
|
async sendMessage(text3) {
|
|
28005
28063
|
const message = text3.trim();
|
|
28006
28064
|
if (!message) return;
|
|
28065
|
+
this.#cancelInitialSuggestions();
|
|
28007
28066
|
await this.#singleFlight(async (signal) => {
|
|
28008
28067
|
await this.#runChatOperation(
|
|
28009
28068
|
signal,
|
|
@@ -28011,10 +28070,42 @@ var DefaultAssistantClient = class {
|
|
|
28011
28070
|
);
|
|
28012
28071
|
});
|
|
28013
28072
|
}
|
|
28073
|
+
async loadInitialSuggestions() {
|
|
28074
|
+
if (!this.#session) await this.connect();
|
|
28075
|
+
const session = this.#session;
|
|
28076
|
+
if (!session?.endpoints.suggestions) return;
|
|
28077
|
+
if (this.#initialSuggestions) return this.#initialSuggestions.promise;
|
|
28078
|
+
const controller = new AbortController();
|
|
28079
|
+
const clientContext = this.#resolveClientContext();
|
|
28080
|
+
const pageContext = this.#resolvePageContext();
|
|
28081
|
+
const promise2 = this.#request(
|
|
28082
|
+
session.endpoints.suggestions,
|
|
28083
|
+
{
|
|
28084
|
+
method: "POST",
|
|
28085
|
+
headers: authorizedHeaders(session.token, "text/event-stream"),
|
|
28086
|
+
body: JSON.stringify({
|
|
28087
|
+
...clientContext ? { clientContext } : {},
|
|
28088
|
+
...pageContext === void 0 ? {} : { pageContext },
|
|
28089
|
+
...this.#modelContext ? { modelContext: this.#modelContext } : {}
|
|
28090
|
+
}),
|
|
28091
|
+
signal: controller.signal
|
|
28092
|
+
},
|
|
28093
|
+
"turn_failed"
|
|
28094
|
+
).then(async (response) => {
|
|
28095
|
+
if (response.ok) await this.#consume(response);
|
|
28096
|
+
}).finally(() => {
|
|
28097
|
+
if (this.#initialSuggestions?.controller === controller) {
|
|
28098
|
+
this.#initialSuggestions = void 0;
|
|
28099
|
+
}
|
|
28100
|
+
});
|
|
28101
|
+
this.#initialSuggestions = { controller, promise: promise2 };
|
|
28102
|
+
return promise2;
|
|
28103
|
+
}
|
|
28014
28104
|
async respond(id, resolution) {
|
|
28015
28105
|
if (!id) {
|
|
28016
28106
|
throw clientError("invalid_request", "interaction id is required", false);
|
|
28017
28107
|
}
|
|
28108
|
+
this.#cancelInitialSuggestions();
|
|
28018
28109
|
await this.#singleFlight(async (signal) => {
|
|
28019
28110
|
await this.#runChatOperation(signal, async () => {
|
|
28020
28111
|
const pendingApp = this.#pendingAppInteractions.get(id);
|
|
@@ -28034,6 +28125,7 @@ var DefaultAssistantClient = class {
|
|
|
28034
28125
|
const body = modernEndpoint ? {
|
|
28035
28126
|
id,
|
|
28036
28127
|
action: resolution.action,
|
|
28128
|
+
...session.endpoints.suggestions ? { suggestions: true } : {},
|
|
28037
28129
|
...resolution.action === "accept" && resolution.content !== void 0 ? { content: resolution.content } : {}
|
|
28038
28130
|
} : { id };
|
|
28039
28131
|
this.#emit({ event: "interaction_started", data: { id, action: resolution.action } });
|
|
@@ -28112,7 +28204,7 @@ var DefaultAssistantClient = class {
|
|
|
28112
28204
|
this.#modelContext = copyAssistantModelContext(update);
|
|
28113
28205
|
this.#emit({ event: "model_context_changed", data: { modelContext: this.#modelContext } });
|
|
28114
28206
|
}
|
|
28115
|
-
async requestApp(method, params) {
|
|
28207
|
+
async requestApp(method, params, options) {
|
|
28116
28208
|
const session = this.#session;
|
|
28117
28209
|
if (!session?.endpoints.apps) {
|
|
28118
28210
|
throw clientError(
|
|
@@ -28126,7 +28218,11 @@ var DefaultAssistantClient = class {
|
|
|
28126
28218
|
{
|
|
28127
28219
|
method: "POST",
|
|
28128
28220
|
headers: authorizedHeaders(session.token, "application/json"),
|
|
28129
|
-
body: JSON.stringify({
|
|
28221
|
+
body: JSON.stringify({
|
|
28222
|
+
...options?.bridge ? { bridge: options.bridge } : {},
|
|
28223
|
+
method,
|
|
28224
|
+
params
|
|
28225
|
+
})
|
|
28130
28226
|
},
|
|
28131
28227
|
"app_request_failed"
|
|
28132
28228
|
);
|
|
@@ -28141,6 +28237,7 @@ var DefaultAssistantClient = class {
|
|
|
28141
28237
|
const value = await response.json();
|
|
28142
28238
|
const interaction = parseAppInteraction(value);
|
|
28143
28239
|
if (!interaction) return value;
|
|
28240
|
+
options?.onSuspended?.();
|
|
28144
28241
|
return new Promise((resolve2, reject) => {
|
|
28145
28242
|
const id = interaction.data.id;
|
|
28146
28243
|
const replaced = this.#pendingAppInteractions.get(id);
|
|
@@ -28158,6 +28255,7 @@ var DefaultAssistantClient = class {
|
|
|
28158
28255
|
return this.#session?.endpoints.sandbox;
|
|
28159
28256
|
}
|
|
28160
28257
|
resetSession() {
|
|
28258
|
+
this.#cancelInitialSuggestions();
|
|
28161
28259
|
this.#rejectPendingAppInteractions(
|
|
28162
28260
|
clientError("confirmation_expired", "assistant session is not active", false)
|
|
28163
28261
|
);
|
|
@@ -28166,6 +28264,7 @@ var DefaultAssistantClient = class {
|
|
|
28166
28264
|
}
|
|
28167
28265
|
abort() {
|
|
28168
28266
|
this.#active?.abort();
|
|
28267
|
+
this.#cancelInitialSuggestions();
|
|
28169
28268
|
}
|
|
28170
28269
|
async #sendTurn(message, mayRetry, signal, modelContext) {
|
|
28171
28270
|
const session = this.#session ?? await this.#createSession(signal);
|
|
@@ -28181,7 +28280,8 @@ var DefaultAssistantClient = class {
|
|
|
28181
28280
|
message,
|
|
28182
28281
|
...clientContext ? { clientContext } : {},
|
|
28183
28282
|
...pageContext === void 0 ? {} : { pageContext },
|
|
28184
|
-
...modelContext ? { modelContext } : {}
|
|
28283
|
+
...modelContext ? { modelContext } : {},
|
|
28284
|
+
...session.endpoints.suggestions ? { suggestions: true } : {}
|
|
28185
28285
|
}),
|
|
28186
28286
|
signal
|
|
28187
28287
|
},
|
|
@@ -28241,11 +28341,12 @@ var DefaultAssistantClient = class {
|
|
|
28241
28341
|
}
|
|
28242
28342
|
async #createSession(signal) {
|
|
28243
28343
|
const source = this.#source;
|
|
28344
|
+
const visitorId = source.kind === "public" ? visitorIdForSource(sessionSourceKey({ embedId: source.embedId, serviceUrl: source.url })) : void 0;
|
|
28244
28345
|
const response = await this.#requestSession(source, {
|
|
28245
28346
|
method: "POST",
|
|
28246
28347
|
headers: { Accept: "application/json", "Content-Type": "application/json" },
|
|
28247
28348
|
body: JSON.stringify(
|
|
28248
|
-
source.kind === "public" ? { embedId: source.embedId } : this.#context ? { context: this.#context } : {}
|
|
28349
|
+
source.kind === "public" ? { embedId: source.embedId, ...visitorId ? { visitorId } : {} } : this.#context ? { context: this.#context } : {}
|
|
28249
28350
|
),
|
|
28250
28351
|
credentials: source.kind === "public" ? "omit" : "same-origin",
|
|
28251
28352
|
signal
|
|
@@ -28370,6 +28471,9 @@ var DefaultAssistantClient = class {
|
|
|
28370
28471
|
this.#active = void 0;
|
|
28371
28472
|
}
|
|
28372
28473
|
}
|
|
28474
|
+
#cancelInitialSuggestions() {
|
|
28475
|
+
this.#initialSuggestions?.controller.abort();
|
|
28476
|
+
}
|
|
28373
28477
|
async #runChatOperation(signal, operation) {
|
|
28374
28478
|
try {
|
|
28375
28479
|
await operation();
|
|
@@ -28450,6 +28554,22 @@ function appendConversationRecovery(input) {
|
|
|
28450
28554
|
input.revealLatest();
|
|
28451
28555
|
}
|
|
28452
28556
|
|
|
28557
|
+
// src/element-error-recovery.ts
|
|
28558
|
+
function renderConversationError(options) {
|
|
28559
|
+
const { appearance, error: error51 } = options;
|
|
28560
|
+
const detail = error51 instanceof AssistantClientError ? error51.detail : { code: options.fallbackCode, retryable: false };
|
|
28561
|
+
const startNewConversation = detail.serviceCode === "session_turn_budget_exhausted";
|
|
28562
|
+
const reconnect = detail.retryable !== false || detail.serviceCode === void 0;
|
|
28563
|
+
const recoveryAction = startNewConversation ? { label: appearance.labels.newConversation, run: () => options.startNewConversation() } : reconnect ? { label: appearance.labels.reconnect, run: () => options.reconnect() } : void 0;
|
|
28564
|
+
appendConversationRecovery({
|
|
28565
|
+
messages: options.messages,
|
|
28566
|
+
message: detail.code === "session_expired" ? appearance.labels.sessionExpired : appearance.labels.unavailable,
|
|
28567
|
+
...recoveryAction === void 0 ? {} : { action: recoveryAction },
|
|
28568
|
+
revealLatest: () => options.revealLatest()
|
|
28569
|
+
});
|
|
28570
|
+
return detail;
|
|
28571
|
+
}
|
|
28572
|
+
|
|
28453
28573
|
// src/input-request-card.ts
|
|
28454
28574
|
function createInputRequestCard(options) {
|
|
28455
28575
|
const card = document.createElement("section");
|
|
@@ -32623,6 +32743,59 @@ var ASSISTANT_ELEMENT_STYLES = `<style>
|
|
|
32623
32743
|
@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); } }
|
|
32624
32744
|
</style>`;
|
|
32625
32745
|
|
|
32746
|
+
// src/element-suggestions-controller.ts
|
|
32747
|
+
var AssistantElementSuggestionsController = class {
|
|
32748
|
+
#host;
|
|
32749
|
+
#initialRequested = false;
|
|
32750
|
+
#dynamic;
|
|
32751
|
+
constructor(host) {
|
|
32752
|
+
this.#host = host;
|
|
32753
|
+
}
|
|
32754
|
+
reset() {
|
|
32755
|
+
this.#initialRequested = false;
|
|
32756
|
+
this.clear();
|
|
32757
|
+
}
|
|
32758
|
+
clear() {
|
|
32759
|
+
this.#dynamic = void 0;
|
|
32760
|
+
this.render();
|
|
32761
|
+
}
|
|
32762
|
+
handle(event) {
|
|
32763
|
+
if (event.event === "message_started" || event.event === "interaction_started") {
|
|
32764
|
+
this.clear();
|
|
32765
|
+
return;
|
|
32766
|
+
}
|
|
32767
|
+
if (event.event !== "suggested_prompts") return;
|
|
32768
|
+
this.#dynamic = event.data;
|
|
32769
|
+
this.render();
|
|
32770
|
+
}
|
|
32771
|
+
maybeLoadInitial() {
|
|
32772
|
+
const appearance = this.#host.appearance();
|
|
32773
|
+
if (this.#initialRequested || appearance.suggestedPromptsSource !== "model" || this.#host.hasMessages() || !this.#host.isOpen()) {
|
|
32774
|
+
return;
|
|
32775
|
+
}
|
|
32776
|
+
const client = this.#host.client();
|
|
32777
|
+
if (!client?.loadInitialSuggestions) return;
|
|
32778
|
+
this.#initialRequested = true;
|
|
32779
|
+
void client.loadInitialSuggestions().catch(() => {
|
|
32780
|
+
});
|
|
32781
|
+
}
|
|
32782
|
+
render() {
|
|
32783
|
+
const container = this.#host.root()?.querySelector(".suggested-prompts");
|
|
32784
|
+
if (!container) return;
|
|
32785
|
+
const appearance = this.#host.appearance();
|
|
32786
|
+
const hasMessages = this.#host.hasMessages();
|
|
32787
|
+
const prompts = (this.#dynamic?.phase === "follow_up" || !hasMessages ? this.#dynamic?.prompts : void 0) ?? (!hasMessages && appearance.suggestedPromptsSource === "configured" ? appearance.suggestedPrompts : []);
|
|
32788
|
+
container.replaceChildren();
|
|
32789
|
+
for (const prompt of prompts) {
|
|
32790
|
+
const button2 = document.createElement("button");
|
|
32791
|
+
button2.type = "button";
|
|
32792
|
+
button2.textContent = prompt;
|
|
32793
|
+
button2.addEventListener("click", () => this.#host.send(prompt));
|
|
32794
|
+
container.append(button2);
|
|
32795
|
+
}
|
|
32796
|
+
}
|
|
32797
|
+
};
|
|
32798
|
+
|
|
32626
32799
|
// src/host-appearance.ts
|
|
32627
32800
|
var ROLE_VARIABLES = {
|
|
32628
32801
|
canvas: "--ns-assistant-canvas",
|
|
@@ -32931,6 +33104,147 @@ function applyAssistantElementTheme(input) {
|
|
|
32931
33104
|
return warnings;
|
|
32932
33105
|
}
|
|
32933
33106
|
|
|
33107
|
+
// src/webmcp-bridge.ts
|
|
33108
|
+
var INERT = { registeredToolNames: [], stop: () => {
|
|
33109
|
+
} };
|
|
33110
|
+
async function startWebMcpBridge(ports) {
|
|
33111
|
+
const { client, modelContext, enabled } = ports;
|
|
33112
|
+
if (!enabled || !modelContext) return INERT;
|
|
33113
|
+
let listed;
|
|
33114
|
+
try {
|
|
33115
|
+
listed = await client.requestApp("tools/list", {});
|
|
33116
|
+
} catch {
|
|
33117
|
+
return INERT;
|
|
33118
|
+
}
|
|
33119
|
+
const registrations = [];
|
|
33120
|
+
for (const tool of projectableTools(listed)) {
|
|
33121
|
+
registrations.push({
|
|
33122
|
+
name: tool.name,
|
|
33123
|
+
handle: modelContext.registerTool({
|
|
33124
|
+
name: tool.name,
|
|
33125
|
+
...tool.description === void 0 ? {} : { description: tool.description },
|
|
33126
|
+
...tool.inputSchema === void 0 ? {} : { inputSchema: tool.inputSchema },
|
|
33127
|
+
// Passed through, never inferred: an agent may use `readOnlyHint` to decide it can call
|
|
33128
|
+
// without asking, so a hint this bridge invented would be a hint nobody authored.
|
|
33129
|
+
...tool.annotations === void 0 ? {} : { annotations: tool.annotations },
|
|
33130
|
+
execute: (args) => executeThroughAssistant(client, tool.name, args)
|
|
33131
|
+
})
|
|
33132
|
+
});
|
|
33133
|
+
}
|
|
33134
|
+
let stopped = false;
|
|
33135
|
+
return {
|
|
33136
|
+
get registeredToolNames() {
|
|
33137
|
+
return stopped ? [] : registrations.map((entry) => entry.name);
|
|
33138
|
+
},
|
|
33139
|
+
stop() {
|
|
33140
|
+
if (stopped) return;
|
|
33141
|
+
stopped = true;
|
|
33142
|
+
for (const entry of registrations) entry.handle?.unregister?.();
|
|
33143
|
+
}
|
|
33144
|
+
};
|
|
33145
|
+
}
|
|
33146
|
+
function projectableTools(listed) {
|
|
33147
|
+
const tools = isRecord7(listed) && Array.isArray(listed.tools) ? listed.tools : [];
|
|
33148
|
+
const projectable = [];
|
|
33149
|
+
for (const tool of tools) {
|
|
33150
|
+
if (!isRecord7(tool) || typeof tool.name !== "string" || tool.name.length === 0) continue;
|
|
33151
|
+
const visibility = readVisibility(tool);
|
|
33152
|
+
if (visibility !== void 0 && !(visibility.includes("app") && visibility.includes("model"))) {
|
|
33153
|
+
continue;
|
|
33154
|
+
}
|
|
33155
|
+
projectable.push({
|
|
33156
|
+
name: tool.name,
|
|
33157
|
+
description: typeof tool.description === "string" ? tool.description : void 0,
|
|
33158
|
+
inputSchema: isRecord7(tool.inputSchema) ? tool.inputSchema : void 0,
|
|
33159
|
+
annotations: isRecord7(tool.annotations) ? tool.annotations : void 0
|
|
33160
|
+
});
|
|
33161
|
+
}
|
|
33162
|
+
return projectable;
|
|
33163
|
+
}
|
|
33164
|
+
function readVisibility(tool) {
|
|
33165
|
+
const meta3 = isRecord7(tool._meta) ? tool._meta : void 0;
|
|
33166
|
+
const ui = meta3 && isRecord7(meta3.ui) ? meta3.ui : void 0;
|
|
33167
|
+
const visibility = ui?.visibility;
|
|
33168
|
+
return Array.isArray(visibility) ? visibility.filter((entry) => typeof entry === "string") : void 0;
|
|
33169
|
+
}
|
|
33170
|
+
async function executeThroughAssistant(client, name21, args) {
|
|
33171
|
+
let suspend;
|
|
33172
|
+
const suspended = new Promise((resolve2) => {
|
|
33173
|
+
suspend = resolve2;
|
|
33174
|
+
});
|
|
33175
|
+
try {
|
|
33176
|
+
const call = client.requestApp(
|
|
33177
|
+
"tools/call",
|
|
33178
|
+
{ name: name21, arguments: args },
|
|
33179
|
+
// Attribution only: anyone holding the session token could send this, and it selects a
|
|
33180
|
+
// *narrower* budget than the unmarked path, so declaring it can only cost the declarer.
|
|
33181
|
+
{ bridge: "webmcp", onSuspended: suspend }
|
|
33182
|
+
);
|
|
33183
|
+
void call.catch(() => {
|
|
33184
|
+
});
|
|
33185
|
+
const outcome = await Promise.race([
|
|
33186
|
+
call.then((value) => ({ kind: "result", value })),
|
|
33187
|
+
suspended.then(() => ({ kind: "confirmation" }))
|
|
33188
|
+
]);
|
|
33189
|
+
return outcome.kind === "confirmation" ? CONFIRMATION_REQUIRED : toToolResult(outcome.value);
|
|
33190
|
+
} catch (error51) {
|
|
33191
|
+
return textResult(error51 instanceof Error ? error51.message : "tool call failed", true);
|
|
33192
|
+
}
|
|
33193
|
+
}
|
|
33194
|
+
var CONFIRMATION_REQUIRED = {
|
|
33195
|
+
content: [
|
|
33196
|
+
{
|
|
33197
|
+
type: "text",
|
|
33198
|
+
text: "confirmation required: open the assistant panel on this page to approve this action"
|
|
33199
|
+
}
|
|
33200
|
+
],
|
|
33201
|
+
isError: true
|
|
33202
|
+
};
|
|
33203
|
+
function toToolResult(value) {
|
|
33204
|
+
if (isRecord7(value) && Array.isArray(value.content)) return value;
|
|
33205
|
+
return textResult(JSON.stringify(value ?? null), false);
|
|
33206
|
+
}
|
|
33207
|
+
function textResult(text3, isError) {
|
|
33208
|
+
return { content: [{ type: "text", text: text3 }], isError };
|
|
33209
|
+
}
|
|
33210
|
+
function isRecord7(value) {
|
|
33211
|
+
return typeof value === "object" && value !== null && !Array.isArray(value);
|
|
33212
|
+
}
|
|
33213
|
+
|
|
33214
|
+
// src/element-webmcp-controller.ts
|
|
33215
|
+
var AssistantElementWebMcpController = class {
|
|
33216
|
+
#enabled = false;
|
|
33217
|
+
#bridge;
|
|
33218
|
+
/** Guards against a late `startWebMcpBridge` resolving after the session it belonged to is gone. */
|
|
33219
|
+
#generation = 0;
|
|
33220
|
+
/** Called when resolved configuration arrives; the deployment's opt-in is the only source. */
|
|
33221
|
+
configure(enabled) {
|
|
33222
|
+
this.#enabled = enabled;
|
|
33223
|
+
if (!enabled) this.stop();
|
|
33224
|
+
}
|
|
33225
|
+
start(client) {
|
|
33226
|
+
if (!this.#enabled || !client) return;
|
|
33227
|
+
const modelContext = browserModelContext();
|
|
33228
|
+
if (!modelContext) return;
|
|
33229
|
+
this.stop();
|
|
33230
|
+
const generation = ++this.#generation;
|
|
33231
|
+
void startWebMcpBridge({ client, modelContext, enabled: true }).then((bridge) => {
|
|
33232
|
+
if (generation === this.#generation) this.#bridge = bridge;
|
|
33233
|
+
else bridge.stop();
|
|
33234
|
+
});
|
|
33235
|
+
}
|
|
33236
|
+
stop() {
|
|
33237
|
+
this.#generation += 1;
|
|
33238
|
+
this.#bridge?.stop();
|
|
33239
|
+
this.#bridge = void 0;
|
|
33240
|
+
}
|
|
33241
|
+
};
|
|
33242
|
+
function browserModelContext() {
|
|
33243
|
+
if (typeof document === "undefined") return void 0;
|
|
33244
|
+
const host = document;
|
|
33245
|
+
return typeof host.modelContext?.registerTool === "function" ? host.modelContext : void 0;
|
|
33246
|
+
}
|
|
33247
|
+
|
|
32934
33248
|
// src/presentation-styles.ts
|
|
32935
33249
|
var presentationStyles = `<style>
|
|
32936
33250
|
:host([data-mode="floating"]) {
|
|
@@ -33174,9 +33488,18 @@ var NoodleAssistantElement = class extends HTMLElementBase {
|
|
|
33174
33488
|
#turnInFlight = false;
|
|
33175
33489
|
#fetch;
|
|
33176
33490
|
#hostAppearance;
|
|
33491
|
+
#webmcp = new AssistantElementWebMcpController();
|
|
33177
33492
|
#appearanceWarningKeys = /* @__PURE__ */ new Set();
|
|
33178
33493
|
#appearanceStyleSnapshot = /* @__PURE__ */ new Map();
|
|
33179
33494
|
#scroll = new AssistantElementScrollController();
|
|
33495
|
+
#suggestions = new AssistantElementSuggestionsController({
|
|
33496
|
+
root: () => this.shadowRoot,
|
|
33497
|
+
appearance: () => this.#appearance,
|
|
33498
|
+
client: () => this.#client,
|
|
33499
|
+
hasMessages: () => this.hasAttribute("has-messages"),
|
|
33500
|
+
isOpen: () => this.hasAttribute("open"),
|
|
33501
|
+
send: (prompt) => this.#sendGuarded(prompt)
|
|
33502
|
+
});
|
|
33180
33503
|
sessionEndpoint = "";
|
|
33181
33504
|
/** Public mount: the non-secret embed id `noodle deploy` printed. Mutually exclusive with the above. */
|
|
33182
33505
|
embedId = "";
|
|
@@ -33288,6 +33611,7 @@ var NoodleAssistantElement = class extends HTMLElementBase {
|
|
|
33288
33611
|
this.#launcher.disconnect();
|
|
33289
33612
|
this.#setBusy(false);
|
|
33290
33613
|
this.#environment.disconnect();
|
|
33614
|
+
this.#webmcp.stop();
|
|
33291
33615
|
}
|
|
33292
33616
|
attributeChangedCallback(name21) {
|
|
33293
33617
|
if (name21 === "theme") this.#applyTheme();
|
|
@@ -33321,6 +33645,7 @@ var NoodleAssistantElement = class extends HTMLElementBase {
|
|
|
33321
33645
|
}
|
|
33322
33646
|
resetSession() {
|
|
33323
33647
|
this.#conversationGeneration += 1;
|
|
33648
|
+
this.#webmcp.stop();
|
|
33324
33649
|
this.#client?.abort();
|
|
33325
33650
|
this.#unsubscribeClient?.();
|
|
33326
33651
|
this.#client = void 0;
|
|
@@ -33330,12 +33655,14 @@ var NoodleAssistantElement = class extends HTMLElementBase {
|
|
|
33330
33655
|
this.#events.resetConversation();
|
|
33331
33656
|
this.#pendingUserEcho = void 0;
|
|
33332
33657
|
this.removeAttribute("has-messages");
|
|
33658
|
+
this.#suggestions.reset();
|
|
33333
33659
|
this.#setBusy(false);
|
|
33334
33660
|
this.#setSessionState("idle");
|
|
33335
33661
|
}
|
|
33336
33662
|
/** Re-establish the session without replaying a message or interaction decision. */
|
|
33337
33663
|
reconnect() {
|
|
33338
33664
|
this.#conversationGeneration += 1;
|
|
33665
|
+
this.#webmcp.stop();
|
|
33339
33666
|
this.#client?.abort();
|
|
33340
33667
|
this.#unsubscribeClient?.();
|
|
33341
33668
|
this.#client = void 0;
|
|
@@ -33393,6 +33720,7 @@ var NoodleAssistantElement = class extends HTMLElementBase {
|
|
|
33393
33720
|
this.#turnInFlight = true;
|
|
33394
33721
|
this.#pendingUserEcho = message;
|
|
33395
33722
|
this.#appendMessage("user", message);
|
|
33723
|
+
this.#suggestions.clear();
|
|
33396
33724
|
this.#setBusy(true);
|
|
33397
33725
|
if (this.#sessionState !== "ready") this.#setSessionState("loading");
|
|
33398
33726
|
try {
|
|
@@ -33412,12 +33740,7 @@ var NoodleAssistantElement = class extends HTMLElementBase {
|
|
|
33412
33740
|
if (generation === this.#conversationGeneration) this.#setBusy(false);
|
|
33413
33741
|
}
|
|
33414
33742
|
}
|
|
33415
|
-
/**
|
|
33416
|
-
* Every listener the element attaches to its own DOM must go through this guard: internal UI
|
|
33417
|
-
* failures surface as `assistant-error` events (already dispatched by the failing path) and must
|
|
33418
|
-
* never escape as unhandled rejections into the embedding page. Programmatic callers use
|
|
33419
|
-
* `sendMessage`/`confirmTool` directly and keep the rejection.
|
|
33420
|
-
*/
|
|
33743
|
+
/** DOM listeners swallow after the failing path dispatches its typed assistant-error event. */
|
|
33421
33744
|
#sendGuarded(text3) {
|
|
33422
33745
|
void this.sendMessage(text3).catch(() => {
|
|
33423
33746
|
});
|
|
@@ -33469,13 +33792,21 @@ var NoodleAssistantElement = class extends HTMLElementBase {
|
|
|
33469
33792
|
}
|
|
33470
33793
|
#primeSession() {
|
|
33471
33794
|
if (!this.sessionEndpoint && !this.embedId) return;
|
|
33472
|
-
if (this.#sessionBootstrap
|
|
33795
|
+
if (this.#sessionBootstrap) return;
|
|
33796
|
+
if (this.#client?.hasSession()) {
|
|
33797
|
+
this.#suggestions.maybeLoadInitial();
|
|
33798
|
+
return;
|
|
33799
|
+
}
|
|
33473
33800
|
if (this.#client?.isBusy?.() === true) return;
|
|
33474
33801
|
if (this.embedId && !this.#pageContext) void this.#automaticPageContext.refresh();
|
|
33475
33802
|
const client = this.#ensureClient();
|
|
33476
33803
|
const generation = this.#conversationGeneration;
|
|
33477
33804
|
this.#setSessionState("loading");
|
|
33478
|
-
const bootstrap = client.connect().
|
|
33805
|
+
const bootstrap = client.connect().then(() => {
|
|
33806
|
+
if (generation === this.#conversationGeneration && this.#client === client) {
|
|
33807
|
+
this.#suggestions.maybeLoadInitial();
|
|
33808
|
+
}
|
|
33809
|
+
}).catch((error51) => {
|
|
33479
33810
|
if (generation !== this.#conversationGeneration || this.#client !== client) return;
|
|
33480
33811
|
this.#dispatchClientError(error51, "session_failed");
|
|
33481
33812
|
this.#presentationGate.reveal();
|
|
@@ -33487,15 +33818,18 @@ var NoodleAssistantElement = class extends HTMLElementBase {
|
|
|
33487
33818
|
#handleClientEvent(event) {
|
|
33488
33819
|
this.dispatchEvent(new CustomEvent("assistant-event", { detail: event }));
|
|
33489
33820
|
this.#events.handle(event);
|
|
33821
|
+
this.#suggestions.handle(event);
|
|
33490
33822
|
if (event.event === "session_started") {
|
|
33491
33823
|
this.#publicConfiguration.disconnect();
|
|
33492
33824
|
this.removeAttribute("data-public-configuration-loading");
|
|
33493
33825
|
this.#presentationGate.reveal();
|
|
33494
33826
|
this.#setSessionState("ready");
|
|
33495
33827
|
this.#messages?.querySelector(".conversation-error")?.remove();
|
|
33828
|
+
this.#webmcp.start(this.#client);
|
|
33496
33829
|
}
|
|
33497
33830
|
if (event.event === "session_expired" || event.event === "session_reset") {
|
|
33498
33831
|
this.#setSessionState("idle");
|
|
33832
|
+
this.#webmcp.stop();
|
|
33499
33833
|
}
|
|
33500
33834
|
if (event.event === "tool_proposed" || event.event === "interaction_proposed" || event.event === "input_requested") {
|
|
33501
33835
|
this.#removeThinking();
|
|
@@ -33599,23 +33933,17 @@ var NoodleAssistantElement = class extends HTMLElementBase {
|
|
|
33599
33933
|
if (error51 instanceof AssistantClientError && error51.detail.code === "session_failed") {
|
|
33600
33934
|
this.#setSessionState("error");
|
|
33601
33935
|
}
|
|
33602
|
-
|
|
33603
|
-
|
|
33604
|
-
|
|
33605
|
-
|
|
33606
|
-
|
|
33607
|
-
|
|
33608
|
-
|
|
33609
|
-
|
|
33610
|
-
|
|
33611
|
-
|
|
33612
|
-
|
|
33613
|
-
// open tab trying is exactly the load the cap was set to refuse — so the button goes, not just
|
|
33614
|
-
// the alarming words. A spent *session* keeps it: reconnect mints a fresh one, which is the fix.
|
|
33615
|
-
...recoveryAction === void 0 ? {} : { action: recoveryAction },
|
|
33616
|
-
revealLatest: () => this.#revealLatest()
|
|
33617
|
-
});
|
|
33618
|
-
this.#dispatchError(detail);
|
|
33936
|
+
this.#dispatchError(
|
|
33937
|
+
renderConversationError({
|
|
33938
|
+
messages: this.#messages,
|
|
33939
|
+
appearance: this.#appearance,
|
|
33940
|
+
error: error51,
|
|
33941
|
+
fallbackCode,
|
|
33942
|
+
startNewConversation: () => this.#startNewConversation(),
|
|
33943
|
+
reconnect: () => this.reconnect(),
|
|
33944
|
+
revealLatest: () => this.#revealLatest()
|
|
33945
|
+
})
|
|
33946
|
+
);
|
|
33619
33947
|
}
|
|
33620
33948
|
#startNewConversation() {
|
|
33621
33949
|
this.resetSession();
|
|
@@ -33648,7 +33976,9 @@ var NoodleAssistantElement = class extends HTMLElementBase {
|
|
|
33648
33976
|
}
|
|
33649
33977
|
}
|
|
33650
33978
|
#applyConfiguration(configuration) {
|
|
33979
|
+
this.#webmcp.configure(configuration.assistant?.webmcp?.enabled === true);
|
|
33651
33980
|
this.#appearance = resolveAppearance(configuration);
|
|
33981
|
+
this.#suggestions.render();
|
|
33652
33982
|
this.#syncAppearance();
|
|
33653
33983
|
this.#applyStartOpenPolicy();
|
|
33654
33984
|
}
|
|
@@ -33693,15 +34023,7 @@ var NoodleAssistantElement = class extends HTMLElementBase {
|
|
|
33693
34023
|
"aria-label",
|
|
33694
34024
|
appearance.labels.close
|
|
33695
34025
|
);
|
|
33696
|
-
|
|
33697
|
-
prompts.replaceChildren();
|
|
33698
|
-
for (const prompt of appearance.suggestedPrompts) {
|
|
33699
|
-
const button2 = document.createElement("button");
|
|
33700
|
-
button2.type = "button";
|
|
33701
|
-
button2.textContent = prompt;
|
|
33702
|
-
button2.addEventListener("click", () => this.#sendGuarded(prompt));
|
|
33703
|
-
prompts.append(button2);
|
|
33704
|
-
}
|
|
34026
|
+
this.#suggestions.render();
|
|
33705
34027
|
queryRequired(this.shadowRoot, "header").hidden = !appearance.behavior.showHeader;
|
|
33706
34028
|
const legal = queryRequired(this.shadowRoot, ".legal");
|
|
33707
34029
|
legal.replaceChildren();
|
|
@@ -33739,14 +34061,7 @@ var NoodleAssistantElement = class extends HTMLElementBase {
|
|
|
33739
34061
|
textarea.placeholder = appearance.labels.composerPlaceholder;
|
|
33740
34062
|
textarea.setAttribute("aria-label", appearance.labels.composerPlaceholder);
|
|
33741
34063
|
queryRequired(this.shadowRoot, ".send").textContent = appearance.labels.send;
|
|
33742
|
-
|
|
33743
|
-
for (const prompt of appearance.suggestedPrompts) {
|
|
33744
|
-
const button2 = document.createElement("button");
|
|
33745
|
-
button2.type = "button";
|
|
33746
|
-
button2.textContent = prompt;
|
|
33747
|
-
button2.addEventListener("click", () => this.#sendGuarded(prompt));
|
|
33748
|
-
prompts.append(button2);
|
|
33749
|
-
}
|
|
34064
|
+
this.#suggestions.render();
|
|
33750
34065
|
if (!appearance.behavior.showLauncher)
|
|
33751
34066
|
queryRequired(this.shadowRoot, ".launcher").hidden = true;
|
|
33752
34067
|
if (!appearance.behavior.showHeader)
|