@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
|
@@ -11,7 +11,7 @@ import {
|
|
|
11
11
|
parseAssistantConfiguration,
|
|
12
12
|
publicConfigurationUrl,
|
|
13
13
|
sessionSourceKey
|
|
14
|
-
} from "./chunk-
|
|
14
|
+
} from "./chunk-5EVZFPTD.js";
|
|
15
15
|
|
|
16
16
|
// src/appearance.ts
|
|
17
17
|
var common = {
|
|
@@ -154,11 +154,8 @@ var DEFAULT_APPEARANCE = {
|
|
|
154
154
|
composer: { leadingIcon: "none", sendIcon: "arrow-up", shape: "pill" },
|
|
155
155
|
messages: { userStyle: "bubble", assistantStyle: "plain" }
|
|
156
156
|
},
|
|
157
|
-
suggestedPrompts: [
|
|
158
|
-
|
|
159
|
-
"Tell me about your business",
|
|
160
|
-
"How can I get in touch?"
|
|
161
|
-
],
|
|
157
|
+
suggestedPrompts: [],
|
|
158
|
+
suggestedPromptsSource: "model",
|
|
162
159
|
locale: "en",
|
|
163
160
|
direction: "auto"
|
|
164
161
|
};
|
|
@@ -191,11 +188,8 @@ function resolveAppearance(input = {}) {
|
|
|
191
188
|
...assistant?.labels
|
|
192
189
|
},
|
|
193
190
|
presentation: resolvePresentation(assistant?.presentation),
|
|
194
|
-
suggestedPrompts: assistant?.suggestedPrompts ??
|
|
195
|
-
|
|
196
|
-
`Tell me about ${branding.name}`,
|
|
197
|
-
"How can I get in touch?"
|
|
198
|
-
] : DEFAULT_APPEARANCE.suggestedPrompts),
|
|
191
|
+
suggestedPrompts: assistant?.suggestedPrompts ?? [],
|
|
192
|
+
suggestedPromptsSource: assistant?.suggestedPrompts === void 0 ? "model" : "configured",
|
|
199
193
|
...assistant?.privacyUrl ? { privacyUrl: assistant.privacyUrl } : {},
|
|
200
194
|
...assistant?.termsUrl ? { termsUrl: assistant.termsUrl } : {},
|
|
201
195
|
locale: assistant?.locale ?? DEFAULT_APPEARANCE.locale,
|
|
@@ -438,6 +432,22 @@ function appendConversationRecovery(input) {
|
|
|
438
432
|
input.revealLatest();
|
|
439
433
|
}
|
|
440
434
|
|
|
435
|
+
// src/element-error-recovery.ts
|
|
436
|
+
function renderConversationError(options) {
|
|
437
|
+
const { appearance, error } = options;
|
|
438
|
+
const detail = error instanceof AssistantClientError ? error.detail : { code: options.fallbackCode, retryable: false };
|
|
439
|
+
const startNewConversation = detail.serviceCode === "session_turn_budget_exhausted";
|
|
440
|
+
const reconnect = detail.retryable !== false || detail.serviceCode === void 0;
|
|
441
|
+
const recoveryAction = startNewConversation ? { label: appearance.labels.newConversation, run: () => options.startNewConversation() } : reconnect ? { label: appearance.labels.reconnect, run: () => options.reconnect() } : void 0;
|
|
442
|
+
appendConversationRecovery({
|
|
443
|
+
messages: options.messages,
|
|
444
|
+
message: detail.code === "session_expired" ? appearance.labels.sessionExpired : appearance.labels.unavailable,
|
|
445
|
+
...recoveryAction === void 0 ? {} : { action: recoveryAction },
|
|
446
|
+
revealLatest: () => options.revealLatest()
|
|
447
|
+
});
|
|
448
|
+
return detail;
|
|
449
|
+
}
|
|
450
|
+
|
|
441
451
|
// src/input-request-card.ts
|
|
442
452
|
function createInputRequestCard(options) {
|
|
443
453
|
const card = document.createElement("section");
|
|
@@ -4588,6 +4598,59 @@ var ASSISTANT_ELEMENT_STYLES = `<style>
|
|
|
4588
4598
|
@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); } }
|
|
4589
4599
|
</style>`;
|
|
4590
4600
|
|
|
4601
|
+
// src/element-suggestions-controller.ts
|
|
4602
|
+
var AssistantElementSuggestionsController = class {
|
|
4603
|
+
#host;
|
|
4604
|
+
#initialRequested = false;
|
|
4605
|
+
#dynamic;
|
|
4606
|
+
constructor(host) {
|
|
4607
|
+
this.#host = host;
|
|
4608
|
+
}
|
|
4609
|
+
reset() {
|
|
4610
|
+
this.#initialRequested = false;
|
|
4611
|
+
this.clear();
|
|
4612
|
+
}
|
|
4613
|
+
clear() {
|
|
4614
|
+
this.#dynamic = void 0;
|
|
4615
|
+
this.render();
|
|
4616
|
+
}
|
|
4617
|
+
handle(event) {
|
|
4618
|
+
if (event.event === "message_started" || event.event === "interaction_started") {
|
|
4619
|
+
this.clear();
|
|
4620
|
+
return;
|
|
4621
|
+
}
|
|
4622
|
+
if (event.event !== "suggested_prompts") return;
|
|
4623
|
+
this.#dynamic = event.data;
|
|
4624
|
+
this.render();
|
|
4625
|
+
}
|
|
4626
|
+
maybeLoadInitial() {
|
|
4627
|
+
const appearance = this.#host.appearance();
|
|
4628
|
+
if (this.#initialRequested || appearance.suggestedPromptsSource !== "model" || this.#host.hasMessages() || !this.#host.isOpen()) {
|
|
4629
|
+
return;
|
|
4630
|
+
}
|
|
4631
|
+
const client = this.#host.client();
|
|
4632
|
+
if (!client?.loadInitialSuggestions) return;
|
|
4633
|
+
this.#initialRequested = true;
|
|
4634
|
+
void client.loadInitialSuggestions().catch(() => {
|
|
4635
|
+
});
|
|
4636
|
+
}
|
|
4637
|
+
render() {
|
|
4638
|
+
const container = this.#host.root()?.querySelector(".suggested-prompts");
|
|
4639
|
+
if (!container) return;
|
|
4640
|
+
const appearance = this.#host.appearance();
|
|
4641
|
+
const hasMessages = this.#host.hasMessages();
|
|
4642
|
+
const prompts = (this.#dynamic?.phase === "follow_up" || !hasMessages ? this.#dynamic?.prompts : void 0) ?? (!hasMessages && appearance.suggestedPromptsSource === "configured" ? appearance.suggestedPrompts : []);
|
|
4643
|
+
container.replaceChildren();
|
|
4644
|
+
for (const prompt of prompts) {
|
|
4645
|
+
const button2 = document.createElement("button");
|
|
4646
|
+
button2.type = "button";
|
|
4647
|
+
button2.textContent = prompt;
|
|
4648
|
+
button2.addEventListener("click", () => this.#host.send(prompt));
|
|
4649
|
+
container.append(button2);
|
|
4650
|
+
}
|
|
4651
|
+
}
|
|
4652
|
+
};
|
|
4653
|
+
|
|
4591
4654
|
// src/host-appearance.ts
|
|
4592
4655
|
var ROLE_VARIABLES = {
|
|
4593
4656
|
canvas: "--ns-assistant-canvas",
|
|
@@ -4896,6 +4959,147 @@ function applyAssistantElementTheme(input) {
|
|
|
4896
4959
|
return warnings;
|
|
4897
4960
|
}
|
|
4898
4961
|
|
|
4962
|
+
// src/webmcp-bridge.ts
|
|
4963
|
+
var INERT = { registeredToolNames: [], stop: () => {
|
|
4964
|
+
} };
|
|
4965
|
+
async function startWebMcpBridge(ports) {
|
|
4966
|
+
const { client, modelContext, enabled } = ports;
|
|
4967
|
+
if (!enabled || !modelContext) return INERT;
|
|
4968
|
+
let listed;
|
|
4969
|
+
try {
|
|
4970
|
+
listed = await client.requestApp("tools/list", {});
|
|
4971
|
+
} catch {
|
|
4972
|
+
return INERT;
|
|
4973
|
+
}
|
|
4974
|
+
const registrations = [];
|
|
4975
|
+
for (const tool of projectableTools(listed)) {
|
|
4976
|
+
registrations.push({
|
|
4977
|
+
name: tool.name,
|
|
4978
|
+
handle: modelContext.registerTool({
|
|
4979
|
+
name: tool.name,
|
|
4980
|
+
...tool.description === void 0 ? {} : { description: tool.description },
|
|
4981
|
+
...tool.inputSchema === void 0 ? {} : { inputSchema: tool.inputSchema },
|
|
4982
|
+
// Passed through, never inferred: an agent may use `readOnlyHint` to decide it can call
|
|
4983
|
+
// without asking, so a hint this bridge invented would be a hint nobody authored.
|
|
4984
|
+
...tool.annotations === void 0 ? {} : { annotations: tool.annotations },
|
|
4985
|
+
execute: (args) => executeThroughAssistant(client, tool.name, args)
|
|
4986
|
+
})
|
|
4987
|
+
});
|
|
4988
|
+
}
|
|
4989
|
+
let stopped = false;
|
|
4990
|
+
return {
|
|
4991
|
+
get registeredToolNames() {
|
|
4992
|
+
return stopped ? [] : registrations.map((entry) => entry.name);
|
|
4993
|
+
},
|
|
4994
|
+
stop() {
|
|
4995
|
+
if (stopped) return;
|
|
4996
|
+
stopped = true;
|
|
4997
|
+
for (const entry of registrations) entry.handle?.unregister?.();
|
|
4998
|
+
}
|
|
4999
|
+
};
|
|
5000
|
+
}
|
|
5001
|
+
function projectableTools(listed) {
|
|
5002
|
+
const tools = isRecord3(listed) && Array.isArray(listed.tools) ? listed.tools : [];
|
|
5003
|
+
const projectable = [];
|
|
5004
|
+
for (const tool of tools) {
|
|
5005
|
+
if (!isRecord3(tool) || typeof tool.name !== "string" || tool.name.length === 0) continue;
|
|
5006
|
+
const visibility = readVisibility(tool);
|
|
5007
|
+
if (visibility !== void 0 && !(visibility.includes("app") && visibility.includes("model"))) {
|
|
5008
|
+
continue;
|
|
5009
|
+
}
|
|
5010
|
+
projectable.push({
|
|
5011
|
+
name: tool.name,
|
|
5012
|
+
description: typeof tool.description === "string" ? tool.description : void 0,
|
|
5013
|
+
inputSchema: isRecord3(tool.inputSchema) ? tool.inputSchema : void 0,
|
|
5014
|
+
annotations: isRecord3(tool.annotations) ? tool.annotations : void 0
|
|
5015
|
+
});
|
|
5016
|
+
}
|
|
5017
|
+
return projectable;
|
|
5018
|
+
}
|
|
5019
|
+
function readVisibility(tool) {
|
|
5020
|
+
const meta = isRecord3(tool._meta) ? tool._meta : void 0;
|
|
5021
|
+
const ui = meta && isRecord3(meta.ui) ? meta.ui : void 0;
|
|
5022
|
+
const visibility = ui?.visibility;
|
|
5023
|
+
return Array.isArray(visibility) ? visibility.filter((entry) => typeof entry === "string") : void 0;
|
|
5024
|
+
}
|
|
5025
|
+
async function executeThroughAssistant(client, name, args) {
|
|
5026
|
+
let suspend;
|
|
5027
|
+
const suspended = new Promise((resolve) => {
|
|
5028
|
+
suspend = resolve;
|
|
5029
|
+
});
|
|
5030
|
+
try {
|
|
5031
|
+
const call = client.requestApp(
|
|
5032
|
+
"tools/call",
|
|
5033
|
+
{ name, arguments: args },
|
|
5034
|
+
// Attribution only: anyone holding the session token could send this, and it selects a
|
|
5035
|
+
// *narrower* budget than the unmarked path, so declaring it can only cost the declarer.
|
|
5036
|
+
{ bridge: "webmcp", onSuspended: suspend }
|
|
5037
|
+
);
|
|
5038
|
+
void call.catch(() => {
|
|
5039
|
+
});
|
|
5040
|
+
const outcome = await Promise.race([
|
|
5041
|
+
call.then((value) => ({ kind: "result", value })),
|
|
5042
|
+
suspended.then(() => ({ kind: "confirmation" }))
|
|
5043
|
+
]);
|
|
5044
|
+
return outcome.kind === "confirmation" ? CONFIRMATION_REQUIRED : toToolResult(outcome.value);
|
|
5045
|
+
} catch (error) {
|
|
5046
|
+
return textResult(error instanceof Error ? error.message : "tool call failed", true);
|
|
5047
|
+
}
|
|
5048
|
+
}
|
|
5049
|
+
var CONFIRMATION_REQUIRED = {
|
|
5050
|
+
content: [
|
|
5051
|
+
{
|
|
5052
|
+
type: "text",
|
|
5053
|
+
text: "confirmation required: open the assistant panel on this page to approve this action"
|
|
5054
|
+
}
|
|
5055
|
+
],
|
|
5056
|
+
isError: true
|
|
5057
|
+
};
|
|
5058
|
+
function toToolResult(value) {
|
|
5059
|
+
if (isRecord3(value) && Array.isArray(value.content)) return value;
|
|
5060
|
+
return textResult(JSON.stringify(value ?? null), false);
|
|
5061
|
+
}
|
|
5062
|
+
function textResult(text2, isError) {
|
|
5063
|
+
return { content: [{ type: "text", text: text2 }], isError };
|
|
5064
|
+
}
|
|
5065
|
+
function isRecord3(value) {
|
|
5066
|
+
return typeof value === "object" && value !== null && !Array.isArray(value);
|
|
5067
|
+
}
|
|
5068
|
+
|
|
5069
|
+
// src/element-webmcp-controller.ts
|
|
5070
|
+
var AssistantElementWebMcpController = class {
|
|
5071
|
+
#enabled = false;
|
|
5072
|
+
#bridge;
|
|
5073
|
+
/** Guards against a late `startWebMcpBridge` resolving after the session it belonged to is gone. */
|
|
5074
|
+
#generation = 0;
|
|
5075
|
+
/** Called when resolved configuration arrives; the deployment's opt-in is the only source. */
|
|
5076
|
+
configure(enabled) {
|
|
5077
|
+
this.#enabled = enabled;
|
|
5078
|
+
if (!enabled) this.stop();
|
|
5079
|
+
}
|
|
5080
|
+
start(client) {
|
|
5081
|
+
if (!this.#enabled || !client) return;
|
|
5082
|
+
const modelContext = browserModelContext();
|
|
5083
|
+
if (!modelContext) return;
|
|
5084
|
+
this.stop();
|
|
5085
|
+
const generation = ++this.#generation;
|
|
5086
|
+
void startWebMcpBridge({ client, modelContext, enabled: true }).then((bridge) => {
|
|
5087
|
+
if (generation === this.#generation) this.#bridge = bridge;
|
|
5088
|
+
else bridge.stop();
|
|
5089
|
+
});
|
|
5090
|
+
}
|
|
5091
|
+
stop() {
|
|
5092
|
+
this.#generation += 1;
|
|
5093
|
+
this.#bridge?.stop();
|
|
5094
|
+
this.#bridge = void 0;
|
|
5095
|
+
}
|
|
5096
|
+
};
|
|
5097
|
+
function browserModelContext() {
|
|
5098
|
+
if (typeof document === "undefined") return void 0;
|
|
5099
|
+
const host = document;
|
|
5100
|
+
return typeof host.modelContext?.registerTool === "function" ? host.modelContext : void 0;
|
|
5101
|
+
}
|
|
5102
|
+
|
|
4899
5103
|
// src/presentation-styles.ts
|
|
4900
5104
|
var presentationStyles = `<style>
|
|
4901
5105
|
:host([data-mode="floating"]) {
|
|
@@ -5139,9 +5343,18 @@ var NoodleAssistantElement = class extends HTMLElementBase {
|
|
|
5139
5343
|
#turnInFlight = false;
|
|
5140
5344
|
#fetch;
|
|
5141
5345
|
#hostAppearance;
|
|
5346
|
+
#webmcp = new AssistantElementWebMcpController();
|
|
5142
5347
|
#appearanceWarningKeys = /* @__PURE__ */ new Set();
|
|
5143
5348
|
#appearanceStyleSnapshot = /* @__PURE__ */ new Map();
|
|
5144
5349
|
#scroll = new AssistantElementScrollController();
|
|
5350
|
+
#suggestions = new AssistantElementSuggestionsController({
|
|
5351
|
+
root: () => this.shadowRoot,
|
|
5352
|
+
appearance: () => this.#appearance,
|
|
5353
|
+
client: () => this.#client,
|
|
5354
|
+
hasMessages: () => this.hasAttribute("has-messages"),
|
|
5355
|
+
isOpen: () => this.hasAttribute("open"),
|
|
5356
|
+
send: (prompt) => this.#sendGuarded(prompt)
|
|
5357
|
+
});
|
|
5145
5358
|
sessionEndpoint = "";
|
|
5146
5359
|
/** Public mount: the non-secret embed id `noodle deploy` printed. Mutually exclusive with the above. */
|
|
5147
5360
|
embedId = "";
|
|
@@ -5253,6 +5466,7 @@ var NoodleAssistantElement = class extends HTMLElementBase {
|
|
|
5253
5466
|
this.#launcher.disconnect();
|
|
5254
5467
|
this.#setBusy(false);
|
|
5255
5468
|
this.#environment.disconnect();
|
|
5469
|
+
this.#webmcp.stop();
|
|
5256
5470
|
}
|
|
5257
5471
|
attributeChangedCallback(name) {
|
|
5258
5472
|
if (name === "theme") this.#applyTheme();
|
|
@@ -5286,6 +5500,7 @@ var NoodleAssistantElement = class extends HTMLElementBase {
|
|
|
5286
5500
|
}
|
|
5287
5501
|
resetSession() {
|
|
5288
5502
|
this.#conversationGeneration += 1;
|
|
5503
|
+
this.#webmcp.stop();
|
|
5289
5504
|
this.#client?.abort();
|
|
5290
5505
|
this.#unsubscribeClient?.();
|
|
5291
5506
|
this.#client = void 0;
|
|
@@ -5295,12 +5510,14 @@ var NoodleAssistantElement = class extends HTMLElementBase {
|
|
|
5295
5510
|
this.#events.resetConversation();
|
|
5296
5511
|
this.#pendingUserEcho = void 0;
|
|
5297
5512
|
this.removeAttribute("has-messages");
|
|
5513
|
+
this.#suggestions.reset();
|
|
5298
5514
|
this.#setBusy(false);
|
|
5299
5515
|
this.#setSessionState("idle");
|
|
5300
5516
|
}
|
|
5301
5517
|
/** Re-establish the session without replaying a message or interaction decision. */
|
|
5302
5518
|
reconnect() {
|
|
5303
5519
|
this.#conversationGeneration += 1;
|
|
5520
|
+
this.#webmcp.stop();
|
|
5304
5521
|
this.#client?.abort();
|
|
5305
5522
|
this.#unsubscribeClient?.();
|
|
5306
5523
|
this.#client = void 0;
|
|
@@ -5358,6 +5575,7 @@ var NoodleAssistantElement = class extends HTMLElementBase {
|
|
|
5358
5575
|
this.#turnInFlight = true;
|
|
5359
5576
|
this.#pendingUserEcho = message;
|
|
5360
5577
|
this.#appendMessage("user", message);
|
|
5578
|
+
this.#suggestions.clear();
|
|
5361
5579
|
this.#setBusy(true);
|
|
5362
5580
|
if (this.#sessionState !== "ready") this.#setSessionState("loading");
|
|
5363
5581
|
try {
|
|
@@ -5377,12 +5595,7 @@ var NoodleAssistantElement = class extends HTMLElementBase {
|
|
|
5377
5595
|
if (generation === this.#conversationGeneration) this.#setBusy(false);
|
|
5378
5596
|
}
|
|
5379
5597
|
}
|
|
5380
|
-
/**
|
|
5381
|
-
* Every listener the element attaches to its own DOM must go through this guard: internal UI
|
|
5382
|
-
* failures surface as `assistant-error` events (already dispatched by the failing path) and must
|
|
5383
|
-
* never escape as unhandled rejections into the embedding page. Programmatic callers use
|
|
5384
|
-
* `sendMessage`/`confirmTool` directly and keep the rejection.
|
|
5385
|
-
*/
|
|
5598
|
+
/** DOM listeners swallow after the failing path dispatches its typed assistant-error event. */
|
|
5386
5599
|
#sendGuarded(text2) {
|
|
5387
5600
|
void this.sendMessage(text2).catch(() => {
|
|
5388
5601
|
});
|
|
@@ -5434,13 +5647,21 @@ var NoodleAssistantElement = class extends HTMLElementBase {
|
|
|
5434
5647
|
}
|
|
5435
5648
|
#primeSession() {
|
|
5436
5649
|
if (!this.sessionEndpoint && !this.embedId) return;
|
|
5437
|
-
if (this.#sessionBootstrap
|
|
5650
|
+
if (this.#sessionBootstrap) return;
|
|
5651
|
+
if (this.#client?.hasSession()) {
|
|
5652
|
+
this.#suggestions.maybeLoadInitial();
|
|
5653
|
+
return;
|
|
5654
|
+
}
|
|
5438
5655
|
if (this.#client?.isBusy?.() === true) return;
|
|
5439
5656
|
if (this.embedId && !this.#pageContext) void this.#automaticPageContext.refresh();
|
|
5440
5657
|
const client = this.#ensureClient();
|
|
5441
5658
|
const generation = this.#conversationGeneration;
|
|
5442
5659
|
this.#setSessionState("loading");
|
|
5443
|
-
const bootstrap = client.connect().
|
|
5660
|
+
const bootstrap = client.connect().then(() => {
|
|
5661
|
+
if (generation === this.#conversationGeneration && this.#client === client) {
|
|
5662
|
+
this.#suggestions.maybeLoadInitial();
|
|
5663
|
+
}
|
|
5664
|
+
}).catch((error) => {
|
|
5444
5665
|
if (generation !== this.#conversationGeneration || this.#client !== client) return;
|
|
5445
5666
|
this.#dispatchClientError(error, "session_failed");
|
|
5446
5667
|
this.#presentationGate.reveal();
|
|
@@ -5452,15 +5673,18 @@ var NoodleAssistantElement = class extends HTMLElementBase {
|
|
|
5452
5673
|
#handleClientEvent(event) {
|
|
5453
5674
|
this.dispatchEvent(new CustomEvent("assistant-event", { detail: event }));
|
|
5454
5675
|
this.#events.handle(event);
|
|
5676
|
+
this.#suggestions.handle(event);
|
|
5455
5677
|
if (event.event === "session_started") {
|
|
5456
5678
|
this.#publicConfiguration.disconnect();
|
|
5457
5679
|
this.removeAttribute("data-public-configuration-loading");
|
|
5458
5680
|
this.#presentationGate.reveal();
|
|
5459
5681
|
this.#setSessionState("ready");
|
|
5460
5682
|
this.#messages?.querySelector(".conversation-error")?.remove();
|
|
5683
|
+
this.#webmcp.start(this.#client);
|
|
5461
5684
|
}
|
|
5462
5685
|
if (event.event === "session_expired" || event.event === "session_reset") {
|
|
5463
5686
|
this.#setSessionState("idle");
|
|
5687
|
+
this.#webmcp.stop();
|
|
5464
5688
|
}
|
|
5465
5689
|
if (event.event === "tool_proposed" || event.event === "interaction_proposed" || event.event === "input_requested") {
|
|
5466
5690
|
this.#removeThinking();
|
|
@@ -5564,23 +5788,17 @@ var NoodleAssistantElement = class extends HTMLElementBase {
|
|
|
5564
5788
|
if (error instanceof AssistantClientError && error.detail.code === "session_failed") {
|
|
5565
5789
|
this.#setSessionState("error");
|
|
5566
5790
|
}
|
|
5567
|
-
|
|
5568
|
-
|
|
5569
|
-
|
|
5570
|
-
|
|
5571
|
-
|
|
5572
|
-
|
|
5573
|
-
|
|
5574
|
-
|
|
5575
|
-
|
|
5576
|
-
|
|
5577
|
-
|
|
5578
|
-
// open tab trying is exactly the load the cap was set to refuse — so the button goes, not just
|
|
5579
|
-
// the alarming words. A spent *session* keeps it: reconnect mints a fresh one, which is the fix.
|
|
5580
|
-
...recoveryAction === void 0 ? {} : { action: recoveryAction },
|
|
5581
|
-
revealLatest: () => this.#revealLatest()
|
|
5582
|
-
});
|
|
5583
|
-
this.#dispatchError(detail);
|
|
5791
|
+
this.#dispatchError(
|
|
5792
|
+
renderConversationError({
|
|
5793
|
+
messages: this.#messages,
|
|
5794
|
+
appearance: this.#appearance,
|
|
5795
|
+
error,
|
|
5796
|
+
fallbackCode,
|
|
5797
|
+
startNewConversation: () => this.#startNewConversation(),
|
|
5798
|
+
reconnect: () => this.reconnect(),
|
|
5799
|
+
revealLatest: () => this.#revealLatest()
|
|
5800
|
+
})
|
|
5801
|
+
);
|
|
5584
5802
|
}
|
|
5585
5803
|
#startNewConversation() {
|
|
5586
5804
|
this.resetSession();
|
|
@@ -5613,7 +5831,9 @@ var NoodleAssistantElement = class extends HTMLElementBase {
|
|
|
5613
5831
|
}
|
|
5614
5832
|
}
|
|
5615
5833
|
#applyConfiguration(configuration) {
|
|
5834
|
+
this.#webmcp.configure(configuration.assistant?.webmcp?.enabled === true);
|
|
5616
5835
|
this.#appearance = resolveAppearance(configuration);
|
|
5836
|
+
this.#suggestions.render();
|
|
5617
5837
|
this.#syncAppearance();
|
|
5618
5838
|
this.#applyStartOpenPolicy();
|
|
5619
5839
|
}
|
|
@@ -5658,15 +5878,7 @@ var NoodleAssistantElement = class extends HTMLElementBase {
|
|
|
5658
5878
|
"aria-label",
|
|
5659
5879
|
appearance.labels.close
|
|
5660
5880
|
);
|
|
5661
|
-
|
|
5662
|
-
prompts.replaceChildren();
|
|
5663
|
-
for (const prompt of appearance.suggestedPrompts) {
|
|
5664
|
-
const button2 = document.createElement("button");
|
|
5665
|
-
button2.type = "button";
|
|
5666
|
-
button2.textContent = prompt;
|
|
5667
|
-
button2.addEventListener("click", () => this.#sendGuarded(prompt));
|
|
5668
|
-
prompts.append(button2);
|
|
5669
|
-
}
|
|
5881
|
+
this.#suggestions.render();
|
|
5670
5882
|
queryRequired(this.shadowRoot, "header").hidden = !appearance.behavior.showHeader;
|
|
5671
5883
|
const legal = queryRequired(this.shadowRoot, ".legal");
|
|
5672
5884
|
legal.replaceChildren();
|
|
@@ -5704,14 +5916,7 @@ var NoodleAssistantElement = class extends HTMLElementBase {
|
|
|
5704
5916
|
textarea.placeholder = appearance.labels.composerPlaceholder;
|
|
5705
5917
|
textarea.setAttribute("aria-label", appearance.labels.composerPlaceholder);
|
|
5706
5918
|
queryRequired(this.shadowRoot, ".send").textContent = appearance.labels.send;
|
|
5707
|
-
|
|
5708
|
-
for (const prompt of appearance.suggestedPrompts) {
|
|
5709
|
-
const button2 = document.createElement("button");
|
|
5710
|
-
button2.type = "button";
|
|
5711
|
-
button2.textContent = prompt;
|
|
5712
|
-
button2.addEventListener("click", () => this.#sendGuarded(prompt));
|
|
5713
|
-
prompts.append(button2);
|
|
5714
|
-
}
|
|
5919
|
+
this.#suggestions.render();
|
|
5715
5920
|
if (!appearance.behavior.showLauncher)
|
|
5716
5921
|
queryRequired(this.shadowRoot, ".launcher").hidden = true;
|
|
5717
5922
|
if (!appearance.behavior.showHeader)
|
|
@@ -5770,4 +5975,4 @@ export {
|
|
|
5770
5975
|
dompurify/dist/purify.es.mjs:
|
|
5771
5976
|
(*! @license DOMPurify 3.4.11 | (c) Cure53 and other contributors | Released under the Apache license 2.0 and Mozilla Public License 2.0 | github.com/cure53/DOMPurify/blob/3.4.11/LICENSE *)
|
|
5772
5977
|
*/
|
|
5773
|
-
//# sourceMappingURL=chunk-
|
|
5978
|
+
//# sourceMappingURL=chunk-T4PS6P2W.js.map
|