@noodleseed/assistant 1.4.0 → 1.6.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +31 -8
- package/dist/{appearance-BLO7kFYB.d.cts → appearance-DowzFJjh.d.cts} +9 -0
- package/dist/{appearance-BLO7kFYB.d.ts → appearance-DowzFJjh.d.ts} +9 -0
- package/dist/{chunk-P34VLBIK.js → chunk-GTYYQNGT.js} +2 -2
- package/dist/chunk-GTYYQNGT.js.map +1 -0
- package/dist/{chunk-JIL4B5HD.js → chunk-ZKXOX67J.js} +463 -100
- package/dist/chunk-ZKXOX67J.js.map +1 -0
- package/dist/{client-nW-Zf4bU.d.ts → client-9kup0-ws.d.cts} +4 -1
- package/dist/{client-1uaN8-yl.d.cts → client-BRjZMXlk.d.ts} +4 -1
- package/dist/client.cjs +1 -1
- package/dist/client.cjs.map +1 -1
- package/dist/client.d.cts +2 -2
- package/dist/client.d.ts +2 -2
- package/dist/client.js +1 -1
- package/dist/index.cjs +462 -99
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +53 -4
- package/dist/index.d.ts +53 -4
- package/dist/index.js +2 -2
- package/dist/index.js.map +1 -1
- package/dist/react.cjs +468 -99
- package/dist/react.cjs.map +1 -1
- package/dist/react.d.cts +6 -4
- package/dist/react.d.ts +6 -4
- package/dist/react.js +8 -2
- package/dist/react.js.map +1 -1
- package/dist/server.d.cts +1 -1
- package/dist/server.d.ts +1 -1
- package/package.json +1 -1
- package/dist/chunk-JIL4B5HD.js.map +0 -1
- package/dist/chunk-P34VLBIK.js.map +0 -1
|
@@ -2,7 +2,7 @@ import {
|
|
|
2
2
|
AssistantClientError,
|
|
3
3
|
copyAssistantModelContext,
|
|
4
4
|
createAssistantClient
|
|
5
|
-
} from "./chunk-
|
|
5
|
+
} from "./chunk-GTYYQNGT.js";
|
|
6
6
|
import {
|
|
7
7
|
_enum,
|
|
8
8
|
_null,
|
|
@@ -3158,12 +3158,12 @@ var common = {
|
|
|
3158
3158
|
baseFontSize: 15,
|
|
3159
3159
|
messageFontSize: 15,
|
|
3160
3160
|
lineHeight: 1.5,
|
|
3161
|
-
panelRadius:
|
|
3162
|
-
cardRadius:
|
|
3163
|
-
inputRadius:
|
|
3164
|
-
buttonRadius:
|
|
3161
|
+
panelRadius: 20,
|
|
3162
|
+
cardRadius: 14,
|
|
3163
|
+
inputRadius: 14,
|
|
3164
|
+
buttonRadius: 12,
|
|
3165
3165
|
launcherRadius: 999,
|
|
3166
|
-
spacing:
|
|
3166
|
+
spacing: 8,
|
|
3167
3167
|
backdropBlur: 18,
|
|
3168
3168
|
motionScale: 1
|
|
3169
3169
|
};
|
|
@@ -3221,7 +3221,7 @@ var DEFAULT_APPEARANCE = {
|
|
|
3221
3221
|
layout: {
|
|
3222
3222
|
mode: "floating",
|
|
3223
3223
|
position: "bottom-right",
|
|
3224
|
-
panelWidth:
|
|
3224
|
+
panelWidth: 520,
|
|
3225
3225
|
panelMinHeight: 540,
|
|
3226
3226
|
panelMaxHeight: 820,
|
|
3227
3227
|
edgeOffset: 20,
|
|
@@ -3248,7 +3248,16 @@ var DEFAULT_APPEARANCE = {
|
|
|
3248
3248
|
close: "Close assistant",
|
|
3249
3249
|
open: "Open assistant",
|
|
3250
3250
|
confirm: "Confirm",
|
|
3251
|
+
decline: "Don't proceed",
|
|
3251
3252
|
cancel: "Cancel",
|
|
3253
|
+
confirmationHeading: "Review and confirm",
|
|
3254
|
+
additionalDetails: "Additional details",
|
|
3255
|
+
redacted: "Hidden for security",
|
|
3256
|
+
completed: "Completed",
|
|
3257
|
+
stopped: "Stopped",
|
|
3258
|
+
copy: "Copy",
|
|
3259
|
+
newMessages: "New messages",
|
|
3260
|
+
reconnect: "Reconnect",
|
|
3252
3261
|
retry: "Try again",
|
|
3253
3262
|
unavailable: "The assistant is temporarily unavailable.",
|
|
3254
3263
|
sessionExpired: "Your assistant session expired. Reopen it to continue.",
|
|
@@ -3259,7 +3268,7 @@ var DEFAULT_APPEARANCE = {
|
|
|
3259
3268
|
},
|
|
3260
3269
|
presentation: {
|
|
3261
3270
|
panel: {
|
|
3262
|
-
surface: "
|
|
3271
|
+
surface: "solid",
|
|
3263
3272
|
elevation: "soft",
|
|
3264
3273
|
border: "subtle"
|
|
3265
3274
|
},
|
|
@@ -3707,22 +3716,54 @@ function record2(value) {
|
|
|
3707
3716
|
function createInteractionCard(options) {
|
|
3708
3717
|
const card = document.createElement("section");
|
|
3709
3718
|
card.className = "tool-proposal";
|
|
3710
|
-
|
|
3711
|
-
|
|
3712
|
-
|
|
3719
|
+
card.setAttribute("aria-label", options.labels.heading);
|
|
3720
|
+
const eyebrow = document.createElement("span");
|
|
3721
|
+
eyebrow.className = "proposal-eyebrow";
|
|
3722
|
+
eyebrow.textContent = options.labels.heading;
|
|
3723
|
+
const title = document.createElement("h3");
|
|
3724
|
+
title.textContent = options.title ?? humanizeArgumentName(options.tool);
|
|
3725
|
+
card.append(eyebrow, title);
|
|
3726
|
+
if (options.description) {
|
|
3727
|
+
const description = document.createElement("p");
|
|
3728
|
+
description.className = "proposal-description";
|
|
3729
|
+
description.textContent = options.description;
|
|
3730
|
+
card.append(description);
|
|
3731
|
+
}
|
|
3713
3732
|
if (options.arguments && Object.keys(options.arguments).length > 0) {
|
|
3714
|
-
|
|
3733
|
+
const { action, ...businessArguments } = options.arguments;
|
|
3734
|
+
if (Object.keys(businessArguments).length > 0) {
|
|
3735
|
+
card.append(createArgumentList(businessArguments, options.reviewSchema, options.labels));
|
|
3736
|
+
}
|
|
3737
|
+
if (action !== void 0) {
|
|
3738
|
+
const technical = document.createElement("details");
|
|
3739
|
+
technical.className = "proposal-details";
|
|
3740
|
+
const summary = document.createElement("summary");
|
|
3741
|
+
summary.textContent = options.labels.details;
|
|
3742
|
+
const properties = record3(options.reviewSchema?.properties);
|
|
3743
|
+
technical.append(summary);
|
|
3744
|
+
const actionObject = record3(action);
|
|
3745
|
+
if (actionObject) {
|
|
3746
|
+
technical.append(
|
|
3747
|
+
createArgumentList(actionObject, record3(properties?.action), options.labels)
|
|
3748
|
+
);
|
|
3749
|
+
} else {
|
|
3750
|
+
const value = document.createElement("div");
|
|
3751
|
+
appendValue(value, action, record3(properties?.action), options.labels);
|
|
3752
|
+
technical.append(value);
|
|
3753
|
+
}
|
|
3754
|
+
card.append(technical);
|
|
3755
|
+
}
|
|
3715
3756
|
}
|
|
3716
3757
|
const actions = document.createElement("div");
|
|
3717
3758
|
actions.className = "proposal-actions";
|
|
3718
3759
|
const buttons = [];
|
|
3719
3760
|
for (const [labelText, action] of [
|
|
3720
3761
|
[options.labels.accept, "accept"],
|
|
3721
|
-
[options.labels.decline, "decline"]
|
|
3722
|
-
[options.labels.cancel, "cancel"]
|
|
3762
|
+
[options.labels.decline, "decline"]
|
|
3723
3763
|
]) {
|
|
3724
3764
|
const button2 = document.createElement("button");
|
|
3725
3765
|
button2.type = "button";
|
|
3766
|
+
button2.className = `proposal-${action}`;
|
|
3726
3767
|
button2.textContent = labelText;
|
|
3727
3768
|
buttons.push(button2);
|
|
3728
3769
|
button2.addEventListener("click", () => {
|
|
@@ -3736,27 +3777,98 @@ function createInteractionCard(options) {
|
|
|
3736
3777
|
card.append(actions);
|
|
3737
3778
|
return card;
|
|
3738
3779
|
}
|
|
3739
|
-
function
|
|
3740
|
-
const
|
|
3741
|
-
|
|
3780
|
+
function createResultCard(result, label, redactedLabel) {
|
|
3781
|
+
const card = document.createElement("section");
|
|
3782
|
+
card.className = "tool-result";
|
|
3783
|
+
const heading = document.createElement("strong");
|
|
3784
|
+
heading.textContent = label;
|
|
3785
|
+
card.append(heading);
|
|
3786
|
+
const body = document.createElement("div");
|
|
3787
|
+
const labels = {
|
|
3788
|
+
heading: label,
|
|
3789
|
+
accept: "",
|
|
3790
|
+
decline: "",
|
|
3791
|
+
details: "",
|
|
3792
|
+
redacted: redactedLabel
|
|
3793
|
+
};
|
|
3794
|
+
appendValue(body, result, void 0, labels);
|
|
3795
|
+
card.append(body);
|
|
3796
|
+
return card;
|
|
3797
|
+
}
|
|
3798
|
+
function createArgumentList(arguments_, schema, labels) {
|
|
3799
|
+
const list = document.createElement("dl");
|
|
3800
|
+
list.className = "proposal-arguments";
|
|
3801
|
+
const properties = record3(schema?.properties);
|
|
3742
3802
|
for (const [name, value] of Object.entries(arguments_)) {
|
|
3803
|
+
const propertySchema = record3(properties?.[name]);
|
|
3743
3804
|
const term = document.createElement("dt");
|
|
3744
|
-
term.textContent = humanizeArgumentName(name);
|
|
3805
|
+
term.textContent = string2(propertySchema?.title) ?? humanizeArgumentName(name);
|
|
3806
|
+
const help = string2(propertySchema?.description);
|
|
3807
|
+
if (help) {
|
|
3808
|
+
const description2 = document.createElement("small");
|
|
3809
|
+
description2.textContent = help;
|
|
3810
|
+
term.append(description2);
|
|
3811
|
+
}
|
|
3745
3812
|
const description = document.createElement("dd");
|
|
3746
|
-
description
|
|
3747
|
-
|
|
3813
|
+
appendValue(description, value, propertySchema, labels);
|
|
3814
|
+
list.append(term, description);
|
|
3815
|
+
}
|
|
3816
|
+
return list;
|
|
3817
|
+
}
|
|
3818
|
+
function appendValue(parent, value, schema, labels) {
|
|
3819
|
+
if (value === "[REDACTED]") {
|
|
3820
|
+
const hidden = document.createElement("span");
|
|
3821
|
+
hidden.className = "proposal-redacted";
|
|
3822
|
+
hidden.textContent = labels.redacted;
|
|
3823
|
+
parent.append(hidden);
|
|
3824
|
+
return;
|
|
3825
|
+
}
|
|
3826
|
+
if (Array.isArray(value)) {
|
|
3827
|
+
const list = document.createElement("ul");
|
|
3828
|
+
const itemSchema = record3(schema?.items);
|
|
3829
|
+
for (const item of value) {
|
|
3830
|
+
const entry = document.createElement("li");
|
|
3831
|
+
appendValue(entry, item, itemSchema, labels);
|
|
3832
|
+
list.append(entry);
|
|
3833
|
+
}
|
|
3834
|
+
parent.append(list);
|
|
3835
|
+
return;
|
|
3836
|
+
}
|
|
3837
|
+
const objectValue = record3(value);
|
|
3838
|
+
if (objectValue) {
|
|
3839
|
+
parent.append(createArgumentList(objectValue, schema, labels));
|
|
3840
|
+
return;
|
|
3841
|
+
}
|
|
3842
|
+
parent.textContent = formatScalar(value, schema);
|
|
3843
|
+
}
|
|
3844
|
+
function formatScalar(value, schema) {
|
|
3845
|
+
if (value === null || value === void 0 || value === "") return "Not provided";
|
|
3846
|
+
if (typeof value === "boolean") return value ? "Yes" : "No";
|
|
3847
|
+
if (typeof value === "number") return new Intl.NumberFormat().format(value);
|
|
3848
|
+
if (typeof value !== "string") return String(value);
|
|
3849
|
+
if (schema?.format === "date") {
|
|
3850
|
+
const date = /* @__PURE__ */ new Date(`${value}T00:00:00`);
|
|
3851
|
+
if (!Number.isNaN(date.valueOf()))
|
|
3852
|
+
return new Intl.DateTimeFormat(void 0, { dateStyle: "medium" }).format(date);
|
|
3853
|
+
}
|
|
3854
|
+
if (schema?.format === "date-time") {
|
|
3855
|
+
const date = new Date(value);
|
|
3856
|
+
if (!Number.isNaN(date.valueOf()))
|
|
3857
|
+
return new Intl.DateTimeFormat(void 0, { dateStyle: "medium", timeStyle: "short" }).format(
|
|
3858
|
+
date
|
|
3859
|
+
);
|
|
3748
3860
|
}
|
|
3749
|
-
return
|
|
3861
|
+
return value;
|
|
3750
3862
|
}
|
|
3751
3863
|
function humanizeArgumentName(value) {
|
|
3752
3864
|
const words = value.replaceAll(/([a-z0-9])([A-Z])/g, "$1 $2").replaceAll(/[_-]+/g, " ");
|
|
3753
3865
|
return words ? `${words[0]?.toUpperCase() ?? ""}${words.slice(1)}` : value;
|
|
3754
3866
|
}
|
|
3755
|
-
function
|
|
3756
|
-
|
|
3757
|
-
|
|
3758
|
-
|
|
3759
|
-
return
|
|
3867
|
+
function record3(value) {
|
|
3868
|
+
return value !== null && typeof value === "object" && !Array.isArray(value) ? value : void 0;
|
|
3869
|
+
}
|
|
3870
|
+
function string2(value) {
|
|
3871
|
+
return typeof value === "string" && value.length > 0 ? value : void 0;
|
|
3760
3872
|
}
|
|
3761
3873
|
|
|
3762
3874
|
// ../../node_modules/.pnpm/dompurify@3.4.11/node_modules/dompurify/dist/purify.es.mjs
|
|
@@ -6492,8 +6604,11 @@ var AssistantElementEventController = class {
|
|
|
6492
6604
|
if (!this.#streamKind) return;
|
|
6493
6605
|
this.#appendToolProposal(
|
|
6494
6606
|
String(data.id ?? ""),
|
|
6495
|
-
String(data.tool ??
|
|
6496
|
-
isRecord(data.arguments) ? data.arguments : void 0
|
|
6607
|
+
String(data.tool ?? "action"),
|
|
6608
|
+
isRecord(data.arguments) ? data.arguments : void 0,
|
|
6609
|
+
typeof data.title === "string" ? data.title : void 0,
|
|
6610
|
+
"description" in data && typeof data.description === "string" ? data.description : void 0,
|
|
6611
|
+
"reviewSchema" in data && isRecord(data.reviewSchema) ? data.reviewSchema : void 0
|
|
6497
6612
|
);
|
|
6498
6613
|
return;
|
|
6499
6614
|
}
|
|
@@ -6531,7 +6646,13 @@ var AssistantElementEventController = class {
|
|
|
6531
6646
|
}
|
|
6532
6647
|
#finishInteraction(id, action) {
|
|
6533
6648
|
if (this.#completedTool && !this.#assistantBody) {
|
|
6534
|
-
this.#host.
|
|
6649
|
+
const messages = this.#host.messages();
|
|
6650
|
+
if (messages) {
|
|
6651
|
+
const labels = this.#host.labels();
|
|
6652
|
+
messages.append(
|
|
6653
|
+
createResultCard(this.#completedTool.result, labels.completed, labels.redacted)
|
|
6654
|
+
);
|
|
6655
|
+
}
|
|
6535
6656
|
}
|
|
6536
6657
|
this.#proposalCards.get(id)?.remove();
|
|
6537
6658
|
this.#proposalCards.delete(id);
|
|
@@ -6546,18 +6667,23 @@ var AssistantElementEventController = class {
|
|
|
6546
6667
|
this.#clearStream();
|
|
6547
6668
|
this.#completedTool = void 0;
|
|
6548
6669
|
}
|
|
6549
|
-
#appendToolProposal(id, tool, arguments_) {
|
|
6670
|
+
#appendToolProposal(id, tool, arguments_, title, description, reviewSchema) {
|
|
6550
6671
|
const messages = this.#host.messages();
|
|
6551
6672
|
if (!messages || !id) return;
|
|
6552
6673
|
this.#proposalCards.get(id)?.remove();
|
|
6553
6674
|
const labels = this.#host.labels();
|
|
6554
6675
|
const card = createInteractionCard({
|
|
6555
6676
|
tool,
|
|
6677
|
+
...title ? { title } : {},
|
|
6678
|
+
...description ? { description } : {},
|
|
6556
6679
|
...arguments_ ? { arguments: arguments_ } : {},
|
|
6680
|
+
...reviewSchema ? { reviewSchema } : {},
|
|
6557
6681
|
labels: {
|
|
6682
|
+
heading: labels.confirmationHeading,
|
|
6558
6683
|
accept: labels.confirm,
|
|
6559
|
-
decline:
|
|
6560
|
-
|
|
6684
|
+
decline: labels.decline,
|
|
6685
|
+
details: labels.additionalDetails,
|
|
6686
|
+
redacted: labels.redacted
|
|
6561
6687
|
},
|
|
6562
6688
|
respond: (action) => this.#host.respond(id, { action })
|
|
6563
6689
|
});
|
|
@@ -6565,7 +6691,9 @@ var AssistantElementEventController = class {
|
|
|
6565
6691
|
this.#proposalCards.set(id, card);
|
|
6566
6692
|
this.#revealLatestMessage(messages);
|
|
6567
6693
|
this.#host.element.dispatchEvent(
|
|
6568
|
-
new CustomEvent("assistant-tool-proposed", {
|
|
6694
|
+
new CustomEvent("assistant-tool-proposed", {
|
|
6695
|
+
detail: { id, tool, title, description, arguments: arguments_, reviewSchema }
|
|
6696
|
+
})
|
|
6569
6697
|
);
|
|
6570
6698
|
}
|
|
6571
6699
|
#appendInputRequest(id, message, requestedSchema) {
|
|
@@ -6616,7 +6744,14 @@ var AssistantElementEventController = class {
|
|
|
6616
6744
|
}
|
|
6617
6745
|
#revealLatestMessage(messages) {
|
|
6618
6746
|
this.#host.element.setAttribute("has-messages", "");
|
|
6619
|
-
messages.scrollTop
|
|
6747
|
+
const distance = messages.scrollHeight - messages.scrollTop - messages.clientHeight;
|
|
6748
|
+
const control = this.#host.element.shadowRoot?.querySelector(".new-messages");
|
|
6749
|
+
if (distance <= 160) {
|
|
6750
|
+
messages.scrollTop = messages.scrollHeight;
|
|
6751
|
+
if (control) control.hidden = true;
|
|
6752
|
+
} else if (control) {
|
|
6753
|
+
control.hidden = false;
|
|
6754
|
+
}
|
|
6620
6755
|
}
|
|
6621
6756
|
};
|
|
6622
6757
|
function isRecord(value) {
|
|
@@ -6651,17 +6786,18 @@ var ASSISTANT_ELEMENT_STYLES = `<style>
|
|
|
6651
6786
|
:host([data-mode="floating"][data-position="bottom-left"]) { right: auto; left: 20px; }
|
|
6652
6787
|
button { font: inherit; }
|
|
6653
6788
|
button, textarea, input, select { -webkit-tap-highlight-color: transparent; }
|
|
6654
|
-
.launcher { display: grid; place-items: center; width: 48px; height: 48px; border: 1px solid var(--ns-assistant-divider, var(--ns-assistant-default-divider)); border-radius: 999px; color: var(--ns-assistant-text, var(--ns-assistant-default-text)); background:
|
|
6789
|
+
.launcher { display: grid; place-items: center; width: 48px; height: 48px; border: 1px solid var(--ns-assistant-launcher-border, var(--ns-assistant-divider, var(--ns-assistant-default-divider))); border-radius: 999px; color: var(--ns-assistant-launcher-text, var(--ns-assistant-text, var(--ns-assistant-default-text))); background: var(--ns-assistant-launcher, var(--ns-assistant-panel, var(--ns-assistant-default-panel))); box-shadow: 0 8px 28px rgba(0,0,0,.14); cursor: pointer; transition: transform .24s cubic-bezier(.25,1,.5,1), box-shadow .2s ease; }
|
|
6655
6790
|
.launcher:hover { transform: translateY(-2px) scale(1.03); box-shadow: 0 8px 26px rgba(0,0,0,.16); }
|
|
6656
6791
|
.launcher img { width: 28px; height: 28px; border-radius: 50%; object-fit: contain; }
|
|
6657
|
-
.panel { display: none; flex-direction: column; width: min(var(--ns-assistant-panel-width, var(--ns-assistant-default-panel-width)), calc(100vw - 40px)); min-height: var(--ns-assistant-min-height, var(--ns-assistant-default-min-height)); max-height: min(var(--ns-assistant-max-height, var(--ns-assistant-default-max-height)), calc(100vh - 40px)); overflow: hidden; color: var(--ns-assistant-text, var(--ns-assistant-default-text)); background:
|
|
6792
|
+
.panel { display: none; flex-direction: column; width: min(var(--ns-assistant-panel-width, var(--ns-assistant-default-panel-width)), calc(100vw - 40px)); min-height: var(--ns-assistant-min-height, var(--ns-assistant-default-min-height)); max-height: min(var(--ns-assistant-max-height, var(--ns-assistant-default-max-height)), calc(100vh - 40px)); overflow: hidden; color: var(--ns-assistant-panel-text, var(--ns-assistant-text, var(--ns-assistant-default-text))); background: var(--ns-assistant-panel, var(--ns-assistant-default-panel)); border: 1px solid var(--ns-assistant-panel-border, var(--ns-assistant-divider, var(--ns-assistant-default-divider))); border-radius: var(--ns-assistant-panel-radius, var(--ns-assistant-default-panel-radius)); box-shadow: var(--ns-assistant-shadow, var(--ns-assistant-default-shadow)); transform-origin: bottom right; animation: halo-panel-in .28s cubic-bezier(.23,1,.32,1) both; }
|
|
6658
6793
|
:host([open]) .panel { display: flex; }
|
|
6794
|
+
.panel { position: relative; }
|
|
6659
6795
|
:host([open]) .launcher { display: none; }
|
|
6660
|
-
header { display: flex; flex: 0 0 auto; gap: 10px; align-items: center; min-height: 64px; padding:
|
|
6796
|
+
header { display: flex; flex: 0 0 auto; gap: 10px; align-items: center; min-height: 64px; padding: 12px 18px; color: var(--ns-assistant-header-text, inherit); background: var(--ns-assistant-header, transparent); border-bottom: 1px solid var(--ns-assistant-header-border, var(--ns-assistant-divider, var(--ns-assistant-default-divider))); }
|
|
6661
6797
|
header strong { flex: 1; font-size: 16px; font-weight: 600; letter-spacing: -.01em; }
|
|
6662
6798
|
.brand-logo { display: block; max-width: 120px; max-height: 28px; object-fit: contain; }
|
|
6663
6799
|
.close, .send { display: grid; place-items: center; border: 0; border-radius: 999px; cursor: pointer; }
|
|
6664
|
-
.close { width:
|
|
6800
|
+
.close { width: 44px; height: 44px; padding: 0; color: var(--ns-assistant-muted-text, var(--ns-assistant-default-muted-text)); background: transparent; font-size: 24px; font-weight: 300; line-height: 1; transition: background .15s ease, color .15s ease; }
|
|
6665
6801
|
.close:hover { color: var(--ns-assistant-text, var(--ns-assistant-default-text)); background: var(--ns-assistant-elevated, var(--ns-assistant-default-elevated)); }
|
|
6666
6802
|
.welcome { flex: 0 0 auto; padding: 30px 22px 18px; }
|
|
6667
6803
|
.welcome h2 { margin: 0; font-size: 1.42em; line-height: 1.25; letter-spacing: -.025em; }
|
|
@@ -6669,16 +6805,24 @@ var ASSISTANT_ELEMENT_STYLES = `<style>
|
|
|
6669
6805
|
:host([has-messages]) .welcome, :host([has-messages]) .suggested-prompts { display: none; }
|
|
6670
6806
|
.suggested-prompts { display: flex; flex: 0 0 auto; flex-wrap: wrap; gap: 8px; padding: 0 20px 16px; }
|
|
6671
6807
|
.suggested-prompts:empty { display: none; }
|
|
6672
|
-
.suggested-prompts button { padding:
|
|
6808
|
+
.suggested-prompts button { min-height: 44px; padding: 9px 14px; color: var(--ns-assistant-suggestion-text, var(--ns-assistant-muted-text, var(--ns-assistant-default-muted-text))); background: var(--ns-assistant-suggestion, transparent); border: 1px solid var(--ns-assistant-suggestion-border, var(--ns-assistant-divider, var(--ns-assistant-default-divider))); border-radius: 12px; cursor: pointer; transition: background .2s ease, color .2s ease, transform .2s ease; }
|
|
6673
6809
|
.suggested-prompts button:hover { color: var(--ns-assistant-text, var(--ns-assistant-default-text)); background: var(--ns-assistant-elevated, var(--ns-assistant-default-elevated)); transform: translateY(-1px); }
|
|
6674
|
-
.messages { flex: 1 1 auto; min-height: 0; padding: 18px 20px; overflow-y: auto; overscroll-behavior: contain; scroll-behavior: smooth; }
|
|
6810
|
+
.messages { flex: 1 1 auto; min-height: 0; padding: 18px 20px; overflow-y: auto; background: var(--ns-assistant-canvas, transparent); overscroll-behavior: contain; scroll-behavior: smooth; }
|
|
6675
6811
|
.messages::-webkit-scrollbar { width: 6px; }
|
|
6676
6812
|
.messages::-webkit-scrollbar-thumb { background: var(--ns-assistant-divider, var(--ns-assistant-default-divider)); border-radius: 999px; }
|
|
6677
6813
|
.message { width: fit-content; max-width: 88%; margin: 0 0 14px; padding: 0; border-radius: var(--ns-assistant-card-radius, var(--ns-assistant-default-card-radius)); background: transparent; white-space: pre-wrap; animation: halo-message-in .2s ease both; }
|
|
6678
6814
|
.message > span, .message > .markdown { overflow-wrap: anywhere; }
|
|
6679
6815
|
.message .avatar { float: left; width: 24px; height: 24px; margin-right: 9px; border-radius: 50%; object-fit: cover; }
|
|
6680
6816
|
.message time { display: block; margin-top: 4px; color: var(--ns-assistant-muted-text, var(--ns-assistant-default-muted-text)); font-size: .75em; line-height: 1.2; }
|
|
6681
|
-
.message
|
|
6817
|
+
.message-copy { min-width: 44px; min-height: 32px; margin-top: 6px; padding: 4px 8px; color: var(--ns-assistant-muted-text, var(--ns-assistant-default-muted-text)); background: transparent; border: 0; border-radius: 8px; cursor: pointer; font-size: .78em; opacity: 0; transition: opacity .15s ease, background .15s ease; }
|
|
6818
|
+
.message:hover .message-copy, .message:focus-within .message-copy { opacity: 1; }
|
|
6819
|
+
.conversation-status { margin: 4px auto 14px; color: var(--ns-assistant-muted-text, var(--ns-assistant-default-muted-text)); font-size: .82em; text-align: center; }
|
|
6820
|
+
.conversation-error { display: flex; gap: 12px; align-items: center; justify-content: space-between; margin: 8px 0 16px; padding: 12px 14px; color: var(--ns-assistant-danger, var(--ns-assistant-default-danger)); border: 1px solid color-mix(in srgb, var(--ns-assistant-danger, var(--ns-assistant-default-danger)) 28%, transparent); border-radius: 12px; background: color-mix(in srgb, var(--ns-assistant-danger, var(--ns-assistant-default-danger)) 7%, transparent); }
|
|
6821
|
+
.conversation-error p { margin: 0; }
|
|
6822
|
+
.conversation-error button { min-height: 44px; padding: 8px 12px; color: var(--ns-assistant-secondary-button-text, inherit); background: var(--ns-assistant-secondary-button, var(--ns-assistant-elevated, var(--ns-assistant-default-elevated))); border: 1px solid var(--ns-assistant-secondary-button-border, var(--ns-assistant-divider, var(--ns-assistant-default-divider))); border-radius: 10px; cursor: pointer; font-weight: 600; }
|
|
6823
|
+
.new-messages { position: absolute; left: 50%; bottom: 82px; z-index: 1; min-height: 36px; padding: 7px 12px; color: var(--ns-assistant-secondary-button-text, inherit); background: var(--ns-assistant-secondary-button, var(--ns-assistant-elevated, var(--ns-assistant-default-elevated))); border: 1px solid var(--ns-assistant-secondary-button-border, var(--ns-assistant-divider, var(--ns-assistant-default-divider))); border-radius: 999px; box-shadow: 0 4px 18px rgba(0,0,0,.12); transform: translateX(-50%); cursor: pointer; }
|
|
6824
|
+
.message.assistant { color: var(--ns-assistant-assistant-message-text, inherit); background: var(--ns-assistant-assistant-message, transparent); border: 1px solid var(--ns-assistant-assistant-message-border, transparent); }
|
|
6825
|
+
.message.user { display: grid; justify-items: start; gap: 3px; margin-left: auto; padding: 10px 16px 8px; color: var(--ns-assistant-user-message-text, var(--ns-assistant-text, var(--ns-assistant-default-text))); background: var(--ns-assistant-user-message, var(--ns-assistant-elevated, var(--ns-assistant-default-elevated))); border: 1px solid var(--ns-assistant-user-message-border, transparent); font-size: .94em; }
|
|
6682
6826
|
.message.user time { margin-top: 0; }
|
|
6683
6827
|
.markdown { white-space: normal; }
|
|
6684
6828
|
.markdown p { margin: 0 0 8px; }
|
|
@@ -6687,8 +6831,8 @@ var ASSISTANT_ELEMENT_STYLES = `<style>
|
|
|
6687
6831
|
.markdown em, .markdown i { font-style: italic; }
|
|
6688
6832
|
.markdown a { color: var(--ns-assistant-link, var(--ns-assistant-default-link)); text-decoration: underline; text-underline-offset: 2px; }
|
|
6689
6833
|
.markdown a:hover { opacity: .8; }
|
|
6690
|
-
.markdown code { padding: 2px 6px; border-radius: 5px; background: var(--ns-assistant-code, var(--ns-assistant-default-code)); font-family: var(--ns-assistant-mono-font-family, var(--ns-assistant-default-mono-font-family)); font-size: .87em; }
|
|
6691
|
-
.markdown pre { margin: 10px 0; padding: 12px 14px; overflow-x: auto; border: 1px solid var(--ns-assistant-divider, var(--ns-assistant-default-divider)); border-radius: 10px; background: var(--ns-assistant-code, var(--ns-assistant-default-code)); white-space: pre; }
|
|
6834
|
+
.markdown code { padding: 2px 6px; color: var(--ns-assistant-code-text, inherit); border: 1px solid var(--ns-assistant-code-border, transparent); border-radius: 5px; background: var(--ns-assistant-code, var(--ns-assistant-default-code)); font-family: var(--ns-assistant-mono-font-family, var(--ns-assistant-default-mono-font-family)); font-size: .87em; }
|
|
6835
|
+
.markdown pre { margin: 10px 0; padding: 12px 14px; overflow-x: auto; color: var(--ns-assistant-code-text, inherit); border: 1px solid var(--ns-assistant-code-border, var(--ns-assistant-divider, var(--ns-assistant-default-divider))); border-radius: 10px; background: var(--ns-assistant-code, var(--ns-assistant-default-code)); white-space: pre; }
|
|
6692
6836
|
.markdown pre code { padding: 0; background: transparent; font-size: .86em; }
|
|
6693
6837
|
.markdown ul, .markdown ol { margin: 8px 0; padding-left: 22px; }
|
|
6694
6838
|
.markdown li { margin: 3px 0; }
|
|
@@ -6697,15 +6841,25 @@ var ASSISTANT_ELEMENT_STYLES = `<style>
|
|
|
6697
6841
|
.markdown h1:first-child, .markdown h2:first-child, .markdown h3:first-child { margin-top: 0; }
|
|
6698
6842
|
.markdown h1 { font-size: 1.3em; } .markdown h2 { font-size: 1.18em; } .markdown h3 { font-size: 1.08em; }
|
|
6699
6843
|
.message.thinking > span { display: inline-block; color: transparent; background: linear-gradient(90deg, var(--ns-assistant-muted-text, var(--ns-assistant-default-muted-text)) 25%, var(--ns-assistant-text, var(--ns-assistant-default-text)) 50%, var(--ns-assistant-muted-text, var(--ns-assistant-default-muted-text)) 75%); background-size: 300% 100%; background-clip: text; -webkit-background-clip: text; font-style: italic; font-weight: 500; animation: halo-shimmer 2s linear infinite; }
|
|
6700
|
-
.tool-proposal { display: grid; gap:
|
|
6701
|
-
.
|
|
6702
|
-
.proposal
|
|
6844
|
+
.tool-proposal { display: grid; gap: 12px; align-items: start; margin: 8px 0 16px; padding: 18px; color: var(--ns-assistant-confirmation-text, inherit); border: 1px solid var(--ns-assistant-confirmation-border, var(--ns-assistant-divider, var(--ns-assistant-default-divider))); border-radius: var(--ns-assistant-card-radius, 14px); background: var(--ns-assistant-confirmation, var(--ns-assistant-input, var(--ns-assistant-default-input))); animation: halo-message-in .2s ease both; }
|
|
6845
|
+
.proposal-eyebrow { color: var(--ns-assistant-muted-text, var(--ns-assistant-default-muted-text)); font-size: .75em; font-weight: 700; letter-spacing: .06em; text-transform: uppercase; }
|
|
6846
|
+
.tool-proposal h3 { margin: -4px 0 0; font-size: 1.08em; line-height: 1.3; letter-spacing: -.01em; }
|
|
6847
|
+
.proposal-description { margin: -4px 0 0; color: var(--ns-assistant-muted-text, var(--ns-assistant-default-muted-text)); }
|
|
6848
|
+
.proposal-arguments { display: grid; grid-template-columns: minmax(100px, .7fr) minmax(0, 1.3fr); gap: 8px 14px; margin: 0; padding: 12px 0; border-block: 1px solid var(--ns-assistant-divider, var(--ns-assistant-default-divider)); font-size: .9em; }
|
|
6849
|
+
.proposal-arguments .proposal-arguments { grid-column: 1 / -1; padding: 4px 0 0; border: 0; }
|
|
6703
6850
|
.proposal-arguments dt { color: var(--ns-assistant-muted-text, var(--ns-assistant-default-muted-text)); }
|
|
6851
|
+
.proposal-arguments dt small { display: block; margin-top: 2px; font-size: .85em; line-height: 1.35; }
|
|
6704
6852
|
.proposal-arguments dd { margin: 0; overflow-wrap: anywhere; }
|
|
6853
|
+
.proposal-details { color: var(--ns-assistant-muted-text, var(--ns-assistant-default-muted-text)); font-size: .86em; }
|
|
6854
|
+
.proposal-details summary { min-height: 36px; padding: 8px 0; cursor: pointer; font-weight: 600; }
|
|
6855
|
+
.proposal-details .proposal-arguments { margin-top: 4px; }
|
|
6705
6856
|
.proposal-actions { display: flex; flex-wrap: wrap; gap: 8px; justify-content: end; }
|
|
6706
|
-
.tool-proposal button { padding:
|
|
6707
|
-
.tool-proposal
|
|
6857
|
+
.tool-proposal button { min-height: 44px; padding: 9px 14px; border: 1px solid var(--ns-assistant-secondary-button-border, transparent); border-radius: var(--ns-assistant-button-radius, 12px); color: var(--ns-assistant-secondary-button-text, var(--ns-assistant-text, var(--ns-assistant-default-text))); background: var(--ns-assistant-secondary-button, var(--ns-assistant-elevated, var(--ns-assistant-default-elevated))); cursor: pointer; font-weight: 600; }
|
|
6858
|
+
.tool-proposal .proposal-accept { color: var(--ns-assistant-primary-button-text, var(--ns-assistant-accent-text, var(--ns-assistant-default-accent-text))); background: var(--ns-assistant-primary-button, var(--ns-assistant-accent, var(--ns-assistant-default-accent))); border-color: var(--ns-assistant-primary-button-border, transparent); }
|
|
6708
6859
|
.tool-proposal button:disabled { opacity: .55; cursor: not-allowed; }
|
|
6860
|
+
.tool-proposal button { min-height: 45px; }
|
|
6861
|
+
.tool-result { display: grid; gap: 10px; margin: 8px 0 16px; padding: 16px; border: 1px solid var(--ns-assistant-divider, var(--ns-assistant-default-divider)); border-radius: var(--ns-assistant-card-radius, 14px); background: var(--ns-assistant-assistant-message, var(--ns-assistant-elevated, var(--ns-assistant-default-elevated))); }
|
|
6862
|
+
.tool-result > strong { color: var(--ns-assistant-success, var(--ns-assistant-default-success)); }
|
|
6709
6863
|
.input-request form { display: grid; gap: 10px; align-items: stretch; min-height: 0; margin: 0; padding: 0; border: 0; border-radius: 0; background: transparent; box-shadow: none; }
|
|
6710
6864
|
.input-request form:focus-within { box-shadow: none; }
|
|
6711
6865
|
.input-request label { display: grid; gap: 4px; color: var(--ns-assistant-muted-text, var(--ns-assistant-default-muted-text)); font-size: .9em; }
|
|
@@ -6714,20 +6868,21 @@ var ASSISTANT_ELEMENT_STYLES = `<style>
|
|
|
6714
6868
|
.input-request input[type="checkbox"] { width: auto; justify-self: start; accent-color: var(--ns-assistant-accent, var(--ns-assistant-default-accent)); }
|
|
6715
6869
|
.input-request input:focus-visible, .input-request select:focus-visible { border-color: var(--ns-assistant-focus, var(--ns-assistant-default-focus)); box-shadow: 0 0 0 2px var(--ns-assistant-focus, var(--ns-assistant-default-focus)); }
|
|
6716
6870
|
.input-request .proposal-actions { margin-top: 2px; }
|
|
6717
|
-
.noodle-app-card { position: relative; display: grid; gap: 8px; width: 100%; margin: 4px 0 16px; overflow: hidden; border: 1px solid var(--ns-assistant-divider, var(--ns-assistant-default-divider)); border-radius: var(--ns-assistant-card-radius, var(--ns-assistant-default-card-radius)); background: var(--ns-assistant-elevated, var(--ns-assistant-default-elevated)); }
|
|
6871
|
+
.noodle-app-card { position: relative; display: grid; gap: 8px; width: 100%; margin: 4px 0 16px; overflow: hidden; color: var(--ns-assistant-app-text, inherit); border: 1px solid var(--ns-assistant-app-border, var(--ns-assistant-divider, var(--ns-assistant-default-divider))); border-radius: var(--ns-assistant-card-radius, var(--ns-assistant-default-card-radius)); background: var(--ns-assistant-app, var(--ns-assistant-elevated, var(--ns-assistant-default-elevated))); }
|
|
6718
6872
|
.noodle-app-title { padding: 10px 12px 0; font-size: .86em; font-weight: 650; }
|
|
6719
6873
|
.noodle-app-frame { display: block; width: 100%; min-height: 120px; border: 0; background: transparent; }
|
|
6720
6874
|
.noodle-app-card[data-fullscreen] { position: fixed; inset: 0; z-index: 2; margin: 0; border-radius: 0; background: var(--ns-assistant-panel, var(--ns-assistant-default-panel)); }
|
|
6721
6875
|
.noodle-app-card[data-fullscreen] .noodle-app-frame { height: 100% !important; }
|
|
6722
|
-
form { display: flex; flex: 0 0 auto; gap: 8px; align-items: center; min-height:
|
|
6876
|
+
form { display: flex; flex: 0 0 auto; gap: 8px; align-items: center; min-height: 56px; margin: 8px 16px 16px; padding: 6px 6px 6px 16px; color: var(--ns-assistant-composer-text, inherit); border: 1px solid var(--ns-assistant-composer-border, var(--ns-assistant-divider, var(--ns-assistant-default-divider))); border-radius: var(--ns-assistant-input-radius, 14px); background: var(--ns-assistant-composer, var(--ns-assistant-input, var(--ns-assistant-default-input))); box-shadow: 0 1px 2px rgba(0,0,0,.04); transition: border-color .15s ease, box-shadow .15s ease; }
|
|
6723
6877
|
form:focus-within { box-shadow: inset 0 0 0 1px var(--ns-assistant-focus, var(--ns-assistant-default-focus)), 0 0 0 2px var(--ns-assistant-focus, var(--ns-assistant-default-focus)); }
|
|
6724
6878
|
textarea { flex: 1; min-height: 24px; max-height: 120px; resize: none; padding: 0; color: var(--ns-assistant-text, var(--ns-assistant-default-text)); background: transparent; border: 0; border-radius: 0; outline: 0; box-shadow: none; appearance: none; -webkit-appearance: none; font: inherit; font-size: 16px; line-height: 24px; }
|
|
6725
6879
|
textarea::placeholder { color: var(--ns-assistant-muted-text, var(--ns-assistant-default-muted-text)); }
|
|
6726
6880
|
textarea:focus, textarea:focus-visible { outline: none; box-shadow: none; }
|
|
6727
6881
|
button:focus-visible { outline: 3px solid var(--ns-assistant-focus, var(--ns-assistant-default-focus)); outline-offset: 2px; }
|
|
6728
|
-
.send { position: relative; display: block; width:
|
|
6729
|
-
.send::before { content: ''; position: absolute; top: 50%; left: 50%; width:
|
|
6882
|
+
.send { position: relative; display: block; width: 44px; height: 44px; flex: 0 0 44px; padding: 0; overflow: hidden; color: transparent; background: var(--ns-assistant-primary-button, var(--ns-assistant-accent, var(--ns-assistant-default-accent))); font-size: 0; line-height: 0; transition: transform .15s ease, background .15s ease; }
|
|
6883
|
+
.send::before { content: ''; position: absolute; top: 50%; left: 50%; width: 17px; height: 17px; background: var(--ns-assistant-primary-button-text, var(--ns-assistant-accent-text, var(--ns-assistant-default-accent-text))); transform: translate(-50%, -50%); -webkit-mask: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24'%3E%3Cpath d='M12 19V5M5 12l7-7 7 7' fill='none' stroke='black' stroke-width='2.25' stroke-linecap='round' stroke-linejoin='round'/%3E%3C/svg%3E") center / contain no-repeat; mask: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24'%3E%3Cpath d='M12 19V5M5 12l7-7 7 7' fill='none' stroke='black' stroke-width='2.25' stroke-linecap='round' stroke-linejoin='round'/%3E%3C/svg%3E") center / contain no-repeat; }
|
|
6730
6884
|
.send:hover { transform: scale(1.05); background: var(--ns-assistant-hover, var(--ns-assistant-default-hover)); }
|
|
6885
|
+
:host([busy]) .send::before { width: 13px; height: 13px; border-radius: 3px; -webkit-mask: none; mask: none; }
|
|
6731
6886
|
.send:disabled, textarea:disabled { opacity: .55; cursor: not-allowed; }
|
|
6732
6887
|
.legal { display: flex; gap: 12px; justify-content: center; padding: 0 12px 9px; font-size: .75em; }
|
|
6733
6888
|
.legal:empty { display: none; }
|
|
@@ -6740,9 +6895,107 @@ var ASSISTANT_ELEMENT_STYLES = `<style>
|
|
|
6740
6895
|
@media (max-width: 640px) { :host([mobile-fullscreen][open]) { inset: 0; } :host([mobile-fullscreen][open]) .panel { width: 100vw; min-height: 100vh; max-height: 100vh; border: 0; border-radius: 0; } }
|
|
6741
6896
|
@media (prefers-reduced-motion: reduce) { *, *::before, *::after { transition-duration: .01ms !important; animation-duration: .01ms !important; } .messages { scroll-behavior: auto; } }
|
|
6742
6897
|
@media (forced-colors: active) { .message.thinking > span { color: CanvasText; background: none; } }
|
|
6898
|
+
@media (hover: none) { .message-copy { opacity: 1; } }
|
|
6743
6899
|
@media (max-width: 560px) { :host([data-mode="floating"]) { inset: auto 12px 12px; } :host([open]) .panel { width: calc(100vw - 24px); max-height: calc(100vh - 24px); } }
|
|
6744
6900
|
</style>`;
|
|
6745
6901
|
|
|
6902
|
+
// src/host-appearance.ts
|
|
6903
|
+
var ROLE_VARIABLES = {
|
|
6904
|
+
canvas: "--ns-assistant-canvas",
|
|
6905
|
+
text: "--ns-assistant-text",
|
|
6906
|
+
mutedText: "--ns-assistant-muted-text",
|
|
6907
|
+
link: "--ns-assistant-link",
|
|
6908
|
+
focus: "--ns-assistant-focus",
|
|
6909
|
+
success: "--ns-assistant-success",
|
|
6910
|
+
warning: "--ns-assistant-warning",
|
|
6911
|
+
danger: "--ns-assistant-danger"
|
|
6912
|
+
};
|
|
6913
|
+
var SURFACE_VARIABLES = {
|
|
6914
|
+
panel: "--ns-assistant-panel",
|
|
6915
|
+
header: "--ns-assistant-header",
|
|
6916
|
+
assistantMessage: "--ns-assistant-assistant-message",
|
|
6917
|
+
userMessage: "--ns-assistant-user-message",
|
|
6918
|
+
composer: "--ns-assistant-composer",
|
|
6919
|
+
suggestion: "--ns-assistant-suggestion",
|
|
6920
|
+
confirmation: "--ns-assistant-confirmation",
|
|
6921
|
+
primaryButton: "--ns-assistant-primary-button",
|
|
6922
|
+
secondaryButton: "--ns-assistant-secondary-button",
|
|
6923
|
+
launcher: "--ns-assistant-launcher",
|
|
6924
|
+
code: "--ns-assistant-code",
|
|
6925
|
+
app: "--ns-assistant-app"
|
|
6926
|
+
};
|
|
6927
|
+
var ASSISTANT_APPEARANCE_VARIABLES = [
|
|
6928
|
+
...Object.values(ROLE_VARIABLES),
|
|
6929
|
+
...Object.values(SURFACE_VARIABLES).flatMap((name) => [name, `${name}-text`, `${name}-border`])
|
|
6930
|
+
];
|
|
6931
|
+
function applyHostAppearance(style, appearance, theme, previous = /* @__PURE__ */ new Map()) {
|
|
6932
|
+
for (const [variable, original] of previous) {
|
|
6933
|
+
if (original.value) style.setProperty(variable, original.value, original.priority);
|
|
6934
|
+
else style.removeProperty(variable);
|
|
6935
|
+
}
|
|
6936
|
+
previous.clear();
|
|
6937
|
+
const selected = appearance?.[theme];
|
|
6938
|
+
if (!selected) return [];
|
|
6939
|
+
for (const [role, variable] of Object.entries(ROLE_VARIABLES)) {
|
|
6940
|
+
const value = selected[role];
|
|
6941
|
+
if (typeof value === "string") setManagedProperty(style, previous, variable, value);
|
|
6942
|
+
}
|
|
6943
|
+
for (const [role, variable] of Object.entries(SURFACE_VARIABLES)) {
|
|
6944
|
+
const value = selected[role];
|
|
6945
|
+
if (!value || typeof value !== "object") continue;
|
|
6946
|
+
if (value.surface) setManagedProperty(style, previous, variable, value.surface);
|
|
6947
|
+
if (value.text) setManagedProperty(style, previous, `${variable}-text`, value.text);
|
|
6948
|
+
if (value.border) setManagedProperty(style, previous, `${variable}-border`, value.border);
|
|
6949
|
+
}
|
|
6950
|
+
return contrastWarnings(selected, theme);
|
|
6951
|
+
}
|
|
6952
|
+
function setManagedProperty(style, previous, variable, value) {
|
|
6953
|
+
previous.set(variable, {
|
|
6954
|
+
value: style.getPropertyValue(variable),
|
|
6955
|
+
priority: style.getPropertyPriority(variable)
|
|
6956
|
+
});
|
|
6957
|
+
style.setProperty(variable, value);
|
|
6958
|
+
}
|
|
6959
|
+
function contrastWarnings(theme, mode) {
|
|
6960
|
+
const warnings = [];
|
|
6961
|
+
const pairs = [
|
|
6962
|
+
["panel", theme.panel?.text ?? theme.text, theme.panel?.surface ?? theme.canvas],
|
|
6963
|
+
["userMessage", theme.userMessage?.text ?? theme.text, theme.userMessage?.surface],
|
|
6964
|
+
["composer", theme.composer?.text ?? theme.text, theme.composer?.surface],
|
|
6965
|
+
["confirmation", theme.confirmation?.text ?? theme.text, theme.confirmation?.surface],
|
|
6966
|
+
["primaryButton", theme.primaryButton?.text, theme.primaryButton?.surface]
|
|
6967
|
+
];
|
|
6968
|
+
for (const [role, foreground, background] of pairs) {
|
|
6969
|
+
if (!foreground || !background) continue;
|
|
6970
|
+
const ratio = contrastRatio2(foreground, background);
|
|
6971
|
+
if (ratio >= 4.5) continue;
|
|
6972
|
+
warnings.push({
|
|
6973
|
+
code: "low_contrast",
|
|
6974
|
+
theme: mode,
|
|
6975
|
+
role,
|
|
6976
|
+
foreground,
|
|
6977
|
+
background,
|
|
6978
|
+
contrastRatio: Math.round(ratio * 100) / 100,
|
|
6979
|
+
recommendedRatio: 4.5
|
|
6980
|
+
});
|
|
6981
|
+
}
|
|
6982
|
+
return warnings;
|
|
6983
|
+
}
|
|
6984
|
+
function contrastRatio2(first, second) {
|
|
6985
|
+
const lighter = Math.max(luminance(first), luminance(second));
|
|
6986
|
+
const darker = Math.min(luminance(first), luminance(second));
|
|
6987
|
+
return (lighter + 0.05) / (darker + 0.05);
|
|
6988
|
+
}
|
|
6989
|
+
function luminance(color) {
|
|
6990
|
+
const match = /^#([0-9a-f]{2})([0-9a-f]{2})([0-9a-f]{2})$/i.exec(color);
|
|
6991
|
+
if (!match) return 1;
|
|
6992
|
+
const values = match.slice(1).map((value) => {
|
|
6993
|
+
const channel = Number.parseInt(value, 16) / 255;
|
|
6994
|
+
return channel <= 0.04045 ? channel / 12.92 : ((channel + 0.055) / 1.055) ** 2.4;
|
|
6995
|
+
});
|
|
6996
|
+
return 0.2126 * (values[0] ?? 0) + 0.7152 * (values[1] ?? 0) + 0.0722 * (values[2] ?? 0);
|
|
6997
|
+
}
|
|
6998
|
+
|
|
6746
6999
|
// src/presentation.ts
|
|
6747
7000
|
function syncAssistantPresentation(host, root, appearance, mode, sessionState) {
|
|
6748
7001
|
const presentation = appearance.presentation;
|
|
@@ -6915,6 +7168,35 @@ function replaceFallback(root, slotName, nodes) {
|
|
|
6915
7168
|
slot?.replaceChildren(...nodes);
|
|
6916
7169
|
}
|
|
6917
7170
|
|
|
7171
|
+
// src/element-theme.ts
|
|
7172
|
+
function applyAssistantElementTheme(input) {
|
|
7173
|
+
const { host, root, appearance, mode } = input;
|
|
7174
|
+
host.setAttribute("data-theme", mode);
|
|
7175
|
+
for (const [name, value] of Object.entries(appearance.theme[mode])) {
|
|
7176
|
+
host.style.setProperty(`--ns-assistant-default-${camelToKebab(name)}`, tokenValue(name, value));
|
|
7177
|
+
}
|
|
7178
|
+
const warnings = applyHostAppearance(host.style, input.hostAppearance, mode, input.styleSnapshot);
|
|
7179
|
+
host.style.setProperty("--ns-assistant-default-panel-width", `${appearance.layout.panelWidth}px`);
|
|
7180
|
+
host.style.setProperty(
|
|
7181
|
+
"--ns-assistant-default-min-height",
|
|
7182
|
+
`${appearance.layout.panelMinHeight}px`
|
|
7183
|
+
);
|
|
7184
|
+
host.style.setProperty(
|
|
7185
|
+
"--ns-assistant-default-max-height",
|
|
7186
|
+
`${appearance.layout.panelMaxHeight}px`
|
|
7187
|
+
);
|
|
7188
|
+
host.style.setProperty("--ns-assistant-default-z-index", String(appearance.layout.zIndex));
|
|
7189
|
+
host.style.setProperty("--ns-assistant-default-edge-offset", `${appearance.layout.edgeOffset}px`);
|
|
7190
|
+
const logo = root?.querySelector(".brand-logo");
|
|
7191
|
+
const logoUrl = appearance.brand.logo[mode];
|
|
7192
|
+
if (logo) {
|
|
7193
|
+
logo.hidden = !logoUrl;
|
|
7194
|
+
if (logoUrl) logo.src = logoUrl;
|
|
7195
|
+
}
|
|
7196
|
+
if (root) syncAssistantPresentation(host, root, appearance, mode, input.sessionState);
|
|
7197
|
+
return warnings;
|
|
7198
|
+
}
|
|
7199
|
+
|
|
6918
7200
|
// src/presentation-styles.ts
|
|
6919
7201
|
var presentationStyles = `<style>
|
|
6920
7202
|
:host([data-mode="floating"]) {
|
|
@@ -7120,7 +7402,18 @@ var NoodleAssistantElement = class extends HTMLElementBase {
|
|
|
7120
7402
|
#pendingUserEcho;
|
|
7121
7403
|
#sessionState = "idle";
|
|
7122
7404
|
#startOpenApplied = false;
|
|
7405
|
+
#hostAppearance;
|
|
7406
|
+
#appearanceWarningKeys = /* @__PURE__ */ new Set();
|
|
7407
|
+
#appearanceStyleSnapshot = /* @__PURE__ */ new Map();
|
|
7123
7408
|
sessionEndpoint = "";
|
|
7409
|
+
get appearance() {
|
|
7410
|
+
return this.#hostAppearance;
|
|
7411
|
+
}
|
|
7412
|
+
set appearance(value) {
|
|
7413
|
+
this.#hostAppearance = value;
|
|
7414
|
+
this.#appearanceWarningKeys.clear();
|
|
7415
|
+
if (this.isConnected) this.#applyTheme();
|
|
7416
|
+
}
|
|
7124
7417
|
#events = new AssistantElementEventController({
|
|
7125
7418
|
element: this,
|
|
7126
7419
|
messages: () => this.#messages,
|
|
@@ -7136,10 +7429,7 @@ var NoodleAssistantElement = class extends HTMLElementBase {
|
|
|
7136
7429
|
this.#syncAppearance();
|
|
7137
7430
|
this.#applyStartOpenPolicy();
|
|
7138
7431
|
},
|
|
7139
|
-
labels: () =>
|
|
7140
|
-
confirm: this.#appearance.labels.confirm,
|
|
7141
|
-
cancel: this.#appearance.labels.cancel
|
|
7142
|
-
}),
|
|
7432
|
+
labels: () => this.#appearance.labels,
|
|
7143
7433
|
respond: (id, response) => this.respond(id, response),
|
|
7144
7434
|
dispatchError: (detail) => this.#dispatchError(detail),
|
|
7145
7435
|
renderView: (detail) => {
|
|
@@ -7200,6 +7490,15 @@ var NoodleAssistantElement = class extends HTMLElementBase {
|
|
|
7200
7490
|
focusComposer() {
|
|
7201
7491
|
this.shadowRoot?.querySelector("textarea")?.focus();
|
|
7202
7492
|
}
|
|
7493
|
+
/** Stop the active stream without discarding the current composer draft or session. */
|
|
7494
|
+
stop() {
|
|
7495
|
+
if (!this.hasAttribute("busy")) return;
|
|
7496
|
+
this.#conversationGeneration += 1;
|
|
7497
|
+
this.#client?.abort();
|
|
7498
|
+
this.#setBusy(false);
|
|
7499
|
+
this.#appendStatus(this.#appearance.labels.stopped);
|
|
7500
|
+
this.dispatchEvent(new CustomEvent("assistant-stopped"));
|
|
7501
|
+
}
|
|
7203
7502
|
resetSession() {
|
|
7204
7503
|
this.#conversationGeneration += 1;
|
|
7205
7504
|
this.#client?.abort();
|
|
@@ -7214,6 +7513,20 @@ var NoodleAssistantElement = class extends HTMLElementBase {
|
|
|
7214
7513
|
this.#setBusy(false);
|
|
7215
7514
|
this.#setSessionState("idle");
|
|
7216
7515
|
}
|
|
7516
|
+
/** Re-establish the session without replaying a message or interaction decision. */
|
|
7517
|
+
reconnect() {
|
|
7518
|
+
this.#conversationGeneration += 1;
|
|
7519
|
+
this.#client?.abort();
|
|
7520
|
+
this.#unsubscribeClient?.();
|
|
7521
|
+
this.#client = void 0;
|
|
7522
|
+
this.#clientEndpoint = "";
|
|
7523
|
+
this.#unsubscribeClient = void 0;
|
|
7524
|
+
this.#sessionBootstrap = void 0;
|
|
7525
|
+
this.#setBusy(false);
|
|
7526
|
+
this.#setSessionState("loading");
|
|
7527
|
+
this.#primeSession();
|
|
7528
|
+
this.dispatchEvent(new CustomEvent("assistant-reconnecting"));
|
|
7529
|
+
}
|
|
7217
7530
|
updateContext(context) {
|
|
7218
7531
|
this.#context = { ...context };
|
|
7219
7532
|
if (this.#client) {
|
|
@@ -7261,6 +7574,7 @@ var NoodleAssistantElement = class extends HTMLElementBase {
|
|
|
7261
7574
|
await this.#ensureClient().sendMessage(message);
|
|
7262
7575
|
} catch (error) {
|
|
7263
7576
|
if (generation !== this.#conversationGeneration) return;
|
|
7577
|
+
if (error instanceof AssistantClientError && error.detail.code === "request_aborted") return;
|
|
7264
7578
|
this.#dispatchClientError(error, "turn_failed");
|
|
7265
7579
|
throw error;
|
|
7266
7580
|
} finally {
|
|
@@ -7340,26 +7654,31 @@ var NoodleAssistantElement = class extends HTMLElementBase {
|
|
|
7340
7654
|
#handleClientEvent(event) {
|
|
7341
7655
|
this.dispatchEvent(new CustomEvent("assistant-event", { detail: event }));
|
|
7342
7656
|
this.#events.handle(event);
|
|
7343
|
-
if (event.event === "session_started")
|
|
7657
|
+
if (event.event === "session_started") {
|
|
7658
|
+
this.#setSessionState("ready");
|
|
7659
|
+
this.#messages?.querySelector(".conversation-error")?.remove();
|
|
7660
|
+
}
|
|
7344
7661
|
if (event.event === "session_expired" || event.event === "session_reset") {
|
|
7345
7662
|
this.#setSessionState("idle");
|
|
7346
7663
|
}
|
|
7347
7664
|
if (event.event === "tool_proposed" || event.event === "interaction_proposed" || event.event === "input_requested") {
|
|
7348
7665
|
this.#removeThinking();
|
|
7349
7666
|
this.setAttribute("has-messages", "");
|
|
7350
|
-
this.#scrollToBottom();
|
|
7351
7667
|
}
|
|
7352
7668
|
if (event.event === "content" || event.event === "message_completed" || event.event === "interaction_completed" || event.event === "error") {
|
|
7353
7669
|
this.#removeThinking();
|
|
7354
|
-
this.#scrollToBottom();
|
|
7355
7670
|
}
|
|
7356
7671
|
}
|
|
7357
7672
|
#setBusy(busy) {
|
|
7358
7673
|
this.toggleAttribute("busy", busy);
|
|
7359
7674
|
const textarea = this.shadowRoot?.querySelector("textarea");
|
|
7360
7675
|
const send = this.shadowRoot?.querySelector(".send");
|
|
7361
|
-
if (textarea) textarea.disabled =
|
|
7362
|
-
if (send)
|
|
7676
|
+
if (textarea) textarea.disabled = false;
|
|
7677
|
+
if (send) {
|
|
7678
|
+
send.dataset.action = busy ? "stop" : "send";
|
|
7679
|
+
send.textContent = busy ? this.#appearance.labels.stop : this.#appearance.labels.send;
|
|
7680
|
+
send.setAttribute("aria-label", send.textContent);
|
|
7681
|
+
}
|
|
7363
7682
|
if (!busy) {
|
|
7364
7683
|
this.#removeThinking();
|
|
7365
7684
|
return;
|
|
@@ -7397,6 +7716,16 @@ var NoodleAssistantElement = class extends HTMLElementBase {
|
|
|
7397
7716
|
body.textContent = text2;
|
|
7398
7717
|
}
|
|
7399
7718
|
message.append(body);
|
|
7719
|
+
if (role === "assistant" && text2) {
|
|
7720
|
+
const copy = document.createElement("button");
|
|
7721
|
+
copy.type = "button";
|
|
7722
|
+
copy.className = "message-copy";
|
|
7723
|
+
copy.textContent = this.#appearance.labels.copy;
|
|
7724
|
+
copy.addEventListener("click", () => {
|
|
7725
|
+
void navigator.clipboard?.writeText(text2);
|
|
7726
|
+
});
|
|
7727
|
+
message.append(copy);
|
|
7728
|
+
}
|
|
7400
7729
|
if (this.#appearance.behavior.showTimestamps) {
|
|
7401
7730
|
const timestamp = document.createElement("time");
|
|
7402
7731
|
timestamp.dateTime = (/* @__PURE__ */ new Date()).toISOString();
|
|
@@ -7408,12 +7737,31 @@ var NoodleAssistantElement = class extends HTMLElementBase {
|
|
|
7408
7737
|
}
|
|
7409
7738
|
this.#messages.append(message);
|
|
7410
7739
|
this.setAttribute("has-messages", "");
|
|
7411
|
-
this.#
|
|
7740
|
+
this.#revealLatest();
|
|
7412
7741
|
return body;
|
|
7413
7742
|
}
|
|
7743
|
+
#appendStatus(text2) {
|
|
7744
|
+
if (!this.#messages) return;
|
|
7745
|
+
const status = document.createElement("p");
|
|
7746
|
+
status.className = "conversation-status";
|
|
7747
|
+
status.setAttribute("role", "status");
|
|
7748
|
+
status.textContent = text2;
|
|
7749
|
+
this.#messages.append(status);
|
|
7750
|
+
}
|
|
7414
7751
|
#scrollToBottom() {
|
|
7415
7752
|
if (this.#messages) this.#messages.scrollTop = this.#messages.scrollHeight;
|
|
7416
7753
|
}
|
|
7754
|
+
#revealLatest() {
|
|
7755
|
+
if (!this.#messages) return;
|
|
7756
|
+
const distance = this.#messages.scrollHeight - this.#messages.scrollTop - this.#messages.clientHeight;
|
|
7757
|
+
const control = this.shadowRoot?.querySelector(".new-messages");
|
|
7758
|
+
if (distance <= 160) {
|
|
7759
|
+
this.#scrollToBottom();
|
|
7760
|
+
if (control) control.hidden = true;
|
|
7761
|
+
} else if (control) {
|
|
7762
|
+
control.hidden = false;
|
|
7763
|
+
}
|
|
7764
|
+
}
|
|
7417
7765
|
#dispatchError(detail) {
|
|
7418
7766
|
this.dispatchEvent(new CustomEvent("assistant-error", { detail }));
|
|
7419
7767
|
}
|
|
@@ -7421,9 +7769,27 @@ var NoodleAssistantElement = class extends HTMLElementBase {
|
|
|
7421
7769
|
if (error instanceof AssistantClientError && error.detail.code === "session_failed") {
|
|
7422
7770
|
this.#setSessionState("error");
|
|
7423
7771
|
}
|
|
7424
|
-
|
|
7425
|
-
|
|
7772
|
+
const detail = error instanceof AssistantClientError ? error.detail : { code: fallbackCode, retryable: false };
|
|
7773
|
+
this.#appendRecoveryError(
|
|
7774
|
+
detail.code === "session_expired" ? this.#appearance.labels.sessionExpired : this.#appearance.labels.unavailable
|
|
7426
7775
|
);
|
|
7776
|
+
this.#dispatchError(detail);
|
|
7777
|
+
}
|
|
7778
|
+
#appendRecoveryError(message) {
|
|
7779
|
+
if (!this.#messages) return;
|
|
7780
|
+
this.#messages.querySelector(".conversation-error")?.remove();
|
|
7781
|
+
const error = document.createElement("section");
|
|
7782
|
+
error.className = "conversation-error";
|
|
7783
|
+
error.setAttribute("role", "alert");
|
|
7784
|
+
const text2 = document.createElement("p");
|
|
7785
|
+
text2.textContent = message;
|
|
7786
|
+
const retry = document.createElement("button");
|
|
7787
|
+
retry.type = "button";
|
|
7788
|
+
retry.textContent = this.#appearance.labels.reconnect;
|
|
7789
|
+
retry.addEventListener("click", () => this.reconnect());
|
|
7790
|
+
error.append(text2, retry);
|
|
7791
|
+
this.#messages.append(error);
|
|
7792
|
+
this.#revealLatest();
|
|
7427
7793
|
}
|
|
7428
7794
|
#resolvedMode() {
|
|
7429
7795
|
const configured = this.getAttribute("theme") ?? this.#appearance.theme.defaultMode;
|
|
@@ -7431,43 +7797,24 @@ var NoodleAssistantElement = class extends HTMLElementBase {
|
|
|
7431
7797
|
}
|
|
7432
7798
|
#applyTheme() {
|
|
7433
7799
|
const mode = this.#resolvedMode();
|
|
7434
|
-
|
|
7435
|
-
|
|
7436
|
-
|
|
7437
|
-
this
|
|
7438
|
-
|
|
7439
|
-
|
|
7800
|
+
for (const warning of applyAssistantElementTheme({
|
|
7801
|
+
host: this,
|
|
7802
|
+
root: this.shadowRoot,
|
|
7803
|
+
appearance: this.#appearance,
|
|
7804
|
+
hostAppearance: this.#hostAppearance,
|
|
7805
|
+
mode,
|
|
7806
|
+
sessionState: this.#sessionState,
|
|
7807
|
+
styleSnapshot: this.#appearanceStyleSnapshot
|
|
7808
|
+
})) {
|
|
7809
|
+
const key = `${warning.theme}:${warning.role}:${warning.foreground}:${warning.background}`;
|
|
7810
|
+
if (this.#appearanceWarningKeys.has(key)) continue;
|
|
7811
|
+
this.#appearanceWarningKeys.add(key);
|
|
7812
|
+
this.dispatchEvent(
|
|
7813
|
+
new CustomEvent("assistant-appearance-warning", {
|
|
7814
|
+
detail: warning
|
|
7815
|
+
})
|
|
7440
7816
|
);
|
|
7441
7817
|
}
|
|
7442
|
-
this.style.setProperty(
|
|
7443
|
-
"--ns-assistant-default-panel-width",
|
|
7444
|
-
`${this.#appearance.layout.panelWidth}px`
|
|
7445
|
-
);
|
|
7446
|
-
this.style.setProperty(
|
|
7447
|
-
"--ns-assistant-default-min-height",
|
|
7448
|
-
`${this.#appearance.layout.panelMinHeight}px`
|
|
7449
|
-
);
|
|
7450
|
-
this.style.setProperty(
|
|
7451
|
-
"--ns-assistant-default-max-height",
|
|
7452
|
-
`${this.#appearance.layout.panelMaxHeight}px`
|
|
7453
|
-
);
|
|
7454
|
-
this.style.setProperty(
|
|
7455
|
-
"--ns-assistant-default-z-index",
|
|
7456
|
-
String(this.#appearance.layout.zIndex)
|
|
7457
|
-
);
|
|
7458
|
-
this.style.setProperty(
|
|
7459
|
-
"--ns-assistant-default-edge-offset",
|
|
7460
|
-
`${this.#appearance.layout.edgeOffset}px`
|
|
7461
|
-
);
|
|
7462
|
-
const logo = this.shadowRoot?.querySelector(".brand-logo");
|
|
7463
|
-
const logoUrl = this.#appearance.brand.logo[mode];
|
|
7464
|
-
if (logo) {
|
|
7465
|
-
logo.hidden = !logoUrl;
|
|
7466
|
-
if (logoUrl) logo.src = logoUrl;
|
|
7467
|
-
}
|
|
7468
|
-
if (this.shadowRoot) {
|
|
7469
|
-
syncAssistantPresentation(this, this.shadowRoot, this.#appearance, mode, this.#sessionState);
|
|
7470
|
-
}
|
|
7471
7818
|
}
|
|
7472
7819
|
#setSessionState(state) {
|
|
7473
7820
|
this.#sessionState = state;
|
|
@@ -7547,6 +7894,7 @@ var NoodleAssistantElement = class extends HTMLElementBase {
|
|
|
7547
7894
|
<div class="welcome"><slot name="empty-state"></slot></div>
|
|
7548
7895
|
<div class="suggested-prompts"></div>
|
|
7549
7896
|
<div class="messages" aria-live="polite"></div>
|
|
7897
|
+
<button class="new-messages" type="button" hidden></button>
|
|
7550
7898
|
<form><slot name="composer-leading"></slot><textarea rows="1"></textarea><button class="send" type="submit"></button><slot name="composer-trailing"></slot></form>
|
|
7551
7899
|
<nav class="legal" aria-label="Legal"></nav>
|
|
7552
7900
|
<slot name="conversation-footer"></slot>
|
|
@@ -7589,6 +7937,10 @@ var NoodleAssistantElement = class extends HTMLElementBase {
|
|
|
7589
7937
|
const form = queryRequired(this.shadowRoot, "form");
|
|
7590
7938
|
form.addEventListener("submit", (event) => {
|
|
7591
7939
|
event.preventDefault();
|
|
7940
|
+
if (this.hasAttribute("busy")) {
|
|
7941
|
+
this.stop();
|
|
7942
|
+
return;
|
|
7943
|
+
}
|
|
7592
7944
|
const value = textarea.value;
|
|
7593
7945
|
textarea.value = "";
|
|
7594
7946
|
textarea.style.height = "auto";
|
|
@@ -7603,6 +7955,17 @@ var NoodleAssistantElement = class extends HTMLElementBase {
|
|
|
7603
7955
|
event.preventDefault();
|
|
7604
7956
|
form.requestSubmit();
|
|
7605
7957
|
});
|
|
7958
|
+
const newMessages = queryRequired(this.shadowRoot, ".new-messages");
|
|
7959
|
+
newMessages.textContent = appearance.labels.newMessages;
|
|
7960
|
+
newMessages.addEventListener("click", () => {
|
|
7961
|
+
this.#scrollToBottom();
|
|
7962
|
+
newMessages.hidden = true;
|
|
7963
|
+
});
|
|
7964
|
+
this.#messages?.addEventListener("scroll", () => {
|
|
7965
|
+
if (this.#messages && this.#messages.scrollHeight - this.#messages.scrollTop - this.#messages.clientHeight < 48) {
|
|
7966
|
+
newMessages.hidden = true;
|
|
7967
|
+
}
|
|
7968
|
+
});
|
|
7606
7969
|
this.#applyTheme();
|
|
7607
7970
|
}
|
|
7608
7971
|
#appendLegalLinks(legal) {
|
|
@@ -7636,4 +7999,4 @@ export {
|
|
|
7636
7999
|
dompurify/dist/purify.es.mjs:
|
|
7637
8000
|
(*! @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 *)
|
|
7638
8001
|
*/
|
|
7639
|
-
//# sourceMappingURL=chunk-
|
|
8002
|
+
//# sourceMappingURL=chunk-ZKXOX67J.js.map
|