@newheap/platform-ai-chat 0.6.0 → 0.8.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 +35 -5
- package/fesm2022/newheap-platform-ai-chat.mjs +303 -39
- package/fesm2022/newheap-platform-ai-chat.mjs.map +1 -1
- package/i18n/en.json +22 -2
- package/i18n/nl.json +22 -2
- package/index.d.ts +59 -6
- package/package.json +1 -1
|
@@ -101,6 +101,9 @@ var en = {
|
|
|
101
101
|
"open-preferences": "Your assistant preferences",
|
|
102
102
|
"open-admin": "Assistant administration",
|
|
103
103
|
share: "Share conversation",
|
|
104
|
+
"add-members": "Add people to the conversation",
|
|
105
|
+
"notifications-on": "Turn notifications on",
|
|
106
|
+
"notifications-off": "Turn notifications off",
|
|
104
107
|
members: "People in this conversation"
|
|
105
108
|
},
|
|
106
109
|
"agent-picker": {
|
|
@@ -146,12 +149,29 @@ var en = {
|
|
|
146
149
|
characters: "{{count}} of {{max}} characters",
|
|
147
150
|
"too-long": "The message is too long.",
|
|
148
151
|
status: {
|
|
149
|
-
running: "
|
|
150
|
-
"waiting-for-approval": "
|
|
152
|
+
running: "The assistant is working",
|
|
153
|
+
"waiting-for-approval": "Waiting for approval",
|
|
151
154
|
"running-by": "{{name}} is working with the assistant…",
|
|
152
155
|
"waiting-for-approval-by": "Waiting for {{name}} to decide…"
|
|
153
156
|
}
|
|
154
157
|
},
|
|
158
|
+
queue: {
|
|
159
|
+
title: "Queue ({{count}})",
|
|
160
|
+
add: "Add message to queue",
|
|
161
|
+
hint: "Enter queues, Shift+Enter adds a new line",
|
|
162
|
+
steer: "Steer now",
|
|
163
|
+
"steer-hint": "Stop the current answer and continue this conversation with this message first",
|
|
164
|
+
edit: "Edit queued message",
|
|
165
|
+
save: "Save message",
|
|
166
|
+
"cancel-edit": "Cancel editing",
|
|
167
|
+
remove: "Remove queued message",
|
|
168
|
+
resume: "Resume queue",
|
|
169
|
+
state: {
|
|
170
|
+
preparing: "Preparing…",
|
|
171
|
+
sending: "Sending…",
|
|
172
|
+
failed: "Not sent; resume to retry"
|
|
173
|
+
}
|
|
174
|
+
},
|
|
155
175
|
"tool-call": {
|
|
156
176
|
label: "Tool call: {{name}}",
|
|
157
177
|
"show-details": "Show details",
|
|
@@ -572,6 +592,9 @@ var nl = {
|
|
|
572
592
|
"open-preferences": "Je assistentvoorkeuren",
|
|
573
593
|
"open-admin": "Beheer van de assistent",
|
|
574
594
|
share: "Gesprek delen",
|
|
595
|
+
"add-members": "Mensen toevoegen aan het gesprek",
|
|
596
|
+
"notifications-on": "Notificaties aanzetten",
|
|
597
|
+
"notifications-off": "Notificaties uitzetten",
|
|
575
598
|
members: "Mensen in dit gesprek"
|
|
576
599
|
},
|
|
577
600
|
"agent-picker": {
|
|
@@ -617,12 +640,29 @@ var nl = {
|
|
|
617
640
|
characters: "{{count}} van {{max}} tekens",
|
|
618
641
|
"too-long": "Het bericht is te lang.",
|
|
619
642
|
status: {
|
|
620
|
-
running: "
|
|
621
|
-
"waiting-for-approval": "
|
|
643
|
+
running: "De assistent is bezig",
|
|
644
|
+
"waiting-for-approval": "Wacht op goedkeuring",
|
|
622
645
|
"running-by": "{{name}} werkt met de assistent…",
|
|
623
646
|
"waiting-for-approval-by": "Wacht op de beslissing van {{name}}…"
|
|
624
647
|
}
|
|
625
648
|
},
|
|
649
|
+
queue: {
|
|
650
|
+
title: "Wachtrij ({{count}})",
|
|
651
|
+
add: "Bericht in de wachtrij zetten",
|
|
652
|
+
hint: "Enter zet in wachtrij, Shift+Enter voegt een regel toe",
|
|
653
|
+
steer: "Bijsturen",
|
|
654
|
+
"steer-hint": "Stop het huidige antwoord en vervolg dit gesprek eerst met dit bericht",
|
|
655
|
+
edit: "Bericht in wachtrij bewerken",
|
|
656
|
+
save: "Bericht opslaan",
|
|
657
|
+
"cancel-edit": "Bewerken annuleren",
|
|
658
|
+
remove: "Bericht uit wachtrij verwijderen",
|
|
659
|
+
resume: "Wachtrij hervatten",
|
|
660
|
+
state: {
|
|
661
|
+
preparing: "Klaarzetten…",
|
|
662
|
+
sending: "Versturen…",
|
|
663
|
+
failed: "Niet verstuurd; hervat om opnieuw te proberen"
|
|
664
|
+
}
|
|
665
|
+
},
|
|
626
666
|
"tool-call": {
|
|
627
667
|
label: "Toolaanroep: {{name}}",
|
|
628
668
|
"show-details": "Details tonen",
|
|
@@ -2407,6 +2447,12 @@ class NhAssistantStore {
|
|
|
2407
2447
|
this.restorePanelOpenState = signal(false, ...(ngDevMode ? [{ debugName: "restorePanelOpenState" }] : []));
|
|
2408
2448
|
this.viewingState = signal(false, ...(ngDevMode ? [{ debugName: "viewingState" }] : []));
|
|
2409
2449
|
this.pageVisibleState = signal(true, ...(ngDevMode ? [{ debugName: "pageVisibleState" }] : []));
|
|
2450
|
+
this.queuedState = signal([], ...(ngDevMode ? [{ debugName: "queuedState" }] : []));
|
|
2451
|
+
this.pausedQueuesState = signal(new Set(), ...(ngDevMode ? [{ debugName: "pausedQueuesState" }] : []));
|
|
2452
|
+
this.queueDispatchState = signal(null, ...(ngDevMode ? [{ debugName: "queueDispatchState" }] : []));
|
|
2453
|
+
this.steeringState = signal(null, ...(ngDevMode ? [{ debugName: "steeringState" }] : []));
|
|
2454
|
+
this.submittingState = signal(false, ...(ngDevMode ? [{ debugName: "submittingState" }] : []));
|
|
2455
|
+
this.destroyed = false;
|
|
2410
2456
|
this.streams = new Map();
|
|
2411
2457
|
this.cancelTimers = new Map();
|
|
2412
2458
|
this.pendingSendResolves = new Map();
|
|
@@ -2463,6 +2509,23 @@ class NhAssistantStore {
|
|
|
2463
2509
|
const blocked = conversation !== null && conversation.status !== 'idle';
|
|
2464
2510
|
return this.enabled() && this.selectedAgentIdState() !== null && !this.streaming() && !this.conversationLoadingState() && !blocked;
|
|
2465
2511
|
}, ...(ngDevMode ? [{ debugName: "canSend" }] : []));
|
|
2512
|
+
/** Messages not yet accepted by the server, for the open conversation. Never persisted. */
|
|
2513
|
+
this.queuedMessages = computed(() => this.queuedState().filter(item => item.conversationId === this.activeIdState()), ...(ngDevMode ? [{ debugName: "queuedMessages" }] : []));
|
|
2514
|
+
/** Sending or queueing is available during a turn and while an approval waits. */
|
|
2515
|
+
this.canSubmit = computed(() => (this.canSend() && !this.submittingState()) || (this.enabled()
|
|
2516
|
+
&& !this.conversationLoading() && this.activeConversation() !== null
|
|
2517
|
+
&& ['idle', 'running', 'waiting-for-approval'].includes(this.activeConversation().status)), ...(ngDevMode ? [{ debugName: "canSubmit" }] : []));
|
|
2518
|
+
this.queuePaused = computed(() => this.pausedQueuesState().has(this.activeIdState() ?? '') || this.error() !== null, ...(ngDevMode ? [{ debugName: "queuePaused" }] : []));
|
|
2519
|
+
/** Steering cancels the active turn before sending the selected correction. */
|
|
2520
|
+
this.canSteer = computed(() => {
|
|
2521
|
+
const conversation = this.activeConversation();
|
|
2522
|
+
const ownsTurn = conversation?.activeActorId && conversation.currentActorId
|
|
2523
|
+
? conversation.activeActorId === conversation.currentActorId : this.activeSession()?.streaming === true;
|
|
2524
|
+
return this.enabled() && this.steeringState() === null && !this.submittingState()
|
|
2525
|
+
&& this.queueDispatchState() === null
|
|
2526
|
+
&& ['running', 'waiting-for-approval'].includes(conversation?.status ?? '')
|
|
2527
|
+
&& (this.isOwner() || ownsTurn);
|
|
2528
|
+
}, ...(ngDevMode ? [{ debugName: "canSteer" }] : []));
|
|
2466
2529
|
/** The owner and participants of the open conversation; empty while it is not shared. */
|
|
2467
2530
|
this.members = computed(() => this.activeConversation()?.members ?? [], ...(ngDevMode ? [{ debugName: "members" }] : []));
|
|
2468
2531
|
/** True when the current user owns the open conversation (or it is new). */
|
|
@@ -2510,11 +2573,36 @@ class NhAssistantStore {
|
|
|
2510
2573
|
this.liveState = this.live.state;
|
|
2511
2574
|
const destroyRef = inject(DestroyRef);
|
|
2512
2575
|
destroyRef.onDestroy(() => {
|
|
2576
|
+
this.destroyed = true;
|
|
2513
2577
|
this.accessSubscription?.unsubscribe();
|
|
2514
2578
|
this.liveSubscription.unsubscribe();
|
|
2515
2579
|
this.stopAllTurns();
|
|
2516
2580
|
clearTimeout(this.refreshTimer);
|
|
2517
2581
|
});
|
|
2582
|
+
effect(() => {
|
|
2583
|
+
const queued = this.queuedState();
|
|
2584
|
+
const sessions = this.sessionsState();
|
|
2585
|
+
const paused = this.pausedQueuesState();
|
|
2586
|
+
const steering = this.steeringState();
|
|
2587
|
+
const steeringItem = queued.find(item => item.id === steering);
|
|
2588
|
+
const steeringSession = steeringItem ? sessions.get(steeringItem.conversationId) : null;
|
|
2589
|
+
if (steering && (!steeringItem || steeringSession?.error
|
|
2590
|
+
|| (steeringSession?.conversation.status === 'idle' && !steeringSession.streaming))) {
|
|
2591
|
+
untracked(() => this.steeringState.set(null));
|
|
2592
|
+
}
|
|
2593
|
+
if (!this.enabled() || this.queueDispatchState() !== null || this.sendingState() !== null || this.submittingState()) {
|
|
2594
|
+
return;
|
|
2595
|
+
}
|
|
2596
|
+
const next = queued.find((item, index) => {
|
|
2597
|
+
const session = sessions.get(item.conversationId);
|
|
2598
|
+
return item.state === 'queued' && !paused.has(item.conversationId)
|
|
2599
|
+
&& !queued.slice(0, index).some(previous => previous.conversationId === item.conversationId)
|
|
2600
|
+
&& session?.conversation.status === 'idle' && !session.streaming && !session.deciding && !session.error;
|
|
2601
|
+
});
|
|
2602
|
+
if (next) {
|
|
2603
|
+
untracked(() => void this.dispatchQueued(next));
|
|
2604
|
+
}
|
|
2605
|
+
});
|
|
2518
2606
|
this.liveSubscription.add(this.live.changed$.subscribe(change => this.onLiveChanged(change)));
|
|
2519
2607
|
this.liveSubscription.add(this.live.read$.subscribe(read => this.onLiveRead(read)));
|
|
2520
2608
|
this.liveSubscription.add(this.live.removed$.subscribe(removed => this.onLiveRemoved(removed)));
|
|
@@ -2681,17 +2769,125 @@ class NhAssistantStore {
|
|
|
2681
2769
|
async send(text) {
|
|
2682
2770
|
// Browsers only ask for notification permission during a user action such as this one.
|
|
2683
2771
|
void this.push.onUserGesture().catch(() => undefined);
|
|
2772
|
+
return this.sendMessage(text);
|
|
2773
|
+
}
|
|
2774
|
+
/** Sends immediately when idle, otherwise appends to the conversation's FIFO queue. */
|
|
2775
|
+
async submit(text) {
|
|
2776
|
+
if (this.canSend() && this.queuedMessages().length === 0 && !this.queuePaused() && !this.submittingState()) {
|
|
2777
|
+
const revision = this.accountRevision;
|
|
2778
|
+
this.submittingState.set(true);
|
|
2779
|
+
try {
|
|
2780
|
+
return await this.send(text);
|
|
2781
|
+
}
|
|
2782
|
+
finally {
|
|
2783
|
+
if (revision === this.accountRevision && !this.destroyed) {
|
|
2784
|
+
this.submittingState.set(false);
|
|
2785
|
+
}
|
|
2786
|
+
}
|
|
2787
|
+
}
|
|
2788
|
+
const conversationId = this.activeIdState();
|
|
2684
2789
|
const trimmed = text.trim();
|
|
2790
|
+
if (!conversationId || !this.canSubmit() || !trimmed || trimmed.length > (this.limits()?.maxMessageChars ?? Infinity)) {
|
|
2791
|
+
return false;
|
|
2792
|
+
}
|
|
2793
|
+
void this.push.onUserGesture().catch(() => undefined);
|
|
2794
|
+
const revision = this.accountRevision;
|
|
2795
|
+
const item = { id: createClientMessageId(), conversationId, text: trimmed, state: 'preparing' };
|
|
2796
|
+
this.queuedState.update(items => [...items, item]);
|
|
2797
|
+
const clientContext = await this.contextForMessage();
|
|
2798
|
+
if (revision !== this.accountRevision || this.destroyed) {
|
|
2799
|
+
return false;
|
|
2800
|
+
}
|
|
2801
|
+
this.queuedState.update(items => items.map(current => current.id === item.id
|
|
2802
|
+
? { ...current, state: 'queued', clientContext } : current));
|
|
2803
|
+
return true;
|
|
2804
|
+
}
|
|
2805
|
+
/** Edits an unsent queued message without replacing the composer's current draft. */
|
|
2806
|
+
updateQueuedMessage(id, text) {
|
|
2807
|
+
const trimmed = text.trim();
|
|
2808
|
+
if (!trimmed || trimmed.length > (this.limits()?.maxMessageChars ?? Infinity)
|
|
2809
|
+
|| !this.queuedMessages().some(item => item.id === id && item.state !== 'sending')) {
|
|
2810
|
+
return false;
|
|
2811
|
+
}
|
|
2812
|
+
this.queuedState.update(items => items.map(item => item.id === id ? { ...item, text: trimmed } : item));
|
|
2813
|
+
return true;
|
|
2814
|
+
}
|
|
2815
|
+
removeQueuedMessage(id) {
|
|
2816
|
+
this.queuedState.update(items => items.filter(item => item.id !== id
|
|
2817
|
+
|| item.conversationId !== this.activeIdState() || item.state === 'sending'));
|
|
2818
|
+
}
|
|
2819
|
+
/** Pauses automatic dispatch while keeping all unsent messages available. */
|
|
2820
|
+
pauseQueue() {
|
|
2821
|
+
const conversationId = this.activeIdState();
|
|
2822
|
+
if (conversationId) {
|
|
2823
|
+
this.pausedQueuesState.update(paused => new Set([...paused, conversationId]));
|
|
2824
|
+
}
|
|
2825
|
+
}
|
|
2826
|
+
/** Explicitly resumes after Stop or a failure; approval decisions remain separate. */
|
|
2827
|
+
resumeQueue() {
|
|
2828
|
+
const conversationId = this.activeIdState();
|
|
2829
|
+
if (!conversationId) {
|
|
2830
|
+
return;
|
|
2831
|
+
}
|
|
2832
|
+
this.pausedQueuesState.update(paused => new Set([...paused].filter(id => id !== conversationId)));
|
|
2833
|
+
this.patchSession(conversationId, session => ({ ...session, error: null }));
|
|
2834
|
+
this.queuedState.update(items => items.map(item => item.conversationId === conversationId && item.state === 'failed'
|
|
2835
|
+
? { ...item, state: 'queued' } : item));
|
|
2836
|
+
}
|
|
2837
|
+
/** Prioritizes a queued correction and waits for confirmed cancellation before dispatch. */
|
|
2838
|
+
async steerQueuedMessage(id) {
|
|
2839
|
+
const item = this.queuedState().find(message => message.id === id && message.conversationId === this.activeIdState());
|
|
2840
|
+
if (!item || item.state !== 'queued' || !this.canSteer()) {
|
|
2841
|
+
return;
|
|
2842
|
+
}
|
|
2843
|
+
this.steeringState.set(id);
|
|
2844
|
+
this.queuedState.update(items => [item, ...items.filter(message => message.id !== id)]);
|
|
2845
|
+
this.resumeQueue();
|
|
2846
|
+
try {
|
|
2847
|
+
await this.cancelConversation(item.conversationId);
|
|
2848
|
+
}
|
|
2849
|
+
finally {
|
|
2850
|
+
if (this.steeringState() === id && this.sessionsState().get(item.conversationId)?.error) {
|
|
2851
|
+
this.steeringState.set(null);
|
|
2852
|
+
}
|
|
2853
|
+
}
|
|
2854
|
+
}
|
|
2855
|
+
async dispatchQueued(item) {
|
|
2856
|
+
const revision = this.accountRevision;
|
|
2857
|
+
this.queueDispatchState.set(item.id);
|
|
2858
|
+
this.queuedState.update(items => items.map(current => current.id === item.id ? { ...current, state: 'sending' } : current));
|
|
2859
|
+
const accepted = await this.sendMessage(item.text, item);
|
|
2860
|
+
if (revision !== this.accountRevision || this.destroyed) {
|
|
2861
|
+
return;
|
|
2862
|
+
}
|
|
2863
|
+
this.queuedState.update(items => accepted ? items.filter(current => current.id !== item.id)
|
|
2864
|
+
: items.map(current => current.id === item.id ? { ...current, state: 'failed' } : current));
|
|
2865
|
+
if (!accepted) {
|
|
2866
|
+
this.pausedQueuesState.update(paused => new Set([...paused, item.conversationId]));
|
|
2867
|
+
}
|
|
2868
|
+
this.queueDispatchState.set(null);
|
|
2869
|
+
}
|
|
2870
|
+
async sendMessage(text, queued) {
|
|
2871
|
+
const trimmed = text.trim();
|
|
2872
|
+
const accountRevision = this.accountRevision;
|
|
2685
2873
|
await this.initialize();
|
|
2686
2874
|
await this.reloadStatus();
|
|
2875
|
+
if (accountRevision !== this.accountRevision || this.destroyed) {
|
|
2876
|
+
return false;
|
|
2877
|
+
}
|
|
2878
|
+
let conversation = queued ? this.sessionsState().get(queued.conversationId)?.conversation ?? null : this.activeConversation();
|
|
2879
|
+
const session = queued ? this.sessionsState().get(queued.conversationId) : null;
|
|
2880
|
+
const available = queued ? this.enabled() && !this.pausedQueuesState().has(queued.conversationId)
|
|
2881
|
+
&& conversation?.status === 'idle' && !session?.streaming
|
|
2882
|
+
&& !session?.deciding && this.agents().some(agent => agent.id === conversation?.agentId) : this.canSend();
|
|
2687
2883
|
const maxChars = this.limits()?.maxMessageChars ?? Number.MAX_SAFE_INTEGER;
|
|
2688
|
-
if (trimmed.length === 0 || trimmed.length > maxChars || !
|
|
2884
|
+
if (trimmed.length === 0 || trimmed.length > maxChars || !available) {
|
|
2689
2885
|
return false;
|
|
2690
2886
|
}
|
|
2691
|
-
const accountRevision = this.accountRevision;
|
|
2692
|
-
let conversation = this.activeConversation();
|
|
2693
2887
|
this.sendingState.set(conversation?.id ?? newConversationKey);
|
|
2694
|
-
|
|
2888
|
+
if (!queued) {
|
|
2889
|
+
this.restoredDraftState.set(null);
|
|
2890
|
+
}
|
|
2695
2891
|
this.draftErrorState.set(null);
|
|
2696
2892
|
if (!conversation) {
|
|
2697
2893
|
conversation = await this.createConversation();
|
|
@@ -2704,7 +2900,7 @@ class NhAssistantStore {
|
|
|
2704
2900
|
}
|
|
2705
2901
|
this.sendingState.set(conversation.id);
|
|
2706
2902
|
}
|
|
2707
|
-
const clientContext = await this.contextForMessage();
|
|
2903
|
+
const clientContext = queued ? queued.clientContext : await this.contextForMessage();
|
|
2708
2904
|
if (accountRevision !== this.accountRevision) {
|
|
2709
2905
|
return false;
|
|
2710
2906
|
}
|
|
@@ -2743,7 +2939,7 @@ class NhAssistantStore {
|
|
|
2743
2939
|
next: event => {
|
|
2744
2940
|
if (event.type === 'error' && !started) {
|
|
2745
2941
|
this.removeMessage(conversationId, clientMessageId, previousStatus);
|
|
2746
|
-
if (this.activeIdState() === conversationId) {
|
|
2942
|
+
if (!queued && this.activeIdState() === conversationId) {
|
|
2747
2943
|
this.restoredDraftState.set(text);
|
|
2748
2944
|
}
|
|
2749
2945
|
this.patchSession(conversationId, session => ({ ...session, error: event.data }));
|
|
@@ -2807,12 +3003,18 @@ class NhAssistantStore {
|
|
|
2807
3003
|
}
|
|
2808
3004
|
/** Asks the server to stop the running turn or to abandon a waiting approval of the open conversation. */
|
|
2809
3005
|
async cancel() {
|
|
2810
|
-
const
|
|
3006
|
+
const conversationId = this.activeIdState();
|
|
3007
|
+
if (conversationId) {
|
|
3008
|
+
this.pauseQueue();
|
|
3009
|
+
await this.cancelConversation(conversationId);
|
|
3010
|
+
}
|
|
3011
|
+
}
|
|
3012
|
+
async cancelConversation(conversationId) {
|
|
3013
|
+
const session = this.sessionsState().get(conversationId);
|
|
2811
3014
|
const conversation = session?.conversation;
|
|
2812
3015
|
if (!session || !conversation || (conversation.status === 'idle' && !session.streaming)) {
|
|
2813
3016
|
return;
|
|
2814
3017
|
}
|
|
2815
|
-
const conversationId = conversation.id;
|
|
2816
3018
|
const revision = this.accountRevision;
|
|
2817
3019
|
try {
|
|
2818
3020
|
await firstValueFrom(this.api.cancel(conversationId), { defaultValue: undefined });
|
|
@@ -3126,6 +3328,11 @@ class NhAssistantStore {
|
|
|
3126
3328
|
this.restoredDraftState.set(null);
|
|
3127
3329
|
this.draftErrorState.set(null);
|
|
3128
3330
|
this.sendingState.set(null);
|
|
3331
|
+
this.queuedState.set([]);
|
|
3332
|
+
this.pausedQueuesState.set(new Set());
|
|
3333
|
+
this.queueDispatchState.set(null);
|
|
3334
|
+
this.steeringState.set(null);
|
|
3335
|
+
this.submittingState.set(false);
|
|
3129
3336
|
void this.live.stop();
|
|
3130
3337
|
void this.push.deactivate().catch(() => undefined);
|
|
3131
3338
|
}
|
|
@@ -3360,7 +3567,8 @@ class NhAssistantStore {
|
|
|
3360
3567
|
if (next.size <= maxSessions) {
|
|
3361
3568
|
break;
|
|
3362
3569
|
}
|
|
3363
|
-
if (id !== activeId && id !== conversation.id && !session.streaming
|
|
3570
|
+
if (id !== activeId && id !== conversation.id && !session.streaming
|
|
3571
|
+
&& !this.queuedState().some(item => item.conversationId === id)) {
|
|
3364
3572
|
next.delete(id);
|
|
3365
3573
|
}
|
|
3366
3574
|
}
|
|
@@ -3411,6 +3619,8 @@ class NhAssistantStore {
|
|
|
3411
3619
|
}
|
|
3412
3620
|
/** Removes a deleted, left or inaccessible conversation everywhere. */
|
|
3413
3621
|
forget(conversationId) {
|
|
3622
|
+
this.queuedState.update(items => items.filter(item => item.conversationId !== conversationId));
|
|
3623
|
+
this.pausedQueuesState.update(paused => new Set([...paused].filter(id => id !== conversationId)));
|
|
3414
3624
|
this.streams.get(conversationId)?.unsubscribe();
|
|
3415
3625
|
this.streams.delete(conversationId);
|
|
3416
3626
|
this.sessionsState.update(sessions => {
|
|
@@ -3989,6 +4199,8 @@ class NhAssistantAgentPickerComponent {
|
|
|
3989
4199
|
this.agents = input.required(...(ngDevMode ? [{ debugName: "agents" }] : []));
|
|
3990
4200
|
this.selectedAgentId = input(null, ...(ngDevMode ? [{ debugName: "selectedAgentId" }] : []));
|
|
3991
4201
|
this.disabled = input(false, ...(ngDevMode ? [{ debugName: "disabled" }] : []));
|
|
4202
|
+
/** Compact prompt-bar control; capability information remains in the tooltip and accessible description. */
|
|
4203
|
+
this.compact = input(false, ...(ngDevMode ? [{ debugName: "compact" }] : []));
|
|
3992
4204
|
this.agentChange = output();
|
|
3993
4205
|
this.selectId = `nh-assistant-agent-picker-${nextId$6++}`;
|
|
3994
4206
|
this.selected = computed(() => this.agents().find(agent => agent.id === this.selectedAgentId()) ?? null, ...(ngDevMode ? [{ debugName: "selected" }] : []));
|
|
@@ -3997,12 +4209,13 @@ class NhAssistantAgentPickerComponent {
|
|
|
3997
4209
|
this.agentChange.emit(event.target.value);
|
|
3998
4210
|
}
|
|
3999
4211
|
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.3.33", ngImport: i0, type: NhAssistantAgentPickerComponent, deps: [], target: i0.ɵɵFactoryTarget.Component }); }
|
|
4000
|
-
static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "20.3.33", type: NhAssistantAgentPickerComponent, isStandalone: true, selector: "nh-assistant-agent-picker", inputs: { agents: { classPropertyName: "agents", publicName: "agents", isSignal: true, isRequired: true, transformFunction: null }, selectedAgentId: { classPropertyName: "selectedAgentId", publicName: "selectedAgentId", isSignal: true, isRequired: false, transformFunction: null }, disabled: { classPropertyName: "disabled", publicName: "disabled", isSignal: true, isRequired: false, transformFunction: null } }, outputs: { agentChange: "agentChange" }, ngImport: i0, template: `
|
|
4212
|
+
static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "20.3.33", type: NhAssistantAgentPickerComponent, isStandalone: true, selector: "nh-assistant-agent-picker", inputs: { agents: { classPropertyName: "agents", publicName: "agents", isSignal: true, isRequired: true, transformFunction: null }, selectedAgentId: { classPropertyName: "selectedAgentId", publicName: "selectedAgentId", isSignal: true, isRequired: false, transformFunction: null }, disabled: { classPropertyName: "disabled", publicName: "disabled", isSignal: true, isRequired: false, transformFunction: null }, compact: { classPropertyName: "compact", publicName: "compact", isSignal: true, isRequired: false, transformFunction: null } }, outputs: { agentChange: "agentChange" }, host: { properties: { "class.compact": "compact()" } }, ngImport: i0, template: `
|
|
4001
4213
|
<label class="visually-hidden" [for]="selectId">{{ 'nh-assistant.agent-picker.label' | translate }}</label>
|
|
4002
4214
|
<select
|
|
4003
4215
|
[id]="selectId"
|
|
4004
4216
|
[disabled]="disabled() || agents().length < 2"
|
|
4005
|
-
[attr.
|
|
4217
|
+
[attr.aria-describedby]="selected() ? selectId + '-capability' : null"
|
|
4218
|
+
[attr.title]="selected() ? (([selected()!.descriptionKey] | nhAssistantTranslate: selected()!.descriptionKey) + (compact() ? ' · ' + ((selected()!.canMutate ? 'nh-assistant.agent-picker.can-mutate' : 'nh-assistant.agent-picker.read-only') | translate) : '')) : null"
|
|
4006
4219
|
(change)="onChange($event)">
|
|
4007
4220
|
@for (agent of agents(); track agent.id) {
|
|
4008
4221
|
<option [value]="agent.id" [selected]="agent.id === selectedAgentId()">
|
|
@@ -4011,20 +4224,21 @@ class NhAssistantAgentPickerComponent {
|
|
|
4011
4224
|
}
|
|
4012
4225
|
</select>
|
|
4013
4226
|
@if (selected(); as agent) {
|
|
4014
|
-
<span class="capability" [attr.data-can-mutate]="agent.canMutate">
|
|
4227
|
+
<span class="capability" [id]="selectId + '-capability'" [class.visually-hidden]="compact()" [attr.data-can-mutate]="agent.canMutate">
|
|
4015
4228
|
{{ (agent.canMutate ? 'nh-assistant.agent-picker.can-mutate' : 'nh-assistant.agent-picker.read-only') | translate }}
|
|
4016
4229
|
</span>
|
|
4017
4230
|
}
|
|
4018
|
-
`, isInline: true, styles: [":host{--nha-font: var(--nh-assistant-font, inherit);--nha-background: var(--nh-assistant-background, #ffffff);--nha-surface: var(--nh-assistant-surface, #f5f7fb);--nha-surface-strong: var(--nh-assistant-surface-strong, #eceff6);--nha-text: var(--nh-assistant-text, #080c1d);--nha-text-muted: var(--nh-assistant-text-muted, #5b6482);--nha-border: var(--nh-assistant-border, #dce0ec);--nha-accent: var(--nh-assistant-accent, #022962);--nha-accent-contrast: var(--nh-assistant-accent-contrast, #ffffff);--nha-highlight: var(--nh-assistant-highlight, #c84f00);--nha-user-bubble: var(--nh-assistant-user-bubble, #022962);--nha-user-text: var(--nh-assistant-user-text, #ffffff);--nha-success: var(--nh-assistant-success, #247d4e);--nha-success-soft: var(--nh-assistant-success-soft, #e6f5ec);--nha-warning: var(--nh-assistant-warning, #8a5a00);--nha-warning-soft: var(--nh-assistant-warning-soft, #fff3d9);--nha-danger: var(--nh-assistant-danger, #b92e52);--nha-danger-soft: var(--nh-assistant-danger-soft, #ffe9ef);--nha-focus: var(--nh-assistant-focus, #ff6700);--nha-shadow: var(--nh-assistant-shadow, 0 16px 36px rgb(2 41 98 / .16));--nha-radius: var(--nh-assistant-radius, 16px);--nha-radius-control: var(--nh-assistant-radius-control, 12px);--nha-mono: var(--nh-assistant-font-mono, ui-monospace, \"Cascadia Code\", Consolas, monospace)}@media(prefers-color-scheme:dark){:host{--nha-background: var(--nh-assistant-background, #0b0e22);--nha-surface: var(--nh-assistant-surface, #11152d);--nha-surface-strong: var(--nh-assistant-surface-strong, #181d3b);--nha-text: var(--nh-assistant-text, #ffffff);--nha-text-muted: var(--nh-assistant-text-muted, #b8bed8);--nha-border: var(--nh-assistant-border, #2b3155);--nha-accent: var(--nh-assistant-accent, #0f4087);--nha-accent-contrast: var(--nh-assistant-accent-contrast, #ffffff);--nha-highlight: var(--nh-assistant-highlight, #ff6700);--nha-user-bubble: var(--nh-assistant-user-bubble, #022962);--nha-user-text: var(--nh-assistant-user-text, #ffffff);--nha-success: var(--nh-assistant-success, #67c58f);--nha-success-soft: var(--nh-assistant-success-soft, #102d24);--nha-warning: var(--nh-assistant-warning, #ffbf5b);--nha-warning-soft: var(--nh-assistant-warning-soft, #342818);--nha-danger: var(--nh-assistant-danger, #ff6d8a);--nha-danger-soft: var(--nh-assistant-danger-soft, #351b2a);--nha-shadow: var(--nh-assistant-shadow, 0 16px 36px rgb(0 0 0 / .32))}}:host{display:flex;flex-direction:column;gap:2px;min-width:0}select{align-self:flex-start;max-width:100%;min-height:32px;border:1px solid var(--nha-border);border-radius:var(--nha-radius-control);padding:4px 28px 4px 10px;color:var(--nha-text);background:var(--nha-background);font:inherit;font-size:13px;font-weight:650}select:focus-visible{outline:3px solid color-mix(in srgb,var(--nha-focus) 80%,transparent);outline-offset:2px}select:disabled{opacity:1;cursor:default}.capability{padding-left:2px;color:var(--nha-text-muted);font-size:11px}.capability[data-can-mutate=true]{color:var(--nha-warning)}.visually-hidden{position:absolute;width:1px;height:1px;overflow:hidden;clip:rect(0 0 0 0);clip-path:inset(50%);white-space:nowrap}\n"], dependencies: [{ kind: "pipe", type: TranslatePipe, name: "translate" }, { kind: "pipe", type: NhAssistantTranslatePipe, name: "nhAssistantTranslate" }], changeDetection: i0.ChangeDetectionStrategy.OnPush }); }
|
|
4231
|
+
`, isInline: true, styles: [":host{--nha-font: var(--nh-assistant-font, inherit);--nha-background: var(--nh-assistant-background, #ffffff);--nha-surface: var(--nh-assistant-surface, #f5f7fb);--nha-surface-strong: var(--nh-assistant-surface-strong, #eceff6);--nha-text: var(--nh-assistant-text, #080c1d);--nha-text-muted: var(--nh-assistant-text-muted, #5b6482);--nha-border: var(--nh-assistant-border, #dce0ec);--nha-accent: var(--nh-assistant-accent, #022962);--nha-accent-contrast: var(--nh-assistant-accent-contrast, #ffffff);--nha-highlight: var(--nh-assistant-highlight, #c84f00);--nha-user-bubble: var(--nh-assistant-user-bubble, #022962);--nha-user-text: var(--nh-assistant-user-text, #ffffff);--nha-success: var(--nh-assistant-success, #247d4e);--nha-success-soft: var(--nh-assistant-success-soft, #e6f5ec);--nha-warning: var(--nh-assistant-warning, #8a5a00);--nha-warning-soft: var(--nh-assistant-warning-soft, #fff3d9);--nha-danger: var(--nh-assistant-danger, #b92e52);--nha-danger-soft: var(--nh-assistant-danger-soft, #ffe9ef);--nha-focus: var(--nh-assistant-focus, #ff6700);--nha-shadow: var(--nh-assistant-shadow, 0 16px 36px rgb(2 41 98 / .16));--nha-radius: var(--nh-assistant-radius, 16px);--nha-radius-control: var(--nh-assistant-radius-control, 12px);--nha-mono: var(--nh-assistant-font-mono, ui-monospace, \"Cascadia Code\", Consolas, monospace)}@media(prefers-color-scheme:dark){:host{--nha-background: var(--nh-assistant-background, #0b0e22);--nha-surface: var(--nh-assistant-surface, #11152d);--nha-surface-strong: var(--nh-assistant-surface-strong, #181d3b);--nha-text: var(--nh-assistant-text, #ffffff);--nha-text-muted: var(--nh-assistant-text-muted, #b8bed8);--nha-border: var(--nh-assistant-border, #2b3155);--nha-accent: var(--nh-assistant-accent, #0f4087);--nha-accent-contrast: var(--nh-assistant-accent-contrast, #ffffff);--nha-highlight: var(--nh-assistant-highlight, #ff6700);--nha-user-bubble: var(--nh-assistant-user-bubble, #022962);--nha-user-text: var(--nh-assistant-user-text, #ffffff);--nha-success: var(--nh-assistant-success, #67c58f);--nha-success-soft: var(--nh-assistant-success-soft, #102d24);--nha-warning: var(--nh-assistant-warning, #ffbf5b);--nha-warning-soft: var(--nh-assistant-warning-soft, #342818);--nha-danger: var(--nh-assistant-danger, #ff6d8a);--nha-danger-soft: var(--nh-assistant-danger-soft, #351b2a);--nha-shadow: var(--nh-assistant-shadow, 0 16px 36px rgb(0 0 0 / .32))}}:host{display:flex;flex-direction:column;gap:2px;min-width:0}:host(.compact){flex-direction:row;align-items:center}:host(.compact) select{min-width:0;max-width:100%;border-color:transparent;padding-left:8px;background:transparent;cursor:pointer}:host(.compact) select:hover:not(:disabled){border-color:var(--nha-border);background:var(--nha-surface-strong)}:host(.compact) select:disabled{cursor:default}select{align-self:flex-start;max-width:100%;min-height:32px;border:1px solid var(--nha-border);border-radius:var(--nha-radius-control);padding:4px 28px 4px 10px;color:var(--nha-text);background:var(--nha-background);font:inherit;font-size:13px;font-weight:650}select:focus-visible{outline:3px solid color-mix(in srgb,var(--nha-focus) 80%,transparent);outline-offset:2px}select:disabled{opacity:1;cursor:default}.capability{padding-left:2px;color:var(--nha-text-muted);font-size:11px}.capability[data-can-mutate=true]{color:var(--nha-warning)}.visually-hidden{position:absolute;width:1px;height:1px;overflow:hidden;clip:rect(0 0 0 0);clip-path:inset(50%);white-space:nowrap}\n"], dependencies: [{ kind: "pipe", type: TranslatePipe, name: "translate" }, { kind: "pipe", type: NhAssistantTranslatePipe, name: "nhAssistantTranslate" }], changeDetection: i0.ChangeDetectionStrategy.OnPush }); }
|
|
4019
4232
|
}
|
|
4020
4233
|
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.33", ngImport: i0, type: NhAssistantAgentPickerComponent, decorators: [{
|
|
4021
4234
|
type: Component,
|
|
4022
|
-
args: [{ selector: 'nh-assistant-agent-picker', standalone: true, imports: [TranslatePipe, NhAssistantTranslatePipe], changeDetection: ChangeDetectionStrategy.OnPush, template: `
|
|
4235
|
+
args: [{ selector: 'nh-assistant-agent-picker', standalone: true, imports: [TranslatePipe, NhAssistantTranslatePipe], changeDetection: ChangeDetectionStrategy.OnPush, host: { '[class.compact]': 'compact()' }, template: `
|
|
4023
4236
|
<label class="visually-hidden" [for]="selectId">{{ 'nh-assistant.agent-picker.label' | translate }}</label>
|
|
4024
4237
|
<select
|
|
4025
4238
|
[id]="selectId"
|
|
4026
4239
|
[disabled]="disabled() || agents().length < 2"
|
|
4027
|
-
[attr.
|
|
4240
|
+
[attr.aria-describedby]="selected() ? selectId + '-capability' : null"
|
|
4241
|
+
[attr.title]="selected() ? (([selected()!.descriptionKey] | nhAssistantTranslate: selected()!.descriptionKey) + (compact() ? ' · ' + ((selected()!.canMutate ? 'nh-assistant.agent-picker.can-mutate' : 'nh-assistant.agent-picker.read-only') | translate) : '')) : null"
|
|
4028
4242
|
(change)="onChange($event)">
|
|
4029
4243
|
@for (agent of agents(); track agent.id) {
|
|
4030
4244
|
<option [value]="agent.id" [selected]="agent.id === selectedAgentId()">
|
|
@@ -4033,12 +4247,12 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.33", ngImpo
|
|
|
4033
4247
|
}
|
|
4034
4248
|
</select>
|
|
4035
4249
|
@if (selected(); as agent) {
|
|
4036
|
-
<span class="capability" [attr.data-can-mutate]="agent.canMutate">
|
|
4250
|
+
<span class="capability" [id]="selectId + '-capability'" [class.visually-hidden]="compact()" [attr.data-can-mutate]="agent.canMutate">
|
|
4037
4251
|
{{ (agent.canMutate ? 'nh-assistant.agent-picker.can-mutate' : 'nh-assistant.agent-picker.read-only') | translate }}
|
|
4038
4252
|
</span>
|
|
4039
4253
|
}
|
|
4040
|
-
`, styles: [":host{--nha-font: var(--nh-assistant-font, inherit);--nha-background: var(--nh-assistant-background, #ffffff);--nha-surface: var(--nh-assistant-surface, #f5f7fb);--nha-surface-strong: var(--nh-assistant-surface-strong, #eceff6);--nha-text: var(--nh-assistant-text, #080c1d);--nha-text-muted: var(--nh-assistant-text-muted, #5b6482);--nha-border: var(--nh-assistant-border, #dce0ec);--nha-accent: var(--nh-assistant-accent, #022962);--nha-accent-contrast: var(--nh-assistant-accent-contrast, #ffffff);--nha-highlight: var(--nh-assistant-highlight, #c84f00);--nha-user-bubble: var(--nh-assistant-user-bubble, #022962);--nha-user-text: var(--nh-assistant-user-text, #ffffff);--nha-success: var(--nh-assistant-success, #247d4e);--nha-success-soft: var(--nh-assistant-success-soft, #e6f5ec);--nha-warning: var(--nh-assistant-warning, #8a5a00);--nha-warning-soft: var(--nh-assistant-warning-soft, #fff3d9);--nha-danger: var(--nh-assistant-danger, #b92e52);--nha-danger-soft: var(--nh-assistant-danger-soft, #ffe9ef);--nha-focus: var(--nh-assistant-focus, #ff6700);--nha-shadow: var(--nh-assistant-shadow, 0 16px 36px rgb(2 41 98 / .16));--nha-radius: var(--nh-assistant-radius, 16px);--nha-radius-control: var(--nh-assistant-radius-control, 12px);--nha-mono: var(--nh-assistant-font-mono, ui-monospace, \"Cascadia Code\", Consolas, monospace)}@media(prefers-color-scheme:dark){:host{--nha-background: var(--nh-assistant-background, #0b0e22);--nha-surface: var(--nh-assistant-surface, #11152d);--nha-surface-strong: var(--nh-assistant-surface-strong, #181d3b);--nha-text: var(--nh-assistant-text, #ffffff);--nha-text-muted: var(--nh-assistant-text-muted, #b8bed8);--nha-border: var(--nh-assistant-border, #2b3155);--nha-accent: var(--nh-assistant-accent, #0f4087);--nha-accent-contrast: var(--nh-assistant-accent-contrast, #ffffff);--nha-highlight: var(--nh-assistant-highlight, #ff6700);--nha-user-bubble: var(--nh-assistant-user-bubble, #022962);--nha-user-text: var(--nh-assistant-user-text, #ffffff);--nha-success: var(--nh-assistant-success, #67c58f);--nha-success-soft: var(--nh-assistant-success-soft, #102d24);--nha-warning: var(--nh-assistant-warning, #ffbf5b);--nha-warning-soft: var(--nh-assistant-warning-soft, #342818);--nha-danger: var(--nh-assistant-danger, #ff6d8a);--nha-danger-soft: var(--nh-assistant-danger-soft, #351b2a);--nha-shadow: var(--nh-assistant-shadow, 0 16px 36px rgb(0 0 0 / .32))}}:host{display:flex;flex-direction:column;gap:2px;min-width:0}select{align-self:flex-start;max-width:100%;min-height:32px;border:1px solid var(--nha-border);border-radius:var(--nha-radius-control);padding:4px 28px 4px 10px;color:var(--nha-text);background:var(--nha-background);font:inherit;font-size:13px;font-weight:650}select:focus-visible{outline:3px solid color-mix(in srgb,var(--nha-focus) 80%,transparent);outline-offset:2px}select:disabled{opacity:1;cursor:default}.capability{padding-left:2px;color:var(--nha-text-muted);font-size:11px}.capability[data-can-mutate=true]{color:var(--nha-warning)}.visually-hidden{position:absolute;width:1px;height:1px;overflow:hidden;clip:rect(0 0 0 0);clip-path:inset(50%);white-space:nowrap}\n"] }]
|
|
4041
|
-
}], propDecorators: { agents: [{ type: i0.Input, args: [{ isSignal: true, alias: "agents", required: true }] }], selectedAgentId: [{ type: i0.Input, args: [{ isSignal: true, alias: "selectedAgentId", required: false }] }], disabled: [{ type: i0.Input, args: [{ isSignal: true, alias: "disabled", required: false }] }], agentChange: [{ type: i0.Output, args: ["agentChange"] }] } });
|
|
4254
|
+
`, styles: [":host{--nha-font: var(--nh-assistant-font, inherit);--nha-background: var(--nh-assistant-background, #ffffff);--nha-surface: var(--nh-assistant-surface, #f5f7fb);--nha-surface-strong: var(--nh-assistant-surface-strong, #eceff6);--nha-text: var(--nh-assistant-text, #080c1d);--nha-text-muted: var(--nh-assistant-text-muted, #5b6482);--nha-border: var(--nh-assistant-border, #dce0ec);--nha-accent: var(--nh-assistant-accent, #022962);--nha-accent-contrast: var(--nh-assistant-accent-contrast, #ffffff);--nha-highlight: var(--nh-assistant-highlight, #c84f00);--nha-user-bubble: var(--nh-assistant-user-bubble, #022962);--nha-user-text: var(--nh-assistant-user-text, #ffffff);--nha-success: var(--nh-assistant-success, #247d4e);--nha-success-soft: var(--nh-assistant-success-soft, #e6f5ec);--nha-warning: var(--nh-assistant-warning, #8a5a00);--nha-warning-soft: var(--nh-assistant-warning-soft, #fff3d9);--nha-danger: var(--nh-assistant-danger, #b92e52);--nha-danger-soft: var(--nh-assistant-danger-soft, #ffe9ef);--nha-focus: var(--nh-assistant-focus, #ff6700);--nha-shadow: var(--nh-assistant-shadow, 0 16px 36px rgb(2 41 98 / .16));--nha-radius: var(--nh-assistant-radius, 16px);--nha-radius-control: var(--nh-assistant-radius-control, 12px);--nha-mono: var(--nh-assistant-font-mono, ui-monospace, \"Cascadia Code\", Consolas, monospace)}@media(prefers-color-scheme:dark){:host{--nha-background: var(--nh-assistant-background, #0b0e22);--nha-surface: var(--nh-assistant-surface, #11152d);--nha-surface-strong: var(--nh-assistant-surface-strong, #181d3b);--nha-text: var(--nh-assistant-text, #ffffff);--nha-text-muted: var(--nh-assistant-text-muted, #b8bed8);--nha-border: var(--nh-assistant-border, #2b3155);--nha-accent: var(--nh-assistant-accent, #0f4087);--nha-accent-contrast: var(--nh-assistant-accent-contrast, #ffffff);--nha-highlight: var(--nh-assistant-highlight, #ff6700);--nha-user-bubble: var(--nh-assistant-user-bubble, #022962);--nha-user-text: var(--nh-assistant-user-text, #ffffff);--nha-success: var(--nh-assistant-success, #67c58f);--nha-success-soft: var(--nh-assistant-success-soft, #102d24);--nha-warning: var(--nh-assistant-warning, #ffbf5b);--nha-warning-soft: var(--nh-assistant-warning-soft, #342818);--nha-danger: var(--nh-assistant-danger, #ff6d8a);--nha-danger-soft: var(--nh-assistant-danger-soft, #351b2a);--nha-shadow: var(--nh-assistant-shadow, 0 16px 36px rgb(0 0 0 / .32))}}:host{display:flex;flex-direction:column;gap:2px;min-width:0}:host(.compact){flex-direction:row;align-items:center}:host(.compact) select{min-width:0;max-width:100%;border-color:transparent;padding-left:8px;background:transparent;cursor:pointer}:host(.compact) select:hover:not(:disabled){border-color:var(--nha-border);background:var(--nha-surface-strong)}:host(.compact) select:disabled{cursor:default}select{align-self:flex-start;max-width:100%;min-height:32px;border:1px solid var(--nha-border);border-radius:var(--nha-radius-control);padding:4px 28px 4px 10px;color:var(--nha-text);background:var(--nha-background);font:inherit;font-size:13px;font-weight:650}select:focus-visible{outline:3px solid color-mix(in srgb,var(--nha-focus) 80%,transparent);outline-offset:2px}select:disabled{opacity:1;cursor:default}.capability{padding-left:2px;color:var(--nha-text-muted);font-size:11px}.capability[data-can-mutate=true]{color:var(--nha-warning)}.visually-hidden{position:absolute;width:1px;height:1px;overflow:hidden;clip:rect(0 0 0 0);clip-path:inset(50%);white-space:nowrap}\n"] }]
|
|
4255
|
+
}], propDecorators: { agents: [{ type: i0.Input, args: [{ isSignal: true, alias: "agents", required: true }] }], selectedAgentId: [{ type: i0.Input, args: [{ isSignal: true, alias: "selectedAgentId", required: false }] }], disabled: [{ type: i0.Input, args: [{ isSignal: true, alias: "disabled", required: false }] }], compact: [{ type: i0.Input, args: [{ isSignal: true, alias: "compact", required: false }] }], agentChange: [{ type: i0.Output, args: ["agentChange"] }] } });
|
|
4042
4256
|
|
|
4043
4257
|
let nextId$5 = 0;
|
|
4044
4258
|
/**
|
|
@@ -4053,6 +4267,8 @@ class NhAssistantComposerComponent {
|
|
|
4053
4267
|
this.sendDisabled = input(false, ...(ngDevMode ? [{ debugName: "sendDisabled" }] : []));
|
|
4054
4268
|
/** Shows the stop button instead of the send button. */
|
|
4055
4269
|
this.busy = input(false, ...(ngDevMode ? [{ debugName: "busy" }] : []));
|
|
4270
|
+
/** Keeps the send action available next to Stop so the host can queue messages. */
|
|
4271
|
+
this.queueWhileBusy = input(false, ...(ngDevMode ? [{ debugName: "queueWhileBusy" }] : []));
|
|
4056
4272
|
/** Announces why sending is temporarily unavailable. */
|
|
4057
4273
|
this.status = input(null, ...(ngDevMode ? [{ debugName: "status" }] : []));
|
|
4058
4274
|
/** Name of the participant whose turn runs or waits, when it is someone else. */
|
|
@@ -4141,12 +4357,12 @@ class NhAssistantComposerComponent {
|
|
|
4141
4357
|
}
|
|
4142
4358
|
}
|
|
4143
4359
|
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.3.33", ngImport: i0, type: NhAssistantComposerComponent, deps: [], target: i0.ɵɵFactoryTarget.Component }); }
|
|
4144
|
-
static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "20.3.33", type: NhAssistantComposerComponent, isStandalone: true, selector: "nh-assistant-composer", inputs: { disabled: { classPropertyName: "disabled", publicName: "disabled", isSignal: true, isRequired: false, transformFunction: null }, sendDisabled: { classPropertyName: "sendDisabled", publicName: "sendDisabled", isSignal: true, isRequired: false, transformFunction: null }, busy: { classPropertyName: "busy", publicName: "busy", isSignal: true, isRequired: false, transformFunction: null }, status: { classPropertyName: "status", publicName: "status", isSignal: true, isRequired: false, transformFunction: null }, statusActor: { classPropertyName: "statusActor", publicName: "statusActor", isSignal: true, isRequired: false, transformFunction: null }, canStop: { classPropertyName: "canStop", publicName: "canStop", isSignal: true, isRequired: false, transformFunction: null }, maxLength: { classPropertyName: "maxLength", publicName: "maxLength", isSignal: true, isRequired: false, transformFunction: null }, restore: { classPropertyName: "restore", publicName: "restore", isSignal: true, isRequired: false, transformFunction: null } }, outputs: { send: "send", cancel: "cancel", restored: "restored" }, host: { listeners: { "focusin": "onFocusIn()", "focusout": "onFocusOut($event)" } }, viewQueries: [{ propertyName: "textarea", first: true, predicate: ["textarea"], descendants: true, isSignal: true }], ngImport: i0, template: "<form class=\"composer\" (submit)=\"onSubmit($event)\">\n <label class=\"visually-hidden\" [for]=\"inputId\">{{ 'nh-assistant.composer.label' | translate }}</label>\n <textarea\n #textarea\n data-nh-assistant-autofocus\n rows=\"2\"\n [id]=\"inputId\"\n [value]=\"text()\"\n [disabled]=\"disabled()\"\n [attr.placeholder]=\"'nh-assistant.composer.placeholder' | translate\"\n [attr.aria-describedby]=\"hintId\"\n [attr.aria-invalid]=\"tooLong() ? true : null\"\n (input)=\"onInput($event)\"\n (keydown)=\"onKeydown($event)\"></textarea>\n\n <div class=\"actions\">\n
|
|
4360
|
+
static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "20.3.33", type: NhAssistantComposerComponent, isStandalone: true, selector: "nh-assistant-composer", inputs: { disabled: { classPropertyName: "disabled", publicName: "disabled", isSignal: true, isRequired: false, transformFunction: null }, sendDisabled: { classPropertyName: "sendDisabled", publicName: "sendDisabled", isSignal: true, isRequired: false, transformFunction: null }, busy: { classPropertyName: "busy", publicName: "busy", isSignal: true, isRequired: false, transformFunction: null }, queueWhileBusy: { classPropertyName: "queueWhileBusy", publicName: "queueWhileBusy", isSignal: true, isRequired: false, transformFunction: null }, status: { classPropertyName: "status", publicName: "status", isSignal: true, isRequired: false, transformFunction: null }, statusActor: { classPropertyName: "statusActor", publicName: "statusActor", isSignal: true, isRequired: false, transformFunction: null }, canStop: { classPropertyName: "canStop", publicName: "canStop", isSignal: true, isRequired: false, transformFunction: null }, maxLength: { classPropertyName: "maxLength", publicName: "maxLength", isSignal: true, isRequired: false, transformFunction: null }, restore: { classPropertyName: "restore", publicName: "restore", isSignal: true, isRequired: false, transformFunction: null } }, outputs: { send: "send", cancel: "cancel", restored: "restored" }, host: { listeners: { "focusin": "onFocusIn()", "focusout": "onFocusOut($event)" } }, viewQueries: [{ propertyName: "textarea", first: true, predicate: ["textarea"], descendants: true, isSignal: true }], ngImport: i0, template: "<form class=\"composer\" (submit)=\"onSubmit($event)\">\n <label class=\"visually-hidden\" [for]=\"inputId\">{{ 'nh-assistant.composer.label' | translate }}</label>\n <textarea\n #textarea\n data-nh-assistant-autofocus\n rows=\"2\"\n [id]=\"inputId\"\n [value]=\"text()\"\n [disabled]=\"disabled()\"\n [attr.placeholder]=\"'nh-assistant.composer.placeholder' | translate\"\n [attr.aria-describedby]=\"hintId\"\n [attr.aria-invalid]=\"tooLong() ? true : null\"\n (input)=\"onInput($event)\"\n (keydown)=\"onKeydown($event)\"></textarea>\n\n <div class=\"prompt-bar\">\n <div class=\"prompt-controls\">\n <ng-content select=\"[nhAssistantComposerControls]\" />\n </div>\n <div class=\"actions\">\n @if (busy() && canStop()) {\n <button\n class=\"stop\"\n type=\"button\"\n [attr.aria-label]=\"'nh-assistant.composer.stop' | translate\"\n [attr.title]=\"'nh-assistant.composer.stop' | translate\"\n (click)=\"cancel.emit()\">\n <nh-assistant-icon name=\"stop\" />\n </button>\n }\n @if (!busy() || !canStop() || queueWhileBusy()) {\n <button\n class=\"send\"\n type=\"submit\"\n [disabled]=\"!canSend()\"\n [attr.aria-label]=\"(busy() && queueWhileBusy() ? 'nh-assistant.queue.add' : 'nh-assistant.composer.send') | translate\"\n [attr.title]=\"(busy() && queueWhileBusy() ? 'nh-assistant.queue.add' : 'nh-assistant.composer.send') | translate\">\n <nh-assistant-icon name=\"send\" />\n </button>\n }\n </div>\n </div>\n</form>\n\n@if (status() === 'waiting-for-approval') {\n <p class=\"composer-status\" role=\"status\" aria-live=\"polite\">\n @if (statusActor(); as name) {\n {{ 'nh-assistant.composer.status.waiting-for-approval-by' | translate: { name } }}\n } @else {\n {{ 'nh-assistant.composer.status.waiting-for-approval' | translate }}\n }\n </p>\n}\n\n<p class=\"hint\" [id]=\"hintId\">\n @if (tooLong()) {\n <span class=\"error\">{{ 'nh-assistant.composer.too-long' | translate }}</span>\n } @else {\n <span>{{ (busy() && queueWhileBusy() ? 'nh-assistant.queue.hint' : 'nh-assistant.composer.hint') | translate }}</span>\n }\n @if (showCounter()) {\n <span class=\"counter\" [class.error]=\"tooLong()\">\n {{ 'nh-assistant.composer.characters' | translate: { count: length(), max: maxLength() } }}\n </span>\n }\n</p>\n", styles: [":host{--nha-font: var(--nh-assistant-font, inherit);--nha-background: var(--nh-assistant-background, #ffffff);--nha-surface: var(--nh-assistant-surface, #f5f7fb);--nha-surface-strong: var(--nh-assistant-surface-strong, #eceff6);--nha-text: var(--nh-assistant-text, #080c1d);--nha-text-muted: var(--nh-assistant-text-muted, #5b6482);--nha-border: var(--nh-assistant-border, #dce0ec);--nha-accent: var(--nh-assistant-accent, #022962);--nha-accent-contrast: var(--nh-assistant-accent-contrast, #ffffff);--nha-highlight: var(--nh-assistant-highlight, #c84f00);--nha-user-bubble: var(--nh-assistant-user-bubble, #022962);--nha-user-text: var(--nh-assistant-user-text, #ffffff);--nha-success: var(--nh-assistant-success, #247d4e);--nha-success-soft: var(--nh-assistant-success-soft, #e6f5ec);--nha-warning: var(--nh-assistant-warning, #8a5a00);--nha-warning-soft: var(--nh-assistant-warning-soft, #fff3d9);--nha-danger: var(--nh-assistant-danger, #b92e52);--nha-danger-soft: var(--nh-assistant-danger-soft, #ffe9ef);--nha-focus: var(--nh-assistant-focus, #ff6700);--nha-shadow: var(--nh-assistant-shadow, 0 16px 36px rgb(2 41 98 / .16));--nha-radius: var(--nh-assistant-radius, 16px);--nha-radius-control: var(--nh-assistant-radius-control, 12px);--nha-mono: var(--nh-assistant-font-mono, ui-monospace, \"Cascadia Code\", Consolas, monospace)}@media(prefers-color-scheme:dark){:host{--nha-background: var(--nh-assistant-background, #0b0e22);--nha-surface: var(--nh-assistant-surface, #11152d);--nha-surface-strong: var(--nh-assistant-surface-strong, #181d3b);--nha-text: var(--nh-assistant-text, #ffffff);--nha-text-muted: var(--nh-assistant-text-muted, #b8bed8);--nha-border: var(--nh-assistant-border, #2b3155);--nha-accent: var(--nh-assistant-accent, #0f4087);--nha-accent-contrast: var(--nh-assistant-accent-contrast, #ffffff);--nha-highlight: var(--nh-assistant-highlight, #ff6700);--nha-user-bubble: var(--nh-assistant-user-bubble, #022962);--nha-user-text: var(--nh-assistant-user-text, #ffffff);--nha-success: var(--nh-assistant-success, #67c58f);--nha-success-soft: var(--nh-assistant-success-soft, #102d24);--nha-warning: var(--nh-assistant-warning, #ffbf5b);--nha-warning-soft: var(--nh-assistant-warning-soft, #342818);--nha-danger: var(--nh-assistant-danger, #ff6d8a);--nha-danger-soft: var(--nh-assistant-danger-soft, #351b2a);--nha-shadow: var(--nh-assistant-shadow, 0 16px 36px rgb(0 0 0 / .32))}}:host{display:block}.composer{display:flex;flex-direction:column;gap:8px;border:1px solid var(--nha-border);border-radius:var(--nha-radius-control);padding:8px 8px 8px 14px;background:var(--nha-surface);box-shadow:0 2px 6px color-mix(in srgb,var(--nha-text) 4%,transparent)}.composer:focus-within{border-color:var(--nha-focus);box-shadow:0 0 0 2px color-mix(in srgb,var(--nha-focus) 16%,transparent)}textarea{width:100%;min-width:0;min-height:44px;max-height:180px;border:0;padding:6px 0;color:var(--nha-text);background:transparent;font:inherit;font-size:14px;line-height:1.45;resize:vertical;outline:none}textarea::placeholder{color:var(--nha-text-muted);opacity:1}textarea:disabled{cursor:not-allowed}.prompt-bar{display:flex;align-items:center;gap:8px;min-width:0}.prompt-controls{flex:1;min-width:0}.actions{display:flex;flex-shrink:0;gap:6px}.send,.stop{display:inline-flex;align-items:center;justify-content:center;width:36px;height:36px;padding:0;border:1px solid transparent;border-radius:var(--nha-radius-control);color:var(--nha-text-muted);background:transparent;cursor:pointer;width:40px;height:40px}.send:focus-visible,.stop:focus-visible{outline:3px solid color-mix(in srgb,var(--nha-focus) 80%,transparent);outline-offset:2px}.send:hover:not(:disabled),.stop:hover:not(:disabled){color:var(--nha-text);background:var(--nha-surface-strong)}.send:disabled,.stop:disabled{cursor:not-allowed;opacity:.5}.send:not(:disabled){color:var(--nha-accent-contrast);background:var(--nha-accent)}.send:not(:disabled):hover{color:var(--nha-accent-contrast);background:var(--nha-accent);filter:brightness(1.12)}.stop{color:var(--nha-danger);border-color:var(--nha-danger)}.hint,.composer-status{display:flex;justify-content:space-between;gap:8px;margin:6px 2px 0;color:var(--nha-text-muted);font-size:11px}.composer-status{margin-bottom:0}.counter{flex:none;font-variant-numeric:tabular-nums}.error{color:var(--nha-danger)}.visually-hidden{position:absolute;width:1px;height:1px;overflow:hidden;clip:rect(0 0 0 0);clip-path:inset(50%);white-space:nowrap}\n"], dependencies: [{ kind: "component", type: NhAssistantIconComponent, selector: "nh-assistant-icon", inputs: ["name"] }, { kind: "pipe", type: TranslatePipe, name: "translate" }], changeDetection: i0.ChangeDetectionStrategy.OnPush }); }
|
|
4145
4361
|
}
|
|
4146
4362
|
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.33", ngImport: i0, type: NhAssistantComposerComponent, decorators: [{
|
|
4147
4363
|
type: Component,
|
|
4148
|
-
args: [{ selector: 'nh-assistant-composer', standalone: true, imports: [TranslatePipe, NhAssistantIconComponent], changeDetection: ChangeDetectionStrategy.OnPush, template: "<form class=\"composer\" (submit)=\"onSubmit($event)\">\n <label class=\"visually-hidden\" [for]=\"inputId\">{{ 'nh-assistant.composer.label' | translate }}</label>\n <textarea\n #textarea\n data-nh-assistant-autofocus\n rows=\"2\"\n [id]=\"inputId\"\n [value]=\"text()\"\n [disabled]=\"disabled()\"\n [attr.placeholder]=\"'nh-assistant.composer.placeholder' | translate\"\n [attr.aria-describedby]=\"hintId\"\n [attr.aria-invalid]=\"tooLong() ? true : null\"\n (input)=\"onInput($event)\"\n (keydown)=\"onKeydown($event)\"></textarea>\n\n <div class=\"actions\">\n
|
|
4149
|
-
}], ctorParameters: () => [], propDecorators: { disabled: [{ type: i0.Input, args: [{ isSignal: true, alias: "disabled", required: false }] }], sendDisabled: [{ type: i0.Input, args: [{ isSignal: true, alias: "sendDisabled", required: false }] }], busy: [{ type: i0.Input, args: [{ isSignal: true, alias: "busy", required: false }] }], status: [{ type: i0.Input, args: [{ isSignal: true, alias: "status", required: false }] }], statusActor: [{ type: i0.Input, args: [{ isSignal: true, alias: "statusActor", required: false }] }], canStop: [{ type: i0.Input, args: [{ isSignal: true, alias: "canStop", required: false }] }], maxLength: [{ type: i0.Input, args: [{ isSignal: true, alias: "maxLength", required: false }] }], restore: [{ type: i0.Input, args: [{ isSignal: true, alias: "restore", required: false }] }], send: [{ type: i0.Output, args: ["send"] }], cancel: [{ type: i0.Output, args: ["cancel"] }], restored: [{ type: i0.Output, args: ["restored"] }], textarea: [{ type: i0.ViewChild, args: ['textarea', { isSignal: true }] }], onFocusIn: [{
|
|
4364
|
+
args: [{ selector: 'nh-assistant-composer', standalone: true, imports: [TranslatePipe, NhAssistantIconComponent], changeDetection: ChangeDetectionStrategy.OnPush, template: "<form class=\"composer\" (submit)=\"onSubmit($event)\">\n <label class=\"visually-hidden\" [for]=\"inputId\">{{ 'nh-assistant.composer.label' | translate }}</label>\n <textarea\n #textarea\n data-nh-assistant-autofocus\n rows=\"2\"\n [id]=\"inputId\"\n [value]=\"text()\"\n [disabled]=\"disabled()\"\n [attr.placeholder]=\"'nh-assistant.composer.placeholder' | translate\"\n [attr.aria-describedby]=\"hintId\"\n [attr.aria-invalid]=\"tooLong() ? true : null\"\n (input)=\"onInput($event)\"\n (keydown)=\"onKeydown($event)\"></textarea>\n\n <div class=\"prompt-bar\">\n <div class=\"prompt-controls\">\n <ng-content select=\"[nhAssistantComposerControls]\" />\n </div>\n <div class=\"actions\">\n @if (busy() && canStop()) {\n <button\n class=\"stop\"\n type=\"button\"\n [attr.aria-label]=\"'nh-assistant.composer.stop' | translate\"\n [attr.title]=\"'nh-assistant.composer.stop' | translate\"\n (click)=\"cancel.emit()\">\n <nh-assistant-icon name=\"stop\" />\n </button>\n }\n @if (!busy() || !canStop() || queueWhileBusy()) {\n <button\n class=\"send\"\n type=\"submit\"\n [disabled]=\"!canSend()\"\n [attr.aria-label]=\"(busy() && queueWhileBusy() ? 'nh-assistant.queue.add' : 'nh-assistant.composer.send') | translate\"\n [attr.title]=\"(busy() && queueWhileBusy() ? 'nh-assistant.queue.add' : 'nh-assistant.composer.send') | translate\">\n <nh-assistant-icon name=\"send\" />\n </button>\n }\n </div>\n </div>\n</form>\n\n@if (status() === 'waiting-for-approval') {\n <p class=\"composer-status\" role=\"status\" aria-live=\"polite\">\n @if (statusActor(); as name) {\n {{ 'nh-assistant.composer.status.waiting-for-approval-by' | translate: { name } }}\n } @else {\n {{ 'nh-assistant.composer.status.waiting-for-approval' | translate }}\n }\n </p>\n}\n\n<p class=\"hint\" [id]=\"hintId\">\n @if (tooLong()) {\n <span class=\"error\">{{ 'nh-assistant.composer.too-long' | translate }}</span>\n } @else {\n <span>{{ (busy() && queueWhileBusy() ? 'nh-assistant.queue.hint' : 'nh-assistant.composer.hint') | translate }}</span>\n }\n @if (showCounter()) {\n <span class=\"counter\" [class.error]=\"tooLong()\">\n {{ 'nh-assistant.composer.characters' | translate: { count: length(), max: maxLength() } }}\n </span>\n }\n</p>\n", styles: [":host{--nha-font: var(--nh-assistant-font, inherit);--nha-background: var(--nh-assistant-background, #ffffff);--nha-surface: var(--nh-assistant-surface, #f5f7fb);--nha-surface-strong: var(--nh-assistant-surface-strong, #eceff6);--nha-text: var(--nh-assistant-text, #080c1d);--nha-text-muted: var(--nh-assistant-text-muted, #5b6482);--nha-border: var(--nh-assistant-border, #dce0ec);--nha-accent: var(--nh-assistant-accent, #022962);--nha-accent-contrast: var(--nh-assistant-accent-contrast, #ffffff);--nha-highlight: var(--nh-assistant-highlight, #c84f00);--nha-user-bubble: var(--nh-assistant-user-bubble, #022962);--nha-user-text: var(--nh-assistant-user-text, #ffffff);--nha-success: var(--nh-assistant-success, #247d4e);--nha-success-soft: var(--nh-assistant-success-soft, #e6f5ec);--nha-warning: var(--nh-assistant-warning, #8a5a00);--nha-warning-soft: var(--nh-assistant-warning-soft, #fff3d9);--nha-danger: var(--nh-assistant-danger, #b92e52);--nha-danger-soft: var(--nh-assistant-danger-soft, #ffe9ef);--nha-focus: var(--nh-assistant-focus, #ff6700);--nha-shadow: var(--nh-assistant-shadow, 0 16px 36px rgb(2 41 98 / .16));--nha-radius: var(--nh-assistant-radius, 16px);--nha-radius-control: var(--nh-assistant-radius-control, 12px);--nha-mono: var(--nh-assistant-font-mono, ui-monospace, \"Cascadia Code\", Consolas, monospace)}@media(prefers-color-scheme:dark){:host{--nha-background: var(--nh-assistant-background, #0b0e22);--nha-surface: var(--nh-assistant-surface, #11152d);--nha-surface-strong: var(--nh-assistant-surface-strong, #181d3b);--nha-text: var(--nh-assistant-text, #ffffff);--nha-text-muted: var(--nh-assistant-text-muted, #b8bed8);--nha-border: var(--nh-assistant-border, #2b3155);--nha-accent: var(--nh-assistant-accent, #0f4087);--nha-accent-contrast: var(--nh-assistant-accent-contrast, #ffffff);--nha-highlight: var(--nh-assistant-highlight, #ff6700);--nha-user-bubble: var(--nh-assistant-user-bubble, #022962);--nha-user-text: var(--nh-assistant-user-text, #ffffff);--nha-success: var(--nh-assistant-success, #67c58f);--nha-success-soft: var(--nh-assistant-success-soft, #102d24);--nha-warning: var(--nh-assistant-warning, #ffbf5b);--nha-warning-soft: var(--nh-assistant-warning-soft, #342818);--nha-danger: var(--nh-assistant-danger, #ff6d8a);--nha-danger-soft: var(--nh-assistant-danger-soft, #351b2a);--nha-shadow: var(--nh-assistant-shadow, 0 16px 36px rgb(0 0 0 / .32))}}:host{display:block}.composer{display:flex;flex-direction:column;gap:8px;border:1px solid var(--nha-border);border-radius:var(--nha-radius-control);padding:8px 8px 8px 14px;background:var(--nha-surface);box-shadow:0 2px 6px color-mix(in srgb,var(--nha-text) 4%,transparent)}.composer:focus-within{border-color:var(--nha-focus);box-shadow:0 0 0 2px color-mix(in srgb,var(--nha-focus) 16%,transparent)}textarea{width:100%;min-width:0;min-height:44px;max-height:180px;border:0;padding:6px 0;color:var(--nha-text);background:transparent;font:inherit;font-size:14px;line-height:1.45;resize:vertical;outline:none}textarea::placeholder{color:var(--nha-text-muted);opacity:1}textarea:disabled{cursor:not-allowed}.prompt-bar{display:flex;align-items:center;gap:8px;min-width:0}.prompt-controls{flex:1;min-width:0}.actions{display:flex;flex-shrink:0;gap:6px}.send,.stop{display:inline-flex;align-items:center;justify-content:center;width:36px;height:36px;padding:0;border:1px solid transparent;border-radius:var(--nha-radius-control);color:var(--nha-text-muted);background:transparent;cursor:pointer;width:40px;height:40px}.send:focus-visible,.stop:focus-visible{outline:3px solid color-mix(in srgb,var(--nha-focus) 80%,transparent);outline-offset:2px}.send:hover:not(:disabled),.stop:hover:not(:disabled){color:var(--nha-text);background:var(--nha-surface-strong)}.send:disabled,.stop:disabled{cursor:not-allowed;opacity:.5}.send:not(:disabled){color:var(--nha-accent-contrast);background:var(--nha-accent)}.send:not(:disabled):hover{color:var(--nha-accent-contrast);background:var(--nha-accent);filter:brightness(1.12)}.stop{color:var(--nha-danger);border-color:var(--nha-danger)}.hint,.composer-status{display:flex;justify-content:space-between;gap:8px;margin:6px 2px 0;color:var(--nha-text-muted);font-size:11px}.composer-status{margin-bottom:0}.counter{flex:none;font-variant-numeric:tabular-nums}.error{color:var(--nha-danger)}.visually-hidden{position:absolute;width:1px;height:1px;overflow:hidden;clip:rect(0 0 0 0);clip-path:inset(50%);white-space:nowrap}\n"] }]
|
|
4365
|
+
}], ctorParameters: () => [], propDecorators: { disabled: [{ type: i0.Input, args: [{ isSignal: true, alias: "disabled", required: false }] }], sendDisabled: [{ type: i0.Input, args: [{ isSignal: true, alias: "sendDisabled", required: false }] }], busy: [{ type: i0.Input, args: [{ isSignal: true, alias: "busy", required: false }] }], queueWhileBusy: [{ type: i0.Input, args: [{ isSignal: true, alias: "queueWhileBusy", required: false }] }], status: [{ type: i0.Input, args: [{ isSignal: true, alias: "status", required: false }] }], statusActor: [{ type: i0.Input, args: [{ isSignal: true, alias: "statusActor", required: false }] }], canStop: [{ type: i0.Input, args: [{ isSignal: true, alias: "canStop", required: false }] }], maxLength: [{ type: i0.Input, args: [{ isSignal: true, alias: "maxLength", required: false }] }], restore: [{ type: i0.Input, args: [{ isSignal: true, alias: "restore", required: false }] }], send: [{ type: i0.Output, args: ["send"] }], cancel: [{ type: i0.Output, args: ["cancel"] }], restored: [{ type: i0.Output, args: ["restored"] }], textarea: [{ type: i0.ViewChild, args: ['textarea', { isSignal: true }] }], onFocusIn: [{
|
|
4150
4366
|
type: HostListener,
|
|
4151
4367
|
args: ['focusin']
|
|
4152
4368
|
}], onFocusOut: [{
|
|
@@ -4333,6 +4549,8 @@ class NhAssistantShareComponent {
|
|
|
4333
4549
|
this.searchRevision = 0;
|
|
4334
4550
|
/** Emitted when the user leaves the view. */
|
|
4335
4551
|
this.closed = output();
|
|
4552
|
+
/** Show the invitation link, participants, or both (the default for custom hosts). */
|
|
4553
|
+
this.section = input('all', ...(ngDevMode ? [{ debugName: "section" }] : []));
|
|
4336
4554
|
this.id = `nh-assistant-share-${nextId$3++}`;
|
|
4337
4555
|
this.conversation = this.store.activeConversation;
|
|
4338
4556
|
this.isOwner = this.store.isOwner;
|
|
@@ -4435,12 +4653,12 @@ class NhAssistantShareComponent {
|
|
|
4435
4653
|
}
|
|
4436
4654
|
}
|
|
4437
4655
|
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.3.33", ngImport: i0, type: NhAssistantShareComponent, deps: [], target: i0.ɵɵFactoryTarget.Component }); }
|
|
4438
|
-
static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "20.3.33", type: NhAssistantShareComponent, isStandalone: true, selector: "nh-assistant-share", outputs: { closed: "closed" }, ngImport: i0, template: "<section class=\"share\" [attr.aria-labelledby]=\"id + '-title'\" [attr.aria-busy]=\"busy()\">\n <header class=\"header\">\n <h3 [id]=\"id + '-title'\">\n {{ (isOwner() ? 'nh-assistant.share.title' : 'nh-assistant.share.members-title') | translate }}\n </h3>\n <button\n class=\"icon-button\"\n type=\"button\"\n [attr.aria-label]=\"'nh-assistant.share.back' | translate\"\n [attr.title]=\"'nh-assistant.share.back' | translate\"\n (click)=\"closed.emit()\">\n <nh-assistant-icon name=\"close\" />\n </button>\n </header>\n\n @if (conversation(); as conversation) {\n <div class=\"content\">\n @if (isOwner()) {\n <p class=\"description\">{{ 'nh-assistant.share.description' | translate }}</p>\n\n <section class=\"block\" [attr.aria-labelledby]=\"id + '-link'\">\n <h4 [id]=\"id + '-link'\">{{ 'nh-assistant.share.link-title' | translate }}</h4>\n @if (link(); as link) {\n <div class=\"link-row\">\n <label class=\"visually-hidden\" [for]=\"id + '-link-input'\">{{ 'nh-assistant.share.link-label' | translate }}</label>\n <input #linkInput type=\"text\" readonly [id]=\"id + '-link-input'\" [value]=\"link\" (focus)=\"linkInput.select()\" />\n <button\n class=\"icon-button\"\n type=\"button\"\n [attr.aria-label]=\"'nh-assistant.share.copy' | translate\"\n [attr.title]=\"'nh-assistant.share.copy' | translate\"\n (click)=\"copy(linkInput)\">\n <nh-assistant-icon name=\"copy\" />\n </button>\n </div>\n @if (copied()) {\n <p class=\"message success\" role=\"status\">\n <nh-assistant-icon name=\"check\" />\n {{ 'nh-assistant.share.copied' | translate }}\n </p>\n }\n <div class=\"actions\">\n <button class=\"secondary\" type=\"button\" [disabled]=\"busy()\" (click)=\"revokeLink()\">\n {{ 'nh-assistant.share.revoke' | translate }}\n </button>\n <button class=\"secondary\" type=\"button\" [disabled]=\"busy()\" (click)=\"createLink()\">\n {{ 'nh-assistant.share.renew' | translate }}\n </button>\n </div>\n <p class=\"hint\">{{ 'nh-assistant.share.link-hint' | translate }}</p>\n } @else {\n <button class=\"primary\" type=\"button\" [disabled]=\"busy() || full()\" (click)=\"createLink()\">\n <nh-assistant-icon name=\"link\" />\n {{ 'nh-assistant.share.create' | translate }}\n </button>\n }\n </section>\n\n @if (directory()) {\n <section class=\"block\" [attr.aria-labelledby]=\"id + '-invite'\">\n <h4 [id]=\"id + '-invite'\">{{ 'nh-assistant.share.invite-title' | translate }}</h4>\n <label class=\"visually-hidden\" [for]=\"id + '-search'\">{{ 'nh-assistant.share.search-label' | translate }}</label>\n <input\n type=\"search\"\n autocomplete=\"off\"\n [id]=\"id + '-search'\"\n [value]=\"query()\"\n [disabled]=\"full()\"\n [attr.placeholder]=\"'nh-assistant.share.search-placeholder' | translate\"\n (input)=\"onSearch($event)\" />\n @if (searching()) {\n <p class=\"hint\" role=\"status\">{{ 'nh-assistant.share.searching' | translate }}</p>\n } @else if (query().trim().length >= 2 && candidates().length === 0 && !invited()) {\n <p class=\"hint\">{{ 'nh-assistant.share.no-results' | translate }}</p>\n }\n @if (candidates().length > 0) {\n <ul class=\"people\">\n @for (entry of candidates(); track entry.actorId) {\n <li>\n <span class=\"person\">\n <strong>{{ entry.displayName }}</strong>\n @if (entry.detail) {\n <small>{{ entry.detail }}</small>\n }\n </span>\n <button class=\"secondary small\" type=\"button\" [disabled]=\"busy() || full()\" (click)=\"invite(entry)\">\n {{ 'nh-assistant.share.invite' | translate }}\n </button>\n </li>\n }\n </ul>\n }\n @if (invited(); as name) {\n <p class=\"message success\" role=\"status\">\n <nh-assistant-icon name=\"check\" />\n {{ 'nh-assistant.share.invited' | translate: { name } }}\n </p>\n }\n </section>\n }\n }\n\n <section class=\"block\" [attr.aria-labelledby]=\"id + '-members'\">\n <h4 [id]=\"id + '-members'\">\n {{ 'nh-assistant.share.members' | translate }}\n @if (maxParticipants() !== null && isOwner()) {\n <span class=\"count\">{{ 'nh-assistant.share.count' | translate: { count: participants().length, max: maxParticipants() } }}</span>\n }\n </h4>\n @if (store.members().length === 0) {\n <p class=\"hint\">{{ 'nh-assistant.share.not-shared' | translate }}</p>\n } @else {\n <ul class=\"people\">\n @for (member of store.members(); track member.actorId) {\n <li>\n <span class=\"person\">\n <strong>\n {{ member.displayName || ('nh-assistant.share.unnamed' | translate) }}\n @if (isCurrentUser(member)) {\n <small class=\"you\">{{ 'nh-assistant.share.you' | translate }}</small>\n }\n </strong>\n <small>{{ 'nh-assistant.share.role.' + member.role | translate }}</small>\n </span>\n @if (isOwner() && member.role === 'participant') {\n <button\n class=\"icon-button\"\n type=\"button\"\n [disabled]=\"busy()\"\n [attr.aria-label]=\"'nh-assistant.share.remove' | translate: { name: member.displayName || ('nh-assistant.share.unnamed' | translate) }\"\n [attr.title]=\"'nh-assistant.share.remove' | translate: { name: member.displayName || ('nh-assistant.share.unnamed' | translate) }\"\n (click)=\"remove(member)\">\n <nh-assistant-icon name=\"trash\" />\n </button>\n }\n </li>\n }\n </ul>\n }\n </section>\n\n @if (!isOwner()) {\n <div class=\"actions\">\n <button class=\"secondary danger\" type=\"button\" [disabled]=\"busy() || conversation.status === 'running'\" (click)=\"leave()\">\n <nh-assistant-icon name=\"leave\" />\n {{ 'nh-assistant.share.leave' | translate }}\n </button>\n </div>\n }\n </div>\n } @else {\n <p class=\"state\">{{ 'nh-assistant.share.no-conversation' | translate }}</p>\n }\n</section>\n", styles: [":host{--nha-font: var(--nh-assistant-font, inherit);--nha-background: var(--nh-assistant-background, #ffffff);--nha-surface: var(--nh-assistant-surface, #f5f7fb);--nha-surface-strong: var(--nh-assistant-surface-strong, #eceff6);--nha-text: var(--nh-assistant-text, #080c1d);--nha-text-muted: var(--nh-assistant-text-muted, #5b6482);--nha-border: var(--nh-assistant-border, #dce0ec);--nha-accent: var(--nh-assistant-accent, #022962);--nha-accent-contrast: var(--nh-assistant-accent-contrast, #ffffff);--nha-highlight: var(--nh-assistant-highlight, #c84f00);--nha-user-bubble: var(--nh-assistant-user-bubble, #022962);--nha-user-text: var(--nh-assistant-user-text, #ffffff);--nha-success: var(--nh-assistant-success, #247d4e);--nha-success-soft: var(--nh-assistant-success-soft, #e6f5ec);--nha-warning: var(--nh-assistant-warning, #8a5a00);--nha-warning-soft: var(--nh-assistant-warning-soft, #fff3d9);--nha-danger: var(--nh-assistant-danger, #b92e52);--nha-danger-soft: var(--nh-assistant-danger-soft, #ffe9ef);--nha-focus: var(--nh-assistant-focus, #ff6700);--nha-shadow: var(--nh-assistant-shadow, 0 16px 36px rgb(2 41 98 / .16));--nha-radius: var(--nh-assistant-radius, 16px);--nha-radius-control: var(--nh-assistant-radius-control, 12px);--nha-mono: var(--nh-assistant-font-mono, ui-monospace, \"Cascadia Code\", Consolas, monospace)}@media(prefers-color-scheme:dark){:host{--nha-background: var(--nh-assistant-background, #0b0e22);--nha-surface: var(--nh-assistant-surface, #11152d);--nha-surface-strong: var(--nh-assistant-surface-strong, #181d3b);--nha-text: var(--nh-assistant-text, #ffffff);--nha-text-muted: var(--nh-assistant-text-muted, #b8bed8);--nha-border: var(--nh-assistant-border, #2b3155);--nha-accent: var(--nh-assistant-accent, #0f4087);--nha-accent-contrast: var(--nh-assistant-accent-contrast, #ffffff);--nha-highlight: var(--nh-assistant-highlight, #ff6700);--nha-user-bubble: var(--nh-assistant-user-bubble, #022962);--nha-user-text: var(--nh-assistant-user-text, #ffffff);--nha-success: var(--nh-assistant-success, #67c58f);--nha-success-soft: var(--nh-assistant-success-soft, #102d24);--nha-warning: var(--nh-assistant-warning, #ffbf5b);--nha-warning-soft: var(--nh-assistant-warning-soft, #342818);--nha-danger: var(--nh-assistant-danger, #ff6d8a);--nha-danger-soft: var(--nh-assistant-danger-soft, #351b2a);--nha-shadow: var(--nh-assistant-shadow, 0 16px 36px rgb(0 0 0 / .32))}}:host{display:flex;flex-direction:column;min-height:0;color:var(--nha-text)}:host fieldset{min-width:0;margin:0;border:0;padding:0}:host legend,:host .label,:host .field>label{display:block;margin-bottom:6px;padding:0;color:var(--nha-text);font-size:12px;font-weight:700}:host input[type=text],:host input[type=url],:host input[type=password],:host input[type=search],:host select,:host textarea{width:100%;min-width:0;min-height:38px;border:1px solid var(--nha-border);border-radius:var(--nha-radius-control);padding:8px 10px;color:var(--nha-text);background:var(--nha-background);font:inherit;font-size:13px}:host input[type=text]:focus-visible,:host input[type=url]:focus-visible,:host input[type=password]:focus-visible,:host input[type=search]:focus-visible,:host select:focus-visible,:host textarea:focus-visible{outline:3px solid color-mix(in srgb,var(--nha-focus) 80%,transparent);outline-offset:2px}:host input[type=text]:disabled,:host input[type=url]:disabled,:host input[type=password]:disabled,:host input[type=search]:disabled,:host select:disabled,:host textarea:disabled{cursor:not-allowed;opacity:.6}:host input[type=text][aria-invalid=true],:host input[type=url][aria-invalid=true],:host input[type=password][aria-invalid=true],:host input[type=search][aria-invalid=true],:host select[aria-invalid=true],:host textarea[aria-invalid=true]{border-color:var(--nha-danger)}:host textarea{line-height:1.45;resize:vertical}:host .mono{font-family:var(--nha-mono);font-size:12px}:host .field{display:flex;flex-direction:column;min-width:0}:host .hint{display:flex;justify-content:space-between;gap:8px;margin:4px 2px 0;color:var(--nha-text-muted);font-size:11px}:host .counter{flex:none;font-variant-numeric:tabular-nums}:host .error-text{color:var(--nha-danger)}:host .message{display:flex;align-items:center;gap:8px;margin:0;border:1px solid transparent;border-radius:var(--nha-radius-control);padding:8px 12px;font-size:13px}:host .message.error{border-color:var(--nha-danger);color:var(--nha-text);background:var(--nha-danger-soft)}:host .message.warning{border-color:var(--nha-warning);color:var(--nha-text);background:var(--nha-warning-soft)}:host .message.success{border-color:var(--nha-success);color:var(--nha-text);background:var(--nha-success-soft)}:host .message nh-assistant-icon{flex:none}:host .primary,:host .secondary,:host .danger{display:inline-flex;align-items:center;justify-content:center;gap:6px;min-height:36px;border:1px solid var(--nha-border);border-radius:var(--nha-radius-control);padding:6px 14px;font:inherit;font-size:13px;font-weight:700;white-space:nowrap;cursor:pointer}:host .primary:focus-visible,:host .secondary:focus-visible,:host .danger:focus-visible{outline:3px solid color-mix(in srgb,var(--nha-focus) 80%,transparent);outline-offset:2px}:host .primary:disabled,:host .secondary:disabled,:host .danger:disabled{cursor:not-allowed;opacity:.55}:host .primary{border-color:var(--nha-accent);color:var(--nha-accent-contrast);background:var(--nha-accent)}:host .primary:hover:not(:disabled){filter:brightness(1.12)}:host .secondary{color:var(--nha-text);background:transparent}:host .secondary:hover:not(:disabled){background:var(--nha-surface-strong)}:host .danger{border-color:var(--nha-danger);color:var(--nha-danger);background:transparent}:host .danger:hover:not(:disabled){background:var(--nha-danger-soft)}:host .icon-button{display:inline-flex;align-items:center;justify-content:center;width:36px;height:36px;padding:0;border:1px solid transparent;border-radius:var(--nha-radius-control);color:var(--nha-text-muted);background:transparent;cursor:pointer}:host .icon-button:focus-visible{outline:3px solid color-mix(in srgb,var(--nha-focus) 80%,transparent);outline-offset:2px}:host .icon-button:hover:not(:disabled){color:var(--nha-text);background:var(--nha-surface-strong)}:host .icon-button:disabled{cursor:not-allowed;opacity:.5}:host .actions{display:flex;flex-wrap:wrap;justify-content:flex-end;gap:8px}:host .badge{display:inline-flex;align-items:center;gap:4px;border-radius:999px;padding:2px 8px;color:var(--nha-text-muted);background:var(--nha-surface-strong);font-size:11px;font-weight:700;white-space:nowrap}:host .badge.success{color:var(--nha-success);background:var(--nha-success-soft)}:host .badge.warning{color:var(--nha-warning);background:var(--nha-warning-soft)}:host .badge.danger{color:var(--nha-danger);background:var(--nha-danger-soft)}:host .visually-hidden{position:absolute;width:1px;height:1px;overflow:hidden;clip:rect(0 0 0 0);clip-path:inset(50%);white-space:nowrap}.share{display:flex;flex:1;flex-direction:column;min-height:0}.header{display:flex;align-items:center;gap:8px;padding:12px 12px 8px 16px}h3{flex:1;margin:0;font-size:15px;font-weight:700}.content{display:flex;flex:1;flex-direction:column;gap:18px;min-height:0;overflow-y:auto;padding:0 16px 16px}.description,.state{margin:0;color:var(--nha-text-muted);font-size:13px}.state{padding:12px 16px}.block{display:flex;flex-direction:column;gap:8px}h4{display:flex;align-items:baseline;gap:8px;margin:0;font-size:12px;font-weight:700}.count{color:var(--nha-text-muted);font-size:11px;font-weight:400}.link-row{display:flex;align-items:center;gap:4px}.link-row input{font-family:var(--nha-mono);font-size:12px}.actions{justify-content:flex-start}.people{display:flex;flex-direction:column;gap:4px;margin:0;padding:0;list-style:none}.people li{display:flex;align-items:center;gap:8px;border:1px solid var(--nha-border);border-radius:var(--nha-radius-control);padding:6px 6px 6px 10px}.person{display:flex;flex:1;flex-direction:column;min-width:0}.person strong{overflow:hidden;font-size:13px;text-overflow:ellipsis;white-space:nowrap}.person small{color:var(--nha-text-muted);font-size:11px}.you{margin-left:4px;font-weight:400}.small{min-height:30px;padding:4px 10px;font-size:12px}\n"], dependencies: [{ kind: "component", type: NhAssistantIconComponent, selector: "nh-assistant-icon", inputs: ["name"] }, { kind: "pipe", type: TranslatePipe, name: "translate" }], changeDetection: i0.ChangeDetectionStrategy.OnPush }); }
|
|
4656
|
+
static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "20.3.33", type: NhAssistantShareComponent, isStandalone: true, selector: "nh-assistant-share", inputs: { section: { classPropertyName: "section", publicName: "section", isSignal: true, isRequired: false, transformFunction: null } }, outputs: { closed: "closed" }, ngImport: i0, template: "<section class=\"share\" [attr.aria-labelledby]=\"id + '-title'\" [attr.aria-busy]=\"busy()\">\n <header class=\"header\">\n <h3 [id]=\"id + '-title'\">\n {{ (isOwner() && section() !== 'members' ? 'nh-assistant.share.title' : 'nh-assistant.share.members-title') | translate }}\n </h3>\n <button\n class=\"icon-button\"\n type=\"button\"\n [attr.aria-label]=\"'nh-assistant.share.back' | translate\"\n [attr.title]=\"'nh-assistant.share.back' | translate\"\n (click)=\"closed.emit()\">\n <nh-assistant-icon name=\"close\" />\n </button>\n </header>\n\n @if (conversation(); as conversation) {\n <div class=\"content\">\n @if (isOwner()) {\n <p class=\"description\">{{ 'nh-assistant.share.description' | translate }}</p>\n\n @if (section() !== 'members' || !directory()) {\n <section class=\"block\" [attr.aria-labelledby]=\"id + '-link'\">\n <h4 [id]=\"id + '-link'\">{{ 'nh-assistant.share.link-title' | translate }}</h4>\n @if (link(); as link) {\n <div class=\"link-row\">\n <label class=\"visually-hidden\" [for]=\"id + '-link-input'\">{{ 'nh-assistant.share.link-label' | translate }}</label>\n <input #linkInput type=\"text\" readonly [id]=\"id + '-link-input'\" [value]=\"link\" (focus)=\"linkInput.select()\" />\n <button\n class=\"icon-button\"\n type=\"button\"\n [attr.aria-label]=\"'nh-assistant.share.copy' | translate\"\n [attr.title]=\"'nh-assistant.share.copy' | translate\"\n (click)=\"copy(linkInput)\">\n <nh-assistant-icon name=\"copy\" />\n </button>\n </div>\n @if (copied()) {\n <p class=\"message success\" role=\"status\">\n <nh-assistant-icon name=\"check\" />\n {{ 'nh-assistant.share.copied' | translate }}\n </p>\n }\n <div class=\"actions\">\n <button class=\"secondary\" type=\"button\" [disabled]=\"busy()\" (click)=\"revokeLink()\">\n {{ 'nh-assistant.share.revoke' | translate }}\n </button>\n <button class=\"secondary\" type=\"button\" [disabled]=\"busy()\" (click)=\"createLink()\">\n {{ 'nh-assistant.share.renew' | translate }}\n </button>\n </div>\n <p class=\"hint\">{{ 'nh-assistant.share.link-hint' | translate }}</p>\n } @else {\n <button class=\"primary\" type=\"button\" [disabled]=\"busy() || full()\" (click)=\"createLink()\">\n <nh-assistant-icon name=\"link\" />\n {{ 'nh-assistant.share.create' | translate }}\n </button>\n }\n </section>\n }\n\n @if (directory() && section() !== 'link') {\n <section class=\"block\" [attr.aria-labelledby]=\"id + '-invite'\">\n <h4 [id]=\"id + '-invite'\">{{ 'nh-assistant.share.invite-title' | translate }}</h4>\n <label class=\"visually-hidden\" [for]=\"id + '-search'\">{{ 'nh-assistant.share.search-label' | translate }}</label>\n <input\n type=\"search\"\n autocomplete=\"off\"\n [id]=\"id + '-search'\"\n [value]=\"query()\"\n [disabled]=\"full()\"\n [attr.placeholder]=\"'nh-assistant.share.search-placeholder' | translate\"\n (input)=\"onSearch($event)\" />\n @if (searching()) {\n <p class=\"hint\" role=\"status\">{{ 'nh-assistant.share.searching' | translate }}</p>\n } @else if (query().trim().length >= 2 && candidates().length === 0 && !invited()) {\n <p class=\"hint\">{{ 'nh-assistant.share.no-results' | translate }}</p>\n }\n @if (candidates().length > 0) {\n <ul class=\"people\">\n @for (entry of candidates(); track entry.actorId) {\n <li>\n <span class=\"person\">\n <strong>{{ entry.displayName }}</strong>\n @if (entry.detail) {\n <small>{{ entry.detail }}</small>\n }\n </span>\n <button class=\"secondary small\" type=\"button\" [disabled]=\"busy() || full()\" (click)=\"invite(entry)\">\n {{ 'nh-assistant.share.invite' | translate }}\n </button>\n </li>\n }\n </ul>\n }\n @if (invited(); as name) {\n <p class=\"message success\" role=\"status\">\n <nh-assistant-icon name=\"check\" />\n {{ 'nh-assistant.share.invited' | translate: { name } }}\n </p>\n }\n </section>\n }\n }\n\n @if (section() !== 'link') {\n <section class=\"block\" [attr.aria-labelledby]=\"id + '-members'\">\n <h4 [id]=\"id + '-members'\">\n {{ 'nh-assistant.share.members' | translate }}\n @if (maxParticipants() !== null && isOwner()) {\n <span class=\"count\">{{ 'nh-assistant.share.count' | translate: { count: participants().length, max: maxParticipants() } }}</span>\n }\n </h4>\n @if (store.members().length === 0) {\n <p class=\"hint\">{{ 'nh-assistant.share.not-shared' | translate }}</p>\n } @else {\n <ul class=\"people\">\n @for (member of store.members(); track member.actorId) {\n <li>\n <span class=\"person\">\n <strong>\n {{ member.displayName || ('nh-assistant.share.unnamed' | translate) }}\n @if (isCurrentUser(member)) {\n <small class=\"you\">{{ 'nh-assistant.share.you' | translate }}</small>\n }\n </strong>\n <small>{{ 'nh-assistant.share.role.' + member.role | translate }}</small>\n </span>\n @if (isOwner() && member.role === 'participant') {\n <button\n class=\"icon-button\"\n type=\"button\"\n [disabled]=\"busy()\"\n [attr.aria-label]=\"'nh-assistant.share.remove' | translate: { name: member.displayName || ('nh-assistant.share.unnamed' | translate) }\"\n [attr.title]=\"'nh-assistant.share.remove' | translate: { name: member.displayName || ('nh-assistant.share.unnamed' | translate) }\"\n (click)=\"remove(member)\">\n <nh-assistant-icon name=\"trash\" />\n </button>\n }\n </li>\n }\n </ul>\n }\n </section>\n }\n\n @if (!isOwner()) {\n <div class=\"actions\">\n <button class=\"secondary danger\" type=\"button\" [disabled]=\"busy() || conversation.status === 'running'\" (click)=\"leave()\">\n <nh-assistant-icon name=\"leave\" />\n {{ 'nh-assistant.share.leave' | translate }}\n </button>\n </div>\n }\n </div>\n } @else {\n <p class=\"state\">{{ 'nh-assistant.share.no-conversation' | translate }}</p>\n }\n</section>\n", styles: [":host{--nha-font: var(--nh-assistant-font, inherit);--nha-background: var(--nh-assistant-background, #ffffff);--nha-surface: var(--nh-assistant-surface, #f5f7fb);--nha-surface-strong: var(--nh-assistant-surface-strong, #eceff6);--nha-text: var(--nh-assistant-text, #080c1d);--nha-text-muted: var(--nh-assistant-text-muted, #5b6482);--nha-border: var(--nh-assistant-border, #dce0ec);--nha-accent: var(--nh-assistant-accent, #022962);--nha-accent-contrast: var(--nh-assistant-accent-contrast, #ffffff);--nha-highlight: var(--nh-assistant-highlight, #c84f00);--nha-user-bubble: var(--nh-assistant-user-bubble, #022962);--nha-user-text: var(--nh-assistant-user-text, #ffffff);--nha-success: var(--nh-assistant-success, #247d4e);--nha-success-soft: var(--nh-assistant-success-soft, #e6f5ec);--nha-warning: var(--nh-assistant-warning, #8a5a00);--nha-warning-soft: var(--nh-assistant-warning-soft, #fff3d9);--nha-danger: var(--nh-assistant-danger, #b92e52);--nha-danger-soft: var(--nh-assistant-danger-soft, #ffe9ef);--nha-focus: var(--nh-assistant-focus, #ff6700);--nha-shadow: var(--nh-assistant-shadow, 0 16px 36px rgb(2 41 98 / .16));--nha-radius: var(--nh-assistant-radius, 16px);--nha-radius-control: var(--nh-assistant-radius-control, 12px);--nha-mono: var(--nh-assistant-font-mono, ui-monospace, \"Cascadia Code\", Consolas, monospace)}@media(prefers-color-scheme:dark){:host{--nha-background: var(--nh-assistant-background, #0b0e22);--nha-surface: var(--nh-assistant-surface, #11152d);--nha-surface-strong: var(--nh-assistant-surface-strong, #181d3b);--nha-text: var(--nh-assistant-text, #ffffff);--nha-text-muted: var(--nh-assistant-text-muted, #b8bed8);--nha-border: var(--nh-assistant-border, #2b3155);--nha-accent: var(--nh-assistant-accent, #0f4087);--nha-accent-contrast: var(--nh-assistant-accent-contrast, #ffffff);--nha-highlight: var(--nh-assistant-highlight, #ff6700);--nha-user-bubble: var(--nh-assistant-user-bubble, #022962);--nha-user-text: var(--nh-assistant-user-text, #ffffff);--nha-success: var(--nh-assistant-success, #67c58f);--nha-success-soft: var(--nh-assistant-success-soft, #102d24);--nha-warning: var(--nh-assistant-warning, #ffbf5b);--nha-warning-soft: var(--nh-assistant-warning-soft, #342818);--nha-danger: var(--nh-assistant-danger, #ff6d8a);--nha-danger-soft: var(--nh-assistant-danger-soft, #351b2a);--nha-shadow: var(--nh-assistant-shadow, 0 16px 36px rgb(0 0 0 / .32))}}:host{display:flex;flex-direction:column;min-height:0;color:var(--nha-text)}:host fieldset{min-width:0;margin:0;border:0;padding:0}:host legend,:host .label,:host .field>label{display:block;margin-bottom:6px;padding:0;color:var(--nha-text);font-size:12px;font-weight:700}:host input[type=text],:host input[type=url],:host input[type=password],:host input[type=search],:host select,:host textarea{width:100%;min-width:0;min-height:38px;border:1px solid var(--nha-border);border-radius:var(--nha-radius-control);padding:8px 10px;color:var(--nha-text);background:var(--nha-background);font:inherit;font-size:13px}:host input[type=text]:focus-visible,:host input[type=url]:focus-visible,:host input[type=password]:focus-visible,:host input[type=search]:focus-visible,:host select:focus-visible,:host textarea:focus-visible{outline:3px solid color-mix(in srgb,var(--nha-focus) 80%,transparent);outline-offset:2px}:host input[type=text]:disabled,:host input[type=url]:disabled,:host input[type=password]:disabled,:host input[type=search]:disabled,:host select:disabled,:host textarea:disabled{cursor:not-allowed;opacity:.6}:host input[type=text][aria-invalid=true],:host input[type=url][aria-invalid=true],:host input[type=password][aria-invalid=true],:host input[type=search][aria-invalid=true],:host select[aria-invalid=true],:host textarea[aria-invalid=true]{border-color:var(--nha-danger)}:host textarea{line-height:1.45;resize:vertical}:host .mono{font-family:var(--nha-mono);font-size:12px}:host .field{display:flex;flex-direction:column;min-width:0}:host .hint{display:flex;justify-content:space-between;gap:8px;margin:4px 2px 0;color:var(--nha-text-muted);font-size:11px}:host .counter{flex:none;font-variant-numeric:tabular-nums}:host .error-text{color:var(--nha-danger)}:host .message{display:flex;align-items:center;gap:8px;margin:0;border:1px solid transparent;border-radius:var(--nha-radius-control);padding:8px 12px;font-size:13px}:host .message.error{border-color:var(--nha-danger);color:var(--nha-text);background:var(--nha-danger-soft)}:host .message.warning{border-color:var(--nha-warning);color:var(--nha-text);background:var(--nha-warning-soft)}:host .message.success{border-color:var(--nha-success);color:var(--nha-text);background:var(--nha-success-soft)}:host .message nh-assistant-icon{flex:none}:host .primary,:host .secondary,:host .danger{display:inline-flex;align-items:center;justify-content:center;gap:6px;min-height:36px;border:1px solid var(--nha-border);border-radius:var(--nha-radius-control);padding:6px 14px;font:inherit;font-size:13px;font-weight:700;white-space:nowrap;cursor:pointer}:host .primary:focus-visible,:host .secondary:focus-visible,:host .danger:focus-visible{outline:3px solid color-mix(in srgb,var(--nha-focus) 80%,transparent);outline-offset:2px}:host .primary:disabled,:host .secondary:disabled,:host .danger:disabled{cursor:not-allowed;opacity:.55}:host .primary{border-color:var(--nha-accent);color:var(--nha-accent-contrast);background:var(--nha-accent)}:host .primary:hover:not(:disabled){filter:brightness(1.12)}:host .secondary{color:var(--nha-text);background:transparent}:host .secondary:hover:not(:disabled){background:var(--nha-surface-strong)}:host .danger{border-color:var(--nha-danger);color:var(--nha-danger);background:transparent}:host .danger:hover:not(:disabled){background:var(--nha-danger-soft)}:host .icon-button{display:inline-flex;align-items:center;justify-content:center;width:36px;height:36px;padding:0;border:1px solid transparent;border-radius:var(--nha-radius-control);color:var(--nha-text-muted);background:transparent;cursor:pointer}:host .icon-button:focus-visible{outline:3px solid color-mix(in srgb,var(--nha-focus) 80%,transparent);outline-offset:2px}:host .icon-button:hover:not(:disabled){color:var(--nha-text);background:var(--nha-surface-strong)}:host .icon-button:disabled{cursor:not-allowed;opacity:.5}:host .actions{display:flex;flex-wrap:wrap;justify-content:flex-end;gap:8px}:host .badge{display:inline-flex;align-items:center;gap:4px;border-radius:999px;padding:2px 8px;color:var(--nha-text-muted);background:var(--nha-surface-strong);font-size:11px;font-weight:700;white-space:nowrap}:host .badge.success{color:var(--nha-success);background:var(--nha-success-soft)}:host .badge.warning{color:var(--nha-warning);background:var(--nha-warning-soft)}:host .badge.danger{color:var(--nha-danger);background:var(--nha-danger-soft)}:host .visually-hidden{position:absolute;width:1px;height:1px;overflow:hidden;clip:rect(0 0 0 0);clip-path:inset(50%);white-space:nowrap}.share{display:flex;flex:1;flex-direction:column;min-height:0}.header{display:flex;align-items:center;gap:8px;padding:12px 12px 8px 16px}h3{flex:1;margin:0;font-size:15px;font-weight:700}.content{display:flex;flex:1;flex-direction:column;gap:18px;min-height:0;overflow-y:auto;padding:0 16px 16px}.description,.state{margin:0;color:var(--nha-text-muted);font-size:13px}.state{padding:12px 16px}.block{display:flex;flex-direction:column;gap:8px}h4{display:flex;align-items:baseline;gap:8px;margin:0;font-size:12px;font-weight:700}.count{color:var(--nha-text-muted);font-size:11px;font-weight:400}.link-row{display:flex;align-items:center;gap:4px}.link-row input{font-family:var(--nha-mono);font-size:12px}.actions{justify-content:flex-start}.people{display:flex;flex-direction:column;gap:4px;margin:0;padding:0;list-style:none}.people li{display:flex;align-items:center;gap:8px;border:1px solid var(--nha-border);border-radius:var(--nha-radius-control);padding:6px 6px 6px 10px}.person{display:flex;flex:1;flex-direction:column;min-width:0}.person strong{overflow:hidden;font-size:13px;text-overflow:ellipsis;white-space:nowrap}.person small{color:var(--nha-text-muted);font-size:11px}.you{margin-left:4px;font-weight:400}.small{min-height:30px;padding:4px 10px;font-size:12px}\n"], dependencies: [{ kind: "component", type: NhAssistantIconComponent, selector: "nh-assistant-icon", inputs: ["name"] }, { kind: "pipe", type: TranslatePipe, name: "translate" }], changeDetection: i0.ChangeDetectionStrategy.OnPush }); }
|
|
4439
4657
|
}
|
|
4440
4658
|
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.33", ngImport: i0, type: NhAssistantShareComponent, decorators: [{
|
|
4441
4659
|
type: Component,
|
|
4442
|
-
args: [{ selector: 'nh-assistant-share', standalone: true, imports: [TranslatePipe, NhAssistantIconComponent], changeDetection: ChangeDetectionStrategy.OnPush, template: "<section class=\"share\" [attr.aria-labelledby]=\"id + '-title'\" [attr.aria-busy]=\"busy()\">\n <header class=\"header\">\n <h3 [id]=\"id + '-title'\">\n {{ (isOwner() ? 'nh-assistant.share.title' : 'nh-assistant.share.members-title') | translate }}\n </h3>\n <button\n class=\"icon-button\"\n type=\"button\"\n [attr.aria-label]=\"'nh-assistant.share.back' | translate\"\n [attr.title]=\"'nh-assistant.share.back' | translate\"\n (click)=\"closed.emit()\">\n <nh-assistant-icon name=\"close\" />\n </button>\n </header>\n\n @if (conversation(); as conversation) {\n <div class=\"content\">\n @if (isOwner()) {\n <p class=\"description\">{{ 'nh-assistant.share.description' | translate }}</p>\n\n <section class=\"block\" [attr.aria-labelledby]=\"id + '-link'\">\n <h4 [id]=\"id + '-link'\">{{ 'nh-assistant.share.link-title' | translate }}</h4>\n @if (link(); as link) {\n <div class=\"link-row\">\n <label class=\"visually-hidden\" [for]=\"id + '-link-input'\">{{ 'nh-assistant.share.link-label' | translate }}</label>\n <input #linkInput type=\"text\" readonly [id]=\"id + '-link-input'\" [value]=\"link\" (focus)=\"linkInput.select()\" />\n <button\n class=\"icon-button\"\n type=\"button\"\n [attr.aria-label]=\"'nh-assistant.share.copy' | translate\"\n [attr.title]=\"'nh-assistant.share.copy' | translate\"\n (click)=\"copy(linkInput)\">\n <nh-assistant-icon name=\"copy\" />\n </button>\n </div>\n @if (copied()) {\n <p class=\"message success\" role=\"status\">\n <nh-assistant-icon name=\"check\" />\n {{ 'nh-assistant.share.copied' | translate }}\n </p>\n }\n <div class=\"actions\">\n <button class=\"secondary\" type=\"button\" [disabled]=\"busy()\" (click)=\"revokeLink()\">\n {{ 'nh-assistant.share.revoke' | translate }}\n </button>\n <button class=\"secondary\" type=\"button\" [disabled]=\"busy()\" (click)=\"createLink()\">\n {{ 'nh-assistant.share.renew' | translate }}\n </button>\n </div>\n <p class=\"hint\">{{ 'nh-assistant.share.link-hint' | translate }}</p>\n } @else {\n <button class=\"primary\" type=\"button\" [disabled]=\"busy() || full()\" (click)=\"createLink()\">\n <nh-assistant-icon name=\"link\" />\n {{ 'nh-assistant.share.create' | translate }}\n </button>\n }\n </section>\n\n @if (directory()) {\n <section class=\"block\" [attr.aria-labelledby]=\"id + '-invite'\">\n <h4 [id]=\"id + '-invite'\">{{ 'nh-assistant.share.invite-title' | translate }}</h4>\n <label class=\"visually-hidden\" [for]=\"id + '-search'\">{{ 'nh-assistant.share.search-label' | translate }}</label>\n <input\n type=\"search\"\n autocomplete=\"off\"\n [id]=\"id + '-search'\"\n [value]=\"query()\"\n [disabled]=\"full()\"\n [attr.placeholder]=\"'nh-assistant.share.search-placeholder' | translate\"\n (input)=\"onSearch($event)\" />\n @if (searching()) {\n <p class=\"hint\" role=\"status\">{{ 'nh-assistant.share.searching' | translate }}</p>\n } @else if (query().trim().length >= 2 && candidates().length === 0 && !invited()) {\n <p class=\"hint\">{{ 'nh-assistant.share.no-results' | translate }}</p>\n }\n @if (candidates().length > 0) {\n <ul class=\"people\">\n @for (entry of candidates(); track entry.actorId) {\n <li>\n <span class=\"person\">\n <strong>{{ entry.displayName }}</strong>\n @if (entry.detail) {\n <small>{{ entry.detail }}</small>\n }\n </span>\n <button class=\"secondary small\" type=\"button\" [disabled]=\"busy() || full()\" (click)=\"invite(entry)\">\n {{ 'nh-assistant.share.invite' | translate }}\n </button>\n </li>\n }\n </ul>\n }\n @if (invited(); as name) {\n <p class=\"message success\" role=\"status\">\n <nh-assistant-icon name=\"check\" />\n {{ 'nh-assistant.share.invited' | translate: { name } }}\n </p>\n }\n </section>\n }\n }\n\n <section class=\"block\" [attr.aria-labelledby]=\"id + '-members'\">\n <h4 [id]=\"id + '-members'\">\n {{ 'nh-assistant.share.members' | translate }}\n @if (maxParticipants() !== null && isOwner()) {\n <span class=\"count\">{{ 'nh-assistant.share.count' | translate: { count: participants().length, max: maxParticipants() } }}</span>\n }\n </h4>\n @if (store.members().length === 0) {\n <p class=\"hint\">{{ 'nh-assistant.share.not-shared' | translate }}</p>\n } @else {\n <ul class=\"people\">\n @for (member of store.members(); track member.actorId) {\n <li>\n <span class=\"person\">\n <strong>\n {{ member.displayName || ('nh-assistant.share.unnamed' | translate) }}\n @if (isCurrentUser(member)) {\n <small class=\"you\">{{ 'nh-assistant.share.you' | translate }}</small>\n }\n </strong>\n <small>{{ 'nh-assistant.share.role.' + member.role | translate }}</small>\n </span>\n @if (isOwner() && member.role === 'participant') {\n <button\n class=\"icon-button\"\n type=\"button\"\n [disabled]=\"busy()\"\n [attr.aria-label]=\"'nh-assistant.share.remove' | translate: { name: member.displayName || ('nh-assistant.share.unnamed' | translate) }\"\n [attr.title]=\"'nh-assistant.share.remove' | translate: { name: member.displayName || ('nh-assistant.share.unnamed' | translate) }\"\n (click)=\"remove(member)\">\n <nh-assistant-icon name=\"trash\" />\n </button>\n }\n </li>\n }\n </ul>\n }\n </section>\n\n @if (!isOwner()) {\n <div class=\"actions\">\n <button class=\"secondary danger\" type=\"button\" [disabled]=\"busy() || conversation.status === 'running'\" (click)=\"leave()\">\n <nh-assistant-icon name=\"leave\" />\n {{ 'nh-assistant.share.leave' | translate }}\n </button>\n </div>\n }\n </div>\n } @else {\n <p class=\"state\">{{ 'nh-assistant.share.no-conversation' | translate }}</p>\n }\n</section>\n", styles: [":host{--nha-font: var(--nh-assistant-font, inherit);--nha-background: var(--nh-assistant-background, #ffffff);--nha-surface: var(--nh-assistant-surface, #f5f7fb);--nha-surface-strong: var(--nh-assistant-surface-strong, #eceff6);--nha-text: var(--nh-assistant-text, #080c1d);--nha-text-muted: var(--nh-assistant-text-muted, #5b6482);--nha-border: var(--nh-assistant-border, #dce0ec);--nha-accent: var(--nh-assistant-accent, #022962);--nha-accent-contrast: var(--nh-assistant-accent-contrast, #ffffff);--nha-highlight: var(--nh-assistant-highlight, #c84f00);--nha-user-bubble: var(--nh-assistant-user-bubble, #022962);--nha-user-text: var(--nh-assistant-user-text, #ffffff);--nha-success: var(--nh-assistant-success, #247d4e);--nha-success-soft: var(--nh-assistant-success-soft, #e6f5ec);--nha-warning: var(--nh-assistant-warning, #8a5a00);--nha-warning-soft: var(--nh-assistant-warning-soft, #fff3d9);--nha-danger: var(--nh-assistant-danger, #b92e52);--nha-danger-soft: var(--nh-assistant-danger-soft, #ffe9ef);--nha-focus: var(--nh-assistant-focus, #ff6700);--nha-shadow: var(--nh-assistant-shadow, 0 16px 36px rgb(2 41 98 / .16));--nha-radius: var(--nh-assistant-radius, 16px);--nha-radius-control: var(--nh-assistant-radius-control, 12px);--nha-mono: var(--nh-assistant-font-mono, ui-monospace, \"Cascadia Code\", Consolas, monospace)}@media(prefers-color-scheme:dark){:host{--nha-background: var(--nh-assistant-background, #0b0e22);--nha-surface: var(--nh-assistant-surface, #11152d);--nha-surface-strong: var(--nh-assistant-surface-strong, #181d3b);--nha-text: var(--nh-assistant-text, #ffffff);--nha-text-muted: var(--nh-assistant-text-muted, #b8bed8);--nha-border: var(--nh-assistant-border, #2b3155);--nha-accent: var(--nh-assistant-accent, #0f4087);--nha-accent-contrast: var(--nh-assistant-accent-contrast, #ffffff);--nha-highlight: var(--nh-assistant-highlight, #ff6700);--nha-user-bubble: var(--nh-assistant-user-bubble, #022962);--nha-user-text: var(--nh-assistant-user-text, #ffffff);--nha-success: var(--nh-assistant-success, #67c58f);--nha-success-soft: var(--nh-assistant-success-soft, #102d24);--nha-warning: var(--nh-assistant-warning, #ffbf5b);--nha-warning-soft: var(--nh-assistant-warning-soft, #342818);--nha-danger: var(--nh-assistant-danger, #ff6d8a);--nha-danger-soft: var(--nh-assistant-danger-soft, #351b2a);--nha-shadow: var(--nh-assistant-shadow, 0 16px 36px rgb(0 0 0 / .32))}}:host{display:flex;flex-direction:column;min-height:0;color:var(--nha-text)}:host fieldset{min-width:0;margin:0;border:0;padding:0}:host legend,:host .label,:host .field>label{display:block;margin-bottom:6px;padding:0;color:var(--nha-text);font-size:12px;font-weight:700}:host input[type=text],:host input[type=url],:host input[type=password],:host input[type=search],:host select,:host textarea{width:100%;min-width:0;min-height:38px;border:1px solid var(--nha-border);border-radius:var(--nha-radius-control);padding:8px 10px;color:var(--nha-text);background:var(--nha-background);font:inherit;font-size:13px}:host input[type=text]:focus-visible,:host input[type=url]:focus-visible,:host input[type=password]:focus-visible,:host input[type=search]:focus-visible,:host select:focus-visible,:host textarea:focus-visible{outline:3px solid color-mix(in srgb,var(--nha-focus) 80%,transparent);outline-offset:2px}:host input[type=text]:disabled,:host input[type=url]:disabled,:host input[type=password]:disabled,:host input[type=search]:disabled,:host select:disabled,:host textarea:disabled{cursor:not-allowed;opacity:.6}:host input[type=text][aria-invalid=true],:host input[type=url][aria-invalid=true],:host input[type=password][aria-invalid=true],:host input[type=search][aria-invalid=true],:host select[aria-invalid=true],:host textarea[aria-invalid=true]{border-color:var(--nha-danger)}:host textarea{line-height:1.45;resize:vertical}:host .mono{font-family:var(--nha-mono);font-size:12px}:host .field{display:flex;flex-direction:column;min-width:0}:host .hint{display:flex;justify-content:space-between;gap:8px;margin:4px 2px 0;color:var(--nha-text-muted);font-size:11px}:host .counter{flex:none;font-variant-numeric:tabular-nums}:host .error-text{color:var(--nha-danger)}:host .message{display:flex;align-items:center;gap:8px;margin:0;border:1px solid transparent;border-radius:var(--nha-radius-control);padding:8px 12px;font-size:13px}:host .message.error{border-color:var(--nha-danger);color:var(--nha-text);background:var(--nha-danger-soft)}:host .message.warning{border-color:var(--nha-warning);color:var(--nha-text);background:var(--nha-warning-soft)}:host .message.success{border-color:var(--nha-success);color:var(--nha-text);background:var(--nha-success-soft)}:host .message nh-assistant-icon{flex:none}:host .primary,:host .secondary,:host .danger{display:inline-flex;align-items:center;justify-content:center;gap:6px;min-height:36px;border:1px solid var(--nha-border);border-radius:var(--nha-radius-control);padding:6px 14px;font:inherit;font-size:13px;font-weight:700;white-space:nowrap;cursor:pointer}:host .primary:focus-visible,:host .secondary:focus-visible,:host .danger:focus-visible{outline:3px solid color-mix(in srgb,var(--nha-focus) 80%,transparent);outline-offset:2px}:host .primary:disabled,:host .secondary:disabled,:host .danger:disabled{cursor:not-allowed;opacity:.55}:host .primary{border-color:var(--nha-accent);color:var(--nha-accent-contrast);background:var(--nha-accent)}:host .primary:hover:not(:disabled){filter:brightness(1.12)}:host .secondary{color:var(--nha-text);background:transparent}:host .secondary:hover:not(:disabled){background:var(--nha-surface-strong)}:host .danger{border-color:var(--nha-danger);color:var(--nha-danger);background:transparent}:host .danger:hover:not(:disabled){background:var(--nha-danger-soft)}:host .icon-button{display:inline-flex;align-items:center;justify-content:center;width:36px;height:36px;padding:0;border:1px solid transparent;border-radius:var(--nha-radius-control);color:var(--nha-text-muted);background:transparent;cursor:pointer}:host .icon-button:focus-visible{outline:3px solid color-mix(in srgb,var(--nha-focus) 80%,transparent);outline-offset:2px}:host .icon-button:hover:not(:disabled){color:var(--nha-text);background:var(--nha-surface-strong)}:host .icon-button:disabled{cursor:not-allowed;opacity:.5}:host .actions{display:flex;flex-wrap:wrap;justify-content:flex-end;gap:8px}:host .badge{display:inline-flex;align-items:center;gap:4px;border-radius:999px;padding:2px 8px;color:var(--nha-text-muted);background:var(--nha-surface-strong);font-size:11px;font-weight:700;white-space:nowrap}:host .badge.success{color:var(--nha-success);background:var(--nha-success-soft)}:host .badge.warning{color:var(--nha-warning);background:var(--nha-warning-soft)}:host .badge.danger{color:var(--nha-danger);background:var(--nha-danger-soft)}:host .visually-hidden{position:absolute;width:1px;height:1px;overflow:hidden;clip:rect(0 0 0 0);clip-path:inset(50%);white-space:nowrap}.share{display:flex;flex:1;flex-direction:column;min-height:0}.header{display:flex;align-items:center;gap:8px;padding:12px 12px 8px 16px}h3{flex:1;margin:0;font-size:15px;font-weight:700}.content{display:flex;flex:1;flex-direction:column;gap:18px;min-height:0;overflow-y:auto;padding:0 16px 16px}.description,.state{margin:0;color:var(--nha-text-muted);font-size:13px}.state{padding:12px 16px}.block{display:flex;flex-direction:column;gap:8px}h4{display:flex;align-items:baseline;gap:8px;margin:0;font-size:12px;font-weight:700}.count{color:var(--nha-text-muted);font-size:11px;font-weight:400}.link-row{display:flex;align-items:center;gap:4px}.link-row input{font-family:var(--nha-mono);font-size:12px}.actions{justify-content:flex-start}.people{display:flex;flex-direction:column;gap:4px;margin:0;padding:0;list-style:none}.people li{display:flex;align-items:center;gap:8px;border:1px solid var(--nha-border);border-radius:var(--nha-radius-control);padding:6px 6px 6px 10px}.person{display:flex;flex:1;flex-direction:column;min-width:0}.person strong{overflow:hidden;font-size:13px;text-overflow:ellipsis;white-space:nowrap}.person small{color:var(--nha-text-muted);font-size:11px}.you{margin-left:4px;font-weight:400}.small{min-height:30px;padding:4px 10px;font-size:12px}\n"] }]
|
|
4443
|
-
}], ctorParameters: () => [], propDecorators: { closed: [{ type: i0.Output, args: ["closed"] }] } });
|
|
4660
|
+
args: [{ selector: 'nh-assistant-share', standalone: true, imports: [TranslatePipe, NhAssistantIconComponent], changeDetection: ChangeDetectionStrategy.OnPush, template: "<section class=\"share\" [attr.aria-labelledby]=\"id + '-title'\" [attr.aria-busy]=\"busy()\">\n <header class=\"header\">\n <h3 [id]=\"id + '-title'\">\n {{ (isOwner() && section() !== 'members' ? 'nh-assistant.share.title' : 'nh-assistant.share.members-title') | translate }}\n </h3>\n <button\n class=\"icon-button\"\n type=\"button\"\n [attr.aria-label]=\"'nh-assistant.share.back' | translate\"\n [attr.title]=\"'nh-assistant.share.back' | translate\"\n (click)=\"closed.emit()\">\n <nh-assistant-icon name=\"close\" />\n </button>\n </header>\n\n @if (conversation(); as conversation) {\n <div class=\"content\">\n @if (isOwner()) {\n <p class=\"description\">{{ 'nh-assistant.share.description' | translate }}</p>\n\n @if (section() !== 'members' || !directory()) {\n <section class=\"block\" [attr.aria-labelledby]=\"id + '-link'\">\n <h4 [id]=\"id + '-link'\">{{ 'nh-assistant.share.link-title' | translate }}</h4>\n @if (link(); as link) {\n <div class=\"link-row\">\n <label class=\"visually-hidden\" [for]=\"id + '-link-input'\">{{ 'nh-assistant.share.link-label' | translate }}</label>\n <input #linkInput type=\"text\" readonly [id]=\"id + '-link-input'\" [value]=\"link\" (focus)=\"linkInput.select()\" />\n <button\n class=\"icon-button\"\n type=\"button\"\n [attr.aria-label]=\"'nh-assistant.share.copy' | translate\"\n [attr.title]=\"'nh-assistant.share.copy' | translate\"\n (click)=\"copy(linkInput)\">\n <nh-assistant-icon name=\"copy\" />\n </button>\n </div>\n @if (copied()) {\n <p class=\"message success\" role=\"status\">\n <nh-assistant-icon name=\"check\" />\n {{ 'nh-assistant.share.copied' | translate }}\n </p>\n }\n <div class=\"actions\">\n <button class=\"secondary\" type=\"button\" [disabled]=\"busy()\" (click)=\"revokeLink()\">\n {{ 'nh-assistant.share.revoke' | translate }}\n </button>\n <button class=\"secondary\" type=\"button\" [disabled]=\"busy()\" (click)=\"createLink()\">\n {{ 'nh-assistant.share.renew' | translate }}\n </button>\n </div>\n <p class=\"hint\">{{ 'nh-assistant.share.link-hint' | translate }}</p>\n } @else {\n <button class=\"primary\" type=\"button\" [disabled]=\"busy() || full()\" (click)=\"createLink()\">\n <nh-assistant-icon name=\"link\" />\n {{ 'nh-assistant.share.create' | translate }}\n </button>\n }\n </section>\n }\n\n @if (directory() && section() !== 'link') {\n <section class=\"block\" [attr.aria-labelledby]=\"id + '-invite'\">\n <h4 [id]=\"id + '-invite'\">{{ 'nh-assistant.share.invite-title' | translate }}</h4>\n <label class=\"visually-hidden\" [for]=\"id + '-search'\">{{ 'nh-assistant.share.search-label' | translate }}</label>\n <input\n type=\"search\"\n autocomplete=\"off\"\n [id]=\"id + '-search'\"\n [value]=\"query()\"\n [disabled]=\"full()\"\n [attr.placeholder]=\"'nh-assistant.share.search-placeholder' | translate\"\n (input)=\"onSearch($event)\" />\n @if (searching()) {\n <p class=\"hint\" role=\"status\">{{ 'nh-assistant.share.searching' | translate }}</p>\n } @else if (query().trim().length >= 2 && candidates().length === 0 && !invited()) {\n <p class=\"hint\">{{ 'nh-assistant.share.no-results' | translate }}</p>\n }\n @if (candidates().length > 0) {\n <ul class=\"people\">\n @for (entry of candidates(); track entry.actorId) {\n <li>\n <span class=\"person\">\n <strong>{{ entry.displayName }}</strong>\n @if (entry.detail) {\n <small>{{ entry.detail }}</small>\n }\n </span>\n <button class=\"secondary small\" type=\"button\" [disabled]=\"busy() || full()\" (click)=\"invite(entry)\">\n {{ 'nh-assistant.share.invite' | translate }}\n </button>\n </li>\n }\n </ul>\n }\n @if (invited(); as name) {\n <p class=\"message success\" role=\"status\">\n <nh-assistant-icon name=\"check\" />\n {{ 'nh-assistant.share.invited' | translate: { name } }}\n </p>\n }\n </section>\n }\n }\n\n @if (section() !== 'link') {\n <section class=\"block\" [attr.aria-labelledby]=\"id + '-members'\">\n <h4 [id]=\"id + '-members'\">\n {{ 'nh-assistant.share.members' | translate }}\n @if (maxParticipants() !== null && isOwner()) {\n <span class=\"count\">{{ 'nh-assistant.share.count' | translate: { count: participants().length, max: maxParticipants() } }}</span>\n }\n </h4>\n @if (store.members().length === 0) {\n <p class=\"hint\">{{ 'nh-assistant.share.not-shared' | translate }}</p>\n } @else {\n <ul class=\"people\">\n @for (member of store.members(); track member.actorId) {\n <li>\n <span class=\"person\">\n <strong>\n {{ member.displayName || ('nh-assistant.share.unnamed' | translate) }}\n @if (isCurrentUser(member)) {\n <small class=\"you\">{{ 'nh-assistant.share.you' | translate }}</small>\n }\n </strong>\n <small>{{ 'nh-assistant.share.role.' + member.role | translate }}</small>\n </span>\n @if (isOwner() && member.role === 'participant') {\n <button\n class=\"icon-button\"\n type=\"button\"\n [disabled]=\"busy()\"\n [attr.aria-label]=\"'nh-assistant.share.remove' | translate: { name: member.displayName || ('nh-assistant.share.unnamed' | translate) }\"\n [attr.title]=\"'nh-assistant.share.remove' | translate: { name: member.displayName || ('nh-assistant.share.unnamed' | translate) }\"\n (click)=\"remove(member)\">\n <nh-assistant-icon name=\"trash\" />\n </button>\n }\n </li>\n }\n </ul>\n }\n </section>\n }\n\n @if (!isOwner()) {\n <div class=\"actions\">\n <button class=\"secondary danger\" type=\"button\" [disabled]=\"busy() || conversation.status === 'running'\" (click)=\"leave()\">\n <nh-assistant-icon name=\"leave\" />\n {{ 'nh-assistant.share.leave' | translate }}\n </button>\n </div>\n }\n </div>\n } @else {\n <p class=\"state\">{{ 'nh-assistant.share.no-conversation' | translate }}</p>\n }\n</section>\n", styles: [":host{--nha-font: var(--nh-assistant-font, inherit);--nha-background: var(--nh-assistant-background, #ffffff);--nha-surface: var(--nh-assistant-surface, #f5f7fb);--nha-surface-strong: var(--nh-assistant-surface-strong, #eceff6);--nha-text: var(--nh-assistant-text, #080c1d);--nha-text-muted: var(--nh-assistant-text-muted, #5b6482);--nha-border: var(--nh-assistant-border, #dce0ec);--nha-accent: var(--nh-assistant-accent, #022962);--nha-accent-contrast: var(--nh-assistant-accent-contrast, #ffffff);--nha-highlight: var(--nh-assistant-highlight, #c84f00);--nha-user-bubble: var(--nh-assistant-user-bubble, #022962);--nha-user-text: var(--nh-assistant-user-text, #ffffff);--nha-success: var(--nh-assistant-success, #247d4e);--nha-success-soft: var(--nh-assistant-success-soft, #e6f5ec);--nha-warning: var(--nh-assistant-warning, #8a5a00);--nha-warning-soft: var(--nh-assistant-warning-soft, #fff3d9);--nha-danger: var(--nh-assistant-danger, #b92e52);--nha-danger-soft: var(--nh-assistant-danger-soft, #ffe9ef);--nha-focus: var(--nh-assistant-focus, #ff6700);--nha-shadow: var(--nh-assistant-shadow, 0 16px 36px rgb(2 41 98 / .16));--nha-radius: var(--nh-assistant-radius, 16px);--nha-radius-control: var(--nh-assistant-radius-control, 12px);--nha-mono: var(--nh-assistant-font-mono, ui-monospace, \"Cascadia Code\", Consolas, monospace)}@media(prefers-color-scheme:dark){:host{--nha-background: var(--nh-assistant-background, #0b0e22);--nha-surface: var(--nh-assistant-surface, #11152d);--nha-surface-strong: var(--nh-assistant-surface-strong, #181d3b);--nha-text: var(--nh-assistant-text, #ffffff);--nha-text-muted: var(--nh-assistant-text-muted, #b8bed8);--nha-border: var(--nh-assistant-border, #2b3155);--nha-accent: var(--nh-assistant-accent, #0f4087);--nha-accent-contrast: var(--nh-assistant-accent-contrast, #ffffff);--nha-highlight: var(--nh-assistant-highlight, #ff6700);--nha-user-bubble: var(--nh-assistant-user-bubble, #022962);--nha-user-text: var(--nh-assistant-user-text, #ffffff);--nha-success: var(--nh-assistant-success, #67c58f);--nha-success-soft: var(--nh-assistant-success-soft, #102d24);--nha-warning: var(--nh-assistant-warning, #ffbf5b);--nha-warning-soft: var(--nh-assistant-warning-soft, #342818);--nha-danger: var(--nh-assistant-danger, #ff6d8a);--nha-danger-soft: var(--nh-assistant-danger-soft, #351b2a);--nha-shadow: var(--nh-assistant-shadow, 0 16px 36px rgb(0 0 0 / .32))}}:host{display:flex;flex-direction:column;min-height:0;color:var(--nha-text)}:host fieldset{min-width:0;margin:0;border:0;padding:0}:host legend,:host .label,:host .field>label{display:block;margin-bottom:6px;padding:0;color:var(--nha-text);font-size:12px;font-weight:700}:host input[type=text],:host input[type=url],:host input[type=password],:host input[type=search],:host select,:host textarea{width:100%;min-width:0;min-height:38px;border:1px solid var(--nha-border);border-radius:var(--nha-radius-control);padding:8px 10px;color:var(--nha-text);background:var(--nha-background);font:inherit;font-size:13px}:host input[type=text]:focus-visible,:host input[type=url]:focus-visible,:host input[type=password]:focus-visible,:host input[type=search]:focus-visible,:host select:focus-visible,:host textarea:focus-visible{outline:3px solid color-mix(in srgb,var(--nha-focus) 80%,transparent);outline-offset:2px}:host input[type=text]:disabled,:host input[type=url]:disabled,:host input[type=password]:disabled,:host input[type=search]:disabled,:host select:disabled,:host textarea:disabled{cursor:not-allowed;opacity:.6}:host input[type=text][aria-invalid=true],:host input[type=url][aria-invalid=true],:host input[type=password][aria-invalid=true],:host input[type=search][aria-invalid=true],:host select[aria-invalid=true],:host textarea[aria-invalid=true]{border-color:var(--nha-danger)}:host textarea{line-height:1.45;resize:vertical}:host .mono{font-family:var(--nha-mono);font-size:12px}:host .field{display:flex;flex-direction:column;min-width:0}:host .hint{display:flex;justify-content:space-between;gap:8px;margin:4px 2px 0;color:var(--nha-text-muted);font-size:11px}:host .counter{flex:none;font-variant-numeric:tabular-nums}:host .error-text{color:var(--nha-danger)}:host .message{display:flex;align-items:center;gap:8px;margin:0;border:1px solid transparent;border-radius:var(--nha-radius-control);padding:8px 12px;font-size:13px}:host .message.error{border-color:var(--nha-danger);color:var(--nha-text);background:var(--nha-danger-soft)}:host .message.warning{border-color:var(--nha-warning);color:var(--nha-text);background:var(--nha-warning-soft)}:host .message.success{border-color:var(--nha-success);color:var(--nha-text);background:var(--nha-success-soft)}:host .message nh-assistant-icon{flex:none}:host .primary,:host .secondary,:host .danger{display:inline-flex;align-items:center;justify-content:center;gap:6px;min-height:36px;border:1px solid var(--nha-border);border-radius:var(--nha-radius-control);padding:6px 14px;font:inherit;font-size:13px;font-weight:700;white-space:nowrap;cursor:pointer}:host .primary:focus-visible,:host .secondary:focus-visible,:host .danger:focus-visible{outline:3px solid color-mix(in srgb,var(--nha-focus) 80%,transparent);outline-offset:2px}:host .primary:disabled,:host .secondary:disabled,:host .danger:disabled{cursor:not-allowed;opacity:.55}:host .primary{border-color:var(--nha-accent);color:var(--nha-accent-contrast);background:var(--nha-accent)}:host .primary:hover:not(:disabled){filter:brightness(1.12)}:host .secondary{color:var(--nha-text);background:transparent}:host .secondary:hover:not(:disabled){background:var(--nha-surface-strong)}:host .danger{border-color:var(--nha-danger);color:var(--nha-danger);background:transparent}:host .danger:hover:not(:disabled){background:var(--nha-danger-soft)}:host .icon-button{display:inline-flex;align-items:center;justify-content:center;width:36px;height:36px;padding:0;border:1px solid transparent;border-radius:var(--nha-radius-control);color:var(--nha-text-muted);background:transparent;cursor:pointer}:host .icon-button:focus-visible{outline:3px solid color-mix(in srgb,var(--nha-focus) 80%,transparent);outline-offset:2px}:host .icon-button:hover:not(:disabled){color:var(--nha-text);background:var(--nha-surface-strong)}:host .icon-button:disabled{cursor:not-allowed;opacity:.5}:host .actions{display:flex;flex-wrap:wrap;justify-content:flex-end;gap:8px}:host .badge{display:inline-flex;align-items:center;gap:4px;border-radius:999px;padding:2px 8px;color:var(--nha-text-muted);background:var(--nha-surface-strong);font-size:11px;font-weight:700;white-space:nowrap}:host .badge.success{color:var(--nha-success);background:var(--nha-success-soft)}:host .badge.warning{color:var(--nha-warning);background:var(--nha-warning-soft)}:host .badge.danger{color:var(--nha-danger);background:var(--nha-danger-soft)}:host .visually-hidden{position:absolute;width:1px;height:1px;overflow:hidden;clip:rect(0 0 0 0);clip-path:inset(50%);white-space:nowrap}.share{display:flex;flex:1;flex-direction:column;min-height:0}.header{display:flex;align-items:center;gap:8px;padding:12px 12px 8px 16px}h3{flex:1;margin:0;font-size:15px;font-weight:700}.content{display:flex;flex:1;flex-direction:column;gap:18px;min-height:0;overflow-y:auto;padding:0 16px 16px}.description,.state{margin:0;color:var(--nha-text-muted);font-size:13px}.state{padding:12px 16px}.block{display:flex;flex-direction:column;gap:8px}h4{display:flex;align-items:baseline;gap:8px;margin:0;font-size:12px;font-weight:700}.count{color:var(--nha-text-muted);font-size:11px;font-weight:400}.link-row{display:flex;align-items:center;gap:4px}.link-row input{font-family:var(--nha-mono);font-size:12px}.actions{justify-content:flex-start}.people{display:flex;flex-direction:column;gap:4px;margin:0;padding:0;list-style:none}.people li{display:flex;align-items:center;gap:8px;border:1px solid var(--nha-border);border-radius:var(--nha-radius-control);padding:6px 6px 6px 10px}.person{display:flex;flex:1;flex-direction:column;min-width:0}.person strong{overflow:hidden;font-size:13px;text-overflow:ellipsis;white-space:nowrap}.person small{color:var(--nha-text-muted);font-size:11px}.you{margin-left:4px;font-weight:400}.small{min-height:30px;padding:4px 10px;font-size:12px}\n"] }]
|
|
4661
|
+
}], ctorParameters: () => [], propDecorators: { closed: [{ type: i0.Output, args: ["closed"] }], section: [{ type: i0.Input, args: [{ isSignal: true, alias: "section", required: false }] }] } });
|
|
4444
4662
|
|
|
4445
4663
|
const allowedTags = [
|
|
4446
4664
|
'p', 'br', 'strong', 'em', 'del', 'code', 'pre', 'blockquote', 'ul', 'ol', 'li', 'a',
|
|
@@ -4856,7 +5074,7 @@ class NhAssistantThreadComponent {
|
|
|
4856
5074
|
}
|
|
4857
5075
|
}
|
|
4858
5076
|
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.3.33", ngImport: i0, type: NhAssistantThreadComponent, deps: [], target: i0.ɵɵFactoryTarget.Component }); }
|
|
4859
|
-
static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "20.3.33", type: NhAssistantThreadComponent, isStandalone: true, selector: "nh-assistant-thread", inputs: { messages: { classPropertyName: "messages", publicName: "messages", isSignal: true, isRequired: true, transformFunction: null }, streaming: { classPropertyName: "streaming", publicName: "streaming", isSignal: true, isRequired: false, transformFunction: null }, deciding: { classPropertyName: "deciding", publicName: "deciding", isSignal: true, isRequired: false, transformFunction: null }, markdown: { classPropertyName: "markdown", publicName: "markdown", isSignal: true, isRequired: false, transformFunction: null }, members: { classPropertyName: "members", publicName: "members", isSignal: true, isRequired: false, transformFunction: null }, currentActorId: { classPropertyName: "currentActorId", publicName: "currentActorId", isSignal: true, isRequired: false, transformFunction: null }, canDecide: { classPropertyName: "canDecide", publicName: "canDecide", isSignal: true, isRequired: false, transformFunction: null }, decisionOwner: { classPropertyName: "decisionOwner", publicName: "decisionOwner", isSignal: true, isRequired: false, transformFunction: null } }, outputs: { approvalDecision: "approvalDecision" }, viewQueries: [{ propertyName: "scroller", first: true, predicate: ["scroller"], descendants: true, isSignal: true }, { propertyName: "viewport", first: true, predicate: CdkVirtualScrollViewport, descendants: true, isSignal: true }], ngImport: i0, template: "<div class=\"log\" role=\"log\" aria-live=\"polite\" [attr.aria-label]=\"'nh-assistant.thread.label' | translate\" [attr.aria-busy]=\"streaming()\">\n @if (virtual()) {\n <cdk-virtual-scroll-viewport class=\"scroller\" itemSize=\"120\" minBufferPx=\"1200\" maxBufferPx=\"2400\">\n <div class=\"row\" *cdkVirtualFor=\"let message of messages(); trackBy: trackMessage\">\n <ng-container [ngTemplateOutlet]=\"messageTemplate\" [ngTemplateOutletContext]=\"{ $implicit: message }\" />\n </div>\n @if (working()) {\n <ng-container [ngTemplateOutlet]=\"workingTemplate\" />\n }\n </cdk-virtual-scroll-viewport>\n } @else {\n <div class=\"scroller\" #scroller tabindex=\"0\">\n @for (message of messages(); track message.id) {\n <div class=\"row\">\n <ng-container [ngTemplateOutlet]=\"messageTemplate\" [ngTemplateOutletContext]=\"{ $implicit: message }\" />\n </div>\n }\n @if (working()) {\n <ng-container [ngTemplateOutlet]=\"workingTemplate\" />\n }\n </div>\n }\n</div>\n\n<ng-template #messageTemplate let-message>\n <article class=\"message\" [attr.data-role]=\"message.role\" [attr.data-others]=\"isOthers(message) ? 'true' : null\">\n @if (isOthers(message)) {\n <p class=\"author\">{{ authorName(message) ?? ('nh-assistant.thread.participant' | translate) }}</p>\n } @else {\n <p class=\"author\">{{ 'nh-assistant.thread.' + (message.role === 'user' ? 'you' : message.role) | translate }}</p>\n }\n @for (group of message.parts | nhAssistantPartGroups; track group.key) {\n @switch (group.kind) {\n @case ('text') {\n @if (message.role === 'assistant' && markdown()) {\n <div class=\"bubble markdown\" [innerHTML]=\"group.part.text | nhAssistantMarkdown\"></div>\n } @else {\n <div class=\"bubble plain\">{{ group.part.text }}</div>\n }\n }\n @case ('tools') {\n <nh-assistant-tool-call-group class=\"part\" [calls]=\"group.calls\" />\n }\n @case ('approval') {\n <nh-assistant-approval-card\n class=\"part\"\n [approval]=\"group.part\"\n [deciding]=\"deciding()\"\n [canDecide]=\"canDecide()\"\n [decisionOwner]=\"decisionOwner()\"\n (decide)=\"approvalDecision.emit($event)\" />\n }\n }\n }\n </article>\n</ng-template>\n\n<ng-template #workingTemplate>\n <p class=\"working\" role=\"status\">\n <span class=\"dots\" aria-hidden=\"true\"><span></span><span></span><span></span></span>\n {{ 'nh-assistant.thread.working' | translate }}\n @if (elapsedSeconds() > 0) {\n <span class=\"elapsed\">{{ 'nh-assistant.thread.elapsed' | translate: { seconds: elapsedSeconds() } }}</span>\n }\n </p>\n</ng-template>\n", styles: [":host{--nha-font: var(--nh-assistant-font, inherit);--nha-background: var(--nh-assistant-background, #ffffff);--nha-surface: var(--nh-assistant-surface, #f5f7fb);--nha-surface-strong: var(--nh-assistant-surface-strong, #eceff6);--nha-text: var(--nh-assistant-text, #080c1d);--nha-text-muted: var(--nh-assistant-text-muted, #5b6482);--nha-border: var(--nh-assistant-border, #dce0ec);--nha-accent: var(--nh-assistant-accent, #022962);--nha-accent-contrast: var(--nh-assistant-accent-contrast, #ffffff);--nha-highlight: var(--nh-assistant-highlight, #c84f00);--nha-user-bubble: var(--nh-assistant-user-bubble, #022962);--nha-user-text: var(--nh-assistant-user-text, #ffffff);--nha-success: var(--nh-assistant-success, #247d4e);--nha-success-soft: var(--nh-assistant-success-soft, #e6f5ec);--nha-warning: var(--nh-assistant-warning, #8a5a00);--nha-warning-soft: var(--nh-assistant-warning-soft, #fff3d9);--nha-danger: var(--nh-assistant-danger, #b92e52);--nha-danger-soft: var(--nh-assistant-danger-soft, #ffe9ef);--nha-focus: var(--nh-assistant-focus, #ff6700);--nha-shadow: var(--nh-assistant-shadow, 0 16px 36px rgb(2 41 98 / .16));--nha-radius: var(--nh-assistant-radius, 16px);--nha-radius-control: var(--nh-assistant-radius-control, 12px);--nha-mono: var(--nh-assistant-font-mono, ui-monospace, \"Cascadia Code\", Consolas, monospace)}@media(prefers-color-scheme:dark){:host{--nha-background: var(--nh-assistant-background, #0b0e22);--nha-surface: var(--nh-assistant-surface, #11152d);--nha-surface-strong: var(--nh-assistant-surface-strong, #181d3b);--nha-text: var(--nh-assistant-text, #ffffff);--nha-text-muted: var(--nh-assistant-text-muted, #b8bed8);--nha-border: var(--nh-assistant-border, #2b3155);--nha-accent: var(--nh-assistant-accent, #0f4087);--nha-accent-contrast: var(--nh-assistant-accent-contrast, #ffffff);--nha-highlight: var(--nh-assistant-highlight, #ff6700);--nha-user-bubble: var(--nh-assistant-user-bubble, #022962);--nha-user-text: var(--nh-assistant-user-text, #ffffff);--nha-success: var(--nh-assistant-success, #67c58f);--nha-success-soft: var(--nh-assistant-success-soft, #102d24);--nha-warning: var(--nh-assistant-warning, #ffbf5b);--nha-warning-soft: var(--nh-assistant-warning-soft, #342818);--nha-danger: var(--nh-assistant-danger, #ff6d8a);--nha-danger-soft: var(--nh-assistant-danger-soft, #351b2a);--nha-shadow: var(--nh-assistant-shadow, 0 16px 36px rgb(0 0 0 / .32))}}:host{display:flex;flex-direction:column;min-height:0;color:var(--nha-text)}.log{display:flex;flex:1;flex-direction:column;min-height:0}.scroller{flex:1;min-height:0;overflow-y:auto;overscroll-behavior:contain;padding:16px;outline:none}.scroller:focus-visible{box-shadow:inset 0 0 0 2px var(--nha-focus)}cdk-virtual-scroll-viewport.scroller{height:100%}.row+.row{margin-top:14px}.message{display:flex;flex-direction:column;align-items:flex-start;gap:6px;min-width:0}.message[data-role=user]{align-items:flex-end}.author{margin:0;color:var(--nha-text-muted);font-size:11px;font-weight:700;letter-spacing:.04em;text-transform:uppercase}.bubble{max-width:100%;border-radius:var(--nha-radius-control);padding:8px 12px;font-size:14px;line-height:1.5;overflow-wrap:anywhere}.plain{white-space:pre-wrap}.message[data-role=user] .bubble{max-width:88%;color:var(--nha-user-text);background:var(--nha-user-bubble)}.message[data-others=true]{align-items:flex-start}.message[data-others=true] .bubble{color:var(--nha-text);background:var(--nha-surface-strong)}.message[data-role=assistant] .bubble,.message[data-role=tool] .bubble{border:1px solid var(--nha-border);background:var(--nha-surface)}.part{width:100%}:host ::ng-deep .markdown :first-child{margin-top:0}:host ::ng-deep .markdown :last-child{margin-bottom:0}:host ::ng-deep .markdown p,:host ::ng-deep .markdown ul,:host ::ng-deep .markdown ol,:host ::ng-deep .markdown pre,:host ::ng-deep .markdown blockquote,:host ::ng-deep .markdown table{margin:0 0 8px}:host ::ng-deep .markdown ul,:host ::ng-deep .markdown ol{padding-left:20px}:host ::ng-deep .markdown h1,:host ::ng-deep .markdown h2,:host ::ng-deep .markdown h3,:host ::ng-deep .markdown h4,:host ::ng-deep .markdown h5,:host ::ng-deep .markdown h6{margin:10px 0 6px;font-size:15px;line-height:1.3}:host ::ng-deep .markdown a{color:var(--nha-highlight);text-decoration:underline}:host ::ng-deep .markdown a:focus-visible{outline:3px solid color-mix(in srgb,var(--nha-focus) 80%,transparent);outline-offset:2px}:host ::ng-deep .markdown code{border-radius:6px;padding:1px 4px;background:var(--nha-surface-strong);font-family:var(--nha-mono);font-size:12.5px}:host ::ng-deep .markdown pre{overflow-x:auto;border-radius:8px;padding:8px;background:var(--nha-surface-strong)}:host ::ng-deep .markdown pre code{padding:0;background:none}:host ::ng-deep .markdown blockquote{border-left:3px solid var(--nha-border);padding-left:10px;color:var(--nha-text-muted)}:host ::ng-deep .markdown table{display:block;max-width:100%;overflow-x:auto;border-collapse:collapse;font-size:13px}:host ::ng-deep .markdown th,:host ::ng-deep .markdown td{border:1px solid var(--nha-border);padding:4px 8px;text-align:left}.working{display:flex;align-items:center;gap:8px;margin:14px 0 0;color:var(--nha-text-muted);font-size:13px}.elapsed{font-variant-numeric:tabular-nums}.dots{display:inline-flex;gap:3px}.dots span{width:6px;height:6px;border-radius:50%;background:currentColor;opacity:.6}@media(prefers-reduced-motion:no-preference){.dots span{animation:nha-bounce 1s ease-in-out infinite}.dots span:nth-child(2){animation-delay:.15s}.dots span:nth-child(3){animation-delay:.3s}}@keyframes nha-bounce{0%,80%,to{transform:translateY(0);opacity:.35}40%{transform:translateY(-3px);opacity:1}}\n"], dependencies: [{ kind: "directive", type: NgTemplateOutlet, selector: "[ngTemplateOutlet]", inputs: ["ngTemplateOutletContext", "ngTemplateOutlet", "ngTemplateOutletInjector"] }, { kind: "ngmodule", type: ScrollingModule }, { kind: "directive", type: i1.CdkFixedSizeVirtualScroll, selector: "cdk-virtual-scroll-viewport[itemSize]", inputs: ["itemSize", "minBufferPx", "maxBufferPx"] }, { kind: "directive", type: i1.CdkVirtualForOf, selector: "[cdkVirtualFor][cdkVirtualForOf]", inputs: ["cdkVirtualForOf", "cdkVirtualForTrackBy", "cdkVirtualForTemplate", "cdkVirtualForTemplateCacheSize"] }, { kind: "component", type: i1.CdkVirtualScrollViewport, selector: "cdk-virtual-scroll-viewport", inputs: ["orientation", "appendOnly"], outputs: ["scrolledIndexChange"] }, { kind: "component", type: NhAssistantToolCallGroupComponent, selector: "nh-assistant-tool-call-group", inputs: ["calls"] }, { kind: "component", type: NhAssistantApprovalCardComponent, selector: "nh-assistant-approval-card", inputs: ["approval", "deciding", "canDecide", "decisionOwner"], outputs: ["decide"] }, { kind: "pipe", type: TranslatePipe, name: "translate" }, { kind: "pipe", type: NhAssistantMarkdownPipe, name: "nhAssistantMarkdown" }, { kind: "pipe", type: NhAssistantPartGroupsPipe, name: "nhAssistantPartGroups" }], changeDetection: i0.ChangeDetectionStrategy.OnPush }); }
|
|
5077
|
+
static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "20.3.33", type: NhAssistantThreadComponent, isStandalone: true, selector: "nh-assistant-thread", inputs: { messages: { classPropertyName: "messages", publicName: "messages", isSignal: true, isRequired: true, transformFunction: null }, streaming: { classPropertyName: "streaming", publicName: "streaming", isSignal: true, isRequired: false, transformFunction: null }, deciding: { classPropertyName: "deciding", publicName: "deciding", isSignal: true, isRequired: false, transformFunction: null }, markdown: { classPropertyName: "markdown", publicName: "markdown", isSignal: true, isRequired: false, transformFunction: null }, members: { classPropertyName: "members", publicName: "members", isSignal: true, isRequired: false, transformFunction: null }, currentActorId: { classPropertyName: "currentActorId", publicName: "currentActorId", isSignal: true, isRequired: false, transformFunction: null }, canDecide: { classPropertyName: "canDecide", publicName: "canDecide", isSignal: true, isRequired: false, transformFunction: null }, decisionOwner: { classPropertyName: "decisionOwner", publicName: "decisionOwner", isSignal: true, isRequired: false, transformFunction: null } }, outputs: { approvalDecision: "approvalDecision" }, viewQueries: [{ propertyName: "scroller", first: true, predicate: ["scroller"], descendants: true, isSignal: true }, { propertyName: "viewport", first: true, predicate: CdkVirtualScrollViewport, descendants: true, isSignal: true }], ngImport: i0, template: "<div class=\"log\" role=\"log\" aria-live=\"polite\" [attr.aria-label]=\"'nh-assistant.thread.label' | translate\" [attr.aria-busy]=\"streaming()\">\n @if (virtual()) {\n <cdk-virtual-scroll-viewport class=\"scroller\" itemSize=\"120\" minBufferPx=\"1200\" maxBufferPx=\"2400\">\n <div class=\"row\" *cdkVirtualFor=\"let message of messages(); trackBy: trackMessage\">\n <ng-container [ngTemplateOutlet]=\"messageTemplate\" [ngTemplateOutletContext]=\"{ $implicit: message }\" />\n </div>\n @if (working()) {\n <ng-container [ngTemplateOutlet]=\"workingTemplate\" />\n }\n </cdk-virtual-scroll-viewport>\n } @else {\n <div class=\"scroller\" #scroller tabindex=\"0\">\n @for (message of messages(); track message.id) {\n <div class=\"row\">\n <ng-container [ngTemplateOutlet]=\"messageTemplate\" [ngTemplateOutletContext]=\"{ $implicit: message }\" />\n </div>\n }\n @if (working()) {\n <ng-container [ngTemplateOutlet]=\"workingTemplate\" />\n }\n </div>\n }\n</div>\n\n<ng-template #messageTemplate let-message>\n <article class=\"message\" [attr.data-role]=\"message.role\" [attr.data-others]=\"isOthers(message) ? 'true' : null\">\n @if (isOthers(message)) {\n <p class=\"author\">{{ authorName(message) ?? ('nh-assistant.thread.participant' | translate) }}</p>\n } @else {\n <p class=\"author\">{{ 'nh-assistant.thread.' + (message.role === 'user' ? 'you' : message.role) | translate }}</p>\n }\n @for (group of message.parts | nhAssistantPartGroups; track group.key) {\n @switch (group.kind) {\n @case ('text') {\n @if (message.role === 'assistant' && markdown()) {\n <div class=\"bubble markdown\" [innerHTML]=\"group.part.text | nhAssistantMarkdown\"></div>\n } @else {\n <div class=\"bubble plain\">{{ group.part.text }}</div>\n }\n }\n @case ('tools') {\n <nh-assistant-tool-call-group class=\"part\" [calls]=\"group.calls\" />\n }\n @case ('approval') {\n <nh-assistant-approval-card\n class=\"part\"\n [approval]=\"group.part\"\n [deciding]=\"deciding()\"\n [canDecide]=\"canDecide()\"\n [decisionOwner]=\"decisionOwner()\"\n (decide)=\"approvalDecision.emit($event)\" />\n }\n }\n }\n </article>\n</ng-template>\n\n<ng-template #workingTemplate>\n <p class=\"working\" role=\"status\">\n <span class=\"dots\" aria-hidden=\"true\"><span></span><span></span><span></span></span>\n {{ 'nh-assistant.thread.working' | translate }}\n @if (elapsedSeconds() > 0) {\n <span class=\"elapsed\">{{ 'nh-assistant.thread.elapsed' | translate: { seconds: elapsedSeconds() } }}</span>\n }\n </p>\n</ng-template>\n", styles: [":host{--nha-font: var(--nh-assistant-font, inherit);--nha-background: var(--nh-assistant-background, #ffffff);--nha-surface: var(--nh-assistant-surface, #f5f7fb);--nha-surface-strong: var(--nh-assistant-surface-strong, #eceff6);--nha-text: var(--nh-assistant-text, #080c1d);--nha-text-muted: var(--nh-assistant-text-muted, #5b6482);--nha-border: var(--nh-assistant-border, #dce0ec);--nha-accent: var(--nh-assistant-accent, #022962);--nha-accent-contrast: var(--nh-assistant-accent-contrast, #ffffff);--nha-highlight: var(--nh-assistant-highlight, #c84f00);--nha-user-bubble: var(--nh-assistant-user-bubble, #022962);--nha-user-text: var(--nh-assistant-user-text, #ffffff);--nha-success: var(--nh-assistant-success, #247d4e);--nha-success-soft: var(--nh-assistant-success-soft, #e6f5ec);--nha-warning: var(--nh-assistant-warning, #8a5a00);--nha-warning-soft: var(--nh-assistant-warning-soft, #fff3d9);--nha-danger: var(--nh-assistant-danger, #b92e52);--nha-danger-soft: var(--nh-assistant-danger-soft, #ffe9ef);--nha-focus: var(--nh-assistant-focus, #ff6700);--nha-shadow: var(--nh-assistant-shadow, 0 16px 36px rgb(2 41 98 / .16));--nha-radius: var(--nh-assistant-radius, 16px);--nha-radius-control: var(--nh-assistant-radius-control, 12px);--nha-mono: var(--nh-assistant-font-mono, ui-monospace, \"Cascadia Code\", Consolas, monospace)}@media(prefers-color-scheme:dark){:host{--nha-background: var(--nh-assistant-background, #0b0e22);--nha-surface: var(--nh-assistant-surface, #11152d);--nha-surface-strong: var(--nh-assistant-surface-strong, #181d3b);--nha-text: var(--nh-assistant-text, #ffffff);--nha-text-muted: var(--nh-assistant-text-muted, #b8bed8);--nha-border: var(--nh-assistant-border, #2b3155);--nha-accent: var(--nh-assistant-accent, #0f4087);--nha-accent-contrast: var(--nh-assistant-accent-contrast, #ffffff);--nha-highlight: var(--nh-assistant-highlight, #ff6700);--nha-user-bubble: var(--nh-assistant-user-bubble, #022962);--nha-user-text: var(--nh-assistant-user-text, #ffffff);--nha-success: var(--nh-assistant-success, #67c58f);--nha-success-soft: var(--nh-assistant-success-soft, #102d24);--nha-warning: var(--nh-assistant-warning, #ffbf5b);--nha-warning-soft: var(--nh-assistant-warning-soft, #342818);--nha-danger: var(--nh-assistant-danger, #ff6d8a);--nha-danger-soft: var(--nh-assistant-danger-soft, #351b2a);--nha-shadow: var(--nh-assistant-shadow, 0 16px 36px rgb(0 0 0 / .32))}}:host{display:flex;flex-direction:column;min-height:0;color:var(--nha-text)}.log{display:flex;flex:1;flex-direction:column;min-height:0}.scroller{flex:1;min-height:0;overflow-y:auto;overscroll-behavior:contain;padding:16px;outline:none}.scroller:focus-visible{box-shadow:inset 0 0 0 2px var(--nha-focus)}cdk-virtual-scroll-viewport.scroller{height:100%}.row+.row{margin-top:20px}.message{display:flex;flex-direction:column;align-items:flex-start;gap:6px;min-width:0}.message[data-role=user]{align-items:flex-end}.author{margin:0;color:var(--nha-text-muted);font-size:11px;font-weight:600}.bubble{max-width:100%;border-radius:var(--nha-radius-control);padding:8px 12px;font-size:14px;line-height:1.5;overflow-wrap:anywhere}.plain{white-space:pre-wrap}.message[data-role=user] .bubble{max-width:88%;color:var(--nha-user-text);background:var(--nha-user-bubble)}.message[data-others=true]{align-items:flex-start}.message[data-others=true] .bubble{color:var(--nha-text);background:var(--nha-surface-strong)}.message[data-role=assistant] .bubble,.message[data-role=tool] .bubble{padding-inline:0;background:transparent}.part{width:100%}:host ::ng-deep .markdown :first-child{margin-top:0}:host ::ng-deep .markdown :last-child{margin-bottom:0}:host ::ng-deep .markdown p,:host ::ng-deep .markdown ul,:host ::ng-deep .markdown ol,:host ::ng-deep .markdown pre,:host ::ng-deep .markdown blockquote,:host ::ng-deep .markdown table{margin:0 0 8px}:host ::ng-deep .markdown ul,:host ::ng-deep .markdown ol{padding-left:20px}:host ::ng-deep .markdown h1,:host ::ng-deep .markdown h2,:host ::ng-deep .markdown h3,:host ::ng-deep .markdown h4,:host ::ng-deep .markdown h5,:host ::ng-deep .markdown h6{margin:10px 0 6px;font-size:15px;line-height:1.3}:host ::ng-deep .markdown a{color:var(--nha-highlight);text-decoration:underline}:host ::ng-deep .markdown a:focus-visible{outline:3px solid color-mix(in srgb,var(--nha-focus) 80%,transparent);outline-offset:2px}:host ::ng-deep .markdown code{border-radius:6px;padding:1px 4px;background:var(--nha-surface-strong);font-family:var(--nha-mono);font-size:12.5px}:host ::ng-deep .markdown pre{overflow-x:auto;border-radius:8px;padding:8px;background:var(--nha-surface-strong)}:host ::ng-deep .markdown pre code{padding:0;background:none}:host ::ng-deep .markdown blockquote{border-left:3px solid var(--nha-border);padding-left:10px;color:var(--nha-text-muted)}:host ::ng-deep .markdown table{display:block;max-width:100%;overflow-x:auto;border-collapse:collapse;font-size:13px}:host ::ng-deep .markdown th,:host ::ng-deep .markdown td{border:1px solid var(--nha-border);padding:4px 8px;text-align:left}.working{display:flex;align-items:center;gap:8px;margin:14px 0 0;color:var(--nha-text-muted);font-size:13px}.elapsed{font-variant-numeric:tabular-nums}.dots{display:inline-flex;gap:3px}.dots span{width:6px;height:6px;border-radius:50%;background:currentColor;opacity:.6}@media(prefers-reduced-motion:no-preference){.dots span{animation:nha-bounce 1s ease-in-out infinite}.dots span:nth-child(2){animation-delay:.15s}.dots span:nth-child(3){animation-delay:.3s}}@keyframes nha-bounce{0%,80%,to{transform:translateY(0);opacity:.35}40%{transform:translateY(-3px);opacity:1}}\n"], dependencies: [{ kind: "directive", type: NgTemplateOutlet, selector: "[ngTemplateOutlet]", inputs: ["ngTemplateOutletContext", "ngTemplateOutlet", "ngTemplateOutletInjector"] }, { kind: "ngmodule", type: ScrollingModule }, { kind: "directive", type: i1.CdkFixedSizeVirtualScroll, selector: "cdk-virtual-scroll-viewport[itemSize]", inputs: ["itemSize", "minBufferPx", "maxBufferPx"] }, { kind: "directive", type: i1.CdkVirtualForOf, selector: "[cdkVirtualFor][cdkVirtualForOf]", inputs: ["cdkVirtualForOf", "cdkVirtualForTrackBy", "cdkVirtualForTemplate", "cdkVirtualForTemplateCacheSize"] }, { kind: "component", type: i1.CdkVirtualScrollViewport, selector: "cdk-virtual-scroll-viewport", inputs: ["orientation", "appendOnly"], outputs: ["scrolledIndexChange"] }, { kind: "component", type: NhAssistantToolCallGroupComponent, selector: "nh-assistant-tool-call-group", inputs: ["calls"] }, { kind: "component", type: NhAssistantApprovalCardComponent, selector: "nh-assistant-approval-card", inputs: ["approval", "deciding", "canDecide", "decisionOwner"], outputs: ["decide"] }, { kind: "pipe", type: TranslatePipe, name: "translate" }, { kind: "pipe", type: NhAssistantMarkdownPipe, name: "nhAssistantMarkdown" }, { kind: "pipe", type: NhAssistantPartGroupsPipe, name: "nhAssistantPartGroups" }], changeDetection: i0.ChangeDetectionStrategy.OnPush }); }
|
|
4860
5078
|
}
|
|
4861
5079
|
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.33", ngImport: i0, type: NhAssistantThreadComponent, decorators: [{
|
|
4862
5080
|
type: Component,
|
|
@@ -4868,7 +5086,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.33", ngImpo
|
|
|
4868
5086
|
NhAssistantPartGroupsPipe,
|
|
4869
5087
|
NhAssistantToolCallGroupComponent,
|
|
4870
5088
|
NhAssistantApprovalCardComponent
|
|
4871
|
-
], changeDetection: ChangeDetectionStrategy.OnPush, template: "<div class=\"log\" role=\"log\" aria-live=\"polite\" [attr.aria-label]=\"'nh-assistant.thread.label' | translate\" [attr.aria-busy]=\"streaming()\">\n @if (virtual()) {\n <cdk-virtual-scroll-viewport class=\"scroller\" itemSize=\"120\" minBufferPx=\"1200\" maxBufferPx=\"2400\">\n <div class=\"row\" *cdkVirtualFor=\"let message of messages(); trackBy: trackMessage\">\n <ng-container [ngTemplateOutlet]=\"messageTemplate\" [ngTemplateOutletContext]=\"{ $implicit: message }\" />\n </div>\n @if (working()) {\n <ng-container [ngTemplateOutlet]=\"workingTemplate\" />\n }\n </cdk-virtual-scroll-viewport>\n } @else {\n <div class=\"scroller\" #scroller tabindex=\"0\">\n @for (message of messages(); track message.id) {\n <div class=\"row\">\n <ng-container [ngTemplateOutlet]=\"messageTemplate\" [ngTemplateOutletContext]=\"{ $implicit: message }\" />\n </div>\n }\n @if (working()) {\n <ng-container [ngTemplateOutlet]=\"workingTemplate\" />\n }\n </div>\n }\n</div>\n\n<ng-template #messageTemplate let-message>\n <article class=\"message\" [attr.data-role]=\"message.role\" [attr.data-others]=\"isOthers(message) ? 'true' : null\">\n @if (isOthers(message)) {\n <p class=\"author\">{{ authorName(message) ?? ('nh-assistant.thread.participant' | translate) }}</p>\n } @else {\n <p class=\"author\">{{ 'nh-assistant.thread.' + (message.role === 'user' ? 'you' : message.role) | translate }}</p>\n }\n @for (group of message.parts | nhAssistantPartGroups; track group.key) {\n @switch (group.kind) {\n @case ('text') {\n @if (message.role === 'assistant' && markdown()) {\n <div class=\"bubble markdown\" [innerHTML]=\"group.part.text | nhAssistantMarkdown\"></div>\n } @else {\n <div class=\"bubble plain\">{{ group.part.text }}</div>\n }\n }\n @case ('tools') {\n <nh-assistant-tool-call-group class=\"part\" [calls]=\"group.calls\" />\n }\n @case ('approval') {\n <nh-assistant-approval-card\n class=\"part\"\n [approval]=\"group.part\"\n [deciding]=\"deciding()\"\n [canDecide]=\"canDecide()\"\n [decisionOwner]=\"decisionOwner()\"\n (decide)=\"approvalDecision.emit($event)\" />\n }\n }\n }\n </article>\n</ng-template>\n\n<ng-template #workingTemplate>\n <p class=\"working\" role=\"status\">\n <span class=\"dots\" aria-hidden=\"true\"><span></span><span></span><span></span></span>\n {{ 'nh-assistant.thread.working' | translate }}\n @if (elapsedSeconds() > 0) {\n <span class=\"elapsed\">{{ 'nh-assistant.thread.elapsed' | translate: { seconds: elapsedSeconds() } }}</span>\n }\n </p>\n</ng-template>\n", styles: [":host{--nha-font: var(--nh-assistant-font, inherit);--nha-background: var(--nh-assistant-background, #ffffff);--nha-surface: var(--nh-assistant-surface, #f5f7fb);--nha-surface-strong: var(--nh-assistant-surface-strong, #eceff6);--nha-text: var(--nh-assistant-text, #080c1d);--nha-text-muted: var(--nh-assistant-text-muted, #5b6482);--nha-border: var(--nh-assistant-border, #dce0ec);--nha-accent: var(--nh-assistant-accent, #022962);--nha-accent-contrast: var(--nh-assistant-accent-contrast, #ffffff);--nha-highlight: var(--nh-assistant-highlight, #c84f00);--nha-user-bubble: var(--nh-assistant-user-bubble, #022962);--nha-user-text: var(--nh-assistant-user-text, #ffffff);--nha-success: var(--nh-assistant-success, #247d4e);--nha-success-soft: var(--nh-assistant-success-soft, #e6f5ec);--nha-warning: var(--nh-assistant-warning, #8a5a00);--nha-warning-soft: var(--nh-assistant-warning-soft, #fff3d9);--nha-danger: var(--nh-assistant-danger, #b92e52);--nha-danger-soft: var(--nh-assistant-danger-soft, #ffe9ef);--nha-focus: var(--nh-assistant-focus, #ff6700);--nha-shadow: var(--nh-assistant-shadow, 0 16px 36px rgb(2 41 98 / .16));--nha-radius: var(--nh-assistant-radius, 16px);--nha-radius-control: var(--nh-assistant-radius-control, 12px);--nha-mono: var(--nh-assistant-font-mono, ui-monospace, \"Cascadia Code\", Consolas, monospace)}@media(prefers-color-scheme:dark){:host{--nha-background: var(--nh-assistant-background, #0b0e22);--nha-surface: var(--nh-assistant-surface, #11152d);--nha-surface-strong: var(--nh-assistant-surface-strong, #181d3b);--nha-text: var(--nh-assistant-text, #ffffff);--nha-text-muted: var(--nh-assistant-text-muted, #b8bed8);--nha-border: var(--nh-assistant-border, #2b3155);--nha-accent: var(--nh-assistant-accent, #0f4087);--nha-accent-contrast: var(--nh-assistant-accent-contrast, #ffffff);--nha-highlight: var(--nh-assistant-highlight, #ff6700);--nha-user-bubble: var(--nh-assistant-user-bubble, #022962);--nha-user-text: var(--nh-assistant-user-text, #ffffff);--nha-success: var(--nh-assistant-success, #67c58f);--nha-success-soft: var(--nh-assistant-success-soft, #102d24);--nha-warning: var(--nh-assistant-warning, #ffbf5b);--nha-warning-soft: var(--nh-assistant-warning-soft, #342818);--nha-danger: var(--nh-assistant-danger, #ff6d8a);--nha-danger-soft: var(--nh-assistant-danger-soft, #351b2a);--nha-shadow: var(--nh-assistant-shadow, 0 16px 36px rgb(0 0 0 / .32))}}:host{display:flex;flex-direction:column;min-height:0;color:var(--nha-text)}.log{display:flex;flex:1;flex-direction:column;min-height:0}.scroller{flex:1;min-height:0;overflow-y:auto;overscroll-behavior:contain;padding:16px;outline:none}.scroller:focus-visible{box-shadow:inset 0 0 0 2px var(--nha-focus)}cdk-virtual-scroll-viewport.scroller{height:100%}.row+.row{margin-top:
|
|
5089
|
+
], changeDetection: ChangeDetectionStrategy.OnPush, template: "<div class=\"log\" role=\"log\" aria-live=\"polite\" [attr.aria-label]=\"'nh-assistant.thread.label' | translate\" [attr.aria-busy]=\"streaming()\">\n @if (virtual()) {\n <cdk-virtual-scroll-viewport class=\"scroller\" itemSize=\"120\" minBufferPx=\"1200\" maxBufferPx=\"2400\">\n <div class=\"row\" *cdkVirtualFor=\"let message of messages(); trackBy: trackMessage\">\n <ng-container [ngTemplateOutlet]=\"messageTemplate\" [ngTemplateOutletContext]=\"{ $implicit: message }\" />\n </div>\n @if (working()) {\n <ng-container [ngTemplateOutlet]=\"workingTemplate\" />\n }\n </cdk-virtual-scroll-viewport>\n } @else {\n <div class=\"scroller\" #scroller tabindex=\"0\">\n @for (message of messages(); track message.id) {\n <div class=\"row\">\n <ng-container [ngTemplateOutlet]=\"messageTemplate\" [ngTemplateOutletContext]=\"{ $implicit: message }\" />\n </div>\n }\n @if (working()) {\n <ng-container [ngTemplateOutlet]=\"workingTemplate\" />\n }\n </div>\n }\n</div>\n\n<ng-template #messageTemplate let-message>\n <article class=\"message\" [attr.data-role]=\"message.role\" [attr.data-others]=\"isOthers(message) ? 'true' : null\">\n @if (isOthers(message)) {\n <p class=\"author\">{{ authorName(message) ?? ('nh-assistant.thread.participant' | translate) }}</p>\n } @else {\n <p class=\"author\">{{ 'nh-assistant.thread.' + (message.role === 'user' ? 'you' : message.role) | translate }}</p>\n }\n @for (group of message.parts | nhAssistantPartGroups; track group.key) {\n @switch (group.kind) {\n @case ('text') {\n @if (message.role === 'assistant' && markdown()) {\n <div class=\"bubble markdown\" [innerHTML]=\"group.part.text | nhAssistantMarkdown\"></div>\n } @else {\n <div class=\"bubble plain\">{{ group.part.text }}</div>\n }\n }\n @case ('tools') {\n <nh-assistant-tool-call-group class=\"part\" [calls]=\"group.calls\" />\n }\n @case ('approval') {\n <nh-assistant-approval-card\n class=\"part\"\n [approval]=\"group.part\"\n [deciding]=\"deciding()\"\n [canDecide]=\"canDecide()\"\n [decisionOwner]=\"decisionOwner()\"\n (decide)=\"approvalDecision.emit($event)\" />\n }\n }\n }\n </article>\n</ng-template>\n\n<ng-template #workingTemplate>\n <p class=\"working\" role=\"status\">\n <span class=\"dots\" aria-hidden=\"true\"><span></span><span></span><span></span></span>\n {{ 'nh-assistant.thread.working' | translate }}\n @if (elapsedSeconds() > 0) {\n <span class=\"elapsed\">{{ 'nh-assistant.thread.elapsed' | translate: { seconds: elapsedSeconds() } }}</span>\n }\n </p>\n</ng-template>\n", styles: [":host{--nha-font: var(--nh-assistant-font, inherit);--nha-background: var(--nh-assistant-background, #ffffff);--nha-surface: var(--nh-assistant-surface, #f5f7fb);--nha-surface-strong: var(--nh-assistant-surface-strong, #eceff6);--nha-text: var(--nh-assistant-text, #080c1d);--nha-text-muted: var(--nh-assistant-text-muted, #5b6482);--nha-border: var(--nh-assistant-border, #dce0ec);--nha-accent: var(--nh-assistant-accent, #022962);--nha-accent-contrast: var(--nh-assistant-accent-contrast, #ffffff);--nha-highlight: var(--nh-assistant-highlight, #c84f00);--nha-user-bubble: var(--nh-assistant-user-bubble, #022962);--nha-user-text: var(--nh-assistant-user-text, #ffffff);--nha-success: var(--nh-assistant-success, #247d4e);--nha-success-soft: var(--nh-assistant-success-soft, #e6f5ec);--nha-warning: var(--nh-assistant-warning, #8a5a00);--nha-warning-soft: var(--nh-assistant-warning-soft, #fff3d9);--nha-danger: var(--nh-assistant-danger, #b92e52);--nha-danger-soft: var(--nh-assistant-danger-soft, #ffe9ef);--nha-focus: var(--nh-assistant-focus, #ff6700);--nha-shadow: var(--nh-assistant-shadow, 0 16px 36px rgb(2 41 98 / .16));--nha-radius: var(--nh-assistant-radius, 16px);--nha-radius-control: var(--nh-assistant-radius-control, 12px);--nha-mono: var(--nh-assistant-font-mono, ui-monospace, \"Cascadia Code\", Consolas, monospace)}@media(prefers-color-scheme:dark){:host{--nha-background: var(--nh-assistant-background, #0b0e22);--nha-surface: var(--nh-assistant-surface, #11152d);--nha-surface-strong: var(--nh-assistant-surface-strong, #181d3b);--nha-text: var(--nh-assistant-text, #ffffff);--nha-text-muted: var(--nh-assistant-text-muted, #b8bed8);--nha-border: var(--nh-assistant-border, #2b3155);--nha-accent: var(--nh-assistant-accent, #0f4087);--nha-accent-contrast: var(--nh-assistant-accent-contrast, #ffffff);--nha-highlight: var(--nh-assistant-highlight, #ff6700);--nha-user-bubble: var(--nh-assistant-user-bubble, #022962);--nha-user-text: var(--nh-assistant-user-text, #ffffff);--nha-success: var(--nh-assistant-success, #67c58f);--nha-success-soft: var(--nh-assistant-success-soft, #102d24);--nha-warning: var(--nh-assistant-warning, #ffbf5b);--nha-warning-soft: var(--nh-assistant-warning-soft, #342818);--nha-danger: var(--nh-assistant-danger, #ff6d8a);--nha-danger-soft: var(--nh-assistant-danger-soft, #351b2a);--nha-shadow: var(--nh-assistant-shadow, 0 16px 36px rgb(0 0 0 / .32))}}:host{display:flex;flex-direction:column;min-height:0;color:var(--nha-text)}.log{display:flex;flex:1;flex-direction:column;min-height:0}.scroller{flex:1;min-height:0;overflow-y:auto;overscroll-behavior:contain;padding:16px;outline:none}.scroller:focus-visible{box-shadow:inset 0 0 0 2px var(--nha-focus)}cdk-virtual-scroll-viewport.scroller{height:100%}.row+.row{margin-top:20px}.message{display:flex;flex-direction:column;align-items:flex-start;gap:6px;min-width:0}.message[data-role=user]{align-items:flex-end}.author{margin:0;color:var(--nha-text-muted);font-size:11px;font-weight:600}.bubble{max-width:100%;border-radius:var(--nha-radius-control);padding:8px 12px;font-size:14px;line-height:1.5;overflow-wrap:anywhere}.plain{white-space:pre-wrap}.message[data-role=user] .bubble{max-width:88%;color:var(--nha-user-text);background:var(--nha-user-bubble)}.message[data-others=true]{align-items:flex-start}.message[data-others=true] .bubble{color:var(--nha-text);background:var(--nha-surface-strong)}.message[data-role=assistant] .bubble,.message[data-role=tool] .bubble{padding-inline:0;background:transparent}.part{width:100%}:host ::ng-deep .markdown :first-child{margin-top:0}:host ::ng-deep .markdown :last-child{margin-bottom:0}:host ::ng-deep .markdown p,:host ::ng-deep .markdown ul,:host ::ng-deep .markdown ol,:host ::ng-deep .markdown pre,:host ::ng-deep .markdown blockquote,:host ::ng-deep .markdown table{margin:0 0 8px}:host ::ng-deep .markdown ul,:host ::ng-deep .markdown ol{padding-left:20px}:host ::ng-deep .markdown h1,:host ::ng-deep .markdown h2,:host ::ng-deep .markdown h3,:host ::ng-deep .markdown h4,:host ::ng-deep .markdown h5,:host ::ng-deep .markdown h6{margin:10px 0 6px;font-size:15px;line-height:1.3}:host ::ng-deep .markdown a{color:var(--nha-highlight);text-decoration:underline}:host ::ng-deep .markdown a:focus-visible{outline:3px solid color-mix(in srgb,var(--nha-focus) 80%,transparent);outline-offset:2px}:host ::ng-deep .markdown code{border-radius:6px;padding:1px 4px;background:var(--nha-surface-strong);font-family:var(--nha-mono);font-size:12.5px}:host ::ng-deep .markdown pre{overflow-x:auto;border-radius:8px;padding:8px;background:var(--nha-surface-strong)}:host ::ng-deep .markdown pre code{padding:0;background:none}:host ::ng-deep .markdown blockquote{border-left:3px solid var(--nha-border);padding-left:10px;color:var(--nha-text-muted)}:host ::ng-deep .markdown table{display:block;max-width:100%;overflow-x:auto;border-collapse:collapse;font-size:13px}:host ::ng-deep .markdown th,:host ::ng-deep .markdown td{border:1px solid var(--nha-border);padding:4px 8px;text-align:left}.working{display:flex;align-items:center;gap:8px;margin:14px 0 0;color:var(--nha-text-muted);font-size:13px}.elapsed{font-variant-numeric:tabular-nums}.dots{display:inline-flex;gap:3px}.dots span{width:6px;height:6px;border-radius:50%;background:currentColor;opacity:.6}@media(prefers-reduced-motion:no-preference){.dots span{animation:nha-bounce 1s ease-in-out infinite}.dots span:nth-child(2){animation-delay:.15s}.dots span:nth-child(3){animation-delay:.3s}}@keyframes nha-bounce{0%,80%,to{transform:translateY(0);opacity:.35}40%{transform:translateY(-3px);opacity:1}}\n"] }]
|
|
4872
5090
|
}], ctorParameters: () => [], propDecorators: { messages: [{ type: i0.Input, args: [{ isSignal: true, alias: "messages", required: true }] }], streaming: [{ type: i0.Input, args: [{ isSignal: true, alias: "streaming", required: false }] }], deciding: [{ type: i0.Input, args: [{ isSignal: true, alias: "deciding", required: false }] }], markdown: [{ type: i0.Input, args: [{ isSignal: true, alias: "markdown", required: false }] }], members: [{ type: i0.Input, args: [{ isSignal: true, alias: "members", required: false }] }], currentActorId: [{ type: i0.Input, args: [{ isSignal: true, alias: "currentActorId", required: false }] }], canDecide: [{ type: i0.Input, args: [{ isSignal: true, alias: "canDecide", required: false }] }], decisionOwner: [{ type: i0.Input, args: [{ isSignal: true, alias: "decisionOwner", required: false }] }], approvalDecision: [{ type: i0.Output, args: ["approvalDecision"] }], scroller: [{ type: i0.ViewChild, args: ['scroller', { isSignal: true }] }], viewport: [{ type: i0.ViewChild, args: [i0.forwardRef(() => CdkVirtualScrollViewport), { isSignal: true }] }] } });
|
|
4873
5091
|
|
|
4874
5092
|
let nextId = 0;
|
|
@@ -4891,6 +5109,10 @@ class NhAssistantPanelComponent {
|
|
|
4891
5109
|
this.showConversations = signal(false, ...(ngDevMode ? [{ debugName: "showConversations" }] : []));
|
|
4892
5110
|
this.showPreferences = signal(false, ...(ngDevMode ? [{ debugName: "showPreferences" }] : []));
|
|
4893
5111
|
this.showShare = signal(false, ...(ngDevMode ? [{ debugName: "showShare" }] : []));
|
|
5112
|
+
this.shareSection = signal('all', ...(ngDevMode ? [{ debugName: "shareSection" }] : []));
|
|
5113
|
+
this.notificationError = signal(null, ...(ngDevMode ? [{ debugName: "notificationError" }] : []));
|
|
5114
|
+
this.notificationsLabel = computed(() => this.push.settings()?.pushEnabled
|
|
5115
|
+
? 'nh-assistant.panel.notifications-off' : 'nh-assistant.panel.notifications-on', ...(ngDevMode ? [{ debugName: "notificationsLabel" }] : []));
|
|
4894
5116
|
this.adminRoute = this.config.adminRoute ?? null;
|
|
4895
5117
|
this.conversation = this.store.activeConversation;
|
|
4896
5118
|
this.conversationId = computed(() => this.conversation()?.id ?? null, ...(ngDevMode ? [{ debugName: "conversationId" }] : []));
|
|
@@ -4900,7 +5122,12 @@ class NhAssistantPanelComponent {
|
|
|
4900
5122
|
return status === 'failed' || status === 'archived';
|
|
4901
5123
|
}, ...(ngDevMode ? [{ debugName: "closed" }] : []));
|
|
4902
5124
|
this.busy = computed(() => this.store.streaming() || this.conversation()?.status === 'running', ...(ngDevMode ? [{ debugName: "busy" }] : []));
|
|
4903
|
-
this.composerDisabled = computed(() => !this.store.
|
|
5125
|
+
this.composerDisabled = computed(() => !this.store.canSubmit(), ...(ngDevMode ? [{ debugName: "composerDisabled" }] : []));
|
|
5126
|
+
this.editingQueuedId = signal(null, ...(ngDevMode ? [{ debugName: "editingQueuedId" }] : []));
|
|
5127
|
+
this.queuedDraft = signal('', ...(ngDevMode ? [{ debugName: "queuedDraft" }] : []));
|
|
5128
|
+
this.resumeAfterEditing = false;
|
|
5129
|
+
this.validQueuedDraft = computed(() => this.queuedDraft().trim().length > 0
|
|
5130
|
+
&& this.queuedDraft().trim().length <= (this.store.limits()?.maxMessageChars ?? Infinity), ...(ngDevMode ? [{ debugName: "validQueuedDraft" }] : []));
|
|
4904
5131
|
this.composerStatus = computed(() => {
|
|
4905
5132
|
if (this.store.streaming() || this.conversation()?.status === 'running') {
|
|
4906
5133
|
return 'running';
|
|
@@ -4914,10 +5141,10 @@ class NhAssistantPanelComponent {
|
|
|
4914
5141
|
}, ...(ngDevMode ? [{ debugName: "activeMemberName" }] : []));
|
|
4915
5142
|
/** The owner and the person who started the turn may stop it. */
|
|
4916
5143
|
this.canStop = computed(() => this.store.isOwner() || this.store.activeMember() === null, ...(ngDevMode ? [{ debugName: "canStop" }] : []));
|
|
4917
|
-
this.shared = computed(() => this.store.members().
|
|
5144
|
+
this.shared = computed(() => this.store.members().some(member => member.role === 'participant'), ...(ngDevMode ? [{ debugName: "shared" }] : []));
|
|
4918
5145
|
this.canShare = computed(() => this.conversation() !== null && !!this.store.collaboration(), ...(ngDevMode ? [{ debugName: "canShare" }] : []));
|
|
4919
5146
|
this.errorKeys = computed(() => {
|
|
4920
|
-
const error = this.store.error();
|
|
5147
|
+
const error = this.notificationError() ?? this.store.error();
|
|
4921
5148
|
return error ? [error.messageKey, `nh-assistant.errors.${error.code}`, 'nh-assistant.errors.generic'] : [];
|
|
4922
5149
|
}, ...(ngDevMode ? [{ debugName: "errorKeys" }] : []));
|
|
4923
5150
|
this.noticeKeys = computed(() => {
|
|
@@ -4950,7 +5177,7 @@ class NhAssistantPanelComponent {
|
|
|
4950
5177
|
});
|
|
4951
5178
|
}
|
|
4952
5179
|
});
|
|
4953
|
-
// The drawer stays open while the user navigates; keep the page-context
|
|
5180
|
+
// The drawer stays open while the user navigates; keep the page-context control current.
|
|
4954
5181
|
const navigation = this.router?.events.subscribe(event => {
|
|
4955
5182
|
if (event instanceof NavigationEnd && this.panel.isOpen()) {
|
|
4956
5183
|
this.refreshPageContext();
|
|
@@ -4984,10 +5211,27 @@ class NhAssistantPanelComponent {
|
|
|
4984
5211
|
this.showShare.set(false);
|
|
4985
5212
|
this.showPreferences.update(show => !show);
|
|
4986
5213
|
}
|
|
4987
|
-
toggleShare() {
|
|
5214
|
+
toggleShare(section = 'all') {
|
|
4988
5215
|
this.showConversations.set(false);
|
|
4989
5216
|
this.showPreferences.set(false);
|
|
4990
|
-
this.showShare.
|
|
5217
|
+
const close = this.showShare() && this.shareSection() === section;
|
|
5218
|
+
this.shareSection.set(section);
|
|
5219
|
+
this.showShare.set(!close);
|
|
5220
|
+
}
|
|
5221
|
+
/** Applies the notification choice immediately, including browser permission handling. */
|
|
5222
|
+
async toggleNotifications() {
|
|
5223
|
+
if (this.push.busy() || this.push.state() === 'unavailable') {
|
|
5224
|
+
return;
|
|
5225
|
+
}
|
|
5226
|
+
this.notificationError.set(null);
|
|
5227
|
+
try {
|
|
5228
|
+
await this.push.setEnabled(!this.push.settings()?.pushEnabled);
|
|
5229
|
+
}
|
|
5230
|
+
catch (error) {
|
|
5231
|
+
this.notificationError.set(error instanceof NhAssistantApiError
|
|
5232
|
+
? { code: error.code, messageKey: error.messageKey }
|
|
5233
|
+
: { code: 'assistant-server', messageKey: nhAssistantErrorMessageKey('assistant-server') });
|
|
5234
|
+
}
|
|
4991
5235
|
}
|
|
4992
5236
|
newConversation() {
|
|
4993
5237
|
this.store.startNewConversation();
|
|
@@ -5004,7 +5248,27 @@ class NhAssistantPanelComponent {
|
|
|
5004
5248
|
this.showConversations.set(false);
|
|
5005
5249
|
this.showPreferences.set(false);
|
|
5006
5250
|
this.showShare.set(false);
|
|
5007
|
-
void this.store.
|
|
5251
|
+
void this.store.submit(text);
|
|
5252
|
+
}
|
|
5253
|
+
editQueuedMessage(id, text) {
|
|
5254
|
+
this.resumeAfterEditing = !this.store.queuePaused();
|
|
5255
|
+
this.store.pauseQueue();
|
|
5256
|
+
this.editingQueuedId.set(id);
|
|
5257
|
+
this.queuedDraft.set(text);
|
|
5258
|
+
}
|
|
5259
|
+
changeQueuedDraft(event) {
|
|
5260
|
+
this.queuedDraft.set(event.target.value);
|
|
5261
|
+
}
|
|
5262
|
+
saveQueuedMessage(id) {
|
|
5263
|
+
if (this.store.updateQueuedMessage(id, this.queuedDraft())) {
|
|
5264
|
+
this.cancelQueueEdit();
|
|
5265
|
+
}
|
|
5266
|
+
}
|
|
5267
|
+
cancelQueueEdit() {
|
|
5268
|
+
this.editingQueuedId.set(null);
|
|
5269
|
+
if (this.resumeAfterEditing && !this.store.error()) {
|
|
5270
|
+
this.store.resumeQueue();
|
|
5271
|
+
}
|
|
5008
5272
|
}
|
|
5009
5273
|
/**
|
|
5010
5274
|
* Opens the panel for an invitation link or a clicked notification in the URL fragment and
|
|
@@ -5040,7 +5304,7 @@ class NhAssistantPanelComponent {
|
|
|
5040
5304
|
void this.store.cancel();
|
|
5041
5305
|
}
|
|
5042
5306
|
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.3.33", ngImport: i0, type: NhAssistantPanelComponent, deps: [], target: i0.ɵɵFactoryTarget.Component }); }
|
|
5043
|
-
static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "20.3.33", type: NhAssistantPanelComponent, isStandalone: true, selector: "nh-assistant-panel", viewQueries: [{ propertyName: "drawer", first: true, predicate: ["drawer"], descendants: true, isSignal: true }], ngImport: i0, template: "<ng-template #drawer>\n <section class=\"drawer\" role=\"dialog\" aria-modal=\"false\" [attr.aria-labelledby]=\"titleId\">\n <header class=\"header\">\n <div class=\"heading\">\n <h2 [id]=\"titleId\">{{ 'nh-assistant.panel.title' | translate }}</h2>\n @if (store.enabled()) {\n <nh-assistant-agent-picker\n [agents]=\"store.agents()\"\n [selectedAgentId]=\"store.selectedAgentId()\"\n (agentChange)=\"store.selectAgent($event)\" />\n }\n </div>\n <div class=\"header-actions\">\n @if (store.enabled()) {\n @if (canShare()) {\n <button\n class=\"icon-button\"\n type=\"button\"\n [class.active]=\"showShare() || shared()\"\n [attr.aria-expanded]=\"showShare()\"\n [attr.aria-label]=\"(store.isOwner() ? 'nh-assistant.panel.share' : 'nh-assistant.panel.members') | translate\"\n [attr.title]=\"(store.isOwner() ? 'nh-assistant.panel.share' : 'nh-assistant.panel.members') | translate\"\n (click)=\"toggleShare()\">\n <nh-assistant-icon name=\"users\" />\n </button>\n }\n <button\n class=\"icon-button\"\n type=\"button\"\n [class.active]=\"showConversations()\"\n [attr.aria-expanded]=\"showConversations()\"\n [attr.aria-label]=\"(showConversations() ? 'nh-assistant.panel.hide-conversations' : 'nh-assistant.panel.show-conversations') | translate\"\n [attr.title]=\"(showConversations() ? 'nh-assistant.panel.hide-conversations' : 'nh-assistant.panel.show-conversations') | translate\"\n (click)=\"toggleConversations()\">\n <nh-assistant-icon name=\"list\" />\n </button>\n <button\n class=\"icon-button\"\n type=\"button\"\n [class.active]=\"showPreferences()\"\n [attr.aria-expanded]=\"showPreferences()\"\n [attr.aria-label]=\"'nh-assistant.panel.open-preferences' | translate\"\n [attr.title]=\"'nh-assistant.panel.open-preferences' | translate\"\n (click)=\"togglePreferences()\">\n <nh-assistant-icon name=\"settings\" />\n </button>\n @if (adminRoute && store.canAdminister()) {\n <a\n class=\"icon-button\"\n [routerLink]=\"adminRoute\"\n [attr.aria-label]=\"'nh-assistant.panel.open-admin' | translate\"\n [attr.title]=\"'nh-assistant.panel.open-admin' | translate\"\n (click)=\"panel.close()\">\n <nh-assistant-icon name=\"admin\" />\n </a>\n }\n <button\n class=\"icon-button\"\n type=\"button\"\n [attr.aria-label]=\"'nh-assistant.panel.new-conversation' | translate\"\n [attr.title]=\"'nh-assistant.panel.new-conversation' | translate\"\n (click)=\"newConversation()\">\n <nh-assistant-icon name=\"plus\" />\n </button>\n }\n <button\n class=\"icon-button\"\n type=\"button\"\n [attr.aria-label]=\"'nh-assistant.panel.close' | translate\"\n [attr.title]=\"'nh-assistant.panel.close' | translate\"\n (click)=\"panel.close()\">\n <nh-assistant-icon name=\"close\" />\n </button>\n </div>\n </header>\n\n @if (store.enabled()) {\n <nh-assistant-activity [items]=\"store.activity()\" (conversationSelect)=\"openConversation($event)\" />\n }\n\n <div class=\"body\">\n @if (store.statusLoading() && !store.enabled()) {\n <div class=\"state\" role=\"status\">\n <p class=\"state-title\">{{ 'nh-assistant.panel.loading' | translate }}</p>\n </div>\n } @else if (!store.enabled()) {\n <div class=\"state\">\n <nh-assistant-icon class=\"state-icon\" name=\"warning\" />\n <p class=\"state-title\">{{ 'nh-assistant.panel.unavailable-title' | translate }}</p>\n <p>{{ 'nh-assistant.panel.unavailable-description' | translate }}</p>\n </div>\n } @else {\n @if (showPreferences()) {\n <nh-assistant-preferences class=\"overlay-view\" (closed)=\"showPreferences.set(false)\" />\n }\n\n @if (showShare()) {\n <nh-assistant-share class=\"overlay-view\" (closed)=\"showShare.set(false)\" />\n }\n\n @if (showConversations()) {\n <nh-assistant-conversation-list\n class=\"overlay-view\"\n [conversations]=\"store.conversations()\"\n [total]=\"store.conversationsTotal()\"\n [activeConversationId]=\"conversation()?.id ?? null\"\n [loading]=\"store.conversationsLoading()\"\n (conversationSelect)=\"openConversation($event)\"\n (conversationDelete)=\"deleteConversation($event)\"\n (conversationCreate)=\"newConversation()\" />\n }\n\n @if (store.conversationLoading()) {\n <div class=\"state\" role=\"status\">\n <p class=\"state-title\">{{ 'nh-assistant.thread.loading' | translate }}</p>\n </div>\n } @else if (messages().length === 0 && !store.streaming()) {\n <div class=\"state\">\n <nh-assistant-icon class=\"state-icon\" name=\"assistant\" />\n <p class=\"state-title\">{{ 'nh-assistant.panel.empty-title' | translate }}</p>\n <p>{{ 'nh-assistant.panel.empty-description' | translate }}</p>\n </div>\n } @else {\n <nh-assistant-thread\n class=\"thread\"\n [messages]=\"messages()\"\n [streaming]=\"busy()\"\n [deciding]=\"store.deciding()\"\n [markdown]=\"markdown\"\n [members]=\"store.members()\"\n [currentActorId]=\"conversation()?.currentActorId ?? null\"\n [canDecide]=\"store.canDecide()\"\n [decisionOwner]=\"activeMemberName()\"\n (approvalDecision)=\"decide($event)\" />\n }\n }\n </div>\n\n @if (store.error(); as error) {\n <div class=\"error\" role=\"alert\">\n <nh-assistant-icon name=\"warning\" />\n <p>{{ errorKeys() | nhAssistantTranslate: error.code }}</p>\n <button\n class=\"icon-button\"\n type=\"button\"\n [attr.aria-label]=\"'nh-assistant.panel.dismiss-error' | translate\"\n [attr.title]=\"'nh-assistant.panel.dismiss-error' | translate\"\n (click)=\"store.clearError()\">\n <nh-assistant-icon name=\"close\" />\n </button>\n </div>\n } @else if (store.notice(); as notice) {\n <div class=\"turn-notice\" role=\"status\">\n <nh-assistant-icon name=\"warning\" />\n <p>{{ noticeKeys() | nhAssistantTranslate: notice.code }}</p>\n <button\n class=\"icon-button\"\n type=\"button\"\n [attr.aria-label]=\"'nh-assistant.panel.dismiss-error' | translate\"\n [attr.title]=\"'nh-assistant.panel.dismiss-error' | translate\"\n (click)=\"store.clearNotice()\">\n <nh-assistant-icon name=\"close\" />\n </button>\n </div>\n }\n\n @if (store.enabled() && !showPreferences() && !showShare()) {\n <footer class=\"footer\" (focusin)=\"refreshPageContext()\">\n @if (closed()) {\n <p class=\"notice\">{{ 'nh-assistant.panel.conversation-closed' | translate }}</p>\n }\n @if (store.pageContext(); as context) {\n <div class=\"context-chip\" [class.excluded]=\"store.pageContextExcluded()\" [attr.title]=\"context.route\">\n <nh-assistant-icon name=\"page\" />\n <span class=\"context-text\">\n {{ (store.pageContextExcluded() ? 'nh-assistant.page-context.excluded' : 'nh-assistant.page-context.included') | translate: { page: describeContext(context) } }}\n </span>\n <button\n class=\"icon-button small\"\n type=\"button\"\n [attr.aria-pressed]=\"store.pageContextExcluded()\"\n [attr.aria-label]=\"(store.pageContextExcluded() ? 'nh-assistant.page-context.include' : 'nh-assistant.page-context.exclude') | translate: { page: describeContext(context) }\"\n [attr.title]=\"(store.pageContextExcluded() ? 'nh-assistant.page-context.include' : 'nh-assistant.page-context.exclude') | translate: { page: describeContext(context) }\"\n (click)=\"store.setPageContextExcluded(!store.pageContextExcluded())\">\n <nh-assistant-icon [name]=\"store.pageContextExcluded() ? 'plus' : 'x'\" />\n </button>\n </div>\n }\n <nh-assistant-composer\n [disabled]=\"closed()\"\n [sendDisabled]=\"composerDisabled()\"\n [busy]=\"busy()\"\n [status]=\"composerStatus()\"\n [statusActor]=\"activeMemberName()\"\n [canStop]=\"canStop()\"\n [maxLength]=\"store.limits()?.maxMessageChars ?? null\"\n [restore]=\"store.restoredDraft()\"\n (restored)=\"store.consumeRestoredDraft()\"\n (send)=\"send($event)\"\n (cancel)=\"cancel()\" />\n </footer>\n }\n </section>\n</ng-template>\n", styles: [":host{--nha-font: var(--nh-assistant-font, inherit);--nha-background: var(--nh-assistant-background, #ffffff);--nha-surface: var(--nh-assistant-surface, #f5f7fb);--nha-surface-strong: var(--nh-assistant-surface-strong, #eceff6);--nha-text: var(--nh-assistant-text, #080c1d);--nha-text-muted: var(--nh-assistant-text-muted, #5b6482);--nha-border: var(--nh-assistant-border, #dce0ec);--nha-accent: var(--nh-assistant-accent, #022962);--nha-accent-contrast: var(--nh-assistant-accent-contrast, #ffffff);--nha-highlight: var(--nh-assistant-highlight, #c84f00);--nha-user-bubble: var(--nh-assistant-user-bubble, #022962);--nha-user-text: var(--nh-assistant-user-text, #ffffff);--nha-success: var(--nh-assistant-success, #247d4e);--nha-success-soft: var(--nh-assistant-success-soft, #e6f5ec);--nha-warning: var(--nh-assistant-warning, #8a5a00);--nha-warning-soft: var(--nh-assistant-warning-soft, #fff3d9);--nha-danger: var(--nh-assistant-danger, #b92e52);--nha-danger-soft: var(--nh-assistant-danger-soft, #ffe9ef);--nha-focus: var(--nh-assistant-focus, #ff6700);--nha-shadow: var(--nh-assistant-shadow, 0 16px 36px rgb(2 41 98 / .16));--nha-radius: var(--nh-assistant-radius, 16px);--nha-radius-control: var(--nh-assistant-radius-control, 12px);--nha-mono: var(--nh-assistant-font-mono, ui-monospace, \"Cascadia Code\", Consolas, monospace)}@media(prefers-color-scheme:dark){:host{--nha-background: var(--nh-assistant-background, #0b0e22);--nha-surface: var(--nh-assistant-surface, #11152d);--nha-surface-strong: var(--nh-assistant-surface-strong, #181d3b);--nha-text: var(--nh-assistant-text, #ffffff);--nha-text-muted: var(--nh-assistant-text-muted, #b8bed8);--nha-border: var(--nh-assistant-border, #2b3155);--nha-accent: var(--nh-assistant-accent, #0f4087);--nha-accent-contrast: var(--nh-assistant-accent-contrast, #ffffff);--nha-highlight: var(--nh-assistant-highlight, #ff6700);--nha-user-bubble: var(--nh-assistant-user-bubble, #022962);--nha-user-text: var(--nh-assistant-user-text, #ffffff);--nha-success: var(--nh-assistant-success, #67c58f);--nha-success-soft: var(--nh-assistant-success-soft, #102d24);--nha-warning: var(--nh-assistant-warning, #ffbf5b);--nha-warning-soft: var(--nh-assistant-warning-soft, #342818);--nha-danger: var(--nh-assistant-danger, #ff6d8a);--nha-danger-soft: var(--nh-assistant-danger-soft, #351b2a);--nha-shadow: var(--nh-assistant-shadow, 0 16px 36px rgb(0 0 0 / .32))}}.drawer{--nha-font: var(--nh-assistant-font, inherit);--nha-background: var(--nh-assistant-background, #ffffff);--nha-surface: var(--nh-assistant-surface, #f5f7fb);--nha-surface-strong: var(--nh-assistant-surface-strong, #eceff6);--nha-text: var(--nh-assistant-text, #080c1d);--nha-text-muted: var(--nh-assistant-text-muted, #5b6482);--nha-border: var(--nh-assistant-border, #dce0ec);--nha-accent: var(--nh-assistant-accent, #022962);--nha-accent-contrast: var(--nh-assistant-accent-contrast, #ffffff);--nha-highlight: var(--nh-assistant-highlight, #c84f00);--nha-user-bubble: var(--nh-assistant-user-bubble, #022962);--nha-user-text: var(--nh-assistant-user-text, #ffffff);--nha-success: var(--nh-assistant-success, #247d4e);--nha-success-soft: var(--nh-assistant-success-soft, #e6f5ec);--nha-warning: var(--nh-assistant-warning, #8a5a00);--nha-warning-soft: var(--nh-assistant-warning-soft, #fff3d9);--nha-danger: var(--nh-assistant-danger, #b92e52);--nha-danger-soft: var(--nh-assistant-danger-soft, #ffe9ef);--nha-focus: var(--nh-assistant-focus, #ff6700);--nha-shadow: var(--nh-assistant-shadow, 0 16px 36px rgb(2 41 98 / .16));--nha-radius: var(--nh-assistant-radius, 16px);--nha-radius-control: var(--nh-assistant-radius-control, 12px);--nha-mono: var(--nh-assistant-font-mono, ui-monospace, \"Cascadia Code\", Consolas, monospace)}@media(prefers-color-scheme:dark){.drawer{--nha-background: var(--nh-assistant-background, #0b0e22);--nha-surface: var(--nh-assistant-surface, #11152d);--nha-surface-strong: var(--nh-assistant-surface-strong, #181d3b);--nha-text: var(--nh-assistant-text, #ffffff);--nha-text-muted: var(--nh-assistant-text-muted, #b8bed8);--nha-border: var(--nh-assistant-border, #2b3155);--nha-accent: var(--nh-assistant-accent, #0f4087);--nha-accent-contrast: var(--nh-assistant-accent-contrast, #ffffff);--nha-highlight: var(--nh-assistant-highlight, #ff6700);--nha-user-bubble: var(--nh-assistant-user-bubble, #022962);--nha-user-text: var(--nh-assistant-user-text, #ffffff);--nha-success: var(--nh-assistant-success, #67c58f);--nha-success-soft: var(--nh-assistant-success-soft, #102d24);--nha-warning: var(--nh-assistant-warning, #ffbf5b);--nha-warning-soft: var(--nh-assistant-warning-soft, #342818);--nha-danger: var(--nh-assistant-danger, #ff6d8a);--nha-danger-soft: var(--nh-assistant-danger-soft, #351b2a);--nha-shadow: var(--nh-assistant-shadow, 0 16px 36px rgb(0 0 0 / .32))}}:host{display:contents}.drawer{position:relative;display:flex;flex-direction:column;box-sizing:border-box;width:100%;height:100%;border-left:1px solid var(--nha-border);color:var(--nha-text);background:var(--nha-background);box-shadow:var(--nha-shadow);font-family:var(--nha-font);font-size:14px}.drawer *,.drawer *:before,.drawer *:after{box-sizing:border-box}.header{display:grid;grid-template-columns:minmax(0,1fr) auto;align-items:center;gap:6px 12px;border-bottom:1px solid var(--nha-border);padding:12px 12px 12px 16px}.heading{display:contents}nh-assistant-agent-picker{grid-column:1/-1;grid-row:2}h2{grid-row:1;min-width:0;margin:0;overflow:hidden;font-size:16px;font-weight:750;letter-spacing:-.01em;text-overflow:ellipsis;white-space:nowrap}.header-actions{display:flex;flex:none;grid-column:2;grid-row:1;gap:4px}.icon-button{display:inline-flex;align-items:center;justify-content:center;width:36px;height:36px;padding:0;border:1px solid transparent;border-radius:var(--nha-radius-control);color:var(--nha-text-muted);background:transparent;cursor:pointer;text-decoration:none}.icon-button:focus-visible{outline:3px solid color-mix(in srgb,var(--nha-focus) 80%,transparent);outline-offset:2px}.icon-button:hover:not(:disabled){color:var(--nha-text);background:var(--nha-surface-strong)}.icon-button:disabled{cursor:not-allowed;opacity:.5}.icon-button.active{color:var(--nha-highlight);background:var(--nha-surface-strong)}.body{position:relative;display:flex;flex:1;flex-direction:column;min-height:0;background:var(--nha-background)}.thread{flex:1;min-height:0}.overlay-view{position:absolute;z-index:1;inset:0;border-bottom:1px solid var(--nha-border);background:var(--nha-background)}.state{display:flex;flex:1;flex-direction:column;align-items:center;justify-content:center;gap:4px;padding:24px;color:var(--nha-text-muted);text-align:center}.state p{max-width:32ch;margin:0;font-size:13px}.state-icon{margin-bottom:8px;color:var(--nha-highlight);font-size:28px}.state .state-title{color:var(--nha-text);font-size:15px;font-weight:700}.error{display:flex;align-items:center;gap:8px;margin:0 12px 8px;border:1px solid var(--nha-danger);border-radius:var(--nha-radius-control);padding:4px 4px 4px 12px;color:var(--nha-danger);background:var(--nha-danger-soft)}.error p{flex:1;margin:0;color:var(--nha-text);font-size:13px}.turn-notice{display:flex;align-items:center;gap:8px;margin:0 12px 8px;border:1px solid var(--nha-warning);border-radius:var(--nha-radius-control);padding:4px 4px 4px 12px;color:var(--nha-warning);background:var(--nha-warning-soft)}.turn-notice p{flex:1;margin:0;color:var(--nha-text);font-size:13px}.footer{border-top:1px solid var(--nha-border);padding:12px 16px 14px}.context-chip{display:flex;align-items:center;gap:6px;max-width:100%;margin:0 0 8px;border:1px solid var(--nha-border);border-radius:999px;padding:2px 2px 2px 10px;width:fit-content;color:var(--nha-text-muted);background:var(--nha-surface);font-size:12px}.context-chip.excluded .context-text{text-decoration:line-through}.context-text{min-width:0;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}.icon-button.small{flex:none;width:26px;height:26px;border-radius:999px}.notice{margin:0 0 8px;color:var(--nha-text-muted);font-size:12px}\n"], dependencies: [{ kind: "directive", type: RouterLink, selector: "[routerLink]", inputs: ["target", "queryParams", "fragment", "queryParamsHandling", "state", "info", "relativeTo", "preserveFragment", "skipLocationChange", "replaceUrl", "routerLink"] }, { kind: "component", type: NhAssistantIconComponent, selector: "nh-assistant-icon", inputs: ["name"] }, { kind: "component", type: NhAssistantActivityComponent, selector: "nh-assistant-activity", inputs: ["items"], outputs: ["conversationSelect"] }, { kind: "component", type: NhAssistantAgentPickerComponent, selector: "nh-assistant-agent-picker", inputs: ["agents", "selectedAgentId", "disabled"], outputs: ["agentChange"] }, { kind: "component", type: NhAssistantComposerComponent, selector: "nh-assistant-composer", inputs: ["disabled", "sendDisabled", "busy", "status", "statusActor", "canStop", "maxLength", "restore"], outputs: ["send", "cancel", "restored"] }, { kind: "component", type: NhAssistantConversationListComponent, selector: "nh-assistant-conversation-list", inputs: ["conversations", "total", "activeConversationId", "loading", "disabled"], outputs: ["conversationSelect", "conversationDelete", "conversationCreate"] }, { kind: "component", type: NhAssistantPreferencesComponent, selector: "nh-assistant-preferences", outputs: ["closed", "saved"] }, { kind: "component", type: NhAssistantShareComponent, selector: "nh-assistant-share", outputs: ["closed"] }, { kind: "component", type: NhAssistantThreadComponent, selector: "nh-assistant-thread", inputs: ["messages", "streaming", "deciding", "markdown", "members", "currentActorId", "canDecide", "decisionOwner"], outputs: ["approvalDecision"] }, { kind: "pipe", type: TranslatePipe, name: "translate" }, { kind: "pipe", type: NhAssistantTranslatePipe, name: "nhAssistantTranslate" }], changeDetection: i0.ChangeDetectionStrategy.OnPush }); }
|
|
5307
|
+
static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "20.3.33", type: NhAssistantPanelComponent, isStandalone: true, selector: "nh-assistant-panel", viewQueries: [{ propertyName: "drawer", first: true, predicate: ["drawer"], descendants: true, isSignal: true }], ngImport: i0, template: "<ng-template #drawer>\n <section class=\"drawer\" role=\"dialog\" aria-modal=\"false\" [attr.aria-labelledby]=\"titleId\">\n <header class=\"header\">\n <div class=\"heading\">\n <h2 [id]=\"titleId\">{{ 'nh-assistant.panel.title' | translate }}</h2>\n </div>\n <div class=\"header-actions\">\n @if (store.enabled()) {\n @if (push.state() !== 'unavailable') {\n <button\n class=\"icon-button notification-button\"\n type=\"button\"\n [class.active]=\"push.state() === 'on'\"\n [class.off]=\"!push.settings()?.pushEnabled\"\n [class.blocked]=\"push.state() === 'blocked'\"\n [disabled]=\"push.busy()\"\n [attr.aria-pressed]=\"push.settings()?.pushEnabled === true\"\n [attr.aria-label]=\"notificationsLabel() | translate\"\n [attr.title]=\"('nh-assistant.preferences.notifications-state.' + push.state() | translate) + ' \u00B7 ' + (notificationsLabel() | translate)\"\n (click)=\"toggleNotifications()\">\n <nh-assistant-icon name=\"bell\" />\n </button>\n }\n <button\n class=\"icon-button\"\n type=\"button\"\n [class.active]=\"showConversations()\"\n [attr.aria-expanded]=\"showConversations()\"\n [attr.aria-label]=\"(showConversations() ? 'nh-assistant.panel.hide-conversations' : 'nh-assistant.panel.show-conversations') | translate\"\n [attr.title]=\"(showConversations() ? 'nh-assistant.panel.hide-conversations' : 'nh-assistant.panel.show-conversations') | translate\"\n (click)=\"toggleConversations()\">\n <nh-assistant-icon name=\"list\" />\n </button>\n <button\n class=\"icon-button\"\n type=\"button\"\n [class.active]=\"showPreferences()\"\n [attr.aria-expanded]=\"showPreferences()\"\n [attr.aria-label]=\"'nh-assistant.panel.open-preferences' | translate\"\n [attr.title]=\"'nh-assistant.panel.open-preferences' | translate\"\n (click)=\"togglePreferences()\">\n <nh-assistant-icon name=\"settings\" />\n </button>\n @if (adminRoute && store.canAdminister()) {\n <a\n class=\"icon-button\"\n [routerLink]=\"adminRoute\"\n [attr.aria-label]=\"'nh-assistant.panel.open-admin' | translate\"\n [attr.title]=\"'nh-assistant.panel.open-admin' | translate\"\n (click)=\"panel.close()\">\n <nh-assistant-icon name=\"admin\" />\n </a>\n }\n <button\n class=\"icon-button\"\n type=\"button\"\n [attr.aria-label]=\"'nh-assistant.panel.new-conversation' | translate\"\n [attr.title]=\"'nh-assistant.panel.new-conversation' | translate\"\n (click)=\"newConversation()\">\n <nh-assistant-icon name=\"plus\" />\n </button>\n }\n <button\n class=\"icon-button\"\n type=\"button\"\n [attr.aria-label]=\"'nh-assistant.panel.close' | translate\"\n [attr.title]=\"'nh-assistant.panel.close' | translate\"\n (click)=\"panel.close()\">\n <nh-assistant-icon name=\"close\" />\n </button>\n </div>\n </header>\n\n @if (store.enabled()) {\n <nh-assistant-activity [items]=\"store.activity()\" (conversationSelect)=\"openConversation($event)\" />\n }\n\n <div class=\"body\">\n @if (store.statusLoading() && !store.enabled()) {\n <div class=\"state\" role=\"status\">\n <p class=\"state-title\">{{ 'nh-assistant.panel.loading' | translate }}</p>\n </div>\n } @else if (!store.enabled()) {\n <div class=\"state\">\n <nh-assistant-icon class=\"state-icon\" name=\"warning\" />\n <p class=\"state-title\">{{ 'nh-assistant.panel.unavailable-title' | translate }}</p>\n <p>{{ 'nh-assistant.panel.unavailable-description' | translate }}</p>\n </div>\n } @else {\n @if (showPreferences()) {\n <nh-assistant-preferences class=\"overlay-view\" (closed)=\"showPreferences.set(false)\" />\n }\n\n @if (showShare()) {\n <nh-assistant-share class=\"overlay-view\" [section]=\"shareSection()\" (closed)=\"showShare.set(false)\" />\n }\n\n @if (showConversations()) {\n <nh-assistant-conversation-list\n class=\"overlay-view\"\n [conversations]=\"store.conversations()\"\n [total]=\"store.conversationsTotal()\"\n [activeConversationId]=\"conversation()?.id ?? null\"\n [loading]=\"store.conversationsLoading()\"\n (conversationSelect)=\"openConversation($event)\"\n (conversationDelete)=\"deleteConversation($event)\"\n (conversationCreate)=\"newConversation()\" />\n }\n\n @if (store.conversationLoading()) {\n <div class=\"state\" role=\"status\">\n <p class=\"state-title\">{{ 'nh-assistant.thread.loading' | translate }}</p>\n </div>\n } @else if (messages().length === 0 && !store.streaming()) {\n <div class=\"state\">\n <nh-assistant-icon class=\"state-icon\" name=\"assistant\" />\n <p class=\"state-title\">{{ 'nh-assistant.panel.empty-title' | translate }}</p>\n <p>{{ 'nh-assistant.panel.empty-description' | translate }}</p>\n </div>\n } @else {\n <nh-assistant-thread\n class=\"thread\"\n [attr.inert]=\"showPreferences() || showShare() || showConversations() ? '' : null\"\n [messages]=\"messages()\"\n [streaming]=\"busy()\"\n [deciding]=\"store.deciding()\"\n [markdown]=\"markdown\"\n [members]=\"store.members()\"\n [currentActorId]=\"conversation()?.currentActorId ?? null\"\n [canDecide]=\"store.canDecide()\"\n [decisionOwner]=\"activeMemberName()\"\n (approvalDecision)=\"decide($event)\" />\n }\n }\n </div>\n\n @if (notificationError() ?? store.error(); as error) {\n <div class=\"error\" role=\"alert\">\n <nh-assistant-icon name=\"warning\" />\n <p>{{ errorKeys() | nhAssistantTranslate: error.code }}</p>\n <button\n class=\"icon-button\"\n type=\"button\"\n [attr.aria-label]=\"'nh-assistant.panel.dismiss-error' | translate\"\n [attr.title]=\"'nh-assistant.panel.dismiss-error' | translate\"\n (click)=\"store.clearError(); notificationError.set(null)\">\n <nh-assistant-icon name=\"close\" />\n </button>\n </div>\n } @else if (store.notice(); as notice) {\n <div class=\"turn-notice\" role=\"status\">\n <nh-assistant-icon name=\"warning\" />\n <p>{{ noticeKeys() | nhAssistantTranslate: notice.code }}</p>\n <button\n class=\"icon-button\"\n type=\"button\"\n [attr.aria-label]=\"'nh-assistant.panel.dismiss-error' | translate\"\n [attr.title]=\"'nh-assistant.panel.dismiss-error' | translate\"\n (click)=\"store.clearNotice()\">\n <nh-assistant-icon name=\"close\" />\n </button>\n </div>\n }\n\n @if (store.enabled() && !showPreferences() && !showShare()) {\n <footer class=\"footer\" (focusin)=\"refreshPageContext()\">\n @if (closed()) {\n <p class=\"notice\">{{ 'nh-assistant.panel.conversation-closed' | translate }}</p>\n }\n @if (store.collaboration() || store.pageContext()) {\n <div class=\"conversation-actions\">\n @if (store.collaboration()) {\n @if (!conversation() || store.isOwner()) {\n <button class=\"icon-button\" type=\"button\" [disabled]=\"!canShare()\"\n [attr.aria-label]=\"'nh-assistant.panel.share' | translate\"\n [attr.title]=\"'nh-assistant.panel.share' | translate\"\n [attr.aria-expanded]=\"showShare() && shareSection() === 'link'\"\n (click)=\"toggleShare('link')\">\n <nh-assistant-icon name=\"link\" />\n </button>\n }\n <button class=\"icon-button\" type=\"button\" [disabled]=\"!canShare()\"\n [class.active]=\"shared()\"\n [attr.aria-label]=\"(store.isOwner() || !conversation() ? 'nh-assistant.panel.add-members' : 'nh-assistant.panel.members') | translate\"\n [attr.title]=\"(store.isOwner() || !conversation() ? 'nh-assistant.panel.add-members' : 'nh-assistant.panel.members') | translate\"\n [attr.aria-expanded]=\"showShare() && shareSection() === 'members'\"\n (click)=\"toggleShare('members')\">\n <nh-assistant-icon name=\"users\" />\n </button>\n }\n @if (store.pageContext(); as context) {\n <button\n class=\"icon-button page-context-button\"\n [class.active]=\"!store.pageContextExcluded()\"\n type=\"button\"\n [attr.aria-pressed]=\"!store.pageContextExcluded()\"\n [attr.aria-label]=\"(store.pageContextExcluded() ? 'nh-assistant.page-context.include' : 'nh-assistant.page-context.exclude') | translate: { page: describeContext(context) }\"\n [attr.title]=\"(store.pageContextExcluded() ? 'nh-assistant.page-context.include' : 'nh-assistant.page-context.exclude') | translate: { page: describeContext(context) }\"\n (click)=\"store.setPageContextExcluded(!store.pageContextExcluded())\">\n <nh-assistant-icon name=\"page\" />\n </button>\n }\n </div>\n }\n @if (store.queuedMessages().length > 0) {\n <section class=\"message-queue\" [attr.aria-label]=\"'nh-assistant.queue.title' | translate: { count: store.queuedMessages().length }\">\n <div class=\"queue-heading\">\n <span aria-live=\"polite\">{{ 'nh-assistant.queue.title' | translate: { count: store.queuedMessages().length } }}</span>\n @if (store.queuePaused()) {\n <button type=\"button\" class=\"queue-resume\" [disabled]=\"editingQueuedId() !== null\" (click)=\"store.resumeQueue()\">\n {{ 'nh-assistant.queue.resume' | translate }}\n </button>\n }\n </div>\n <ol class=\"queue-items\">\n @for (item of store.queuedMessages(); track item.id) {\n <li class=\"queue-item\" [class.failed]=\"item.state === 'failed'\">\n @if (editingQueuedId() === item.id && item.state !== 'sending') {\n <div class=\"queue-edit\">\n <textarea rows=\"2\" [value]=\"queuedDraft()\" (input)=\"changeQueuedDraft($event)\"\n [attr.aria-label]=\"'nh-assistant.queue.edit' | translate\"></textarea>\n <div class=\"queue-buttons\">\n <button type=\"button\" class=\"icon-button\" [disabled]=\"!validQueuedDraft()\"\n [attr.aria-label]=\"'nh-assistant.queue.save' | translate\" [attr.title]=\"'nh-assistant.queue.save' | translate\"\n (click)=\"saveQueuedMessage(item.id)\"><nh-assistant-icon name=\"check\" /></button>\n <button type=\"button\" class=\"icon-button\" [attr.aria-label]=\"'nh-assistant.queue.cancel-edit' | translate\"\n [attr.title]=\"'nh-assistant.queue.cancel-edit' | translate\"\n (click)=\"cancelQueueEdit()\"><nh-assistant-icon name=\"close\" /></button>\n </div>\n </div>\n } @else {\n <div class=\"queue-message\">\n <p [title]=\"item.text\">{{ item.text }}</p>\n @if (item.state !== 'queued') {\n <span class=\"queue-state\">{{ 'nh-assistant.queue.state.' + item.state | translate }}</span>\n }\n </div>\n <div class=\"queue-buttons\">\n @if (store.canSteer() && item.state === 'queued') {\n <button type=\"button\" class=\"queue-steer\" [disabled]=\"editingQueuedId() !== null\"\n [attr.title]=\"'nh-assistant.queue.steer-hint' | translate\"\n (click)=\"store.steerQueuedMessage(item.id)\">{{ 'nh-assistant.queue.steer' | translate }}</button>\n }\n <button type=\"button\" class=\"icon-button\" [disabled]=\"item.state === 'sending'\"\n [attr.aria-label]=\"'nh-assistant.queue.edit' | translate\" [attr.title]=\"'nh-assistant.queue.edit' | translate\"\n (click)=\"editQueuedMessage(item.id, item.text)\"><nh-assistant-icon name=\"edit\" /></button>\n <button type=\"button\" class=\"icon-button\" [disabled]=\"item.state === 'sending'\"\n [attr.aria-label]=\"'nh-assistant.queue.remove' | translate\" [attr.title]=\"'nh-assistant.queue.remove' | translate\"\n (click)=\"store.removeQueuedMessage(item.id)\"><nh-assistant-icon name=\"close\" /></button>\n </div>\n }\n </li>\n }\n </ol>\n </section>\n }\n <nh-assistant-composer\n [disabled]=\"closed()\"\n [sendDisabled]=\"composerDisabled()\"\n [busy]=\"busy()\"\n [queueWhileBusy]=\"true\"\n [status]=\"composerStatus()\"\n [statusActor]=\"activeMemberName()\"\n [canStop]=\"canStop()\"\n [maxLength]=\"store.limits()?.maxMessageChars ?? null\"\n [restore]=\"store.restoredDraft()\"\n (restored)=\"store.consumeRestoredDraft()\"\n (send)=\"send($event)\"\n (cancel)=\"cancel()\">\n <nh-assistant-agent-picker\n nhAssistantComposerControls\n [compact]=\"true\"\n [agents]=\"store.agents()\"\n [selectedAgentId]=\"store.selectedAgentId()\"\n (agentChange)=\"store.selectAgent($event)\" />\n </nh-assistant-composer>\n </footer>\n }\n </section>\n</ng-template>\n", styles: [":host{--nha-font: var(--nh-assistant-font, inherit);--nha-background: var(--nh-assistant-background, #ffffff);--nha-surface: var(--nh-assistant-surface, #f5f7fb);--nha-surface-strong: var(--nh-assistant-surface-strong, #eceff6);--nha-text: var(--nh-assistant-text, #080c1d);--nha-text-muted: var(--nh-assistant-text-muted, #5b6482);--nha-border: var(--nh-assistant-border, #dce0ec);--nha-accent: var(--nh-assistant-accent, #022962);--nha-accent-contrast: var(--nh-assistant-accent-contrast, #ffffff);--nha-highlight: var(--nh-assistant-highlight, #c84f00);--nha-user-bubble: var(--nh-assistant-user-bubble, #022962);--nha-user-text: var(--nh-assistant-user-text, #ffffff);--nha-success: var(--nh-assistant-success, #247d4e);--nha-success-soft: var(--nh-assistant-success-soft, #e6f5ec);--nha-warning: var(--nh-assistant-warning, #8a5a00);--nha-warning-soft: var(--nh-assistant-warning-soft, #fff3d9);--nha-danger: var(--nh-assistant-danger, #b92e52);--nha-danger-soft: var(--nh-assistant-danger-soft, #ffe9ef);--nha-focus: var(--nh-assistant-focus, #ff6700);--nha-shadow: var(--nh-assistant-shadow, 0 16px 36px rgb(2 41 98 / .16));--nha-radius: var(--nh-assistant-radius, 16px);--nha-radius-control: var(--nh-assistant-radius-control, 12px);--nha-mono: var(--nh-assistant-font-mono, ui-monospace, \"Cascadia Code\", Consolas, monospace)}@media(prefers-color-scheme:dark){:host{--nha-background: var(--nh-assistant-background, #0b0e22);--nha-surface: var(--nh-assistant-surface, #11152d);--nha-surface-strong: var(--nh-assistant-surface-strong, #181d3b);--nha-text: var(--nh-assistant-text, #ffffff);--nha-text-muted: var(--nh-assistant-text-muted, #b8bed8);--nha-border: var(--nh-assistant-border, #2b3155);--nha-accent: var(--nh-assistant-accent, #0f4087);--nha-accent-contrast: var(--nh-assistant-accent-contrast, #ffffff);--nha-highlight: var(--nh-assistant-highlight, #ff6700);--nha-user-bubble: var(--nh-assistant-user-bubble, #022962);--nha-user-text: var(--nh-assistant-user-text, #ffffff);--nha-success: var(--nh-assistant-success, #67c58f);--nha-success-soft: var(--nh-assistant-success-soft, #102d24);--nha-warning: var(--nh-assistant-warning, #ffbf5b);--nha-warning-soft: var(--nh-assistant-warning-soft, #342818);--nha-danger: var(--nh-assistant-danger, #ff6d8a);--nha-danger-soft: var(--nh-assistant-danger-soft, #351b2a);--nha-shadow: var(--nh-assistant-shadow, 0 16px 36px rgb(0 0 0 / .32))}}.drawer{--nha-font: var(--nh-assistant-font, inherit);--nha-background: var(--nh-assistant-background, #ffffff);--nha-surface: var(--nh-assistant-surface, #f5f7fb);--nha-surface-strong: var(--nh-assistant-surface-strong, #eceff6);--nha-text: var(--nh-assistant-text, #080c1d);--nha-text-muted: var(--nh-assistant-text-muted, #5b6482);--nha-border: var(--nh-assistant-border, #dce0ec);--nha-accent: var(--nh-assistant-accent, #022962);--nha-accent-contrast: var(--nh-assistant-accent-contrast, #ffffff);--nha-highlight: var(--nh-assistant-highlight, #c84f00);--nha-user-bubble: var(--nh-assistant-user-bubble, #022962);--nha-user-text: var(--nh-assistant-user-text, #ffffff);--nha-success: var(--nh-assistant-success, #247d4e);--nha-success-soft: var(--nh-assistant-success-soft, #e6f5ec);--nha-warning: var(--nh-assistant-warning, #8a5a00);--nha-warning-soft: var(--nh-assistant-warning-soft, #fff3d9);--nha-danger: var(--nh-assistant-danger, #b92e52);--nha-danger-soft: var(--nh-assistant-danger-soft, #ffe9ef);--nha-focus: var(--nh-assistant-focus, #ff6700);--nha-shadow: var(--nh-assistant-shadow, 0 16px 36px rgb(2 41 98 / .16));--nha-radius: var(--nh-assistant-radius, 16px);--nha-radius-control: var(--nh-assistant-radius-control, 12px);--nha-mono: var(--nh-assistant-font-mono, ui-monospace, \"Cascadia Code\", Consolas, monospace)}@media(prefers-color-scheme:dark){.drawer{--nha-background: var(--nh-assistant-background, #0b0e22);--nha-surface: var(--nh-assistant-surface, #11152d);--nha-surface-strong: var(--nh-assistant-surface-strong, #181d3b);--nha-text: var(--nh-assistant-text, #ffffff);--nha-text-muted: var(--nh-assistant-text-muted, #b8bed8);--nha-border: var(--nh-assistant-border, #2b3155);--nha-accent: var(--nh-assistant-accent, #0f4087);--nha-accent-contrast: var(--nh-assistant-accent-contrast, #ffffff);--nha-highlight: var(--nh-assistant-highlight, #ff6700);--nha-user-bubble: var(--nh-assistant-user-bubble, #022962);--nha-user-text: var(--nh-assistant-user-text, #ffffff);--nha-success: var(--nh-assistant-success, #67c58f);--nha-success-soft: var(--nh-assistant-success-soft, #102d24);--nha-warning: var(--nh-assistant-warning, #ffbf5b);--nha-warning-soft: var(--nh-assistant-warning-soft, #342818);--nha-danger: var(--nh-assistant-danger, #ff6d8a);--nha-danger-soft: var(--nh-assistant-danger-soft, #351b2a);--nha-shadow: var(--nh-assistant-shadow, 0 16px 36px rgb(0 0 0 / .32))}}:host{display:contents}.drawer{position:relative;display:flex;flex-direction:column;box-sizing:border-box;width:100%;height:100%;border-left:1px solid var(--nha-border);color:var(--nha-text);background:var(--nha-background);box-shadow:var(--nha-shadow);font-family:var(--nha-font);font-size:14px}.drawer *,.drawer *:before,.drawer *:after{box-sizing:border-box}.header{display:grid;grid-template-columns:minmax(0,1fr) auto;align-items:center;gap:6px 12px;border-bottom:1px solid var(--nha-border);padding:12px 12px 12px 16px}.heading{display:contents}h2{grid-row:1;min-width:0;margin:0;overflow:hidden;font-size:16px;font-weight:750;letter-spacing:-.01em;text-overflow:ellipsis;white-space:nowrap}.header-actions{display:flex;flex:none;grid-column:2;grid-row:1;gap:2px;min-width:0}.header-actions .icon-button{width:32px;height:32px}.icon-button{display:inline-flex;align-items:center;justify-content:center;width:36px;height:36px;padding:0;border:1px solid transparent;border-radius:var(--nha-radius-control);color:var(--nha-text-muted);background:transparent;cursor:pointer;text-decoration:none}.icon-button:focus-visible{outline:3px solid color-mix(in srgb,var(--nha-focus) 80%,transparent);outline-offset:2px}.icon-button:hover:not(:disabled){color:var(--nha-text);background:var(--nha-surface-strong)}.icon-button:disabled{cursor:not-allowed;opacity:.5}.icon-button.active{color:var(--nha-highlight);background:var(--nha-surface-strong)}.body{position:relative;display:flex;flex:1;flex-direction:column;min-height:0;background:var(--nha-background)}.thread{flex:1;min-height:0}.overlay-view{position:absolute;z-index:1;inset:0;border-bottom:1px solid var(--nha-border);background:var(--nha-background)}.state{display:flex;flex:1;flex-direction:column;align-items:center;justify-content:center;gap:4px;padding:24px;color:var(--nha-text-muted);text-align:center}.state p{max-width:32ch;margin:0;font-size:13px}.state-icon{margin-bottom:8px;color:var(--nha-highlight);font-size:28px}.state .state-title{color:var(--nha-text);font-size:15px;font-weight:700}.error{display:flex;align-items:center;gap:8px;margin:0 12px 8px;border:1px solid var(--nha-danger);border-radius:var(--nha-radius-control);padding:4px 4px 4px 12px;color:var(--nha-danger);background:var(--nha-danger-soft)}.error p{flex:1;margin:0;color:var(--nha-text);font-size:13px}.turn-notice{display:flex;align-items:center;gap:8px;margin:0 12px 8px;border:1px solid var(--nha-warning);border-radius:var(--nha-radius-control);padding:4px 4px 4px 12px;color:var(--nha-warning);background:var(--nha-warning-soft)}.turn-notice p{flex:1;margin:0;color:var(--nha-text);font-size:13px}.footer{padding:12px 16px 14px}.conversation-actions{display:flex;align-items:center;gap:4px;margin:0 -4px 6px}.page-context-button{margin-left:auto}.message-queue{margin-bottom:10px;border:1px solid var(--nha-border);border-radius:var(--nha-radius-control);background:var(--nha-background);overflow:hidden;font-size:12px}.queue-heading{display:flex;justify-content:space-between;align-items:center;gap:8px;padding:8px 10px;color:var(--nha-text-muted)}.queue-items{max-height:180px;overflow-y:auto;margin:0;padding:0;list-style:none}.queue-item{display:flex;align-items:center;gap:8px;border-top:1px solid var(--nha-border);padding:6px 8px 6px 10px}.queue-item.failed{border-left:2px solid var(--nha-danger)}.queue-message{flex:1;min-width:0}.queue-message p{display:-webkit-box;-webkit-line-clamp:2;-webkit-box-orient:vertical;overflow:hidden;overflow-wrap:anywhere;margin:0}.queue-state{color:var(--nha-text-muted);font-size:11px}.queue-buttons{display:flex;flex-shrink:0;align-items:center;gap:2px}.queue-buttons .icon-button{width:28px;height:30px}.queue-resume,.queue-steer{border:0;border-radius:6px;padding:6px;color:var(--nha-highlight);background:transparent;font:inherit;cursor:pointer}.queue-resume:hover,.queue-steer:hover{background:var(--nha-surface)}.queue-resume:focus-visible,.queue-steer:focus-visible{outline:2px solid var(--nha-focus)}.queue-resume:disabled,.queue-steer:disabled{cursor:not-allowed;opacity:.5}.queue-edit{width:100%}.queue-edit textarea{box-sizing:border-box;width:100%;border:1px solid var(--nha-border);border-radius:6px;padding:8px;color:var(--nha-text);background:var(--nha-surface);font:inherit;resize:vertical}.queue-edit .queue-buttons{justify-content:flex-end}.notification-button{position:relative}.notification-button.off:after{content:\"\";position:absolute;width:18px;height:2px;border-radius:1px;background:currentColor;transform:rotate(-45deg)}.notification-button.blocked{color:var(--nha-warning)}@media(max-width:359px){.header{gap:6px;padding-inline:12px}.header-actions .icon-button{width:28px;height:32px}}.notice{margin:0 0 8px;color:var(--nha-text-muted);font-size:12px}\n"], dependencies: [{ kind: "directive", type: RouterLink, selector: "[routerLink]", inputs: ["target", "queryParams", "fragment", "queryParamsHandling", "state", "info", "relativeTo", "preserveFragment", "skipLocationChange", "replaceUrl", "routerLink"] }, { kind: "component", type: NhAssistantIconComponent, selector: "nh-assistant-icon", inputs: ["name"] }, { kind: "component", type: NhAssistantActivityComponent, selector: "nh-assistant-activity", inputs: ["items"], outputs: ["conversationSelect"] }, { kind: "component", type: NhAssistantAgentPickerComponent, selector: "nh-assistant-agent-picker", inputs: ["agents", "selectedAgentId", "disabled", "compact"], outputs: ["agentChange"] }, { kind: "component", type: NhAssistantComposerComponent, selector: "nh-assistant-composer", inputs: ["disabled", "sendDisabled", "busy", "queueWhileBusy", "status", "statusActor", "canStop", "maxLength", "restore"], outputs: ["send", "cancel", "restored"] }, { kind: "component", type: NhAssistantConversationListComponent, selector: "nh-assistant-conversation-list", inputs: ["conversations", "total", "activeConversationId", "loading", "disabled"], outputs: ["conversationSelect", "conversationDelete", "conversationCreate"] }, { kind: "component", type: NhAssistantPreferencesComponent, selector: "nh-assistant-preferences", outputs: ["closed", "saved"] }, { kind: "component", type: NhAssistantShareComponent, selector: "nh-assistant-share", inputs: ["section"], outputs: ["closed"] }, { kind: "component", type: NhAssistantThreadComponent, selector: "nh-assistant-thread", inputs: ["messages", "streaming", "deciding", "markdown", "members", "currentActorId", "canDecide", "decisionOwner"], outputs: ["approvalDecision"] }, { kind: "pipe", type: TranslatePipe, name: "translate" }, { kind: "pipe", type: NhAssistantTranslatePipe, name: "nhAssistantTranslate" }], changeDetection: i0.ChangeDetectionStrategy.OnPush }); }
|
|
5044
5308
|
}
|
|
5045
5309
|
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.33", ngImport: i0, type: NhAssistantPanelComponent, decorators: [{
|
|
5046
5310
|
type: Component,
|
|
@@ -5056,7 +5320,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.33", ngImpo
|
|
|
5056
5320
|
NhAssistantPreferencesComponent,
|
|
5057
5321
|
NhAssistantShareComponent,
|
|
5058
5322
|
NhAssistantThreadComponent
|
|
5059
|
-
], changeDetection: ChangeDetectionStrategy.OnPush, template: "<ng-template #drawer>\n <section class=\"drawer\" role=\"dialog\" aria-modal=\"false\" [attr.aria-labelledby]=\"titleId\">\n <header class=\"header\">\n <div class=\"heading\">\n <h2 [id]=\"titleId\">{{ 'nh-assistant.panel.title' | translate }}</h2>\n @if (store.enabled()) {\n <nh-assistant-agent-picker\n [agents]=\"store.agents()\"\n [selectedAgentId]=\"store.selectedAgentId()\"\n (agentChange)=\"store.selectAgent($event)\" />\n }\n </div>\n <div class=\"header-actions\">\n @if (store.enabled()) {\n @if (canShare()) {\n <button\n class=\"icon-button\"\n type=\"button\"\n [class.active]=\"showShare() || shared()\"\n [attr.aria-expanded]=\"showShare()\"\n [attr.aria-label]=\"(store.isOwner() ? 'nh-assistant.panel.share' : 'nh-assistant.panel.members') | translate\"\n [attr.title]=\"(store.isOwner() ? 'nh-assistant.panel.share' : 'nh-assistant.panel.members') | translate\"\n (click)=\"toggleShare()\">\n <nh-assistant-icon name=\"users\" />\n </button>\n }\n <button\n class=\"icon-button\"\n type=\"button\"\n [class.active]=\"showConversations()\"\n [attr.aria-expanded]=\"showConversations()\"\n [attr.aria-label]=\"(showConversations() ? 'nh-assistant.panel.hide-conversations' : 'nh-assistant.panel.show-conversations') | translate\"\n [attr.title]=\"(showConversations() ? 'nh-assistant.panel.hide-conversations' : 'nh-assistant.panel.show-conversations') | translate\"\n (click)=\"toggleConversations()\">\n <nh-assistant-icon name=\"list\" />\n </button>\n <button\n class=\"icon-button\"\n type=\"button\"\n [class.active]=\"showPreferences()\"\n [attr.aria-expanded]=\"showPreferences()\"\n [attr.aria-label]=\"'nh-assistant.panel.open-preferences' | translate\"\n [attr.title]=\"'nh-assistant.panel.open-preferences' | translate\"\n (click)=\"togglePreferences()\">\n <nh-assistant-icon name=\"settings\" />\n </button>\n @if (adminRoute && store.canAdminister()) {\n <a\n class=\"icon-button\"\n [routerLink]=\"adminRoute\"\n [attr.aria-label]=\"'nh-assistant.panel.open-admin' | translate\"\n [attr.title]=\"'nh-assistant.panel.open-admin' | translate\"\n (click)=\"panel.close()\">\n <nh-assistant-icon name=\"admin\" />\n </a>\n }\n <button\n class=\"icon-button\"\n type=\"button\"\n [attr.aria-label]=\"'nh-assistant.panel.new-conversation' | translate\"\n [attr.title]=\"'nh-assistant.panel.new-conversation' | translate\"\n (click)=\"newConversation()\">\n <nh-assistant-icon name=\"plus\" />\n </button>\n }\n <button\n class=\"icon-button\"\n type=\"button\"\n [attr.aria-label]=\"'nh-assistant.panel.close' | translate\"\n [attr.title]=\"'nh-assistant.panel.close' | translate\"\n (click)=\"panel.close()\">\n <nh-assistant-icon name=\"close\" />\n </button>\n </div>\n </header>\n\n @if (store.enabled()) {\n <nh-assistant-activity [items]=\"store.activity()\" (conversationSelect)=\"openConversation($event)\" />\n }\n\n <div class=\"body\">\n @if (store.statusLoading() && !store.enabled()) {\n <div class=\"state\" role=\"status\">\n <p class=\"state-title\">{{ 'nh-assistant.panel.loading' | translate }}</p>\n </div>\n } @else if (!store.enabled()) {\n <div class=\"state\">\n <nh-assistant-icon class=\"state-icon\" name=\"warning\" />\n <p class=\"state-title\">{{ 'nh-assistant.panel.unavailable-title' | translate }}</p>\n <p>{{ 'nh-assistant.panel.unavailable-description' | translate }}</p>\n </div>\n } @else {\n @if (showPreferences()) {\n <nh-assistant-preferences class=\"overlay-view\" (closed)=\"showPreferences.set(false)\" />\n }\n\n @if (showShare()) {\n <nh-assistant-share class=\"overlay-view\" (closed)=\"showShare.set(false)\" />\n }\n\n @if (showConversations()) {\n <nh-assistant-conversation-list\n class=\"overlay-view\"\n [conversations]=\"store.conversations()\"\n [total]=\"store.conversationsTotal()\"\n [activeConversationId]=\"conversation()?.id ?? null\"\n [loading]=\"store.conversationsLoading()\"\n (conversationSelect)=\"openConversation($event)\"\n (conversationDelete)=\"deleteConversation($event)\"\n (conversationCreate)=\"newConversation()\" />\n }\n\n @if (store.conversationLoading()) {\n <div class=\"state\" role=\"status\">\n <p class=\"state-title\">{{ 'nh-assistant.thread.loading' | translate }}</p>\n </div>\n } @else if (messages().length === 0 && !store.streaming()) {\n <div class=\"state\">\n <nh-assistant-icon class=\"state-icon\" name=\"assistant\" />\n <p class=\"state-title\">{{ 'nh-assistant.panel.empty-title' | translate }}</p>\n <p>{{ 'nh-assistant.panel.empty-description' | translate }}</p>\n </div>\n } @else {\n <nh-assistant-thread\n class=\"thread\"\n [messages]=\"messages()\"\n [streaming]=\"busy()\"\n [deciding]=\"store.deciding()\"\n [markdown]=\"markdown\"\n [members]=\"store.members()\"\n [currentActorId]=\"conversation()?.currentActorId ?? null\"\n [canDecide]=\"store.canDecide()\"\n [decisionOwner]=\"activeMemberName()\"\n (approvalDecision)=\"decide($event)\" />\n }\n }\n </div>\n\n @if (store.error(); as error) {\n <div class=\"error\" role=\"alert\">\n <nh-assistant-icon name=\"warning\" />\n <p>{{ errorKeys() | nhAssistantTranslate: error.code }}</p>\n <button\n class=\"icon-button\"\n type=\"button\"\n [attr.aria-label]=\"'nh-assistant.panel.dismiss-error' | translate\"\n [attr.title]=\"'nh-assistant.panel.dismiss-error' | translate\"\n (click)=\"store.clearError()\">\n <nh-assistant-icon name=\"close\" />\n </button>\n </div>\n } @else if (store.notice(); as notice) {\n <div class=\"turn-notice\" role=\"status\">\n <nh-assistant-icon name=\"warning\" />\n <p>{{ noticeKeys() | nhAssistantTranslate: notice.code }}</p>\n <button\n class=\"icon-button\"\n type=\"button\"\n [attr.aria-label]=\"'nh-assistant.panel.dismiss-error' | translate\"\n [attr.title]=\"'nh-assistant.panel.dismiss-error' | translate\"\n (click)=\"store.clearNotice()\">\n <nh-assistant-icon name=\"close\" />\n </button>\n </div>\n }\n\n @if (store.enabled() && !showPreferences() && !showShare()) {\n <footer class=\"footer\" (focusin)=\"refreshPageContext()\">\n @if (closed()) {\n <p class=\"notice\">{{ 'nh-assistant.panel.conversation-closed' | translate }}</p>\n }\n @if (store.pageContext(); as context) {\n <div class=\"context-chip\" [class.excluded]=\"store.pageContextExcluded()\" [attr.title]=\"context.route\">\n <nh-assistant-icon name=\"page\" />\n <span class=\"context-text\">\n {{ (store.pageContextExcluded() ? 'nh-assistant.page-context.excluded' : 'nh-assistant.page-context.included') | translate: { page: describeContext(context) } }}\n </span>\n <button\n class=\"icon-button small\"\n type=\"button\"\n [attr.aria-pressed]=\"store.pageContextExcluded()\"\n [attr.aria-label]=\"(store.pageContextExcluded() ? 'nh-assistant.page-context.include' : 'nh-assistant.page-context.exclude') | translate: { page: describeContext(context) }\"\n [attr.title]=\"(store.pageContextExcluded() ? 'nh-assistant.page-context.include' : 'nh-assistant.page-context.exclude') | translate: { page: describeContext(context) }\"\n (click)=\"store.setPageContextExcluded(!store.pageContextExcluded())\">\n <nh-assistant-icon [name]=\"store.pageContextExcluded() ? 'plus' : 'x'\" />\n </button>\n </div>\n }\n <nh-assistant-composer\n [disabled]=\"closed()\"\n [sendDisabled]=\"composerDisabled()\"\n [busy]=\"busy()\"\n [status]=\"composerStatus()\"\n [statusActor]=\"activeMemberName()\"\n [canStop]=\"canStop()\"\n [maxLength]=\"store.limits()?.maxMessageChars ?? null\"\n [restore]=\"store.restoredDraft()\"\n (restored)=\"store.consumeRestoredDraft()\"\n (send)=\"send($event)\"\n (cancel)=\"cancel()\" />\n </footer>\n }\n </section>\n</ng-template>\n", styles: [":host{--nha-font: var(--nh-assistant-font, inherit);--nha-background: var(--nh-assistant-background, #ffffff);--nha-surface: var(--nh-assistant-surface, #f5f7fb);--nha-surface-strong: var(--nh-assistant-surface-strong, #eceff6);--nha-text: var(--nh-assistant-text, #080c1d);--nha-text-muted: var(--nh-assistant-text-muted, #5b6482);--nha-border: var(--nh-assistant-border, #dce0ec);--nha-accent: var(--nh-assistant-accent, #022962);--nha-accent-contrast: var(--nh-assistant-accent-contrast, #ffffff);--nha-highlight: var(--nh-assistant-highlight, #c84f00);--nha-user-bubble: var(--nh-assistant-user-bubble, #022962);--nha-user-text: var(--nh-assistant-user-text, #ffffff);--nha-success: var(--nh-assistant-success, #247d4e);--nha-success-soft: var(--nh-assistant-success-soft, #e6f5ec);--nha-warning: var(--nh-assistant-warning, #8a5a00);--nha-warning-soft: var(--nh-assistant-warning-soft, #fff3d9);--nha-danger: var(--nh-assistant-danger, #b92e52);--nha-danger-soft: var(--nh-assistant-danger-soft, #ffe9ef);--nha-focus: var(--nh-assistant-focus, #ff6700);--nha-shadow: var(--nh-assistant-shadow, 0 16px 36px rgb(2 41 98 / .16));--nha-radius: var(--nh-assistant-radius, 16px);--nha-radius-control: var(--nh-assistant-radius-control, 12px);--nha-mono: var(--nh-assistant-font-mono, ui-monospace, \"Cascadia Code\", Consolas, monospace)}@media(prefers-color-scheme:dark){:host{--nha-background: var(--nh-assistant-background, #0b0e22);--nha-surface: var(--nh-assistant-surface, #11152d);--nha-surface-strong: var(--nh-assistant-surface-strong, #181d3b);--nha-text: var(--nh-assistant-text, #ffffff);--nha-text-muted: var(--nh-assistant-text-muted, #b8bed8);--nha-border: var(--nh-assistant-border, #2b3155);--nha-accent: var(--nh-assistant-accent, #0f4087);--nha-accent-contrast: var(--nh-assistant-accent-contrast, #ffffff);--nha-highlight: var(--nh-assistant-highlight, #ff6700);--nha-user-bubble: var(--nh-assistant-user-bubble, #022962);--nha-user-text: var(--nh-assistant-user-text, #ffffff);--nha-success: var(--nh-assistant-success, #67c58f);--nha-success-soft: var(--nh-assistant-success-soft, #102d24);--nha-warning: var(--nh-assistant-warning, #ffbf5b);--nha-warning-soft: var(--nh-assistant-warning-soft, #342818);--nha-danger: var(--nh-assistant-danger, #ff6d8a);--nha-danger-soft: var(--nh-assistant-danger-soft, #351b2a);--nha-shadow: var(--nh-assistant-shadow, 0 16px 36px rgb(0 0 0 / .32))}}.drawer{--nha-font: var(--nh-assistant-font, inherit);--nha-background: var(--nh-assistant-background, #ffffff);--nha-surface: var(--nh-assistant-surface, #f5f7fb);--nha-surface-strong: var(--nh-assistant-surface-strong, #eceff6);--nha-text: var(--nh-assistant-text, #080c1d);--nha-text-muted: var(--nh-assistant-text-muted, #5b6482);--nha-border: var(--nh-assistant-border, #dce0ec);--nha-accent: var(--nh-assistant-accent, #022962);--nha-accent-contrast: var(--nh-assistant-accent-contrast, #ffffff);--nha-highlight: var(--nh-assistant-highlight, #c84f00);--nha-user-bubble: var(--nh-assistant-user-bubble, #022962);--nha-user-text: var(--nh-assistant-user-text, #ffffff);--nha-success: var(--nh-assistant-success, #247d4e);--nha-success-soft: var(--nh-assistant-success-soft, #e6f5ec);--nha-warning: var(--nh-assistant-warning, #8a5a00);--nha-warning-soft: var(--nh-assistant-warning-soft, #fff3d9);--nha-danger: var(--nh-assistant-danger, #b92e52);--nha-danger-soft: var(--nh-assistant-danger-soft, #ffe9ef);--nha-focus: var(--nh-assistant-focus, #ff6700);--nha-shadow: var(--nh-assistant-shadow, 0 16px 36px rgb(2 41 98 / .16));--nha-radius: var(--nh-assistant-radius, 16px);--nha-radius-control: var(--nh-assistant-radius-control, 12px);--nha-mono: var(--nh-assistant-font-mono, ui-monospace, \"Cascadia Code\", Consolas, monospace)}@media(prefers-color-scheme:dark){.drawer{--nha-background: var(--nh-assistant-background, #0b0e22);--nha-surface: var(--nh-assistant-surface, #11152d);--nha-surface-strong: var(--nh-assistant-surface-strong, #181d3b);--nha-text: var(--nh-assistant-text, #ffffff);--nha-text-muted: var(--nh-assistant-text-muted, #b8bed8);--nha-border: var(--nh-assistant-border, #2b3155);--nha-accent: var(--nh-assistant-accent, #0f4087);--nha-accent-contrast: var(--nh-assistant-accent-contrast, #ffffff);--nha-highlight: var(--nh-assistant-highlight, #ff6700);--nha-user-bubble: var(--nh-assistant-user-bubble, #022962);--nha-user-text: var(--nh-assistant-user-text, #ffffff);--nha-success: var(--nh-assistant-success, #67c58f);--nha-success-soft: var(--nh-assistant-success-soft, #102d24);--nha-warning: var(--nh-assistant-warning, #ffbf5b);--nha-warning-soft: var(--nh-assistant-warning-soft, #342818);--nha-danger: var(--nh-assistant-danger, #ff6d8a);--nha-danger-soft: var(--nh-assistant-danger-soft, #351b2a);--nha-shadow: var(--nh-assistant-shadow, 0 16px 36px rgb(0 0 0 / .32))}}:host{display:contents}.drawer{position:relative;display:flex;flex-direction:column;box-sizing:border-box;width:100%;height:100%;border-left:1px solid var(--nha-border);color:var(--nha-text);background:var(--nha-background);box-shadow:var(--nha-shadow);font-family:var(--nha-font);font-size:14px}.drawer *,.drawer *:before,.drawer *:after{box-sizing:border-box}.header{display:grid;grid-template-columns:minmax(0,1fr) auto;align-items:center;gap:6px 12px;border-bottom:1px solid var(--nha-border);padding:12px 12px 12px 16px}.heading{display:contents}nh-assistant-agent-picker{grid-column:1/-1;grid-row:2}h2{grid-row:1;min-width:0;margin:0;overflow:hidden;font-size:16px;font-weight:750;letter-spacing:-.01em;text-overflow:ellipsis;white-space:nowrap}.header-actions{display:flex;flex:none;grid-column:2;grid-row:1;gap:4px}.icon-button{display:inline-flex;align-items:center;justify-content:center;width:36px;height:36px;padding:0;border:1px solid transparent;border-radius:var(--nha-radius-control);color:var(--nha-text-muted);background:transparent;cursor:pointer;text-decoration:none}.icon-button:focus-visible{outline:3px solid color-mix(in srgb,var(--nha-focus) 80%,transparent);outline-offset:2px}.icon-button:hover:not(:disabled){color:var(--nha-text);background:var(--nha-surface-strong)}.icon-button:disabled{cursor:not-allowed;opacity:.5}.icon-button.active{color:var(--nha-highlight);background:var(--nha-surface-strong)}.body{position:relative;display:flex;flex:1;flex-direction:column;min-height:0;background:var(--nha-background)}.thread{flex:1;min-height:0}.overlay-view{position:absolute;z-index:1;inset:0;border-bottom:1px solid var(--nha-border);background:var(--nha-background)}.state{display:flex;flex:1;flex-direction:column;align-items:center;justify-content:center;gap:4px;padding:24px;color:var(--nha-text-muted);text-align:center}.state p{max-width:32ch;margin:0;font-size:13px}.state-icon{margin-bottom:8px;color:var(--nha-highlight);font-size:28px}.state .state-title{color:var(--nha-text);font-size:15px;font-weight:700}.error{display:flex;align-items:center;gap:8px;margin:0 12px 8px;border:1px solid var(--nha-danger);border-radius:var(--nha-radius-control);padding:4px 4px 4px 12px;color:var(--nha-danger);background:var(--nha-danger-soft)}.error p{flex:1;margin:0;color:var(--nha-text);font-size:13px}.turn-notice{display:flex;align-items:center;gap:8px;margin:0 12px 8px;border:1px solid var(--nha-warning);border-radius:var(--nha-radius-control);padding:4px 4px 4px 12px;color:var(--nha-warning);background:var(--nha-warning-soft)}.turn-notice p{flex:1;margin:0;color:var(--nha-text);font-size:13px}.footer{border-top:1px solid var(--nha-border);padding:12px 16px 14px}.context-chip{display:flex;align-items:center;gap:6px;max-width:100%;margin:0 0 8px;border:1px solid var(--nha-border);border-radius:999px;padding:2px 2px 2px 10px;width:fit-content;color:var(--nha-text-muted);background:var(--nha-surface);font-size:12px}.context-chip.excluded .context-text{text-decoration:line-through}.context-text{min-width:0;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}.icon-button.small{flex:none;width:26px;height:26px;border-radius:999px}.notice{margin:0 0 8px;color:var(--nha-text-muted);font-size:12px}\n"] }]
|
|
5323
|
+
], changeDetection: ChangeDetectionStrategy.OnPush, template: "<ng-template #drawer>\n <section class=\"drawer\" role=\"dialog\" aria-modal=\"false\" [attr.aria-labelledby]=\"titleId\">\n <header class=\"header\">\n <div class=\"heading\">\n <h2 [id]=\"titleId\">{{ 'nh-assistant.panel.title' | translate }}</h2>\n </div>\n <div class=\"header-actions\">\n @if (store.enabled()) {\n @if (push.state() !== 'unavailable') {\n <button\n class=\"icon-button notification-button\"\n type=\"button\"\n [class.active]=\"push.state() === 'on'\"\n [class.off]=\"!push.settings()?.pushEnabled\"\n [class.blocked]=\"push.state() === 'blocked'\"\n [disabled]=\"push.busy()\"\n [attr.aria-pressed]=\"push.settings()?.pushEnabled === true\"\n [attr.aria-label]=\"notificationsLabel() | translate\"\n [attr.title]=\"('nh-assistant.preferences.notifications-state.' + push.state() | translate) + ' \u00B7 ' + (notificationsLabel() | translate)\"\n (click)=\"toggleNotifications()\">\n <nh-assistant-icon name=\"bell\" />\n </button>\n }\n <button\n class=\"icon-button\"\n type=\"button\"\n [class.active]=\"showConversations()\"\n [attr.aria-expanded]=\"showConversations()\"\n [attr.aria-label]=\"(showConversations() ? 'nh-assistant.panel.hide-conversations' : 'nh-assistant.panel.show-conversations') | translate\"\n [attr.title]=\"(showConversations() ? 'nh-assistant.panel.hide-conversations' : 'nh-assistant.panel.show-conversations') | translate\"\n (click)=\"toggleConversations()\">\n <nh-assistant-icon name=\"list\" />\n </button>\n <button\n class=\"icon-button\"\n type=\"button\"\n [class.active]=\"showPreferences()\"\n [attr.aria-expanded]=\"showPreferences()\"\n [attr.aria-label]=\"'nh-assistant.panel.open-preferences' | translate\"\n [attr.title]=\"'nh-assistant.panel.open-preferences' | translate\"\n (click)=\"togglePreferences()\">\n <nh-assistant-icon name=\"settings\" />\n </button>\n @if (adminRoute && store.canAdminister()) {\n <a\n class=\"icon-button\"\n [routerLink]=\"adminRoute\"\n [attr.aria-label]=\"'nh-assistant.panel.open-admin' | translate\"\n [attr.title]=\"'nh-assistant.panel.open-admin' | translate\"\n (click)=\"panel.close()\">\n <nh-assistant-icon name=\"admin\" />\n </a>\n }\n <button\n class=\"icon-button\"\n type=\"button\"\n [attr.aria-label]=\"'nh-assistant.panel.new-conversation' | translate\"\n [attr.title]=\"'nh-assistant.panel.new-conversation' | translate\"\n (click)=\"newConversation()\">\n <nh-assistant-icon name=\"plus\" />\n </button>\n }\n <button\n class=\"icon-button\"\n type=\"button\"\n [attr.aria-label]=\"'nh-assistant.panel.close' | translate\"\n [attr.title]=\"'nh-assistant.panel.close' | translate\"\n (click)=\"panel.close()\">\n <nh-assistant-icon name=\"close\" />\n </button>\n </div>\n </header>\n\n @if (store.enabled()) {\n <nh-assistant-activity [items]=\"store.activity()\" (conversationSelect)=\"openConversation($event)\" />\n }\n\n <div class=\"body\">\n @if (store.statusLoading() && !store.enabled()) {\n <div class=\"state\" role=\"status\">\n <p class=\"state-title\">{{ 'nh-assistant.panel.loading' | translate }}</p>\n </div>\n } @else if (!store.enabled()) {\n <div class=\"state\">\n <nh-assistant-icon class=\"state-icon\" name=\"warning\" />\n <p class=\"state-title\">{{ 'nh-assistant.panel.unavailable-title' | translate }}</p>\n <p>{{ 'nh-assistant.panel.unavailable-description' | translate }}</p>\n </div>\n } @else {\n @if (showPreferences()) {\n <nh-assistant-preferences class=\"overlay-view\" (closed)=\"showPreferences.set(false)\" />\n }\n\n @if (showShare()) {\n <nh-assistant-share class=\"overlay-view\" [section]=\"shareSection()\" (closed)=\"showShare.set(false)\" />\n }\n\n @if (showConversations()) {\n <nh-assistant-conversation-list\n class=\"overlay-view\"\n [conversations]=\"store.conversations()\"\n [total]=\"store.conversationsTotal()\"\n [activeConversationId]=\"conversation()?.id ?? null\"\n [loading]=\"store.conversationsLoading()\"\n (conversationSelect)=\"openConversation($event)\"\n (conversationDelete)=\"deleteConversation($event)\"\n (conversationCreate)=\"newConversation()\" />\n }\n\n @if (store.conversationLoading()) {\n <div class=\"state\" role=\"status\">\n <p class=\"state-title\">{{ 'nh-assistant.thread.loading' | translate }}</p>\n </div>\n } @else if (messages().length === 0 && !store.streaming()) {\n <div class=\"state\">\n <nh-assistant-icon class=\"state-icon\" name=\"assistant\" />\n <p class=\"state-title\">{{ 'nh-assistant.panel.empty-title' | translate }}</p>\n <p>{{ 'nh-assistant.panel.empty-description' | translate }}</p>\n </div>\n } @else {\n <nh-assistant-thread\n class=\"thread\"\n [attr.inert]=\"showPreferences() || showShare() || showConversations() ? '' : null\"\n [messages]=\"messages()\"\n [streaming]=\"busy()\"\n [deciding]=\"store.deciding()\"\n [markdown]=\"markdown\"\n [members]=\"store.members()\"\n [currentActorId]=\"conversation()?.currentActorId ?? null\"\n [canDecide]=\"store.canDecide()\"\n [decisionOwner]=\"activeMemberName()\"\n (approvalDecision)=\"decide($event)\" />\n }\n }\n </div>\n\n @if (notificationError() ?? store.error(); as error) {\n <div class=\"error\" role=\"alert\">\n <nh-assistant-icon name=\"warning\" />\n <p>{{ errorKeys() | nhAssistantTranslate: error.code }}</p>\n <button\n class=\"icon-button\"\n type=\"button\"\n [attr.aria-label]=\"'nh-assistant.panel.dismiss-error' | translate\"\n [attr.title]=\"'nh-assistant.panel.dismiss-error' | translate\"\n (click)=\"store.clearError(); notificationError.set(null)\">\n <nh-assistant-icon name=\"close\" />\n </button>\n </div>\n } @else if (store.notice(); as notice) {\n <div class=\"turn-notice\" role=\"status\">\n <nh-assistant-icon name=\"warning\" />\n <p>{{ noticeKeys() | nhAssistantTranslate: notice.code }}</p>\n <button\n class=\"icon-button\"\n type=\"button\"\n [attr.aria-label]=\"'nh-assistant.panel.dismiss-error' | translate\"\n [attr.title]=\"'nh-assistant.panel.dismiss-error' | translate\"\n (click)=\"store.clearNotice()\">\n <nh-assistant-icon name=\"close\" />\n </button>\n </div>\n }\n\n @if (store.enabled() && !showPreferences() && !showShare()) {\n <footer class=\"footer\" (focusin)=\"refreshPageContext()\">\n @if (closed()) {\n <p class=\"notice\">{{ 'nh-assistant.panel.conversation-closed' | translate }}</p>\n }\n @if (store.collaboration() || store.pageContext()) {\n <div class=\"conversation-actions\">\n @if (store.collaboration()) {\n @if (!conversation() || store.isOwner()) {\n <button class=\"icon-button\" type=\"button\" [disabled]=\"!canShare()\"\n [attr.aria-label]=\"'nh-assistant.panel.share' | translate\"\n [attr.title]=\"'nh-assistant.panel.share' | translate\"\n [attr.aria-expanded]=\"showShare() && shareSection() === 'link'\"\n (click)=\"toggleShare('link')\">\n <nh-assistant-icon name=\"link\" />\n </button>\n }\n <button class=\"icon-button\" type=\"button\" [disabled]=\"!canShare()\"\n [class.active]=\"shared()\"\n [attr.aria-label]=\"(store.isOwner() || !conversation() ? 'nh-assistant.panel.add-members' : 'nh-assistant.panel.members') | translate\"\n [attr.title]=\"(store.isOwner() || !conversation() ? 'nh-assistant.panel.add-members' : 'nh-assistant.panel.members') | translate\"\n [attr.aria-expanded]=\"showShare() && shareSection() === 'members'\"\n (click)=\"toggleShare('members')\">\n <nh-assistant-icon name=\"users\" />\n </button>\n }\n @if (store.pageContext(); as context) {\n <button\n class=\"icon-button page-context-button\"\n [class.active]=\"!store.pageContextExcluded()\"\n type=\"button\"\n [attr.aria-pressed]=\"!store.pageContextExcluded()\"\n [attr.aria-label]=\"(store.pageContextExcluded() ? 'nh-assistant.page-context.include' : 'nh-assistant.page-context.exclude') | translate: { page: describeContext(context) }\"\n [attr.title]=\"(store.pageContextExcluded() ? 'nh-assistant.page-context.include' : 'nh-assistant.page-context.exclude') | translate: { page: describeContext(context) }\"\n (click)=\"store.setPageContextExcluded(!store.pageContextExcluded())\">\n <nh-assistant-icon name=\"page\" />\n </button>\n }\n </div>\n }\n @if (store.queuedMessages().length > 0) {\n <section class=\"message-queue\" [attr.aria-label]=\"'nh-assistant.queue.title' | translate: { count: store.queuedMessages().length }\">\n <div class=\"queue-heading\">\n <span aria-live=\"polite\">{{ 'nh-assistant.queue.title' | translate: { count: store.queuedMessages().length } }}</span>\n @if (store.queuePaused()) {\n <button type=\"button\" class=\"queue-resume\" [disabled]=\"editingQueuedId() !== null\" (click)=\"store.resumeQueue()\">\n {{ 'nh-assistant.queue.resume' | translate }}\n </button>\n }\n </div>\n <ol class=\"queue-items\">\n @for (item of store.queuedMessages(); track item.id) {\n <li class=\"queue-item\" [class.failed]=\"item.state === 'failed'\">\n @if (editingQueuedId() === item.id && item.state !== 'sending') {\n <div class=\"queue-edit\">\n <textarea rows=\"2\" [value]=\"queuedDraft()\" (input)=\"changeQueuedDraft($event)\"\n [attr.aria-label]=\"'nh-assistant.queue.edit' | translate\"></textarea>\n <div class=\"queue-buttons\">\n <button type=\"button\" class=\"icon-button\" [disabled]=\"!validQueuedDraft()\"\n [attr.aria-label]=\"'nh-assistant.queue.save' | translate\" [attr.title]=\"'nh-assistant.queue.save' | translate\"\n (click)=\"saveQueuedMessage(item.id)\"><nh-assistant-icon name=\"check\" /></button>\n <button type=\"button\" class=\"icon-button\" [attr.aria-label]=\"'nh-assistant.queue.cancel-edit' | translate\"\n [attr.title]=\"'nh-assistant.queue.cancel-edit' | translate\"\n (click)=\"cancelQueueEdit()\"><nh-assistant-icon name=\"close\" /></button>\n </div>\n </div>\n } @else {\n <div class=\"queue-message\">\n <p [title]=\"item.text\">{{ item.text }}</p>\n @if (item.state !== 'queued') {\n <span class=\"queue-state\">{{ 'nh-assistant.queue.state.' + item.state | translate }}</span>\n }\n </div>\n <div class=\"queue-buttons\">\n @if (store.canSteer() && item.state === 'queued') {\n <button type=\"button\" class=\"queue-steer\" [disabled]=\"editingQueuedId() !== null\"\n [attr.title]=\"'nh-assistant.queue.steer-hint' | translate\"\n (click)=\"store.steerQueuedMessage(item.id)\">{{ 'nh-assistant.queue.steer' | translate }}</button>\n }\n <button type=\"button\" class=\"icon-button\" [disabled]=\"item.state === 'sending'\"\n [attr.aria-label]=\"'nh-assistant.queue.edit' | translate\" [attr.title]=\"'nh-assistant.queue.edit' | translate\"\n (click)=\"editQueuedMessage(item.id, item.text)\"><nh-assistant-icon name=\"edit\" /></button>\n <button type=\"button\" class=\"icon-button\" [disabled]=\"item.state === 'sending'\"\n [attr.aria-label]=\"'nh-assistant.queue.remove' | translate\" [attr.title]=\"'nh-assistant.queue.remove' | translate\"\n (click)=\"store.removeQueuedMessage(item.id)\"><nh-assistant-icon name=\"close\" /></button>\n </div>\n }\n </li>\n }\n </ol>\n </section>\n }\n <nh-assistant-composer\n [disabled]=\"closed()\"\n [sendDisabled]=\"composerDisabled()\"\n [busy]=\"busy()\"\n [queueWhileBusy]=\"true\"\n [status]=\"composerStatus()\"\n [statusActor]=\"activeMemberName()\"\n [canStop]=\"canStop()\"\n [maxLength]=\"store.limits()?.maxMessageChars ?? null\"\n [restore]=\"store.restoredDraft()\"\n (restored)=\"store.consumeRestoredDraft()\"\n (send)=\"send($event)\"\n (cancel)=\"cancel()\">\n <nh-assistant-agent-picker\n nhAssistantComposerControls\n [compact]=\"true\"\n [agents]=\"store.agents()\"\n [selectedAgentId]=\"store.selectedAgentId()\"\n (agentChange)=\"store.selectAgent($event)\" />\n </nh-assistant-composer>\n </footer>\n }\n </section>\n</ng-template>\n", styles: [":host{--nha-font: var(--nh-assistant-font, inherit);--nha-background: var(--nh-assistant-background, #ffffff);--nha-surface: var(--nh-assistant-surface, #f5f7fb);--nha-surface-strong: var(--nh-assistant-surface-strong, #eceff6);--nha-text: var(--nh-assistant-text, #080c1d);--nha-text-muted: var(--nh-assistant-text-muted, #5b6482);--nha-border: var(--nh-assistant-border, #dce0ec);--nha-accent: var(--nh-assistant-accent, #022962);--nha-accent-contrast: var(--nh-assistant-accent-contrast, #ffffff);--nha-highlight: var(--nh-assistant-highlight, #c84f00);--nha-user-bubble: var(--nh-assistant-user-bubble, #022962);--nha-user-text: var(--nh-assistant-user-text, #ffffff);--nha-success: var(--nh-assistant-success, #247d4e);--nha-success-soft: var(--nh-assistant-success-soft, #e6f5ec);--nha-warning: var(--nh-assistant-warning, #8a5a00);--nha-warning-soft: var(--nh-assistant-warning-soft, #fff3d9);--nha-danger: var(--nh-assistant-danger, #b92e52);--nha-danger-soft: var(--nh-assistant-danger-soft, #ffe9ef);--nha-focus: var(--nh-assistant-focus, #ff6700);--nha-shadow: var(--nh-assistant-shadow, 0 16px 36px rgb(2 41 98 / .16));--nha-radius: var(--nh-assistant-radius, 16px);--nha-radius-control: var(--nh-assistant-radius-control, 12px);--nha-mono: var(--nh-assistant-font-mono, ui-monospace, \"Cascadia Code\", Consolas, monospace)}@media(prefers-color-scheme:dark){:host{--nha-background: var(--nh-assistant-background, #0b0e22);--nha-surface: var(--nh-assistant-surface, #11152d);--nha-surface-strong: var(--nh-assistant-surface-strong, #181d3b);--nha-text: var(--nh-assistant-text, #ffffff);--nha-text-muted: var(--nh-assistant-text-muted, #b8bed8);--nha-border: var(--nh-assistant-border, #2b3155);--nha-accent: var(--nh-assistant-accent, #0f4087);--nha-accent-contrast: var(--nh-assistant-accent-contrast, #ffffff);--nha-highlight: var(--nh-assistant-highlight, #ff6700);--nha-user-bubble: var(--nh-assistant-user-bubble, #022962);--nha-user-text: var(--nh-assistant-user-text, #ffffff);--nha-success: var(--nh-assistant-success, #67c58f);--nha-success-soft: var(--nh-assistant-success-soft, #102d24);--nha-warning: var(--nh-assistant-warning, #ffbf5b);--nha-warning-soft: var(--nh-assistant-warning-soft, #342818);--nha-danger: var(--nh-assistant-danger, #ff6d8a);--nha-danger-soft: var(--nh-assistant-danger-soft, #351b2a);--nha-shadow: var(--nh-assistant-shadow, 0 16px 36px rgb(0 0 0 / .32))}}.drawer{--nha-font: var(--nh-assistant-font, inherit);--nha-background: var(--nh-assistant-background, #ffffff);--nha-surface: var(--nh-assistant-surface, #f5f7fb);--nha-surface-strong: var(--nh-assistant-surface-strong, #eceff6);--nha-text: var(--nh-assistant-text, #080c1d);--nha-text-muted: var(--nh-assistant-text-muted, #5b6482);--nha-border: var(--nh-assistant-border, #dce0ec);--nha-accent: var(--nh-assistant-accent, #022962);--nha-accent-contrast: var(--nh-assistant-accent-contrast, #ffffff);--nha-highlight: var(--nh-assistant-highlight, #c84f00);--nha-user-bubble: var(--nh-assistant-user-bubble, #022962);--nha-user-text: var(--nh-assistant-user-text, #ffffff);--nha-success: var(--nh-assistant-success, #247d4e);--nha-success-soft: var(--nh-assistant-success-soft, #e6f5ec);--nha-warning: var(--nh-assistant-warning, #8a5a00);--nha-warning-soft: var(--nh-assistant-warning-soft, #fff3d9);--nha-danger: var(--nh-assistant-danger, #b92e52);--nha-danger-soft: var(--nh-assistant-danger-soft, #ffe9ef);--nha-focus: var(--nh-assistant-focus, #ff6700);--nha-shadow: var(--nh-assistant-shadow, 0 16px 36px rgb(2 41 98 / .16));--nha-radius: var(--nh-assistant-radius, 16px);--nha-radius-control: var(--nh-assistant-radius-control, 12px);--nha-mono: var(--nh-assistant-font-mono, ui-monospace, \"Cascadia Code\", Consolas, monospace)}@media(prefers-color-scheme:dark){.drawer{--nha-background: var(--nh-assistant-background, #0b0e22);--nha-surface: var(--nh-assistant-surface, #11152d);--nha-surface-strong: var(--nh-assistant-surface-strong, #181d3b);--nha-text: var(--nh-assistant-text, #ffffff);--nha-text-muted: var(--nh-assistant-text-muted, #b8bed8);--nha-border: var(--nh-assistant-border, #2b3155);--nha-accent: var(--nh-assistant-accent, #0f4087);--nha-accent-contrast: var(--nh-assistant-accent-contrast, #ffffff);--nha-highlight: var(--nh-assistant-highlight, #ff6700);--nha-user-bubble: var(--nh-assistant-user-bubble, #022962);--nha-user-text: var(--nh-assistant-user-text, #ffffff);--nha-success: var(--nh-assistant-success, #67c58f);--nha-success-soft: var(--nh-assistant-success-soft, #102d24);--nha-warning: var(--nh-assistant-warning, #ffbf5b);--nha-warning-soft: var(--nh-assistant-warning-soft, #342818);--nha-danger: var(--nh-assistant-danger, #ff6d8a);--nha-danger-soft: var(--nh-assistant-danger-soft, #351b2a);--nha-shadow: var(--nh-assistant-shadow, 0 16px 36px rgb(0 0 0 / .32))}}:host{display:contents}.drawer{position:relative;display:flex;flex-direction:column;box-sizing:border-box;width:100%;height:100%;border-left:1px solid var(--nha-border);color:var(--nha-text);background:var(--nha-background);box-shadow:var(--nha-shadow);font-family:var(--nha-font);font-size:14px}.drawer *,.drawer *:before,.drawer *:after{box-sizing:border-box}.header{display:grid;grid-template-columns:minmax(0,1fr) auto;align-items:center;gap:6px 12px;border-bottom:1px solid var(--nha-border);padding:12px 12px 12px 16px}.heading{display:contents}h2{grid-row:1;min-width:0;margin:0;overflow:hidden;font-size:16px;font-weight:750;letter-spacing:-.01em;text-overflow:ellipsis;white-space:nowrap}.header-actions{display:flex;flex:none;grid-column:2;grid-row:1;gap:2px;min-width:0}.header-actions .icon-button{width:32px;height:32px}.icon-button{display:inline-flex;align-items:center;justify-content:center;width:36px;height:36px;padding:0;border:1px solid transparent;border-radius:var(--nha-radius-control);color:var(--nha-text-muted);background:transparent;cursor:pointer;text-decoration:none}.icon-button:focus-visible{outline:3px solid color-mix(in srgb,var(--nha-focus) 80%,transparent);outline-offset:2px}.icon-button:hover:not(:disabled){color:var(--nha-text);background:var(--nha-surface-strong)}.icon-button:disabled{cursor:not-allowed;opacity:.5}.icon-button.active{color:var(--nha-highlight);background:var(--nha-surface-strong)}.body{position:relative;display:flex;flex:1;flex-direction:column;min-height:0;background:var(--nha-background)}.thread{flex:1;min-height:0}.overlay-view{position:absolute;z-index:1;inset:0;border-bottom:1px solid var(--nha-border);background:var(--nha-background)}.state{display:flex;flex:1;flex-direction:column;align-items:center;justify-content:center;gap:4px;padding:24px;color:var(--nha-text-muted);text-align:center}.state p{max-width:32ch;margin:0;font-size:13px}.state-icon{margin-bottom:8px;color:var(--nha-highlight);font-size:28px}.state .state-title{color:var(--nha-text);font-size:15px;font-weight:700}.error{display:flex;align-items:center;gap:8px;margin:0 12px 8px;border:1px solid var(--nha-danger);border-radius:var(--nha-radius-control);padding:4px 4px 4px 12px;color:var(--nha-danger);background:var(--nha-danger-soft)}.error p{flex:1;margin:0;color:var(--nha-text);font-size:13px}.turn-notice{display:flex;align-items:center;gap:8px;margin:0 12px 8px;border:1px solid var(--nha-warning);border-radius:var(--nha-radius-control);padding:4px 4px 4px 12px;color:var(--nha-warning);background:var(--nha-warning-soft)}.turn-notice p{flex:1;margin:0;color:var(--nha-text);font-size:13px}.footer{padding:12px 16px 14px}.conversation-actions{display:flex;align-items:center;gap:4px;margin:0 -4px 6px}.page-context-button{margin-left:auto}.message-queue{margin-bottom:10px;border:1px solid var(--nha-border);border-radius:var(--nha-radius-control);background:var(--nha-background);overflow:hidden;font-size:12px}.queue-heading{display:flex;justify-content:space-between;align-items:center;gap:8px;padding:8px 10px;color:var(--nha-text-muted)}.queue-items{max-height:180px;overflow-y:auto;margin:0;padding:0;list-style:none}.queue-item{display:flex;align-items:center;gap:8px;border-top:1px solid var(--nha-border);padding:6px 8px 6px 10px}.queue-item.failed{border-left:2px solid var(--nha-danger)}.queue-message{flex:1;min-width:0}.queue-message p{display:-webkit-box;-webkit-line-clamp:2;-webkit-box-orient:vertical;overflow:hidden;overflow-wrap:anywhere;margin:0}.queue-state{color:var(--nha-text-muted);font-size:11px}.queue-buttons{display:flex;flex-shrink:0;align-items:center;gap:2px}.queue-buttons .icon-button{width:28px;height:30px}.queue-resume,.queue-steer{border:0;border-radius:6px;padding:6px;color:var(--nha-highlight);background:transparent;font:inherit;cursor:pointer}.queue-resume:hover,.queue-steer:hover{background:var(--nha-surface)}.queue-resume:focus-visible,.queue-steer:focus-visible{outline:2px solid var(--nha-focus)}.queue-resume:disabled,.queue-steer:disabled{cursor:not-allowed;opacity:.5}.queue-edit{width:100%}.queue-edit textarea{box-sizing:border-box;width:100%;border:1px solid var(--nha-border);border-radius:6px;padding:8px;color:var(--nha-text);background:var(--nha-surface);font:inherit;resize:vertical}.queue-edit .queue-buttons{justify-content:flex-end}.notification-button{position:relative}.notification-button.off:after{content:\"\";position:absolute;width:18px;height:2px;border-radius:1px;background:currentColor;transform:rotate(-45deg)}.notification-button.blocked{color:var(--nha-warning)}@media(max-width:359px){.header{gap:6px;padding-inline:12px}.header-actions .icon-button{width:28px;height:32px}}.notice{margin:0 0 8px;color:var(--nha-text-muted);font-size:12px}\n"] }]
|
|
5060
5324
|
}], ctorParameters: () => [], propDecorators: { drawer: [{ type: i0.ViewChild, args: ['drawer', { isSignal: true }] }] } });
|
|
5061
5325
|
|
|
5062
5326
|
/** Converts any failure into a user-facing code and translation key, never raw text. */
|