@newheap/platform-ai-chat 0.8.1 → 0.10.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 +185 -3
- package/admin/index.d.ts +85 -4
- package/agent-runs/index.d.ts +384 -0
- package/fesm2022/newheap-platform-ai-chat-admin.mjs +251 -12
- package/fesm2022/newheap-platform-ai-chat-admin.mjs.map +1 -1
- package/fesm2022/newheap-platform-ai-chat-agent-runs.mjs +1029 -0
- package/fesm2022/newheap-platform-ai-chat-agent-runs.mjs.map +1 -0
- package/fesm2022/newheap-platform-ai-chat-testing.mjs +30 -1
- package/fesm2022/newheap-platform-ai-chat-testing.mjs.map +1 -1
- package/fesm2022/newheap-platform-ai-chat.mjs +1837 -80
- package/fesm2022/newheap-platform-ai-chat.mjs.map +1 -1
- package/i18n/en.json +330 -8
- package/i18n/nl.json +330 -8
- package/index.d.ts +1013 -67
- package/package.json +5 -1
- package/testing/index.d.ts +4 -2
|
@@ -0,0 +1,1029 @@
|
|
|
1
|
+
import * as i0 from '@angular/core';
|
|
2
|
+
import { inject, ElementRef, Injector, input, output, signal, computed, DestroyRef, afterNextRender, ChangeDetectionStrategy, Component, viewChild, effect, untracked } from '@angular/core';
|
|
3
|
+
import { TranslatePipe } from '@ngx-translate/core';
|
|
4
|
+
import { NhAssistantAgentRunApiService, ɵnhAssistantErrorKeys as _nhAssistantErrorKeys, NH_ASSISTANT_MAX_PROPOSAL_LOOKUP, ɵtoNhAssistantError as _toNhAssistantError, ɵNhAssistantIconComponent as _NhAssistantIconComponent, NhAssistantProposalFeedbackComponent, ɵNhAssistantTranslatePipe as _NhAssistantTranslatePipe, ɵnhAssistantReloadOnAgentWork as _nhAssistantReloadOnAgentWork, NhAssistantPanelService, NhAssistantStore, NhAssistantApiError } from '@newheap/platform-ai-chat';
|
|
5
|
+
import { DatePipe, DOCUMENT } from '@angular/common';
|
|
6
|
+
import { Subscription, forkJoin } from 'rxjs';
|
|
7
|
+
|
|
8
|
+
/**
|
|
9
|
+
* A list of agent proposals with their decision and execution state. People who may decide see
|
|
10
|
+
* approve and reject on pending proposals and the resolution of an execution with an unknown
|
|
11
|
+
* outcome; the server checks every decision again. With `selectable`, pending proposals can be
|
|
12
|
+
* approved or rejected together. Deciding takes one action. After a rejection the list asks,
|
|
13
|
+
* optionally and above the list, what was wrong; closed proposals keep a low-key action to give or
|
|
14
|
+
* change that feedback later. With `decisionRights` each proposal has its own right, for example
|
|
15
|
+
* from the agent work on a subject, and a pending proposal the viewer may not decide says who does.
|
|
16
|
+
* A proposal that no longer fits, for example because a person already did the work, shows why.
|
|
17
|
+
* With `holdClosedCards`, a list of open proposals keeps such a proposal, or one a newer proposal
|
|
18
|
+
* replaced, as a closed card when it closes while shown, or when an approval is refused because of
|
|
19
|
+
* it, until the person dismisses it. It reads those proposals by id with one lookup, never through
|
|
20
|
+
* their threads.
|
|
21
|
+
*/
|
|
22
|
+
class NhAssistantAgentProposalsComponent {
|
|
23
|
+
constructor() {
|
|
24
|
+
this.api = inject(NhAssistantAgentRunApiService);
|
|
25
|
+
this.host = inject(ElementRef);
|
|
26
|
+
this.injector = inject(Injector);
|
|
27
|
+
this.proposals = input.required(...(ngDevMode ? [{ debugName: "proposals" }] : []));
|
|
28
|
+
/** Whether the caller may decide: an approver of the subjects or the inbox owner. */
|
|
29
|
+
this.canDecide = input(false, ...(ngDevMode ? [{ debugName: "canDecide" }] : []));
|
|
30
|
+
/**
|
|
31
|
+
* The caller's live right per proposal, by approval id, for example from
|
|
32
|
+
* `AgentSubjectWork.openProposals`. A proposal with a right uses it instead of `canDecide`.
|
|
33
|
+
*/
|
|
34
|
+
this.decisionRights = input(null, ...(ngDevMode ? [{ debugName: "decisionRights" }] : []));
|
|
35
|
+
this.selectable = input(false, ...(ngDevMode ? [{ debugName: "selectable" }] : []));
|
|
36
|
+
/**
|
|
37
|
+
* Keeps proposals that close as stale or are replaced while shown as closed cards with their
|
|
38
|
+
* explanation until they are dismissed. For lists of open proposals, which drop a proposal once
|
|
39
|
+
* it closes.
|
|
40
|
+
*/
|
|
41
|
+
this.holdClosedCards = input(false, ...(ngDevMode ? [{ debugName: "holdClosedCards" }] : []));
|
|
42
|
+
/** Emits after a proposal or its feedback changed, so the host reloads its list. */
|
|
43
|
+
this.changed = output();
|
|
44
|
+
this.busy = signal(false, ...(ngDevMode ? [{ debugName: "busy" }] : []));
|
|
45
|
+
this.selected = signal(new Set(), ...(ngDevMode ? [{ debugName: "selected" }] : []));
|
|
46
|
+
this.error = signal(null, ...(ngDevMode ? [{ debugName: "error" }] : []));
|
|
47
|
+
this.errorKeys = computed(() => _nhAssistantErrorKeys(this.error()), ...(ngDevMode ? [{ debugName: "errorKeys" }] : []));
|
|
48
|
+
/** Pending proposals the caller may decide. */
|
|
49
|
+
this.pending = computed(() => this.proposals().filter(proposal => proposal.status === 'pending' && this.mayDecide(proposal)), ...(ngDevMode ? [{ debugName: "pending" }] : []));
|
|
50
|
+
this.allSelected = computed(() => this.pending().length > 0 && this.pending().every(proposal => this.selected().has(proposal.approvalId)), ...(ngDevMode ? [{ debugName: "allSelected" }] : []));
|
|
51
|
+
/** The feedback question. It does not depend on `proposals`, which drop rejected proposals in the inbox. */
|
|
52
|
+
this.feedback = signal(null, ...(ngDevMode ? [{ debugName: "feedback" }] : []));
|
|
53
|
+
/** Proposals that closed as stale while shown, kept until dismissed; newest first. */
|
|
54
|
+
this.held = signal([], ...(ngDevMode ? [{ debugName: "held" }] : []));
|
|
55
|
+
/** The held closed cards first, then the proposals the host gave. */
|
|
56
|
+
this.shown = computed(() => {
|
|
57
|
+
const held = this.held();
|
|
58
|
+
const heldIds = new Set(held.map(proposal => proposal.approvalId));
|
|
59
|
+
return [...held, ...this.proposals().filter(proposal => !heldIds.has(proposal.approvalId))];
|
|
60
|
+
}, ...(ngDevMode ? [{ debugName: "shown" }] : []));
|
|
61
|
+
this.lookups = new Subscription();
|
|
62
|
+
inject(DestroyRef).onDestroy(() => {
|
|
63
|
+
this.subscription?.unsubscribe();
|
|
64
|
+
this.lookups.unsubscribe();
|
|
65
|
+
});
|
|
66
|
+
}
|
|
67
|
+
/**
|
|
68
|
+
* The translation key of a proposal's status: the kind of a stale proposal, "replaced" for a
|
|
69
|
+
* superseded one, otherwise its status.
|
|
70
|
+
*/
|
|
71
|
+
statusKey(proposal) {
|
|
72
|
+
if (proposal.status === 'stale' && proposal.staleKind) {
|
|
73
|
+
return `nh-assistant.approval.stale-kind.${proposal.staleKind}`;
|
|
74
|
+
}
|
|
75
|
+
return isSuperseded(proposal)
|
|
76
|
+
? 'nh-assistant.approval.superseded'
|
|
77
|
+
: `nh-assistant.agent-runs.proposal.status.${proposal.status}`;
|
|
78
|
+
}
|
|
79
|
+
/** True when the newer proposal that replaced this one is in the list. */
|
|
80
|
+
hasSuccessor(proposal) {
|
|
81
|
+
const successor = proposal.supersededByApprovalId;
|
|
82
|
+
return !!successor && this.shown().some(item => item.approvalId === successor);
|
|
83
|
+
}
|
|
84
|
+
/** Moves focus to the newer proposal that replaced this one. */
|
|
85
|
+
showSuccessor(proposal) {
|
|
86
|
+
const card = Array.from(this.host.nativeElement.querySelectorAll('[data-approval-id]'))
|
|
87
|
+
.find(element => element.dataset['approvalId'] === proposal.supersededByApprovalId);
|
|
88
|
+
card?.scrollIntoView({ block: 'nearest' });
|
|
89
|
+
card?.focus();
|
|
90
|
+
}
|
|
91
|
+
/** True for a closed card the list keeps until it is dismissed. */
|
|
92
|
+
isHeld(proposal) {
|
|
93
|
+
return this.held().some(item => item.approvalId === proposal.approvalId);
|
|
94
|
+
}
|
|
95
|
+
/** Removes a closed card. */
|
|
96
|
+
dismiss(proposal) {
|
|
97
|
+
this.held.update(held => held.filter(item => item.approvalId !== proposal.approvalId));
|
|
98
|
+
}
|
|
99
|
+
/**
|
|
100
|
+
* Called by a host of open proposals after a live update replaced `previous` with `next`: keeps
|
|
101
|
+
* the shown pending proposals that left the list because they closed as stale or were replaced.
|
|
102
|
+
*/
|
|
103
|
+
holdClosed(previous, next) {
|
|
104
|
+
const nextIds = new Set(next.map(proposal => proposal.approvalId));
|
|
105
|
+
this.holdStale(previous.filter(proposal => proposal.status === 'pending' && !nextIds.has(proposal.approvalId)));
|
|
106
|
+
}
|
|
107
|
+
/** Whether the caller may decide this proposal: its own right when one was given, otherwise `canDecide`. */
|
|
108
|
+
mayDecide(proposal) {
|
|
109
|
+
const right = this.decisionRights()?.get(proposal.approvalId);
|
|
110
|
+
return right ? right.canDecide : this.canDecide();
|
|
111
|
+
}
|
|
112
|
+
/**
|
|
113
|
+
* Who decides a pending proposal that has a right the caller lacks: another approver when
|
|
114
|
+
* four-eyes keeps out the person who started the work, otherwise an approver.
|
|
115
|
+
*/
|
|
116
|
+
waitingForKey(proposal) {
|
|
117
|
+
const right = this.decisionRights()?.get(proposal.approvalId);
|
|
118
|
+
if (!right || right.canDecide || proposal.status !== 'pending') {
|
|
119
|
+
return null;
|
|
120
|
+
}
|
|
121
|
+
return right.reasonCode === 'assistant-four-eyes-required'
|
|
122
|
+
? 'nh-assistant.approval.waiting-for-other-approver'
|
|
123
|
+
: 'nh-assistant.approval.waiting-for-approver';
|
|
124
|
+
}
|
|
125
|
+
toggle(proposal) {
|
|
126
|
+
const next = new Set(this.selected());
|
|
127
|
+
if (next.has(proposal.approvalId)) {
|
|
128
|
+
next.delete(proposal.approvalId);
|
|
129
|
+
}
|
|
130
|
+
else {
|
|
131
|
+
next.add(proposal.approvalId);
|
|
132
|
+
}
|
|
133
|
+
this.selected.set(next);
|
|
134
|
+
}
|
|
135
|
+
toggleAll() {
|
|
136
|
+
this.selected.set(this.allSelected() ? new Set() : new Set(this.pending().map(proposal => proposal.approvalId)));
|
|
137
|
+
}
|
|
138
|
+
decide(proposal, decision) {
|
|
139
|
+
this.run(this.api.decide(proposal, decision), result => {
|
|
140
|
+
if (decision === 'reject' && result.status === 'rejected' && result.canGiveFeedback === true) {
|
|
141
|
+
this.ask([proposal.approvalId], summaryOf(proposal));
|
|
142
|
+
}
|
|
143
|
+
}, code => {
|
|
144
|
+
if (code === staleCode) {
|
|
145
|
+
// The approval was refused because the proposal no longer fits; show why.
|
|
146
|
+
this.holdStale([proposal]);
|
|
147
|
+
}
|
|
148
|
+
});
|
|
149
|
+
}
|
|
150
|
+
decideSelected(decision) {
|
|
151
|
+
const ids = [...this.selected()];
|
|
152
|
+
if (ids.length === 0) {
|
|
153
|
+
return;
|
|
154
|
+
}
|
|
155
|
+
const proposals = this.proposals();
|
|
156
|
+
this.run(this.api.decideMany(ids, decision), response => {
|
|
157
|
+
this.selected.set(new Set());
|
|
158
|
+
const stale = response.results
|
|
159
|
+
.filter(outcome => !outcome.succeeded && outcome.code === staleCode)
|
|
160
|
+
.map(outcome => outcome.approvalId);
|
|
161
|
+
this.holdStale(proposals.filter(proposal => stale.includes(proposal.approvalId)));
|
|
162
|
+
if (decision !== 'reject') {
|
|
163
|
+
return;
|
|
164
|
+
}
|
|
165
|
+
const rejected = response.results
|
|
166
|
+
.filter(outcome => outcome.succeeded && outcome.status === 'rejected')
|
|
167
|
+
.map(outcome => outcome.approvalId);
|
|
168
|
+
if (rejected.length > 0) {
|
|
169
|
+
const single = rejected.length === 1 ? proposals.find(proposal => proposal.approvalId === rejected[0]) : undefined;
|
|
170
|
+
this.ask(rejected, single ? summaryOf(single) : null);
|
|
171
|
+
}
|
|
172
|
+
});
|
|
173
|
+
}
|
|
174
|
+
resolve(proposal, action) {
|
|
175
|
+
this.run(this.api.resolve(proposal.approvalId, action));
|
|
176
|
+
}
|
|
177
|
+
/** Opens the feedback question in the card of a closed proposal, with the caller's own feedback. */
|
|
178
|
+
giveFeedback(proposal) {
|
|
179
|
+
this.feedback.set({
|
|
180
|
+
approvalIds: [proposal.approvalId],
|
|
181
|
+
initial: proposal.feedback ?? null,
|
|
182
|
+
placement: 'card',
|
|
183
|
+
summary: null,
|
|
184
|
+
saved: false
|
|
185
|
+
});
|
|
186
|
+
}
|
|
187
|
+
/** True while the feedback question for this proposal is open, above the list or in its card. */
|
|
188
|
+
isAsking(proposal) {
|
|
189
|
+
const request = this.feedback();
|
|
190
|
+
return request !== null && !request.saved && request.approvalIds.includes(proposal.approvalId);
|
|
191
|
+
}
|
|
192
|
+
/** True when the card of this proposal shows the feedback question or its thanks. */
|
|
193
|
+
inCard(proposal) {
|
|
194
|
+
const request = this.feedback();
|
|
195
|
+
return request?.placement === 'card' && request.approvalIds[0] === proposal.approvalId;
|
|
196
|
+
}
|
|
197
|
+
/** Keeps the panel, which now thanks the person, and lets the host reload the proposals. */
|
|
198
|
+
onFeedbackSaved() {
|
|
199
|
+
this.feedback.update(request => request ? { ...request, saved: true } : request);
|
|
200
|
+
this.changed.emit();
|
|
201
|
+
}
|
|
202
|
+
/** Closes the question; from a card, focus returns to the card's feedback action. */
|
|
203
|
+
onFeedbackDismissed() {
|
|
204
|
+
const request = this.feedback();
|
|
205
|
+
this.feedback.set(null);
|
|
206
|
+
if (request?.placement !== 'card') {
|
|
207
|
+
return;
|
|
208
|
+
}
|
|
209
|
+
const [approvalId] = request.approvalIds;
|
|
210
|
+
afterNextRender(() => {
|
|
211
|
+
const action = Array.from(this.host.nativeElement.querySelectorAll('[data-feedback-approval]'))
|
|
212
|
+
.find(item => item.dataset['feedbackApproval'] === approvalId);
|
|
213
|
+
action?.focus();
|
|
214
|
+
}, { injector: this.injector });
|
|
215
|
+
}
|
|
216
|
+
ask(approvalIds, summary) {
|
|
217
|
+
this.feedback.set({ approvalIds, initial: null, placement: 'prompt', summary, saved: false });
|
|
218
|
+
}
|
|
219
|
+
/**
|
|
220
|
+
* Reads `proposals` again by id and keeps those that closed as stale or were replaced as closed
|
|
221
|
+
* cards, with their kind and explanation or their successor.
|
|
222
|
+
*/
|
|
223
|
+
holdStale(proposals) {
|
|
224
|
+
if (!this.holdClosedCards() || proposals.length === 0) {
|
|
225
|
+
return;
|
|
226
|
+
}
|
|
227
|
+
// The proposals are read by id, never through their threads.
|
|
228
|
+
const ids = [...new Set(proposals.map(proposal => proposal.approvalId))];
|
|
229
|
+
const batches = [];
|
|
230
|
+
for (let start = 0; start < ids.length; start += NH_ASSISTANT_MAX_PROPOSAL_LOOKUP) {
|
|
231
|
+
batches.push(ids.slice(start, start + NH_ASSISTANT_MAX_PROPOSAL_LOOKUP));
|
|
232
|
+
}
|
|
233
|
+
this.lookups.add(forkJoin(batches.map(batch => this.api.lookupProposals(batch))).subscribe({
|
|
234
|
+
next: lookups => {
|
|
235
|
+
const closed = lookups
|
|
236
|
+
.flatMap(lookup => lookup.items)
|
|
237
|
+
.map(item => item.proposal)
|
|
238
|
+
.filter(proposal => proposal.status === 'stale' || isSuperseded(proposal));
|
|
239
|
+
if (closed.length === 0) {
|
|
240
|
+
return;
|
|
241
|
+
}
|
|
242
|
+
this.held.update(held => [
|
|
243
|
+
...closed,
|
|
244
|
+
...held.filter(item => !closed.some(proposal => proposal.approvalId === item.approvalId))
|
|
245
|
+
]);
|
|
246
|
+
},
|
|
247
|
+
// Without the lookup the proposal just leaves the list, as it did before.
|
|
248
|
+
error: () => undefined
|
|
249
|
+
}));
|
|
250
|
+
}
|
|
251
|
+
run(request, done, failed) {
|
|
252
|
+
this.busy.set(true);
|
|
253
|
+
this.error.set(null);
|
|
254
|
+
if (this.feedback()?.saved) {
|
|
255
|
+
this.feedback.set(null);
|
|
256
|
+
}
|
|
257
|
+
this.subscription?.unsubscribe();
|
|
258
|
+
this.subscription = request.subscribe({
|
|
259
|
+
next: result => {
|
|
260
|
+
this.busy.set(false);
|
|
261
|
+
done?.(result);
|
|
262
|
+
this.changed.emit();
|
|
263
|
+
},
|
|
264
|
+
error: failure => {
|
|
265
|
+
this.busy.set(false);
|
|
266
|
+
const error = _toNhAssistantError(failure);
|
|
267
|
+
this.error.set(error);
|
|
268
|
+
failed?.(error.code);
|
|
269
|
+
this.changed.emit();
|
|
270
|
+
}
|
|
271
|
+
});
|
|
272
|
+
}
|
|
273
|
+
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.3.33", ngImport: i0, type: NhAssistantAgentProposalsComponent, deps: [], target: i0.ɵɵFactoryTarget.Component }); }
|
|
274
|
+
static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "20.3.33", type: NhAssistantAgentProposalsComponent, isStandalone: true, selector: "nh-assistant-agent-proposals", inputs: { proposals: { classPropertyName: "proposals", publicName: "proposals", isSignal: true, isRequired: true, transformFunction: null }, canDecide: { classPropertyName: "canDecide", publicName: "canDecide", isSignal: true, isRequired: false, transformFunction: null }, decisionRights: { classPropertyName: "decisionRights", publicName: "decisionRights", isSignal: true, isRequired: false, transformFunction: null }, selectable: { classPropertyName: "selectable", publicName: "selectable", isSignal: true, isRequired: false, transformFunction: null }, holdClosedCards: { classPropertyName: "holdClosedCards", publicName: "holdClosedCards", isSignal: true, isRequired: false, transformFunction: null } }, outputs: { changed: "changed" }, ngImport: i0, template: "<div class=\"proposal-list\">\n @if (error(); as failure) {\n <p class=\"message error\" role=\"alert\"><nh-assistant-icon name=\"warning\" />{{ errorKeys() | nhAssistantTranslate: failure.code }}</p>\n }\n\n @if (feedback(); as request) {\n @if (request.placement === 'prompt') {\n <div class=\"feedback-prompt\">\n @if (request.summary && !request.saved) {\n <p class=\"muted\">{{ 'nh-assistant.agent-runs.proposal.rejected-one' | translate: { summary: request.summary } }}</p>\n }\n <nh-assistant-proposal-feedback\n [approvalIds]=\"request.approvalIds\"\n [initial]=\"request.initial\"\n (saved)=\"onFeedbackSaved()\"\n (dismissed)=\"onFeedbackDismissed()\" />\n </div>\n }\n }\n\n @if (selectable() && pending().length > 0) {\n <div class=\"toolbar\">\n <label class=\"select\">\n <input type=\"checkbox\" [checked]=\"allSelected()\" [disabled]=\"busy()\" (change)=\"toggleAll()\" />\n {{ 'nh-assistant.agent-runs.inbox.select-all' | translate }}\n </label>\n <button class=\"primary\" type=\"button\" [disabled]=\"busy() || selected().size === 0\" (click)=\"decideSelected('approve')\">\n <nh-assistant-icon name=\"check\" />{{ 'nh-assistant.agent-runs.inbox.approve-selected' | translate }}\n </button>\n <button class=\"secondary\" type=\"button\" [disabled]=\"busy() || selected().size === 0\" (click)=\"decideSelected('reject')\">\n <nh-assistant-icon name=\"x\" />{{ 'nh-assistant.agent-runs.inbox.reject-selected' | translate }}\n </button>\n </div>\n }\n\n @if (shown().length > 0) {\n <ul class=\"cards\" [attr.aria-busy]=\"busy()\">\n @for (proposal of shown(); track proposal.approvalId) {\n <li\n class=\"card\"\n tabindex=\"-1\"\n [attr.data-approval-id]=\"proposal.approvalId\"\n [class.selected]=\"selected().has(proposal.approvalId)\"\n [class.closed]=\"isHeld(proposal)\">\n <div class=\"card-header\">\n @if (selectable() && proposal.status === 'pending' && mayDecide(proposal)) {\n <input\n type=\"checkbox\"\n [checked]=\"selected().has(proposal.approvalId)\"\n [disabled]=\"busy()\"\n [attr.aria-label]=\"'nh-assistant.agent-runs.inbox.select' | translate\"\n (change)=\"toggle(proposal)\" />\n }\n <strong>{{ proposal.subjectDisplayName ?? proposal.subjectId }}</strong>\n <span class=\"muted\">{{ proposal.presentation?.toolDisplayName ?? proposal.toolId }}</span>\n <span\n class=\"badge\"\n [class.success]=\"proposal.status === 'executed' || proposal.status === 'resolved'\"\n [class.warning]=\"proposal.status === 'pending' || proposal.status === 'execution-unknown' || proposal.status === 'stale'\"\n [class.danger]=\"proposal.status === 'execution-failed' || proposal.status === 'rejected'\">\n {{ statusKey(proposal) | translate }}\n </span>\n <span class=\"badge\">{{ 'nh-assistant.agent-runs.proposal.mode.' + proposal.mode | translate }}</span>\n @if (proposal.grantSource !== 'none') {\n <span class=\"badge\" [attr.title]=\"'nh-assistant.tool-call.grant-source.' + proposal.grantSource + '-hint' | translate\">\n {{ 'nh-assistant.tool-call.grant-source.' + proposal.grantSource | translate }}\n </span>\n }\n @if (proposal.consultationId) {\n <span class=\"badge\" [attr.title]=\"'nh-assistant.agent-runs.proposal.from-consultation-hint' | translate\">\n {{ 'nh-assistant.agent-runs.proposal.from-consultation' | translate }}\n </span>\n }\n </div>\n @if (proposal.presentation; as presentation) {\n <p class=\"summary\">{{ presentation.summary }}</p>\n @if (presentation.fields.length > 0) {\n <dl class=\"presentation-fields\">\n @for (field of presentation.fields; track $index) {\n <div>\n <dt>{{ field.label }}</dt>\n <dd>{{ field.value }}</dd>\n </div>\n }\n </dl>\n }\n @if (presentation.notice) {\n <p class=\"message warning\">{{ presentation.notice }}</p>\n }\n } @else {\n <p class=\"summary\">{{ 'nh-assistant.approval.fallback-summary' | translate }}</p>\n }\n @if (proposal.rationale) {\n <p class=\"rationale\">{{ 'nh-assistant.approval.rationale' | translate: { rationale: proposal.rationale } }}</p>\n }\n @if (proposal.status === 'stale' && proposal.staleExplanation) {\n <p class=\"message stale-explanation\">{{ proposal.staleExplanation }}</p>\n }\n @if (hasSuccessor(proposal)) {\n <button class=\"text-button\" type=\"button\" (click)=\"showSuccessor(proposal)\">\n {{ 'nh-assistant.agent-runs.proposal.show-successor' | translate }}\n </button>\n }\n @if (isHeld(proposal)) {\n <div class=\"closed-card\">\n <p class=\"muted\" role=\"status\">{{ 'nh-assistant.agent-runs.proposal.closed' | translate }}</p>\n <button\n class=\"text-button\"\n type=\"button\"\n [attr.aria-label]=\"'nh-assistant.agent-runs.proposal.dismiss-label' | translate: { summary: proposal.presentation?.summary ?? proposal.toolId }\"\n (click)=\"dismiss(proposal)\">\n {{ 'nh-assistant.agent-runs.proposal.dismiss' | translate }}\n </button>\n </div>\n }\n <details class=\"technical-details\">\n <summary>{{ 'nh-assistant.approval.technical-details' | translate }}</summary>\n <p class=\"label\">{{ 'nh-assistant.approval.tool-id' | translate }}</p>\n <code>{{ proposal.toolId }}</code>\n @if (proposal.targets.length > 0) {\n <p class=\"label\">{{ 'nh-assistant.approval.targets' | translate }}</p>\n <ul class=\"targets\">\n @for (target of proposal.targets; track $index) {\n <li>{{ target }}</li>\n }\n </ul>\n }\n @if (proposal.argumentsPreview) {\n <p class=\"label\">{{ 'nh-assistant.approval.arguments' | translate }}</p>\n <pre>{{ proposal.argumentsPreview }}</pre>\n }\n </details>\n <div class=\"meta\">\n @if (proposal.status === 'pending') {\n <span>{{ 'nh-assistant.agent-runs.proposal.expires' | translate: { date: (proposal.expiresAt | date: 'short') } }}</span>\n }\n @if (proposal.decidedByActorId) {\n <span>{{ 'nh-assistant.agent-runs.proposal.decided-by' | translate: { actor: proposal.decidedByDisplayName || proposal.decidedByActorId } }}</span>\n }\n @if (proposal.status === 'stale' && proposal.staleByActorId) {\n <span>{{ 'nh-assistant.agent-runs.proposal.stale-by' | translate: { actor: proposal.staleByDisplayName || proposal.staleByActorId } }}</span>\n }\n @if (proposal.executionResultCode; as code) {\n <span class=\"mono\">{{ code }}</span>\n }\n @if (proposal.feedback; as given) {\n <span>\n {{ 'nh-assistant.agent-runs.proposal.your-feedback' | translate: { category: ('nh-assistant.proposal-feedback.categories.' + given.category | translate) } }}\n </span>\n }\n @if (proposal.canGiveFeedback && !isAsking(proposal)) {\n <button\n class=\"text-button\"\n type=\"button\"\n [attr.data-feedback-approval]=\"proposal.approvalId\"\n [disabled]=\"busy()\"\n (click)=\"giveFeedback(proposal)\">\n {{ (proposal.feedback ? 'nh-assistant.agent-runs.proposal.change-feedback' : 'nh-assistant.agent-runs.proposal.give-feedback') | translate }}\n </button>\n }\n </div>\n @if (inCard(proposal) && feedback(); as request) {\n <nh-assistant-proposal-feedback\n [approvalIds]=\"request.approvalIds\"\n [initial]=\"request.initial\"\n (saved)=\"onFeedbackSaved()\"\n (dismissed)=\"onFeedbackDismissed()\" />\n }\n @if (waitingForKey(proposal); as waitingFor) {\n <p class=\"waiting-for\"><nh-assistant-icon name=\"users\" />{{ waitingFor | translate }}</p>\n }\n @if (proposal.status === 'pending' && mayDecide(proposal)) {\n <div class=\"card-actions\">\n <button class=\"primary\" type=\"button\" [disabled]=\"busy()\" (click)=\"decide(proposal, 'approve')\">\n <nh-assistant-icon name=\"check\" />{{ 'nh-assistant.agent-runs.proposal.approve' | translate }}\n </button>\n <button class=\"secondary\" type=\"button\" [disabled]=\"busy()\" (click)=\"decide(proposal, 'reject')\">\n <nh-assistant-icon name=\"x\" />{{ 'nh-assistant.agent-runs.proposal.reject' | translate }}\n </button>\n </div>\n }\n @if (proposal.status === 'execution-unknown' && mayDecide(proposal)) {\n <p class=\"message warning\"><nh-assistant-icon name=\"warning\" />{{ 'nh-assistant.agent-runs.proposal.unknown-hint' | translate }}</p>\n <div class=\"card-actions\">\n <button class=\"secondary\" type=\"button\" [disabled]=\"busy()\" (click)=\"resolve(proposal, 'mark-resolved')\">\n <nh-assistant-icon name=\"check\" />{{ 'nh-assistant.agent-runs.proposal.mark-resolved' | translate }}\n </button>\n <button class=\"danger\" type=\"button\" [disabled]=\"busy()\" (click)=\"resolve(proposal, 're-execute')\">\n <nh-assistant-icon name=\"refresh\" />{{ 'nh-assistant.agent-runs.proposal.re-execute' | translate }}\n </button>\n </div>\n }\n </li>\n }\n </ul>\n }\n</div>\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;min-width:0;color:var(--nha-text);font-family:var(--nha-font);font-size:14px}: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}.section{display:flex;flex-direction:column;gap:14px;min-width:0}.section-header{display:flex;flex-wrap:wrap;align-items:flex-start;justify-content:space-between;gap:12px}.section-header>div{min-width:0;max-width:72ch}h3{margin:0 0 4px;font-size:17px;font-weight:750}.muted{margin:0;color:var(--nha-text-muted);font-size:13px}.state{display:flex;flex-direction:column;align-items:flex-start;gap:10px;margin:0;border:1px dashed var(--nha-border);border-radius:var(--nha-radius);padding:18px;color:var(--nha-text-muted);font-size:13px}.state p{margin:0}.cards{display:grid;gap:10px;margin:0;padding:0;list-style:none}.card{display:flex;flex-direction:column;gap:8px;min-width:0;border:1px solid var(--nha-border);border-radius:var(--nha-radius);padding:12px 14px;background:var(--nha-surface)}.card.selected{border-color:var(--nha-accent, currentColor)}.card[tabindex]:focus-visible{outline:3px solid color-mix(in srgb,var(--nha-focus) 80%,transparent);outline-offset:2px}.card.closed{border-style:dashed}.closed-card{display:flex;flex-wrap:wrap;align-items:center;justify-content:space-between;gap:8px}.message.stale-explanation{overflow-wrap:anywhere;color:var(--nha-text);background:var(--nha-surface-strong)}.rationale{margin:0;overflow-wrap:anywhere;color:var(--nha-text-muted);font-size:13px}.card-header{display:flex;flex-wrap:wrap;align-items:center;gap:8px;min-width:0}.card-header strong{font-size:14px;overflow-wrap:anywhere}.card-actions{display:flex;flex-wrap:wrap;align-items:center;gap:8px}.meta{display:flex;flex-wrap:wrap;align-items:center;gap:6px 12px;color:var(--nha-text-muted);font-size:12px;overflow-wrap:anywhere}pre{max-height:220px;margin:0;overflow:auto;border-radius:var(--nha-radius-control);padding:8px 10px;background:var(--nha-surface-muted, rgba(127, 127, 127, .08));font-family:var(--nha-mono);font-size:12px;white-space:pre-wrap;overflow-wrap:anywhere}.summary{margin:0;font-size:13px;overflow-wrap:anywhere}.presentation-fields{display:grid;gap:6px;margin:0}.presentation-fields div{display:grid;grid-template-columns:minmax(90px,.4fr) minmax(0,1fr);gap:8px}.presentation-fields dt{color:var(--nha-text-muted);font-size:12px;font-weight:700;overflow-wrap:anywhere}.presentation-fields dd{margin:0;font-size:13px;overflow-wrap:anywhere}.technical-details{color:var(--nha-text-muted);font-size:12px}.technical-details summary{cursor:pointer;font-weight:700}.technical-details code{overflow-wrap:anywhere}.technical-details .label{margin:10px 0 4px;font-size:11px;font-weight:700;text-transform:uppercase;letter-spacing:.04em}.technical-details .targets{margin:0;padding-left:18px;overflow-wrap:anywhere}.tabs{display:flex;flex-wrap:wrap;gap:4px;border-bottom:1px solid var(--nha-border)}.tabs button{border:0;border-bottom:2px solid transparent;border-radius:0;padding:8px 12px;background:transparent;color:var(--nha-text-muted);font:inherit;cursor:pointer}.tabs button[aria-selected=true]{border-bottom-color:currentColor;color:var(--nha-text);font-weight:650}.toolbar{display:flex;flex-wrap:wrap;align-items:center;gap:8px}.reason{flex:1 1 200px;min-width:0}.select{display:inline-flex;align-items:center;gap:6px;font-size:12px}.proposal-list{display:flex;flex-direction:column;gap:10px;min-width:0}.feedback-prompt{display:flex;flex-direction:column;gap:6px;min-width:0}.feedback-prompt .muted{overflow-wrap:anywhere}.text-button{display:inline-flex;align-items:center;border:0;border-radius:6px;padding:2px 4px;color:var(--nha-text-muted);background:transparent;font:inherit;font-size:12px;font-weight:650;text-decoration:underline;text-underline-offset:2px;cursor:pointer}.text-button:focus-visible{outline:3px solid color-mix(in srgb,var(--nha-focus) 80%,transparent);outline-offset:2px}.text-button:hover:not(:disabled){color:var(--nha-text)}.text-button:disabled{cursor:not-allowed;opacity:.55}.waiting-for{display:flex;align-items:center;gap:6px;margin:0;color:var(--nha-text-muted);font-size:12px;overflow-wrap:anywhere}.subject-agents{display:grid;gap:8px;margin:0;padding:0;list-style:none}.subject-agent{display:flex;flex-wrap:wrap;align-items:center;justify-content:space-between;gap:8px 12px;min-width:0;border:1px solid var(--nha-border);border-radius:var(--nha-radius-control);padding:10px 12px}.subject-agent-text{display:flex;flex-direction:column;gap:2px;min-width:0}.subject-agent-text strong{font-size:14px;overflow-wrap:anywhere}\n"], dependencies: [{ kind: "component", type: _NhAssistantIconComponent, selector: "nh-assistant-icon", inputs: ["name"] }, { kind: "component", type: NhAssistantProposalFeedbackComponent, selector: "nh-assistant-proposal-feedback", inputs: ["approvalIds", "initial"], outputs: ["saved", "dismissed"] }, { kind: "pipe", type: DatePipe, name: "date" }, { kind: "pipe", type: TranslatePipe, name: "translate" }, { kind: "pipe", type: _NhAssistantTranslatePipe, name: "nhAssistantTranslate" }], changeDetection: i0.ChangeDetectionStrategy.OnPush }); }
|
|
275
|
+
}
|
|
276
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.33", ngImport: i0, type: NhAssistantAgentProposalsComponent, decorators: [{
|
|
277
|
+
type: Component,
|
|
278
|
+
args: [{ selector: 'nh-assistant-agent-proposals', standalone: true, imports: [DatePipe, TranslatePipe, _NhAssistantTranslatePipe, _NhAssistantIconComponent, NhAssistantProposalFeedbackComponent], changeDetection: ChangeDetectionStrategy.OnPush, template: "<div class=\"proposal-list\">\n @if (error(); as failure) {\n <p class=\"message error\" role=\"alert\"><nh-assistant-icon name=\"warning\" />{{ errorKeys() | nhAssistantTranslate: failure.code }}</p>\n }\n\n @if (feedback(); as request) {\n @if (request.placement === 'prompt') {\n <div class=\"feedback-prompt\">\n @if (request.summary && !request.saved) {\n <p class=\"muted\">{{ 'nh-assistant.agent-runs.proposal.rejected-one' | translate: { summary: request.summary } }}</p>\n }\n <nh-assistant-proposal-feedback\n [approvalIds]=\"request.approvalIds\"\n [initial]=\"request.initial\"\n (saved)=\"onFeedbackSaved()\"\n (dismissed)=\"onFeedbackDismissed()\" />\n </div>\n }\n }\n\n @if (selectable() && pending().length > 0) {\n <div class=\"toolbar\">\n <label class=\"select\">\n <input type=\"checkbox\" [checked]=\"allSelected()\" [disabled]=\"busy()\" (change)=\"toggleAll()\" />\n {{ 'nh-assistant.agent-runs.inbox.select-all' | translate }}\n </label>\n <button class=\"primary\" type=\"button\" [disabled]=\"busy() || selected().size === 0\" (click)=\"decideSelected('approve')\">\n <nh-assistant-icon name=\"check\" />{{ 'nh-assistant.agent-runs.inbox.approve-selected' | translate }}\n </button>\n <button class=\"secondary\" type=\"button\" [disabled]=\"busy() || selected().size === 0\" (click)=\"decideSelected('reject')\">\n <nh-assistant-icon name=\"x\" />{{ 'nh-assistant.agent-runs.inbox.reject-selected' | translate }}\n </button>\n </div>\n }\n\n @if (shown().length > 0) {\n <ul class=\"cards\" [attr.aria-busy]=\"busy()\">\n @for (proposal of shown(); track proposal.approvalId) {\n <li\n class=\"card\"\n tabindex=\"-1\"\n [attr.data-approval-id]=\"proposal.approvalId\"\n [class.selected]=\"selected().has(proposal.approvalId)\"\n [class.closed]=\"isHeld(proposal)\">\n <div class=\"card-header\">\n @if (selectable() && proposal.status === 'pending' && mayDecide(proposal)) {\n <input\n type=\"checkbox\"\n [checked]=\"selected().has(proposal.approvalId)\"\n [disabled]=\"busy()\"\n [attr.aria-label]=\"'nh-assistant.agent-runs.inbox.select' | translate\"\n (change)=\"toggle(proposal)\" />\n }\n <strong>{{ proposal.subjectDisplayName ?? proposal.subjectId }}</strong>\n <span class=\"muted\">{{ proposal.presentation?.toolDisplayName ?? proposal.toolId }}</span>\n <span\n class=\"badge\"\n [class.success]=\"proposal.status === 'executed' || proposal.status === 'resolved'\"\n [class.warning]=\"proposal.status === 'pending' || proposal.status === 'execution-unknown' || proposal.status === 'stale'\"\n [class.danger]=\"proposal.status === 'execution-failed' || proposal.status === 'rejected'\">\n {{ statusKey(proposal) | translate }}\n </span>\n <span class=\"badge\">{{ 'nh-assistant.agent-runs.proposal.mode.' + proposal.mode | translate }}</span>\n @if (proposal.grantSource !== 'none') {\n <span class=\"badge\" [attr.title]=\"'nh-assistant.tool-call.grant-source.' + proposal.grantSource + '-hint' | translate\">\n {{ 'nh-assistant.tool-call.grant-source.' + proposal.grantSource | translate }}\n </span>\n }\n @if (proposal.consultationId) {\n <span class=\"badge\" [attr.title]=\"'nh-assistant.agent-runs.proposal.from-consultation-hint' | translate\">\n {{ 'nh-assistant.agent-runs.proposal.from-consultation' | translate }}\n </span>\n }\n </div>\n @if (proposal.presentation; as presentation) {\n <p class=\"summary\">{{ presentation.summary }}</p>\n @if (presentation.fields.length > 0) {\n <dl class=\"presentation-fields\">\n @for (field of presentation.fields; track $index) {\n <div>\n <dt>{{ field.label }}</dt>\n <dd>{{ field.value }}</dd>\n </div>\n }\n </dl>\n }\n @if (presentation.notice) {\n <p class=\"message warning\">{{ presentation.notice }}</p>\n }\n } @else {\n <p class=\"summary\">{{ 'nh-assistant.approval.fallback-summary' | translate }}</p>\n }\n @if (proposal.rationale) {\n <p class=\"rationale\">{{ 'nh-assistant.approval.rationale' | translate: { rationale: proposal.rationale } }}</p>\n }\n @if (proposal.status === 'stale' && proposal.staleExplanation) {\n <p class=\"message stale-explanation\">{{ proposal.staleExplanation }}</p>\n }\n @if (hasSuccessor(proposal)) {\n <button class=\"text-button\" type=\"button\" (click)=\"showSuccessor(proposal)\">\n {{ 'nh-assistant.agent-runs.proposal.show-successor' | translate }}\n </button>\n }\n @if (isHeld(proposal)) {\n <div class=\"closed-card\">\n <p class=\"muted\" role=\"status\">{{ 'nh-assistant.agent-runs.proposal.closed' | translate }}</p>\n <button\n class=\"text-button\"\n type=\"button\"\n [attr.aria-label]=\"'nh-assistant.agent-runs.proposal.dismiss-label' | translate: { summary: proposal.presentation?.summary ?? proposal.toolId }\"\n (click)=\"dismiss(proposal)\">\n {{ 'nh-assistant.agent-runs.proposal.dismiss' | translate }}\n </button>\n </div>\n }\n <details class=\"technical-details\">\n <summary>{{ 'nh-assistant.approval.technical-details' | translate }}</summary>\n <p class=\"label\">{{ 'nh-assistant.approval.tool-id' | translate }}</p>\n <code>{{ proposal.toolId }}</code>\n @if (proposal.targets.length > 0) {\n <p class=\"label\">{{ 'nh-assistant.approval.targets' | translate }}</p>\n <ul class=\"targets\">\n @for (target of proposal.targets; track $index) {\n <li>{{ target }}</li>\n }\n </ul>\n }\n @if (proposal.argumentsPreview) {\n <p class=\"label\">{{ 'nh-assistant.approval.arguments' | translate }}</p>\n <pre>{{ proposal.argumentsPreview }}</pre>\n }\n </details>\n <div class=\"meta\">\n @if (proposal.status === 'pending') {\n <span>{{ 'nh-assistant.agent-runs.proposal.expires' | translate: { date: (proposal.expiresAt | date: 'short') } }}</span>\n }\n @if (proposal.decidedByActorId) {\n <span>{{ 'nh-assistant.agent-runs.proposal.decided-by' | translate: { actor: proposal.decidedByDisplayName || proposal.decidedByActorId } }}</span>\n }\n @if (proposal.status === 'stale' && proposal.staleByActorId) {\n <span>{{ 'nh-assistant.agent-runs.proposal.stale-by' | translate: { actor: proposal.staleByDisplayName || proposal.staleByActorId } }}</span>\n }\n @if (proposal.executionResultCode; as code) {\n <span class=\"mono\">{{ code }}</span>\n }\n @if (proposal.feedback; as given) {\n <span>\n {{ 'nh-assistant.agent-runs.proposal.your-feedback' | translate: { category: ('nh-assistant.proposal-feedback.categories.' + given.category | translate) } }}\n </span>\n }\n @if (proposal.canGiveFeedback && !isAsking(proposal)) {\n <button\n class=\"text-button\"\n type=\"button\"\n [attr.data-feedback-approval]=\"proposal.approvalId\"\n [disabled]=\"busy()\"\n (click)=\"giveFeedback(proposal)\">\n {{ (proposal.feedback ? 'nh-assistant.agent-runs.proposal.change-feedback' : 'nh-assistant.agent-runs.proposal.give-feedback') | translate }}\n </button>\n }\n </div>\n @if (inCard(proposal) && feedback(); as request) {\n <nh-assistant-proposal-feedback\n [approvalIds]=\"request.approvalIds\"\n [initial]=\"request.initial\"\n (saved)=\"onFeedbackSaved()\"\n (dismissed)=\"onFeedbackDismissed()\" />\n }\n @if (waitingForKey(proposal); as waitingFor) {\n <p class=\"waiting-for\"><nh-assistant-icon name=\"users\" />{{ waitingFor | translate }}</p>\n }\n @if (proposal.status === 'pending' && mayDecide(proposal)) {\n <div class=\"card-actions\">\n <button class=\"primary\" type=\"button\" [disabled]=\"busy()\" (click)=\"decide(proposal, 'approve')\">\n <nh-assistant-icon name=\"check\" />{{ 'nh-assistant.agent-runs.proposal.approve' | translate }}\n </button>\n <button class=\"secondary\" type=\"button\" [disabled]=\"busy()\" (click)=\"decide(proposal, 'reject')\">\n <nh-assistant-icon name=\"x\" />{{ 'nh-assistant.agent-runs.proposal.reject' | translate }}\n </button>\n </div>\n }\n @if (proposal.status === 'execution-unknown' && mayDecide(proposal)) {\n <p class=\"message warning\"><nh-assistant-icon name=\"warning\" />{{ 'nh-assistant.agent-runs.proposal.unknown-hint' | translate }}</p>\n <div class=\"card-actions\">\n <button class=\"secondary\" type=\"button\" [disabled]=\"busy()\" (click)=\"resolve(proposal, 'mark-resolved')\">\n <nh-assistant-icon name=\"check\" />{{ 'nh-assistant.agent-runs.proposal.mark-resolved' | translate }}\n </button>\n <button class=\"danger\" type=\"button\" [disabled]=\"busy()\" (click)=\"resolve(proposal, 're-execute')\">\n <nh-assistant-icon name=\"refresh\" />{{ 'nh-assistant.agent-runs.proposal.re-execute' | translate }}\n </button>\n </div>\n }\n </li>\n }\n </ul>\n }\n</div>\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;min-width:0;color:var(--nha-text);font-family:var(--nha-font);font-size:14px}: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}.section{display:flex;flex-direction:column;gap:14px;min-width:0}.section-header{display:flex;flex-wrap:wrap;align-items:flex-start;justify-content:space-between;gap:12px}.section-header>div{min-width:0;max-width:72ch}h3{margin:0 0 4px;font-size:17px;font-weight:750}.muted{margin:0;color:var(--nha-text-muted);font-size:13px}.state{display:flex;flex-direction:column;align-items:flex-start;gap:10px;margin:0;border:1px dashed var(--nha-border);border-radius:var(--nha-radius);padding:18px;color:var(--nha-text-muted);font-size:13px}.state p{margin:0}.cards{display:grid;gap:10px;margin:0;padding:0;list-style:none}.card{display:flex;flex-direction:column;gap:8px;min-width:0;border:1px solid var(--nha-border);border-radius:var(--nha-radius);padding:12px 14px;background:var(--nha-surface)}.card.selected{border-color:var(--nha-accent, currentColor)}.card[tabindex]:focus-visible{outline:3px solid color-mix(in srgb,var(--nha-focus) 80%,transparent);outline-offset:2px}.card.closed{border-style:dashed}.closed-card{display:flex;flex-wrap:wrap;align-items:center;justify-content:space-between;gap:8px}.message.stale-explanation{overflow-wrap:anywhere;color:var(--nha-text);background:var(--nha-surface-strong)}.rationale{margin:0;overflow-wrap:anywhere;color:var(--nha-text-muted);font-size:13px}.card-header{display:flex;flex-wrap:wrap;align-items:center;gap:8px;min-width:0}.card-header strong{font-size:14px;overflow-wrap:anywhere}.card-actions{display:flex;flex-wrap:wrap;align-items:center;gap:8px}.meta{display:flex;flex-wrap:wrap;align-items:center;gap:6px 12px;color:var(--nha-text-muted);font-size:12px;overflow-wrap:anywhere}pre{max-height:220px;margin:0;overflow:auto;border-radius:var(--nha-radius-control);padding:8px 10px;background:var(--nha-surface-muted, rgba(127, 127, 127, .08));font-family:var(--nha-mono);font-size:12px;white-space:pre-wrap;overflow-wrap:anywhere}.summary{margin:0;font-size:13px;overflow-wrap:anywhere}.presentation-fields{display:grid;gap:6px;margin:0}.presentation-fields div{display:grid;grid-template-columns:minmax(90px,.4fr) minmax(0,1fr);gap:8px}.presentation-fields dt{color:var(--nha-text-muted);font-size:12px;font-weight:700;overflow-wrap:anywhere}.presentation-fields dd{margin:0;font-size:13px;overflow-wrap:anywhere}.technical-details{color:var(--nha-text-muted);font-size:12px}.technical-details summary{cursor:pointer;font-weight:700}.technical-details code{overflow-wrap:anywhere}.technical-details .label{margin:10px 0 4px;font-size:11px;font-weight:700;text-transform:uppercase;letter-spacing:.04em}.technical-details .targets{margin:0;padding-left:18px;overflow-wrap:anywhere}.tabs{display:flex;flex-wrap:wrap;gap:4px;border-bottom:1px solid var(--nha-border)}.tabs button{border:0;border-bottom:2px solid transparent;border-radius:0;padding:8px 12px;background:transparent;color:var(--nha-text-muted);font:inherit;cursor:pointer}.tabs button[aria-selected=true]{border-bottom-color:currentColor;color:var(--nha-text);font-weight:650}.toolbar{display:flex;flex-wrap:wrap;align-items:center;gap:8px}.reason{flex:1 1 200px;min-width:0}.select{display:inline-flex;align-items:center;gap:6px;font-size:12px}.proposal-list{display:flex;flex-direction:column;gap:10px;min-width:0}.feedback-prompt{display:flex;flex-direction:column;gap:6px;min-width:0}.feedback-prompt .muted{overflow-wrap:anywhere}.text-button{display:inline-flex;align-items:center;border:0;border-radius:6px;padding:2px 4px;color:var(--nha-text-muted);background:transparent;font:inherit;font-size:12px;font-weight:650;text-decoration:underline;text-underline-offset:2px;cursor:pointer}.text-button:focus-visible{outline:3px solid color-mix(in srgb,var(--nha-focus) 80%,transparent);outline-offset:2px}.text-button:hover:not(:disabled){color:var(--nha-text)}.text-button:disabled{cursor:not-allowed;opacity:.55}.waiting-for{display:flex;align-items:center;gap:6px;margin:0;color:var(--nha-text-muted);font-size:12px;overflow-wrap:anywhere}.subject-agents{display:grid;gap:8px;margin:0;padding:0;list-style:none}.subject-agent{display:flex;flex-wrap:wrap;align-items:center;justify-content:space-between;gap:8px 12px;min-width:0;border:1px solid var(--nha-border);border-radius:var(--nha-radius-control);padding:10px 12px}.subject-agent-text{display:flex;flex-direction:column;gap:2px;min-width:0}.subject-agent-text strong{font-size:14px;overflow-wrap:anywhere}\n"] }]
|
|
279
|
+
}], ctorParameters: () => [], propDecorators: { proposals: [{ type: i0.Input, args: [{ isSignal: true, alias: "proposals", required: true }] }], canDecide: [{ type: i0.Input, args: [{ isSignal: true, alias: "canDecide", required: false }] }], decisionRights: [{ type: i0.Input, args: [{ isSignal: true, alias: "decisionRights", required: false }] }], selectable: [{ type: i0.Input, args: [{ isSignal: true, alias: "selectable", required: false }] }], holdClosedCards: [{ type: i0.Input, args: [{ isSignal: true, alias: "holdClosedCards", required: false }] }], changed: [{ type: i0.Output, args: ["changed"] }] } });
|
|
280
|
+
/** The refusal of an approval because the proposal no longer fits. */
|
|
281
|
+
const staleCode = 'assistant-proposal-stale';
|
|
282
|
+
/** The application's words for a proposal, falling back to its subject and tool. */
|
|
283
|
+
function summaryOf(proposal) {
|
|
284
|
+
return proposal.presentation?.summary
|
|
285
|
+
?? `${proposal.subjectDisplayName ?? proposal.subjectId} · ${proposal.presentation?.toolDisplayName ?? proposal.toolId}`;
|
|
286
|
+
}
|
|
287
|
+
/** True for a proposal a newer proposal for the same objects replaced. */
|
|
288
|
+
function isSuperseded(proposal) {
|
|
289
|
+
return proposal.status === 'withdrawn' && !!proposal.supersededByApprovalId;
|
|
290
|
+
}
|
|
291
|
+
|
|
292
|
+
/**
|
|
293
|
+
* The approval inbox: pending agent proposals across subjects that the signed-in person may
|
|
294
|
+
* decide, earliest expiry first. Proposals are decided in place, one by one or together; the
|
|
295
|
+
* server checks each decision against the proposal's approval policy again. After a rejection the
|
|
296
|
+
* inbox asks, optionally, what was wrong, also when the rejected proposals have left the list.
|
|
297
|
+
* With live updates the inbox reloads by itself when agent work changes, for example when a
|
|
298
|
+
* colleague decided a proposal or a run proposed a new one. A proposal that closes because it no
|
|
299
|
+
* longer fits, for example because someone did the work by hand, stays as a closed card with the
|
|
300
|
+
* reason until it is dismissed.
|
|
301
|
+
*/
|
|
302
|
+
class NhAssistantAgentInboxComponent {
|
|
303
|
+
constructor() {
|
|
304
|
+
this.api = inject(NhAssistantAgentRunApiService);
|
|
305
|
+
this.proposalList = viewChild(NhAssistantAgentProposalsComponent, ...(ngDevMode ? [{ debugName: "proposalList" }] : []));
|
|
306
|
+
/** Limits the inbox to one agent. */
|
|
307
|
+
this.agentId = input(undefined, ...(ngDevMode ? [{ debugName: "agentId" }] : []));
|
|
308
|
+
/** Limits the inbox to one kind of subject, for example `project`. */
|
|
309
|
+
this.subjectType = input(undefined, ...(ngDevMode ? [{ debugName: "subjectType" }] : []));
|
|
310
|
+
this.itemsPerPage = input(20, ...(ngDevMode ? [{ debugName: "itemsPerPage" }] : []));
|
|
311
|
+
this.page = signal(1, ...(ngDevMode ? [{ debugName: "page" }] : []));
|
|
312
|
+
this.loading = signal(true, ...(ngDevMode ? [{ debugName: "loading" }] : []));
|
|
313
|
+
/** True after the first successful load; later loads keep the list, and an open feedback question, in place. */
|
|
314
|
+
this.loaded = signal(false, ...(ngDevMode ? [{ debugName: "loaded" }] : []));
|
|
315
|
+
this.loadFailed = signal(false, ...(ngDevMode ? [{ debugName: "loadFailed" }] : []));
|
|
316
|
+
this.items = signal([], ...(ngDevMode ? [{ debugName: "items" }] : []));
|
|
317
|
+
this.total = signal(0, ...(ngDevMode ? [{ debugName: "total" }] : []));
|
|
318
|
+
this.pages = computed(() => Math.max(1, Math.ceil(this.total() / this.itemsPerPage())), ...(ngDevMode ? [{ debugName: "pages" }] : []));
|
|
319
|
+
inject(DestroyRef).onDestroy(() => this.subscription?.unsubscribe());
|
|
320
|
+
effect(() => {
|
|
321
|
+
this.agentId();
|
|
322
|
+
this.subjectType();
|
|
323
|
+
untracked(() => {
|
|
324
|
+
this.page.set(1);
|
|
325
|
+
this.load();
|
|
326
|
+
});
|
|
327
|
+
});
|
|
328
|
+
// Any agent's work may add, decide or close a proposal of this inbox.
|
|
329
|
+
_nhAssistantReloadOnAgentWork(() => true, () => this.refresh());
|
|
330
|
+
}
|
|
331
|
+
load() {
|
|
332
|
+
this.fetch(false);
|
|
333
|
+
}
|
|
334
|
+
goTo(page) {
|
|
335
|
+
this.page.set(Math.min(Math.max(1, page), this.pages()));
|
|
336
|
+
this.load();
|
|
337
|
+
}
|
|
338
|
+
/**
|
|
339
|
+
* Reloads after a live update. Once the inbox is shown it reloads quietly: no loading state, and
|
|
340
|
+
* a failure keeps the list and an open feedback question in place. While a decision of the list
|
|
341
|
+
* is in flight it waits, because the decision reloads the inbox when it ends.
|
|
342
|
+
*/
|
|
343
|
+
refresh() {
|
|
344
|
+
if (this.proposalList()?.busy()) {
|
|
345
|
+
return;
|
|
346
|
+
}
|
|
347
|
+
this.fetch(this.loaded() && !this.loading() && !this.loadFailed());
|
|
348
|
+
}
|
|
349
|
+
fetch(quiet) {
|
|
350
|
+
if (!quiet) {
|
|
351
|
+
this.loading.set(true);
|
|
352
|
+
this.loadFailed.set(false);
|
|
353
|
+
}
|
|
354
|
+
this.subscription?.unsubscribe();
|
|
355
|
+
this.subscription = this.api
|
|
356
|
+
.getInbox({
|
|
357
|
+
agentId: this.agentId(),
|
|
358
|
+
subjectType: this.subjectType(),
|
|
359
|
+
page: this.page(),
|
|
360
|
+
itemsPerPage: this.itemsPerPage()
|
|
361
|
+
})
|
|
362
|
+
.subscribe({
|
|
363
|
+
next: inbox => {
|
|
364
|
+
const lastPage = Math.max(1, Math.ceil(inbox.total / this.itemsPerPage()));
|
|
365
|
+
if (inbox.items.length === 0 && this.page() > lastPage) {
|
|
366
|
+
// Proposals were decided elsewhere and this page no longer exists.
|
|
367
|
+
this.page.set(lastPage);
|
|
368
|
+
this.fetch(quiet);
|
|
369
|
+
return;
|
|
370
|
+
}
|
|
371
|
+
const previous = this.items();
|
|
372
|
+
this.items.set(inbox.items);
|
|
373
|
+
if (quiet) {
|
|
374
|
+
this.proposalList()?.holdClosed(previous, inbox.items);
|
|
375
|
+
}
|
|
376
|
+
this.total.set(inbox.total);
|
|
377
|
+
this.loading.set(false);
|
|
378
|
+
this.loadFailed.set(false);
|
|
379
|
+
this.loaded.set(true);
|
|
380
|
+
},
|
|
381
|
+
error: () => {
|
|
382
|
+
if (quiet) {
|
|
383
|
+
return;
|
|
384
|
+
}
|
|
385
|
+
this.loading.set(false);
|
|
386
|
+
this.loadFailed.set(true);
|
|
387
|
+
}
|
|
388
|
+
});
|
|
389
|
+
}
|
|
390
|
+
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.3.33", ngImport: i0, type: NhAssistantAgentInboxComponent, deps: [], target: i0.ɵɵFactoryTarget.Component }); }
|
|
391
|
+
static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "20.3.33", type: NhAssistantAgentInboxComponent, isStandalone: true, selector: "nh-assistant-agent-inbox", inputs: { agentId: { classPropertyName: "agentId", publicName: "agentId", isSignal: true, isRequired: false, transformFunction: null }, subjectType: { classPropertyName: "subjectType", publicName: "subjectType", isSignal: true, isRequired: false, transformFunction: null }, itemsPerPage: { classPropertyName: "itemsPerPage", publicName: "itemsPerPage", isSignal: true, isRequired: false, transformFunction: null } }, viewQueries: [{ propertyName: "proposalList", first: true, predicate: NhAssistantAgentProposalsComponent, descendants: true, isSignal: true }], ngImport: i0, template: "<section class=\"section\" aria-labelledby=\"nh-assistant-agent-inbox-title\" [attr.aria-busy]=\"loading()\">\n <header class=\"section-header\">\n <div>\n <h3 id=\"nh-assistant-agent-inbox-title\">{{ 'nh-assistant.agent-runs.inbox.title' | translate }}</h3>\n <p class=\"muted\">{{ 'nh-assistant.agent-runs.inbox.description' | translate }}</p>\n </div>\n <button class=\"secondary\" type=\"button\" [disabled]=\"loading()\" (click)=\"load()\">\n <nh-assistant-icon name=\"refresh\" />{{ 'nh-assistant.agent-runs.refresh' | translate }}\n </button>\n </header>\n\n @if (loading() && items().length === 0 && !loaded()) {\n <p class=\"state\" role=\"status\">{{ 'nh-assistant.agent-runs.loading' | translate }}</p>\n } @else if (loadFailed()) {\n <div class=\"state\" role=\"alert\">\n <p>{{ 'nh-assistant.agent-runs.load-failed' | translate }}</p>\n <button class=\"secondary\" type=\"button\" (click)=\"load()\">{{ 'nh-assistant.agent-runs.retry' | translate }}</button>\n </div>\n } @else {\n <!-- Stays rendered when the list empties, so the optional feedback after a rejection remains. -->\n <nh-assistant-agent-proposals\n [proposals]=\"items()\"\n [canDecide]=\"true\"\n [selectable]=\"true\"\n [holdClosedCards]=\"true\"\n (changed)=\"load()\" />\n @if (items().length === 0) {\n <p class=\"state\">{{ 'nh-assistant.agent-runs.inbox.empty' | translate }}</p>\n }\n @if (pages() > 1) {\n <nav class=\"toolbar\" [attr.aria-label]=\"'nh-assistant.agent-runs.inbox.pages' | translate\">\n <button class=\"secondary\" type=\"button\" [disabled]=\"page() <= 1 || loading()\" (click)=\"goTo(page() - 1)\">\n {{ 'nh-assistant.agent-runs.inbox.previous' | translate }}\n </button>\n <span class=\"muted\">{{ 'nh-assistant.agent-runs.inbox.page' | translate: { page: page(), pages: pages() } }}</span>\n <button class=\"secondary\" type=\"button\" [disabled]=\"page() >= pages() || loading()\" (click)=\"goTo(page() + 1)\">\n {{ 'nh-assistant.agent-runs.inbox.next' | translate }}\n </button>\n </nav>\n }\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:block;min-width:0;color:var(--nha-text);font-family:var(--nha-font);font-size:14px}: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}.section{display:flex;flex-direction:column;gap:14px;min-width:0}.section-header{display:flex;flex-wrap:wrap;align-items:flex-start;justify-content:space-between;gap:12px}.section-header>div{min-width:0;max-width:72ch}h3{margin:0 0 4px;font-size:17px;font-weight:750}.muted{margin:0;color:var(--nha-text-muted);font-size:13px}.state{display:flex;flex-direction:column;align-items:flex-start;gap:10px;margin:0;border:1px dashed var(--nha-border);border-radius:var(--nha-radius);padding:18px;color:var(--nha-text-muted);font-size:13px}.state p{margin:0}.cards{display:grid;gap:10px;margin:0;padding:0;list-style:none}.card{display:flex;flex-direction:column;gap:8px;min-width:0;border:1px solid var(--nha-border);border-radius:var(--nha-radius);padding:12px 14px;background:var(--nha-surface)}.card.selected{border-color:var(--nha-accent, currentColor)}.card[tabindex]:focus-visible{outline:3px solid color-mix(in srgb,var(--nha-focus) 80%,transparent);outline-offset:2px}.card.closed{border-style:dashed}.closed-card{display:flex;flex-wrap:wrap;align-items:center;justify-content:space-between;gap:8px}.message.stale-explanation{overflow-wrap:anywhere;color:var(--nha-text);background:var(--nha-surface-strong)}.rationale{margin:0;overflow-wrap:anywhere;color:var(--nha-text-muted);font-size:13px}.card-header{display:flex;flex-wrap:wrap;align-items:center;gap:8px;min-width:0}.card-header strong{font-size:14px;overflow-wrap:anywhere}.card-actions{display:flex;flex-wrap:wrap;align-items:center;gap:8px}.meta{display:flex;flex-wrap:wrap;align-items:center;gap:6px 12px;color:var(--nha-text-muted);font-size:12px;overflow-wrap:anywhere}pre{max-height:220px;margin:0;overflow:auto;border-radius:var(--nha-radius-control);padding:8px 10px;background:var(--nha-surface-muted, rgba(127, 127, 127, .08));font-family:var(--nha-mono);font-size:12px;white-space:pre-wrap;overflow-wrap:anywhere}.summary{margin:0;font-size:13px;overflow-wrap:anywhere}.presentation-fields{display:grid;gap:6px;margin:0}.presentation-fields div{display:grid;grid-template-columns:minmax(90px,.4fr) minmax(0,1fr);gap:8px}.presentation-fields dt{color:var(--nha-text-muted);font-size:12px;font-weight:700;overflow-wrap:anywhere}.presentation-fields dd{margin:0;font-size:13px;overflow-wrap:anywhere}.technical-details{color:var(--nha-text-muted);font-size:12px}.technical-details summary{cursor:pointer;font-weight:700}.technical-details code{overflow-wrap:anywhere}.technical-details .label{margin:10px 0 4px;font-size:11px;font-weight:700;text-transform:uppercase;letter-spacing:.04em}.technical-details .targets{margin:0;padding-left:18px;overflow-wrap:anywhere}.tabs{display:flex;flex-wrap:wrap;gap:4px;border-bottom:1px solid var(--nha-border)}.tabs button{border:0;border-bottom:2px solid transparent;border-radius:0;padding:8px 12px;background:transparent;color:var(--nha-text-muted);font:inherit;cursor:pointer}.tabs button[aria-selected=true]{border-bottom-color:currentColor;color:var(--nha-text);font-weight:650}.toolbar{display:flex;flex-wrap:wrap;align-items:center;gap:8px}.reason{flex:1 1 200px;min-width:0}.select{display:inline-flex;align-items:center;gap:6px;font-size:12px}.proposal-list{display:flex;flex-direction:column;gap:10px;min-width:0}.feedback-prompt{display:flex;flex-direction:column;gap:6px;min-width:0}.feedback-prompt .muted{overflow-wrap:anywhere}.text-button{display:inline-flex;align-items:center;border:0;border-radius:6px;padding:2px 4px;color:var(--nha-text-muted);background:transparent;font:inherit;font-size:12px;font-weight:650;text-decoration:underline;text-underline-offset:2px;cursor:pointer}.text-button:focus-visible{outline:3px solid color-mix(in srgb,var(--nha-focus) 80%,transparent);outline-offset:2px}.text-button:hover:not(:disabled){color:var(--nha-text)}.text-button:disabled{cursor:not-allowed;opacity:.55}.waiting-for{display:flex;align-items:center;gap:6px;margin:0;color:var(--nha-text-muted);font-size:12px;overflow-wrap:anywhere}.subject-agents{display:grid;gap:8px;margin:0;padding:0;list-style:none}.subject-agent{display:flex;flex-wrap:wrap;align-items:center;justify-content:space-between;gap:8px 12px;min-width:0;border:1px solid var(--nha-border);border-radius:var(--nha-radius-control);padding:10px 12px}.subject-agent-text{display:flex;flex-direction:column;gap:2px;min-width:0}.subject-agent-text strong{font-size:14px;overflow-wrap:anywhere}\n"], dependencies: [{ kind: "component", type: _NhAssistantIconComponent, selector: "nh-assistant-icon", inputs: ["name"] }, { kind: "component", type: NhAssistantAgentProposalsComponent, selector: "nh-assistant-agent-proposals", inputs: ["proposals", "canDecide", "decisionRights", "selectable", "holdClosedCards"], outputs: ["changed"] }, { kind: "pipe", type: TranslatePipe, name: "translate" }], changeDetection: i0.ChangeDetectionStrategy.OnPush }); }
|
|
392
|
+
}
|
|
393
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.33", ngImport: i0, type: NhAssistantAgentInboxComponent, decorators: [{
|
|
394
|
+
type: Component,
|
|
395
|
+
args: [{ selector: 'nh-assistant-agent-inbox', standalone: true, imports: [TranslatePipe, _NhAssistantIconComponent, NhAssistantAgentProposalsComponent], changeDetection: ChangeDetectionStrategy.OnPush, template: "<section class=\"section\" aria-labelledby=\"nh-assistant-agent-inbox-title\" [attr.aria-busy]=\"loading()\">\n <header class=\"section-header\">\n <div>\n <h3 id=\"nh-assistant-agent-inbox-title\">{{ 'nh-assistant.agent-runs.inbox.title' | translate }}</h3>\n <p class=\"muted\">{{ 'nh-assistant.agent-runs.inbox.description' | translate }}</p>\n </div>\n <button class=\"secondary\" type=\"button\" [disabled]=\"loading()\" (click)=\"load()\">\n <nh-assistant-icon name=\"refresh\" />{{ 'nh-assistant.agent-runs.refresh' | translate }}\n </button>\n </header>\n\n @if (loading() && items().length === 0 && !loaded()) {\n <p class=\"state\" role=\"status\">{{ 'nh-assistant.agent-runs.loading' | translate }}</p>\n } @else if (loadFailed()) {\n <div class=\"state\" role=\"alert\">\n <p>{{ 'nh-assistant.agent-runs.load-failed' | translate }}</p>\n <button class=\"secondary\" type=\"button\" (click)=\"load()\">{{ 'nh-assistant.agent-runs.retry' | translate }}</button>\n </div>\n } @else {\n <!-- Stays rendered when the list empties, so the optional feedback after a rejection remains. -->\n <nh-assistant-agent-proposals\n [proposals]=\"items()\"\n [canDecide]=\"true\"\n [selectable]=\"true\"\n [holdClosedCards]=\"true\"\n (changed)=\"load()\" />\n @if (items().length === 0) {\n <p class=\"state\">{{ 'nh-assistant.agent-runs.inbox.empty' | translate }}</p>\n }\n @if (pages() > 1) {\n <nav class=\"toolbar\" [attr.aria-label]=\"'nh-assistant.agent-runs.inbox.pages' | translate\">\n <button class=\"secondary\" type=\"button\" [disabled]=\"page() <= 1 || loading()\" (click)=\"goTo(page() - 1)\">\n {{ 'nh-assistant.agent-runs.inbox.previous' | translate }}\n </button>\n <span class=\"muted\">{{ 'nh-assistant.agent-runs.inbox.page' | translate: { page: page(), pages: pages() } }}</span>\n <button class=\"secondary\" type=\"button\" [disabled]=\"page() >= pages() || loading()\" (click)=\"goTo(page() + 1)\">\n {{ 'nh-assistant.agent-runs.inbox.next' | translate }}\n </button>\n </nav>\n }\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:block;min-width:0;color:var(--nha-text);font-family:var(--nha-font);font-size:14px}: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}.section{display:flex;flex-direction:column;gap:14px;min-width:0}.section-header{display:flex;flex-wrap:wrap;align-items:flex-start;justify-content:space-between;gap:12px}.section-header>div{min-width:0;max-width:72ch}h3{margin:0 0 4px;font-size:17px;font-weight:750}.muted{margin:0;color:var(--nha-text-muted);font-size:13px}.state{display:flex;flex-direction:column;align-items:flex-start;gap:10px;margin:0;border:1px dashed var(--nha-border);border-radius:var(--nha-radius);padding:18px;color:var(--nha-text-muted);font-size:13px}.state p{margin:0}.cards{display:grid;gap:10px;margin:0;padding:0;list-style:none}.card{display:flex;flex-direction:column;gap:8px;min-width:0;border:1px solid var(--nha-border);border-radius:var(--nha-radius);padding:12px 14px;background:var(--nha-surface)}.card.selected{border-color:var(--nha-accent, currentColor)}.card[tabindex]:focus-visible{outline:3px solid color-mix(in srgb,var(--nha-focus) 80%,transparent);outline-offset:2px}.card.closed{border-style:dashed}.closed-card{display:flex;flex-wrap:wrap;align-items:center;justify-content:space-between;gap:8px}.message.stale-explanation{overflow-wrap:anywhere;color:var(--nha-text);background:var(--nha-surface-strong)}.rationale{margin:0;overflow-wrap:anywhere;color:var(--nha-text-muted);font-size:13px}.card-header{display:flex;flex-wrap:wrap;align-items:center;gap:8px;min-width:0}.card-header strong{font-size:14px;overflow-wrap:anywhere}.card-actions{display:flex;flex-wrap:wrap;align-items:center;gap:8px}.meta{display:flex;flex-wrap:wrap;align-items:center;gap:6px 12px;color:var(--nha-text-muted);font-size:12px;overflow-wrap:anywhere}pre{max-height:220px;margin:0;overflow:auto;border-radius:var(--nha-radius-control);padding:8px 10px;background:var(--nha-surface-muted, rgba(127, 127, 127, .08));font-family:var(--nha-mono);font-size:12px;white-space:pre-wrap;overflow-wrap:anywhere}.summary{margin:0;font-size:13px;overflow-wrap:anywhere}.presentation-fields{display:grid;gap:6px;margin:0}.presentation-fields div{display:grid;grid-template-columns:minmax(90px,.4fr) minmax(0,1fr);gap:8px}.presentation-fields dt{color:var(--nha-text-muted);font-size:12px;font-weight:700;overflow-wrap:anywhere}.presentation-fields dd{margin:0;font-size:13px;overflow-wrap:anywhere}.technical-details{color:var(--nha-text-muted);font-size:12px}.technical-details summary{cursor:pointer;font-weight:700}.technical-details code{overflow-wrap:anywhere}.technical-details .label{margin:10px 0 4px;font-size:11px;font-weight:700;text-transform:uppercase;letter-spacing:.04em}.technical-details .targets{margin:0;padding-left:18px;overflow-wrap:anywhere}.tabs{display:flex;flex-wrap:wrap;gap:4px;border-bottom:1px solid var(--nha-border)}.tabs button{border:0;border-bottom:2px solid transparent;border-radius:0;padding:8px 12px;background:transparent;color:var(--nha-text-muted);font:inherit;cursor:pointer}.tabs button[aria-selected=true]{border-bottom-color:currentColor;color:var(--nha-text);font-weight:650}.toolbar{display:flex;flex-wrap:wrap;align-items:center;gap:8px}.reason{flex:1 1 200px;min-width:0}.select{display:inline-flex;align-items:center;gap:6px;font-size:12px}.proposal-list{display:flex;flex-direction:column;gap:10px;min-width:0}.feedback-prompt{display:flex;flex-direction:column;gap:6px;min-width:0}.feedback-prompt .muted{overflow-wrap:anywhere}.text-button{display:inline-flex;align-items:center;border:0;border-radius:6px;padding:2px 4px;color:var(--nha-text-muted);background:transparent;font:inherit;font-size:12px;font-weight:650;text-decoration:underline;text-underline-offset:2px;cursor:pointer}.text-button:focus-visible{outline:3px solid color-mix(in srgb,var(--nha-focus) 80%,transparent);outline-offset:2px}.text-button:hover:not(:disabled){color:var(--nha-text)}.text-button:disabled{cursor:not-allowed;opacity:.55}.waiting-for{display:flex;align-items:center;gap:6px;margin:0;color:var(--nha-text-muted);font-size:12px;overflow-wrap:anywhere}.subject-agents{display:grid;gap:8px;margin:0;padding:0;list-style:none}.subject-agent{display:flex;flex-wrap:wrap;align-items:center;justify-content:space-between;gap:8px 12px;min-width:0;border:1px solid var(--nha-border);border-radius:var(--nha-radius-control);padding:10px 12px}.subject-agent-text{display:flex;flex-direction:column;gap:2px;min-width:0}.subject-agent-text strong{font-size:14px;overflow-wrap:anywhere}\n"] }]
|
|
396
|
+
}], ctorParameters: () => [], propDecorators: { proposalList: [{ type: i0.ViewChild, args: [i0.forwardRef(() => NhAssistantAgentProposalsComponent), { isSignal: true }] }], agentId: [{ type: i0.Input, args: [{ isSignal: true, alias: "agentId", required: false }] }], subjectType: [{ type: i0.Input, args: [{ isSignal: true, alias: "subjectType", required: false }] }], itemsPerPage: [{ type: i0.Input, args: [{ isSignal: true, alias: "itemsPerPage", required: false }] }] } });
|
|
397
|
+
|
|
398
|
+
/**
|
|
399
|
+
* The files the agent's tools saved in a thread, every version newest first. Files of the
|
|
400
|
+
* agent's own grant that the viewer may not read are listed as shielded and cannot be downloaded.
|
|
401
|
+
* With live updates the list reloads by itself when a run or proposal of the thread changes.
|
|
402
|
+
*/
|
|
403
|
+
class NhAssistantAgentArtifactsComponent {
|
|
404
|
+
constructor() {
|
|
405
|
+
this.api = inject(NhAssistantAgentRunApiService);
|
|
406
|
+
this.document = inject(DOCUMENT);
|
|
407
|
+
this.conversationId = input.required(...(ngDevMode ? [{ debugName: "conversationId" }] : []));
|
|
408
|
+
this.loading = signal(true, ...(ngDevMode ? [{ debugName: "loading" }] : []));
|
|
409
|
+
this.loadFailed = signal(false, ...(ngDevMode ? [{ debugName: "loadFailed" }] : []));
|
|
410
|
+
this.downloadFailed = signal(false, ...(ngDevMode ? [{ debugName: "downloadFailed" }] : []));
|
|
411
|
+
this.artifacts = signal([], ...(ngDevMode ? [{ debugName: "artifacts" }] : []));
|
|
412
|
+
this.downloadingId = signal(null, ...(ngDevMode ? [{ debugName: "downloadingId" }] : []));
|
|
413
|
+
inject(DestroyRef).onDestroy(() => this.subscription?.unsubscribe());
|
|
414
|
+
effect(() => {
|
|
415
|
+
this.conversationId();
|
|
416
|
+
untracked(() => this.load());
|
|
417
|
+
});
|
|
418
|
+
_nhAssistantReloadOnAgentWork(change => change.conversationId === this.conversationId() && change.reason !== 'feedback', () => this.fetch(!this.loading() && !this.loadFailed()));
|
|
419
|
+
}
|
|
420
|
+
load() {
|
|
421
|
+
this.fetch(false);
|
|
422
|
+
}
|
|
423
|
+
async download(artifact) {
|
|
424
|
+
this.downloadingId.set(artifact.id);
|
|
425
|
+
this.downloadFailed.set(false);
|
|
426
|
+
try {
|
|
427
|
+
const blob = await this.api.downloadArtifact(this.conversationId(), artifact.id);
|
|
428
|
+
const url = URL.createObjectURL(blob);
|
|
429
|
+
const link = this.document.createElement('a');
|
|
430
|
+
link.href = url;
|
|
431
|
+
link.download = `${artifact.name}-v${artifact.version}`;
|
|
432
|
+
link.click();
|
|
433
|
+
URL.revokeObjectURL(url);
|
|
434
|
+
}
|
|
435
|
+
catch {
|
|
436
|
+
this.downloadFailed.set(true);
|
|
437
|
+
}
|
|
438
|
+
finally {
|
|
439
|
+
this.downloadingId.set(null);
|
|
440
|
+
}
|
|
441
|
+
}
|
|
442
|
+
/** A quiet load, after a live update, shows no loading state and keeps the files when it fails. */
|
|
443
|
+
fetch(quiet) {
|
|
444
|
+
if (!quiet) {
|
|
445
|
+
this.loading.set(true);
|
|
446
|
+
this.loadFailed.set(false);
|
|
447
|
+
}
|
|
448
|
+
this.subscription?.unsubscribe();
|
|
449
|
+
this.subscription = this.api.getArtifacts(this.conversationId()).subscribe({
|
|
450
|
+
next: artifacts => {
|
|
451
|
+
this.artifacts.set(artifacts);
|
|
452
|
+
this.loading.set(false);
|
|
453
|
+
this.loadFailed.set(false);
|
|
454
|
+
},
|
|
455
|
+
error: () => {
|
|
456
|
+
if (quiet) {
|
|
457
|
+
return;
|
|
458
|
+
}
|
|
459
|
+
this.loading.set(false);
|
|
460
|
+
this.loadFailed.set(true);
|
|
461
|
+
}
|
|
462
|
+
});
|
|
463
|
+
}
|
|
464
|
+
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.3.33", ngImport: i0, type: NhAssistantAgentArtifactsComponent, deps: [], target: i0.ɵɵFactoryTarget.Component }); }
|
|
465
|
+
static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "20.3.33", type: NhAssistantAgentArtifactsComponent, isStandalone: true, selector: "nh-assistant-agent-artifacts", inputs: { conversationId: { classPropertyName: "conversationId", publicName: "conversationId", isSignal: true, isRequired: true, transformFunction: null } }, ngImport: i0, template: "@if (downloadFailed()) {\n <p class=\"message error\" role=\"alert\"><nh-assistant-icon name=\"warning\" />{{ 'nh-assistant.agent-runs.artifacts.download-failed' | translate }}</p>\n}\n\n@if (loading()) {\n <p class=\"state\" role=\"status\">{{ 'nh-assistant.agent-runs.loading' | translate }}</p>\n} @else if (loadFailed()) {\n <div class=\"state\" role=\"alert\">\n <p>{{ 'nh-assistant.agent-runs.load-failed' | translate }}</p>\n <button class=\"secondary\" type=\"button\" (click)=\"load()\">{{ 'nh-assistant.agent-runs.retry' | translate }}</button>\n </div>\n} @else if (artifacts().length === 0) {\n <p class=\"state\">{{ 'nh-assistant.agent-runs.artifacts.empty' | translate }}</p>\n} @else {\n <ul class=\"cards\">\n @for (artifact of artifacts(); track artifact.id) {\n <li class=\"card\">\n <div class=\"card-header\">\n <strong>{{ artifact.name }}</strong>\n <span class=\"badge\">{{ 'nh-assistant.agent-runs.artifacts.version' | translate: { version: artifact.version } }}</span>\n @if (artifact.restricted) {\n <span class=\"badge warning\">{{ 'nh-assistant.agent-runs.artifacts.restricted' | translate }}</span>\n }\n </div>\n <div class=\"meta\">\n <span class=\"mono\">{{ artifact.contentType }}</span>\n <span>{{ 'nh-assistant.agent-runs.artifacts.size' | translate: { size: artifact.sizeBytes } }}</span>\n <span>{{ artifact.createdAt | date: 'short' }}</span>\n </div>\n @if (!artifact.restricted) {\n <div class=\"card-actions\">\n <button class=\"secondary\" type=\"button\" [disabled]=\"downloadingId() !== null\" (click)=\"download(artifact)\">\n <nh-assistant-icon name=\"page\" />{{ 'nh-assistant.agent-runs.artifacts.download' | translate }}\n </button>\n </div>\n }\n </li>\n }\n </ul>\n}\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;min-width:0;color:var(--nha-text);font-family:var(--nha-font);font-size:14px}: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}.section{display:flex;flex-direction:column;gap:14px;min-width:0}.section-header{display:flex;flex-wrap:wrap;align-items:flex-start;justify-content:space-between;gap:12px}.section-header>div{min-width:0;max-width:72ch}h3{margin:0 0 4px;font-size:17px;font-weight:750}.muted{margin:0;color:var(--nha-text-muted);font-size:13px}.state{display:flex;flex-direction:column;align-items:flex-start;gap:10px;margin:0;border:1px dashed var(--nha-border);border-radius:var(--nha-radius);padding:18px;color:var(--nha-text-muted);font-size:13px}.state p{margin:0}.cards{display:grid;gap:10px;margin:0;padding:0;list-style:none}.card{display:flex;flex-direction:column;gap:8px;min-width:0;border:1px solid var(--nha-border);border-radius:var(--nha-radius);padding:12px 14px;background:var(--nha-surface)}.card.selected{border-color:var(--nha-accent, currentColor)}.card[tabindex]:focus-visible{outline:3px solid color-mix(in srgb,var(--nha-focus) 80%,transparent);outline-offset:2px}.card.closed{border-style:dashed}.closed-card{display:flex;flex-wrap:wrap;align-items:center;justify-content:space-between;gap:8px}.message.stale-explanation{overflow-wrap:anywhere;color:var(--nha-text);background:var(--nha-surface-strong)}.rationale{margin:0;overflow-wrap:anywhere;color:var(--nha-text-muted);font-size:13px}.card-header{display:flex;flex-wrap:wrap;align-items:center;gap:8px;min-width:0}.card-header strong{font-size:14px;overflow-wrap:anywhere}.card-actions{display:flex;flex-wrap:wrap;align-items:center;gap:8px}.meta{display:flex;flex-wrap:wrap;align-items:center;gap:6px 12px;color:var(--nha-text-muted);font-size:12px;overflow-wrap:anywhere}pre{max-height:220px;margin:0;overflow:auto;border-radius:var(--nha-radius-control);padding:8px 10px;background:var(--nha-surface-muted, rgba(127, 127, 127, .08));font-family:var(--nha-mono);font-size:12px;white-space:pre-wrap;overflow-wrap:anywhere}.summary{margin:0;font-size:13px;overflow-wrap:anywhere}.presentation-fields{display:grid;gap:6px;margin:0}.presentation-fields div{display:grid;grid-template-columns:minmax(90px,.4fr) minmax(0,1fr);gap:8px}.presentation-fields dt{color:var(--nha-text-muted);font-size:12px;font-weight:700;overflow-wrap:anywhere}.presentation-fields dd{margin:0;font-size:13px;overflow-wrap:anywhere}.technical-details{color:var(--nha-text-muted);font-size:12px}.technical-details summary{cursor:pointer;font-weight:700}.technical-details code{overflow-wrap:anywhere}.technical-details .label{margin:10px 0 4px;font-size:11px;font-weight:700;text-transform:uppercase;letter-spacing:.04em}.technical-details .targets{margin:0;padding-left:18px;overflow-wrap:anywhere}.tabs{display:flex;flex-wrap:wrap;gap:4px;border-bottom:1px solid var(--nha-border)}.tabs button{border:0;border-bottom:2px solid transparent;border-radius:0;padding:8px 12px;background:transparent;color:var(--nha-text-muted);font:inherit;cursor:pointer}.tabs button[aria-selected=true]{border-bottom-color:currentColor;color:var(--nha-text);font-weight:650}.toolbar{display:flex;flex-wrap:wrap;align-items:center;gap:8px}.reason{flex:1 1 200px;min-width:0}.select{display:inline-flex;align-items:center;gap:6px;font-size:12px}.proposal-list{display:flex;flex-direction:column;gap:10px;min-width:0}.feedback-prompt{display:flex;flex-direction:column;gap:6px;min-width:0}.feedback-prompt .muted{overflow-wrap:anywhere}.text-button{display:inline-flex;align-items:center;border:0;border-radius:6px;padding:2px 4px;color:var(--nha-text-muted);background:transparent;font:inherit;font-size:12px;font-weight:650;text-decoration:underline;text-underline-offset:2px;cursor:pointer}.text-button:focus-visible{outline:3px solid color-mix(in srgb,var(--nha-focus) 80%,transparent);outline-offset:2px}.text-button:hover:not(:disabled){color:var(--nha-text)}.text-button:disabled{cursor:not-allowed;opacity:.55}.waiting-for{display:flex;align-items:center;gap:6px;margin:0;color:var(--nha-text-muted);font-size:12px;overflow-wrap:anywhere}.subject-agents{display:grid;gap:8px;margin:0;padding:0;list-style:none}.subject-agent{display:flex;flex-wrap:wrap;align-items:center;justify-content:space-between;gap:8px 12px;min-width:0;border:1px solid var(--nha-border);border-radius:var(--nha-radius-control);padding:10px 12px}.subject-agent-text{display:flex;flex-direction:column;gap:2px;min-width:0}.subject-agent-text strong{font-size:14px;overflow-wrap:anywhere}\n"], dependencies: [{ kind: "component", type: _NhAssistantIconComponent, selector: "nh-assistant-icon", inputs: ["name"] }, { kind: "pipe", type: DatePipe, name: "date" }, { kind: "pipe", type: TranslatePipe, name: "translate" }], changeDetection: i0.ChangeDetectionStrategy.OnPush }); }
|
|
466
|
+
}
|
|
467
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.33", ngImport: i0, type: NhAssistantAgentArtifactsComponent, decorators: [{
|
|
468
|
+
type: Component,
|
|
469
|
+
args: [{ selector: 'nh-assistant-agent-artifacts', standalone: true, imports: [DatePipe, TranslatePipe, _NhAssistantIconComponent], changeDetection: ChangeDetectionStrategy.OnPush, template: "@if (downloadFailed()) {\n <p class=\"message error\" role=\"alert\"><nh-assistant-icon name=\"warning\" />{{ 'nh-assistant.agent-runs.artifacts.download-failed' | translate }}</p>\n}\n\n@if (loading()) {\n <p class=\"state\" role=\"status\">{{ 'nh-assistant.agent-runs.loading' | translate }}</p>\n} @else if (loadFailed()) {\n <div class=\"state\" role=\"alert\">\n <p>{{ 'nh-assistant.agent-runs.load-failed' | translate }}</p>\n <button class=\"secondary\" type=\"button\" (click)=\"load()\">{{ 'nh-assistant.agent-runs.retry' | translate }}</button>\n </div>\n} @else if (artifacts().length === 0) {\n <p class=\"state\">{{ 'nh-assistant.agent-runs.artifacts.empty' | translate }}</p>\n} @else {\n <ul class=\"cards\">\n @for (artifact of artifacts(); track artifact.id) {\n <li class=\"card\">\n <div class=\"card-header\">\n <strong>{{ artifact.name }}</strong>\n <span class=\"badge\">{{ 'nh-assistant.agent-runs.artifacts.version' | translate: { version: artifact.version } }}</span>\n @if (artifact.restricted) {\n <span class=\"badge warning\">{{ 'nh-assistant.agent-runs.artifacts.restricted' | translate }}</span>\n }\n </div>\n <div class=\"meta\">\n <span class=\"mono\">{{ artifact.contentType }}</span>\n <span>{{ 'nh-assistant.agent-runs.artifacts.size' | translate: { size: artifact.sizeBytes } }}</span>\n <span>{{ artifact.createdAt | date: 'short' }}</span>\n </div>\n @if (!artifact.restricted) {\n <div class=\"card-actions\">\n <button class=\"secondary\" type=\"button\" [disabled]=\"downloadingId() !== null\" (click)=\"download(artifact)\">\n <nh-assistant-icon name=\"page\" />{{ 'nh-assistant.agent-runs.artifacts.download' | translate }}\n </button>\n </div>\n }\n </li>\n }\n </ul>\n}\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;min-width:0;color:var(--nha-text);font-family:var(--nha-font);font-size:14px}: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}.section{display:flex;flex-direction:column;gap:14px;min-width:0}.section-header{display:flex;flex-wrap:wrap;align-items:flex-start;justify-content:space-between;gap:12px}.section-header>div{min-width:0;max-width:72ch}h3{margin:0 0 4px;font-size:17px;font-weight:750}.muted{margin:0;color:var(--nha-text-muted);font-size:13px}.state{display:flex;flex-direction:column;align-items:flex-start;gap:10px;margin:0;border:1px dashed var(--nha-border);border-radius:var(--nha-radius);padding:18px;color:var(--nha-text-muted);font-size:13px}.state p{margin:0}.cards{display:grid;gap:10px;margin:0;padding:0;list-style:none}.card{display:flex;flex-direction:column;gap:8px;min-width:0;border:1px solid var(--nha-border);border-radius:var(--nha-radius);padding:12px 14px;background:var(--nha-surface)}.card.selected{border-color:var(--nha-accent, currentColor)}.card[tabindex]:focus-visible{outline:3px solid color-mix(in srgb,var(--nha-focus) 80%,transparent);outline-offset:2px}.card.closed{border-style:dashed}.closed-card{display:flex;flex-wrap:wrap;align-items:center;justify-content:space-between;gap:8px}.message.stale-explanation{overflow-wrap:anywhere;color:var(--nha-text);background:var(--nha-surface-strong)}.rationale{margin:0;overflow-wrap:anywhere;color:var(--nha-text-muted);font-size:13px}.card-header{display:flex;flex-wrap:wrap;align-items:center;gap:8px;min-width:0}.card-header strong{font-size:14px;overflow-wrap:anywhere}.card-actions{display:flex;flex-wrap:wrap;align-items:center;gap:8px}.meta{display:flex;flex-wrap:wrap;align-items:center;gap:6px 12px;color:var(--nha-text-muted);font-size:12px;overflow-wrap:anywhere}pre{max-height:220px;margin:0;overflow:auto;border-radius:var(--nha-radius-control);padding:8px 10px;background:var(--nha-surface-muted, rgba(127, 127, 127, .08));font-family:var(--nha-mono);font-size:12px;white-space:pre-wrap;overflow-wrap:anywhere}.summary{margin:0;font-size:13px;overflow-wrap:anywhere}.presentation-fields{display:grid;gap:6px;margin:0}.presentation-fields div{display:grid;grid-template-columns:minmax(90px,.4fr) minmax(0,1fr);gap:8px}.presentation-fields dt{color:var(--nha-text-muted);font-size:12px;font-weight:700;overflow-wrap:anywhere}.presentation-fields dd{margin:0;font-size:13px;overflow-wrap:anywhere}.technical-details{color:var(--nha-text-muted);font-size:12px}.technical-details summary{cursor:pointer;font-weight:700}.technical-details code{overflow-wrap:anywhere}.technical-details .label{margin:10px 0 4px;font-size:11px;font-weight:700;text-transform:uppercase;letter-spacing:.04em}.technical-details .targets{margin:0;padding-left:18px;overflow-wrap:anywhere}.tabs{display:flex;flex-wrap:wrap;gap:4px;border-bottom:1px solid var(--nha-border)}.tabs button{border:0;border-bottom:2px solid transparent;border-radius:0;padding:8px 12px;background:transparent;color:var(--nha-text-muted);font:inherit;cursor:pointer}.tabs button[aria-selected=true]{border-bottom-color:currentColor;color:var(--nha-text);font-weight:650}.toolbar{display:flex;flex-wrap:wrap;align-items:center;gap:8px}.reason{flex:1 1 200px;min-width:0}.select{display:inline-flex;align-items:center;gap:6px;font-size:12px}.proposal-list{display:flex;flex-direction:column;gap:10px;min-width:0}.feedback-prompt{display:flex;flex-direction:column;gap:6px;min-width:0}.feedback-prompt .muted{overflow-wrap:anywhere}.text-button{display:inline-flex;align-items:center;border:0;border-radius:6px;padding:2px 4px;color:var(--nha-text-muted);background:transparent;font:inherit;font-size:12px;font-weight:650;text-decoration:underline;text-underline-offset:2px;cursor:pointer}.text-button:focus-visible{outline:3px solid color-mix(in srgb,var(--nha-focus) 80%,transparent);outline-offset:2px}.text-button:hover:not(:disabled){color:var(--nha-text)}.text-button:disabled{cursor:not-allowed;opacity:.55}.waiting-for{display:flex;align-items:center;gap:6px;margin:0;color:var(--nha-text-muted);font-size:12px;overflow-wrap:anywhere}.subject-agents{display:grid;gap:8px;margin:0;padding:0;list-style:none}.subject-agent{display:flex;flex-wrap:wrap;align-items:center;justify-content:space-between;gap:8px 12px;min-width:0;border:1px solid var(--nha-border);border-radius:var(--nha-radius-control);padding:10px 12px}.subject-agent-text{display:flex;flex-direction:column;gap:2px;min-width:0}.subject-agent-text strong{font-size:14px;overflow-wrap:anywhere}\n"] }]
|
|
470
|
+
}], ctorParameters: () => [], propDecorators: { conversationId: [{ type: i0.Input, args: [{ isSignal: true, alias: "conversationId", required: true }] }] } });
|
|
471
|
+
|
|
472
|
+
/**
|
|
473
|
+
* Who consulted the thread's agent through another assistant, newest first: the person whose rights
|
|
474
|
+
* were used, the asking assistant, the outcome, the usage and the proposals left for approvers. The
|
|
475
|
+
* question and the answer stay in the asking conversation and are never shown here. With live
|
|
476
|
+
* updates the list reloads by itself when a run or proposal of the thread changes.
|
|
477
|
+
*/
|
|
478
|
+
class NhAssistantAgentConsultationsComponent {
|
|
479
|
+
constructor() {
|
|
480
|
+
this.api = inject(NhAssistantAgentRunApiService);
|
|
481
|
+
this.conversationId = input.required(...(ngDevMode ? [{ debugName: "conversationId" }] : []));
|
|
482
|
+
this.loading = signal(true, ...(ngDevMode ? [{ debugName: "loading" }] : []));
|
|
483
|
+
this.loadFailed = signal(false, ...(ngDevMode ? [{ debugName: "loadFailed" }] : []));
|
|
484
|
+
this.consultations = signal([], ...(ngDevMode ? [{ debugName: "consultations" }] : []));
|
|
485
|
+
this.total = signal(0, ...(ngDevMode ? [{ debugName: "total" }] : []));
|
|
486
|
+
inject(DestroyRef).onDestroy(() => this.subscription?.unsubscribe());
|
|
487
|
+
effect(() => {
|
|
488
|
+
this.conversationId();
|
|
489
|
+
untracked(() => this.load());
|
|
490
|
+
});
|
|
491
|
+
_nhAssistantReloadOnAgentWork(change => change.conversationId === this.conversationId() && change.reason !== 'feedback', () => this.fetch(!this.loading() && !this.loadFailed()));
|
|
492
|
+
}
|
|
493
|
+
load() {
|
|
494
|
+
this.fetch(false);
|
|
495
|
+
}
|
|
496
|
+
/** A quiet load, after a live update, shows no loading state and keeps the list when it fails. */
|
|
497
|
+
fetch(quiet) {
|
|
498
|
+
if (!quiet) {
|
|
499
|
+
this.loading.set(true);
|
|
500
|
+
this.loadFailed.set(false);
|
|
501
|
+
}
|
|
502
|
+
this.subscription?.unsubscribe();
|
|
503
|
+
this.subscription = this.api.getConsultations(this.conversationId()).subscribe({
|
|
504
|
+
next: list => {
|
|
505
|
+
this.consultations.set(list.items);
|
|
506
|
+
this.total.set(list.total);
|
|
507
|
+
this.loading.set(false);
|
|
508
|
+
this.loadFailed.set(false);
|
|
509
|
+
},
|
|
510
|
+
error: () => {
|
|
511
|
+
if (quiet) {
|
|
512
|
+
return;
|
|
513
|
+
}
|
|
514
|
+
this.loading.set(false);
|
|
515
|
+
this.loadFailed.set(true);
|
|
516
|
+
}
|
|
517
|
+
});
|
|
518
|
+
}
|
|
519
|
+
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.3.33", ngImport: i0, type: NhAssistantAgentConsultationsComponent, deps: [], target: i0.ɵɵFactoryTarget.Component }); }
|
|
520
|
+
static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "20.3.33", type: NhAssistantAgentConsultationsComponent, isStandalone: true, selector: "nh-assistant-agent-consultations", inputs: { conversationId: { classPropertyName: "conversationId", publicName: "conversationId", isSignal: true, isRequired: true, transformFunction: null } }, ngImport: i0, template: "@if (loading() && consultations().length === 0) {\n <p class=\"state\" role=\"status\">{{ 'nh-assistant.agent-runs.loading' | translate }}</p>\n} @else if (loadFailed()) {\n <div class=\"state\" role=\"alert\">\n <p>{{ 'nh-assistant.agent-runs.load-failed' | translate }}</p>\n <button class=\"secondary\" type=\"button\" (click)=\"load()\">{{ 'nh-assistant.agent-runs.retry' | translate }}</button>\n </div>\n} @else if (consultations().length === 0) {\n <p class=\"state\">{{ 'nh-assistant.agent-runs.consultation.empty' | translate }}</p>\n} @else {\n <p class=\"muted\">{{ 'nh-assistant.agent-runs.consultation.private' | translate }}</p>\n <ol class=\"cards\" [attr.aria-label]=\"'nh-assistant.agent-runs.thread.tabs.consultations' | translate\">\n @for (consultation of consultations(); track consultation.id) {\n <li class=\"card\">\n <div class=\"card-header\">\n <strong>{{ consultation.createdAt | date: 'short' }}</strong>\n <span\n class=\"badge\"\n [class.success]=\"consultation.status === 'completed'\"\n [class.warning]=\"consultation.status === 'running'\"\n [class.danger]=\"consultation.status === 'failed'\">\n {{ 'nh-assistant.agent-runs.consultation.status.' + consultation.status | translate }}\n </span>\n <span>\n {{ 'nh-assistant.agent-runs.consultation.asked-by' | translate: { name: consultation.askerDisplayName ?? consultation.askerActorId } }}\n @if (consultation.askingAgentId; as agentId) {\n {{ 'nh-assistant.agent-runs.consultation.through' | translate: { agent: (['nh-assistant.agents.' + agentId + '.name'] | nhAssistantTranslate: agentId) } }}\n }\n </span>\n @if (consultation.depth > 1) {\n <span class=\"badge\">{{ 'nh-assistant.agent-runs.consultation.depth' | translate: { depth: consultation.depth } }}</span>\n }\n </div>\n <div class=\"meta\">\n <span>{{ 'nh-assistant.agent-runs.run.tool-calls' | translate: { count: consultation.toolCalls } }}</span>\n <span>{{ 'nh-assistant.agent-runs.run.tokens' | translate: { count: consultation.inputTokens + consultation.outputTokens } }}</span>\n <span>{{ 'nh-assistant.agent-runs.run.proposals' | translate: { count: consultation.proposalCount } }}</span>\n @if (consultation.failureCode; as code) {\n <span><nh-assistant-icon name=\"warning\" />{{ ['nh-assistant.errors.' + code] | nhAssistantTranslate: code }}</span>\n }\n </div>\n </li>\n }\n </ol>\n @if (total() > consultations().length) {\n <p class=\"muted\">{{ 'nh-assistant.agent-runs.consultation.more' | translate: { count: total() - consultations().length } }}</p>\n }\n}\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;min-width:0;color:var(--nha-text);font-family:var(--nha-font);font-size:14px}: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}.section{display:flex;flex-direction:column;gap:14px;min-width:0}.section-header{display:flex;flex-wrap:wrap;align-items:flex-start;justify-content:space-between;gap:12px}.section-header>div{min-width:0;max-width:72ch}h3{margin:0 0 4px;font-size:17px;font-weight:750}.muted{margin:0;color:var(--nha-text-muted);font-size:13px}.state{display:flex;flex-direction:column;align-items:flex-start;gap:10px;margin:0;border:1px dashed var(--nha-border);border-radius:var(--nha-radius);padding:18px;color:var(--nha-text-muted);font-size:13px}.state p{margin:0}.cards{display:grid;gap:10px;margin:0;padding:0;list-style:none}.card{display:flex;flex-direction:column;gap:8px;min-width:0;border:1px solid var(--nha-border);border-radius:var(--nha-radius);padding:12px 14px;background:var(--nha-surface)}.card.selected{border-color:var(--nha-accent, currentColor)}.card[tabindex]:focus-visible{outline:3px solid color-mix(in srgb,var(--nha-focus) 80%,transparent);outline-offset:2px}.card.closed{border-style:dashed}.closed-card{display:flex;flex-wrap:wrap;align-items:center;justify-content:space-between;gap:8px}.message.stale-explanation{overflow-wrap:anywhere;color:var(--nha-text);background:var(--nha-surface-strong)}.rationale{margin:0;overflow-wrap:anywhere;color:var(--nha-text-muted);font-size:13px}.card-header{display:flex;flex-wrap:wrap;align-items:center;gap:8px;min-width:0}.card-header strong{font-size:14px;overflow-wrap:anywhere}.card-actions{display:flex;flex-wrap:wrap;align-items:center;gap:8px}.meta{display:flex;flex-wrap:wrap;align-items:center;gap:6px 12px;color:var(--nha-text-muted);font-size:12px;overflow-wrap:anywhere}pre{max-height:220px;margin:0;overflow:auto;border-radius:var(--nha-radius-control);padding:8px 10px;background:var(--nha-surface-muted, rgba(127, 127, 127, .08));font-family:var(--nha-mono);font-size:12px;white-space:pre-wrap;overflow-wrap:anywhere}.summary{margin:0;font-size:13px;overflow-wrap:anywhere}.presentation-fields{display:grid;gap:6px;margin:0}.presentation-fields div{display:grid;grid-template-columns:minmax(90px,.4fr) minmax(0,1fr);gap:8px}.presentation-fields dt{color:var(--nha-text-muted);font-size:12px;font-weight:700;overflow-wrap:anywhere}.presentation-fields dd{margin:0;font-size:13px;overflow-wrap:anywhere}.technical-details{color:var(--nha-text-muted);font-size:12px}.technical-details summary{cursor:pointer;font-weight:700}.technical-details code{overflow-wrap:anywhere}.technical-details .label{margin:10px 0 4px;font-size:11px;font-weight:700;text-transform:uppercase;letter-spacing:.04em}.technical-details .targets{margin:0;padding-left:18px;overflow-wrap:anywhere}.tabs{display:flex;flex-wrap:wrap;gap:4px;border-bottom:1px solid var(--nha-border)}.tabs button{border:0;border-bottom:2px solid transparent;border-radius:0;padding:8px 12px;background:transparent;color:var(--nha-text-muted);font:inherit;cursor:pointer}.tabs button[aria-selected=true]{border-bottom-color:currentColor;color:var(--nha-text);font-weight:650}.toolbar{display:flex;flex-wrap:wrap;align-items:center;gap:8px}.reason{flex:1 1 200px;min-width:0}.select{display:inline-flex;align-items:center;gap:6px;font-size:12px}.proposal-list{display:flex;flex-direction:column;gap:10px;min-width:0}.feedback-prompt{display:flex;flex-direction:column;gap:6px;min-width:0}.feedback-prompt .muted{overflow-wrap:anywhere}.text-button{display:inline-flex;align-items:center;border:0;border-radius:6px;padding:2px 4px;color:var(--nha-text-muted);background:transparent;font:inherit;font-size:12px;font-weight:650;text-decoration:underline;text-underline-offset:2px;cursor:pointer}.text-button:focus-visible{outline:3px solid color-mix(in srgb,var(--nha-focus) 80%,transparent);outline-offset:2px}.text-button:hover:not(:disabled){color:var(--nha-text)}.text-button:disabled{cursor:not-allowed;opacity:.55}.waiting-for{display:flex;align-items:center;gap:6px;margin:0;color:var(--nha-text-muted);font-size:12px;overflow-wrap:anywhere}.subject-agents{display:grid;gap:8px;margin:0;padding:0;list-style:none}.subject-agent{display:flex;flex-wrap:wrap;align-items:center;justify-content:space-between;gap:8px 12px;min-width:0;border:1px solid var(--nha-border);border-radius:var(--nha-radius-control);padding:10px 12px}.subject-agent-text{display:flex;flex-direction:column;gap:2px;min-width:0}.subject-agent-text strong{font-size:14px;overflow-wrap:anywhere}\n"], dependencies: [{ kind: "component", type: _NhAssistantIconComponent, selector: "nh-assistant-icon", inputs: ["name"] }, { kind: "pipe", type: DatePipe, name: "date" }, { kind: "pipe", type: TranslatePipe, name: "translate" }, { kind: "pipe", type: _NhAssistantTranslatePipe, name: "nhAssistantTranslate" }], changeDetection: i0.ChangeDetectionStrategy.OnPush }); }
|
|
521
|
+
}
|
|
522
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.33", ngImport: i0, type: NhAssistantAgentConsultationsComponent, decorators: [{
|
|
523
|
+
type: Component,
|
|
524
|
+
args: [{ selector: 'nh-assistant-agent-consultations', standalone: true, imports: [DatePipe, TranslatePipe, _NhAssistantTranslatePipe, _NhAssistantIconComponent], changeDetection: ChangeDetectionStrategy.OnPush, template: "@if (loading() && consultations().length === 0) {\n <p class=\"state\" role=\"status\">{{ 'nh-assistant.agent-runs.loading' | translate }}</p>\n} @else if (loadFailed()) {\n <div class=\"state\" role=\"alert\">\n <p>{{ 'nh-assistant.agent-runs.load-failed' | translate }}</p>\n <button class=\"secondary\" type=\"button\" (click)=\"load()\">{{ 'nh-assistant.agent-runs.retry' | translate }}</button>\n </div>\n} @else if (consultations().length === 0) {\n <p class=\"state\">{{ 'nh-assistant.agent-runs.consultation.empty' | translate }}</p>\n} @else {\n <p class=\"muted\">{{ 'nh-assistant.agent-runs.consultation.private' | translate }}</p>\n <ol class=\"cards\" [attr.aria-label]=\"'nh-assistant.agent-runs.thread.tabs.consultations' | translate\">\n @for (consultation of consultations(); track consultation.id) {\n <li class=\"card\">\n <div class=\"card-header\">\n <strong>{{ consultation.createdAt | date: 'short' }}</strong>\n <span\n class=\"badge\"\n [class.success]=\"consultation.status === 'completed'\"\n [class.warning]=\"consultation.status === 'running'\"\n [class.danger]=\"consultation.status === 'failed'\">\n {{ 'nh-assistant.agent-runs.consultation.status.' + consultation.status | translate }}\n </span>\n <span>\n {{ 'nh-assistant.agent-runs.consultation.asked-by' | translate: { name: consultation.askerDisplayName ?? consultation.askerActorId } }}\n @if (consultation.askingAgentId; as agentId) {\n {{ 'nh-assistant.agent-runs.consultation.through' | translate: { agent: (['nh-assistant.agents.' + agentId + '.name'] | nhAssistantTranslate: agentId) } }}\n }\n </span>\n @if (consultation.depth > 1) {\n <span class=\"badge\">{{ 'nh-assistant.agent-runs.consultation.depth' | translate: { depth: consultation.depth } }}</span>\n }\n </div>\n <div class=\"meta\">\n <span>{{ 'nh-assistant.agent-runs.run.tool-calls' | translate: { count: consultation.toolCalls } }}</span>\n <span>{{ 'nh-assistant.agent-runs.run.tokens' | translate: { count: consultation.inputTokens + consultation.outputTokens } }}</span>\n <span>{{ 'nh-assistant.agent-runs.run.proposals' | translate: { count: consultation.proposalCount } }}</span>\n @if (consultation.failureCode; as code) {\n <span><nh-assistant-icon name=\"warning\" />{{ ['nh-assistant.errors.' + code] | nhAssistantTranslate: code }}</span>\n }\n </div>\n </li>\n }\n </ol>\n @if (total() > consultations().length) {\n <p class=\"muted\">{{ 'nh-assistant.agent-runs.consultation.more' | translate: { count: total() - consultations().length } }}</p>\n }\n}\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;min-width:0;color:var(--nha-text);font-family:var(--nha-font);font-size:14px}: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}.section{display:flex;flex-direction:column;gap:14px;min-width:0}.section-header{display:flex;flex-wrap:wrap;align-items:flex-start;justify-content:space-between;gap:12px}.section-header>div{min-width:0;max-width:72ch}h3{margin:0 0 4px;font-size:17px;font-weight:750}.muted{margin:0;color:var(--nha-text-muted);font-size:13px}.state{display:flex;flex-direction:column;align-items:flex-start;gap:10px;margin:0;border:1px dashed var(--nha-border);border-radius:var(--nha-radius);padding:18px;color:var(--nha-text-muted);font-size:13px}.state p{margin:0}.cards{display:grid;gap:10px;margin:0;padding:0;list-style:none}.card{display:flex;flex-direction:column;gap:8px;min-width:0;border:1px solid var(--nha-border);border-radius:var(--nha-radius);padding:12px 14px;background:var(--nha-surface)}.card.selected{border-color:var(--nha-accent, currentColor)}.card[tabindex]:focus-visible{outline:3px solid color-mix(in srgb,var(--nha-focus) 80%,transparent);outline-offset:2px}.card.closed{border-style:dashed}.closed-card{display:flex;flex-wrap:wrap;align-items:center;justify-content:space-between;gap:8px}.message.stale-explanation{overflow-wrap:anywhere;color:var(--nha-text);background:var(--nha-surface-strong)}.rationale{margin:0;overflow-wrap:anywhere;color:var(--nha-text-muted);font-size:13px}.card-header{display:flex;flex-wrap:wrap;align-items:center;gap:8px;min-width:0}.card-header strong{font-size:14px;overflow-wrap:anywhere}.card-actions{display:flex;flex-wrap:wrap;align-items:center;gap:8px}.meta{display:flex;flex-wrap:wrap;align-items:center;gap:6px 12px;color:var(--nha-text-muted);font-size:12px;overflow-wrap:anywhere}pre{max-height:220px;margin:0;overflow:auto;border-radius:var(--nha-radius-control);padding:8px 10px;background:var(--nha-surface-muted, rgba(127, 127, 127, .08));font-family:var(--nha-mono);font-size:12px;white-space:pre-wrap;overflow-wrap:anywhere}.summary{margin:0;font-size:13px;overflow-wrap:anywhere}.presentation-fields{display:grid;gap:6px;margin:0}.presentation-fields div{display:grid;grid-template-columns:minmax(90px,.4fr) minmax(0,1fr);gap:8px}.presentation-fields dt{color:var(--nha-text-muted);font-size:12px;font-weight:700;overflow-wrap:anywhere}.presentation-fields dd{margin:0;font-size:13px;overflow-wrap:anywhere}.technical-details{color:var(--nha-text-muted);font-size:12px}.technical-details summary{cursor:pointer;font-weight:700}.technical-details code{overflow-wrap:anywhere}.technical-details .label{margin:10px 0 4px;font-size:11px;font-weight:700;text-transform:uppercase;letter-spacing:.04em}.technical-details .targets{margin:0;padding-left:18px;overflow-wrap:anywhere}.tabs{display:flex;flex-wrap:wrap;gap:4px;border-bottom:1px solid var(--nha-border)}.tabs button{border:0;border-bottom:2px solid transparent;border-radius:0;padding:8px 12px;background:transparent;color:var(--nha-text-muted);font:inherit;cursor:pointer}.tabs button[aria-selected=true]{border-bottom-color:currentColor;color:var(--nha-text);font-weight:650}.toolbar{display:flex;flex-wrap:wrap;align-items:center;gap:8px}.reason{flex:1 1 200px;min-width:0}.select{display:inline-flex;align-items:center;gap:6px;font-size:12px}.proposal-list{display:flex;flex-direction:column;gap:10px;min-width:0}.feedback-prompt{display:flex;flex-direction:column;gap:6px;min-width:0}.feedback-prompt .muted{overflow-wrap:anywhere}.text-button{display:inline-flex;align-items:center;border:0;border-radius:6px;padding:2px 4px;color:var(--nha-text-muted);background:transparent;font:inherit;font-size:12px;font-weight:650;text-decoration:underline;text-underline-offset:2px;cursor:pointer}.text-button:focus-visible{outline:3px solid color-mix(in srgb,var(--nha-focus) 80%,transparent);outline-offset:2px}.text-button:hover:not(:disabled){color:var(--nha-text)}.text-button:disabled{cursor:not-allowed;opacity:.55}.waiting-for{display:flex;align-items:center;gap:6px;margin:0;color:var(--nha-text-muted);font-size:12px;overflow-wrap:anywhere}.subject-agents{display:grid;gap:8px;margin:0;padding:0;list-style:none}.subject-agent{display:flex;flex-wrap:wrap;align-items:center;justify-content:space-between;gap:8px 12px;min-width:0;border:1px solid var(--nha-border);border-radius:var(--nha-radius-control);padding:10px 12px}.subject-agent-text{display:flex;flex-direction:column;gap:2px;min-width:0}.subject-agent-text strong{font-size:14px;overflow-wrap:anywhere}\n"] }]
|
|
525
|
+
}], ctorParameters: () => [], propDecorators: { conversationId: [{ type: i0.Input, args: [{ isSignal: true, alias: "conversationId", required: true }] }] } });
|
|
526
|
+
|
|
527
|
+
/**
|
|
528
|
+
* The working memory of an agent about the subject of a thread, read-only. The agent keeps it
|
|
529
|
+
* up to date itself; it is shown so that people can see what the agent remembers. With live
|
|
530
|
+
* updates it reloads by itself when a run of the thread changes.
|
|
531
|
+
*/
|
|
532
|
+
class NhAssistantAgentMemoryComponent {
|
|
533
|
+
constructor() {
|
|
534
|
+
this.api = inject(NhAssistantAgentRunApiService);
|
|
535
|
+
this.conversationId = input.required(...(ngDevMode ? [{ debugName: "conversationId" }] : []));
|
|
536
|
+
this.loading = signal(true, ...(ngDevMode ? [{ debugName: "loading" }] : []));
|
|
537
|
+
this.loadFailed = signal(false, ...(ngDevMode ? [{ debugName: "loadFailed" }] : []));
|
|
538
|
+
this.memory = signal(null, ...(ngDevMode ? [{ debugName: "memory" }] : []));
|
|
539
|
+
this.formatted = computed(() => {
|
|
540
|
+
const value = this.memory()?.memory;
|
|
541
|
+
return value === null || value === undefined ? null : JSON.stringify(value, null, 2);
|
|
542
|
+
}, ...(ngDevMode ? [{ debugName: "formatted" }] : []));
|
|
543
|
+
inject(DestroyRef).onDestroy(() => this.subscription?.unsubscribe());
|
|
544
|
+
effect(() => {
|
|
545
|
+
this.conversationId();
|
|
546
|
+
untracked(() => this.load());
|
|
547
|
+
});
|
|
548
|
+
// Only runs write the working memory.
|
|
549
|
+
_nhAssistantReloadOnAgentWork(change => change.conversationId === this.conversationId() && change.reason === 'run', () => this.fetch(!this.loading() && !this.loadFailed()));
|
|
550
|
+
}
|
|
551
|
+
load() {
|
|
552
|
+
this.fetch(false);
|
|
553
|
+
}
|
|
554
|
+
/** A quiet load, after a live update, shows no loading state and keeps the memory when it fails. */
|
|
555
|
+
fetch(quiet) {
|
|
556
|
+
if (!quiet) {
|
|
557
|
+
this.loading.set(true);
|
|
558
|
+
this.loadFailed.set(false);
|
|
559
|
+
}
|
|
560
|
+
this.subscription?.unsubscribe();
|
|
561
|
+
this.subscription = this.api.getMemory(this.conversationId()).subscribe({
|
|
562
|
+
next: memory => {
|
|
563
|
+
this.memory.set(memory);
|
|
564
|
+
this.loading.set(false);
|
|
565
|
+
this.loadFailed.set(false);
|
|
566
|
+
},
|
|
567
|
+
error: () => {
|
|
568
|
+
if (quiet) {
|
|
569
|
+
return;
|
|
570
|
+
}
|
|
571
|
+
this.loading.set(false);
|
|
572
|
+
this.loadFailed.set(true);
|
|
573
|
+
}
|
|
574
|
+
});
|
|
575
|
+
}
|
|
576
|
+
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.3.33", ngImport: i0, type: NhAssistantAgentMemoryComponent, deps: [], target: i0.ɵɵFactoryTarget.Component }); }
|
|
577
|
+
static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "20.3.33", type: NhAssistantAgentMemoryComponent, isStandalone: true, selector: "nh-assistant-agent-memory", inputs: { conversationId: { classPropertyName: "conversationId", publicName: "conversationId", isSignal: true, isRequired: true, transformFunction: null } }, ngImport: i0, template: "@if (loading()) {\n <p class=\"state\" role=\"status\">{{ 'nh-assistant.agent-runs.loading' | translate }}</p>\n} @else if (loadFailed()) {\n <div class=\"state\" role=\"alert\">\n <p>{{ 'nh-assistant.agent-runs.load-failed' | translate }}</p>\n <button class=\"secondary\" type=\"button\" (click)=\"load()\">{{ 'nh-assistant.agent-runs.retry' | translate }}</button>\n </div>\n} @else if (!memory()?.configured) {\n <p class=\"state\">{{ 'nh-assistant.agent-runs.memory.not-configured' | translate }}</p>\n} @else if (formatted(); as json) {\n <div class=\"section\">\n <div class=\"meta\">\n <span>{{ 'nh-assistant.agent-runs.memory.version' | translate: { version: memory()!.schemaVersion } }}</span>\n @if (memory()!.updatedAt; as updatedAt) {\n <span>{{ 'nh-assistant.agent-runs.memory.updated' | translate: { date: (updatedAt | date: 'short') } }}</span>\n }\n </div>\n <pre [attr.aria-label]=\"'nh-assistant.agent-runs.thread.tabs.memory' | translate\">{{ json }}</pre>\n </div>\n} @else {\n <p class=\"state\">{{ 'nh-assistant.agent-runs.memory.empty' | translate }}</p>\n}\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;min-width:0;color:var(--nha-text);font-family:var(--nha-font);font-size:14px}: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}.section{display:flex;flex-direction:column;gap:14px;min-width:0}.section-header{display:flex;flex-wrap:wrap;align-items:flex-start;justify-content:space-between;gap:12px}.section-header>div{min-width:0;max-width:72ch}h3{margin:0 0 4px;font-size:17px;font-weight:750}.muted{margin:0;color:var(--nha-text-muted);font-size:13px}.state{display:flex;flex-direction:column;align-items:flex-start;gap:10px;margin:0;border:1px dashed var(--nha-border);border-radius:var(--nha-radius);padding:18px;color:var(--nha-text-muted);font-size:13px}.state p{margin:0}.cards{display:grid;gap:10px;margin:0;padding:0;list-style:none}.card{display:flex;flex-direction:column;gap:8px;min-width:0;border:1px solid var(--nha-border);border-radius:var(--nha-radius);padding:12px 14px;background:var(--nha-surface)}.card.selected{border-color:var(--nha-accent, currentColor)}.card[tabindex]:focus-visible{outline:3px solid color-mix(in srgb,var(--nha-focus) 80%,transparent);outline-offset:2px}.card.closed{border-style:dashed}.closed-card{display:flex;flex-wrap:wrap;align-items:center;justify-content:space-between;gap:8px}.message.stale-explanation{overflow-wrap:anywhere;color:var(--nha-text);background:var(--nha-surface-strong)}.rationale{margin:0;overflow-wrap:anywhere;color:var(--nha-text-muted);font-size:13px}.card-header{display:flex;flex-wrap:wrap;align-items:center;gap:8px;min-width:0}.card-header strong{font-size:14px;overflow-wrap:anywhere}.card-actions{display:flex;flex-wrap:wrap;align-items:center;gap:8px}.meta{display:flex;flex-wrap:wrap;align-items:center;gap:6px 12px;color:var(--nha-text-muted);font-size:12px;overflow-wrap:anywhere}pre{max-height:220px;margin:0;overflow:auto;border-radius:var(--nha-radius-control);padding:8px 10px;background:var(--nha-surface-muted, rgba(127, 127, 127, .08));font-family:var(--nha-mono);font-size:12px;white-space:pre-wrap;overflow-wrap:anywhere}.summary{margin:0;font-size:13px;overflow-wrap:anywhere}.presentation-fields{display:grid;gap:6px;margin:0}.presentation-fields div{display:grid;grid-template-columns:minmax(90px,.4fr) minmax(0,1fr);gap:8px}.presentation-fields dt{color:var(--nha-text-muted);font-size:12px;font-weight:700;overflow-wrap:anywhere}.presentation-fields dd{margin:0;font-size:13px;overflow-wrap:anywhere}.technical-details{color:var(--nha-text-muted);font-size:12px}.technical-details summary{cursor:pointer;font-weight:700}.technical-details code{overflow-wrap:anywhere}.technical-details .label{margin:10px 0 4px;font-size:11px;font-weight:700;text-transform:uppercase;letter-spacing:.04em}.technical-details .targets{margin:0;padding-left:18px;overflow-wrap:anywhere}.tabs{display:flex;flex-wrap:wrap;gap:4px;border-bottom:1px solid var(--nha-border)}.tabs button{border:0;border-bottom:2px solid transparent;border-radius:0;padding:8px 12px;background:transparent;color:var(--nha-text-muted);font:inherit;cursor:pointer}.tabs button[aria-selected=true]{border-bottom-color:currentColor;color:var(--nha-text);font-weight:650}.toolbar{display:flex;flex-wrap:wrap;align-items:center;gap:8px}.reason{flex:1 1 200px;min-width:0}.select{display:inline-flex;align-items:center;gap:6px;font-size:12px}.proposal-list{display:flex;flex-direction:column;gap:10px;min-width:0}.feedback-prompt{display:flex;flex-direction:column;gap:6px;min-width:0}.feedback-prompt .muted{overflow-wrap:anywhere}.text-button{display:inline-flex;align-items:center;border:0;border-radius:6px;padding:2px 4px;color:var(--nha-text-muted);background:transparent;font:inherit;font-size:12px;font-weight:650;text-decoration:underline;text-underline-offset:2px;cursor:pointer}.text-button:focus-visible{outline:3px solid color-mix(in srgb,var(--nha-focus) 80%,transparent);outline-offset:2px}.text-button:hover:not(:disabled){color:var(--nha-text)}.text-button:disabled{cursor:not-allowed;opacity:.55}.waiting-for{display:flex;align-items:center;gap:6px;margin:0;color:var(--nha-text-muted);font-size:12px;overflow-wrap:anywhere}.subject-agents{display:grid;gap:8px;margin:0;padding:0;list-style:none}.subject-agent{display:flex;flex-wrap:wrap;align-items:center;justify-content:space-between;gap:8px 12px;min-width:0;border:1px solid var(--nha-border);border-radius:var(--nha-radius-control);padding:10px 12px}.subject-agent-text{display:flex;flex-direction:column;gap:2px;min-width:0}.subject-agent-text strong{font-size:14px;overflow-wrap:anywhere}\n"], dependencies: [{ kind: "pipe", type: DatePipe, name: "date" }, { kind: "pipe", type: TranslatePipe, name: "translate" }], changeDetection: i0.ChangeDetectionStrategy.OnPush }); }
|
|
578
|
+
}
|
|
579
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.33", ngImport: i0, type: NhAssistantAgentMemoryComponent, decorators: [{
|
|
580
|
+
type: Component,
|
|
581
|
+
args: [{ selector: 'nh-assistant-agent-memory', standalone: true, imports: [DatePipe, TranslatePipe], changeDetection: ChangeDetectionStrategy.OnPush, template: "@if (loading()) {\n <p class=\"state\" role=\"status\">{{ 'nh-assistant.agent-runs.loading' | translate }}</p>\n} @else if (loadFailed()) {\n <div class=\"state\" role=\"alert\">\n <p>{{ 'nh-assistant.agent-runs.load-failed' | translate }}</p>\n <button class=\"secondary\" type=\"button\" (click)=\"load()\">{{ 'nh-assistant.agent-runs.retry' | translate }}</button>\n </div>\n} @else if (!memory()?.configured) {\n <p class=\"state\">{{ 'nh-assistant.agent-runs.memory.not-configured' | translate }}</p>\n} @else if (formatted(); as json) {\n <div class=\"section\">\n <div class=\"meta\">\n <span>{{ 'nh-assistant.agent-runs.memory.version' | translate: { version: memory()!.schemaVersion } }}</span>\n @if (memory()!.updatedAt; as updatedAt) {\n <span>{{ 'nh-assistant.agent-runs.memory.updated' | translate: { date: (updatedAt | date: 'short') } }}</span>\n }\n </div>\n <pre [attr.aria-label]=\"'nh-assistant.agent-runs.thread.tabs.memory' | translate\">{{ json }}</pre>\n </div>\n} @else {\n <p class=\"state\">{{ 'nh-assistant.agent-runs.memory.empty' | translate }}</p>\n}\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;min-width:0;color:var(--nha-text);font-family:var(--nha-font);font-size:14px}: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}.section{display:flex;flex-direction:column;gap:14px;min-width:0}.section-header{display:flex;flex-wrap:wrap;align-items:flex-start;justify-content:space-between;gap:12px}.section-header>div{min-width:0;max-width:72ch}h3{margin:0 0 4px;font-size:17px;font-weight:750}.muted{margin:0;color:var(--nha-text-muted);font-size:13px}.state{display:flex;flex-direction:column;align-items:flex-start;gap:10px;margin:0;border:1px dashed var(--nha-border);border-radius:var(--nha-radius);padding:18px;color:var(--nha-text-muted);font-size:13px}.state p{margin:0}.cards{display:grid;gap:10px;margin:0;padding:0;list-style:none}.card{display:flex;flex-direction:column;gap:8px;min-width:0;border:1px solid var(--nha-border);border-radius:var(--nha-radius);padding:12px 14px;background:var(--nha-surface)}.card.selected{border-color:var(--nha-accent, currentColor)}.card[tabindex]:focus-visible{outline:3px solid color-mix(in srgb,var(--nha-focus) 80%,transparent);outline-offset:2px}.card.closed{border-style:dashed}.closed-card{display:flex;flex-wrap:wrap;align-items:center;justify-content:space-between;gap:8px}.message.stale-explanation{overflow-wrap:anywhere;color:var(--nha-text);background:var(--nha-surface-strong)}.rationale{margin:0;overflow-wrap:anywhere;color:var(--nha-text-muted);font-size:13px}.card-header{display:flex;flex-wrap:wrap;align-items:center;gap:8px;min-width:0}.card-header strong{font-size:14px;overflow-wrap:anywhere}.card-actions{display:flex;flex-wrap:wrap;align-items:center;gap:8px}.meta{display:flex;flex-wrap:wrap;align-items:center;gap:6px 12px;color:var(--nha-text-muted);font-size:12px;overflow-wrap:anywhere}pre{max-height:220px;margin:0;overflow:auto;border-radius:var(--nha-radius-control);padding:8px 10px;background:var(--nha-surface-muted, rgba(127, 127, 127, .08));font-family:var(--nha-mono);font-size:12px;white-space:pre-wrap;overflow-wrap:anywhere}.summary{margin:0;font-size:13px;overflow-wrap:anywhere}.presentation-fields{display:grid;gap:6px;margin:0}.presentation-fields div{display:grid;grid-template-columns:minmax(90px,.4fr) minmax(0,1fr);gap:8px}.presentation-fields dt{color:var(--nha-text-muted);font-size:12px;font-weight:700;overflow-wrap:anywhere}.presentation-fields dd{margin:0;font-size:13px;overflow-wrap:anywhere}.technical-details{color:var(--nha-text-muted);font-size:12px}.technical-details summary{cursor:pointer;font-weight:700}.technical-details code{overflow-wrap:anywhere}.technical-details .label{margin:10px 0 4px;font-size:11px;font-weight:700;text-transform:uppercase;letter-spacing:.04em}.technical-details .targets{margin:0;padding-left:18px;overflow-wrap:anywhere}.tabs{display:flex;flex-wrap:wrap;gap:4px;border-bottom:1px solid var(--nha-border)}.tabs button{border:0;border-bottom:2px solid transparent;border-radius:0;padding:8px 12px;background:transparent;color:var(--nha-text-muted);font:inherit;cursor:pointer}.tabs button[aria-selected=true]{border-bottom-color:currentColor;color:var(--nha-text);font-weight:650}.toolbar{display:flex;flex-wrap:wrap;align-items:center;gap:8px}.reason{flex:1 1 200px;min-width:0}.select{display:inline-flex;align-items:center;gap:6px;font-size:12px}.proposal-list{display:flex;flex-direction:column;gap:10px;min-width:0}.feedback-prompt{display:flex;flex-direction:column;gap:6px;min-width:0}.feedback-prompt .muted{overflow-wrap:anywhere}.text-button{display:inline-flex;align-items:center;border:0;border-radius:6px;padding:2px 4px;color:var(--nha-text-muted);background:transparent;font:inherit;font-size:12px;font-weight:650;text-decoration:underline;text-underline-offset:2px;cursor:pointer}.text-button:focus-visible{outline:3px solid color-mix(in srgb,var(--nha-focus) 80%,transparent);outline-offset:2px}.text-button:hover:not(:disabled){color:var(--nha-text)}.text-button:disabled{cursor:not-allowed;opacity:.55}.waiting-for{display:flex;align-items:center;gap:6px;margin:0;color:var(--nha-text-muted);font-size:12px;overflow-wrap:anywhere}.subject-agents{display:grid;gap:8px;margin:0;padding:0;list-style:none}.subject-agent{display:flex;flex-wrap:wrap;align-items:center;justify-content:space-between;gap:8px 12px;min-width:0;border:1px solid var(--nha-border);border-radius:var(--nha-radius-control);padding:10px 12px}.subject-agent-text{display:flex;flex-direction:column;gap:2px;min-width:0}.subject-agent-text strong{font-size:14px;overflow-wrap:anywhere}\n"] }]
|
|
582
|
+
}], ctorParameters: () => [], propDecorators: { conversationId: [{ type: i0.Input, args: [{ isSignal: true, alias: "conversationId", required: true }] }] } });
|
|
583
|
+
|
|
584
|
+
const endedStatuses = new Set(['completed', 'failed', 'cancelled']);
|
|
585
|
+
/**
|
|
586
|
+
* The runs of an agent thread, newest first: trigger, status, failure, usage, proposals and the
|
|
587
|
+
* summary the next run starts from. Participants cancel an open run; approvers resume or restart
|
|
588
|
+
* a failed or cancelled one. With live updates it reloads by itself when a run or proposal of the
|
|
589
|
+
* thread changes.
|
|
590
|
+
*/
|
|
591
|
+
class NhAssistantRunTimelineComponent {
|
|
592
|
+
constructor() {
|
|
593
|
+
this.api = inject(NhAssistantAgentRunApiService);
|
|
594
|
+
this.conversationId = input.required(...(ngDevMode ? [{ debugName: "conversationId" }] : []));
|
|
595
|
+
this.role = input('reader', ...(ngDevMode ? [{ debugName: "role" }] : []));
|
|
596
|
+
/** Emits after a run was cancelled or retried. */
|
|
597
|
+
this.changed = output();
|
|
598
|
+
this.loading = signal(true, ...(ngDevMode ? [{ debugName: "loading" }] : []));
|
|
599
|
+
this.loadFailed = signal(false, ...(ngDevMode ? [{ debugName: "loadFailed" }] : []));
|
|
600
|
+
this.runs = signal([], ...(ngDevMode ? [{ debugName: "runs" }] : []));
|
|
601
|
+
this.busyRunId = signal(null, ...(ngDevMode ? [{ debugName: "busyRunId" }] : []));
|
|
602
|
+
this.error = signal(null, ...(ngDevMode ? [{ debugName: "error" }] : []));
|
|
603
|
+
this.errorKeys = computed(() => _nhAssistantErrorKeys(this.error()), ...(ngDevMode ? [{ debugName: "errorKeys" }] : []));
|
|
604
|
+
this.canCancel = computed(() => this.role() === 'participant' || this.role() === 'approver', ...(ngDevMode ? [{ debugName: "canCancel" }] : []));
|
|
605
|
+
this.canRetry = computed(() => this.role() === 'approver', ...(ngDevMode ? [{ debugName: "canRetry" }] : []));
|
|
606
|
+
inject(DestroyRef).onDestroy(() => {
|
|
607
|
+
this.subscription?.unsubscribe();
|
|
608
|
+
this.actionSubscription?.unsubscribe();
|
|
609
|
+
});
|
|
610
|
+
effect(() => {
|
|
611
|
+
this.conversationId();
|
|
612
|
+
untracked(() => this.load());
|
|
613
|
+
});
|
|
614
|
+
_nhAssistantReloadOnAgentWork(change => change.conversationId === this.conversationId() && change.reason !== 'feedback', () => this.fetch(!this.loading() && !this.loadFailed()));
|
|
615
|
+
}
|
|
616
|
+
load() {
|
|
617
|
+
this.fetch(false);
|
|
618
|
+
}
|
|
619
|
+
isOpen(run) {
|
|
620
|
+
return !endedStatuses.has(run.status);
|
|
621
|
+
}
|
|
622
|
+
canRetryRun(run) {
|
|
623
|
+
return this.canRetry() && (run.status === 'failed' || run.status === 'cancelled');
|
|
624
|
+
}
|
|
625
|
+
cancel(run) {
|
|
626
|
+
this.act(run, this.api.cancelRun(run.id));
|
|
627
|
+
}
|
|
628
|
+
retry(run, mode) {
|
|
629
|
+
this.act(run, this.api.retryRun(run.id, mode));
|
|
630
|
+
}
|
|
631
|
+
act(run, request) {
|
|
632
|
+
this.busyRunId.set(run.id);
|
|
633
|
+
this.error.set(null);
|
|
634
|
+
this.actionSubscription?.unsubscribe();
|
|
635
|
+
this.actionSubscription = request.subscribe({
|
|
636
|
+
next: () => {
|
|
637
|
+
this.busyRunId.set(null);
|
|
638
|
+
this.changed.emit();
|
|
639
|
+
this.load();
|
|
640
|
+
},
|
|
641
|
+
error: failure => {
|
|
642
|
+
this.busyRunId.set(null);
|
|
643
|
+
this.error.set(_toNhAssistantError(failure));
|
|
644
|
+
}
|
|
645
|
+
});
|
|
646
|
+
}
|
|
647
|
+
/** A quiet load, after a live update, shows no loading state and keeps the runs when it fails. */
|
|
648
|
+
fetch(quiet) {
|
|
649
|
+
if (!quiet) {
|
|
650
|
+
this.loading.set(true);
|
|
651
|
+
this.loadFailed.set(false);
|
|
652
|
+
}
|
|
653
|
+
this.subscription?.unsubscribe();
|
|
654
|
+
this.subscription = this.api.getRuns(this.conversationId()).subscribe({
|
|
655
|
+
next: list => {
|
|
656
|
+
this.runs.set(list.items);
|
|
657
|
+
this.loading.set(false);
|
|
658
|
+
this.loadFailed.set(false);
|
|
659
|
+
},
|
|
660
|
+
error: () => {
|
|
661
|
+
if (quiet) {
|
|
662
|
+
return;
|
|
663
|
+
}
|
|
664
|
+
this.loading.set(false);
|
|
665
|
+
this.loadFailed.set(true);
|
|
666
|
+
}
|
|
667
|
+
});
|
|
668
|
+
}
|
|
669
|
+
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.3.33", ngImport: i0, type: NhAssistantRunTimelineComponent, deps: [], target: i0.ɵɵFactoryTarget.Component }); }
|
|
670
|
+
static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "20.3.33", type: NhAssistantRunTimelineComponent, isStandalone: true, selector: "nh-assistant-run-timeline", inputs: { conversationId: { classPropertyName: "conversationId", publicName: "conversationId", isSignal: true, isRequired: true, transformFunction: null }, role: { classPropertyName: "role", publicName: "role", isSignal: true, isRequired: false, transformFunction: null } }, outputs: { changed: "changed" }, ngImport: i0, template: "@if (error(); as failure) {\n <p class=\"message error\" role=\"alert\"><nh-assistant-icon name=\"warning\" />{{ errorKeys() | nhAssistantTranslate: failure.code }}</p>\n}\n\n@if (loading() && runs().length === 0) {\n <p class=\"state\" role=\"status\">{{ 'nh-assistant.agent-runs.loading' | translate }}</p>\n} @else if (loadFailed()) {\n <div class=\"state\" role=\"alert\">\n <p>{{ 'nh-assistant.agent-runs.load-failed' | translate }}</p>\n <button class=\"secondary\" type=\"button\" (click)=\"load()\">{{ 'nh-assistant.agent-runs.retry' | translate }}</button>\n </div>\n} @else if (runs().length === 0) {\n <p class=\"state\">{{ 'nh-assistant.agent-runs.run.empty' | translate }}</p>\n} @else {\n <ol class=\"cards\" [attr.aria-label]=\"'nh-assistant.agent-runs.thread.tabs.runs' | translate\">\n @for (run of runs(); track run.id) {\n <li class=\"card\" [attr.aria-busy]=\"busyRunId() === run.id\">\n <div class=\"card-header\">\n <strong>{{ run.createdAt | date: 'short' }}</strong>\n <span\n class=\"badge\"\n [class.success]=\"run.status === 'completed'\"\n [class.warning]=\"run.status === 'waiting-for-approval' || run.status === 'queued' || run.status === 'running'\"\n [class.danger]=\"run.status === 'failed'\">\n {{ 'nh-assistant.agent-runs.run.status.' + run.status | translate }}\n </span>\n @if (run.shadow) {\n <span class=\"badge\">{{ 'nh-assistant.agent-runs.run.shadow' | translate }}</span>\n }\n @if (run.kind && run.kind !== 'model') {\n <span class=\"badge\" [attr.data-kind]=\"run.kind\">{{ 'nh-assistant.agent-runs.run.kind.' + run.kind | translate }}</span>\n }\n <span class=\"mono muted\">{{ 'nh-assistant.agent-runs.run.trigger' | translate: { trigger: run.triggerId } }}</span>\n </div>\n <div class=\"meta\">\n <span>{{ 'nh-assistant.agent-runs.run.tool-calls' | translate: { count: run.toolCalls } }}</span>\n <span>{{ 'nh-assistant.agent-runs.run.tokens' | translate: { count: run.inputTokens + run.outputTokens } }}</span>\n <span>{{ 'nh-assistant.agent-runs.run.proposals' | translate: { count: run.proposalCount } }}</span>\n @if (run.attempt > 1) {\n <span>{{ 'nh-assistant.agent-runs.run.attempt' | translate: { attempt: run.attempt } }}</span>\n }\n @if (run.failureCode; as code) {\n <span>{{ ['nh-assistant.errors.' + code] | nhAssistantTranslate: code }}</span>\n }\n </div>\n @if (run.summary) {\n <p class=\"summary\">{{ run.summary }}</p>\n }\n @if ((isOpen(run) && canCancel()) || canRetryRun(run)) {\n <div class=\"card-actions\">\n @if (isOpen(run) && canCancel()) {\n <button class=\"secondary\" type=\"button\" [disabled]=\"busyRunId() !== null\" (click)=\"cancel(run)\">\n <nh-assistant-icon name=\"stop\" />{{ 'nh-assistant.agent-runs.run.cancel' | translate }}\n </button>\n }\n @if (canRetryRun(run)) {\n <button class=\"secondary\" type=\"button\" [disabled]=\"busyRunId() !== null\" (click)=\"retry(run, 'resume')\">\n <nh-assistant-icon name=\"refresh\" />{{ 'nh-assistant.agent-runs.run.resume' | translate }}\n </button>\n <button class=\"secondary\" type=\"button\" [disabled]=\"busyRunId() !== null\" (click)=\"retry(run, 'restart')\">\n <nh-assistant-icon name=\"refresh\" />{{ 'nh-assistant.agent-runs.run.restart' | translate }}\n </button>\n }\n </div>\n }\n </li>\n }\n </ol>\n}\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;min-width:0;color:var(--nha-text);font-family:var(--nha-font);font-size:14px}: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}.section{display:flex;flex-direction:column;gap:14px;min-width:0}.section-header{display:flex;flex-wrap:wrap;align-items:flex-start;justify-content:space-between;gap:12px}.section-header>div{min-width:0;max-width:72ch}h3{margin:0 0 4px;font-size:17px;font-weight:750}.muted{margin:0;color:var(--nha-text-muted);font-size:13px}.state{display:flex;flex-direction:column;align-items:flex-start;gap:10px;margin:0;border:1px dashed var(--nha-border);border-radius:var(--nha-radius);padding:18px;color:var(--nha-text-muted);font-size:13px}.state p{margin:0}.cards{display:grid;gap:10px;margin:0;padding:0;list-style:none}.card{display:flex;flex-direction:column;gap:8px;min-width:0;border:1px solid var(--nha-border);border-radius:var(--nha-radius);padding:12px 14px;background:var(--nha-surface)}.card.selected{border-color:var(--nha-accent, currentColor)}.card[tabindex]:focus-visible{outline:3px solid color-mix(in srgb,var(--nha-focus) 80%,transparent);outline-offset:2px}.card.closed{border-style:dashed}.closed-card{display:flex;flex-wrap:wrap;align-items:center;justify-content:space-between;gap:8px}.message.stale-explanation{overflow-wrap:anywhere;color:var(--nha-text);background:var(--nha-surface-strong)}.rationale{margin:0;overflow-wrap:anywhere;color:var(--nha-text-muted);font-size:13px}.card-header{display:flex;flex-wrap:wrap;align-items:center;gap:8px;min-width:0}.card-header strong{font-size:14px;overflow-wrap:anywhere}.card-actions{display:flex;flex-wrap:wrap;align-items:center;gap:8px}.meta{display:flex;flex-wrap:wrap;align-items:center;gap:6px 12px;color:var(--nha-text-muted);font-size:12px;overflow-wrap:anywhere}pre{max-height:220px;margin:0;overflow:auto;border-radius:var(--nha-radius-control);padding:8px 10px;background:var(--nha-surface-muted, rgba(127, 127, 127, .08));font-family:var(--nha-mono);font-size:12px;white-space:pre-wrap;overflow-wrap:anywhere}.summary{margin:0;font-size:13px;overflow-wrap:anywhere}.presentation-fields{display:grid;gap:6px;margin:0}.presentation-fields div{display:grid;grid-template-columns:minmax(90px,.4fr) minmax(0,1fr);gap:8px}.presentation-fields dt{color:var(--nha-text-muted);font-size:12px;font-weight:700;overflow-wrap:anywhere}.presentation-fields dd{margin:0;font-size:13px;overflow-wrap:anywhere}.technical-details{color:var(--nha-text-muted);font-size:12px}.technical-details summary{cursor:pointer;font-weight:700}.technical-details code{overflow-wrap:anywhere}.technical-details .label{margin:10px 0 4px;font-size:11px;font-weight:700;text-transform:uppercase;letter-spacing:.04em}.technical-details .targets{margin:0;padding-left:18px;overflow-wrap:anywhere}.tabs{display:flex;flex-wrap:wrap;gap:4px;border-bottom:1px solid var(--nha-border)}.tabs button{border:0;border-bottom:2px solid transparent;border-radius:0;padding:8px 12px;background:transparent;color:var(--nha-text-muted);font:inherit;cursor:pointer}.tabs button[aria-selected=true]{border-bottom-color:currentColor;color:var(--nha-text);font-weight:650}.toolbar{display:flex;flex-wrap:wrap;align-items:center;gap:8px}.reason{flex:1 1 200px;min-width:0}.select{display:inline-flex;align-items:center;gap:6px;font-size:12px}.proposal-list{display:flex;flex-direction:column;gap:10px;min-width:0}.feedback-prompt{display:flex;flex-direction:column;gap:6px;min-width:0}.feedback-prompt .muted{overflow-wrap:anywhere}.text-button{display:inline-flex;align-items:center;border:0;border-radius:6px;padding:2px 4px;color:var(--nha-text-muted);background:transparent;font:inherit;font-size:12px;font-weight:650;text-decoration:underline;text-underline-offset:2px;cursor:pointer}.text-button:focus-visible{outline:3px solid color-mix(in srgb,var(--nha-focus) 80%,transparent);outline-offset:2px}.text-button:hover:not(:disabled){color:var(--nha-text)}.text-button:disabled{cursor:not-allowed;opacity:.55}.waiting-for{display:flex;align-items:center;gap:6px;margin:0;color:var(--nha-text-muted);font-size:12px;overflow-wrap:anywhere}.subject-agents{display:grid;gap:8px;margin:0;padding:0;list-style:none}.subject-agent{display:flex;flex-wrap:wrap;align-items:center;justify-content:space-between;gap:8px 12px;min-width:0;border:1px solid var(--nha-border);border-radius:var(--nha-radius-control);padding:10px 12px}.subject-agent-text{display:flex;flex-direction:column;gap:2px;min-width:0}.subject-agent-text strong{font-size:14px;overflow-wrap:anywhere}\n"], dependencies: [{ kind: "component", type: _NhAssistantIconComponent, selector: "nh-assistant-icon", inputs: ["name"] }, { kind: "pipe", type: DatePipe, name: "date" }, { kind: "pipe", type: TranslatePipe, name: "translate" }, { kind: "pipe", type: _NhAssistantTranslatePipe, name: "nhAssistantTranslate" }], changeDetection: i0.ChangeDetectionStrategy.OnPush }); }
|
|
671
|
+
}
|
|
672
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.33", ngImport: i0, type: NhAssistantRunTimelineComponent, decorators: [{
|
|
673
|
+
type: Component,
|
|
674
|
+
args: [{ selector: 'nh-assistant-run-timeline', standalone: true, imports: [DatePipe, TranslatePipe, _NhAssistantTranslatePipe, _NhAssistantIconComponent], changeDetection: ChangeDetectionStrategy.OnPush, template: "@if (error(); as failure) {\n <p class=\"message error\" role=\"alert\"><nh-assistant-icon name=\"warning\" />{{ errorKeys() | nhAssistantTranslate: failure.code }}</p>\n}\n\n@if (loading() && runs().length === 0) {\n <p class=\"state\" role=\"status\">{{ 'nh-assistant.agent-runs.loading' | translate }}</p>\n} @else if (loadFailed()) {\n <div class=\"state\" role=\"alert\">\n <p>{{ 'nh-assistant.agent-runs.load-failed' | translate }}</p>\n <button class=\"secondary\" type=\"button\" (click)=\"load()\">{{ 'nh-assistant.agent-runs.retry' | translate }}</button>\n </div>\n} @else if (runs().length === 0) {\n <p class=\"state\">{{ 'nh-assistant.agent-runs.run.empty' | translate }}</p>\n} @else {\n <ol class=\"cards\" [attr.aria-label]=\"'nh-assistant.agent-runs.thread.tabs.runs' | translate\">\n @for (run of runs(); track run.id) {\n <li class=\"card\" [attr.aria-busy]=\"busyRunId() === run.id\">\n <div class=\"card-header\">\n <strong>{{ run.createdAt | date: 'short' }}</strong>\n <span\n class=\"badge\"\n [class.success]=\"run.status === 'completed'\"\n [class.warning]=\"run.status === 'waiting-for-approval' || run.status === 'queued' || run.status === 'running'\"\n [class.danger]=\"run.status === 'failed'\">\n {{ 'nh-assistant.agent-runs.run.status.' + run.status | translate }}\n </span>\n @if (run.shadow) {\n <span class=\"badge\">{{ 'nh-assistant.agent-runs.run.shadow' | translate }}</span>\n }\n @if (run.kind && run.kind !== 'model') {\n <span class=\"badge\" [attr.data-kind]=\"run.kind\">{{ 'nh-assistant.agent-runs.run.kind.' + run.kind | translate }}</span>\n }\n <span class=\"mono muted\">{{ 'nh-assistant.agent-runs.run.trigger' | translate: { trigger: run.triggerId } }}</span>\n </div>\n <div class=\"meta\">\n <span>{{ 'nh-assistant.agent-runs.run.tool-calls' | translate: { count: run.toolCalls } }}</span>\n <span>{{ 'nh-assistant.agent-runs.run.tokens' | translate: { count: run.inputTokens + run.outputTokens } }}</span>\n <span>{{ 'nh-assistant.agent-runs.run.proposals' | translate: { count: run.proposalCount } }}</span>\n @if (run.attempt > 1) {\n <span>{{ 'nh-assistant.agent-runs.run.attempt' | translate: { attempt: run.attempt } }}</span>\n }\n @if (run.failureCode; as code) {\n <span>{{ ['nh-assistant.errors.' + code] | nhAssistantTranslate: code }}</span>\n }\n </div>\n @if (run.summary) {\n <p class=\"summary\">{{ run.summary }}</p>\n }\n @if ((isOpen(run) && canCancel()) || canRetryRun(run)) {\n <div class=\"card-actions\">\n @if (isOpen(run) && canCancel()) {\n <button class=\"secondary\" type=\"button\" [disabled]=\"busyRunId() !== null\" (click)=\"cancel(run)\">\n <nh-assistant-icon name=\"stop\" />{{ 'nh-assistant.agent-runs.run.cancel' | translate }}\n </button>\n }\n @if (canRetryRun(run)) {\n <button class=\"secondary\" type=\"button\" [disabled]=\"busyRunId() !== null\" (click)=\"retry(run, 'resume')\">\n <nh-assistant-icon name=\"refresh\" />{{ 'nh-assistant.agent-runs.run.resume' | translate }}\n </button>\n <button class=\"secondary\" type=\"button\" [disabled]=\"busyRunId() !== null\" (click)=\"retry(run, 'restart')\">\n <nh-assistant-icon name=\"refresh\" />{{ 'nh-assistant.agent-runs.run.restart' | translate }}\n </button>\n }\n </div>\n }\n </li>\n }\n </ol>\n}\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;min-width:0;color:var(--nha-text);font-family:var(--nha-font);font-size:14px}: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}.section{display:flex;flex-direction:column;gap:14px;min-width:0}.section-header{display:flex;flex-wrap:wrap;align-items:flex-start;justify-content:space-between;gap:12px}.section-header>div{min-width:0;max-width:72ch}h3{margin:0 0 4px;font-size:17px;font-weight:750}.muted{margin:0;color:var(--nha-text-muted);font-size:13px}.state{display:flex;flex-direction:column;align-items:flex-start;gap:10px;margin:0;border:1px dashed var(--nha-border);border-radius:var(--nha-radius);padding:18px;color:var(--nha-text-muted);font-size:13px}.state p{margin:0}.cards{display:grid;gap:10px;margin:0;padding:0;list-style:none}.card{display:flex;flex-direction:column;gap:8px;min-width:0;border:1px solid var(--nha-border);border-radius:var(--nha-radius);padding:12px 14px;background:var(--nha-surface)}.card.selected{border-color:var(--nha-accent, currentColor)}.card[tabindex]:focus-visible{outline:3px solid color-mix(in srgb,var(--nha-focus) 80%,transparent);outline-offset:2px}.card.closed{border-style:dashed}.closed-card{display:flex;flex-wrap:wrap;align-items:center;justify-content:space-between;gap:8px}.message.stale-explanation{overflow-wrap:anywhere;color:var(--nha-text);background:var(--nha-surface-strong)}.rationale{margin:0;overflow-wrap:anywhere;color:var(--nha-text-muted);font-size:13px}.card-header{display:flex;flex-wrap:wrap;align-items:center;gap:8px;min-width:0}.card-header strong{font-size:14px;overflow-wrap:anywhere}.card-actions{display:flex;flex-wrap:wrap;align-items:center;gap:8px}.meta{display:flex;flex-wrap:wrap;align-items:center;gap:6px 12px;color:var(--nha-text-muted);font-size:12px;overflow-wrap:anywhere}pre{max-height:220px;margin:0;overflow:auto;border-radius:var(--nha-radius-control);padding:8px 10px;background:var(--nha-surface-muted, rgba(127, 127, 127, .08));font-family:var(--nha-mono);font-size:12px;white-space:pre-wrap;overflow-wrap:anywhere}.summary{margin:0;font-size:13px;overflow-wrap:anywhere}.presentation-fields{display:grid;gap:6px;margin:0}.presentation-fields div{display:grid;grid-template-columns:minmax(90px,.4fr) minmax(0,1fr);gap:8px}.presentation-fields dt{color:var(--nha-text-muted);font-size:12px;font-weight:700;overflow-wrap:anywhere}.presentation-fields dd{margin:0;font-size:13px;overflow-wrap:anywhere}.technical-details{color:var(--nha-text-muted);font-size:12px}.technical-details summary{cursor:pointer;font-weight:700}.technical-details code{overflow-wrap:anywhere}.technical-details .label{margin:10px 0 4px;font-size:11px;font-weight:700;text-transform:uppercase;letter-spacing:.04em}.technical-details .targets{margin:0;padding-left:18px;overflow-wrap:anywhere}.tabs{display:flex;flex-wrap:wrap;gap:4px;border-bottom:1px solid var(--nha-border)}.tabs button{border:0;border-bottom:2px solid transparent;border-radius:0;padding:8px 12px;background:transparent;color:var(--nha-text-muted);font:inherit;cursor:pointer}.tabs button[aria-selected=true]{border-bottom-color:currentColor;color:var(--nha-text);font-weight:650}.toolbar{display:flex;flex-wrap:wrap;align-items:center;gap:8px}.reason{flex:1 1 200px;min-width:0}.select{display:inline-flex;align-items:center;gap:6px;font-size:12px}.proposal-list{display:flex;flex-direction:column;gap:10px;min-width:0}.feedback-prompt{display:flex;flex-direction:column;gap:6px;min-width:0}.feedback-prompt .muted{overflow-wrap:anywhere}.text-button{display:inline-flex;align-items:center;border:0;border-radius:6px;padding:2px 4px;color:var(--nha-text-muted);background:transparent;font:inherit;font-size:12px;font-weight:650;text-decoration:underline;text-underline-offset:2px;cursor:pointer}.text-button:focus-visible{outline:3px solid color-mix(in srgb,var(--nha-focus) 80%,transparent);outline-offset:2px}.text-button:hover:not(:disabled){color:var(--nha-text)}.text-button:disabled{cursor:not-allowed;opacity:.55}.waiting-for{display:flex;align-items:center;gap:6px;margin:0;color:var(--nha-text-muted);font-size:12px;overflow-wrap:anywhere}.subject-agents{display:grid;gap:8px;margin:0;padding:0;list-style:none}.subject-agent{display:flex;flex-wrap:wrap;align-items:center;justify-content:space-between;gap:8px 12px;min-width:0;border:1px solid var(--nha-border);border-radius:var(--nha-radius-control);padding:10px 12px}.subject-agent-text{display:flex;flex-direction:column;gap:2px;min-width:0}.subject-agent-text strong{font-size:14px;overflow-wrap:anywhere}\n"] }]
|
|
675
|
+
}], ctorParameters: () => [], propDecorators: { conversationId: [{ type: i0.Input, args: [{ isSignal: true, alias: "conversationId", required: true }] }], role: [{ type: i0.Input, args: [{ isSignal: true, alias: "role", required: false }] }], changed: [{ type: i0.Output, args: ["changed"] }] } });
|
|
676
|
+
|
|
677
|
+
/**
|
|
678
|
+
* The agent's work on one subject, for example an "Intake review" tab on a project page: the
|
|
679
|
+
* caller's role, a start action for participants, and the thread's proposals, runs, consultations
|
|
680
|
+
* by other assistants, working memory and files. Everything follows the caller's live role on the
|
|
681
|
+
* subject. With live updates the view reloads by itself when the thread's runs, proposals or
|
|
682
|
+
* feedback change, also when a colleague decided elsewhere.
|
|
683
|
+
*/
|
|
684
|
+
class NhAssistantAgentThreadViewComponent {
|
|
685
|
+
constructor() {
|
|
686
|
+
this.api = inject(NhAssistantAgentRunApiService);
|
|
687
|
+
this.proposalList = viewChild(NhAssistantAgentProposalsComponent, ...(ngDevMode ? [{ debugName: "proposalList" }] : []));
|
|
688
|
+
this.agentId = input.required(...(ngDevMode ? [{ debugName: "agentId" }] : []));
|
|
689
|
+
this.subjectType = input.required(...(ngDevMode ? [{ debugName: "subjectType" }] : []));
|
|
690
|
+
this.subjectId = input.required(...(ngDevMode ? [{ debugName: "subjectId" }] : []));
|
|
691
|
+
/** Emits the thread's conversation id, so the host can open it in the assistant panel. */
|
|
692
|
+
this.openConversation = output();
|
|
693
|
+
this.tab = signal('proposals', ...(ngDevMode ? [{ debugName: "tab" }] : []));
|
|
694
|
+
this.loading = signal(true, ...(ngDevMode ? [{ debugName: "loading" }] : []));
|
|
695
|
+
this.loadFailed = signal(false, ...(ngDevMode ? [{ debugName: "loadFailed" }] : []));
|
|
696
|
+
this.lookup = signal(null, ...(ngDevMode ? [{ debugName: "lookup" }] : []));
|
|
697
|
+
this.proposals = signal([], ...(ngDevMode ? [{ debugName: "proposals" }] : []));
|
|
698
|
+
this.message = signal('', ...(ngDevMode ? [{ debugName: "message" }] : []));
|
|
699
|
+
this.starting = signal(false, ...(ngDevMode ? [{ debugName: "starting" }] : []));
|
|
700
|
+
this.receipt = signal(null, ...(ngDevMode ? [{ debugName: "receipt" }] : []));
|
|
701
|
+
this.error = signal(null, ...(ngDevMode ? [{ debugName: "error" }] : []));
|
|
702
|
+
this.errorKeys = computed(() => _nhAssistantErrorKeys(this.error()), ...(ngDevMode ? [{ debugName: "errorKeys" }] : []));
|
|
703
|
+
this.thread = computed(() => this.lookup()?.thread ?? null, ...(ngDevMode ? [{ debugName: "thread" }] : []));
|
|
704
|
+
this.role = computed(() => this.lookup()?.role ?? 'none', ...(ngDevMode ? [{ debugName: "role" }] : []));
|
|
705
|
+
this.tabs = ['proposals', 'runs', 'consultations', 'memory', 'artifacts'];
|
|
706
|
+
inject(DestroyRef).onDestroy(() => {
|
|
707
|
+
this.subscription?.unsubscribe();
|
|
708
|
+
this.proposalSubscription?.unsubscribe();
|
|
709
|
+
this.startSubscription?.unsubscribe();
|
|
710
|
+
});
|
|
711
|
+
effect(() => {
|
|
712
|
+
this.agentId();
|
|
713
|
+
this.subjectType();
|
|
714
|
+
this.subjectId();
|
|
715
|
+
untracked(() => this.load());
|
|
716
|
+
});
|
|
717
|
+
_nhAssistantReloadOnAgentWork(change => this.concerns(change), () => this.refresh());
|
|
718
|
+
}
|
|
719
|
+
load() {
|
|
720
|
+
this.fetch(false);
|
|
721
|
+
}
|
|
722
|
+
loadProposals() {
|
|
723
|
+
this.fetchProposals(false);
|
|
724
|
+
}
|
|
725
|
+
onMessage(event) {
|
|
726
|
+
this.message.set(event.target.value);
|
|
727
|
+
}
|
|
728
|
+
start() {
|
|
729
|
+
this.starting.set(true);
|
|
730
|
+
this.error.set(null);
|
|
731
|
+
this.receipt.set(null);
|
|
732
|
+
this.startSubscription?.unsubscribe();
|
|
733
|
+
this.startSubscription = this.api
|
|
734
|
+
.startAgent({
|
|
735
|
+
agentId: this.agentId(),
|
|
736
|
+
subjectType: this.subjectType(),
|
|
737
|
+
subjectId: this.subjectId(),
|
|
738
|
+
message: this.message().trim() || null
|
|
739
|
+
})
|
|
740
|
+
.subscribe({
|
|
741
|
+
next: receipt => {
|
|
742
|
+
this.starting.set(false);
|
|
743
|
+
this.receipt.set(receipt);
|
|
744
|
+
this.message.set('');
|
|
745
|
+
this.load();
|
|
746
|
+
},
|
|
747
|
+
error: failure => {
|
|
748
|
+
this.starting.set(false);
|
|
749
|
+
this.error.set(_toNhAssistantError(failure));
|
|
750
|
+
}
|
|
751
|
+
});
|
|
752
|
+
}
|
|
753
|
+
/**
|
|
754
|
+
* Whether a live update is about this view: its own thread, or, before the subject has a thread,
|
|
755
|
+
* a run that may have started it.
|
|
756
|
+
*/
|
|
757
|
+
concerns(change) {
|
|
758
|
+
const thread = this.thread();
|
|
759
|
+
return thread ? change.conversationId === thread.conversationId : change.reason === 'run';
|
|
760
|
+
}
|
|
761
|
+
/**
|
|
762
|
+
* Reloads after a live update. Once the thread is shown it reloads quietly: no loading state, and
|
|
763
|
+
* a failure keeps what is shown, including an open feedback question. While a decision of the
|
|
764
|
+
* proposal list is in flight only the thread reloads, because the decision reloads the proposals
|
|
765
|
+
* when it ends.
|
|
766
|
+
*/
|
|
767
|
+
refresh() {
|
|
768
|
+
const withProposals = this.proposalList()?.busy() !== true;
|
|
769
|
+
this.fetch(this.lookup() !== null && !this.loading() && !this.loadFailed(), withProposals);
|
|
770
|
+
}
|
|
771
|
+
fetch(quiet, withProposals = true) {
|
|
772
|
+
if (!quiet) {
|
|
773
|
+
this.loading.set(true);
|
|
774
|
+
this.loadFailed.set(false);
|
|
775
|
+
}
|
|
776
|
+
this.subscription?.unsubscribe();
|
|
777
|
+
this.subscription = this.api.getThread(this.agentId(), this.subjectType(), this.subjectId()).subscribe({
|
|
778
|
+
next: lookup => {
|
|
779
|
+
this.lookup.set(lookup);
|
|
780
|
+
if (!lookup.thread?.activeRun && this.receipt()?.runId) {
|
|
781
|
+
// The run the receipt announced has ended; the run timeline shows how.
|
|
782
|
+
this.receipt.set(null);
|
|
783
|
+
}
|
|
784
|
+
this.loading.set(false);
|
|
785
|
+
this.loadFailed.set(false);
|
|
786
|
+
if (withProposals) {
|
|
787
|
+
this.fetchProposals(quiet);
|
|
788
|
+
}
|
|
789
|
+
},
|
|
790
|
+
error: () => {
|
|
791
|
+
if (quiet) {
|
|
792
|
+
return;
|
|
793
|
+
}
|
|
794
|
+
this.loading.set(false);
|
|
795
|
+
this.loadFailed.set(true);
|
|
796
|
+
}
|
|
797
|
+
});
|
|
798
|
+
}
|
|
799
|
+
fetchProposals(quiet) {
|
|
800
|
+
const thread = this.thread();
|
|
801
|
+
this.proposalSubscription?.unsubscribe();
|
|
802
|
+
if (!thread) {
|
|
803
|
+
this.proposals.set([]);
|
|
804
|
+
return;
|
|
805
|
+
}
|
|
806
|
+
this.proposalSubscription = this.api.getProposals(thread.conversationId).subscribe({
|
|
807
|
+
next: proposals => this.proposals.set(proposals),
|
|
808
|
+
error: () => {
|
|
809
|
+
if (!quiet) {
|
|
810
|
+
this.proposals.set([]);
|
|
811
|
+
}
|
|
812
|
+
}
|
|
813
|
+
});
|
|
814
|
+
}
|
|
815
|
+
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.3.33", ngImport: i0, type: NhAssistantAgentThreadViewComponent, deps: [], target: i0.ɵɵFactoryTarget.Component }); }
|
|
816
|
+
static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "20.3.33", type: NhAssistantAgentThreadViewComponent, isStandalone: true, selector: "nh-assistant-agent-thread-view", inputs: { agentId: { classPropertyName: "agentId", publicName: "agentId", isSignal: true, isRequired: true, transformFunction: null }, subjectType: { classPropertyName: "subjectType", publicName: "subjectType", isSignal: true, isRequired: true, transformFunction: null }, subjectId: { classPropertyName: "subjectId", publicName: "subjectId", isSignal: true, isRequired: true, transformFunction: null } }, outputs: { openConversation: "openConversation" }, viewQueries: [{ propertyName: "proposalList", first: true, predicate: NhAssistantAgentProposalsComponent, descendants: true, isSignal: true }], ngImport: i0, template: "<section class=\"section\" aria-labelledby=\"nh-assistant-agent-thread-title\" [attr.aria-busy]=\"loading()\">\n <header class=\"section-header\">\n <div>\n <h3 id=\"nh-assistant-agent-thread-title\">{{ thread()?.subjectDisplayName ?? ('nh-assistant.agent-runs.thread.title' | translate) }}</h3>\n <p class=\"muted\">\n {{ 'nh-assistant.agent-runs.role.' + role() | translate }}\n @if (thread()?.activeRun; as activeRun) {\n \u00B7 {{ 'nh-assistant.agent-runs.run.status.' + activeRun.status | translate }}\n }\n @if (thread()?.waitingInputs) {\n \u00B7 {{ 'nh-assistant.agent-runs.thread.waiting-inputs' | translate: { count: thread()!.waitingInputs } }}\n }\n </p>\n </div>\n <div class=\"toolbar\">\n @if (thread(); as current) {\n <button class=\"secondary\" type=\"button\" (click)=\"openConversation.emit(current.conversationId)\">\n <nh-assistant-icon name=\"link\" />{{ 'nh-assistant.agent-runs.thread.open-conversation' | translate }}\n </button>\n }\n <button class=\"secondary\" type=\"button\" [disabled]=\"loading()\" (click)=\"load()\">\n <nh-assistant-icon name=\"refresh\" />{{ 'nh-assistant.agent-runs.refresh' | translate }}\n </button>\n </div>\n </header>\n\n @if (error(); as failure) {\n <p class=\"message error\" role=\"alert\"><nh-assistant-icon name=\"warning\" />{{ errorKeys() | nhAssistantTranslate: failure.code }}</p>\n }\n @if (receipt(); as started) {\n <p class=\"message success\" role=\"status\">\n <nh-assistant-icon name=\"check\" />{{ 'nh-assistant.agent-runs.thread.outcome.' + started.outcome | translate }}\n </p>\n }\n\n @if (loading() && !lookup()) {\n <p class=\"state\" role=\"status\">{{ 'nh-assistant.agent-runs.loading' | translate }}</p>\n } @else if (loadFailed()) {\n <div class=\"state\" role=\"alert\">\n <p>{{ 'nh-assistant.agent-runs.load-failed' | translate }}</p>\n <button class=\"secondary\" type=\"button\" (click)=\"load()\">{{ 'nh-assistant.agent-runs.retry' | translate }}</button>\n </div>\n } @else {\n @if (lookup()?.canStart) {\n <form class=\"toolbar\" (submit)=\"$event.preventDefault(); start()\">\n <textarea\n class=\"reason\"\n rows=\"2\"\n maxlength=\"4000\"\n [value]=\"message()\"\n [attr.aria-label]=\"'nh-assistant.agent-runs.thread.start-message' | translate\"\n [placeholder]=\"'nh-assistant.agent-runs.thread.start-message' | translate\"\n (input)=\"onMessage($event)\"></textarea>\n <button class=\"primary\" type=\"submit\" [disabled]=\"starting()\">\n <nh-assistant-icon name=\"send\" />{{ (starting() ? 'nh-assistant.agent-runs.thread.starting' : 'nh-assistant.agent-runs.thread.start') | translate }}\n </button>\n </form>\n }\n\n @if (thread(); as current) {\n <div class=\"tabs\" role=\"tablist\">\n @for (item of tabs; track item) {\n <button\n type=\"button\"\n role=\"tab\"\n [attr.aria-selected]=\"tab() === item\"\n (click)=\"tab.set(item)\">\n {{ 'nh-assistant.agent-runs.thread.tabs.' + item | translate }}\n </button>\n }\n </div>\n <div role=\"tabpanel\">\n @switch (tab()) {\n @case ('proposals') {\n @if (proposals().length === 0) {\n <p class=\"state\">{{ 'nh-assistant.agent-runs.thread.no-proposals' | translate }}</p>\n } @else {\n <nh-assistant-agent-proposals [proposals]=\"proposals()\" [canDecide]=\"role() === 'approver'\" (changed)=\"loadProposals()\" />\n }\n }\n @case ('runs') {\n <nh-assistant-run-timeline [conversationId]=\"current.conversationId\" [role]=\"role()\" (changed)=\"load()\" />\n }\n @case ('consultations') {\n <nh-assistant-agent-consultations [conversationId]=\"current.conversationId\" />\n }\n @case ('memory') {\n <nh-assistant-agent-memory [conversationId]=\"current.conversationId\" />\n }\n @case ('artifacts') {\n <nh-assistant-agent-artifacts [conversationId]=\"current.conversationId\" />\n }\n }\n </div>\n } @else {\n <p class=\"state\">{{ 'nh-assistant.agent-runs.thread.no-thread' | translate }}</p>\n }\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:block;min-width:0;color:var(--nha-text);font-family:var(--nha-font);font-size:14px}: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}.section{display:flex;flex-direction:column;gap:14px;min-width:0}.section-header{display:flex;flex-wrap:wrap;align-items:flex-start;justify-content:space-between;gap:12px}.section-header>div{min-width:0;max-width:72ch}h3{margin:0 0 4px;font-size:17px;font-weight:750}.muted{margin:0;color:var(--nha-text-muted);font-size:13px}.state{display:flex;flex-direction:column;align-items:flex-start;gap:10px;margin:0;border:1px dashed var(--nha-border);border-radius:var(--nha-radius);padding:18px;color:var(--nha-text-muted);font-size:13px}.state p{margin:0}.cards{display:grid;gap:10px;margin:0;padding:0;list-style:none}.card{display:flex;flex-direction:column;gap:8px;min-width:0;border:1px solid var(--nha-border);border-radius:var(--nha-radius);padding:12px 14px;background:var(--nha-surface)}.card.selected{border-color:var(--nha-accent, currentColor)}.card[tabindex]:focus-visible{outline:3px solid color-mix(in srgb,var(--nha-focus) 80%,transparent);outline-offset:2px}.card.closed{border-style:dashed}.closed-card{display:flex;flex-wrap:wrap;align-items:center;justify-content:space-between;gap:8px}.message.stale-explanation{overflow-wrap:anywhere;color:var(--nha-text);background:var(--nha-surface-strong)}.rationale{margin:0;overflow-wrap:anywhere;color:var(--nha-text-muted);font-size:13px}.card-header{display:flex;flex-wrap:wrap;align-items:center;gap:8px;min-width:0}.card-header strong{font-size:14px;overflow-wrap:anywhere}.card-actions{display:flex;flex-wrap:wrap;align-items:center;gap:8px}.meta{display:flex;flex-wrap:wrap;align-items:center;gap:6px 12px;color:var(--nha-text-muted);font-size:12px;overflow-wrap:anywhere}pre{max-height:220px;margin:0;overflow:auto;border-radius:var(--nha-radius-control);padding:8px 10px;background:var(--nha-surface-muted, rgba(127, 127, 127, .08));font-family:var(--nha-mono);font-size:12px;white-space:pre-wrap;overflow-wrap:anywhere}.summary{margin:0;font-size:13px;overflow-wrap:anywhere}.presentation-fields{display:grid;gap:6px;margin:0}.presentation-fields div{display:grid;grid-template-columns:minmax(90px,.4fr) minmax(0,1fr);gap:8px}.presentation-fields dt{color:var(--nha-text-muted);font-size:12px;font-weight:700;overflow-wrap:anywhere}.presentation-fields dd{margin:0;font-size:13px;overflow-wrap:anywhere}.technical-details{color:var(--nha-text-muted);font-size:12px}.technical-details summary{cursor:pointer;font-weight:700}.technical-details code{overflow-wrap:anywhere}.technical-details .label{margin:10px 0 4px;font-size:11px;font-weight:700;text-transform:uppercase;letter-spacing:.04em}.technical-details .targets{margin:0;padding-left:18px;overflow-wrap:anywhere}.tabs{display:flex;flex-wrap:wrap;gap:4px;border-bottom:1px solid var(--nha-border)}.tabs button{border:0;border-bottom:2px solid transparent;border-radius:0;padding:8px 12px;background:transparent;color:var(--nha-text-muted);font:inherit;cursor:pointer}.tabs button[aria-selected=true]{border-bottom-color:currentColor;color:var(--nha-text);font-weight:650}.toolbar{display:flex;flex-wrap:wrap;align-items:center;gap:8px}.reason{flex:1 1 200px;min-width:0}.select{display:inline-flex;align-items:center;gap:6px;font-size:12px}.proposal-list{display:flex;flex-direction:column;gap:10px;min-width:0}.feedback-prompt{display:flex;flex-direction:column;gap:6px;min-width:0}.feedback-prompt .muted{overflow-wrap:anywhere}.text-button{display:inline-flex;align-items:center;border:0;border-radius:6px;padding:2px 4px;color:var(--nha-text-muted);background:transparent;font:inherit;font-size:12px;font-weight:650;text-decoration:underline;text-underline-offset:2px;cursor:pointer}.text-button:focus-visible{outline:3px solid color-mix(in srgb,var(--nha-focus) 80%,transparent);outline-offset:2px}.text-button:hover:not(:disabled){color:var(--nha-text)}.text-button:disabled{cursor:not-allowed;opacity:.55}.waiting-for{display:flex;align-items:center;gap:6px;margin:0;color:var(--nha-text-muted);font-size:12px;overflow-wrap:anywhere}.subject-agents{display:grid;gap:8px;margin:0;padding:0;list-style:none}.subject-agent{display:flex;flex-wrap:wrap;align-items:center;justify-content:space-between;gap:8px 12px;min-width:0;border:1px solid var(--nha-border);border-radius:var(--nha-radius-control);padding:10px 12px}.subject-agent-text{display:flex;flex-direction:column;gap:2px;min-width:0}.subject-agent-text strong{font-size:14px;overflow-wrap:anywhere}\n"], dependencies: [{ kind: "component", type: _NhAssistantIconComponent, selector: "nh-assistant-icon", inputs: ["name"] }, { kind: "component", type: NhAssistantAgentProposalsComponent, selector: "nh-assistant-agent-proposals", inputs: ["proposals", "canDecide", "decisionRights", "selectable", "holdClosedCards"], outputs: ["changed"] }, { kind: "component", type: NhAssistantRunTimelineComponent, selector: "nh-assistant-run-timeline", inputs: ["conversationId", "role"], outputs: ["changed"] }, { kind: "component", type: NhAssistantAgentMemoryComponent, selector: "nh-assistant-agent-memory", inputs: ["conversationId"] }, { kind: "component", type: NhAssistantAgentArtifactsComponent, selector: "nh-assistant-agent-artifacts", inputs: ["conversationId"] }, { kind: "component", type: NhAssistantAgentConsultationsComponent, selector: "nh-assistant-agent-consultations", inputs: ["conversationId"] }, { kind: "pipe", type: TranslatePipe, name: "translate" }, { kind: "pipe", type: _NhAssistantTranslatePipe, name: "nhAssistantTranslate" }], changeDetection: i0.ChangeDetectionStrategy.OnPush }); }
|
|
817
|
+
}
|
|
818
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.33", ngImport: i0, type: NhAssistantAgentThreadViewComponent, decorators: [{
|
|
819
|
+
type: Component,
|
|
820
|
+
args: [{ selector: 'nh-assistant-agent-thread-view', standalone: true, imports: [
|
|
821
|
+
TranslatePipe,
|
|
822
|
+
_NhAssistantTranslatePipe,
|
|
823
|
+
_NhAssistantIconComponent,
|
|
824
|
+
NhAssistantAgentProposalsComponent,
|
|
825
|
+
NhAssistantRunTimelineComponent,
|
|
826
|
+
NhAssistantAgentMemoryComponent,
|
|
827
|
+
NhAssistantAgentArtifactsComponent,
|
|
828
|
+
NhAssistantAgentConsultationsComponent
|
|
829
|
+
], changeDetection: ChangeDetectionStrategy.OnPush, template: "<section class=\"section\" aria-labelledby=\"nh-assistant-agent-thread-title\" [attr.aria-busy]=\"loading()\">\n <header class=\"section-header\">\n <div>\n <h3 id=\"nh-assistant-agent-thread-title\">{{ thread()?.subjectDisplayName ?? ('nh-assistant.agent-runs.thread.title' | translate) }}</h3>\n <p class=\"muted\">\n {{ 'nh-assistant.agent-runs.role.' + role() | translate }}\n @if (thread()?.activeRun; as activeRun) {\n \u00B7 {{ 'nh-assistant.agent-runs.run.status.' + activeRun.status | translate }}\n }\n @if (thread()?.waitingInputs) {\n \u00B7 {{ 'nh-assistant.agent-runs.thread.waiting-inputs' | translate: { count: thread()!.waitingInputs } }}\n }\n </p>\n </div>\n <div class=\"toolbar\">\n @if (thread(); as current) {\n <button class=\"secondary\" type=\"button\" (click)=\"openConversation.emit(current.conversationId)\">\n <nh-assistant-icon name=\"link\" />{{ 'nh-assistant.agent-runs.thread.open-conversation' | translate }}\n </button>\n }\n <button class=\"secondary\" type=\"button\" [disabled]=\"loading()\" (click)=\"load()\">\n <nh-assistant-icon name=\"refresh\" />{{ 'nh-assistant.agent-runs.refresh' | translate }}\n </button>\n </div>\n </header>\n\n @if (error(); as failure) {\n <p class=\"message error\" role=\"alert\"><nh-assistant-icon name=\"warning\" />{{ errorKeys() | nhAssistantTranslate: failure.code }}</p>\n }\n @if (receipt(); as started) {\n <p class=\"message success\" role=\"status\">\n <nh-assistant-icon name=\"check\" />{{ 'nh-assistant.agent-runs.thread.outcome.' + started.outcome | translate }}\n </p>\n }\n\n @if (loading() && !lookup()) {\n <p class=\"state\" role=\"status\">{{ 'nh-assistant.agent-runs.loading' | translate }}</p>\n } @else if (loadFailed()) {\n <div class=\"state\" role=\"alert\">\n <p>{{ 'nh-assistant.agent-runs.load-failed' | translate }}</p>\n <button class=\"secondary\" type=\"button\" (click)=\"load()\">{{ 'nh-assistant.agent-runs.retry' | translate }}</button>\n </div>\n } @else {\n @if (lookup()?.canStart) {\n <form class=\"toolbar\" (submit)=\"$event.preventDefault(); start()\">\n <textarea\n class=\"reason\"\n rows=\"2\"\n maxlength=\"4000\"\n [value]=\"message()\"\n [attr.aria-label]=\"'nh-assistant.agent-runs.thread.start-message' | translate\"\n [placeholder]=\"'nh-assistant.agent-runs.thread.start-message' | translate\"\n (input)=\"onMessage($event)\"></textarea>\n <button class=\"primary\" type=\"submit\" [disabled]=\"starting()\">\n <nh-assistant-icon name=\"send\" />{{ (starting() ? 'nh-assistant.agent-runs.thread.starting' : 'nh-assistant.agent-runs.thread.start') | translate }}\n </button>\n </form>\n }\n\n @if (thread(); as current) {\n <div class=\"tabs\" role=\"tablist\">\n @for (item of tabs; track item) {\n <button\n type=\"button\"\n role=\"tab\"\n [attr.aria-selected]=\"tab() === item\"\n (click)=\"tab.set(item)\">\n {{ 'nh-assistant.agent-runs.thread.tabs.' + item | translate }}\n </button>\n }\n </div>\n <div role=\"tabpanel\">\n @switch (tab()) {\n @case ('proposals') {\n @if (proposals().length === 0) {\n <p class=\"state\">{{ 'nh-assistant.agent-runs.thread.no-proposals' | translate }}</p>\n } @else {\n <nh-assistant-agent-proposals [proposals]=\"proposals()\" [canDecide]=\"role() === 'approver'\" (changed)=\"loadProposals()\" />\n }\n }\n @case ('runs') {\n <nh-assistant-run-timeline [conversationId]=\"current.conversationId\" [role]=\"role()\" (changed)=\"load()\" />\n }\n @case ('consultations') {\n <nh-assistant-agent-consultations [conversationId]=\"current.conversationId\" />\n }\n @case ('memory') {\n <nh-assistant-agent-memory [conversationId]=\"current.conversationId\" />\n }\n @case ('artifacts') {\n <nh-assistant-agent-artifacts [conversationId]=\"current.conversationId\" />\n }\n }\n </div>\n } @else {\n <p class=\"state\">{{ 'nh-assistant.agent-runs.thread.no-thread' | translate }}</p>\n }\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:block;min-width:0;color:var(--nha-text);font-family:var(--nha-font);font-size:14px}: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}.section{display:flex;flex-direction:column;gap:14px;min-width:0}.section-header{display:flex;flex-wrap:wrap;align-items:flex-start;justify-content:space-between;gap:12px}.section-header>div{min-width:0;max-width:72ch}h3{margin:0 0 4px;font-size:17px;font-weight:750}.muted{margin:0;color:var(--nha-text-muted);font-size:13px}.state{display:flex;flex-direction:column;align-items:flex-start;gap:10px;margin:0;border:1px dashed var(--nha-border);border-radius:var(--nha-radius);padding:18px;color:var(--nha-text-muted);font-size:13px}.state p{margin:0}.cards{display:grid;gap:10px;margin:0;padding:0;list-style:none}.card{display:flex;flex-direction:column;gap:8px;min-width:0;border:1px solid var(--nha-border);border-radius:var(--nha-radius);padding:12px 14px;background:var(--nha-surface)}.card.selected{border-color:var(--nha-accent, currentColor)}.card[tabindex]:focus-visible{outline:3px solid color-mix(in srgb,var(--nha-focus) 80%,transparent);outline-offset:2px}.card.closed{border-style:dashed}.closed-card{display:flex;flex-wrap:wrap;align-items:center;justify-content:space-between;gap:8px}.message.stale-explanation{overflow-wrap:anywhere;color:var(--nha-text);background:var(--nha-surface-strong)}.rationale{margin:0;overflow-wrap:anywhere;color:var(--nha-text-muted);font-size:13px}.card-header{display:flex;flex-wrap:wrap;align-items:center;gap:8px;min-width:0}.card-header strong{font-size:14px;overflow-wrap:anywhere}.card-actions{display:flex;flex-wrap:wrap;align-items:center;gap:8px}.meta{display:flex;flex-wrap:wrap;align-items:center;gap:6px 12px;color:var(--nha-text-muted);font-size:12px;overflow-wrap:anywhere}pre{max-height:220px;margin:0;overflow:auto;border-radius:var(--nha-radius-control);padding:8px 10px;background:var(--nha-surface-muted, rgba(127, 127, 127, .08));font-family:var(--nha-mono);font-size:12px;white-space:pre-wrap;overflow-wrap:anywhere}.summary{margin:0;font-size:13px;overflow-wrap:anywhere}.presentation-fields{display:grid;gap:6px;margin:0}.presentation-fields div{display:grid;grid-template-columns:minmax(90px,.4fr) minmax(0,1fr);gap:8px}.presentation-fields dt{color:var(--nha-text-muted);font-size:12px;font-weight:700;overflow-wrap:anywhere}.presentation-fields dd{margin:0;font-size:13px;overflow-wrap:anywhere}.technical-details{color:var(--nha-text-muted);font-size:12px}.technical-details summary{cursor:pointer;font-weight:700}.technical-details code{overflow-wrap:anywhere}.technical-details .label{margin:10px 0 4px;font-size:11px;font-weight:700;text-transform:uppercase;letter-spacing:.04em}.technical-details .targets{margin:0;padding-left:18px;overflow-wrap:anywhere}.tabs{display:flex;flex-wrap:wrap;gap:4px;border-bottom:1px solid var(--nha-border)}.tabs button{border:0;border-bottom:2px solid transparent;border-radius:0;padding:8px 12px;background:transparent;color:var(--nha-text-muted);font:inherit;cursor:pointer}.tabs button[aria-selected=true]{border-bottom-color:currentColor;color:var(--nha-text);font-weight:650}.toolbar{display:flex;flex-wrap:wrap;align-items:center;gap:8px}.reason{flex:1 1 200px;min-width:0}.select{display:inline-flex;align-items:center;gap:6px;font-size:12px}.proposal-list{display:flex;flex-direction:column;gap:10px;min-width:0}.feedback-prompt{display:flex;flex-direction:column;gap:6px;min-width:0}.feedback-prompt .muted{overflow-wrap:anywhere}.text-button{display:inline-flex;align-items:center;border:0;border-radius:6px;padding:2px 4px;color:var(--nha-text-muted);background:transparent;font:inherit;font-size:12px;font-weight:650;text-decoration:underline;text-underline-offset:2px;cursor:pointer}.text-button:focus-visible{outline:3px solid color-mix(in srgb,var(--nha-focus) 80%,transparent);outline-offset:2px}.text-button:hover:not(:disabled){color:var(--nha-text)}.text-button:disabled{cursor:not-allowed;opacity:.55}.waiting-for{display:flex;align-items:center;gap:6px;margin:0;color:var(--nha-text-muted);font-size:12px;overflow-wrap:anywhere}.subject-agents{display:grid;gap:8px;margin:0;padding:0;list-style:none}.subject-agent{display:flex;flex-wrap:wrap;align-items:center;justify-content:space-between;gap:8px 12px;min-width:0;border:1px solid var(--nha-border);border-radius:var(--nha-radius-control);padding:10px 12px}.subject-agent-text{display:flex;flex-direction:column;gap:2px;min-width:0}.subject-agent-text strong{font-size:14px;overflow-wrap:anywhere}\n"] }]
|
|
830
|
+
}], ctorParameters: () => [], propDecorators: { proposalList: [{ type: i0.ViewChild, args: [i0.forwardRef(() => NhAssistantAgentProposalsComponent), { isSignal: true }] }], agentId: [{ type: i0.Input, args: [{ isSignal: true, alias: "agentId", required: true }] }], subjectType: [{ type: i0.Input, args: [{ isSignal: true, alias: "subjectType", required: true }] }], subjectId: [{ type: i0.Input, args: [{ isSignal: true, alias: "subjectId", required: true }] }], openConversation: [{ type: i0.Output, args: ["openConversation"] }] } });
|
|
831
|
+
|
|
832
|
+
let nextSuggestionsId = 0;
|
|
833
|
+
/**
|
|
834
|
+
* The agent work on one subject of the application, for example in a project's dialog: the open
|
|
835
|
+
* proposals of every agent on the subject with the viewer's own decision right, including who
|
|
836
|
+
* decides when the viewer may not and the optional question after a rejection, and per agent the
|
|
837
|
+
* conversation about the subject and, for participants, a start action. `agentId` names the agent
|
|
838
|
+
* whose conversation the host offers also before it worked on the subject. With live updates the
|
|
839
|
+
* view reloads by itself when agent work on its subject changes; a proposal that closes because it
|
|
840
|
+
* no longer fits stays as a closed card with the reason until it is dismissed. Opening a
|
|
841
|
+
* conversation uses `NhAssistantPanelService.openSubject` and emits `conversationOpened` afterwards.
|
|
842
|
+
*/
|
|
843
|
+
class NhAssistantSubjectSuggestionsComponent {
|
|
844
|
+
constructor() {
|
|
845
|
+
this.api = inject(NhAssistantAgentRunApiService);
|
|
846
|
+
this.panel = inject(NhAssistantPanelService);
|
|
847
|
+
this.store = inject(NhAssistantStore);
|
|
848
|
+
this.proposalList = viewChild(NhAssistantAgentProposalsComponent, ...(ngDevMode ? [{ debugName: "proposalList" }] : []));
|
|
849
|
+
this.destroyed = false;
|
|
850
|
+
/** The application's kind of subject, for example `project`. */
|
|
851
|
+
this.subjectType = input.required(...(ngDevMode ? [{ debugName: "subjectType" }] : []));
|
|
852
|
+
this.subjectId = input.required(...(ngDevMode ? [{ debugName: "subjectId" }] : []));
|
|
853
|
+
/** The agent whose conversation about the subject the host offers, also before it worked on it. */
|
|
854
|
+
this.agentId = input(undefined, ...(ngDevMode ? [{ debugName: "agentId" }] : []));
|
|
855
|
+
/** Emits once the panel opens the conversation, so a host in a dialog can make room for it. */
|
|
856
|
+
this.conversationOpened = output();
|
|
857
|
+
this.headingId = `nh-assistant-subject-suggestions-${++nextSuggestionsId}`;
|
|
858
|
+
this.loading = signal(true, ...(ngDevMode ? [{ debugName: "loading" }] : []));
|
|
859
|
+
/** True after the first successful load; later loads keep the list, and an open feedback question, in place. */
|
|
860
|
+
this.loaded = signal(false, ...(ngDevMode ? [{ debugName: "loaded" }] : []));
|
|
861
|
+
this.loadFailed = signal(false, ...(ngDevMode ? [{ debugName: "loadFailed" }] : []));
|
|
862
|
+
/** The caller has no role on the subject, or it no longer exists. */
|
|
863
|
+
this.unavailable = signal(false, ...(ngDevMode ? [{ debugName: "unavailable" }] : []));
|
|
864
|
+
this.work = signal(null, ...(ngDevMode ? [{ debugName: "work" }] : []));
|
|
865
|
+
/** The agent whose conversation is opening or which is starting. */
|
|
866
|
+
this.opening = signal(null, ...(ngDevMode ? [{ debugName: "opening" }] : []));
|
|
867
|
+
this.starting = signal(null, ...(ngDevMode ? [{ debugName: "starting" }] : []));
|
|
868
|
+
this.started = signal(null, ...(ngDevMode ? [{ debugName: "started" }] : []));
|
|
869
|
+
this.error = signal(null, ...(ngDevMode ? [{ debugName: "error" }] : []));
|
|
870
|
+
this.errorKeys = computed(() => _nhAssistantErrorKeys(this.error()), ...(ngDevMode ? [{ debugName: "errorKeys" }] : []));
|
|
871
|
+
/** True while the assistant panel can show a conversation. */
|
|
872
|
+
this.assistantEnabled = this.store.enabled;
|
|
873
|
+
this.agents = computed(() => this.work()?.agents ?? [], ...(ngDevMode ? [{ debugName: "agents" }] : []));
|
|
874
|
+
this.proposals = computed(() => this.work()?.openProposals.map(item => item.proposal) ?? [], ...(ngDevMode ? [{ debugName: "proposals" }] : []));
|
|
875
|
+
this.decisionRights = computed(() => new Map((this.work()?.openProposals ?? []).map(item => [
|
|
876
|
+
item.proposal.approvalId,
|
|
877
|
+
{ canDecide: item.canDecide, reasonCode: item.reasonCode }
|
|
878
|
+
])), ...(ngDevMode ? [{ debugName: "decisionRights" }] : []));
|
|
879
|
+
inject(DestroyRef).onDestroy(() => {
|
|
880
|
+
this.destroyed = true;
|
|
881
|
+
this.subscription?.unsubscribe();
|
|
882
|
+
this.startSubscription?.unsubscribe();
|
|
883
|
+
});
|
|
884
|
+
// Browser only: the access policy and the status need the signed-in user.
|
|
885
|
+
afterNextRender(() => {
|
|
886
|
+
void this.store.initialize();
|
|
887
|
+
});
|
|
888
|
+
effect(() => {
|
|
889
|
+
this.subjectType();
|
|
890
|
+
this.subjectId();
|
|
891
|
+
this.agentId();
|
|
892
|
+
untracked(() => {
|
|
893
|
+
this.work.set(null);
|
|
894
|
+
this.loaded.set(false);
|
|
895
|
+
this.started.set(null);
|
|
896
|
+
this.error.set(null);
|
|
897
|
+
this.load();
|
|
898
|
+
});
|
|
899
|
+
});
|
|
900
|
+
_nhAssistantReloadOnAgentWork(change => change.subjectType === this.subjectType() && change.subjectId === this.subjectId(), () => this.refresh());
|
|
901
|
+
}
|
|
902
|
+
load() {
|
|
903
|
+
this.fetch(false);
|
|
904
|
+
}
|
|
905
|
+
/** The translation keys of an agent's name: from the server's status, then the convention. */
|
|
906
|
+
agentNameKeys(agentId) {
|
|
907
|
+
const known = this.store.agents().find(agent => agent.id === agentId)?.displayNameKey;
|
|
908
|
+
return known ? [known, `nh-assistant.agents.${agentId}.name`] : [`nh-assistant.agents.${agentId}.name`];
|
|
909
|
+
}
|
|
910
|
+
/** Readers may open an existing conversation; creating one needs the participant role. */
|
|
911
|
+
canOpen(agent) {
|
|
912
|
+
return agent.thread !== null || this.work()?.role !== 'reader';
|
|
913
|
+
}
|
|
914
|
+
async open(agent) {
|
|
915
|
+
this.opening.set(agent.agentId);
|
|
916
|
+
this.error.set(null);
|
|
917
|
+
try {
|
|
918
|
+
const lookup = await this.panel.openSubject(agent.agentId, { type: this.subjectType(), id: this.subjectId() });
|
|
919
|
+
if (!this.destroyed) {
|
|
920
|
+
this.conversationOpened.emit(lookup);
|
|
921
|
+
if (!agent.thread) {
|
|
922
|
+
// The conversation now exists; show it as the agent's thread.
|
|
923
|
+
this.fetch(true);
|
|
924
|
+
}
|
|
925
|
+
}
|
|
926
|
+
}
|
|
927
|
+
catch (failure) {
|
|
928
|
+
if (!this.destroyed) {
|
|
929
|
+
this.error.set(_toNhAssistantError(failure));
|
|
930
|
+
}
|
|
931
|
+
}
|
|
932
|
+
finally {
|
|
933
|
+
if (!this.destroyed) {
|
|
934
|
+
this.opening.set(null);
|
|
935
|
+
}
|
|
936
|
+
}
|
|
937
|
+
}
|
|
938
|
+
start(agent) {
|
|
939
|
+
this.starting.set(agent.agentId);
|
|
940
|
+
this.error.set(null);
|
|
941
|
+
this.started.set(null);
|
|
942
|
+
this.startSubscription?.unsubscribe();
|
|
943
|
+
this.startSubscription = this.api
|
|
944
|
+
.startAgent({ agentId: agent.agentId, subjectType: this.subjectType(), subjectId: this.subjectId() })
|
|
945
|
+
.subscribe({
|
|
946
|
+
next: receipt => {
|
|
947
|
+
this.starting.set(null);
|
|
948
|
+
this.started.set({ agentId: agent.agentId, receipt });
|
|
949
|
+
this.fetch(true);
|
|
950
|
+
},
|
|
951
|
+
error: failure => {
|
|
952
|
+
this.starting.set(null);
|
|
953
|
+
this.error.set(_toNhAssistantError(failure));
|
|
954
|
+
}
|
|
955
|
+
});
|
|
956
|
+
}
|
|
957
|
+
/**
|
|
958
|
+
* Reloads after a live update. Once the work is shown it reloads quietly: no loading state, and
|
|
959
|
+
* a failure keeps what is shown, including an open feedback question. While a decision of the
|
|
960
|
+
* list is in flight it waits, because the decision reloads the list when it ends.
|
|
961
|
+
*/
|
|
962
|
+
refresh() {
|
|
963
|
+
if (this.proposalList()?.busy()) {
|
|
964
|
+
return;
|
|
965
|
+
}
|
|
966
|
+
this.fetch(this.loaded() && !this.loading() && !this.loadFailed());
|
|
967
|
+
}
|
|
968
|
+
fetch(quiet) {
|
|
969
|
+
if (!quiet) {
|
|
970
|
+
this.loading.set(true);
|
|
971
|
+
this.loadFailed.set(false);
|
|
972
|
+
this.unavailable.set(false);
|
|
973
|
+
}
|
|
974
|
+
this.subscription?.unsubscribe();
|
|
975
|
+
this.subscription = this.api.getSubjectWork(this.subjectType(), this.subjectId(), this.agentId()).subscribe({
|
|
976
|
+
next: work => {
|
|
977
|
+
const previous = this.proposals();
|
|
978
|
+
this.work.set(work);
|
|
979
|
+
if (quiet) {
|
|
980
|
+
this.proposalList()?.holdClosed(previous, this.proposals());
|
|
981
|
+
}
|
|
982
|
+
const started = this.started();
|
|
983
|
+
const startedAgent = started ? work.agents.find(agent => agent.agentId === started.agentId) : undefined;
|
|
984
|
+
if (started?.receipt.runId && !startedAgent?.thread?.activeRun) {
|
|
985
|
+
// The run the start announced has ended; its proposals are in the list.
|
|
986
|
+
this.started.set(null);
|
|
987
|
+
}
|
|
988
|
+
this.loading.set(false);
|
|
989
|
+
this.loadFailed.set(false);
|
|
990
|
+
this.unavailable.set(false);
|
|
991
|
+
this.loaded.set(true);
|
|
992
|
+
},
|
|
993
|
+
error: failure => {
|
|
994
|
+
if (quiet) {
|
|
995
|
+
return;
|
|
996
|
+
}
|
|
997
|
+
this.loading.set(false);
|
|
998
|
+
if (failure instanceof NhAssistantApiError && failure.status === 404) {
|
|
999
|
+
this.unavailable.set(true);
|
|
1000
|
+
}
|
|
1001
|
+
else {
|
|
1002
|
+
this.loadFailed.set(true);
|
|
1003
|
+
}
|
|
1004
|
+
}
|
|
1005
|
+
});
|
|
1006
|
+
}
|
|
1007
|
+
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.3.33", ngImport: i0, type: NhAssistantSubjectSuggestionsComponent, deps: [], target: i0.ɵɵFactoryTarget.Component }); }
|
|
1008
|
+
static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "20.3.33", type: NhAssistantSubjectSuggestionsComponent, isStandalone: true, selector: "nh-assistant-subject-suggestions", inputs: { subjectType: { classPropertyName: "subjectType", publicName: "subjectType", isSignal: true, isRequired: true, transformFunction: null }, subjectId: { classPropertyName: "subjectId", publicName: "subjectId", isSignal: true, isRequired: true, transformFunction: null }, agentId: { classPropertyName: "agentId", publicName: "agentId", isSignal: true, isRequired: false, transformFunction: null } }, outputs: { conversationOpened: "conversationOpened" }, viewQueries: [{ propertyName: "proposalList", first: true, predicate: NhAssistantAgentProposalsComponent, descendants: true, isSignal: true }], ngImport: i0, template: "<section class=\"section\" [attr.aria-labelledby]=\"headingId\" [attr.aria-busy]=\"loading()\">\n <header class=\"section-header\">\n <div>\n <h3 [id]=\"headingId\">{{ 'nh-assistant.agent-runs.subject.title' | translate }}</h3>\n <p class=\"muted\">{{ 'nh-assistant.agent-runs.subject.description' | translate }}</p>\n </div>\n <button class=\"secondary\" type=\"button\" [disabled]=\"loading()\" (click)=\"load()\">\n <nh-assistant-icon name=\"refresh\" />{{ 'nh-assistant.agent-runs.refresh' | translate }}\n </button>\n </header>\n\n @if (error(); as failure) {\n <p class=\"message error\" role=\"alert\"><nh-assistant-icon name=\"warning\" />{{ errorKeys() | nhAssistantTranslate: failure.code }}</p>\n }\n @if (started(); as start) {\n <p class=\"message success\" role=\"status\">\n <nh-assistant-icon name=\"check\" />{{ 'nh-assistant.agent-runs.thread.outcome.' + start.receipt.outcome | translate }}\n </p>\n }\n\n @if (loading() && !loaded()) {\n <p class=\"state\" role=\"status\">{{ 'nh-assistant.agent-runs.loading' | translate }}</p>\n } @else if (unavailable()) {\n <p class=\"state\">{{ 'nh-assistant.agent-runs.subject.unavailable' | translate }}</p>\n } @else if (loadFailed()) {\n <div class=\"state\" role=\"alert\">\n <p>{{ 'nh-assistant.agent-runs.load-failed' | translate }}</p>\n <button class=\"secondary\" type=\"button\" (click)=\"load()\">{{ 'nh-assistant.agent-runs.retry' | translate }}</button>\n </div>\n } @else {\n @if (agents().length > 0) {\n <ul class=\"subject-agents\" [attr.aria-label]=\"'nh-assistant.agent-runs.subject.agents' | translate\">\n @for (agent of agents(); track agent.agentId) {\n @let name = agentNameKeys(agent.agentId) | nhAssistantTranslate: agent.agentId;\n <li class=\"subject-agent\">\n <div class=\"subject-agent-text\">\n <strong>{{ name }}</strong>\n <span class=\"muted\">\n @if (agent.thread?.activeRun; as activeRun) {\n {{ 'nh-assistant.agent-runs.run.status.' + activeRun.status | translate }}\n } @else if (!agent.thread) {\n {{ 'nh-assistant.agent-runs.thread.no-thread' | translate }}\n } @else {\n {{ 'nh-assistant.agent-runs.subject.idle' | translate }}\n }\n </span>\n </div>\n <div class=\"card-actions\">\n @if (canOpen(agent)) {\n <button\n class=\"secondary\"\n type=\"button\"\n [disabled]=\"opening() !== null || !assistantEnabled()\"\n [attr.aria-label]=\"'nh-assistant.agent-runs.subject.open-conversation-label' | translate: { agent: name }\"\n [attr.title]=\"assistantEnabled() ? null : ('nh-assistant.agent-runs.subject.assistant-unavailable' | translate)\"\n (click)=\"open(agent)\">\n <nh-assistant-icon name=\"assistant\" />{{ (opening() === agent.agentId ? 'nh-assistant.agent-runs.subject.opening' : 'nh-assistant.agent-runs.thread.open-conversation') | translate }}\n </button>\n }\n @if (agent.canStart) {\n <button\n class=\"secondary\"\n type=\"button\"\n [disabled]=\"starting() !== null\"\n [attr.aria-label]=\"'nh-assistant.agent-runs.subject.start-label' | translate: { agent: name }\"\n (click)=\"start(agent)\">\n <nh-assistant-icon name=\"send\" />{{ (starting() === agent.agentId ? 'nh-assistant.agent-runs.thread.starting' : 'nh-assistant.agent-runs.thread.start') | translate }}\n </button>\n }\n </div>\n </li>\n }\n </ul>\n }\n\n <!-- Stays rendered when the list empties, so the optional feedback after a rejection remains. -->\n <nh-assistant-agent-proposals\n [proposals]=\"proposals()\"\n [decisionRights]=\"decisionRights()\"\n [holdClosedCards]=\"true\"\n (changed)=\"load()\" />\n @if (proposals().length === 0) {\n <p class=\"state\">{{ 'nh-assistant.agent-runs.subject.empty' | translate }}</p>\n }\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:block;min-width:0;color:var(--nha-text);font-family:var(--nha-font);font-size:14px}: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}.section{display:flex;flex-direction:column;gap:14px;min-width:0}.section-header{display:flex;flex-wrap:wrap;align-items:flex-start;justify-content:space-between;gap:12px}.section-header>div{min-width:0;max-width:72ch}h3{margin:0 0 4px;font-size:17px;font-weight:750}.muted{margin:0;color:var(--nha-text-muted);font-size:13px}.state{display:flex;flex-direction:column;align-items:flex-start;gap:10px;margin:0;border:1px dashed var(--nha-border);border-radius:var(--nha-radius);padding:18px;color:var(--nha-text-muted);font-size:13px}.state p{margin:0}.cards{display:grid;gap:10px;margin:0;padding:0;list-style:none}.card{display:flex;flex-direction:column;gap:8px;min-width:0;border:1px solid var(--nha-border);border-radius:var(--nha-radius);padding:12px 14px;background:var(--nha-surface)}.card.selected{border-color:var(--nha-accent, currentColor)}.card[tabindex]:focus-visible{outline:3px solid color-mix(in srgb,var(--nha-focus) 80%,transparent);outline-offset:2px}.card.closed{border-style:dashed}.closed-card{display:flex;flex-wrap:wrap;align-items:center;justify-content:space-between;gap:8px}.message.stale-explanation{overflow-wrap:anywhere;color:var(--nha-text);background:var(--nha-surface-strong)}.rationale{margin:0;overflow-wrap:anywhere;color:var(--nha-text-muted);font-size:13px}.card-header{display:flex;flex-wrap:wrap;align-items:center;gap:8px;min-width:0}.card-header strong{font-size:14px;overflow-wrap:anywhere}.card-actions{display:flex;flex-wrap:wrap;align-items:center;gap:8px}.meta{display:flex;flex-wrap:wrap;align-items:center;gap:6px 12px;color:var(--nha-text-muted);font-size:12px;overflow-wrap:anywhere}pre{max-height:220px;margin:0;overflow:auto;border-radius:var(--nha-radius-control);padding:8px 10px;background:var(--nha-surface-muted, rgba(127, 127, 127, .08));font-family:var(--nha-mono);font-size:12px;white-space:pre-wrap;overflow-wrap:anywhere}.summary{margin:0;font-size:13px;overflow-wrap:anywhere}.presentation-fields{display:grid;gap:6px;margin:0}.presentation-fields div{display:grid;grid-template-columns:minmax(90px,.4fr) minmax(0,1fr);gap:8px}.presentation-fields dt{color:var(--nha-text-muted);font-size:12px;font-weight:700;overflow-wrap:anywhere}.presentation-fields dd{margin:0;font-size:13px;overflow-wrap:anywhere}.technical-details{color:var(--nha-text-muted);font-size:12px}.technical-details summary{cursor:pointer;font-weight:700}.technical-details code{overflow-wrap:anywhere}.technical-details .label{margin:10px 0 4px;font-size:11px;font-weight:700;text-transform:uppercase;letter-spacing:.04em}.technical-details .targets{margin:0;padding-left:18px;overflow-wrap:anywhere}.tabs{display:flex;flex-wrap:wrap;gap:4px;border-bottom:1px solid var(--nha-border)}.tabs button{border:0;border-bottom:2px solid transparent;border-radius:0;padding:8px 12px;background:transparent;color:var(--nha-text-muted);font:inherit;cursor:pointer}.tabs button[aria-selected=true]{border-bottom-color:currentColor;color:var(--nha-text);font-weight:650}.toolbar{display:flex;flex-wrap:wrap;align-items:center;gap:8px}.reason{flex:1 1 200px;min-width:0}.select{display:inline-flex;align-items:center;gap:6px;font-size:12px}.proposal-list{display:flex;flex-direction:column;gap:10px;min-width:0}.feedback-prompt{display:flex;flex-direction:column;gap:6px;min-width:0}.feedback-prompt .muted{overflow-wrap:anywhere}.text-button{display:inline-flex;align-items:center;border:0;border-radius:6px;padding:2px 4px;color:var(--nha-text-muted);background:transparent;font:inherit;font-size:12px;font-weight:650;text-decoration:underline;text-underline-offset:2px;cursor:pointer}.text-button:focus-visible{outline:3px solid color-mix(in srgb,var(--nha-focus) 80%,transparent);outline-offset:2px}.text-button:hover:not(:disabled){color:var(--nha-text)}.text-button:disabled{cursor:not-allowed;opacity:.55}.waiting-for{display:flex;align-items:center;gap:6px;margin:0;color:var(--nha-text-muted);font-size:12px;overflow-wrap:anywhere}.subject-agents{display:grid;gap:8px;margin:0;padding:0;list-style:none}.subject-agent{display:flex;flex-wrap:wrap;align-items:center;justify-content:space-between;gap:8px 12px;min-width:0;border:1px solid var(--nha-border);border-radius:var(--nha-radius-control);padding:10px 12px}.subject-agent-text{display:flex;flex-direction:column;gap:2px;min-width:0}.subject-agent-text strong{font-size:14px;overflow-wrap:anywhere}\n"], dependencies: [{ kind: "component", type: _NhAssistantIconComponent, selector: "nh-assistant-icon", inputs: ["name"] }, { kind: "component", type: NhAssistantAgentProposalsComponent, selector: "nh-assistant-agent-proposals", inputs: ["proposals", "canDecide", "decisionRights", "selectable", "holdClosedCards"], outputs: ["changed"] }, { kind: "pipe", type: TranslatePipe, name: "translate" }, { kind: "pipe", type: _NhAssistantTranslatePipe, name: "nhAssistantTranslate" }], changeDetection: i0.ChangeDetectionStrategy.OnPush }); }
|
|
1009
|
+
}
|
|
1010
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.33", ngImport: i0, type: NhAssistantSubjectSuggestionsComponent, decorators: [{
|
|
1011
|
+
type: Component,
|
|
1012
|
+
args: [{ selector: 'nh-assistant-subject-suggestions', standalone: true, imports: [TranslatePipe, _NhAssistantTranslatePipe, _NhAssistantIconComponent, NhAssistantAgentProposalsComponent], changeDetection: ChangeDetectionStrategy.OnPush, template: "<section class=\"section\" [attr.aria-labelledby]=\"headingId\" [attr.aria-busy]=\"loading()\">\n <header class=\"section-header\">\n <div>\n <h3 [id]=\"headingId\">{{ 'nh-assistant.agent-runs.subject.title' | translate }}</h3>\n <p class=\"muted\">{{ 'nh-assistant.agent-runs.subject.description' | translate }}</p>\n </div>\n <button class=\"secondary\" type=\"button\" [disabled]=\"loading()\" (click)=\"load()\">\n <nh-assistant-icon name=\"refresh\" />{{ 'nh-assistant.agent-runs.refresh' | translate }}\n </button>\n </header>\n\n @if (error(); as failure) {\n <p class=\"message error\" role=\"alert\"><nh-assistant-icon name=\"warning\" />{{ errorKeys() | nhAssistantTranslate: failure.code }}</p>\n }\n @if (started(); as start) {\n <p class=\"message success\" role=\"status\">\n <nh-assistant-icon name=\"check\" />{{ 'nh-assistant.agent-runs.thread.outcome.' + start.receipt.outcome | translate }}\n </p>\n }\n\n @if (loading() && !loaded()) {\n <p class=\"state\" role=\"status\">{{ 'nh-assistant.agent-runs.loading' | translate }}</p>\n } @else if (unavailable()) {\n <p class=\"state\">{{ 'nh-assistant.agent-runs.subject.unavailable' | translate }}</p>\n } @else if (loadFailed()) {\n <div class=\"state\" role=\"alert\">\n <p>{{ 'nh-assistant.agent-runs.load-failed' | translate }}</p>\n <button class=\"secondary\" type=\"button\" (click)=\"load()\">{{ 'nh-assistant.agent-runs.retry' | translate }}</button>\n </div>\n } @else {\n @if (agents().length > 0) {\n <ul class=\"subject-agents\" [attr.aria-label]=\"'nh-assistant.agent-runs.subject.agents' | translate\">\n @for (agent of agents(); track agent.agentId) {\n @let name = agentNameKeys(agent.agentId) | nhAssistantTranslate: agent.agentId;\n <li class=\"subject-agent\">\n <div class=\"subject-agent-text\">\n <strong>{{ name }}</strong>\n <span class=\"muted\">\n @if (agent.thread?.activeRun; as activeRun) {\n {{ 'nh-assistant.agent-runs.run.status.' + activeRun.status | translate }}\n } @else if (!agent.thread) {\n {{ 'nh-assistant.agent-runs.thread.no-thread' | translate }}\n } @else {\n {{ 'nh-assistant.agent-runs.subject.idle' | translate }}\n }\n </span>\n </div>\n <div class=\"card-actions\">\n @if (canOpen(agent)) {\n <button\n class=\"secondary\"\n type=\"button\"\n [disabled]=\"opening() !== null || !assistantEnabled()\"\n [attr.aria-label]=\"'nh-assistant.agent-runs.subject.open-conversation-label' | translate: { agent: name }\"\n [attr.title]=\"assistantEnabled() ? null : ('nh-assistant.agent-runs.subject.assistant-unavailable' | translate)\"\n (click)=\"open(agent)\">\n <nh-assistant-icon name=\"assistant\" />{{ (opening() === agent.agentId ? 'nh-assistant.agent-runs.subject.opening' : 'nh-assistant.agent-runs.thread.open-conversation') | translate }}\n </button>\n }\n @if (agent.canStart) {\n <button\n class=\"secondary\"\n type=\"button\"\n [disabled]=\"starting() !== null\"\n [attr.aria-label]=\"'nh-assistant.agent-runs.subject.start-label' | translate: { agent: name }\"\n (click)=\"start(agent)\">\n <nh-assistant-icon name=\"send\" />{{ (starting() === agent.agentId ? 'nh-assistant.agent-runs.thread.starting' : 'nh-assistant.agent-runs.thread.start') | translate }}\n </button>\n }\n </div>\n </li>\n }\n </ul>\n }\n\n <!-- Stays rendered when the list empties, so the optional feedback after a rejection remains. -->\n <nh-assistant-agent-proposals\n [proposals]=\"proposals()\"\n [decisionRights]=\"decisionRights()\"\n [holdClosedCards]=\"true\"\n (changed)=\"load()\" />\n @if (proposals().length === 0) {\n <p class=\"state\">{{ 'nh-assistant.agent-runs.subject.empty' | translate }}</p>\n }\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:block;min-width:0;color:var(--nha-text);font-family:var(--nha-font);font-size:14px}: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}.section{display:flex;flex-direction:column;gap:14px;min-width:0}.section-header{display:flex;flex-wrap:wrap;align-items:flex-start;justify-content:space-between;gap:12px}.section-header>div{min-width:0;max-width:72ch}h3{margin:0 0 4px;font-size:17px;font-weight:750}.muted{margin:0;color:var(--nha-text-muted);font-size:13px}.state{display:flex;flex-direction:column;align-items:flex-start;gap:10px;margin:0;border:1px dashed var(--nha-border);border-radius:var(--nha-radius);padding:18px;color:var(--nha-text-muted);font-size:13px}.state p{margin:0}.cards{display:grid;gap:10px;margin:0;padding:0;list-style:none}.card{display:flex;flex-direction:column;gap:8px;min-width:0;border:1px solid var(--nha-border);border-radius:var(--nha-radius);padding:12px 14px;background:var(--nha-surface)}.card.selected{border-color:var(--nha-accent, currentColor)}.card[tabindex]:focus-visible{outline:3px solid color-mix(in srgb,var(--nha-focus) 80%,transparent);outline-offset:2px}.card.closed{border-style:dashed}.closed-card{display:flex;flex-wrap:wrap;align-items:center;justify-content:space-between;gap:8px}.message.stale-explanation{overflow-wrap:anywhere;color:var(--nha-text);background:var(--nha-surface-strong)}.rationale{margin:0;overflow-wrap:anywhere;color:var(--nha-text-muted);font-size:13px}.card-header{display:flex;flex-wrap:wrap;align-items:center;gap:8px;min-width:0}.card-header strong{font-size:14px;overflow-wrap:anywhere}.card-actions{display:flex;flex-wrap:wrap;align-items:center;gap:8px}.meta{display:flex;flex-wrap:wrap;align-items:center;gap:6px 12px;color:var(--nha-text-muted);font-size:12px;overflow-wrap:anywhere}pre{max-height:220px;margin:0;overflow:auto;border-radius:var(--nha-radius-control);padding:8px 10px;background:var(--nha-surface-muted, rgba(127, 127, 127, .08));font-family:var(--nha-mono);font-size:12px;white-space:pre-wrap;overflow-wrap:anywhere}.summary{margin:0;font-size:13px;overflow-wrap:anywhere}.presentation-fields{display:grid;gap:6px;margin:0}.presentation-fields div{display:grid;grid-template-columns:minmax(90px,.4fr) minmax(0,1fr);gap:8px}.presentation-fields dt{color:var(--nha-text-muted);font-size:12px;font-weight:700;overflow-wrap:anywhere}.presentation-fields dd{margin:0;font-size:13px;overflow-wrap:anywhere}.technical-details{color:var(--nha-text-muted);font-size:12px}.technical-details summary{cursor:pointer;font-weight:700}.technical-details code{overflow-wrap:anywhere}.technical-details .label{margin:10px 0 4px;font-size:11px;font-weight:700;text-transform:uppercase;letter-spacing:.04em}.technical-details .targets{margin:0;padding-left:18px;overflow-wrap:anywhere}.tabs{display:flex;flex-wrap:wrap;gap:4px;border-bottom:1px solid var(--nha-border)}.tabs button{border:0;border-bottom:2px solid transparent;border-radius:0;padding:8px 12px;background:transparent;color:var(--nha-text-muted);font:inherit;cursor:pointer}.tabs button[aria-selected=true]{border-bottom-color:currentColor;color:var(--nha-text);font-weight:650}.toolbar{display:flex;flex-wrap:wrap;align-items:center;gap:8px}.reason{flex:1 1 200px;min-width:0}.select{display:inline-flex;align-items:center;gap:6px;font-size:12px}.proposal-list{display:flex;flex-direction:column;gap:10px;min-width:0}.feedback-prompt{display:flex;flex-direction:column;gap:6px;min-width:0}.feedback-prompt .muted{overflow-wrap:anywhere}.text-button{display:inline-flex;align-items:center;border:0;border-radius:6px;padding:2px 4px;color:var(--nha-text-muted);background:transparent;font:inherit;font-size:12px;font-weight:650;text-decoration:underline;text-underline-offset:2px;cursor:pointer}.text-button:focus-visible{outline:3px solid color-mix(in srgb,var(--nha-focus) 80%,transparent);outline-offset:2px}.text-button:hover:not(:disabled){color:var(--nha-text)}.text-button:disabled{cursor:not-allowed;opacity:.55}.waiting-for{display:flex;align-items:center;gap:6px;margin:0;color:var(--nha-text-muted);font-size:12px;overflow-wrap:anywhere}.subject-agents{display:grid;gap:8px;margin:0;padding:0;list-style:none}.subject-agent{display:flex;flex-wrap:wrap;align-items:center;justify-content:space-between;gap:8px 12px;min-width:0;border:1px solid var(--nha-border);border-radius:var(--nha-radius-control);padding:10px 12px}.subject-agent-text{display:flex;flex-direction:column;gap:2px;min-width:0}.subject-agent-text strong{font-size:14px;overflow-wrap:anywhere}\n"] }]
|
|
1013
|
+
}], ctorParameters: () => [], propDecorators: { proposalList: [{ type: i0.ViewChild, args: [i0.forwardRef(() => NhAssistantAgentProposalsComponent), { isSignal: true }] }], subjectType: [{ type: i0.Input, args: [{ isSignal: true, alias: "subjectType", required: true }] }], subjectId: [{ type: i0.Input, args: [{ isSignal: true, alias: "subjectId", required: true }] }], agentId: [{ type: i0.Input, args: [{ isSignal: true, alias: "agentId", required: false }] }], conversationOpened: [{ type: i0.Output, args: ["conversationOpened"] }] } });
|
|
1014
|
+
|
|
1015
|
+
/*
|
|
1016
|
+
* Public API surface of @newheap/platform-ai-chat/agent-runs.
|
|
1017
|
+
*
|
|
1018
|
+
* Agents that run on their own are a separate entry point, so hosts load the inbox and the
|
|
1019
|
+
* subject views only on the routes that show them and the chat panel stays small. The
|
|
1020
|
+
* components use `NhAssistantAgentRunApiService` from the `provideNhAssistant` scope and reload
|
|
1021
|
+
* by themselves on the agent-work updates of its `NhAssistantLiveService`.
|
|
1022
|
+
*/
|
|
1023
|
+
|
|
1024
|
+
/**
|
|
1025
|
+
* Generated bundle index. Do not edit.
|
|
1026
|
+
*/
|
|
1027
|
+
|
|
1028
|
+
export { NhAssistantAgentArtifactsComponent, NhAssistantAgentConsultationsComponent, NhAssistantAgentInboxComponent, NhAssistantAgentMemoryComponent, NhAssistantAgentProposalsComponent, NhAssistantAgentThreadViewComponent, NhAssistantRunTimelineComponent, NhAssistantSubjectSuggestionsComponent };
|
|
1029
|
+
//# sourceMappingURL=newheap-platform-ai-chat-agent-runs.mjs.map
|