@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/index.d.ts CHANGED
@@ -4,6 +4,327 @@ import { Observable } from 'rxjs';
4
4
  import { TranslationObject } from '@ngx-translate/core';
5
5
  import { TemplatePortal } from '@angular/cdk/portal';
6
6
 
7
+ /**
8
+ * Contracts of the agent-run endpoints of `NewHeap.Platform.AI.Chat.AspNet`: threads about a
9
+ * subject, runs, proposals, the approval inbox, working memory and artifacts.
10
+ */
11
+ /** The caller's role on the subject of a thread. */
12
+ type AgentSubjectRole = 'none' | 'reader' | 'participant' | 'approver';
13
+ type AgentRunStatus = 'queued' | 'running' | 'waiting-for-approval' | 'completed' | 'failed' | 'cancelled';
14
+ type AgentProposalStatus = 'pending' | 'approved' | 'rejected' | 'expired' | 'withdrawn' | 'stale' | 'executing' | 'executed' | 'execution-failed' | 'execution-unknown' | 'resolved' | 'shadow';
15
+ type AgentGrantSource = 'none' | 'delegated' | 'agent';
16
+ /**
17
+ * How a run worked: `model` through the language model, `rule` through the agent's rules without a
18
+ * model, `rule-then-model` when the rules handed the run over to the model.
19
+ */
20
+ type AgentRunKind = 'model' | 'rule' | 'rule-then-model';
21
+ interface AgentRun {
22
+ id: string;
23
+ conversationId: string;
24
+ triggerId: string;
25
+ status: AgentRunStatus;
26
+ failureClass: string | null;
27
+ failureCode: string | null;
28
+ initiatorActorId: string | null;
29
+ accountableOwnerId: string;
30
+ attempt: number;
31
+ agentVersion: number;
32
+ toolCalls: number;
33
+ inputTokens: number;
34
+ outputTokens: number;
35
+ proposalCount: number;
36
+ summary: string | null;
37
+ shadow: boolean;
38
+ createdAt: string;
39
+ startedAt: string | null;
40
+ endedAt: string | null;
41
+ backgroundOperationId: string | null;
42
+ /** How the run worked. Missing on older servers, which only ran the model. */
43
+ kind?: AgentRunKind;
44
+ }
45
+ interface AgentRunList {
46
+ items: AgentRun[];
47
+ total: number;
48
+ }
49
+ interface AgentThread {
50
+ conversationId: string;
51
+ agentId: string;
52
+ subjectType: string;
53
+ subjectId: string;
54
+ subjectDisplayName: string | null;
55
+ accountability: string;
56
+ accountableOwnerId: string;
57
+ role: AgentSubjectRole;
58
+ activeRun: AgentRun | null;
59
+ waitingInputs: number;
60
+ }
61
+ interface AgentThreadLookup {
62
+ thread: AgentThread | null;
63
+ canStart: boolean;
64
+ role: AgentSubjectRole;
65
+ }
66
+ /** The caller's live right to decide one open proposal; the server checks every decision again. */
67
+ interface AgentProposalDecisionRight {
68
+ canDecide: boolean;
69
+ /**
70
+ * Why the caller may not decide, for example `assistant-four-eyes-required` or
71
+ * `assistant-approval-policy-denied`; `null` when they may.
72
+ */
73
+ reasonCode: string | null;
74
+ }
75
+ /** One agent on a subject: its thread, `null` before it worked on the subject, and whether the caller may start it. */
76
+ interface AgentSubjectWorkAgent {
77
+ agentId: string;
78
+ thread: AgentThread | null;
79
+ canStart: boolean;
80
+ }
81
+ /**
82
+ * A proposal on a subject with the caller's live decision right. Only a pending proposal can be
83
+ * decided; for every other status `canDecide` is `false` and `reasonCode` is `null`.
84
+ */
85
+ interface AgentSubjectWorkProposal extends AgentProposalDecisionRight {
86
+ proposal: AgentProposal;
87
+ }
88
+ /** The most proposals one `POST approvals/lookup` reads. */
89
+ declare const NH_ASSISTANT_MAX_PROPOSAL_LOOKUP = 100;
90
+ /**
91
+ * Response of `POST approvals/lookup`: the requested proposals the caller may see, in the order of
92
+ * the request. Ids the caller may not see, or that do not exist, are left out.
93
+ */
94
+ interface AgentProposalLookup {
95
+ items: AgentSubjectWorkProposal[];
96
+ }
97
+ /**
98
+ * All agent work on one subject as the caller may see it (`GET subjects/{type}/{id}/work`): every
99
+ * agent with a thread on the subject plus the requested agent, and the pending proposals of all
100
+ * those threads, the earliest expiry first.
101
+ */
102
+ interface AgentSubjectWork {
103
+ subjectType: string;
104
+ subjectId: string;
105
+ subjectDisplayName: string | null;
106
+ /** The caller's live role. Without a role the server answers `404 assistant-subject-not-found`. */
107
+ role: Exclude<AgentSubjectRole, 'none'>;
108
+ agents: AgentSubjectWorkAgent[];
109
+ openProposals: AgentSubjectWorkProposal[];
110
+ }
111
+ /** The agent work on one subject for a list view (`POST subjects/{type}/summary`). */
112
+ interface AgentSubjectSummary {
113
+ subjectId: string;
114
+ /** Proposals that wait for a decision on the subject. */
115
+ openProposals: number;
116
+ /** The open proposals the caller may decide, counted like the approval inbox. */
117
+ proposalsToDecide: number;
118
+ /** An agent works on the subject now. */
119
+ runActive: boolean;
120
+ }
121
+ /** One summary per requested subject, in request order; subjects without visible work count zero. */
122
+ interface AgentSubjectSummaryList {
123
+ subjectType: string;
124
+ items: AgentSubjectSummary[];
125
+ }
126
+ /** Maximum number of subjects one `POST subjects/{type}/summary` request accepts. */
127
+ declare const NH_ASSISTANT_MAX_SUBJECT_SUMMARY = 200;
128
+ interface StartAgentRequest {
129
+ agentId: string;
130
+ subjectType: string;
131
+ subjectId: string;
132
+ message?: string | null;
133
+ }
134
+ interface AgentTriggerReceipt {
135
+ triggerId: string;
136
+ outcome: 'started' | 'queued' | 'coalesced' | 'superseded' | 'ignored' | 'deduplicated' | 'rejected';
137
+ runId: string | null;
138
+ conversationId: string | null;
139
+ reasonCode: string | null;
140
+ }
141
+ interface AgentProposal {
142
+ approvalId: string;
143
+ proposalId: string;
144
+ proposalHash: string;
145
+ conversationId: string;
146
+ runId: string | null;
147
+ agentId: string;
148
+ subjectType: string;
149
+ subjectId: string;
150
+ subjectDisplayName: string | null;
151
+ toolId: string;
152
+ summary: string;
153
+ /**
154
+ * The application's localized explanation, written when the proposal was recorded. Show it
155
+ * instead of `argumentsPreview`; `null` when no presenter handled the tool.
156
+ */
157
+ presentation: ApprovalPresentation | null;
158
+ argumentsPreview: string;
159
+ targets: string[];
160
+ status: AgentProposalStatus;
161
+ mode: 'inline' | 'deferred';
162
+ policyId: string | null;
163
+ grantSource: AgentGrantSource;
164
+ createdAt: string;
165
+ expiresAt: string;
166
+ initiatorActorId: string | null;
167
+ decidedByActorId: string | null;
168
+ /**
169
+ * The name of `decidedByActorId` from the subject's member snapshot; `null` when the snapshot
170
+ * does not know the person. Show `decidedByActorId` then. Missing on older servers.
171
+ */
172
+ decidedByDisplayName?: string | null;
173
+ decidedAt: string | null;
174
+ executionResultCode: string | null;
175
+ executedAt: string | null;
176
+ /**
177
+ * The consultation that proposed it, when another assistant consulted the agent for
178
+ * `initiatorActorId`; it executes with that person's rights only.
179
+ */
180
+ consultationId?: string | null;
181
+ /** The caller's own feedback on the proposal; `null` when they gave none. Missing on older servers. */
182
+ feedback?: AgentProposalFeedback | null;
183
+ /**
184
+ * Whether the caller may give or change feedback: the proposal was rejected, expired, withdrawn or
185
+ * closed as stale, and the caller decided it or is an approver of the subject. Missing on older servers.
186
+ */
187
+ canGiveFeedback?: boolean;
188
+ /**
189
+ * Why a stale proposal no longer fits; `null` for other statuses. Its reason code is
190
+ * `executionResultCode`. Missing on older servers.
191
+ */
192
+ staleKind?: StaleKind | null;
193
+ /**
194
+ * The application's explanation of a stale proposal in the caller's language, such as who already
195
+ * did the work; `null` when it gave none. Missing on older servers.
196
+ */
197
+ staleExplanation?: string | null;
198
+ /**
199
+ * Who made the proposal stale, when the application's guard named them; `null` otherwise.
200
+ * Missing on older servers.
201
+ */
202
+ staleByActorId?: string | null;
203
+ /** The name of `staleByActorId` from the subject's member snapshot; `null` when unknown. */
204
+ staleByDisplayName?: string | null;
205
+ /**
206
+ * The application objects the proposal changes, as its guards named them, so lists can group
207
+ * proposals by object. `targets` holds execution scopes instead. Missing on older servers.
208
+ */
209
+ objects?: AgentProposalObject[];
210
+ /**
211
+ * The newer proposal for the same objects that replaced this withdrawn one; `null` otherwise.
212
+ * Missing on older servers.
213
+ */
214
+ supersededByApprovalId?: string | null;
215
+ /**
216
+ * Why the agent's rules proposed it, in the caller's language; `null` for proposals of the model.
217
+ * Missing on older servers.
218
+ */
219
+ rationale?: string | null;
220
+ }
221
+ /** An application object a proposal changes, such as `{ type: 'project-task', id: '4711' }`. */
222
+ interface AgentProposalObject {
223
+ type: string;
224
+ id: string;
225
+ }
226
+ /**
227
+ * Why a person rejected a proposal. `incorrect`, `wrong-value` and `not-needed` say the agent was
228
+ * wrong; `not-now` and `already-done` say it was right but not at this moment; `not-allowed` says
229
+ * it went beyond what the agent should do; `other` leaves the explanation to the text.
230
+ */
231
+ type AgentProposalFeedbackCategory = 'incorrect' | 'wrong-value' | 'not-needed' | 'not-now' | 'already-done' | 'not-allowed' | 'other';
232
+ /** The group of a feedback category. `right-but-not-now` never counts as "the agent was wrong". */
233
+ type AgentProposalFeedbackGroup = 'wrong' | 'right-but-not-now' | 'not-allowed' | 'other';
234
+ /** The feedback categories in the order people choose them. */
235
+ declare const NH_ASSISTANT_FEEDBACK_CATEGORIES: readonly AgentProposalFeedbackCategory[];
236
+ /** The group of each feedback category, as the server reports it. */
237
+ declare const NH_ASSISTANT_FEEDBACK_GROUPS: Readonly<Record<AgentProposalFeedbackCategory, AgentProposalFeedbackGroup>>;
238
+ /** Maximum length of the text of a feedback. */
239
+ declare const NH_ASSISTANT_MAX_FEEDBACK_TEXT = 1000;
240
+ /** Maximum number of proposals one `POST approvals/feedback` request accepts. */
241
+ declare const NH_ASSISTANT_MAX_BULK_FEEDBACK = 50;
242
+ /**
243
+ * One person's feedback on a rejected or otherwise closed proposal. It is separate from the
244
+ * decision's reason, arrives after the decision and can be changed by its author.
245
+ */
246
+ interface AgentProposalFeedback {
247
+ approvalId: string;
248
+ category: AgentProposalFeedbackCategory;
249
+ group: AgentProposalFeedbackGroup;
250
+ text: string | null;
251
+ /** Given once for several proposals that were rejected together. */
252
+ bulk: boolean;
253
+ createdAt: string;
254
+ updatedAt: string;
255
+ }
256
+ /** The outcome of the feedback on one proposal of `POST approvals/feedback`. */
257
+ interface AgentFeedbackOutcome {
258
+ approvalId: string;
259
+ succeeded: boolean;
260
+ /** For example `assistant-feedback-not-accepted`; `null` when it succeeded. */
261
+ code: string | null;
262
+ }
263
+ type AgentConsultationStatus = 'running' | 'completed' | 'failed';
264
+ /**
265
+ * One consultation of a thread's agent by another assistant. It names who asked and through which
266
+ * assistant; the question and the answer stay in the asking conversation.
267
+ */
268
+ interface AgentConsultation {
269
+ id: string;
270
+ askerActorId: string;
271
+ /** The asker's name from the subject's members, when known. */
272
+ askerDisplayName: string | null;
273
+ askingAgentId: string | null;
274
+ depth: number;
275
+ status: AgentConsultationStatus;
276
+ failureCode: string | null;
277
+ toolCalls: number;
278
+ inputTokens: number;
279
+ outputTokens: number;
280
+ proposalCount: number;
281
+ createdAt: string;
282
+ endedAt: string | null;
283
+ }
284
+ interface AgentConsultationList {
285
+ items: AgentConsultation[];
286
+ total: number;
287
+ }
288
+ interface AgentInbox {
289
+ items: AgentProposal[];
290
+ total: number;
291
+ }
292
+ interface AgentInboxFilter {
293
+ subjectType?: string;
294
+ agentId?: string;
295
+ divisionId?: string;
296
+ runId?: string;
297
+ page?: number;
298
+ itemsPerPage?: number;
299
+ }
300
+ type AgentProposalDecision = 'approve' | 'reject';
301
+ interface AgentDecisionOutcome {
302
+ approvalId: string;
303
+ succeeded: boolean;
304
+ code: string | null;
305
+ status: AgentProposalStatus | null;
306
+ }
307
+ interface AgentThreadMemory {
308
+ configured: boolean;
309
+ schemaVersion: number;
310
+ memory: unknown;
311
+ updatedAt: string | null;
312
+ }
313
+ interface AgentArtifact {
314
+ id: string;
315
+ name: string;
316
+ version: number;
317
+ contentType: string;
318
+ sizeBytes: number;
319
+ createdAt: string;
320
+ runId: string | null;
321
+ restricted: boolean;
322
+ }
323
+ /** `resume` continues the run from its last checkpoint; `restart` starts a new run in the thread. */
324
+ type AgentRunRetryMode = 'resume' | 'restart';
325
+ /** `re-execute` runs the proposal again; `mark-resolved` confirms its outcome without running it. */
326
+ type AgentExecutionResolution = 're-execute' | 'mark-resolved';
327
+
7
328
  interface AssistantStatus {
8
329
  enabled: boolean;
9
330
  agents: AgentSummary[];
@@ -63,6 +384,43 @@ interface Conversation extends ConversationSummary {
63
384
  shareToken?: string | null;
64
385
  /** The caller's actor id, to recognize the caller's own messages. */
65
386
  currentActorId?: string | null;
387
+ /** Default `chat` for servers without agent runs. */
388
+ kind?: ConversationKind;
389
+ /**
390
+ * The subject of an agent thread and the caller's standing in it, including who may decide its
391
+ * open proposals; `null` for a chat.
392
+ */
393
+ thread?: ConversationThread | null;
394
+ }
395
+ /** `chat` for a conversation people start; `thread` for the durable thread of an agent about one subject. */
396
+ type ConversationKind = 'chat' | 'thread';
397
+ /**
398
+ * The subject of an agent thread as the caller sees it. In a thread the subject's approvers decide
399
+ * the agent's proposals, not the author of a turn. The server checks the role on every request.
400
+ */
401
+ interface ConversationThread {
402
+ subjectType: string;
403
+ subjectId: string;
404
+ subjectDisplayName: string | null;
405
+ /** The caller's live role on the subject. */
406
+ role: AgentSubjectRole;
407
+ /** Each open proposal of the thread and whether the caller may decide it now, oldest first. */
408
+ decisions: ConversationThreadDecision[];
409
+ }
410
+ /**
411
+ * The caller's right to decide one open proposal of an agent thread, checked like the decision
412
+ * itself: the approval policy, four-eyes and the tool's approve policy.
413
+ */
414
+ interface ConversationThreadDecision {
415
+ approvalId: string;
416
+ /**
417
+ * The run that proposed it; such a proposal is decided with `POST approvals/{id}/decisions`.
418
+ * `null` for a proposal of a person's turn in the thread, decided in the conversation.
419
+ */
420
+ runId: string | null;
421
+ canDecide: boolean;
422
+ /** Why the caller may not decide, for example `assistant-four-eyes-required`; `null` when they may. */
423
+ reasonCode: string | null;
66
424
  }
67
425
  type ConversationStatus = 'idle' | 'running' | 'waiting-for-approval' | 'failed' | 'archived';
68
426
  /** The owner or a participant of a shared conversation. */
@@ -82,13 +440,29 @@ interface Message {
82
440
  sequence?: number;
83
441
  /** The writer of a user message. */
84
442
  authorActorId?: string | null;
443
+ /**
444
+ * Who wrote the message: a person or a trigger of an agent for user messages, `rule` for the
445
+ * summary an agent's rules wrote instead of the model; missing on old servers.
446
+ */
447
+ authorKind?: MessageAuthorKind | null;
85
448
  }
449
+ /**
450
+ * `person` for a message a person wrote; `trigger` for one a trigger wrote into an agent thread;
451
+ * `rule` for an assistant message the agent's rules wrote without a model.
452
+ */
453
+ type MessageAuthorKind = 'person' | 'trigger' | 'rule';
86
454
  type MessagePart = TextPart | ToolCallPart | ApprovalPart;
87
455
  interface TextPart {
88
456
  type: 'text';
89
457
  text: string;
90
458
  }
91
- type ToolCallStatus = 'running' | 'succeeded' | 'failed' | 'awaiting-approval' | 'rejected';
459
+ /**
460
+ * `awaiting-approval` waits for a person. A call whose agent proposal closed without running ends
461
+ * as `rejected`, as `not-executed` when the proposal expired, was withdrawn or became stale, or as
462
+ * `failed` when its execution failed before it started; its `resultCode` is then
463
+ * `assistant-proposal-<approval status>`, for example `assistant-proposal-expired`.
464
+ */
465
+ type ToolCallStatus = 'running' | 'succeeded' | 'failed' | 'awaiting-approval' | 'rejected' | 'not-executed';
92
466
  interface ToolCallPart {
93
467
  type: 'tool-call';
94
468
  invocationId: string;
@@ -99,8 +473,17 @@ interface ToolCallPart {
99
473
  argumentsPreview: string | null;
100
474
  resultPreview: string | null;
101
475
  resultCode: string | null;
476
+ /** `delegated` or `agent` when an agent used rights beyond the caller's own. */
477
+ grantSource?: 'delegated' | 'agent' | null;
478
+ /** The result came from the agent's own grant and is shielded from this viewer. */
479
+ restricted?: boolean;
102
480
  }
103
- type ApprovalStatus = 'pending' | 'approved' | 'rejected' | 'expired';
481
+ /**
482
+ * Chat approvals are `pending`, `approved`, `rejected` or `expired`; proposals of agents that run on
483
+ * their own continue through execution (`executing`, `executed`, `execution-failed`,
484
+ * `execution-unknown`, `resolved`) or end as `withdrawn`, `stale` or `shadow`.
485
+ */
486
+ type ApprovalStatus = 'pending' | 'approved' | 'rejected' | 'expired' | 'withdrawn' | 'stale' | 'executing' | 'executed' | 'execution-failed' | 'execution-unknown' | 'resolved' | 'shadow';
104
487
  interface ApprovalPresentationField {
105
488
  label: string;
106
489
  value: string;
@@ -111,6 +494,11 @@ interface ApprovalPresentation {
111
494
  fields: ApprovalPresentationField[];
112
495
  notice: string | null;
113
496
  }
497
+ /**
498
+ * Why a stale proposal no longer fits: the work was already done another way, what it was based on
499
+ * changed, or it no longer applies.
500
+ */
501
+ type StaleKind = 'already-done' | 'changed' | 'not-applicable';
114
502
  interface ApprovalPart {
115
503
  type: 'approval';
116
504
  approvalId: string;
@@ -124,6 +512,14 @@ interface ApprovalPart {
124
512
  targets: string[];
125
513
  expiresAt: string;
126
514
  status: ApprovalStatus;
515
+ /** Why a stale proposal no longer fits. Only sent for stale proposals; missing on older servers. */
516
+ staleKind?: StaleKind;
517
+ /** The application's explanation of a stale proposal in the reader's language, such as who did the work. */
518
+ staleExplanation?: string;
519
+ /** Why the agent's rules proposed it, in the reader's language. Only sent for rule proposals. */
520
+ rationale?: string;
521
+ /** The newer proposal for the same objects that replaced this withdrawn one. Only sent then. */
522
+ supersededByApprovalId?: string;
127
523
  }
128
524
  /** Response of `GET conversations?page=&itemsPerPage=`. */
129
525
  interface ConversationPage {
@@ -298,6 +694,23 @@ interface LiveConversationRead {
298
694
  interface LiveConversationRemoved {
299
695
  conversationId: string;
300
696
  }
697
+ /** What changed in an agent thread: a run, a proposal or the feedback on a proposal. */
698
+ type LiveAgentWorkReason = 'run' | 'proposal' | 'feedback';
699
+ /**
700
+ * `AgentWorkChanged`: a run of an agent thread started, waits, ended or was cancelled, a proposal
701
+ * was decided, resolved, executed, closed, escalated or expired, or feedback was given. Sent to the
702
+ * thread's participants and everyone on its subject. It carries no content: reload the agent-run
703
+ * endpoints that show the thread, which check access again. It names the thread's subject, so
704
+ * lists and pages of the application refresh by subject without knowing conversation ids.
705
+ */
706
+ interface LiveAgentWorkChanged {
707
+ conversationId: string;
708
+ reason: LiveAgentWorkReason;
709
+ approvalId: string | null;
710
+ runId: string | null;
711
+ subjectType: string;
712
+ subjectId: string;
713
+ }
301
714
  /**
302
715
  * `ConversationEvent`: one turn event with the same `type` and `data` as the server-sent events
303
716
  * of the starting request, or `message.created` with a `Message` when a participant's message
@@ -418,6 +831,123 @@ interface UpdateMcpToolRequest {
418
831
  effect: McpToolEffect;
419
832
  descriptionOverride: string | null;
420
833
  }
834
+ /**
835
+ * Filter of the feedback report of an agent. The server selects proposals by when they were made,
836
+ * defaults to the 30 days before `to` (now) and allows at most 366 days; it only reports scopes the
837
+ * caller administers.
838
+ */
839
+ interface AgentFeedbackFilter {
840
+ /** Start of the period as an ISO 8601 date-time. */
841
+ from?: string;
842
+ /** End of the period, exclusive, as an ISO 8601 date-time. */
843
+ to?: string;
844
+ scopeKey?: string;
845
+ toolId?: string;
846
+ agentVersion?: number;
847
+ }
848
+ /** Filter and page of `GET admin/agents/{id}/feedback`. */
849
+ interface AgentFeedbackListFilter extends AgentFeedbackFilter {
850
+ category?: AgentProposalFeedbackCategory;
851
+ page?: number;
852
+ /** At most 100. */
853
+ itemsPerPage?: number;
854
+ }
855
+ /** Filter of `GET admin/agents/{id}/feedback/export`. */
856
+ interface AgentFeedbackExportFilter extends AgentFeedbackFilter {
857
+ category?: AgentProposalFeedbackCategory;
858
+ /** Maximum number of records; the server defaults to 10,000 and allows at most 50,000. */
859
+ limit?: number;
860
+ }
861
+ interface AgentFeedbackCategoryCount {
862
+ category: AgentProposalFeedbackCategory;
863
+ group: AgentProposalFeedbackGroup;
864
+ count: number;
865
+ }
866
+ /** The proposals of one tool and agent version in the period and what people said about them. */
867
+ interface AgentFeedbackSummaryRow {
868
+ toolId: string;
869
+ /** The agent row version of the runs that proposed them; `null` for proposals of consultations. */
870
+ agentVersion: number | null;
871
+ pending: number;
872
+ /** Approved proposals, including those that executed, failed, closed as stale or were resolved. */
873
+ approved: number;
874
+ rejected: number;
875
+ expired: number;
876
+ withdrawn: number;
877
+ /** Approved proposals closed right before execution because they no longer fit; part of `approved`. */
878
+ stale: number;
879
+ /** Approved proposals whose execution failed; part of `approved`. */
880
+ executionFailed: number;
881
+ /** Rejected divided by approved plus rejected (0..1); `null` before anyone decided. */
882
+ rejectionRate: number | null;
883
+ /** Rejected proposals with at least one feedback. */
884
+ rejectedWithFeedback: number;
885
+ /** Proposals of any status with at least one feedback. */
886
+ feedbackProposals: number;
887
+ /** Different people who gave feedback, so one critical approver counts as one. */
888
+ feedbackAuthors: number;
889
+ categories: AgentFeedbackCategoryCount[];
890
+ /**
891
+ * Open proposals closed before anyone decided because they no longer fit, such as work a person
892
+ * already did. Neither approved nor rejected, and not part of `rejectionRate`. Missing on older servers.
893
+ */
894
+ invalidated?: number;
895
+ /** Why proposals closed as stale, per kind and reason code. Missing on older servers. */
896
+ invalidations?: AgentInvalidationCount[];
897
+ }
898
+ /** Proposals of one tool and agent version that closed as stale for one kind and reason. */
899
+ interface AgentInvalidationCount {
900
+ kind: StaleKind;
901
+ /** The application guard's reason code. */
902
+ reasonCode: string;
903
+ /** True when the proposal closed right before execution, after its approval. */
904
+ afterApproval: boolean;
905
+ count: number;
906
+ }
907
+ /** Response of `GET admin/agents/{id}/feedback/summary`. */
908
+ interface AgentFeedbackSummary {
909
+ agentId: string;
910
+ from: string;
911
+ /** Exclusive end of the period. */
912
+ to: string;
913
+ rows: AgentFeedbackSummaryRow[];
914
+ }
915
+ /** One feedback with the proposal it is about, as approvers read it. */
916
+ interface AgentFeedbackItem {
917
+ id: string;
918
+ approvalId: string;
919
+ proposalId: string;
920
+ conversationId: string;
921
+ runId: string | null;
922
+ scopeKey: string;
923
+ subjectType: string;
924
+ subjectId: string;
925
+ subjectDisplayName: string | null;
926
+ toolId: string;
927
+ agentVersion: number | null;
928
+ /** The proposal's status when the feedback was given. */
929
+ approvalStatus: AgentProposalStatus;
930
+ /** The proposal's summary as the agent recorded it. */
931
+ summary: string;
932
+ presentation: ApprovalPresentation | null;
933
+ category: AgentProposalFeedbackCategory;
934
+ group: AgentProposalFeedbackGroup;
935
+ text: string | null;
936
+ authorActorId: string;
937
+ /**
938
+ * The name of `authorActorId` from the member snapshots; `null` when no snapshot knows the
939
+ * person. Show `authorActorId` then. Missing on older servers.
940
+ */
941
+ authorDisplayName?: string | null;
942
+ bulk: boolean;
943
+ createdAt: string;
944
+ updatedAt: string;
945
+ }
946
+ /** Response of `GET admin/agents/{id}/feedback`, newest change first. */
947
+ interface AgentFeedbackList {
948
+ items: AgentFeedbackItem[];
949
+ total: number;
950
+ }
421
951
 
422
952
  /** Decides whether the current user may see and use the assistant. */
423
953
  interface NhAssistantAccessPolicy {
@@ -432,6 +962,29 @@ interface NhAssistantConfig {
432
962
  * `inject(...)`, for example `() => inject(MyAuthService).getAuthorization()?.token ?? null`.
433
963
  */
434
964
  getAccessToken: () => string | null | Promise<string | null>;
965
+ /**
966
+ * Returns extra headers for every assistant request, for example the NewHeap active division:
967
+ * `() => ({ 'X-NH-ActiveDivisionId': inject(MyAuthService).getAuthorization()?.activeDivision?.id ?? '' })`.
968
+ * Runs in the assistant's injection context before every request, like `getAccessToken`, and
969
+ * when the live-update connection starts. `Authorization`, `Accept`, `Accept-Language` and
970
+ * `Content-Type` stay under the library's control, and empty values are left out. Browsers send
971
+ * no custom headers with the WebSocket and server-sent event transports of the live connection;
972
+ * pass what the hub needs with `getHubQueryParameters`. Default: none.
973
+ */
974
+ getRequestHeaders?: () => Record<string, string> | null | Promise<Record<string, string> | null>;
975
+ /**
976
+ * Returns query parameters for the live-update hub URL: the values the hub needs that browsers
977
+ * cannot send as headers, because the WebSocket and server-sent event transports carry none.
978
+ * Without them a hub that requires such a value refuses those transports and the connection
979
+ * falls back to long polling. For example the NewHeap active division, which the platform's JWT
980
+ * handler copies from `divisionId` to `X-NH-ActiveDivisionId` on `/hub` paths:
981
+ * `() => ({ divisionId: inject(MyAuthService).getAuthorization()?.activeDivision?.id ?? '' })`.
982
+ * Runs in the assistant's injection context each time the connection starts. `access_token`,
983
+ * `id` and `negotiateVersion` stay under the control of the library and SignalR, empty values
984
+ * are left out and a failing getter only leaves the parameters out. Never return a secret: URLs
985
+ * appear in server and proxy logs. Default: none.
986
+ */
987
+ getHubQueryParameters?: () => Record<string, string> | null | Promise<Record<string, string> | null>;
435
988
  /**
436
989
  * Returns what the user has open, sent with each message as untrusted page context.
437
990
  * Runs in the assistant's injection context when the panel opens and before every
@@ -658,11 +1211,106 @@ declare class NhAssistantAdminApiService {
658
1211
  syncMcpServer(serverId: string): Observable<McpTool[]>;
659
1212
  getMcpTools(serverId: string): Observable<McpTool[]>;
660
1213
  updateMcpTool(serverId: string, remoteName: string, request: UpdateMcpToolRequest): Observable<McpTool>;
1214
+ /**
1215
+ * The agent's proposals per tool and agent version in the period: decisions, the rejection rate,
1216
+ * feedback per category and the number of different people who gave it.
1217
+ */
1218
+ getAgentFeedbackSummary(agentId: string, filter?: AgentFeedbackFilter): Observable<AgentFeedbackSummary>;
1219
+ /** The feedback on the agent's proposals with the proposal as approvers read it, newest change first. */
1220
+ getAgentFeedback(agentId: string, filter?: AgentFeedbackListFilter): Observable<AgentFeedbackList>;
1221
+ /**
1222
+ * Downloads the feedback as JSON Lines with the tool input of each proposal. The file holds
1223
+ * subject data and the server audits the export. Rejects with `NhAssistantApiError`.
1224
+ */
1225
+ exportAgentFeedback(agentId: string, filter?: AgentFeedbackExportFilter): Promise<Blob>;
661
1226
  private request;
662
1227
  static ɵfac: _angular_core.ɵɵFactoryDeclaration<NhAssistantAdminApiService, never>;
663
1228
  static ɵprov: _angular_core.ɵɵInjectableDeclaration<NhAssistantAdminApiService>;
664
1229
  }
665
1230
 
1231
+ /**
1232
+ * Client for the agent-run endpoints: the agent thread about a subject, its runs, proposals,
1233
+ * working memory and artifacts, and the approval inbox. Access follows the caller's role on the
1234
+ * subject, which the server checks on every request; failures error with `NhAssistantApiError`.
1235
+ */
1236
+ declare class NhAssistantAgentRunApiService {
1237
+ private readonly transport;
1238
+ /** The agent's thread about the subject, the caller's role and whether the caller may start the agent. */
1239
+ getThread(agentId: string, subjectType: string, subjectId: string): Observable<AgentThreadLookup>;
1240
+ /**
1241
+ * The agent's thread about the subject, created without starting a run when it is missing, so
1242
+ * the caller can open the conversation and type there. Creating a thread needs the participant
1243
+ * role; readers may open an existing one. Errors with `assistant-subject-access-denied` otherwise.
1244
+ */
1245
+ openThread(agentId: string, subjectType: string, subjectId: string): Observable<AgentThreadLookup>;
1246
+ /** Starts the agent on the subject with the caller as initiator; needs the participant role. */
1247
+ startAgent(request: StartAgentRequest): Observable<AgentTriggerReceipt>;
1248
+ /**
1249
+ * All agent work on one subject: the caller's role, every agent with a thread on it plus
1250
+ * `agentId`, and the open proposals of all of them with the caller's live decision right. Errors
1251
+ * with `assistant-subject-not-found` when the caller has no role on the subject.
1252
+ */
1253
+ getSubjectWork(subjectType: string, subjectId: string, agentId?: string): Observable<AgentSubjectWork>;
1254
+ /**
1255
+ * Counts the agent work on at most `NH_ASSISTANT_MAX_SUBJECT_SUMMARY` subjects of one type in one
1256
+ * request, for badges in a list; one item per id in request order. `NhAssistantSubjectSummaryService`
1257
+ * batches and caches these requests for many badges.
1258
+ */
1259
+ summarizeSubjects(subjectType: string, subjectIds: readonly string[]): Observable<AgentSubjectSummaryList>;
1260
+ getRuns(conversationId: string): Observable<AgentRunList>;
1261
+ /** Who consulted the thread's agent through another assistant, newest first. */
1262
+ getConsultations(conversationId: string, page?: number, itemsPerPage?: number): Observable<AgentConsultationList>;
1263
+ getProposals(conversationId: string): Observable<AgentProposal[]>;
1264
+ /**
1265
+ * One proposal of an agent thread in any status, with the caller's live right to decide it, for
1266
+ * example the one an `AgentWorkChanged` update names. Fails with `assistant-approval-not-found`
1267
+ * for an unknown proposal and for one the caller may not see.
1268
+ */
1269
+ getProposal(approvalId: string): Observable<AgentSubjectWorkProposal>;
1270
+ /**
1271
+ * The proposals among at most `NH_ASSISTANT_MAX_PROPOSAL_LOOKUP` ids that the caller may see, in
1272
+ * the order of the ids, each with the caller's live right to decide it. The others are left out.
1273
+ */
1274
+ lookupProposals(approvalIds: readonly string[]): Observable<AgentProposalLookup>;
1275
+ getMemory(conversationId: string): Observable<AgentThreadMemory>;
1276
+ getArtifacts(conversationId: string): Observable<AgentArtifact[]>;
1277
+ /** Downloads one artifact version with the host's credentials. */
1278
+ downloadArtifact(conversationId: string, artifactId: string): Promise<Blob>;
1279
+ /** Cancels a run at its next safe point and withdraws its open proposals; needs the participant role. */
1280
+ cancelRun(runId: string): Observable<void>;
1281
+ /** Resumes or restarts a failed or cancelled run; needs the approver role. */
1282
+ retryRun(runId: string, mode: AgentRunRetryMode): Observable<AgentTriggerReceipt>;
1283
+ /** Pending proposals the caller may decide, sorted by expiry. */
1284
+ getInbox(filter?: AgentInboxFilter): Observable<AgentInbox>;
1285
+ /**
1286
+ * Decides one proposal, bound to the proposal hash the person saw; the server checks the approval
1287
+ * policy and the tool's approve policy again. Accepts an inbox proposal or the approval part of an
1288
+ * agent thread.
1289
+ */
1290
+ decide(proposal: Pick<AgentProposal, 'approvalId' | 'proposalHash'>, decision: AgentProposalDecision, reason?: string): Observable<AgentProposal>;
1291
+ /** Decides several proposals; each one is checked and decided on its own. */
1292
+ decideMany(approvalIds: string[], decision: AgentProposalDecision, reason?: string): Observable<{
1293
+ results: AgentDecisionOutcome[];
1294
+ }>;
1295
+ /** Resolves an execution whose outcome is unknown. */
1296
+ resolve(approvalId: string, action: AgentExecutionResolution, reason?: string): Observable<AgentProposal>;
1297
+ /**
1298
+ * Gives or changes the caller's feedback on a closed proposal (`canGiveFeedback`). Feedback is
1299
+ * optional and separate from the decision; an empty text is sent as `null`. Fails with
1300
+ * `assistant-feedback-not-accepted` while the proposal is pending or after it was approved.
1301
+ */
1302
+ giveFeedback(approvalId: string, category: AgentProposalFeedbackCategory, text?: string | null): Observable<AgentProposalFeedback>;
1303
+ /**
1304
+ * Gives the same feedback on at most `NH_ASSISTANT_MAX_BULK_FEEDBACK` proposals that were
1305
+ * rejected together. Each proposal is checked on its own and stored as bulk feedback.
1306
+ */
1307
+ giveFeedbackMany(approvalIds: readonly string[], category: AgentProposalFeedbackCategory, text?: string | null): Observable<{
1308
+ results: AgentFeedbackOutcome[];
1309
+ }>;
1310
+ static ɵfac: _angular_core.ɵɵFactoryDeclaration<NhAssistantAgentRunApiService, never>;
1311
+ static ɵprov: _angular_core.ɵɵInjectableDeclaration<NhAssistantAgentRunApiService>;
1312
+ }
1313
+
666
1314
  /**
667
1315
  * Applies one assistant event to a conversation and returns the new conversation.
668
1316
  * The input is never mutated, so the result can be stored in a signal directly.
@@ -707,9 +1355,10 @@ declare function describeNhAssistantClientContext(context: ClientContext): strin
707
1355
 
708
1356
  type NhAssistantLiveState = 'off' | 'connecting' | 'connected' | 'reconnecting' | 'disconnected';
709
1357
  /**
710
- * Live updates of the assistant hub: conversation changes, read positions, removals and the
711
- * turn events of other sessions. Connects only while the store asks for it, reconnects on its
712
- * own and emits `resync` after every (re)connect, because updates sent while disconnected are lost.
1358
+ * Live updates of the assistant hub: conversation changes, read positions, removals, the turn
1359
+ * events of other sessions and changes to the work of agents that run on their own. Connects only
1360
+ * while the store asks for it, reconnects on its own and emits `resync` after every (re)connect,
1361
+ * because updates sent while disconnected are lost.
713
1362
  */
714
1363
  declare class NhAssistantLiveService {
715
1364
  private readonly config;
@@ -719,6 +1368,7 @@ declare class NhAssistantLiveService {
719
1368
  private readonly readSubject;
720
1369
  private readonly removedSubject;
721
1370
  private readonly eventSubject;
1371
+ private readonly agentWorkSubject;
722
1372
  private readonly resyncSubject;
723
1373
  private readonly stateSignal;
724
1374
  private connection?;
@@ -730,6 +1380,11 @@ declare class NhAssistantLiveService {
730
1380
  readonly read$: Observable<LiveConversationRead>;
731
1381
  readonly removed$: Observable<LiveConversationRemoved>;
732
1382
  readonly events$: Observable<LiveConversationEvent>;
1383
+ /**
1384
+ * A run, proposal or feedback of an agent thread changed. It carries no content; components
1385
+ * that show the thread reload it.
1386
+ */
1387
+ readonly agentWork$: Observable<LiveAgentWorkChanged>;
733
1388
  /** Reload snapshots: emitted after every (re)connect. */
734
1389
  readonly resync$: Observable<void>;
735
1390
  readonly state: _angular_core.Signal<NhAssistantLiveState>;
@@ -745,6 +1400,11 @@ declare class NhAssistantLiveService {
745
1400
  /** Starts over after the automatic reconnect gave up or the first start failed. */
746
1401
  private scheduleRestart;
747
1402
  private token;
1403
+ /**
1404
+ * The hub URL with the host's `getHubQueryParameters`, which reach the hub on every transport,
1405
+ * unlike headers on WebSockets and server-sent events.
1406
+ */
1407
+ private withQueryParameters;
748
1408
  /** `hubBaseUrl` + `hubPath`, or the hub path on the origin of `apiBaseUrl`. */
749
1409
  private resolveUrl;
750
1410
  static ɵfac: _angular_core.ɵɵFactoryDeclaration<NhAssistantLiveService, never>;
@@ -770,6 +1430,25 @@ interface NhAssistantQueuedMessage {
770
1430
  }
771
1431
  /** Notice code for a completed turn that produced no answer text and no server code. */
772
1432
  declare const NH_ASSISTANT_NO_ANSWER_NOTICE_CODE = "assistant-no-answer";
1433
+ /**
1434
+ * Who decides an approval the current user cannot decide: `turn`, the person whose turn created
1435
+ * it in a chat; `approver`, an approver of the agent thread's subject; `other-approver`, another
1436
+ * approver, because the current user started the work and four-eyes applies.
1437
+ */
1438
+ type NhAssistantApprovalWaitingFor = 'turn' | 'approver' | 'other-approver';
1439
+ /** The current user's right to decide, or to give feedback on, one approval of the open conversation. */
1440
+ interface NhAssistantApprovalRight {
1441
+ canDecide: boolean;
1442
+ /** Who decides when the current user cannot. */
1443
+ waitingFor: NhAssistantApprovalWaitingFor;
1444
+ /** Name of the person who decides a `turn` approval; `null` when unknown. */
1445
+ decisionOwner: string | null;
1446
+ /**
1447
+ * True for an agent's proposal the current user rejected in this session, so the approval card
1448
+ * offers the optional feedback question. Chat approvals never offer feedback.
1449
+ */
1450
+ canGiveFeedback?: boolean;
1451
+ }
773
1452
  /**
774
1453
  * A conversation that needs attention outside the open thread: a turn runs, an approval waits or
775
1454
  * there is something unread.
@@ -794,6 +1473,7 @@ declare function nhAssistantIsUnread(summary: Pick<ConversationSummary, 'status'
794
1473
  */
795
1474
  declare class NhAssistantStore {
796
1475
  private readonly api;
1476
+ private readonly agentRuns;
797
1477
  private readonly config;
798
1478
  private readonly injector;
799
1479
  private readonly accessPolicy;
@@ -826,9 +1506,13 @@ declare class NhAssistantStore {
826
1506
  private readonly queueDispatchState;
827
1507
  private readonly steeringState;
828
1508
  private readonly submittingState;
1509
+ /** Agent proposals the current user rejected in this session and may give feedback on. */
1510
+ private readonly feedbackApprovalsState;
829
1511
  private destroyed;
830
1512
  private readonly streams;
831
1513
  private readonly cancelTimers;
1514
+ /** Pending reloads of agent threads after live agent-work updates, per conversation. */
1515
+ private readonly agentWorkTimers;
832
1516
  private readonly pendingSendResolves;
833
1517
  private readonly markingRead;
834
1518
  private readonly liveSubscription;
@@ -889,7 +1573,20 @@ declare class NhAssistantStore {
889
1573
  readonly members: _angular_core.Signal<ConversationMember[]>;
890
1574
  /** True when the current user owns the open conversation (or it is new). */
891
1575
  readonly isOwner: _angular_core.Signal<boolean>;
892
- /** True when the current user may decide the pending approval: it belongs to their own turn. */
1576
+ /** True when the open conversation is the durable thread of an agent about a subject. */
1577
+ readonly isAgentThread: _angular_core.Signal<boolean>;
1578
+ /**
1579
+ * The current user's right to decide each pending approval of the open conversation, by approval
1580
+ * id. In a chat only the author of the waiting turn decides. In an agent thread the subject's
1581
+ * approvers decide, as the server reports per proposal: the approval policy, four-eyes and the
1582
+ * tool's approve policy, checked live. Proposals the user rejected in this session carry
1583
+ * `canGiveFeedback`.
1584
+ */
1585
+ readonly approvalRights: _angular_core.Signal<ReadonlyMap<string, NhAssistantApprovalRight>>;
1586
+ /**
1587
+ * True when the current user may decide the pending approval: in a chat it belongs to their own
1588
+ * turn, in an agent thread the server allows them as an approver.
1589
+ */
893
1590
  readonly canDecide: _angular_core.Signal<boolean>;
894
1591
  /** The member whose turn runs or waits in the open conversation, when it is someone else. */
895
1592
  readonly activeMember: _angular_core.Signal<ConversationMember | null>;
@@ -937,8 +1634,19 @@ declare class NhAssistantStore {
937
1634
  steerQueuedMessage(id: string): Promise<void>;
938
1635
  private dispatchQueued;
939
1636
  private sendMessage;
940
- /** Approves or rejects the pending approval. Ignores repeated calls while a decision is in flight. */
941
- decide(decision: ApprovalDecision, reason?: string): void;
1637
+ /**
1638
+ * Approves or rejects an approval of the open conversation: `approvalId`, or the pending approval
1639
+ * when it is left out. A proposal of an agent's run is decided with its proposal hash through the
1640
+ * agent-run endpoint; other approvals resume their turn as a stream. Ignores calls the current
1641
+ * user may not make and repeated calls while a decision is in flight.
1642
+ */
1643
+ decide(decision: ApprovalDecision, reason?: string, approvalId?: string): void;
1644
+ /**
1645
+ * Decides a proposal of an agent's run with `POST approvals/{id}/decisions`. An approved deferred
1646
+ * proposal executes later as a background operation; an inline one wakes the waiting run. The
1647
+ * reloaded snapshot shows the outcome and the proposals that remain open.
1648
+ */
1649
+ private decideProposal;
942
1650
  /** Asks the server to stop the running turn or to abandon a waiting approval of the open conversation. */
943
1651
  cancel(): Promise<void>;
944
1652
  private cancelConversation;
@@ -991,6 +1699,13 @@ declare class NhAssistantStore {
991
1699
  private onLiveRead;
992
1700
  private onLiveRemoved;
993
1701
  private onLiveEvent;
1702
+ /**
1703
+ * A run or proposal of an agent thread changed, for example a colleague decided a proposal in the
1704
+ * inbox: reload the thread when this tab has it open, so its approval cards show the decision.
1705
+ * A burst of updates reloads once. Feedback does not change the thread.
1706
+ */
1707
+ private onLiveAgentWork;
1708
+ private clearAgentWorkTimers;
994
1709
  /** After a reconnect: updates sent while disconnected are lost, so reload what is shown. */
995
1710
  private resync;
996
1711
  private scheduleRefresh;
@@ -1083,6 +1798,7 @@ declare const NH_ASSISTANT_PANEL_MOBILE_QUERY = "(max-width: 599.98px)";
1083
1798
  declare class NhAssistantPanelService {
1084
1799
  private readonly overlay;
1085
1800
  private readonly store;
1801
+ private readonly agentRuns;
1086
1802
  private readonly injector;
1087
1803
  private readonly document;
1088
1804
  private readonly breakpoints;
@@ -1094,6 +1810,20 @@ declare class NhAssistantPanelService {
1094
1810
  readonly isOpen: Signal<boolean>;
1095
1811
  constructor();
1096
1812
  open(conversationId?: string): void;
1813
+ /**
1814
+ * Opens the panel on the conversation with an agent about a subject, for example the intake
1815
+ * reviewer about one project. The server returns the agent's thread about the subject and creates
1816
+ * it without starting a run when it is missing; people then type in the conversation, which runs
1817
+ * a turn. Creating needs the participant role, readers may open an existing thread.
1818
+ *
1819
+ * Resolves with the lookup once the panel opens the conversation. A failure, such as
1820
+ * `assistant-subject-access-denied`, rejects with `NhAssistantApiError` and leaves the panel as
1821
+ * it is, so the caller shows the localized `messageKey` where the person asked.
1822
+ */
1823
+ openSubject(agentId: string, subject: {
1824
+ type: string;
1825
+ id: string;
1826
+ }): Promise<AgentThreadLookup>;
1097
1827
  private showPanel;
1098
1828
  close(): void;
1099
1829
  toggle(): void;
@@ -1108,6 +1838,62 @@ declare class NhAssistantPanelService {
1108
1838
  static ɵprov: _angular_core.ɵɵInjectableDeclaration<NhAssistantPanelService>;
1109
1839
  }
1110
1840
 
1841
+ /**
1842
+ * Counts of agent work per subject for badges in lists and on pages. Every summary asked for in the
1843
+ * same tick becomes one `POST subjects/{type}/summary` per subject type, in chunks of
1844
+ * `NH_ASSISTANT_MAX_SUBJECT_SUMMARY`. Results are cached per subject and shared by everyone who
1845
+ * shows it. Live agent-work updates refetch only the subjects they name, batched; a reconnect of
1846
+ * the hub refetches every subject shown. Nothing is requested on the server or while the assistant
1847
+ * is disabled or denied, and the cache clears when it becomes unavailable, for example on sign-out.
1848
+ */
1849
+ declare class NhAssistantSubjectSummaryService {
1850
+ private readonly api;
1851
+ private readonly store;
1852
+ private readonly live;
1853
+ private readonly browser;
1854
+ private readonly entries;
1855
+ /** Subject ids per type that wait for the next request. */
1856
+ private readonly queue;
1857
+ /** Subjects named by live updates that wait for the end of the burst. */
1858
+ private readonly changed;
1859
+ private requests;
1860
+ private readonly liveSubscription;
1861
+ private flushScheduled;
1862
+ private changedTimer?;
1863
+ private requestRevision;
1864
+ private destroyed;
1865
+ constructor();
1866
+ /**
1867
+ * The agent work on one subject: `null` until it is known, then every update. Subscribing shows
1868
+ * the subject; summaries of subjects that are shown stay current with live updates. The request
1869
+ * starts in the next microtask, together with every other summary asked for until then.
1870
+ */
1871
+ summary(subjectType: string, subjectId: string): Observable<AgentSubjectSummary | null>;
1872
+ /**
1873
+ * Fetches the summaries of these subjects again, or of every subject of the type that is shown,
1874
+ * for example after the application changed them without an agent.
1875
+ */
1876
+ refresh(subjectType: string, subjectIds?: readonly string[]): void;
1877
+ private watch;
1878
+ private unwatch;
1879
+ private isCurrent;
1880
+ /** Drops a summary nobody shows; the next subscriber fetches it again. */
1881
+ private forget;
1882
+ private enqueue;
1883
+ private scheduleFlush;
1884
+ /** Sends the queued subjects: one request per type and chunk. Waits while the assistant is unavailable. */
1885
+ private flush;
1886
+ private send;
1887
+ private onAgentWork;
1888
+ /** Refetches the shown subjects of a burst of live updates, together. */
1889
+ private refetchChanged;
1890
+ /** After a reconnect updates may have been missed: refetch what is shown, forget the rest. */
1891
+ private refetchShown;
1892
+ private onAvailabilityChanged;
1893
+ static ɵfac: _angular_core.ɵɵFactoryDeclaration<NhAssistantSubjectSummaryService, never>;
1894
+ static ɵprov: _angular_core.ɵɵInjectableDeclaration<NhAssistantSubjectSummaryService>;
1895
+ }
1896
+
1111
1897
  /** Fragment the panel reads to join a shared conversation: `#nh-assistant-join=<id>.<token>`. */
1112
1898
  declare const NH_ASSISTANT_JOIN_FRAGMENT = "nh-assistant-join";
1113
1899
  /** Fragment a clicked notification opens: `#nh-assistant-conversation=<id>`. */
@@ -1149,6 +1935,79 @@ declare class NhAssistantLauncherComponent {
1149
1935
  static ɵcmp: _angular_core.ɵɵComponentDeclaration<NhAssistantLauncherComponent, "nh-assistant-launcher", never, {}, {}, never, ["*"], true, never>;
1150
1936
  }
1151
1937
 
1938
+ /** A decision about one approval of the thread. */
1939
+ interface NhAssistantApprovalChoice {
1940
+ approvalId: string;
1941
+ decision: ApprovalDecision;
1942
+ }
1943
+ /** Above this number of messages the thread renders through CDK virtual scrolling. */
1944
+ declare const NH_ASSISTANT_VIRTUAL_SCROLL_THRESHOLD = 200;
1945
+ /**
1946
+ * The messages of a conversation as a live log. Assistant text renders as sanitized
1947
+ * Markdown, consecutive tool calls as one collapsible group that counts along, and
1948
+ * approvals as cards. Messages a trigger wrote into an agent thread read as events, not as
1949
+ * a person. While a turn runs without visible progress, a working indicator shows the
1950
+ * elapsed time. The thread follows new content while the user is at the bottom.
1951
+ */
1952
+ declare class NhAssistantThreadComponent {
1953
+ private readonly injector;
1954
+ readonly messages: _angular_core.InputSignal<readonly Message[]>;
1955
+ readonly streaming: _angular_core.InputSignal<boolean>;
1956
+ readonly deciding: _angular_core.InputSignal<boolean>;
1957
+ readonly markdown: _angular_core.InputSignal<boolean>;
1958
+ /** The owner and participants of a shared conversation; empty while it is not shared. */
1959
+ readonly members: _angular_core.InputSignal<readonly ConversationMember[]>;
1960
+ /** The current user, to tell their own messages from those of others. */
1961
+ readonly currentActorId: _angular_core.InputSignal<string | null>;
1962
+ /** False when the pending approval belongs to another participant's turn. */
1963
+ readonly canDecide: _angular_core.InputSignal<boolean>;
1964
+ /** Name of the participant who decides the pending approval, when it is someone else. */
1965
+ readonly decisionOwner: _angular_core.InputSignal<string | null>;
1966
+ /**
1967
+ * Who may decide each pending approval, by approval id, for example `NhAssistantStore.approvalRights`.
1968
+ * An agent thread can hold several open proposals that the subject's approvers decide. Approvals
1969
+ * without an entry use `canDecide` and `decisionOwner`. An entry with `canGiveFeedback` lets the
1970
+ * card of a rejected proposal ask what was wrong.
1971
+ */
1972
+ readonly approvalRights: _angular_core.InputSignal<ReadonlyMap<string, NhAssistantApprovalRight> | null>;
1973
+ /** The decision about an approval card, without the approval it belongs to. */
1974
+ readonly approvalDecision: _angular_core.OutputEmitterRef<ApprovalDecision>;
1975
+ /** The decision about an approval card together with its approval id. */
1976
+ readonly approvalChoice: _angular_core.OutputEmitterRef<NhAssistantApprovalChoice>;
1977
+ private readonly names;
1978
+ readonly virtualThreshold = 200;
1979
+ readonly virtual: _angular_core.Signal<boolean>;
1980
+ /**
1981
+ * True while the turn runs and nothing else shows progress: before the first part and
1982
+ * between tool calls while the model decides what to do next. Streaming text and a
1983
+ * running tool group show their own progress; an approval waits for the user.
1984
+ */
1985
+ readonly working: _angular_core.Signal<boolean>;
1986
+ /** Whole seconds since the running turn started. */
1987
+ readonly elapsedSeconds: _angular_core.Signal<number>;
1988
+ private readonly turnStartedAt;
1989
+ private readonly now;
1990
+ private readonly scroller;
1991
+ private readonly viewport;
1992
+ constructor();
1993
+ trackMessage(_index: number, message: Message): string;
1994
+ /** True for a user message a trigger wrote into an agent thread. */
1995
+ isTrigger(message: Message): boolean;
1996
+ /** True for an assistant message the agent's rules wrote without a model. */
1997
+ isRule(message: Message): boolean;
1998
+ /** True for a user message written by another person in a shared conversation. */
1999
+ isOthers(message: Message): boolean;
2000
+ /** Whether and why the current user may decide an approval card. */
2001
+ rightFor(approval: ApprovalPart): NhAssistantApprovalRight;
2002
+ choose(approval: ApprovalPart, decision: ApprovalDecision): void;
2003
+ /** Display name of another person's message, or `null` when the application provides none. */
2004
+ authorName(message: Message): string | null;
2005
+ private scrollElement;
2006
+ private scrollToEnd;
2007
+ static ɵfac: _angular_core.ɵɵFactoryDeclaration<NhAssistantThreadComponent, never>;
2008
+ static ɵcmp: _angular_core.ɵɵComponentDeclaration<NhAssistantThreadComponent, "nh-assistant-thread", never, { "messages": { "alias": "messages"; "required": true; "isSignal": true; }; "streaming": { "alias": "streaming"; "required": false; "isSignal": true; }; "deciding": { "alias": "deciding"; "required": false; "isSignal": true; }; "markdown": { "alias": "markdown"; "required": false; "isSignal": true; }; "members": { "alias": "members"; "required": false; "isSignal": true; }; "currentActorId": { "alias": "currentActorId"; "required": false; "isSignal": true; }; "canDecide": { "alias": "canDecide"; "required": false; "isSignal": true; }; "decisionOwner": { "alias": "decisionOwner"; "required": false; "isSignal": true; }; "approvalRights": { "alias": "approvalRights"; "required": false; "isSignal": true; }; }, { "approvalDecision": "approvalDecision"; "approvalChoice": "approvalChoice"; }, never, never, true, never>;
2009
+ }
2010
+
1152
2011
  /**
1153
2012
  * The assistant drawer. Place it once in the application layout; it renders nothing in
1154
2013
  * place and appears as an overlay when `NhAssistantPanelService.open()` is called. It opens
@@ -1215,6 +2074,8 @@ declare class NhAssistantPanelComponent implements AfterViewInit, OnDestroy {
1215
2074
  */
1216
2075
  private openFromLocation;
1217
2076
  decide(decision: ApprovalDecision): void;
2077
+ /** Decides the approval of a card; in an agent thread several proposals can be open. */
2078
+ decideApproval(choice: NhAssistantApprovalChoice): void;
1218
2079
  cancel(): void;
1219
2080
  static ɵfac: _angular_core.ɵɵFactoryDeclaration<NhAssistantPanelComponent, never>;
1220
2081
  static ɵcmp: _angular_core.ɵɵComponentDeclaration<NhAssistantPanelComponent, "nh-assistant-panel", never, {}, {}, never, never, true, never>;
@@ -1241,56 +2102,6 @@ declare class NhAssistantConversationListComponent {
1241
2102
  static ɵcmp: _angular_core.ɵɵComponentDeclaration<NhAssistantConversationListComponent, "nh-assistant-conversation-list", never, { "conversations": { "alias": "conversations"; "required": true; "isSignal": true; }; "total": { "alias": "total"; "required": false; "isSignal": true; }; "activeConversationId": { "alias": "activeConversationId"; "required": false; "isSignal": true; }; "loading": { "alias": "loading"; "required": false; "isSignal": true; }; "disabled": { "alias": "disabled"; "required": false; "isSignal": true; }; }, { "conversationSelect": "conversationSelect"; "conversationDelete": "conversationDelete"; "conversationCreate": "conversationCreate"; }, never, never, true, never>;
1242
2103
  }
1243
2104
 
1244
- /** Above this number of messages the thread renders through CDK virtual scrolling. */
1245
- declare const NH_ASSISTANT_VIRTUAL_SCROLL_THRESHOLD = 200;
1246
- /**
1247
- * The messages of a conversation as a live log. Assistant text renders as sanitized
1248
- * Markdown, consecutive tool calls as one collapsible group that counts along, and
1249
- * approvals as cards. While a turn runs without visible progress, a working indicator
1250
- * shows the elapsed time. The thread follows new content while the user is at the bottom.
1251
- */
1252
- declare class NhAssistantThreadComponent {
1253
- private readonly injector;
1254
- readonly messages: _angular_core.InputSignal<readonly Message[]>;
1255
- readonly streaming: _angular_core.InputSignal<boolean>;
1256
- readonly deciding: _angular_core.InputSignal<boolean>;
1257
- readonly markdown: _angular_core.InputSignal<boolean>;
1258
- /** The owner and participants of a shared conversation; empty while it is not shared. */
1259
- readonly members: _angular_core.InputSignal<readonly ConversationMember[]>;
1260
- /** The current user, to tell their own messages from those of others. */
1261
- readonly currentActorId: _angular_core.InputSignal<string | null>;
1262
- /** False when the pending approval belongs to another participant's turn. */
1263
- readonly canDecide: _angular_core.InputSignal<boolean>;
1264
- /** Name of the participant who decides the pending approval, when it is someone else. */
1265
- readonly decisionOwner: _angular_core.InputSignal<string | null>;
1266
- readonly approvalDecision: _angular_core.OutputEmitterRef<ApprovalDecision>;
1267
- private readonly names;
1268
- readonly virtualThreshold = 200;
1269
- readonly virtual: _angular_core.Signal<boolean>;
1270
- /**
1271
- * True while the turn runs and nothing else shows progress: before the first part and
1272
- * between tool calls while the model decides what to do next. Streaming text and a
1273
- * running tool group show their own progress; an approval waits for the user.
1274
- */
1275
- readonly working: _angular_core.Signal<boolean>;
1276
- /** Whole seconds since the running turn started. */
1277
- readonly elapsedSeconds: _angular_core.Signal<number>;
1278
- private readonly turnStartedAt;
1279
- private readonly now;
1280
- private readonly scroller;
1281
- private readonly viewport;
1282
- constructor();
1283
- trackMessage(_index: number, message: Message): string;
1284
- /** True for a user message written by another person in a shared conversation. */
1285
- isOthers(message: Message): boolean;
1286
- /** Display name of another person's message, or `null` when the application provides none. */
1287
- authorName(message: Message): string | null;
1288
- private scrollElement;
1289
- private scrollToEnd;
1290
- static ɵfac: _angular_core.ɵɵFactoryDeclaration<NhAssistantThreadComponent, never>;
1291
- static ɵcmp: _angular_core.ɵɵComponentDeclaration<NhAssistantThreadComponent, "nh-assistant-thread", never, { "messages": { "alias": "messages"; "required": true; "isSignal": true; }; "streaming": { "alias": "streaming"; "required": false; "isSignal": true; }; "deciding": { "alias": "deciding"; "required": false; "isSignal": true; }; "markdown": { "alias": "markdown"; "required": false; "isSignal": true; }; "members": { "alias": "members"; "required": false; "isSignal": true; }; "currentActorId": { "alias": "currentActorId"; "required": false; "isSignal": true; }; "canDecide": { "alias": "canDecide"; "required": false; "isSignal": true; }; "decisionOwner": { "alias": "decisionOwner"; "required": false; "isSignal": true; }; }, { "approvalDecision": "approvalDecision"; }, never, never, true, never>;
1292
- }
1293
-
1294
2105
  /**
1295
2106
  * Message input. Enter sends when sending is available; Shift+Enter inserts a new line.
1296
2107
  * Drafting remains available while the assistant runs or waits for approval.
@@ -1351,8 +2162,12 @@ declare class NhAssistantToolCallCardComponent {
1351
2162
  static ɵcmp: _angular_core.ɵɵComponentDeclaration<NhAssistantToolCallCardComponent, "nh-assistant-tool-call-card", never, { "part": { "alias": "part"; "required": true; "isSignal": true; }; }, {}, never, never, true, never>;
1352
2163
  }
1353
2164
 
1354
- /** Overall state of a run of tool calls, from most to least urgent. */
1355
- type NhAssistantToolCallGroupState = 'awaiting-approval' | 'running' | 'failed' | 'succeeded';
2165
+ /**
2166
+ * Overall state of a run of tool calls, from most to least urgent. `not-executed` means that every
2167
+ * call finished and at least one ended without running, because its proposal expired, was
2168
+ * withdrawn or became stale.
2169
+ */
2170
+ type NhAssistantToolCallGroupState = 'awaiting-approval' | 'running' | 'failed' | 'not-executed' | 'succeeded';
1356
2171
  /**
1357
2172
  * Summarizes consecutive tool calls in one collapsed line that counts along live: the
1358
2173
  * tool that runs now while the assistant works, and how many tools were used and failed
@@ -1367,6 +2182,8 @@ declare class NhAssistantToolCallGroupComponent {
1367
2182
  readonly total: _angular_core.Signal<number>;
1368
2183
  readonly finished: _angular_core.Signal<number>;
1369
2184
  readonly failed: _angular_core.Signal<number>;
2185
+ /** Calls that finished without running; they never wait. */
2186
+ readonly notExecuted: _angular_core.Signal<number>;
1370
2187
  readonly state: _angular_core.Signal<NhAssistantToolCallGroupState>;
1371
2188
  readonly stateIcon: _angular_core.Signal<NhAssistantIconName>;
1372
2189
  toggle(): void;
@@ -1379,33 +2196,130 @@ declare function formatNhAssistantCountdown(milliseconds: number): string;
1379
2196
  /**
1380
2197
  * Asks the user to approve or reject a proposed mutation. Shows the summary, targets,
1381
2198
  * proposed arguments and a countdown to expiry. A decision is emitted at most once until
1382
- * the host reports that it is no longer deciding.
2199
+ * the host reports that it is no longer deciding. After the user rejected an agent's proposal
2200
+ * (`canGiveFeedback`), a low-key action asks what was wrong. A proposal that closed because it no
2201
+ * longer fits shows why, such as "Already done", with the application's explanation.
1383
2202
  */
1384
2203
  declare class NhAssistantApprovalCardComponent {
1385
2204
  readonly approval: _angular_core.InputSignal<ApprovalPart>;
1386
2205
  /** True while the host submits a decision; disables both buttons. */
1387
2206
  readonly deciding: _angular_core.InputSignal<boolean>;
1388
2207
  /**
1389
- * False when the approval belongs to another participant's turn: only the person whose
1390
- * permissions the action would use may decide it.
2208
+ * False when the current user may not decide: in a chat the approval belongs to another
2209
+ * participant's turn, in an agent thread the user is no approver of the proposal.
1391
2210
  */
1392
2211
  readonly canDecide: _angular_core.InputSignal<boolean>;
1393
- /** Name of the participant who decides, shown when the current user cannot. */
2212
+ /** Name of the participant who decides a `turn` approval, shown when the current user cannot. */
1394
2213
  readonly decisionOwner: _angular_core.InputSignal<string | null>;
2214
+ /**
2215
+ * Who decides when the current user cannot: the author of the turn (`turn`, the default), an
2216
+ * approver of the agent thread's subject (`approver`), or another approver because the current
2217
+ * user started the work (`other-approver`).
2218
+ */
2219
+ readonly waitingFor: _angular_core.InputSignal<NhAssistantApprovalWaitingFor>;
2220
+ /**
2221
+ * True when the current user rejected this agent proposal and may say what was wrong, for example
2222
+ * from `NhAssistantStore.approvalRights`. Chat approvals never offer feedback.
2223
+ */
2224
+ readonly canGiveFeedback: _angular_core.InputSignal<boolean>;
1395
2225
  readonly decide: _angular_core.OutputEmitterRef<ApprovalDecision>;
1396
2226
  private readonly now;
1397
2227
  private readonly submitted;
2228
+ /** The feedback question is expanded. */
2229
+ readonly feedbackOpen: _angular_core.WritableSignal<boolean>;
2230
+ /** The feedback was stored; the question thanks the person and the action disappears. */
2231
+ readonly feedbackSaved: _angular_core.WritableSignal<boolean>;
2232
+ private readonly feedbackToggle;
1398
2233
  readonly remainingMs: _angular_core.Signal<number>;
1399
2234
  readonly expired: _angular_core.Signal<boolean>;
1400
2235
  readonly effectiveStatus: _angular_core.Signal<ApprovalStatus>;
2236
+ /**
2237
+ * Translation key of the status: the kind of a stale proposal, "replaced" for a superseded one,
2238
+ * otherwise the status itself.
2239
+ */
2240
+ readonly statusKey: _angular_core.Signal<string>;
2241
+ /** Why the agent's rules proposed it; model proposals have none. */
2242
+ readonly rationale: _angular_core.Signal<string | null>;
2243
+ /** The application's explanation of a stale proposal, such as who already did the work. */
2244
+ readonly staleExplanation: _angular_core.Signal<string | null>;
1401
2245
  readonly actionable: _angular_core.Signal<boolean>;
2246
+ readonly succeeded: _angular_core.Signal<boolean>;
1402
2247
  readonly disabled: _angular_core.Signal<boolean>;
1403
2248
  readonly countdown: _angular_core.Signal<string>;
1404
2249
  readonly presentedSummary: _angular_core.Signal<string | null>;
2250
+ readonly feedbackAvailable: _angular_core.Signal<boolean>;
2251
+ readonly feedbackIds: _angular_core.Signal<string[]>;
2252
+ readonly feedbackPanelId: string;
2253
+ /** Translation key of the text shown instead of the buttons when the current user cannot decide. */
2254
+ readonly waitingKey: _angular_core.Signal<"nh-assistant.approval.waiting-for-approver" | "nh-assistant.approval.waiting-for-other-approver" | "nh-assistant.approval.waiting-for" | "nh-assistant.approval.waiting-for-participant">;
1405
2255
  constructor();
1406
2256
  choose(decision: ApprovalDecision): void;
2257
+ toggleFeedback(): void;
2258
+ onFeedbackSaved(): void;
2259
+ /** Collapses the question and returns focus to the action that opened it. */
2260
+ onFeedbackDismissed(): void;
1407
2261
  static ɵfac: _angular_core.ɵɵFactoryDeclaration<NhAssistantApprovalCardComponent, never>;
1408
- static ɵcmp: _angular_core.ɵɵComponentDeclaration<NhAssistantApprovalCardComponent, "nh-assistant-approval-card", never, { "approval": { "alias": "approval"; "required": true; "isSignal": true; }; "deciding": { "alias": "deciding"; "required": false; "isSignal": true; }; "canDecide": { "alias": "canDecide"; "required": false; "isSignal": true; }; "decisionOwner": { "alias": "decisionOwner"; "required": false; "isSignal": true; }; }, { "decide": "decide"; }, never, never, true, never>;
2262
+ static ɵcmp: _angular_core.ɵɵComponentDeclaration<NhAssistantApprovalCardComponent, "nh-assistant-approval-card", never, { "approval": { "alias": "approval"; "required": true; "isSignal": true; }; "deciding": { "alias": "deciding"; "required": false; "isSignal": true; }; "canDecide": { "alias": "canDecide"; "required": false; "isSignal": true; }; "decisionOwner": { "alias": "decisionOwner"; "required": false; "isSignal": true; }; "waitingFor": { "alias": "waitingFor"; "required": false; "isSignal": true; }; "canGiveFeedback": { "alias": "canGiveFeedback"; "required": false; "isSignal": true; }; }, { "decide": "decide"; }, never, never, true, never>;
2263
+ }
2264
+
2265
+ /** What `nh-assistant-proposal-feedback` stored. */
2266
+ interface NhAssistantProposalFeedbackSaved {
2267
+ /** The proposals whose feedback the server stored. */
2268
+ approvalIds: string[];
2269
+ category: AgentProposalFeedbackCategory;
2270
+ text: string | null;
2271
+ }
2272
+ /**
2273
+ * Asks, after a rejection, what was wrong with one or more agent proposals: a category from a fixed
2274
+ * set and an optional text. It is optional and never blocks the decision; people skip it with one
2275
+ * action. One proposal is sent with `PUT approvals/{id}/feedback`, several rejected together with
2276
+ * `POST approvals/feedback` as bulk feedback. With `initial` it changes the caller's own feedback.
2277
+ * After saving it thanks the person in place of the form; hosts remove it after `dismissed`.
2278
+ */
2279
+ declare class NhAssistantProposalFeedbackComponent {
2280
+ private readonly api;
2281
+ private readonly host;
2282
+ private readonly document;
2283
+ private readonly injector;
2284
+ private readonly thanks;
2285
+ private subscription?;
2286
+ /** The proposals the feedback is about; several when they were rejected together. */
2287
+ readonly approvalIds: _angular_core.InputSignal<readonly string[]>;
2288
+ /** The caller's current feedback, to change it; `null` for new feedback. */
2289
+ readonly initial: _angular_core.InputSignal<AgentProposalFeedback | null>;
2290
+ /** Emits after the server stored the feedback. */
2291
+ readonly saved: _angular_core.OutputEmitterRef<NhAssistantProposalFeedbackSaved>;
2292
+ /** Emits when the person skips the question. */
2293
+ readonly dismissed: _angular_core.OutputEmitterRef<void>;
2294
+ readonly id: string;
2295
+ readonly categories: readonly AgentProposalFeedbackCategory[];
2296
+ readonly maxText = 1000;
2297
+ /** A new question when the host passes other proposals or other initial feedback. */
2298
+ private readonly question;
2299
+ readonly category: _angular_core.WritableSignal<AgentProposalFeedbackCategory | null>;
2300
+ readonly text: _angular_core.WritableSignal<string>;
2301
+ readonly busy: _angular_core.WritableSignal<boolean>;
2302
+ readonly done: _angular_core.WritableSignal<boolean>;
2303
+ /** Set when a bulk request stored the feedback for only part of the proposals. */
2304
+ readonly partial: _angular_core.WritableSignal<{
2305
+ stored: number;
2306
+ total: number;
2307
+ } | null>;
2308
+ readonly error: _angular_core.WritableSignal<NhAssistantError | null>;
2309
+ readonly errorKeys: _angular_core.Signal<string[]>;
2310
+ readonly count: _angular_core.Signal<number>;
2311
+ readonly textLength: _angular_core.Signal<number>;
2312
+ readonly tooLong: _angular_core.Signal<boolean>;
2313
+ readonly canSend: _angular_core.Signal<boolean>;
2314
+ constructor();
2315
+ choose(category: AgentProposalFeedbackCategory): void;
2316
+ onText(event: Event): void;
2317
+ dismiss(): void;
2318
+ send(): void;
2319
+ /** One proposal through its own endpoint; several in requests of at most the bulk limit. */
2320
+ private request;
2321
+ static ɵfac: _angular_core.ɵɵFactoryDeclaration<NhAssistantProposalFeedbackComponent, never>;
2322
+ static ɵcmp: _angular_core.ɵɵComponentDeclaration<NhAssistantProposalFeedbackComponent, "nh-assistant-proposal-feedback", never, { "approvalIds": { "alias": "approvalIds"; "required": true; "isSignal": true; }; "initial": { "alias": "initial"; "required": false; "isSignal": true; }; }, { "saved": "saved"; "dismissed": "dismissed"; }, never, never, true, never>;
1409
2323
  }
1410
2324
 
1411
2325
  /**
@@ -1533,6 +2447,30 @@ declare class NhAssistantActivityComponent {
1533
2447
  static ɵcmp: _angular_core.ɵɵComponentDeclaration<NhAssistantActivityComponent, "nh-assistant-activity", never, { "items": { "alias": "items"; "required": true; "isSignal": true; }; }, { "conversationSelect": "conversationSelect"; }, never, never, true, never>;
1534
2448
  }
1535
2449
 
2450
+ /**
2451
+ * A compact count of the agent work on one subject, for example on each row of a project list.
2452
+ * It shows nothing while the subject has no work. Otherwise it shows the number of proposals the
2453
+ * viewer may decide in the accent color, or, when they may decide none, a neutral count of the
2454
+ * open proposals, and a small working indicator while an agent works on the subject. Its tooltip
2455
+ * and accessible name say both counts. Badges on one page share one summary request per tick and
2456
+ * refresh on live agent-work updates of their subject; see `NhAssistantSubjectSummaryService`.
2457
+ */
2458
+ declare class NhAssistantSubjectBadgeComponent {
2459
+ private readonly summaries;
2460
+ private readonly summary;
2461
+ /** The application's kind of subject, for example `project`. */
2462
+ readonly subjectType: _angular_core.InputSignal<string>;
2463
+ readonly subjectId: _angular_core.InputSignal<string>;
2464
+ /** The summary while the subject has work to show; `null` otherwise. */
2465
+ readonly work: _angular_core.Signal<AgentSubjectSummary | null>;
2466
+ readonly count: _angular_core.Signal<number>;
2467
+ readonly countLabel: _angular_core.Signal<string>;
2468
+ readonly proposalsKey: _angular_core.Signal<"nh-assistant.subject-badge.to-decide" | "nh-assistant.subject-badge.open" | null>;
2469
+ constructor();
2470
+ static ɵfac: _angular_core.ɵɵFactoryDeclaration<NhAssistantSubjectBadgeComponent, never>;
2471
+ static ɵcmp: _angular_core.ɵɵComponentDeclaration<NhAssistantSubjectBadgeComponent, "nh-assistant-subject-badge", never, { "subjectType": { "alias": "subjectType"; "required": true; "isSignal": true; }; "subjectId": { "alias": "subjectId"; "required": true; "isSignal": true; }; }, {}, never, never, true, never>;
2472
+ }
2473
+
1536
2474
  /**
1537
2475
  * Translates the first key that has a translation and otherwise returns the fallback text.
1538
2476
  * Used for server-provided keys (agent names, error message keys, result codes) that the
@@ -1551,6 +2489,14 @@ declare class NhAssistantTranslatePipe implements PipeTransform {
1551
2489
  static ɵpipe: _angular_core.ɵɵPipeDeclaration<NhAssistantTranslatePipe, "nhAssistantTranslate", true>;
1552
2490
  }
1553
2491
 
2492
+ /**
2493
+ * Calls `reload` once a burst of live agent-work updates that `matches` has settled, and after
2494
+ * every (re)connect of the hub, because updates sent while it was disconnected are lost. Without a
2495
+ * live service or a connected hub nothing arrives and the view keeps its manual refresh. Call it in
2496
+ * an injection context, for example a component constructor; it stops when that context ends.
2497
+ */
2498
+ declare function nhAssistantReloadOnAgentWork(matches: (change: LiveAgentWorkChanged) => boolean, reload: () => void): void;
2499
+
1554
2500
  /** Converts any failure into a user-facing code and translation key, never raw text. */
1555
2501
  declare function toNhAssistantError(error: unknown): NhAssistantError;
1556
2502
  /** Translation keys for an error, from the most to the least specific. */
@@ -1558,5 +2504,5 @@ declare function nhAssistantErrorKeys(error: NhAssistantError | null): string[];
1558
2504
  /** Dash-case identifiers as the contract requires for agent and MCP server ids. */
1559
2505
  declare const NH_ASSISTANT_DASH_CASE: RegExp;
1560
2506
 
1561
- export { NH_ASSISTANT_ACCESS_POLICY, NH_ASSISTANT_CONFIG, NH_ASSISTANT_CONVERSATION_FRAGMENT, NH_ASSISTANT_FETCH, NH_ASSISTANT_ICONS, NH_ASSISTANT_JOIN_FRAGMENT, NH_ASSISTANT_MAX_CUSTOM_INSTRUCTIONS, NH_ASSISTANT_NO_ANSWER_NOTICE_CODE, NH_ASSISTANT_PAGE_CONTEXT_LIMITS, NH_ASSISTANT_PANEL_MOBILE_QUERY, NH_ASSISTANT_PANEL_WIDTH, NH_ASSISTANT_SSE_EVENT_TYPES, NH_ASSISTANT_TRANSLATIONS, NH_ASSISTANT_VIRTUAL_SCROLL_THRESHOLD, NhAssistantActivityComponent, NhAssistantAdminApiService, NhAssistantAgentPickerComponent, NhAssistantAllowAllAccessPolicy, NhAssistantApiError, NhAssistantApiService, NhAssistantApprovalCardComponent, NhAssistantClientErrorCodes, NhAssistantComposerComponent, NhAssistantConversationListComponent, NhAssistantLauncherComponent, NhAssistantLiveService, NhAssistantPanelComponent, NhAssistantPanelService, NhAssistantPreferencesComponent, NhAssistantPushService, NhAssistantShareComponent, NhAssistantSseParser, NhAssistantStore, NhAssistantThreadComponent, NhAssistantToolCallCardComponent, NhAssistantToolCallGroupComponent, NhAssistantTranslationMerger, applyNhAssistantApprovalDecision, applyNhAssistantConversationChange, applyNhAssistantEvent, applyNhAssistantLiveEvent, describeNhAssistantClientContext, formatNhAssistantCountdown, nhAssistantCodeForStatus, nhAssistantErrorMessageKey, nhAssistantIsUnread, nhAssistantLatestTurnHasText, nhAssistantShareLink, normalizeNhAssistantClientContext, provideNhAssistant, NH_ASSISTANT_DASH_CASE as ɵNH_ASSISTANT_DASH_CASE, NhAssistantIconComponent as ɵNhAssistantIconComponent, NhAssistantTranslatePipe as ɵNhAssistantTranslatePipe, nhAssistantErrorKeys as ɵnhAssistantErrorKeys, toNhAssistantError as ɵtoNhAssistantError };
1562
- export type { AdminAgent, AdminAgentInput, AgentSummary, ApplicationContext, ApplicationContextVersion, ApprovalDecision, ApprovalPart, ApprovalPresentation, ApprovalPresentationField, ApprovalRequiredEvent, ApprovalStatus, AssistantAddressForm, AssistantAutonomy, AssistantCollaboration, AssistantErrorEvent, AssistantPreferences, AssistantResponseLength, AssistantStatus, AssistantStyle, ClientContext, ClientContextEntity, Conversation, ConversationMember, ConversationPage, ConversationRole, ConversationStatus, ConversationSummary, CreateConversationRequest, DecideApprovalRequest, DirectoryEntry, LiveConversationChanged, LiveConversationEvent, LiveConversationRead, LiveConversationRemoved, McpAuthMode, McpServer, McpServerInput, McpServerTestResult, McpTool, McpToolEffect, McpToolStatus, Message, MessageDeltaEvent, MessagePart, NhAssistantAccessPolicy, NhAssistantActivity, NhAssistantClientContext, NhAssistantClientErrorCode, NhAssistantConfig, NhAssistantError, NhAssistantFetch, NhAssistantIconName, NhAssistantLiveState, NhAssistantNotice, NhAssistantPushConfig, NhAssistantPushState, NhAssistantQueuedMessage, NhAssistantRawSseMessage, NhAssistantSseEvent, NhAssistantSseEventMap, NhAssistantSseEventType, NhAssistantStatusCodes, NhAssistantToolCallGroupState, NotificationSettings, PushSubscriptionRequest, SendMessageRequest, ShareLink, TextPart, ToolCallPart, ToolCallStatus, ToolCatalogEffect, ToolCatalogEntry, ToolCompletedEvent, ToolStartedEvent, TurnCompletedEvent, TurnCompletionStatus, TurnStartedEvent, TurnUsage, UpdateAdminAgentRequest, UpdateApplicationContextRequest, UpdateMcpToolRequest };
2507
+ export { NH_ASSISTANT_ACCESS_POLICY, NH_ASSISTANT_CONFIG, NH_ASSISTANT_CONVERSATION_FRAGMENT, NH_ASSISTANT_FEEDBACK_CATEGORIES, NH_ASSISTANT_FEEDBACK_GROUPS, NH_ASSISTANT_FETCH, NH_ASSISTANT_ICONS, NH_ASSISTANT_JOIN_FRAGMENT, NH_ASSISTANT_MAX_BULK_FEEDBACK, NH_ASSISTANT_MAX_CUSTOM_INSTRUCTIONS, NH_ASSISTANT_MAX_FEEDBACK_TEXT, NH_ASSISTANT_MAX_PROPOSAL_LOOKUP, NH_ASSISTANT_MAX_SUBJECT_SUMMARY, NH_ASSISTANT_NO_ANSWER_NOTICE_CODE, NH_ASSISTANT_PAGE_CONTEXT_LIMITS, NH_ASSISTANT_PANEL_MOBILE_QUERY, NH_ASSISTANT_PANEL_WIDTH, NH_ASSISTANT_SSE_EVENT_TYPES, NH_ASSISTANT_TRANSLATIONS, NH_ASSISTANT_VIRTUAL_SCROLL_THRESHOLD, NhAssistantActivityComponent, NhAssistantAdminApiService, NhAssistantAgentPickerComponent, NhAssistantAgentRunApiService, NhAssistantAllowAllAccessPolicy, NhAssistantApiError, NhAssistantApiService, NhAssistantApprovalCardComponent, NhAssistantClientErrorCodes, NhAssistantComposerComponent, NhAssistantConversationListComponent, NhAssistantLauncherComponent, NhAssistantLiveService, NhAssistantPanelComponent, NhAssistantPanelService, NhAssistantPreferencesComponent, NhAssistantProposalFeedbackComponent, NhAssistantPushService, NhAssistantShareComponent, NhAssistantSseParser, NhAssistantStore, NhAssistantSubjectBadgeComponent, NhAssistantSubjectSummaryService, NhAssistantThreadComponent, NhAssistantToolCallCardComponent, NhAssistantToolCallGroupComponent, NhAssistantTranslationMerger, applyNhAssistantApprovalDecision, applyNhAssistantConversationChange, applyNhAssistantEvent, applyNhAssistantLiveEvent, describeNhAssistantClientContext, formatNhAssistantCountdown, nhAssistantCodeForStatus, nhAssistantErrorMessageKey, nhAssistantIsUnread, nhAssistantLatestTurnHasText, nhAssistantShareLink, normalizeNhAssistantClientContext, provideNhAssistant, NH_ASSISTANT_DASH_CASE as ɵNH_ASSISTANT_DASH_CASE, NhAssistantIconComponent as ɵNhAssistantIconComponent, NhAssistantTranslatePipe as ɵNhAssistantTranslatePipe, nhAssistantErrorKeys as ɵnhAssistantErrorKeys, nhAssistantReloadOnAgentWork as ɵnhAssistantReloadOnAgentWork, toNhAssistantError as ɵtoNhAssistantError };
2508
+ export type { AdminAgent, AdminAgentInput, AgentArtifact, AgentConsultation, AgentConsultationList, AgentConsultationStatus, AgentDecisionOutcome, AgentExecutionResolution, AgentFeedbackCategoryCount, AgentFeedbackExportFilter, AgentFeedbackFilter, AgentFeedbackItem, AgentFeedbackList, AgentFeedbackListFilter, AgentFeedbackOutcome, AgentFeedbackSummary, AgentFeedbackSummaryRow, AgentGrantSource, AgentInbox, AgentInboxFilter, AgentInvalidationCount, AgentProposal, AgentProposalDecision, AgentProposalDecisionRight, AgentProposalFeedback, AgentProposalFeedbackCategory, AgentProposalFeedbackGroup, AgentProposalLookup, AgentProposalObject, AgentProposalStatus, AgentRun, AgentRunKind, AgentRunList, AgentRunRetryMode, AgentRunStatus, AgentSubjectRole, AgentSubjectSummary, AgentSubjectSummaryList, AgentSubjectWork, AgentSubjectWorkAgent, AgentSubjectWorkProposal, AgentSummary, AgentThread, AgentThreadLookup, AgentThreadMemory, AgentTriggerReceipt, ApplicationContext, ApplicationContextVersion, ApprovalDecision, ApprovalPart, ApprovalPresentation, ApprovalPresentationField, ApprovalRequiredEvent, ApprovalStatus, AssistantAddressForm, AssistantAutonomy, AssistantCollaboration, AssistantErrorEvent, AssistantPreferences, AssistantResponseLength, AssistantStatus, AssistantStyle, ClientContext, ClientContextEntity, Conversation, ConversationKind, ConversationMember, ConversationPage, ConversationRole, ConversationStatus, ConversationSummary, ConversationThread, ConversationThreadDecision, CreateConversationRequest, DecideApprovalRequest, DirectoryEntry, LiveAgentWorkChanged, LiveAgentWorkReason, LiveConversationChanged, LiveConversationEvent, LiveConversationRead, LiveConversationRemoved, McpAuthMode, McpServer, McpServerInput, McpServerTestResult, McpTool, McpToolEffect, McpToolStatus, Message, MessageAuthorKind, MessageDeltaEvent, MessagePart, NhAssistantAccessPolicy, NhAssistantActivity, NhAssistantApprovalChoice, NhAssistantApprovalRight, NhAssistantApprovalWaitingFor, NhAssistantClientContext, NhAssistantClientErrorCode, NhAssistantConfig, NhAssistantError, NhAssistantFetch, NhAssistantIconName, NhAssistantLiveState, NhAssistantNotice, NhAssistantProposalFeedbackSaved, NhAssistantPushConfig, NhAssistantPushState, NhAssistantQueuedMessage, NhAssistantRawSseMessage, NhAssistantSseEvent, NhAssistantSseEventMap, NhAssistantSseEventType, NhAssistantStatusCodes, NhAssistantToolCallGroupState, NotificationSettings, PushSubscriptionRequest, SendMessageRequest, ShareLink, StaleKind, StartAgentRequest, TextPart, ToolCallPart, ToolCallStatus, ToolCatalogEffect, ToolCatalogEntry, ToolCompletedEvent, ToolStartedEvent, TurnCompletedEvent, TurnCompletionStatus, TurnStartedEvent, TurnUsage, UpdateAdminAgentRequest, UpdateApplicationContextRequest, UpdateMcpToolRequest };