@noodleseed/assistant 1.27.0 → 1.29.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-3VZ3M5BE.js} +92 -9
- package/dist/{chunk-WJV4MJUR.js.map → chunk-3VZ3M5BE.js.map} +1 -1
- package/dist/{chunk-2A3ZEYZV.js → chunk-DOWFW3KA.js} +260 -55
- package/dist/chunk-DOWFW3KA.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 +91 -8
- 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 +47 -47
- package/dist/index.cjs +349 -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 +91 -8
- 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 +349 -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-2A3ZEYZV.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;
|
|
@@ -27908,6 +27933,7 @@ var DefaultAssistantClient = class {
|
|
|
27908
27933
|
#context;
|
|
27909
27934
|
#modelContext;
|
|
27910
27935
|
#active;
|
|
27936
|
+
#initialSuggestions;
|
|
27911
27937
|
#pendingAppInteractions = /* @__PURE__ */ new Map();
|
|
27912
27938
|
constructor(options) {
|
|
27913
27939
|
this.#source = resolveSessionSource(options);
|
|
@@ -27969,10 +27995,13 @@ var DefaultAssistantClient = class {
|
|
|
27969
27995
|
"turn_failed"
|
|
27970
27996
|
);
|
|
27971
27997
|
if (!response.ok) return;
|
|
27972
|
-
|
|
27998
|
+
const value = await response.json();
|
|
27999
|
+
for (const event of transcriptReplayEvents(parseTranscriptEntries(value))) {
|
|
27973
28000
|
this.#emit(event);
|
|
27974
28001
|
if (event.event === "message_completed") await this.#chat.flush();
|
|
27975
28002
|
}
|
|
28003
|
+
const suggestions = parseTranscriptSuggestions(value);
|
|
28004
|
+
if (suggestions) this.#emit({ event: "suggested_prompts", data: suggestions });
|
|
27976
28005
|
}
|
|
27977
28006
|
/** POST the one-shot resume trigger; a 409 means nothing was pending, which renders as silence. */
|
|
27978
28007
|
async #resumeTurn(session, signal) {
|
|
@@ -27981,7 +28010,10 @@ var DefaultAssistantClient = class {
|
|
|
27981
28010
|
{
|
|
27982
28011
|
method: "POST",
|
|
27983
28012
|
headers: authorizedHeaders(session.token, "text/event-stream"),
|
|
27984
|
-
body: JSON.stringify({
|
|
28013
|
+
body: JSON.stringify({
|
|
28014
|
+
resume: true,
|
|
28015
|
+
...session.endpoints.suggestions ? { suggestions: true } : {}
|
|
28016
|
+
}),
|
|
27985
28017
|
signal
|
|
27986
28018
|
},
|
|
27987
28019
|
"turn_failed"
|
|
@@ -28004,6 +28036,7 @@ var DefaultAssistantClient = class {
|
|
|
28004
28036
|
async sendMessage(text3) {
|
|
28005
28037
|
const message = text3.trim();
|
|
28006
28038
|
if (!message) return;
|
|
28039
|
+
this.#cancelInitialSuggestions();
|
|
28007
28040
|
await this.#singleFlight(async (signal) => {
|
|
28008
28041
|
await this.#runChatOperation(
|
|
28009
28042
|
signal,
|
|
@@ -28011,10 +28044,42 @@ var DefaultAssistantClient = class {
|
|
|
28011
28044
|
);
|
|
28012
28045
|
});
|
|
28013
28046
|
}
|
|
28047
|
+
async loadInitialSuggestions() {
|
|
28048
|
+
if (!this.#session) await this.connect();
|
|
28049
|
+
const session = this.#session;
|
|
28050
|
+
if (!session?.endpoints.suggestions) return;
|
|
28051
|
+
if (this.#initialSuggestions) return this.#initialSuggestions.promise;
|
|
28052
|
+
const controller = new AbortController();
|
|
28053
|
+
const clientContext = this.#resolveClientContext();
|
|
28054
|
+
const pageContext = this.#resolvePageContext();
|
|
28055
|
+
const promise2 = this.#request(
|
|
28056
|
+
session.endpoints.suggestions,
|
|
28057
|
+
{
|
|
28058
|
+
method: "POST",
|
|
28059
|
+
headers: authorizedHeaders(session.token, "text/event-stream"),
|
|
28060
|
+
body: JSON.stringify({
|
|
28061
|
+
...clientContext ? { clientContext } : {},
|
|
28062
|
+
...pageContext === void 0 ? {} : { pageContext },
|
|
28063
|
+
...this.#modelContext ? { modelContext: this.#modelContext } : {}
|
|
28064
|
+
}),
|
|
28065
|
+
signal: controller.signal
|
|
28066
|
+
},
|
|
28067
|
+
"turn_failed"
|
|
28068
|
+
).then(async (response) => {
|
|
28069
|
+
if (response.ok) await this.#consume(response);
|
|
28070
|
+
}).finally(() => {
|
|
28071
|
+
if (this.#initialSuggestions?.controller === controller) {
|
|
28072
|
+
this.#initialSuggestions = void 0;
|
|
28073
|
+
}
|
|
28074
|
+
});
|
|
28075
|
+
this.#initialSuggestions = { controller, promise: promise2 };
|
|
28076
|
+
return promise2;
|
|
28077
|
+
}
|
|
28014
28078
|
async respond(id, resolution) {
|
|
28015
28079
|
if (!id) {
|
|
28016
28080
|
throw clientError("invalid_request", "interaction id is required", false);
|
|
28017
28081
|
}
|
|
28082
|
+
this.#cancelInitialSuggestions();
|
|
28018
28083
|
await this.#singleFlight(async (signal) => {
|
|
28019
28084
|
await this.#runChatOperation(signal, async () => {
|
|
28020
28085
|
const pendingApp = this.#pendingAppInteractions.get(id);
|
|
@@ -28034,6 +28099,7 @@ var DefaultAssistantClient = class {
|
|
|
28034
28099
|
const body = modernEndpoint ? {
|
|
28035
28100
|
id,
|
|
28036
28101
|
action: resolution.action,
|
|
28102
|
+
...session.endpoints.suggestions ? { suggestions: true } : {},
|
|
28037
28103
|
...resolution.action === "accept" && resolution.content !== void 0 ? { content: resolution.content } : {}
|
|
28038
28104
|
} : { id };
|
|
28039
28105
|
this.#emit({ event: "interaction_started", data: { id, action: resolution.action } });
|
|
@@ -28112,7 +28178,7 @@ var DefaultAssistantClient = class {
|
|
|
28112
28178
|
this.#modelContext = copyAssistantModelContext(update);
|
|
28113
28179
|
this.#emit({ event: "model_context_changed", data: { modelContext: this.#modelContext } });
|
|
28114
28180
|
}
|
|
28115
|
-
async requestApp(method, params) {
|
|
28181
|
+
async requestApp(method, params, options) {
|
|
28116
28182
|
const session = this.#session;
|
|
28117
28183
|
if (!session?.endpoints.apps) {
|
|
28118
28184
|
throw clientError(
|
|
@@ -28126,7 +28192,11 @@ var DefaultAssistantClient = class {
|
|
|
28126
28192
|
{
|
|
28127
28193
|
method: "POST",
|
|
28128
28194
|
headers: authorizedHeaders(session.token, "application/json"),
|
|
28129
|
-
body: JSON.stringify({
|
|
28195
|
+
body: JSON.stringify({
|
|
28196
|
+
...options?.bridge ? { bridge: options.bridge } : {},
|
|
28197
|
+
method,
|
|
28198
|
+
params
|
|
28199
|
+
})
|
|
28130
28200
|
},
|
|
28131
28201
|
"app_request_failed"
|
|
28132
28202
|
);
|
|
@@ -28141,6 +28211,7 @@ var DefaultAssistantClient = class {
|
|
|
28141
28211
|
const value = await response.json();
|
|
28142
28212
|
const interaction = parseAppInteraction(value);
|
|
28143
28213
|
if (!interaction) return value;
|
|
28214
|
+
options?.onSuspended?.();
|
|
28144
28215
|
return new Promise((resolve2, reject) => {
|
|
28145
28216
|
const id = interaction.data.id;
|
|
28146
28217
|
const replaced = this.#pendingAppInteractions.get(id);
|
|
@@ -28158,6 +28229,7 @@ var DefaultAssistantClient = class {
|
|
|
28158
28229
|
return this.#session?.endpoints.sandbox;
|
|
28159
28230
|
}
|
|
28160
28231
|
resetSession() {
|
|
28232
|
+
this.#cancelInitialSuggestions();
|
|
28161
28233
|
this.#rejectPendingAppInteractions(
|
|
28162
28234
|
clientError("confirmation_expired", "assistant session is not active", false)
|
|
28163
28235
|
);
|
|
@@ -28166,6 +28238,7 @@ var DefaultAssistantClient = class {
|
|
|
28166
28238
|
}
|
|
28167
28239
|
abort() {
|
|
28168
28240
|
this.#active?.abort();
|
|
28241
|
+
this.#cancelInitialSuggestions();
|
|
28169
28242
|
}
|
|
28170
28243
|
async #sendTurn(message, mayRetry, signal, modelContext) {
|
|
28171
28244
|
const session = this.#session ?? await this.#createSession(signal);
|
|
@@ -28181,7 +28254,8 @@ var DefaultAssistantClient = class {
|
|
|
28181
28254
|
message,
|
|
28182
28255
|
...clientContext ? { clientContext } : {},
|
|
28183
28256
|
...pageContext === void 0 ? {} : { pageContext },
|
|
28184
|
-
...modelContext ? { modelContext } : {}
|
|
28257
|
+
...modelContext ? { modelContext } : {},
|
|
28258
|
+
...session.endpoints.suggestions ? { suggestions: true } : {}
|
|
28185
28259
|
}),
|
|
28186
28260
|
signal
|
|
28187
28261
|
},
|
|
@@ -28370,6 +28444,9 @@ var DefaultAssistantClient = class {
|
|
|
28370
28444
|
this.#active = void 0;
|
|
28371
28445
|
}
|
|
28372
28446
|
}
|
|
28447
|
+
#cancelInitialSuggestions() {
|
|
28448
|
+
this.#initialSuggestions?.controller.abort();
|
|
28449
|
+
}
|
|
28373
28450
|
async #runChatOperation(signal, operation) {
|
|
28374
28451
|
try {
|
|
28375
28452
|
await operation();
|
|
@@ -28450,6 +28527,22 @@ function appendConversationRecovery(input) {
|
|
|
28450
28527
|
input.revealLatest();
|
|
28451
28528
|
}
|
|
28452
28529
|
|
|
28530
|
+
// src/element-error-recovery.ts
|
|
28531
|
+
function renderConversationError(options) {
|
|
28532
|
+
const { appearance, error: error51 } = options;
|
|
28533
|
+
const detail = error51 instanceof AssistantClientError ? error51.detail : { code: options.fallbackCode, retryable: false };
|
|
28534
|
+
const startNewConversation = detail.serviceCode === "session_turn_budget_exhausted";
|
|
28535
|
+
const reconnect = detail.retryable !== false || detail.serviceCode === void 0;
|
|
28536
|
+
const recoveryAction = startNewConversation ? { label: appearance.labels.newConversation, run: () => options.startNewConversation() } : reconnect ? { label: appearance.labels.reconnect, run: () => options.reconnect() } : void 0;
|
|
28537
|
+
appendConversationRecovery({
|
|
28538
|
+
messages: options.messages,
|
|
28539
|
+
message: detail.code === "session_expired" ? appearance.labels.sessionExpired : appearance.labels.unavailable,
|
|
28540
|
+
...recoveryAction === void 0 ? {} : { action: recoveryAction },
|
|
28541
|
+
revealLatest: () => options.revealLatest()
|
|
28542
|
+
});
|
|
28543
|
+
return detail;
|
|
28544
|
+
}
|
|
28545
|
+
|
|
28453
28546
|
// src/input-request-card.ts
|
|
28454
28547
|
function createInputRequestCard(options) {
|
|
28455
28548
|
const card = document.createElement("section");
|
|
@@ -32474,7 +32567,7 @@ var ASSISTANT_ELEMENT_STYLES = `<style>
|
|
|
32474
32567
|
.launcher[hidden] { display: none; }
|
|
32475
32568
|
.launcher:hover { transform: scale(1.02); box-shadow: var(--ns-assistant-halo-launcher-shadow-hover), -6px 0 18px color-mix(in srgb, var(--ns-assistant-accent, var(--ns-assistant-default-accent)) 20%, transparent), 6px 0 18px color-mix(in srgb, var(--ns-assistant-accent, var(--ns-assistant-default-accent)) 20%, transparent); }
|
|
32476
32569
|
.launcher-trigger, .launcher-form { min-width: 0; margin: 0; padding: 0; border: 0; background: transparent; font: inherit; }
|
|
32477
|
-
.launcher-trigger { display: flex; align-items: center; gap: 12px; min-height: 28px; color: var(--ns-assistant-
|
|
32570
|
+
.launcher-trigger { display: flex; align-items: center; gap: 12px; min-height: 28px; color: var(--ns-assistant-launcher-text, var(--ns-assistant-text, var(--ns-assistant-default-text))); cursor: text; }
|
|
32478
32571
|
.launcher-label { padding-left: 6px; white-space: nowrap; font-size: 15px; line-height: 20px; }
|
|
32479
32572
|
.launcher-arrow, .launcher-send { position: relative; display: grid; width: 28px; height: 28px; flex: 0 0 28px; place-items: center; border: 0; border-radius: 50%; color: var(--ns-assistant-text, var(--ns-assistant-default-text)); background: var(--ns-assistant-launcher-action, var(--ns-assistant-halo-launcher-action)); cursor: pointer; }
|
|
32480
32573
|
.launcher-arrow:hover, .launcher-send:hover { background: var(--ns-assistant-launcher-action-hover, var(--ns-assistant-halo-launcher-action-hover)); }
|
|
@@ -32623,6 +32716,59 @@ var ASSISTANT_ELEMENT_STYLES = `<style>
|
|
|
32623
32716
|
@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
32717
|
</style>`;
|
|
32625
32718
|
|
|
32719
|
+
// src/element-suggestions-controller.ts
|
|
32720
|
+
var AssistantElementSuggestionsController = class {
|
|
32721
|
+
#host;
|
|
32722
|
+
#initialRequested = false;
|
|
32723
|
+
#dynamic;
|
|
32724
|
+
constructor(host) {
|
|
32725
|
+
this.#host = host;
|
|
32726
|
+
}
|
|
32727
|
+
reset() {
|
|
32728
|
+
this.#initialRequested = false;
|
|
32729
|
+
this.clear();
|
|
32730
|
+
}
|
|
32731
|
+
clear() {
|
|
32732
|
+
this.#dynamic = void 0;
|
|
32733
|
+
this.render();
|
|
32734
|
+
}
|
|
32735
|
+
handle(event) {
|
|
32736
|
+
if (event.event === "message_started" || event.event === "interaction_started") {
|
|
32737
|
+
this.clear();
|
|
32738
|
+
return;
|
|
32739
|
+
}
|
|
32740
|
+
if (event.event !== "suggested_prompts") return;
|
|
32741
|
+
this.#dynamic = event.data;
|
|
32742
|
+
this.render();
|
|
32743
|
+
}
|
|
32744
|
+
maybeLoadInitial() {
|
|
32745
|
+
const appearance = this.#host.appearance();
|
|
32746
|
+
if (this.#initialRequested || appearance.suggestedPromptsSource !== "model" || this.#host.hasMessages() || !this.#host.isOpen()) {
|
|
32747
|
+
return;
|
|
32748
|
+
}
|
|
32749
|
+
const client = this.#host.client();
|
|
32750
|
+
if (!client?.loadInitialSuggestions) return;
|
|
32751
|
+
this.#initialRequested = true;
|
|
32752
|
+
void client.loadInitialSuggestions().catch(() => {
|
|
32753
|
+
});
|
|
32754
|
+
}
|
|
32755
|
+
render() {
|
|
32756
|
+
const container = this.#host.root()?.querySelector(".suggested-prompts");
|
|
32757
|
+
if (!container) return;
|
|
32758
|
+
const appearance = this.#host.appearance();
|
|
32759
|
+
const hasMessages = this.#host.hasMessages();
|
|
32760
|
+
const prompts = (this.#dynamic?.phase === "follow_up" || !hasMessages ? this.#dynamic?.prompts : void 0) ?? (!hasMessages && appearance.suggestedPromptsSource === "configured" ? appearance.suggestedPrompts : []);
|
|
32761
|
+
container.replaceChildren();
|
|
32762
|
+
for (const prompt of prompts) {
|
|
32763
|
+
const button2 = document.createElement("button");
|
|
32764
|
+
button2.type = "button";
|
|
32765
|
+
button2.textContent = prompt;
|
|
32766
|
+
button2.addEventListener("click", () => this.#host.send(prompt));
|
|
32767
|
+
container.append(button2);
|
|
32768
|
+
}
|
|
32769
|
+
}
|
|
32770
|
+
};
|
|
32771
|
+
|
|
32626
32772
|
// src/host-appearance.ts
|
|
32627
32773
|
var ROLE_VARIABLES = {
|
|
32628
32774
|
canvas: "--ns-assistant-canvas",
|
|
@@ -32931,6 +33077,147 @@ function applyAssistantElementTheme(input) {
|
|
|
32931
33077
|
return warnings;
|
|
32932
33078
|
}
|
|
32933
33079
|
|
|
33080
|
+
// src/webmcp-bridge.ts
|
|
33081
|
+
var INERT = { registeredToolNames: [], stop: () => {
|
|
33082
|
+
} };
|
|
33083
|
+
async function startWebMcpBridge(ports) {
|
|
33084
|
+
const { client, modelContext, enabled } = ports;
|
|
33085
|
+
if (!enabled || !modelContext) return INERT;
|
|
33086
|
+
let listed;
|
|
33087
|
+
try {
|
|
33088
|
+
listed = await client.requestApp("tools/list", {});
|
|
33089
|
+
} catch {
|
|
33090
|
+
return INERT;
|
|
33091
|
+
}
|
|
33092
|
+
const registrations = [];
|
|
33093
|
+
for (const tool of projectableTools(listed)) {
|
|
33094
|
+
registrations.push({
|
|
33095
|
+
name: tool.name,
|
|
33096
|
+
handle: modelContext.registerTool({
|
|
33097
|
+
name: tool.name,
|
|
33098
|
+
...tool.description === void 0 ? {} : { description: tool.description },
|
|
33099
|
+
...tool.inputSchema === void 0 ? {} : { inputSchema: tool.inputSchema },
|
|
33100
|
+
// Passed through, never inferred: an agent may use `readOnlyHint` to decide it can call
|
|
33101
|
+
// without asking, so a hint this bridge invented would be a hint nobody authored.
|
|
33102
|
+
...tool.annotations === void 0 ? {} : { annotations: tool.annotations },
|
|
33103
|
+
execute: (args) => executeThroughAssistant(client, tool.name, args)
|
|
33104
|
+
})
|
|
33105
|
+
});
|
|
33106
|
+
}
|
|
33107
|
+
let stopped = false;
|
|
33108
|
+
return {
|
|
33109
|
+
get registeredToolNames() {
|
|
33110
|
+
return stopped ? [] : registrations.map((entry) => entry.name);
|
|
33111
|
+
},
|
|
33112
|
+
stop() {
|
|
33113
|
+
if (stopped) return;
|
|
33114
|
+
stopped = true;
|
|
33115
|
+
for (const entry of registrations) entry.handle?.unregister?.();
|
|
33116
|
+
}
|
|
33117
|
+
};
|
|
33118
|
+
}
|
|
33119
|
+
function projectableTools(listed) {
|
|
33120
|
+
const tools = isRecord7(listed) && Array.isArray(listed.tools) ? listed.tools : [];
|
|
33121
|
+
const projectable = [];
|
|
33122
|
+
for (const tool of tools) {
|
|
33123
|
+
if (!isRecord7(tool) || typeof tool.name !== "string" || tool.name.length === 0) continue;
|
|
33124
|
+
const visibility = readVisibility(tool);
|
|
33125
|
+
if (visibility !== void 0 && !(visibility.includes("app") && visibility.includes("model"))) {
|
|
33126
|
+
continue;
|
|
33127
|
+
}
|
|
33128
|
+
projectable.push({
|
|
33129
|
+
name: tool.name,
|
|
33130
|
+
description: typeof tool.description === "string" ? tool.description : void 0,
|
|
33131
|
+
inputSchema: isRecord7(tool.inputSchema) ? tool.inputSchema : void 0,
|
|
33132
|
+
annotations: isRecord7(tool.annotations) ? tool.annotations : void 0
|
|
33133
|
+
});
|
|
33134
|
+
}
|
|
33135
|
+
return projectable;
|
|
33136
|
+
}
|
|
33137
|
+
function readVisibility(tool) {
|
|
33138
|
+
const meta3 = isRecord7(tool._meta) ? tool._meta : void 0;
|
|
33139
|
+
const ui = meta3 && isRecord7(meta3.ui) ? meta3.ui : void 0;
|
|
33140
|
+
const visibility = ui?.visibility;
|
|
33141
|
+
return Array.isArray(visibility) ? visibility.filter((entry) => typeof entry === "string") : void 0;
|
|
33142
|
+
}
|
|
33143
|
+
async function executeThroughAssistant(client, name21, args) {
|
|
33144
|
+
let suspend;
|
|
33145
|
+
const suspended = new Promise((resolve2) => {
|
|
33146
|
+
suspend = resolve2;
|
|
33147
|
+
});
|
|
33148
|
+
try {
|
|
33149
|
+
const call = client.requestApp(
|
|
33150
|
+
"tools/call",
|
|
33151
|
+
{ name: name21, arguments: args },
|
|
33152
|
+
// Attribution only: anyone holding the session token could send this, and it selects a
|
|
33153
|
+
// *narrower* budget than the unmarked path, so declaring it can only cost the declarer.
|
|
33154
|
+
{ bridge: "webmcp", onSuspended: suspend }
|
|
33155
|
+
);
|
|
33156
|
+
void call.catch(() => {
|
|
33157
|
+
});
|
|
33158
|
+
const outcome = await Promise.race([
|
|
33159
|
+
call.then((value) => ({ kind: "result", value })),
|
|
33160
|
+
suspended.then(() => ({ kind: "confirmation" }))
|
|
33161
|
+
]);
|
|
33162
|
+
return outcome.kind === "confirmation" ? CONFIRMATION_REQUIRED : toToolResult(outcome.value);
|
|
33163
|
+
} catch (error51) {
|
|
33164
|
+
return textResult(error51 instanceof Error ? error51.message : "tool call failed", true);
|
|
33165
|
+
}
|
|
33166
|
+
}
|
|
33167
|
+
var CONFIRMATION_REQUIRED = {
|
|
33168
|
+
content: [
|
|
33169
|
+
{
|
|
33170
|
+
type: "text",
|
|
33171
|
+
text: "confirmation required: open the assistant panel on this page to approve this action"
|
|
33172
|
+
}
|
|
33173
|
+
],
|
|
33174
|
+
isError: true
|
|
33175
|
+
};
|
|
33176
|
+
function toToolResult(value) {
|
|
33177
|
+
if (isRecord7(value) && Array.isArray(value.content)) return value;
|
|
33178
|
+
return textResult(JSON.stringify(value ?? null), false);
|
|
33179
|
+
}
|
|
33180
|
+
function textResult(text3, isError) {
|
|
33181
|
+
return { content: [{ type: "text", text: text3 }], isError };
|
|
33182
|
+
}
|
|
33183
|
+
function isRecord7(value) {
|
|
33184
|
+
return typeof value === "object" && value !== null && !Array.isArray(value);
|
|
33185
|
+
}
|
|
33186
|
+
|
|
33187
|
+
// src/element-webmcp-controller.ts
|
|
33188
|
+
var AssistantElementWebMcpController = class {
|
|
33189
|
+
#enabled = false;
|
|
33190
|
+
#bridge;
|
|
33191
|
+
/** Guards against a late `startWebMcpBridge` resolving after the session it belonged to is gone. */
|
|
33192
|
+
#generation = 0;
|
|
33193
|
+
/** Called when resolved configuration arrives; the deployment's opt-in is the only source. */
|
|
33194
|
+
configure(enabled) {
|
|
33195
|
+
this.#enabled = enabled;
|
|
33196
|
+
if (!enabled) this.stop();
|
|
33197
|
+
}
|
|
33198
|
+
start(client) {
|
|
33199
|
+
if (!this.#enabled || !client) return;
|
|
33200
|
+
const modelContext = browserModelContext();
|
|
33201
|
+
if (!modelContext) return;
|
|
33202
|
+
this.stop();
|
|
33203
|
+
const generation = ++this.#generation;
|
|
33204
|
+
void startWebMcpBridge({ client, modelContext, enabled: true }).then((bridge) => {
|
|
33205
|
+
if (generation === this.#generation) this.#bridge = bridge;
|
|
33206
|
+
else bridge.stop();
|
|
33207
|
+
});
|
|
33208
|
+
}
|
|
33209
|
+
stop() {
|
|
33210
|
+
this.#generation += 1;
|
|
33211
|
+
this.#bridge?.stop();
|
|
33212
|
+
this.#bridge = void 0;
|
|
33213
|
+
}
|
|
33214
|
+
};
|
|
33215
|
+
function browserModelContext() {
|
|
33216
|
+
if (typeof document === "undefined") return void 0;
|
|
33217
|
+
const host = document;
|
|
33218
|
+
return typeof host.modelContext?.registerTool === "function" ? host.modelContext : void 0;
|
|
33219
|
+
}
|
|
33220
|
+
|
|
32934
33221
|
// src/presentation-styles.ts
|
|
32935
33222
|
var presentationStyles = `<style>
|
|
32936
33223
|
:host([data-mode="floating"]) {
|
|
@@ -33174,9 +33461,18 @@ var NoodleAssistantElement = class extends HTMLElementBase {
|
|
|
33174
33461
|
#turnInFlight = false;
|
|
33175
33462
|
#fetch;
|
|
33176
33463
|
#hostAppearance;
|
|
33464
|
+
#webmcp = new AssistantElementWebMcpController();
|
|
33177
33465
|
#appearanceWarningKeys = /* @__PURE__ */ new Set();
|
|
33178
33466
|
#appearanceStyleSnapshot = /* @__PURE__ */ new Map();
|
|
33179
33467
|
#scroll = new AssistantElementScrollController();
|
|
33468
|
+
#suggestions = new AssistantElementSuggestionsController({
|
|
33469
|
+
root: () => this.shadowRoot,
|
|
33470
|
+
appearance: () => this.#appearance,
|
|
33471
|
+
client: () => this.#client,
|
|
33472
|
+
hasMessages: () => this.hasAttribute("has-messages"),
|
|
33473
|
+
isOpen: () => this.hasAttribute("open"),
|
|
33474
|
+
send: (prompt) => this.#sendGuarded(prompt)
|
|
33475
|
+
});
|
|
33180
33476
|
sessionEndpoint = "";
|
|
33181
33477
|
/** Public mount: the non-secret embed id `noodle deploy` printed. Mutually exclusive with the above. */
|
|
33182
33478
|
embedId = "";
|
|
@@ -33288,6 +33584,7 @@ var NoodleAssistantElement = class extends HTMLElementBase {
|
|
|
33288
33584
|
this.#launcher.disconnect();
|
|
33289
33585
|
this.#setBusy(false);
|
|
33290
33586
|
this.#environment.disconnect();
|
|
33587
|
+
this.#webmcp.stop();
|
|
33291
33588
|
}
|
|
33292
33589
|
attributeChangedCallback(name21) {
|
|
33293
33590
|
if (name21 === "theme") this.#applyTheme();
|
|
@@ -33321,6 +33618,7 @@ var NoodleAssistantElement = class extends HTMLElementBase {
|
|
|
33321
33618
|
}
|
|
33322
33619
|
resetSession() {
|
|
33323
33620
|
this.#conversationGeneration += 1;
|
|
33621
|
+
this.#webmcp.stop();
|
|
33324
33622
|
this.#client?.abort();
|
|
33325
33623
|
this.#unsubscribeClient?.();
|
|
33326
33624
|
this.#client = void 0;
|
|
@@ -33330,12 +33628,14 @@ var NoodleAssistantElement = class extends HTMLElementBase {
|
|
|
33330
33628
|
this.#events.resetConversation();
|
|
33331
33629
|
this.#pendingUserEcho = void 0;
|
|
33332
33630
|
this.removeAttribute("has-messages");
|
|
33631
|
+
this.#suggestions.reset();
|
|
33333
33632
|
this.#setBusy(false);
|
|
33334
33633
|
this.#setSessionState("idle");
|
|
33335
33634
|
}
|
|
33336
33635
|
/** Re-establish the session without replaying a message or interaction decision. */
|
|
33337
33636
|
reconnect() {
|
|
33338
33637
|
this.#conversationGeneration += 1;
|
|
33638
|
+
this.#webmcp.stop();
|
|
33339
33639
|
this.#client?.abort();
|
|
33340
33640
|
this.#unsubscribeClient?.();
|
|
33341
33641
|
this.#client = void 0;
|
|
@@ -33393,6 +33693,7 @@ var NoodleAssistantElement = class extends HTMLElementBase {
|
|
|
33393
33693
|
this.#turnInFlight = true;
|
|
33394
33694
|
this.#pendingUserEcho = message;
|
|
33395
33695
|
this.#appendMessage("user", message);
|
|
33696
|
+
this.#suggestions.clear();
|
|
33396
33697
|
this.#setBusy(true);
|
|
33397
33698
|
if (this.#sessionState !== "ready") this.#setSessionState("loading");
|
|
33398
33699
|
try {
|
|
@@ -33412,12 +33713,7 @@ var NoodleAssistantElement = class extends HTMLElementBase {
|
|
|
33412
33713
|
if (generation === this.#conversationGeneration) this.#setBusy(false);
|
|
33413
33714
|
}
|
|
33414
33715
|
}
|
|
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
|
-
*/
|
|
33716
|
+
/** DOM listeners swallow after the failing path dispatches its typed assistant-error event. */
|
|
33421
33717
|
#sendGuarded(text3) {
|
|
33422
33718
|
void this.sendMessage(text3).catch(() => {
|
|
33423
33719
|
});
|
|
@@ -33469,13 +33765,21 @@ var NoodleAssistantElement = class extends HTMLElementBase {
|
|
|
33469
33765
|
}
|
|
33470
33766
|
#primeSession() {
|
|
33471
33767
|
if (!this.sessionEndpoint && !this.embedId) return;
|
|
33472
|
-
if (this.#sessionBootstrap
|
|
33768
|
+
if (this.#sessionBootstrap) return;
|
|
33769
|
+
if (this.#client?.hasSession()) {
|
|
33770
|
+
this.#suggestions.maybeLoadInitial();
|
|
33771
|
+
return;
|
|
33772
|
+
}
|
|
33473
33773
|
if (this.#client?.isBusy?.() === true) return;
|
|
33474
33774
|
if (this.embedId && !this.#pageContext) void this.#automaticPageContext.refresh();
|
|
33475
33775
|
const client = this.#ensureClient();
|
|
33476
33776
|
const generation = this.#conversationGeneration;
|
|
33477
33777
|
this.#setSessionState("loading");
|
|
33478
|
-
const bootstrap = client.connect().
|
|
33778
|
+
const bootstrap = client.connect().then(() => {
|
|
33779
|
+
if (generation === this.#conversationGeneration && this.#client === client) {
|
|
33780
|
+
this.#suggestions.maybeLoadInitial();
|
|
33781
|
+
}
|
|
33782
|
+
}).catch((error51) => {
|
|
33479
33783
|
if (generation !== this.#conversationGeneration || this.#client !== client) return;
|
|
33480
33784
|
this.#dispatchClientError(error51, "session_failed");
|
|
33481
33785
|
this.#presentationGate.reveal();
|
|
@@ -33487,15 +33791,18 @@ var NoodleAssistantElement = class extends HTMLElementBase {
|
|
|
33487
33791
|
#handleClientEvent(event) {
|
|
33488
33792
|
this.dispatchEvent(new CustomEvent("assistant-event", { detail: event }));
|
|
33489
33793
|
this.#events.handle(event);
|
|
33794
|
+
this.#suggestions.handle(event);
|
|
33490
33795
|
if (event.event === "session_started") {
|
|
33491
33796
|
this.#publicConfiguration.disconnect();
|
|
33492
33797
|
this.removeAttribute("data-public-configuration-loading");
|
|
33493
33798
|
this.#presentationGate.reveal();
|
|
33494
33799
|
this.#setSessionState("ready");
|
|
33495
33800
|
this.#messages?.querySelector(".conversation-error")?.remove();
|
|
33801
|
+
this.#webmcp.start(this.#client);
|
|
33496
33802
|
}
|
|
33497
33803
|
if (event.event === "session_expired" || event.event === "session_reset") {
|
|
33498
33804
|
this.#setSessionState("idle");
|
|
33805
|
+
this.#webmcp.stop();
|
|
33499
33806
|
}
|
|
33500
33807
|
if (event.event === "tool_proposed" || event.event === "interaction_proposed" || event.event === "input_requested") {
|
|
33501
33808
|
this.#removeThinking();
|
|
@@ -33599,23 +33906,17 @@ var NoodleAssistantElement = class extends HTMLElementBase {
|
|
|
33599
33906
|
if (error51 instanceof AssistantClientError && error51.detail.code === "session_failed") {
|
|
33600
33907
|
this.#setSessionState("error");
|
|
33601
33908
|
}
|
|
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);
|
|
33909
|
+
this.#dispatchError(
|
|
33910
|
+
renderConversationError({
|
|
33911
|
+
messages: this.#messages,
|
|
33912
|
+
appearance: this.#appearance,
|
|
33913
|
+
error: error51,
|
|
33914
|
+
fallbackCode,
|
|
33915
|
+
startNewConversation: () => this.#startNewConversation(),
|
|
33916
|
+
reconnect: () => this.reconnect(),
|
|
33917
|
+
revealLatest: () => this.#revealLatest()
|
|
33918
|
+
})
|
|
33919
|
+
);
|
|
33619
33920
|
}
|
|
33620
33921
|
#startNewConversation() {
|
|
33621
33922
|
this.resetSession();
|
|
@@ -33648,7 +33949,9 @@ var NoodleAssistantElement = class extends HTMLElementBase {
|
|
|
33648
33949
|
}
|
|
33649
33950
|
}
|
|
33650
33951
|
#applyConfiguration(configuration) {
|
|
33952
|
+
this.#webmcp.configure(configuration.assistant?.webmcp?.enabled === true);
|
|
33651
33953
|
this.#appearance = resolveAppearance(configuration);
|
|
33954
|
+
this.#suggestions.render();
|
|
33652
33955
|
this.#syncAppearance();
|
|
33653
33956
|
this.#applyStartOpenPolicy();
|
|
33654
33957
|
}
|
|
@@ -33693,15 +33996,7 @@ var NoodleAssistantElement = class extends HTMLElementBase {
|
|
|
33693
33996
|
"aria-label",
|
|
33694
33997
|
appearance.labels.close
|
|
33695
33998
|
);
|
|
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
|
-
}
|
|
33999
|
+
this.#suggestions.render();
|
|
33705
34000
|
queryRequired(this.shadowRoot, "header").hidden = !appearance.behavior.showHeader;
|
|
33706
34001
|
const legal = queryRequired(this.shadowRoot, ".legal");
|
|
33707
34002
|
legal.replaceChildren();
|
|
@@ -33739,14 +34034,7 @@ var NoodleAssistantElement = class extends HTMLElementBase {
|
|
|
33739
34034
|
textarea.placeholder = appearance.labels.composerPlaceholder;
|
|
33740
34035
|
textarea.setAttribute("aria-label", appearance.labels.composerPlaceholder);
|
|
33741
34036
|
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
|
-
}
|
|
34037
|
+
this.#suggestions.render();
|
|
33750
34038
|
if (!appearance.behavior.showLauncher)
|
|
33751
34039
|
queryRequired(this.shadowRoot, ".launcher").hidden = true;
|
|
33752
34040
|
if (!appearance.behavior.showHeader)
|