@echothink-ui/agent 0.1.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.
Files changed (56) hide show
  1. package/README.md +5 -0
  2. package/dist/components/AgentApprovalGate.d.ts +10 -0
  3. package/dist/components/AgentContextViewer.d.ts +7 -0
  4. package/dist/components/AgentGeneratedArtifactPanel.d.ts +8 -0
  5. package/dist/components/AgentHandoffPanel.d.ts +22 -0
  6. package/dist/components/AgentInterruptionPanel.d.ts +13 -0
  7. package/dist/components/AgentMemoryPanel.d.ts +9 -0
  8. package/dist/components/AgentMessageList.d.ts +8 -0
  9. package/dist/components/AgentPlanDiff.d.ts +7 -0
  10. package/dist/components/AgentPlanPreview.d.ts +6 -0
  11. package/dist/components/AgentPromptBox.d.ts +15 -0
  12. package/dist/components/AgentRunControls.d.ts +10 -0
  13. package/dist/components/AgentSafetyPanel.d.ts +6 -0
  14. package/dist/components/AgentStateBadge.d.ts +6 -0
  15. package/dist/components/AgentThinkingChain.d.ts +8 -0
  16. package/dist/components/AgentThinkingPanel.d.ts +8 -0
  17. package/dist/components/AgentToolCallLog.d.ts +7 -0
  18. package/dist/components/AgentTraceViewer.d.ts +6 -0
  19. package/dist/components/AppDomainAgentPanel.d.ts +17 -0
  20. package/dist/components/ChatAgentRail.d.ts +24 -0
  21. package/dist/components/ScopeAttachmentPanel.d.ts +7 -0
  22. package/dist/components/utils.d.ts +20 -0
  23. package/dist/index.cjs +2709 -0
  24. package/dist/index.cjs.map +1 -0
  25. package/dist/index.css +2433 -0
  26. package/dist/index.css.map +1 -0
  27. package/dist/index.d.ts +44 -0
  28. package/dist/index.js +2666 -0
  29. package/dist/index.js.map +1 -0
  30. package/dist/types.d.ts +128 -0
  31. package/package.json +45 -0
  32. package/src/components/AgentApprovalGate.tsx +165 -0
  33. package/src/components/AgentContextViewer.tsx +161 -0
  34. package/src/components/AgentGeneratedArtifactPanel.tsx +224 -0
  35. package/src/components/AgentHandoffPanel.tsx +154 -0
  36. package/src/components/AgentInterruptionPanel.tsx +85 -0
  37. package/src/components/AgentMemoryPanel.tsx +167 -0
  38. package/src/components/AgentMessageList.tsx +209 -0
  39. package/src/components/AgentPlanDiff.tsx +149 -0
  40. package/src/components/AgentPlanPreview.tsx +106 -0
  41. package/src/components/AgentPromptBox.tsx +163 -0
  42. package/src/components/AgentRunControls.tsx +221 -0
  43. package/src/components/AgentSafetyPanel.tsx +113 -0
  44. package/src/components/AgentStateBadge.tsx +30 -0
  45. package/src/components/AgentThinkingChain.tsx +151 -0
  46. package/src/components/AgentThinkingPanel.tsx +56 -0
  47. package/src/components/AgentToolCallLog.tsx +262 -0
  48. package/src/components/AgentTraceViewer.tsx +218 -0
  49. package/src/components/AppDomainAgentPanel.tsx +66 -0
  50. package/src/components/ChatAgentRail.tsx +192 -0
  51. package/src/components/ScopeAttachmentPanel.tsx +130 -0
  52. package/src/components/utils.ts +186 -0
  53. package/src/index.test.tsx +212 -0
  54. package/src/index.tsx +88 -0
  55. package/src/styles.css +2902 -0
  56. package/src/types.ts +158 -0
package/dist/index.js ADDED
@@ -0,0 +1,2666 @@
1
+ // src/components/ChatAgentRail.tsx
2
+ import clsx5 from "clsx";
3
+
4
+ // src/components/AgentMessageList.tsx
5
+ import * as React from "react";
6
+ import clsx from "clsx";
7
+ import { StatusDot, Tag, statusLabel } from "@echothink-ui/core";
8
+
9
+ // src/components/utils.ts
10
+ var EMPTY_MARK = "\u2014";
11
+ function formatDateTime(value) {
12
+ const date = new Date(value);
13
+ if (Number.isNaN(date.getTime())) return value;
14
+ return new Intl.DateTimeFormat(void 0, {
15
+ dateStyle: "medium",
16
+ timeStyle: "short"
17
+ }).format(date);
18
+ }
19
+ function formatTime(value) {
20
+ const date = new Date(value);
21
+ if (Number.isNaN(date.getTime())) return value;
22
+ return new Intl.DateTimeFormat(void 0, {
23
+ hour: "2-digit",
24
+ minute: "2-digit",
25
+ second: "2-digit"
26
+ }).format(date);
27
+ }
28
+ function formatDuration(durationMs) {
29
+ if (durationMs == null) return EMPTY_MARK;
30
+ if (durationMs < 1e3) return `${Math.round(durationMs)} ms`;
31
+ return `${(durationMs / 1e3).toFixed(durationMs < 1e4 ? 1 : 0)} s`;
32
+ }
33
+ function jsonPreview(value, redacted = false, maxLength = 120) {
34
+ if (redacted) return "[redacted]";
35
+ if (value == null) return EMPTY_MARK;
36
+ const text = typeof value === "string" ? value : JSON.stringify(value);
37
+ if (!text) return EMPTY_MARK;
38
+ return text.length > maxLength ? `${text.slice(0, maxLength - 1)}\u2026` : text;
39
+ }
40
+ function prettyJson(value, redacted = false) {
41
+ if (redacted) return "[redacted]";
42
+ if (value == null) return EMPTY_MARK;
43
+ if (typeof value === "string") return value;
44
+ return JSON.stringify(value, null, 2);
45
+ }
46
+ function stateLabel(state) {
47
+ switch (state) {
48
+ case "idle":
49
+ return "Idle";
50
+ case "listening":
51
+ return "Listening";
52
+ case "thinking":
53
+ return "Thinking";
54
+ case "tool-calling":
55
+ return "Calling tools";
56
+ case "waiting-for-user":
57
+ return "Waiting for user";
58
+ case "interrupted":
59
+ return "Interrupted";
60
+ case "failed":
61
+ return "Failed";
62
+ case "completed":
63
+ return "Completed";
64
+ }
65
+ }
66
+ function isActiveAgentState(state) {
67
+ return state === "listening" || state === "thinking" || state === "tool-calling";
68
+ }
69
+ function statusSeverity(status) {
70
+ if (status === "failed" || status === "blocked" || status === "approval-required") {
71
+ return "danger";
72
+ }
73
+ if (status === "warning" || status === "pending-approval") return "warning";
74
+ if (status === "completed" || status === "succeeded" || status === "synced") return "success";
75
+ if (status === "running" || status === "in-progress" || status === "active") return "info";
76
+ return "neutral";
77
+ }
78
+ function riskSeverity(riskLevel = "low") {
79
+ if (riskLevel === "critical" || riskLevel === "high") return "danger";
80
+ if (riskLevel === "medium") return "warning";
81
+ return "info";
82
+ }
83
+ function safetySeverity(check) {
84
+ if (check.status === "pass") return "success";
85
+ if (check.status === "warn") return "warning";
86
+ return "danger";
87
+ }
88
+ function mergeStyle(base, incoming) {
89
+ return incoming ? { ...base, ...incoming } : base;
90
+ }
91
+ function diffPlanSteps(before, after) {
92
+ const beforeById = new Map(before.map((step) => [step.id, step]));
93
+ const afterById = new Map(after.map((step) => [step.id, step]));
94
+ const ids = Array.from(
95
+ /* @__PURE__ */ new Set([...after.map((step) => step.id), ...before.map((step) => step.id)])
96
+ );
97
+ return ids.map((id) => {
98
+ const beforeStep = beforeById.get(id);
99
+ const afterStep = afterById.get(id);
100
+ if (!beforeStep && afterStep) {
101
+ return { id, after: afterStep, status: "added", severity: "success" };
102
+ }
103
+ if (beforeStep && !afterStep) {
104
+ return { id, before: beforeStep, status: "removed", severity: "danger" };
105
+ }
106
+ const changed = JSON.stringify(beforeStep) !== JSON.stringify(afterStep);
107
+ return {
108
+ id,
109
+ before: beforeStep,
110
+ after: afterStep,
111
+ status: changed ? "modified" : "unchanged",
112
+ severity: changed ? "warning" : "neutral"
113
+ };
114
+ });
115
+ }
116
+
117
+ // src/components/AgentMessageList.tsx
118
+ import { jsx, jsxs } from "react/jsx-runtime";
119
+ var roleLabels = {
120
+ user: "You",
121
+ agent: "Agent",
122
+ system: "System",
123
+ tool: "Tool"
124
+ };
125
+ function AgentMessageList({
126
+ messages,
127
+ streaming,
128
+ autoScroll = true,
129
+ className,
130
+ style,
131
+ ...props
132
+ }) {
133
+ const listRef = React.useRef(null);
134
+ React.useEffect(() => {
135
+ if (!autoScroll) return;
136
+ const node = listRef.current;
137
+ if (!node) return;
138
+ node.scrollTo({ top: node.scrollHeight, behavior: "smooth" });
139
+ }, [autoScroll, messages.length, streaming]);
140
+ return /* @__PURE__ */ jsx(
141
+ "div",
142
+ {
143
+ ...props,
144
+ ref: listRef,
145
+ role: "log",
146
+ "aria-live": streaming ? "polite" : "off",
147
+ "aria-relevant": "additions text",
148
+ className: clsx("eth-message-list", "eth-agent-message-list", className),
149
+ "data-eth-component": "AgentMessageList",
150
+ style: mergeStyle(
151
+ {
152
+ background: "var(--eth-color-layer-01)",
153
+ display: "flex",
154
+ flexDirection: "column",
155
+ gap: "1rem",
156
+ maxHeight: "100%",
157
+ overflowY: "auto",
158
+ padding: "1rem"
159
+ },
160
+ style
161
+ ),
162
+ children: messages.map((message, index) => {
163
+ const isStreaming = Boolean(message.streaming || streaming && index === messages.length - 1);
164
+ const isUser = message.role === "user";
165
+ const isSystem = message.role === "system";
166
+ const isTool = message.role === "tool";
167
+ const accentBorder = isTool ? "3px solid var(--eth-color-border-strong)" : "3px solid var(--eth-color-interactive-primary)";
168
+ return /* @__PURE__ */ jsxs(
169
+ "article",
170
+ {
171
+ className: clsx(
172
+ "eth-message-list__item",
173
+ "eth-agent-message",
174
+ `eth-agent-message--${message.role}`,
175
+ isStreaming && "eth-agent-message--streaming"
176
+ ),
177
+ "aria-busy": isStreaming || void 0,
178
+ style: {
179
+ alignSelf: isSystem ? "stretch" : isUser ? "flex-end" : "flex-start",
180
+ contentVisibility: "auto",
181
+ containIntrinsicSize: "1px 96px",
182
+ display: "grid",
183
+ gap: "0.375rem",
184
+ maxWidth: isSystem ? "100%" : "min(100%, 42rem)",
185
+ minWidth: 0,
186
+ textAlign: isSystem ? "center" : "start",
187
+ width: isSystem ? "100%" : "fit-content"
188
+ },
189
+ children: [
190
+ /* @__PURE__ */ jsxs(
191
+ "header",
192
+ {
193
+ className: "eth-agent-message__header",
194
+ style: {
195
+ alignItems: "center",
196
+ color: "var(--eth-color-text-secondary)",
197
+ display: "flex",
198
+ flexWrap: "wrap",
199
+ fontSize: "0.75rem",
200
+ gap: "0.5rem",
201
+ justifyContent: isUser ? "flex-end" : isSystem ? "center" : "flex-start",
202
+ lineHeight: 1.333
203
+ },
204
+ children: [
205
+ /* @__PURE__ */ jsx(
206
+ "span",
207
+ {
208
+ className: "eth-agent-message__avatar",
209
+ "aria-hidden": true,
210
+ style: {
211
+ alignItems: "center",
212
+ background: isSystem ? "transparent" : isUser ? "var(--eth-color-interactive-primary)" : "var(--eth-color-layer-02)",
213
+ border: isSystem ? "1px dashed var(--eth-color-border-subtle)" : "1px solid var(--eth-color-border-subtle)",
214
+ borderRadius: "var(--eth-radius-none)",
215
+ color: isUser ? "#fff" : "var(--eth-color-text-primary)",
216
+ display: "inline-flex",
217
+ fontSize: "0.72rem",
218
+ fontWeight: 700,
219
+ height: 24,
220
+ justifyContent: "center",
221
+ width: 24
222
+ },
223
+ children: roleLabels[message.role].slice(0, 1)
224
+ }
225
+ ),
226
+ /* @__PURE__ */ jsx("strong", { children: roleLabels[message.role] }),
227
+ /* @__PURE__ */ jsx("time", { dateTime: message.createdAt, children: formatDateTime(message.createdAt) }),
228
+ message.status ? /* @__PURE__ */ jsx(StatusDot, { status: message.status, label: statusLabel(message.status) }) : null
229
+ ]
230
+ }
231
+ ),
232
+ /* @__PURE__ */ jsxs(
233
+ "div",
234
+ {
235
+ className: "eth-agent-message__bubble",
236
+ style: {
237
+ background: isSystem ? "var(--eth-color-layer-02)" : isUser ? "var(--eth-color-navy)" : "var(--eth-color-layer-02)",
238
+ border: isSystem ? "1px dashed var(--eth-color-border-subtle)" : "1px solid var(--eth-color-border-subtle)",
239
+ borderInlineEnd: isStreaming ? accentBorder : void 0,
240
+ borderInlineStart: isUser || isSystem ? void 0 : accentBorder,
241
+ borderRadius: "var(--eth-radius-panel)",
242
+ color: isUser ? "#fff" : "var(--eth-color-text-primary)",
243
+ fontFamily: isTool ? "ui-monospace, SFMono-Regular, Menlo, monospace" : void 0,
244
+ fontSize: isTool ? "0.875rem" : void 0,
245
+ lineHeight: 1.5,
246
+ overflowWrap: "anywhere",
247
+ padding: isSystem ? "0.5rem 0.75rem" : "0.875rem 1rem",
248
+ whiteSpace: isTool ? "pre-wrap" : "normal",
249
+ wordBreak: "normal"
250
+ },
251
+ children: [
252
+ message.content,
253
+ isStreaming ? /* @__PURE__ */ jsx(
254
+ "span",
255
+ {
256
+ className: "eth-agent-message__cursor",
257
+ "aria-hidden": true,
258
+ style: {
259
+ animation: "eth-pulse 0.8s infinite",
260
+ color: "var(--eth-color-interactive-primary)",
261
+ display: "inline-block",
262
+ fontWeight: 600,
263
+ marginInlineStart: 3,
264
+ transform: "translateY(1px)"
265
+ },
266
+ children: "\u258C"
267
+ }
268
+ ) : null
269
+ ]
270
+ }
271
+ ),
272
+ message.citations?.length ? /* @__PURE__ */ jsx(
273
+ "div",
274
+ {
275
+ className: "eth-agent-message__citations",
276
+ "aria-label": "Citations",
277
+ style: {
278
+ display: "flex",
279
+ flexWrap: "wrap",
280
+ gap: "0.375rem",
281
+ justifyContent: isUser ? "flex-end" : isSystem ? "center" : "flex-start"
282
+ },
283
+ children: message.citations.map(
284
+ (citation) => citation.href ? /* @__PURE__ */ jsx(
285
+ "a",
286
+ {
287
+ className: "eth-agent-message__citation-link eth-tag",
288
+ href: citation.href,
289
+ children: citation.label
290
+ },
291
+ citation.id
292
+ ) : /* @__PURE__ */ jsx(Tag, { children: citation.label }, citation.id)
293
+ )
294
+ }
295
+ ) : null
296
+ ]
297
+ },
298
+ message.id
299
+ );
300
+ })
301
+ }
302
+ );
303
+ }
304
+
305
+ // src/components/AgentPromptBox.tsx
306
+ import * as React2 from "react";
307
+ import clsx2 from "clsx";
308
+ import { IconButton, Tag as Tag2, Textarea } from "@echothink-ui/core";
309
+ import { ChevronRightIcon, PlusIcon } from "@echothink-ui/icons";
310
+ import { jsx as jsx2, jsxs as jsxs2 } from "react/jsx-runtime";
311
+ function AgentPromptBox({
312
+ value,
313
+ onChange,
314
+ onSubmit,
315
+ placeholder = "Message the agent...",
316
+ disabled,
317
+ scopeLabel,
318
+ attachments = [],
319
+ onAttach,
320
+ onAttachmentRemove,
321
+ onSlash,
322
+ className,
323
+ style,
324
+ ...props
325
+ }) {
326
+ const canSubmit = value.trim().length > 0 && !disabled;
327
+ const hasContext = Boolean(scopeLabel) || attachments.length > 0;
328
+ const submit = React2.useCallback(() => {
329
+ if (!canSubmit) return;
330
+ onSubmit?.(value);
331
+ }, [canSubmit, onSubmit, value]);
332
+ return /* @__PURE__ */ jsxs2(
333
+ "form",
334
+ {
335
+ ...props,
336
+ className: clsx2("eth-agent-prompt-box", className),
337
+ "data-eth-component": "AgentPromptBox",
338
+ style,
339
+ onSubmit: (event) => {
340
+ event.preventDefault();
341
+ submit();
342
+ },
343
+ children: [
344
+ hasContext ? /* @__PURE__ */ jsxs2("div", { className: "eth-agent-prompt-box__context", children: [
345
+ scopeLabel ? /* @__PURE__ */ jsxs2("span", { className: "eth-agent-prompt-box__scope", children: [
346
+ /* @__PURE__ */ jsx2("span", { children: "Scope" }),
347
+ /* @__PURE__ */ jsx2("strong", { children: scopeLabel })
348
+ ] }) : null,
349
+ attachments.length ? /* @__PURE__ */ jsx2("div", { className: "eth-agent-prompt-box__attachments", "aria-label": "Attached context", children: attachments.map((attachment) => /* @__PURE__ */ jsxs2(
350
+ Tag2,
351
+ {
352
+ removable: Boolean(onAttachmentRemove),
353
+ onRemove: onAttachmentRemove ? () => onAttachmentRemove(attachment.id) : void 0,
354
+ children: [
355
+ /* @__PURE__ */ jsx2("span", { className: "eth-agent-prompt-box__attachment-kind", children: kindLabel(attachment.kind) }),
356
+ /* @__PURE__ */ jsx2("span", { className: "eth-agent-prompt-box__attachment-label", children: attachment.label }),
357
+ attachment.status ? /* @__PURE__ */ jsx2(
358
+ "span",
359
+ {
360
+ className: "eth-agent-prompt-box__attachment-status",
361
+ "data-status": attachment.status,
362
+ role: "img",
363
+ "aria-label": `Status: ${statusLabel2(attachment.status)}`
364
+ }
365
+ ) : null
366
+ ]
367
+ },
368
+ attachment.id
369
+ )) }) : null
370
+ ] }) : null,
371
+ /* @__PURE__ */ jsx2(
372
+ Textarea,
373
+ {
374
+ "aria-label": "Agent prompt",
375
+ className: "eth-agent-prompt-box__input",
376
+ disabled,
377
+ placeholder,
378
+ rows: 3,
379
+ value,
380
+ onChange: (event) => onChange(event.currentTarget.value),
381
+ onKeyDown: (event) => {
382
+ if ((event.metaKey || event.ctrlKey) && event.key === "Enter") {
383
+ event.preventDefault();
384
+ submit();
385
+ }
386
+ }
387
+ }
388
+ ),
389
+ /* @__PURE__ */ jsxs2("div", { className: "eth-agent-prompt-box__actions", children: [
390
+ /* @__PURE__ */ jsxs2("div", { className: "eth-agent-prompt-box__tools", children: [
391
+ /* @__PURE__ */ jsx2(
392
+ IconButton,
393
+ {
394
+ label: "Attach scope or file",
395
+ intent: "ghost",
396
+ density: "compact",
397
+ disabled: disabled || !onAttach,
398
+ icon: /* @__PURE__ */ jsx2(PlusIcon, { size: 16 }),
399
+ onClick: onAttach
400
+ }
401
+ ),
402
+ /* @__PURE__ */ jsx2(
403
+ IconButton,
404
+ {
405
+ label: "Open slash commands",
406
+ intent: "ghost",
407
+ density: "compact",
408
+ disabled,
409
+ icon: /* @__PURE__ */ jsx2("span", { className: "eth-agent-prompt-box__command-icon", "aria-hidden": true, children: "/" }),
410
+ onClick: () => {
411
+ if (onSlash) {
412
+ onSlash();
413
+ return;
414
+ }
415
+ if (!value) onChange("/");
416
+ }
417
+ }
418
+ )
419
+ ] }),
420
+ /* @__PURE__ */ jsx2("span", { className: "eth-agent-prompt-box__spacer" }),
421
+ /* @__PURE__ */ jsx2(
422
+ IconButton,
423
+ {
424
+ className: "eth-agent-prompt-box__submit",
425
+ label: "Submit prompt",
426
+ intent: "primary",
427
+ density: "compact",
428
+ disabled: !canSubmit,
429
+ icon: /* @__PURE__ */ jsx2(ChevronRightIcon, { size: 16 }),
430
+ type: "submit"
431
+ }
432
+ )
433
+ ] })
434
+ ]
435
+ }
436
+ );
437
+ }
438
+ function kindLabel(kind) {
439
+ switch (kind) {
440
+ case "app-domain":
441
+ return "App";
442
+ case "document":
443
+ return "Doc";
444
+ default:
445
+ return kind.charAt(0).toUpperCase() + kind.slice(1);
446
+ }
447
+ }
448
+ function statusLabel2(status) {
449
+ return status.replace(/-/g, " ");
450
+ }
451
+
452
+ // src/components/AgentStateBadge.tsx
453
+ import clsx3 from "clsx";
454
+ import { jsx as jsx3, jsxs as jsxs3 } from "react/jsx-runtime";
455
+ function AgentStateBadge({ state = "idle", className, ...props }) {
456
+ const active = isActiveAgentState(state);
457
+ const label = stateLabel(state);
458
+ return /* @__PURE__ */ jsxs3(
459
+ "span",
460
+ {
461
+ ...props,
462
+ className: clsx3(
463
+ "eth-agent-state-badge",
464
+ `eth-agent-state-badge--${state}`,
465
+ active && "eth-agent-state-badge--active",
466
+ className
467
+ ),
468
+ "data-eth-component": "AgentStateBadge",
469
+ "data-state": state,
470
+ children: [
471
+ /* @__PURE__ */ jsx3("span", { className: "eth-agent-state-badge__dot", "aria-hidden": "true" }),
472
+ /* @__PURE__ */ jsx3("span", { className: "eth-agent-state-badge__label", children: label })
473
+ ]
474
+ }
475
+ );
476
+ }
477
+
478
+ // src/components/ScopeAttachmentPanel.tsx
479
+ import clsx4 from "clsx";
480
+ import { Badge, Button, StatusDot as StatusDot2, Surface, statusLabel as statusLabel3 } from "@echothink-ui/core";
481
+ import { jsx as jsx4, jsxs as jsxs4 } from "react/jsx-runtime";
482
+ var attentionStatuses = /* @__PURE__ */ new Set([
483
+ "approval-required",
484
+ "blocked",
485
+ "failed",
486
+ "pending-approval",
487
+ "stale",
488
+ "warning"
489
+ ]);
490
+ function ScopeAttachmentPanel({
491
+ attachments,
492
+ onRemove,
493
+ title = "Attached context",
494
+ subtitle,
495
+ severity,
496
+ className,
497
+ ...props
498
+ }) {
499
+ if (!attachments.length) return null;
500
+ const hasAttention = attachments.some(
501
+ (attachment) => attachment.status ? attentionStatuses.has(attachment.status) : false
502
+ );
503
+ const listLabel = typeof title === "string" ? `${title} items` : "Attached context items";
504
+ const renderedSubtitle = subtitle ?? `${attachments.length} ${attachments.length === 1 ? "scope is" : "scopes are"} available to the agent run`;
505
+ return /* @__PURE__ */ jsx4(
506
+ Surface,
507
+ {
508
+ ...props,
509
+ className: clsx4("eth-agent-scope-attachments", className),
510
+ "data-eth-component": "ScopeAttachmentPanel",
511
+ severity: severity ?? (hasAttention ? "warning" : void 0),
512
+ subtitle: renderedSubtitle,
513
+ title,
514
+ children: /* @__PURE__ */ jsx4("ul", { className: "eth-agent-scope-attachments__list", "aria-label": listLabel, children: attachments.map((attachment) => /* @__PURE__ */ jsxs4(
515
+ "li",
516
+ {
517
+ className: "eth-agent-scope-attachments__item",
518
+ "data-kind": attachment.kind,
519
+ "data-status": attachment.status,
520
+ children: [
521
+ /* @__PURE__ */ jsx4("span", { className: "eth-agent-scope-attachments__icon", "aria-hidden": "true", children: kindInitial(attachment.kind) }),
522
+ /* @__PURE__ */ jsxs4("span", { className: "eth-agent-scope-attachments__main", children: [
523
+ /* @__PURE__ */ jsxs4("span", { className: "eth-agent-scope-attachments__topline", children: [
524
+ /* @__PURE__ */ jsx4("strong", { className: "eth-agent-scope-attachments__label", children: attachment.label }),
525
+ /* @__PURE__ */ jsx4(Badge, { severity: "neutral", children: kindLabel2(attachment.kind) })
526
+ ] }),
527
+ /* @__PURE__ */ jsx4("span", { className: "eth-agent-scope-attachments__meta", children: kindDescription(attachment.kind) })
528
+ ] }),
529
+ /* @__PURE__ */ jsxs4("span", { className: "eth-agent-scope-attachments__aside", children: [
530
+ attachment.status ? /* @__PURE__ */ jsx4(StatusDot2, { status: attachment.status, label: statusLabel3(attachment.status) }) : /* @__PURE__ */ jsx4("span", { className: "eth-agent-scope-attachments__untracked", children: "No status" }),
531
+ onRemove ? /* @__PURE__ */ jsx4(
532
+ Button,
533
+ {
534
+ "aria-label": `Remove ${attachment.label}`,
535
+ density: "compact",
536
+ intent: "ghost",
537
+ onClick: () => onRemove(attachment.id),
538
+ children: "Remove"
539
+ }
540
+ ) : null
541
+ ] })
542
+ ]
543
+ },
544
+ attachment.id
545
+ )) })
546
+ }
547
+ );
548
+ }
549
+ function kindLabel2(kind) {
550
+ switch (kind) {
551
+ case "app-domain":
552
+ return "App domain";
553
+ case "document":
554
+ return "Document";
555
+ default:
556
+ return kind.charAt(0).toUpperCase() + kind.slice(1);
557
+ }
558
+ }
559
+ function kindDescription(kind) {
560
+ switch (kind) {
561
+ case "app-domain":
562
+ return "Runnable application boundary";
563
+ case "document":
564
+ return "Source document";
565
+ case "project":
566
+ return "Project scope";
567
+ case "resource":
568
+ return "External resource";
569
+ case "task":
570
+ return "Task context";
571
+ case "scope":
572
+ return "General scope";
573
+ default:
574
+ return "Attached context";
575
+ }
576
+ }
577
+ function kindInitial(kind) {
578
+ return kindLabel2(kind).charAt(0);
579
+ }
580
+
581
+ // src/components/ChatAgentRail.tsx
582
+ import { Fragment, jsx as jsx5, jsxs as jsxs5 } from "react/jsx-runtime";
583
+ function ChatAgentRail(props) {
584
+ return /* @__PURE__ */ jsx5(
585
+ AgentRailBase,
586
+ {
587
+ ...props,
588
+ componentName: "ChatAgentRail",
589
+ railClassName: "eth-agent-chat-rail",
590
+ placement: "right"
591
+ }
592
+ );
593
+ }
594
+ function LeftAgentRail(props) {
595
+ return /* @__PURE__ */ jsx5(
596
+ AgentRailBase,
597
+ {
598
+ ...props,
599
+ componentName: "LeftAgentRail",
600
+ railClassName: "eth-left-agent-rail eth-agent-left-rail",
601
+ placement: "left"
602
+ }
603
+ );
604
+ }
605
+ function AgentRailBase({
606
+ agentRef,
607
+ projectRef,
608
+ messages,
609
+ state = "idle",
610
+ prompt,
611
+ onPromptChange,
612
+ onSubmit,
613
+ attachments = [],
614
+ onAttachmentRemove,
615
+ onAttach,
616
+ onSlash,
617
+ autoScroll = true,
618
+ runControls,
619
+ header,
620
+ scopeLabel,
621
+ width = 360,
622
+ className,
623
+ style,
624
+ componentName,
625
+ railClassName,
626
+ placement,
627
+ "aria-label": ariaLabel,
628
+ ...props
629
+ }) {
630
+ const streaming = messages.some((message) => message.streaming) || isActiveAgentState(state);
631
+ const border = "1px solid var(--eth-color-border-subtle)";
632
+ return /* @__PURE__ */ jsxs5(
633
+ "aside",
634
+ {
635
+ ...props,
636
+ "aria-label": ariaLabel ?? "Agent collaboration rail",
637
+ className: clsx5("eth-chat-rail", railClassName, className),
638
+ "data-eth-component": componentName,
639
+ "data-placement": placement,
640
+ style: mergeStyle(
641
+ {
642
+ background: "var(--eth-color-layer-01)",
643
+ borderInlineEnd: placement === "left" ? border : 0,
644
+ borderInlineStart: placement === "right" ? border : 0,
645
+ display: "grid",
646
+ flex: `0 0 ${typeof width === "number" ? `${width}px` : width}`,
647
+ gridTemplateRows: "auto minmax(0, 1fr) auto",
648
+ height: "100%",
649
+ maxWidth: "100%",
650
+ minHeight: 0,
651
+ width
652
+ },
653
+ style
654
+ ),
655
+ children: [
656
+ /* @__PURE__ */ jsxs5(
657
+ "header",
658
+ {
659
+ className: "eth-chat-rail__header",
660
+ style: {
661
+ borderBottom: "1px solid var(--eth-color-border-subtle)",
662
+ display: "grid",
663
+ gap: "0.75rem",
664
+ padding: "1rem"
665
+ },
666
+ children: [
667
+ /* @__PURE__ */ jsxs5(
668
+ "div",
669
+ {
670
+ className: "eth-chat-rail__header-main",
671
+ style: {
672
+ alignItems: "flex-start",
673
+ display: "flex",
674
+ gap: "0.75rem",
675
+ justifyContent: "space-between"
676
+ },
677
+ children: [
678
+ /* @__PURE__ */ jsx5("div", { style: { minWidth: 0 }, children: header ?? /* @__PURE__ */ jsxs5(Fragment, { children: [
679
+ /* @__PURE__ */ jsx5("h2", { className: "eth-chat-rail__title", style: { fontSize: "1rem", margin: 0 }, children: "Agent" }),
680
+ agentRef || projectRef ? /* @__PURE__ */ jsx5(
681
+ "p",
682
+ {
683
+ className: "eth-chat-rail__meta",
684
+ style: {
685
+ color: "var(--eth-color-text-secondary)",
686
+ fontSize: "0.8rem",
687
+ margin: "0.25rem 0 0"
688
+ },
689
+ children: [agentRef, projectRef].filter(Boolean).join(" \xB7 ")
690
+ }
691
+ ) : null
692
+ ] }) }),
693
+ /* @__PURE__ */ jsx5(AgentStateBadge, { state })
694
+ ]
695
+ }
696
+ ),
697
+ runControls ? /* @__PURE__ */ jsx5("div", { className: "eth-chat-rail__run-controls", children: runControls }) : null
698
+ ]
699
+ }
700
+ ),
701
+ /* @__PURE__ */ jsx5(
702
+ AgentMessageList,
703
+ {
704
+ className: "eth-chat-rail__messages",
705
+ autoScroll,
706
+ messages,
707
+ streaming,
708
+ style: { minHeight: 0, padding: "1rem" }
709
+ }
710
+ ),
711
+ /* @__PURE__ */ jsxs5(
712
+ "footer",
713
+ {
714
+ className: "eth-chat-rail__footer",
715
+ style: {
716
+ borderTop: "1px solid var(--eth-color-border-subtle)",
717
+ display: "grid",
718
+ gap: "0.75rem",
719
+ padding: "1rem"
720
+ },
721
+ children: [
722
+ /* @__PURE__ */ jsx5(
723
+ ScopeAttachmentPanel,
724
+ {
725
+ attachments: attachments.map((attachment) => ({
726
+ ...attachment,
727
+ kind: attachment.kind === "file" ? "document" : attachment.kind
728
+ })),
729
+ onRemove: onAttachmentRemove
730
+ }
731
+ ),
732
+ /* @__PURE__ */ jsx5(
733
+ AgentPromptBox,
734
+ {
735
+ value: prompt,
736
+ onChange: onPromptChange,
737
+ scopeLabel,
738
+ onAttach,
739
+ onSlash,
740
+ onSubmit: (value) => onSubmit?.(value, attachments)
741
+ }
742
+ )
743
+ ]
744
+ }
745
+ )
746
+ ]
747
+ }
748
+ );
749
+ }
750
+
751
+ // src/components/AgentThinkingPanel.tsx
752
+ import clsx6 from "clsx";
753
+ import { Surface as Surface2 } from "@echothink-ui/core";
754
+ import { jsx as jsx6, jsxs as jsxs6 } from "react/jsx-runtime";
755
+ function AgentThinkingPanel({
756
+ currentStep,
757
+ summary,
758
+ progress,
759
+ lastUpdatedAt,
760
+ title = "Agent thinking",
761
+ subtitle,
762
+ metadata = [],
763
+ className,
764
+ ...props
765
+ }) {
766
+ const normalizedProgress = typeof progress === "number" && Number.isFinite(progress) ? Math.max(0, Math.min(100, Math.round(progress))) : void 0;
767
+ const panelMetadata = lastUpdatedAt ? [{ label: "Last updated", value: formatDateTime(lastUpdatedAt) }, ...metadata] : metadata;
768
+ return /* @__PURE__ */ jsxs6(
769
+ Surface2,
770
+ {
771
+ ...props,
772
+ className: clsx6("eth-agent-thinking-panel", className),
773
+ "data-eth-component": "AgentThinkingPanel",
774
+ title,
775
+ subtitle: currentStep ?? subtitle,
776
+ metadata: panelMetadata.length ? panelMetadata : void 0,
777
+ children: [
778
+ summary ? /* @__PURE__ */ jsx6("p", { className: "eth-agent-thinking-panel__summary", children: summary }) : null,
779
+ normalizedProgress != null ? /* @__PURE__ */ jsxs6("div", { className: "eth-agent-thinking-panel__progress", children: [
780
+ /* @__PURE__ */ jsxs6("div", { className: "eth-agent-thinking-panel__progress-label", children: [
781
+ /* @__PURE__ */ jsx6("span", { children: "Progress" }),
782
+ /* @__PURE__ */ jsxs6("strong", { children: [
783
+ normalizedProgress,
784
+ "%"
785
+ ] })
786
+ ] }),
787
+ /* @__PURE__ */ jsxs6("progress", { max: 100, value: normalizedProgress, "aria-label": "Agent progress", children: [
788
+ normalizedProgress,
789
+ "%"
790
+ ] })
791
+ ] }) : null
792
+ ]
793
+ }
794
+ );
795
+ }
796
+
797
+ // src/components/AgentThinkingChain.tsx
798
+ import clsx7 from "clsx";
799
+ import { Badge as Badge2, EmptyState, StatusDot as StatusDot3, Surface as Surface3, statusLabel as statusLabel4 } from "@echothink-ui/core";
800
+ import { jsx as jsx7, jsxs as jsxs7 } from "react/jsx-runtime";
801
+ function AgentThinkingChain({
802
+ steps,
803
+ streaming,
804
+ redactionPolicy,
805
+ title = "Thinking chain",
806
+ className,
807
+ ...props
808
+ }) {
809
+ return /* @__PURE__ */ jsx7(
810
+ Surface3,
811
+ {
812
+ ...props,
813
+ className: clsx7("eth-agent-thinking-chain", className),
814
+ "data-eth-component": "AgentThinkingChain",
815
+ title,
816
+ subtitle: redactionPolicy ? `Redaction policy: ${redactionPolicy}` : void 0,
817
+ children: steps.length ? /* @__PURE__ */ jsx7("ol", { className: "eth-agent-thinking-chain__steps", "aria-live": streaming ? "polite" : "off", children: steps.map((step) => /* @__PURE__ */ jsx7(ThinkingStep, { step, depth: 0 }, step.id)) }) : /* @__PURE__ */ jsx7(
818
+ EmptyState,
819
+ {
820
+ title: "No thinking steps",
821
+ description: "Steps will appear as the agent records observations, actions, or blockers."
822
+ }
823
+ )
824
+ }
825
+ );
826
+ }
827
+ function ThinkingStep({ step, depth }) {
828
+ const hasChildren = Boolean(step.children?.length);
829
+ const stepClassName = clsx7(
830
+ "eth-agent-thinking-chain__step",
831
+ `eth-agent-thinking-chain__step--${step.status}`,
832
+ hasChildren && "eth-agent-thinking-chain__step--branch"
833
+ );
834
+ return /* @__PURE__ */ jsxs7(
835
+ "li",
836
+ {
837
+ className: clsx7(
838
+ "eth-agent-thinking-chain__item",
839
+ `eth-agent-thinking-chain__item--${step.status}`
840
+ ),
841
+ style: {
842
+ "--eth-agent-thinking-chain-depth-offset": `${depth * 1.5}rem`
843
+ },
844
+ children: [
845
+ /* @__PURE__ */ jsx7("span", { className: "eth-agent-thinking-chain__marker", "aria-hidden": "true" }),
846
+ /* @__PURE__ */ jsxs7("div", { className: "eth-agent-thinking-chain__item-body", children: [
847
+ /* @__PURE__ */ jsxs7("article", { className: stepClassName, children: [
848
+ /* @__PURE__ */ jsx7(StepHeader, { step, hasChildren }),
849
+ /* @__PURE__ */ jsx7(StepDetails, { step })
850
+ ] }),
851
+ hasChildren ? /* @__PURE__ */ jsx7("ol", { className: "eth-agent-thinking-chain__children", children: step.children?.map((child) => /* @__PURE__ */ jsx7(ThinkingStep, { step: child, depth: depth + 1 }, child.id)) }) : null
852
+ ] })
853
+ ]
854
+ }
855
+ );
856
+ }
857
+ function StepHeader({ step, hasChildren }) {
858
+ return /* @__PURE__ */ jsxs7("header", { className: "eth-agent-thinking-chain__step-header", children: [
859
+ /* @__PURE__ */ jsxs7("span", { className: "eth-agent-thinking-chain__step-heading", children: [
860
+ /* @__PURE__ */ jsx7("strong", { className: "eth-agent-thinking-chain__step-title", children: step.title }),
861
+ hasChildren ? /* @__PURE__ */ jsxs7("span", { className: "eth-agent-thinking-chain__branch-count", children: [
862
+ step.children?.length,
863
+ " ",
864
+ step.children?.length === 1 ? "substep" : "substeps"
865
+ ] }) : null
866
+ ] }),
867
+ /* @__PURE__ */ jsxs7("span", { className: "eth-agent-thinking-chain__step-meta", children: [
868
+ step.redacted ? /* @__PURE__ */ jsx7(Badge2, { severity: "warning", children: "Redacted" }) : null,
869
+ /* @__PURE__ */ jsx7(StatusDot3, { status: step.status, label: statusLabel4(step.status) }),
870
+ step.durationMs != null ? /* @__PURE__ */ jsx7("span", { className: "eth-agent-thinking-chain__duration", children: formatDuration(step.durationMs) }) : null
871
+ ] })
872
+ ] });
873
+ }
874
+ function StepDetails({ step }) {
875
+ const hasDetails = Boolean(step.observation || step.action || step.blocker);
876
+ if (step.redacted) {
877
+ return /* @__PURE__ */ jsx7("p", { className: "eth-agent-thinking-chain__redacted", children: "Details are hidden by policy." });
878
+ }
879
+ if (!hasDetails) {
880
+ return /* @__PURE__ */ jsx7("p", { className: "eth-agent-thinking-chain__empty-detail", children: "No public details recorded." });
881
+ }
882
+ return /* @__PURE__ */ jsxs7("dl", { className: "eth-agent-thinking-chain__fields", children: [
883
+ step.observation ? /* @__PURE__ */ jsx7(StepField, { label: "Observation", value: step.observation }) : null,
884
+ step.action ? /* @__PURE__ */ jsx7(StepField, { label: "Action", value: step.action, monospaced: true }) : null,
885
+ step.blocker ? /* @__PURE__ */ jsx7(
886
+ StepField,
887
+ {
888
+ label: "Blocker",
889
+ value: step.blocker,
890
+ className: "eth-agent-thinking-chain__field--blocker"
891
+ }
892
+ ) : null
893
+ ] });
894
+ }
895
+ function StepField({
896
+ label,
897
+ value,
898
+ monospaced,
899
+ className
900
+ }) {
901
+ return /* @__PURE__ */ jsxs7("div", { className: clsx7("eth-agent-thinking-chain__field", className), children: [
902
+ /* @__PURE__ */ jsx7("dt", { children: label }),
903
+ /* @__PURE__ */ jsx7("dd", { className: clsx7(monospaced && "eth-agent-thinking-chain__field-value--mono"), children: value })
904
+ ] });
905
+ }
906
+
907
+ // src/components/AgentTraceViewer.tsx
908
+ import * as React3 from "react";
909
+ import clsx8 from "clsx";
910
+ import { Badge as Badge3, EmptyState as EmptyState2, StatusDot as StatusDot4, Surface as Surface4, statusLabel as statusLabel5 } from "@echothink-ui/core";
911
+ import { Fragment as Fragment2, jsx as jsx8, jsxs as jsxs8 } from "react/jsx-runtime";
912
+ function AgentTraceViewer({
913
+ spans,
914
+ title = "Trace viewer",
915
+ className,
916
+ ...props
917
+ }) {
918
+ const [selectedSpanId, setSelectedSpanId] = React3.useState(spans[0]?.id);
919
+ const timeline = React3.useMemo(() => buildTimeline(spans), [spans]);
920
+ const selectedSpan = spans.find((span) => span.id === selectedSpanId) ?? spans[0];
921
+ const selectedTimelineItem = timeline.items.find((item) => item.span.id === selectedSpan?.id);
922
+ const activeCount = spans.filter(
923
+ (span) => ["running", "in-progress", "pending-approval", "approval-required"].includes(span.status)
924
+ ).length;
925
+ const selectedAttributes = Object.entries(selectedSpan?.attributes ?? {});
926
+ return /* @__PURE__ */ jsx8(
927
+ Surface4,
928
+ {
929
+ ...props,
930
+ className: clsx8("eth-trace", "eth-agent-trace-viewer", className),
931
+ "data-eth-component": "AgentTraceViewer",
932
+ title,
933
+ children: !spans.length ? /* @__PURE__ */ jsx8(EmptyState2, { title: "No trace spans" }) : /* @__PURE__ */ jsxs8(Fragment2, { children: [
934
+ /* @__PURE__ */ jsxs8("dl", { className: "eth-trace__summary", "aria-label": "Trace summary", children: [
935
+ /* @__PURE__ */ jsxs8("div", { children: [
936
+ /* @__PURE__ */ jsx8("dt", { children: "Spans" }),
937
+ /* @__PURE__ */ jsx8("dd", { children: spans.length })
938
+ ] }),
939
+ /* @__PURE__ */ jsxs8("div", { children: [
940
+ /* @__PURE__ */ jsx8("dt", { children: "Window" }),
941
+ /* @__PURE__ */ jsx8("dd", { children: formatDuration(timeline.total) })
942
+ ] }),
943
+ /* @__PURE__ */ jsxs8("div", { children: [
944
+ /* @__PURE__ */ jsx8("dt", { children: "Active" }),
945
+ /* @__PURE__ */ jsx8("dd", { children: activeCount })
946
+ ] })
947
+ ] }),
948
+ /* @__PURE__ */ jsxs8("div", { className: "eth-trace__layout", children: [
949
+ /* @__PURE__ */ jsxs8("section", { className: "eth-trace__timeline-panel", "aria-label": "Trace timeline", children: [
950
+ /* @__PURE__ */ jsxs8("div", { className: "eth-trace__axis", "aria-hidden": "true", children: [
951
+ /* @__PURE__ */ jsx8("span", { children: "0 ms" }),
952
+ /* @__PURE__ */ jsx8("span", { children: formatDuration(timeline.total / 2) }),
953
+ /* @__PURE__ */ jsx8("span", { children: formatDuration(timeline.total) })
954
+ ] }),
955
+ /* @__PURE__ */ jsx8("div", { className: "eth-trace__timeline", role: "list", children: timeline.items.map(({ span, start, end, depth }) => {
956
+ const left = (start - timeline.min) / timeline.total * 100;
957
+ const width = Math.max((end - start) / timeline.total * 100, 1);
958
+ const selected = selectedSpan?.id === span.id;
959
+ return /* @__PURE__ */ jsxs8(
960
+ "div",
961
+ {
962
+ className: clsx8("eth-trace__row", selected && "eth-trace__row--selected"),
963
+ role: "listitem",
964
+ style: {
965
+ "--eth-trace-indent": `${depth}rem`,
966
+ "--eth-trace-left": `${left}%`,
967
+ "--eth-trace-width": `${width}%`
968
+ },
969
+ children: [
970
+ /* @__PURE__ */ jsxs8(
971
+ "button",
972
+ {
973
+ type: "button",
974
+ className: clsx8(
975
+ "eth-trace__span-label",
976
+ selected && "eth-trace__span-label--selected"
977
+ ),
978
+ "aria-pressed": selected,
979
+ onClick: () => setSelectedSpanId(span.id),
980
+ children: [
981
+ /* @__PURE__ */ jsxs8("span", { className: "eth-trace__span-title", children: [
982
+ /* @__PURE__ */ jsx8(StatusDot4, { status: span.status, label: statusLabel5(span.status) }),
983
+ /* @__PURE__ */ jsx8("span", { className: "eth-trace__span-name", children: span.name })
984
+ ] }),
985
+ /* @__PURE__ */ jsxs8("span", { className: "eth-trace__span-meta", children: [
986
+ formatTime(span.startedAt),
987
+ " \xB7 ",
988
+ formatDuration(span.durationMs)
989
+ ] })
990
+ ]
991
+ }
992
+ ),
993
+ /* @__PURE__ */ jsx8(
994
+ "div",
995
+ {
996
+ className: "eth-trace__track",
997
+ role: "group",
998
+ "aria-label": `${span.name}, ${statusLabel5(span.status)}, ${formatDuration(span.durationMs)}`,
999
+ children: /* @__PURE__ */ jsx8(
1000
+ "button",
1001
+ {
1002
+ type: "button",
1003
+ className: clsx8(
1004
+ "eth-trace__bar",
1005
+ `eth-trace__bar--${span.status}`,
1006
+ selected && "eth-trace__bar--selected"
1007
+ ),
1008
+ "aria-label": `Select ${span.name}`,
1009
+ onClick: () => setSelectedSpanId(span.id)
1010
+ }
1011
+ )
1012
+ }
1013
+ )
1014
+ ]
1015
+ },
1016
+ span.id
1017
+ );
1018
+ }) })
1019
+ ] }),
1020
+ /* @__PURE__ */ jsx8("aside", { className: "eth-trace__details", "aria-label": "Selected span details", children: selectedSpan ? /* @__PURE__ */ jsxs8(Fragment2, { children: [
1021
+ /* @__PURE__ */ jsxs8("header", { className: "eth-trace__details-header", children: [
1022
+ /* @__PURE__ */ jsxs8("div", { children: [
1023
+ /* @__PURE__ */ jsx8("p", { className: "eth-trace__details-eyebrow", children: "Selected span" }),
1024
+ /* @__PURE__ */ jsx8("h3", { children: selectedSpan.name })
1025
+ ] }),
1026
+ /* @__PURE__ */ jsx8(Badge3, { severity: statusSeverity(selectedSpan.status), children: statusLabel5(selectedSpan.status) })
1027
+ ] }),
1028
+ /* @__PURE__ */ jsxs8("dl", { className: "eth-trace__detail-grid", children: [
1029
+ /* @__PURE__ */ jsxs8("div", { children: [
1030
+ /* @__PURE__ */ jsx8("dt", { children: "Started" }),
1031
+ /* @__PURE__ */ jsx8("dd", { children: formatTime(selectedSpan.startedAt) })
1032
+ ] }),
1033
+ /* @__PURE__ */ jsxs8("div", { children: [
1034
+ /* @__PURE__ */ jsx8("dt", { children: "Duration" }),
1035
+ /* @__PURE__ */ jsx8("dd", { children: formatDuration(selectedSpan.durationMs) })
1036
+ ] }),
1037
+ /* @__PURE__ */ jsxs8("div", { children: [
1038
+ /* @__PURE__ */ jsx8("dt", { children: "Depth" }),
1039
+ /* @__PURE__ */ jsx8("dd", { children: selectedTimelineItem?.depth ?? 0 })
1040
+ ] }),
1041
+ /* @__PURE__ */ jsxs8("div", { children: [
1042
+ /* @__PURE__ */ jsx8("dt", { children: "Span ID" }),
1043
+ /* @__PURE__ */ jsx8("dd", { children: selectedSpan.id })
1044
+ ] }),
1045
+ selectedSpan.parentId ? /* @__PURE__ */ jsxs8("div", { children: [
1046
+ /* @__PURE__ */ jsx8("dt", { children: "Parent" }),
1047
+ /* @__PURE__ */ jsx8("dd", { children: selectedSpan.parentId })
1048
+ ] }) : null
1049
+ ] }),
1050
+ /* @__PURE__ */ jsxs8("section", { className: "eth-trace__attributes", children: [
1051
+ /* @__PURE__ */ jsxs8("div", { className: "eth-trace__attributes-header", children: [
1052
+ /* @__PURE__ */ jsx8("h4", { children: "Attributes" }),
1053
+ /* @__PURE__ */ jsx8(Badge3, { severity: "neutral", children: selectedAttributes.length })
1054
+ ] }),
1055
+ selectedAttributes.length ? /* @__PURE__ */ jsx8("pre", { children: prettyJson(selectedSpan.attributes) }) : /* @__PURE__ */ jsx8("p", { children: "No attributes recorded." })
1056
+ ] })
1057
+ ] }) : /* @__PURE__ */ jsx8(EmptyState2, { title: "Select a span" }) })
1058
+ ] })
1059
+ ] })
1060
+ }
1061
+ );
1062
+ }
1063
+ function buildTimeline(spans) {
1064
+ if (!spans.length) return { items: [], min: 0, total: 1 };
1065
+ const spansById = new Map(spans.map((span) => [span.id, span]));
1066
+ const depthById = /* @__PURE__ */ new Map();
1067
+ const depthFor = (span, seen = /* @__PURE__ */ new Set()) => {
1068
+ if (depthById.has(span.id)) return depthById.get(span.id) ?? 0;
1069
+ if (!span.parentId || seen.has(span.id)) {
1070
+ depthById.set(span.id, 0);
1071
+ return 0;
1072
+ }
1073
+ const parent = spansById.get(span.parentId);
1074
+ const depth = parent ? depthFor(parent, new Set(seen).add(span.id)) + 1 : 0;
1075
+ depthById.set(span.id, depth);
1076
+ return depth;
1077
+ };
1078
+ const items = spans.map((span, index) => {
1079
+ const parsed = new Date(span.startedAt).getTime();
1080
+ const start = Number.isNaN(parsed) ? index * 10 : parsed;
1081
+ const end = start + Math.max(span.durationMs, 1);
1082
+ return { span, start, end, depth: depthFor(span) };
1083
+ }).sort((a, b) => a.start - b.start);
1084
+ const min = Math.min(...items.map((item) => item.start));
1085
+ const max = Math.max(...items.map((item) => item.end));
1086
+ return { items, min, total: Math.max(max - min, 1) };
1087
+ }
1088
+
1089
+ // src/components/AgentToolCallLog.tsx
1090
+ import * as React4 from "react";
1091
+ import clsx9 from "clsx";
1092
+ import { Button as Button2, Drawer, EmptyState as EmptyState3, StatusDot as StatusDot5, Surface as Surface5, statusLabel as statusLabel6 } from "@echothink-ui/core";
1093
+ import { DataTable } from "@echothink-ui/data";
1094
+ import { SearchIcon } from "@echothink-ui/icons";
1095
+ import { Fragment as Fragment3, jsx as jsx9, jsxs as jsxs9 } from "react/jsx-runtime";
1096
+ function AgentToolCallLog({
1097
+ calls,
1098
+ onSelect,
1099
+ title = "Tool calls",
1100
+ subtitle,
1101
+ className,
1102
+ ...props
1103
+ }) {
1104
+ const [selectedCall, setSelectedCall] = React4.useState();
1105
+ const rows = React4.useMemo(
1106
+ () => calls.map((call) => {
1107
+ const argsPreview = jsonPreview(call.args, call.redacted);
1108
+ const resultPreview = call.error ?? jsonPreview(call.result, call.redacted);
1109
+ return {
1110
+ id: call.id,
1111
+ call,
1112
+ time: formatTime(call.startedAt),
1113
+ toolName: call.toolName,
1114
+ status: call.status,
1115
+ duration: formatDuration(call.durationMs),
1116
+ argsPreview,
1117
+ argsTone: previewTone(argsPreview, call.redacted),
1118
+ resultPreview,
1119
+ resultTone: call.error ? "error" : previewTone(resultPreview, call.redacted)
1120
+ };
1121
+ }),
1122
+ [calls]
1123
+ );
1124
+ const openCall = React4.useCallback(
1125
+ (call) => {
1126
+ setSelectedCall(call);
1127
+ onSelect?.(call);
1128
+ },
1129
+ [onSelect]
1130
+ );
1131
+ const columns = React4.useMemo(
1132
+ () => [
1133
+ {
1134
+ key: "time",
1135
+ header: "Time",
1136
+ width: "7rem",
1137
+ render: (row) => /* @__PURE__ */ jsx9("time", { className: "eth-agent-tool-call-log__time", dateTime: row.call.startedAt, children: row.time })
1138
+ },
1139
+ {
1140
+ key: "toolName",
1141
+ header: "Tool",
1142
+ width: "13rem",
1143
+ render: (row) => /* @__PURE__ */ jsx9("code", { className: "eth-agent-tool-call-log__tool", children: row.toolName })
1144
+ },
1145
+ {
1146
+ key: "status",
1147
+ header: "Status",
1148
+ width: "11rem",
1149
+ render: (row) => /* @__PURE__ */ jsx9(StatusDot5, { status: row.status, label: statusLabel6(row.status) })
1150
+ },
1151
+ {
1152
+ key: "duration",
1153
+ header: "Duration",
1154
+ width: "7rem",
1155
+ align: "end",
1156
+ render: (row) => /* @__PURE__ */ jsx9(PreviewText, { value: row.duration, tone: previewTone(row.duration) })
1157
+ },
1158
+ {
1159
+ key: "argsPreview",
1160
+ header: "Args",
1161
+ render: (row) => /* @__PURE__ */ jsx9(PreviewText, { value: row.argsPreview, tone: row.argsTone })
1162
+ },
1163
+ {
1164
+ key: "resultPreview",
1165
+ header: "Result",
1166
+ render: (row) => /* @__PURE__ */ jsx9(PreviewText, { value: row.resultPreview, tone: row.resultTone })
1167
+ },
1168
+ {
1169
+ key: "actions",
1170
+ header: "Actions",
1171
+ width: "7.5rem",
1172
+ align: "end",
1173
+ render: (row) => /* @__PURE__ */ jsx9(
1174
+ Button2,
1175
+ {
1176
+ "aria-label": `Inspect ${row.toolName} tool call`,
1177
+ className: "eth-agent-tool-call-log__inspect",
1178
+ density: "compact",
1179
+ icon: /* @__PURE__ */ jsx9(SearchIcon, { size: 16 }),
1180
+ intent: "ghost",
1181
+ onClick: () => openCall(row.call),
1182
+ children: "Inspect"
1183
+ }
1184
+ )
1185
+ }
1186
+ ],
1187
+ [openCall]
1188
+ );
1189
+ const defaultSubtitle = React4.useMemo(() => summarizeCalls(calls), [calls]);
1190
+ return /* @__PURE__ */ jsxs9(Fragment3, { children: [
1191
+ /* @__PURE__ */ jsx9(
1192
+ Surface5,
1193
+ {
1194
+ ...props,
1195
+ className: clsx9("eth-agent-tool-call-log", className),
1196
+ "data-eth-component": "AgentToolCallLog",
1197
+ subtitle: subtitle ?? defaultSubtitle,
1198
+ title,
1199
+ children: /* @__PURE__ */ jsx9(
1200
+ DataTable,
1201
+ {
1202
+ rows,
1203
+ columns,
1204
+ rowKey: "id",
1205
+ density: "compact",
1206
+ className: "eth-agent-tool-call-log__table",
1207
+ emptyState: /* @__PURE__ */ jsx9(EmptyState3, { title: "No tool calls" })
1208
+ }
1209
+ )
1210
+ }
1211
+ ),
1212
+ /* @__PURE__ */ jsx9(
1213
+ Drawer,
1214
+ {
1215
+ open: Boolean(selectedCall),
1216
+ title: selectedCall?.toolName ?? "Tool call",
1217
+ onClose: () => setSelectedCall(void 0),
1218
+ children: selectedCall ? /* @__PURE__ */ jsxs9("div", { className: "eth-agent-tool-call-log__drawer", children: [
1219
+ /* @__PURE__ */ jsxs9("div", { className: "eth-agent-tool-call-log__drawer-status", children: [
1220
+ /* @__PURE__ */ jsx9(StatusDot5, { status: selectedCall.status, label: statusLabel6(selectedCall.status) }),
1221
+ selectedCall.redacted ? /* @__PURE__ */ jsx9("span", { className: "eth-agent-tool-call-log__redaction-note", children: "Redaction applied" }) : null
1222
+ ] }),
1223
+ /* @__PURE__ */ jsxs9("dl", { className: "eth-agent-tool-call-log__meta", children: [
1224
+ /* @__PURE__ */ jsxs9("div", { children: [
1225
+ /* @__PURE__ */ jsx9("dt", { children: "Started" }),
1226
+ /* @__PURE__ */ jsx9("dd", { children: formatTime(selectedCall.startedAt) })
1227
+ ] }),
1228
+ /* @__PURE__ */ jsxs9("div", { children: [
1229
+ /* @__PURE__ */ jsx9("dt", { children: "Duration" }),
1230
+ /* @__PURE__ */ jsx9("dd", { children: formatDuration(selectedCall.durationMs) })
1231
+ ] }),
1232
+ /* @__PURE__ */ jsxs9("div", { children: [
1233
+ /* @__PURE__ */ jsx9("dt", { children: "Tool" }),
1234
+ /* @__PURE__ */ jsx9("dd", { children: /* @__PURE__ */ jsx9("code", { children: selectedCall.toolName }) })
1235
+ ] }),
1236
+ /* @__PURE__ */ jsxs9("div", { children: [
1237
+ /* @__PURE__ */ jsx9("dt", { children: "Redaction" }),
1238
+ /* @__PURE__ */ jsx9("dd", { children: selectedCall.redacted ? "Applied" : "None" })
1239
+ ] })
1240
+ ] }),
1241
+ selectedCall.error ? /* @__PURE__ */ jsxs9("section", { className: "eth-agent-tool-call-log__error", children: [
1242
+ /* @__PURE__ */ jsx9("h3", { children: "Error" }),
1243
+ /* @__PURE__ */ jsx9("pre", { tabIndex: 0, children: selectedCall.error })
1244
+ ] }) : null,
1245
+ /* @__PURE__ */ jsx9(
1246
+ JsonBlock,
1247
+ {
1248
+ title: "Arguments",
1249
+ value: prettyJson(selectedCall.args, selectedCall.redacted)
1250
+ }
1251
+ ),
1252
+ /* @__PURE__ */ jsx9(
1253
+ JsonBlock,
1254
+ {
1255
+ title: "Result",
1256
+ value: prettyJson(selectedCall.result, selectedCall.redacted)
1257
+ }
1258
+ )
1259
+ ] }) : null
1260
+ }
1261
+ )
1262
+ ] });
1263
+ }
1264
+ function summarizeCalls(calls) {
1265
+ if (!calls.length) return void 0;
1266
+ const active = calls.filter(
1267
+ (call) => ["queued", "running", "in-progress", "pending-approval", "approval-required"].includes(
1268
+ call.status
1269
+ )
1270
+ ).length;
1271
+ const redacted = calls.filter((call) => call.redacted).length;
1272
+ return [
1273
+ `${calls.length} call${calls.length === 1 ? "" : "s"}`,
1274
+ active ? `${active} active` : null,
1275
+ redacted ? `${redacted} redacted` : null
1276
+ ].filter(Boolean).join(" | ");
1277
+ }
1278
+ function previewTone(value, redacted = false) {
1279
+ if (redacted && value === "[redacted]") return "redacted";
1280
+ if (value === EMPTY_MARK) return "empty";
1281
+ return "default";
1282
+ }
1283
+ function PreviewText({ value, tone = "default" }) {
1284
+ if (tone === "redacted") {
1285
+ return /* @__PURE__ */ jsx9("span", { className: "eth-agent-tool-call-log__preview eth-agent-tool-call-log__preview--redacted", children: "Redacted" });
1286
+ }
1287
+ return /* @__PURE__ */ jsx9(
1288
+ "span",
1289
+ {
1290
+ className: clsx9(
1291
+ "eth-agent-tool-call-log__preview",
1292
+ tone !== "default" && `eth-agent-tool-call-log__preview--${tone}`
1293
+ ),
1294
+ title: value === EMPTY_MARK ? void 0 : value,
1295
+ children: value
1296
+ }
1297
+ );
1298
+ }
1299
+ function JsonBlock({ title, value }) {
1300
+ const headingId = React4.useId();
1301
+ return /* @__PURE__ */ jsxs9("section", { className: "eth-agent-tool-call-log__json", "aria-labelledby": headingId, children: [
1302
+ /* @__PURE__ */ jsx9("h3", { id: headingId, children: title }),
1303
+ /* @__PURE__ */ jsx9("pre", { tabIndex: 0, children: value })
1304
+ ] });
1305
+ }
1306
+
1307
+ // src/components/AgentApprovalGate.tsx
1308
+ import * as React5 from "react";
1309
+ import clsx10 from "clsx";
1310
+ import { Button as Button3, InlineNotification, Surface as Surface6, Textarea as Textarea2 } from "@echothink-ui/core";
1311
+ import { ExternalLinkIcon } from "@echothink-ui/icons";
1312
+ import { Fragment as Fragment4, jsx as jsx10, jsxs as jsxs10 } from "react/jsx-runtime";
1313
+ function AgentApprovalGate({
1314
+ action,
1315
+ evidence = [],
1316
+ onApprove,
1317
+ onReject,
1318
+ state = "idle",
1319
+ title = "Approval required",
1320
+ className,
1321
+ ...props
1322
+ }) {
1323
+ const [reason, setReason] = React5.useState("");
1324
+ const severity = riskSeverity(action.riskLevel);
1325
+ const locked = state === "pending" || state === "approved" || state === "rejected";
1326
+ const stateLabel2 = approvalStateLabel(state);
1327
+ return /* @__PURE__ */ jsx10(
1328
+ Surface6,
1329
+ {
1330
+ ...props,
1331
+ className: clsx10("eth-agent-approval-gate", `eth-agent-approval-gate--${state}`, className),
1332
+ "data-eth-component": "AgentApprovalGate",
1333
+ severity,
1334
+ status: approvalStatus(state),
1335
+ title,
1336
+ subtitle: action.label,
1337
+ children: /* @__PURE__ */ jsxs10("div", { className: "eth-agent-approval-gate__layout", children: [
1338
+ /* @__PURE__ */ jsx10(
1339
+ InlineNotification,
1340
+ {
1341
+ severity,
1342
+ title: `${riskLabel(action.riskLevel)} risk action`,
1343
+ children: action.description
1344
+ }
1345
+ ),
1346
+ /* @__PURE__ */ jsxs10("dl", { className: "eth-agent-approval-gate__summary", "aria-label": "Approval action details", children: [
1347
+ /* @__PURE__ */ jsxs10("div", { children: [
1348
+ /* @__PURE__ */ jsx10("dt", { children: "Action" }),
1349
+ /* @__PURE__ */ jsx10("dd", { children: action.id })
1350
+ ] }),
1351
+ /* @__PURE__ */ jsxs10("div", { children: [
1352
+ /* @__PURE__ */ jsx10("dt", { children: "Risk" }),
1353
+ /* @__PURE__ */ jsx10("dd", { children: riskLabel(action.riskLevel) })
1354
+ ] }),
1355
+ /* @__PURE__ */ jsxs10("div", { children: [
1356
+ /* @__PURE__ */ jsx10("dt", { children: "Status" }),
1357
+ /* @__PURE__ */ jsx10("dd", { children: stateLabel2 })
1358
+ ] })
1359
+ ] }),
1360
+ evidence.length ? /* @__PURE__ */ jsxs10("section", { className: "eth-agent-approval-gate__evidence", children: [
1361
+ /* @__PURE__ */ jsxs10("div", { className: "eth-agent-approval-gate__section-header", children: [
1362
+ /* @__PURE__ */ jsx10("h3", { children: "Evidence" }),
1363
+ /* @__PURE__ */ jsxs10("span", { children: [
1364
+ evidence.length,
1365
+ " reference",
1366
+ evidence.length === 1 ? "" : "s"
1367
+ ] })
1368
+ ] }),
1369
+ /* @__PURE__ */ jsx10("div", { className: "eth-agent-approval-gate__evidence-list", children: evidence.map((item) => /* @__PURE__ */ jsx10(EvidenceItem, { item }, item.id)) })
1370
+ ] }) : null,
1371
+ /* @__PURE__ */ jsx10(
1372
+ Textarea2,
1373
+ {
1374
+ className: "eth-agent-approval-gate__reason",
1375
+ "aria-label": "Approval reason",
1376
+ disabled: locked,
1377
+ labelText: "Approval rationale",
1378
+ placeholder: "Optional reason",
1379
+ rows: 2,
1380
+ value: reason,
1381
+ onChange: (event) => setReason(event.currentTarget.value)
1382
+ }
1383
+ ),
1384
+ /* @__PURE__ */ jsxs10("div", { className: "eth-agent-approval-gate__actions", children: [
1385
+ /* @__PURE__ */ jsx10(
1386
+ Button3,
1387
+ {
1388
+ density: "default",
1389
+ intent: "success",
1390
+ loading: state === "pending",
1391
+ disabled: locked,
1392
+ onClick: () => onApprove?.(reason || void 0),
1393
+ children: state === "approved" ? "Approved" : "Approve"
1394
+ }
1395
+ ),
1396
+ /* @__PURE__ */ jsx10(
1397
+ Button3,
1398
+ {
1399
+ density: "default",
1400
+ intent: "danger",
1401
+ disabled: locked,
1402
+ onClick: () => onReject?.(reason || void 0),
1403
+ children: state === "rejected" ? "Rejected" : "Reject"
1404
+ }
1405
+ )
1406
+ ] })
1407
+ ] })
1408
+ }
1409
+ );
1410
+ }
1411
+ function EvidenceItem({ item }) {
1412
+ const content = /* @__PURE__ */ jsxs10(Fragment4, { children: [
1413
+ /* @__PURE__ */ jsxs10("span", { className: "eth-agent-approval-gate__evidence-copy", children: [
1414
+ /* @__PURE__ */ jsx10("span", { className: "eth-agent-approval-gate__evidence-label", children: item.label }),
1415
+ item.description ? /* @__PURE__ */ jsx10("span", { className: "eth-agent-approval-gate__evidence-description", children: item.description }) : null
1416
+ ] }),
1417
+ item.meta ? /* @__PURE__ */ jsx10("span", { className: "eth-agent-approval-gate__evidence-meta", children: item.meta }) : null,
1418
+ item.href ? /* @__PURE__ */ jsx10(ExternalLinkIcon, { className: "eth-agent-approval-gate__evidence-icon", size: 16 }) : null
1419
+ ] });
1420
+ if (item.href) {
1421
+ return /* @__PURE__ */ jsx10(
1422
+ "a",
1423
+ {
1424
+ className: "eth-agent-approval-gate__evidence-item eth-agent-approval-gate__evidence-item--link",
1425
+ href: item.href,
1426
+ children: content
1427
+ }
1428
+ );
1429
+ }
1430
+ return /* @__PURE__ */ jsx10("div", { className: "eth-agent-approval-gate__evidence-item", children: content });
1431
+ }
1432
+ function riskLabel(riskLevel) {
1433
+ if (!riskLevel) return "Low";
1434
+ return riskLevel.charAt(0).toUpperCase() + riskLevel.slice(1);
1435
+ }
1436
+ function approvalStateLabel(state) {
1437
+ if (state === "pending") return "Submitting";
1438
+ if (state === "approved") return "Approved";
1439
+ if (state === "rejected") return "Rejected";
1440
+ return "Awaiting decision";
1441
+ }
1442
+ function approvalStatus(state) {
1443
+ if (state === "pending") return "running";
1444
+ if (state === "approved") return "completed";
1445
+ if (state === "rejected") return "blocked";
1446
+ return "approval-required";
1447
+ }
1448
+
1449
+ // src/components/AgentPlanPreview.tsx
1450
+ import clsx11 from "clsx";
1451
+ import { Badge as Badge4, Surface as Surface7 } from "@echothink-ui/core";
1452
+ import { jsx as jsx11, jsxs as jsxs11 } from "react/jsx-runtime";
1453
+ function AgentPlanPreview({ plan, title, className, ...props }) {
1454
+ return /* @__PURE__ */ jsx11(
1455
+ Surface7,
1456
+ {
1457
+ ...props,
1458
+ className: clsx11("eth-agent-plan-preview", className),
1459
+ "data-eth-component": "AgentPlanPreview",
1460
+ title: title ?? "Proposed plan",
1461
+ subtitle: "Plan before execution",
1462
+ children: /* @__PURE__ */ jsxs11("div", { className: "eth-agent-plan-preview__body", children: [
1463
+ /* @__PURE__ */ jsxs11("div", { className: "eth-agent-plan-preview__summary", "aria-label": "Plan summary", children: [
1464
+ /* @__PURE__ */ jsxs11("div", { children: [
1465
+ /* @__PURE__ */ jsx11("p", { className: "eth-agent-plan-preview__summary-label", children: "Execution plan" }),
1466
+ /* @__PURE__ */ jsx11("p", { className: "eth-agent-plan-preview__summary-title", children: plan.title })
1467
+ ] }),
1468
+ /* @__PURE__ */ jsxs11("span", { className: "eth-agent-plan-preview__summary-count", children: [
1469
+ plan.steps.length,
1470
+ " ",
1471
+ plan.steps.length === 1 ? "step" : "steps"
1472
+ ] })
1473
+ ] }),
1474
+ plan.steps.length ? /* @__PURE__ */ jsx11("ol", { className: "eth-agent-plan-preview__steps", "aria-label": "Proposed execution steps", children: plan.steps.map((step, index) => /* @__PURE__ */ jsx11(
1475
+ "li",
1476
+ {
1477
+ className: clsx11(
1478
+ "eth-agent-plan-preview__step",
1479
+ step.risks?.length && "eth-agent-plan-preview__step--risk"
1480
+ ),
1481
+ children: /* @__PURE__ */ jsxs11("article", { className: "eth-agent-plan-preview__step-card", children: [
1482
+ /* @__PURE__ */ jsx11("span", { className: "eth-agent-plan-preview__step-index", "aria-hidden": "true", children: String(index + 1).padStart(2, "0") }),
1483
+ /* @__PURE__ */ jsxs11("div", { className: "eth-agent-plan-preview__step-main", children: [
1484
+ /* @__PURE__ */ jsx11("p", { className: "eth-agent-plan-preview__step-description", children: step.description }),
1485
+ step.durationEstimate || step.risks?.length ? /* @__PURE__ */ jsxs11("div", { className: "eth-agent-plan-preview__step-meta", "aria-label": "Step metadata", children: [
1486
+ step.durationEstimate ? /* @__PURE__ */ jsx11(Badge4, { children: step.durationEstimate }) : null,
1487
+ step.risks?.map((risk) => /* @__PURE__ */ jsx11(Badge4, { severity: "warning", children: risk }, risk))
1488
+ ] }) : null
1489
+ ] })
1490
+ ] })
1491
+ },
1492
+ step.id
1493
+ )) }) : /* @__PURE__ */ jsx11("p", { className: "eth-agent-plan-preview__empty", children: "No execution steps have been proposed." }),
1494
+ plan.assumptions?.length || plan.risks?.length ? /* @__PURE__ */ jsxs11("div", { className: "eth-agent-plan-preview__supporting", children: [
1495
+ plan.assumptions?.length ? /* @__PURE__ */ jsx11(TextList, { title: "Assumptions", items: plan.assumptions }) : null,
1496
+ plan.risks?.length ? /* @__PURE__ */ jsx11(TextList, { title: "Risks", items: plan.risks, tone: "risk" }) : null
1497
+ ] }) : null
1498
+ ] })
1499
+ }
1500
+ );
1501
+ }
1502
+ function TextList({
1503
+ title,
1504
+ items,
1505
+ tone = "neutral"
1506
+ }) {
1507
+ return /* @__PURE__ */ jsxs11(
1508
+ "section",
1509
+ {
1510
+ className: clsx11(
1511
+ "eth-agent-plan-preview__note-section",
1512
+ `eth-agent-plan-preview__note-section--${tone}`
1513
+ ),
1514
+ children: [
1515
+ /* @__PURE__ */ jsx11("h3", { className: "eth-agent-plan-preview__note-title", children: title }),
1516
+ /* @__PURE__ */ jsx11("ul", { className: "eth-agent-plan-preview__note-list", children: items.map((item) => /* @__PURE__ */ jsxs11("li", { children: [
1517
+ /* @__PURE__ */ jsx11("span", { className: "eth-agent-plan-preview__note-marker", "aria-hidden": "true" }),
1518
+ /* @__PURE__ */ jsx11("span", { children: item })
1519
+ ] }, item)) })
1520
+ ]
1521
+ }
1522
+ );
1523
+ }
1524
+
1525
+ // src/components/AgentPlanDiff.tsx
1526
+ import * as React6 from "react";
1527
+ import clsx12 from "clsx";
1528
+ import { Badge as Badge5, Surface as Surface8 } from "@echothink-ui/core";
1529
+ import { jsx as jsx12, jsxs as jsxs12 } from "react/jsx-runtime";
1530
+ function AgentPlanDiff({
1531
+ before,
1532
+ after,
1533
+ title = "Plan diff",
1534
+ subtitle = "Compare proposed plan changes before execution",
1535
+ className,
1536
+ ...props
1537
+ }) {
1538
+ const diff = React6.useMemo(() => diffPlanSteps(before, after), [before, after]);
1539
+ const summary = React6.useMemo(
1540
+ () => ({
1541
+ added: diff.filter((item) => item.status === "added").length,
1542
+ modified: diff.filter((item) => item.status === "modified").length,
1543
+ removed: diff.filter((item) => item.status === "removed").length,
1544
+ unchanged: diff.filter((item) => item.status === "unchanged").length
1545
+ }),
1546
+ [diff]
1547
+ );
1548
+ return /* @__PURE__ */ jsx12(
1549
+ Surface8,
1550
+ {
1551
+ ...props,
1552
+ className: clsx12("eth-agent-plan-diff", className),
1553
+ "data-eth-component": "AgentPlanDiff",
1554
+ subtitle,
1555
+ title,
1556
+ children: /* @__PURE__ */ jsxs12("div", { className: "eth-agent-plan-diff__body", children: [
1557
+ /* @__PURE__ */ jsxs12("dl", { className: "eth-agent-plan-diff__summary", "aria-label": "Plan diff summary", children: [
1558
+ /* @__PURE__ */ jsx12(SummaryItem, { label: "Added", value: summary.added, tone: "added" }),
1559
+ /* @__PURE__ */ jsx12(SummaryItem, { label: "Modified", value: summary.modified, tone: "modified" }),
1560
+ /* @__PURE__ */ jsx12(SummaryItem, { label: "Removed", value: summary.removed, tone: "removed" }),
1561
+ /* @__PURE__ */ jsx12(SummaryItem, { label: "Unchanged", value: summary.unchanged, tone: "unchanged" })
1562
+ ] }),
1563
+ diff.length ? /* @__PURE__ */ jsx12("ol", { className: "eth-agent-plan-diff__list", "aria-label": "Plan step changes", children: diff.map((item) => {
1564
+ const stepId = item.after?.id ?? item.before?.id ?? item.id;
1565
+ return /* @__PURE__ */ jsx12("li", { className: "eth-agent-plan-diff__entry", children: /* @__PURE__ */ jsxs12(
1566
+ "article",
1567
+ {
1568
+ className: clsx12(
1569
+ "eth-agent-plan-diff__item",
1570
+ `eth-agent-plan-diff__item--${item.status}`
1571
+ ),
1572
+ children: [
1573
+ /* @__PURE__ */ jsx12("header", { className: "eth-agent-plan-diff__item-header", children: /* @__PURE__ */ jsxs12("div", { className: "eth-agent-plan-diff__item-heading", children: [
1574
+ /* @__PURE__ */ jsxs12("span", { className: "eth-agent-plan-diff__step-id", children: [
1575
+ "Step ",
1576
+ stepId
1577
+ ] }),
1578
+ /* @__PURE__ */ jsx12(Badge5, { severity: item.severity, children: statusLabelFor(item.status) })
1579
+ ] }) }),
1580
+ item.status === "modified" ? /* @__PURE__ */ jsxs12("div", { className: "eth-agent-plan-diff__comparison", children: [
1581
+ /* @__PURE__ */ jsx12(StepSnapshot, { label: "Before", step: item.before }),
1582
+ /* @__PURE__ */ jsx12(StepSnapshot, { label: "After", step: item.after })
1583
+ ] }) : /* @__PURE__ */ jsx12(
1584
+ StepSnapshot,
1585
+ {
1586
+ label: snapshotLabelFor(item.status),
1587
+ step: item.after ?? item.before
1588
+ }
1589
+ )
1590
+ ]
1591
+ }
1592
+ ) }, item.id);
1593
+ }) }) : /* @__PURE__ */ jsx12("p", { className: "eth-agent-plan-diff__empty", children: "No plan steps to compare." })
1594
+ ] })
1595
+ }
1596
+ );
1597
+ }
1598
+ function StepSnapshot({ label, step }) {
1599
+ if (!step) return null;
1600
+ return /* @__PURE__ */ jsxs12("section", { className: "eth-agent-plan-diff__snapshot", children: [
1601
+ /* @__PURE__ */ jsx12("h3", { className: "eth-agent-plan-diff__snapshot-label", children: label }),
1602
+ /* @__PURE__ */ jsx12("p", { className: "eth-agent-plan-diff__snapshot-description", children: step.description }),
1603
+ step.durationEstimate || step.risks?.length ? /* @__PURE__ */ jsxs12("div", { className: "eth-agent-plan-diff__snapshot-meta", "aria-label": `${label} metadata`, children: [
1604
+ step.durationEstimate ? /* @__PURE__ */ jsx12(Badge5, { children: step.durationEstimate }) : null,
1605
+ step.risks?.map((risk) => /* @__PURE__ */ jsx12(Badge5, { severity: "warning", children: risk }, risk))
1606
+ ] }) : null
1607
+ ] });
1608
+ }
1609
+ function SummaryItem({
1610
+ label,
1611
+ value,
1612
+ tone
1613
+ }) {
1614
+ return /* @__PURE__ */ jsxs12(
1615
+ "div",
1616
+ {
1617
+ className: clsx12(
1618
+ "eth-agent-plan-diff__summary-item",
1619
+ `eth-agent-plan-diff__summary-item--${tone}`
1620
+ ),
1621
+ children: [
1622
+ /* @__PURE__ */ jsx12("dt", { children: label }),
1623
+ /* @__PURE__ */ jsx12("dd", { children: value })
1624
+ ]
1625
+ }
1626
+ );
1627
+ }
1628
+ function statusLabelFor(status) {
1629
+ switch (status) {
1630
+ case "added":
1631
+ return "Added";
1632
+ case "removed":
1633
+ return "Removed";
1634
+ case "modified":
1635
+ return "Modified";
1636
+ case "unchanged":
1637
+ return "Unchanged";
1638
+ }
1639
+ }
1640
+ function snapshotLabelFor(status) {
1641
+ if (status === "added") return "Added step";
1642
+ if (status === "removed") return "Removed step";
1643
+ return "Step";
1644
+ }
1645
+
1646
+ // src/components/AgentMemoryPanel.tsx
1647
+ import * as React7 from "react";
1648
+ import clsx13 from "clsx";
1649
+ import { Badge as Badge6, Button as Button4, EmptyState as EmptyState4, Surface as Surface9 } from "@echothink-ui/core";
1650
+ import { jsx as jsx13, jsxs as jsxs13 } from "react/jsx-runtime";
1651
+ var kinds = ["user", "project", "feedback", "reference"];
1652
+ function AgentMemoryPanel({
1653
+ entries,
1654
+ onPin,
1655
+ onEdit,
1656
+ onDelete,
1657
+ title = "Agent memory",
1658
+ subtitle = "Stored instructions and retrieved context available to the agent",
1659
+ className,
1660
+ ...props
1661
+ }) {
1662
+ const headingPrefix = React7.useId();
1663
+ const groups = React7.useMemo(
1664
+ () => kinds.map((kind) => ({ kind, entries: entries.filter((entry) => entry.kind === kind) })).filter((group) => group.entries.length),
1665
+ [entries]
1666
+ );
1667
+ const pinnedCount = React7.useMemo(
1668
+ () => entries.filter((entry) => entry.pinned).length,
1669
+ [entries]
1670
+ );
1671
+ const latestUpdatedAt = React7.useMemo(() => {
1672
+ const sortedEntries = entries.filter(
1673
+ (entry) => Boolean(entry.lastUpdatedAt && !Number.isNaN(new Date(entry.lastUpdatedAt).getTime()))
1674
+ ).sort((a, b) => new Date(b.lastUpdatedAt).getTime() - new Date(a.lastUpdatedAt).getTime());
1675
+ return sortedEntries[0]?.lastUpdatedAt;
1676
+ }, [entries]);
1677
+ return /* @__PURE__ */ jsx13(
1678
+ Surface9,
1679
+ {
1680
+ ...props,
1681
+ className: clsx13("eth-agent-memory-panel", className),
1682
+ "data-eth-component": "AgentMemoryPanel",
1683
+ subtitle,
1684
+ title,
1685
+ children: !groups.length ? /* @__PURE__ */ jsx13(EmptyState4, { title: "No memory entries" }) : /* @__PURE__ */ jsxs13("div", { className: "eth-agent-memory-panel__body", children: [
1686
+ /* @__PURE__ */ jsxs13("dl", { className: "eth-agent-memory-panel__summary", "aria-label": "Memory summary", children: [
1687
+ /* @__PURE__ */ jsxs13("div", { className: "eth-agent-memory-panel__summary-item", children: [
1688
+ /* @__PURE__ */ jsx13("dt", { children: "Total entries" }),
1689
+ /* @__PURE__ */ jsx13("dd", { children: entries.length })
1690
+ ] }),
1691
+ /* @__PURE__ */ jsxs13("div", { className: "eth-agent-memory-panel__summary-item", children: [
1692
+ /* @__PURE__ */ jsx13("dt", { children: "Pinned" }),
1693
+ /* @__PURE__ */ jsx13("dd", { children: pinnedCount })
1694
+ ] }),
1695
+ /* @__PURE__ */ jsxs13("div", { className: "eth-agent-memory-panel__summary-item", children: [
1696
+ /* @__PURE__ */ jsx13("dt", { children: "Latest update" }),
1697
+ /* @__PURE__ */ jsx13("dd", { children: latestUpdatedAt ? /* @__PURE__ */ jsx13("time", { dateTime: latestUpdatedAt, children: formatDateTime(latestUpdatedAt) }) : "Not recorded" })
1698
+ ] })
1699
+ ] }),
1700
+ groups.map((group) => /* @__PURE__ */ jsxs13(
1701
+ "section",
1702
+ {
1703
+ className: "eth-agent-memory-panel__group",
1704
+ "aria-labelledby": `${headingPrefix}-${group.kind}`,
1705
+ children: [
1706
+ /* @__PURE__ */ jsxs13("header", { className: "eth-agent-memory-panel__group-header", children: [
1707
+ /* @__PURE__ */ jsx13("h3", { id: `${headingPrefix}-${group.kind}`, children: kindTitle(group.kind) }),
1708
+ /* @__PURE__ */ jsxs13(Badge6, { severity: "neutral", children: [
1709
+ group.entries.length,
1710
+ " ",
1711
+ group.entries.length === 1 ? "entry" : "entries"
1712
+ ] })
1713
+ ] }),
1714
+ /* @__PURE__ */ jsx13("div", { className: "eth-agent-memory-panel__entries", children: group.entries.map((entry) => /* @__PURE__ */ jsxs13(
1715
+ "article",
1716
+ {
1717
+ className: clsx13(
1718
+ "eth-agent-memory-panel__entry",
1719
+ entry.pinned && "eth-agent-memory-panel__entry--pinned"
1720
+ ),
1721
+ children: [
1722
+ /* @__PURE__ */ jsxs13("header", { className: "eth-agent-memory-panel__entry-header", children: [
1723
+ /* @__PURE__ */ jsxs13("span", { className: "eth-agent-memory-panel__entry-title", children: [
1724
+ /* @__PURE__ */ jsx13("strong", { children: entry.key }),
1725
+ entry.pinned ? /* @__PURE__ */ jsx13(Badge6, { severity: "info", children: "Pinned" }) : null
1726
+ ] }),
1727
+ entry.lastUpdatedAt ? /* @__PURE__ */ jsx13(
1728
+ "time",
1729
+ {
1730
+ className: "eth-agent-memory-panel__updated-at",
1731
+ dateTime: entry.lastUpdatedAt,
1732
+ children: formatDateTime(entry.lastUpdatedAt)
1733
+ }
1734
+ ) : null
1735
+ ] }),
1736
+ /* @__PURE__ */ jsx13("div", { className: "eth-agent-memory-panel__value", children: entry.value }),
1737
+ onPin || onEdit || onDelete ? /* @__PURE__ */ jsxs13(
1738
+ "div",
1739
+ {
1740
+ className: "eth-agent-memory-panel__actions",
1741
+ "aria-label": `${entry.key} memory actions`,
1742
+ children: [
1743
+ onPin ? /* @__PURE__ */ jsx13(
1744
+ Button4,
1745
+ {
1746
+ "aria-label": `${entry.pinned ? "Unpin" : "Pin"} ${entry.key}`,
1747
+ density: "compact",
1748
+ intent: "secondary",
1749
+ onClick: () => onPin(entry.id),
1750
+ children: entry.pinned ? "Unpin" : "Pin"
1751
+ }
1752
+ ) : null,
1753
+ onEdit ? /* @__PURE__ */ jsx13(
1754
+ Button4,
1755
+ {
1756
+ "aria-label": `Edit ${entry.key}`,
1757
+ density: "compact",
1758
+ intent: "secondary",
1759
+ onClick: () => onEdit(entry.id),
1760
+ children: "Edit"
1761
+ }
1762
+ ) : null,
1763
+ onDelete ? /* @__PURE__ */ jsx13(
1764
+ Button4,
1765
+ {
1766
+ "aria-label": `Delete ${entry.key}`,
1767
+ density: "compact",
1768
+ intent: "danger",
1769
+ onClick: () => onDelete(entry.id),
1770
+ children: "Delete"
1771
+ }
1772
+ ) : null
1773
+ ]
1774
+ }
1775
+ ) : null
1776
+ ]
1777
+ },
1778
+ entry.id
1779
+ )) })
1780
+ ]
1781
+ },
1782
+ group.kind
1783
+ ))
1784
+ ] })
1785
+ }
1786
+ );
1787
+ }
1788
+ function kindTitle(kind) {
1789
+ return kind.charAt(0).toUpperCase() + kind.slice(1);
1790
+ }
1791
+
1792
+ // src/components/AgentContextViewer.tsx
1793
+ import * as React8 from "react";
1794
+ import clsx14 from "clsx";
1795
+ import { Badge as Badge7, EmptyState as EmptyState5, Surface as Surface10 } from "@echothink-ui/core";
1796
+ import {
1797
+ AgentRunningIcon,
1798
+ ChevronRightIcon as ChevronRightIcon2,
1799
+ DocumentIcon,
1800
+ ExternalLinkIcon as ExternalLinkIcon2,
1801
+ MessageIcon,
1802
+ SearchIcon as SearchIcon2
1803
+ } from "@echothink-ui/icons";
1804
+ import { Fragment as Fragment5, jsx as jsx14, jsxs as jsxs14 } from "react/jsx-runtime";
1805
+ function AgentContextViewer({
1806
+ sources,
1807
+ onSelect,
1808
+ title = "Context sources",
1809
+ className,
1810
+ ...props
1811
+ }) {
1812
+ const sourceListLabel = typeof title === "string" ? title : "Context sources";
1813
+ const sortedSources = React8.useMemo(
1814
+ () => [...sources].sort((a, b) => (b.relevance ?? -1) - (a.relevance ?? -1)),
1815
+ [sources]
1816
+ );
1817
+ return /* @__PURE__ */ jsx14(
1818
+ Surface10,
1819
+ {
1820
+ ...props,
1821
+ className: clsx14("eth-agent-context-viewer", className),
1822
+ "data-eth-component": "AgentContextViewer",
1823
+ title,
1824
+ children: !sortedSources.length ? /* @__PURE__ */ jsx14(EmptyState5, { title: "No context sources" }) : /* @__PURE__ */ jsx14("ul", { className: "eth-agent-context-viewer__sources", "aria-label": sourceListLabel, children: sortedSources.map((source) => {
1825
+ const SourceIcon = sourceIcon(source.type);
1826
+ const relevance = source.relevance == null ? null : formatRelevance(source.relevance);
1827
+ const relevanceValue = source.relevance == null ? null : normalizedRelevance(source.relevance);
1828
+ const isInteractive = Boolean(source.href || onSelect);
1829
+ const content = /* @__PURE__ */ jsxs14(Fragment5, { children: [
1830
+ /* @__PURE__ */ jsx14("span", { className: "eth-agent-context-viewer__kind-icon", "aria-hidden": "true", children: /* @__PURE__ */ jsx14(SourceIcon, { size: 18 }) }),
1831
+ /* @__PURE__ */ jsxs14("span", { className: "eth-agent-context-viewer__main", children: [
1832
+ /* @__PURE__ */ jsxs14("span", { className: "eth-agent-context-viewer__topline", children: [
1833
+ /* @__PURE__ */ jsx14("strong", { className: "eth-agent-context-viewer__label", children: source.label }),
1834
+ /* @__PURE__ */ jsx14(Badge7, { severity: "neutral", children: typeLabel(source.type) })
1835
+ ] }),
1836
+ source.excerpt ? /* @__PURE__ */ jsx14("span", { className: "eth-agent-context-viewer__excerpt", children: source.excerpt }) : null
1837
+ ] }),
1838
+ /* @__PURE__ */ jsxs14("span", { className: "eth-agent-context-viewer__aside", children: [
1839
+ relevance != null && relevanceValue != null ? /* @__PURE__ */ jsxs14(
1840
+ "span",
1841
+ {
1842
+ className: "eth-agent-context-viewer__relevance",
1843
+ "aria-label": `Relevance ${relevance}`,
1844
+ children: [
1845
+ /* @__PURE__ */ jsxs14("span", { className: "eth-agent-context-viewer__relevance-value", children: [
1846
+ "Relevance ",
1847
+ relevance
1848
+ ] }),
1849
+ /* @__PURE__ */ jsx14(
1850
+ "span",
1851
+ {
1852
+ className: "eth-agent-context-viewer__relevance-meter",
1853
+ "aria-hidden": "true",
1854
+ children: /* @__PURE__ */ jsx14("span", { style: { inlineSize: `${relevanceValue}%` } })
1855
+ }
1856
+ )
1857
+ ]
1858
+ }
1859
+ ) : /* @__PURE__ */ jsx14("span", { className: "eth-agent-context-viewer__unranked", children: "Unranked" }),
1860
+ source.href ? /* @__PURE__ */ jsx14(ExternalLinkIcon2, { className: "eth-agent-context-viewer__indicator", size: 16 }) : isInteractive ? /* @__PURE__ */ jsx14(ChevronRightIcon2, { className: "eth-agent-context-viewer__indicator", size: 16 }) : null
1861
+ ] })
1862
+ ] });
1863
+ return /* @__PURE__ */ jsx14("li", { children: source.href ? /* @__PURE__ */ jsx14(
1864
+ "a",
1865
+ {
1866
+ className: clsx14(
1867
+ "eth-agent-context-viewer__source",
1868
+ "eth-agent-context-viewer__source--interactive"
1869
+ ),
1870
+ href: source.href,
1871
+ onClick: () => onSelect?.(source),
1872
+ children: content
1873
+ }
1874
+ ) : onSelect ? /* @__PURE__ */ jsx14(
1875
+ "button",
1876
+ {
1877
+ type: "button",
1878
+ className: clsx14(
1879
+ "eth-agent-context-viewer__source",
1880
+ "eth-agent-context-viewer__source--interactive"
1881
+ ),
1882
+ onClick: () => onSelect(source),
1883
+ children: content
1884
+ }
1885
+ ) : /* @__PURE__ */ jsx14("article", { className: "eth-agent-context-viewer__source", children: content }) }, source.id);
1886
+ }) })
1887
+ }
1888
+ );
1889
+ }
1890
+ function sourceIcon(type) {
1891
+ switch (type) {
1892
+ case "document":
1893
+ return DocumentIcon;
1894
+ case "query":
1895
+ return SearchIcon2;
1896
+ case "tool-result":
1897
+ return AgentRunningIcon;
1898
+ case "message":
1899
+ default:
1900
+ return MessageIcon;
1901
+ }
1902
+ }
1903
+ function typeLabel(type) {
1904
+ return type.split("-").map((part) => part.charAt(0).toUpperCase() + part.slice(1)).join(" ");
1905
+ }
1906
+ function formatRelevance(relevance) {
1907
+ return `${normalizedRelevance(relevance)}%`;
1908
+ }
1909
+ function normalizedRelevance(relevance) {
1910
+ const normalized = relevance <= 1 ? relevance * 100 : relevance;
1911
+ return Math.min(100, Math.max(0, Math.round(normalized)));
1912
+ }
1913
+
1914
+ // src/components/AgentRunControls.tsx
1915
+ import * as React9 from "react";
1916
+ import clsx15 from "clsx";
1917
+ import { Badge as Badge8, Button as Button5, InlineNotification as InlineNotification2, Textarea as Textarea3 } from "@echothink-ui/core";
1918
+ import { InterruptIcon, PauseIcon, PlayIcon, RetryIcon, StopIcon } from "@echothink-ui/icons";
1919
+ import { jsx as jsx15, jsxs as jsxs15 } from "react/jsx-runtime";
1920
+ var stateMeta = {
1921
+ running: {
1922
+ label: "Running",
1923
+ severity: "info",
1924
+ description: "The agent is actively executing; pause for review, interrupt with steering, or stop the run."
1925
+ },
1926
+ paused: {
1927
+ label: "Paused",
1928
+ severity: "warning",
1929
+ description: "Execution is held. Resume when the run can continue or stop it to cancel remaining work."
1930
+ },
1931
+ stopped: {
1932
+ label: "Stopped",
1933
+ severity: "neutral",
1934
+ description: "The run was stopped before completion. Retry to start a fresh attempt."
1935
+ },
1936
+ failed: {
1937
+ label: "Failed",
1938
+ severity: "danger",
1939
+ description: "The last run failed. Retry after reviewing the failure context."
1940
+ },
1941
+ completed: {
1942
+ label: "Completed",
1943
+ severity: "success",
1944
+ description: "The run completed. Retry only when a new pass is required."
1945
+ }
1946
+ };
1947
+ function AgentRunControls({
1948
+ state,
1949
+ onPause,
1950
+ onResume,
1951
+ onStop,
1952
+ onRetry,
1953
+ onInterrupt,
1954
+ className,
1955
+ style,
1956
+ "aria-label": ariaLabel,
1957
+ "aria-describedby": ariaDescribedBy,
1958
+ ...props
1959
+ }) {
1960
+ const [interrupting, setInterrupting] = React9.useState(false);
1961
+ const [reason, setReason] = React9.useState("");
1962
+ const descriptionId = React9.useId();
1963
+ const meta = stateMeta[state];
1964
+ const canInterrupt = Boolean((state === "running" || state === "paused") && onInterrupt);
1965
+ React9.useEffect(() => {
1966
+ if (!canInterrupt && interrupting) {
1967
+ setInterrupting(false);
1968
+ setReason("");
1969
+ }
1970
+ }, [canInterrupt, interrupting]);
1971
+ const actions = React9.useMemo(() => {
1972
+ const next = [];
1973
+ if (state === "running") {
1974
+ next.push({
1975
+ id: "pause",
1976
+ label: "Pause",
1977
+ intent: "secondary",
1978
+ disabled: !onPause,
1979
+ icon: /* @__PURE__ */ jsx15(PauseIcon, { size: 16 }),
1980
+ onSelect: onPause
1981
+ });
1982
+ }
1983
+ if (state === "paused") {
1984
+ next.push({
1985
+ id: "resume",
1986
+ label: "Resume",
1987
+ intent: "primary",
1988
+ disabled: !onResume,
1989
+ icon: /* @__PURE__ */ jsx15(PlayIcon, { size: 16 }),
1990
+ onSelect: onResume
1991
+ });
1992
+ }
1993
+ if ((state === "running" || state === "paused") && onInterrupt) {
1994
+ next.push({
1995
+ id: "interrupt",
1996
+ label: "Interrupt",
1997
+ intent: "tertiary",
1998
+ disabled: false,
1999
+ icon: /* @__PURE__ */ jsx15(InterruptIcon, { size: 16 }),
2000
+ onSelect: () => setInterrupting(true)
2001
+ });
2002
+ }
2003
+ if (state === "running" || state === "paused") {
2004
+ next.push({
2005
+ id: "stop",
2006
+ label: "Stop",
2007
+ intent: "danger",
2008
+ disabled: !onStop,
2009
+ icon: /* @__PURE__ */ jsx15(StopIcon, { size: 16 }),
2010
+ onSelect: onStop
2011
+ });
2012
+ }
2013
+ if (state === "failed" || state === "stopped" || state === "completed") {
2014
+ next.push({
2015
+ id: "retry",
2016
+ label: "Retry",
2017
+ intent: state === "completed" ? "secondary" : "primary",
2018
+ disabled: !onRetry,
2019
+ icon: /* @__PURE__ */ jsx15(RetryIcon, { size: 16 }),
2020
+ onSelect: onRetry
2021
+ });
2022
+ }
2023
+ return next;
2024
+ }, [onInterrupt, onPause, onResume, onRetry, onStop, state]);
2025
+ const describedBy = ariaDescribedBy ? `${ariaDescribedBy} ${descriptionId}` : descriptionId;
2026
+ const sendInterrupt = () => {
2027
+ const trimmedReason = reason.trim();
2028
+ if (!trimmedReason) return;
2029
+ onInterrupt?.(trimmedReason);
2030
+ setReason("");
2031
+ setInterrupting(false);
2032
+ };
2033
+ return /* @__PURE__ */ jsxs15(
2034
+ "section",
2035
+ {
2036
+ ...props,
2037
+ "aria-label": ariaLabel ?? `${meta.label} agent run controls`,
2038
+ "aria-describedby": describedBy,
2039
+ className: clsx15("eth-agent-run-controls", className),
2040
+ "data-eth-component": "AgentRunControls",
2041
+ "data-state": state,
2042
+ style,
2043
+ children: [
2044
+ /* @__PURE__ */ jsxs15("div", { className: "eth-agent-run-controls__summary", children: [
2045
+ /* @__PURE__ */ jsxs15("div", { className: "eth-agent-run-controls__heading", children: [
2046
+ /* @__PURE__ */ jsx15("span", { className: "eth-agent-run-controls__state-dot", "aria-hidden": "true" }),
2047
+ /* @__PURE__ */ jsx15("span", { className: "eth-agent-run-controls__title", children: "Agent run" }),
2048
+ /* @__PURE__ */ jsx15(Badge8, { severity: meta.severity, children: meta.label })
2049
+ ] }),
2050
+ /* @__PURE__ */ jsx15("p", { id: descriptionId, className: "eth-agent-run-controls__description", children: meta.description })
2051
+ ] }),
2052
+ /* @__PURE__ */ jsx15(
2053
+ "div",
2054
+ {
2055
+ className: "eth-agent-run-controls__actions",
2056
+ role: "group",
2057
+ "aria-label": `${meta.label} run controls`,
2058
+ children: actions.map((action) => /* @__PURE__ */ jsx15(
2059
+ Button5,
2060
+ {
2061
+ density: "compact",
2062
+ intent: action.intent,
2063
+ disabled: action.disabled,
2064
+ icon: action.icon,
2065
+ onClick: action.onSelect,
2066
+ children: action.label
2067
+ },
2068
+ action.id
2069
+ ))
2070
+ }
2071
+ ),
2072
+ interrupting ? /* @__PURE__ */ jsxs15("div", { className: "eth-agent-run-controls__interrupt", children: [
2073
+ /* @__PURE__ */ jsx15(InlineNotification2, { severity: "warning", title: "Interrupt run", children: "Send steering instructions before the agent continues." }),
2074
+ /* @__PURE__ */ jsx15(
2075
+ Textarea3,
2076
+ {
2077
+ "aria-label": "Interrupt reason",
2078
+ rows: 3,
2079
+ value: reason,
2080
+ onChange: (event) => setReason(event.currentTarget.value)
2081
+ }
2082
+ ),
2083
+ /* @__PURE__ */ jsxs15("div", { className: "eth-agent-run-controls__interrupt-actions", children: [
2084
+ /* @__PURE__ */ jsx15(
2085
+ Button5,
2086
+ {
2087
+ density: "compact",
2088
+ intent: "primary",
2089
+ disabled: !reason.trim(),
2090
+ onClick: sendInterrupt,
2091
+ children: "Send interrupt"
2092
+ }
2093
+ ),
2094
+ /* @__PURE__ */ jsx15(Button5, { density: "compact", intent: "ghost", onClick: () => setInterrupting(false), children: "Cancel" })
2095
+ ] })
2096
+ ] }) : null
2097
+ ]
2098
+ }
2099
+ );
2100
+ }
2101
+
2102
+ // src/components/AgentSafetyPanel.tsx
2103
+ import clsx16 from "clsx";
2104
+ import { Badge as Badge9, EmptyState as EmptyState6, Surface as Surface11 } from "@echothink-ui/core";
2105
+ import { jsx as jsx16, jsxs as jsxs16 } from "react/jsx-runtime";
2106
+ function AgentSafetyPanel({
2107
+ checks,
2108
+ title = "Safety checks",
2109
+ subtitle,
2110
+ className,
2111
+ ...props
2112
+ }) {
2113
+ const summary = summarizeChecks(checks);
2114
+ return /* @__PURE__ */ jsx16(
2115
+ Surface11,
2116
+ {
2117
+ ...props,
2118
+ className: clsx16("eth-agent-safety-panel", className),
2119
+ "data-eth-component": "AgentSafetyPanel",
2120
+ subtitle: subtitle ?? summaryLabel(summary),
2121
+ title,
2122
+ children: !checks.length ? /* @__PURE__ */ jsx16(EmptyState6, { title: "No safety checks", description: "No policy gates are attached to this run." }) : /* @__PURE__ */ jsxs16("div", { className: "eth-agent-safety-panel__body", children: [
2123
+ /* @__PURE__ */ jsxs16("dl", { className: "eth-agent-safety-panel__summary", "aria-label": "Safety check summary", children: [
2124
+ /* @__PURE__ */ jsxs16("div", { className: "eth-agent-safety-panel__summary-item", children: [
2125
+ /* @__PURE__ */ jsx16("dt", { children: "Total" }),
2126
+ /* @__PURE__ */ jsx16("dd", { children: summary.total })
2127
+ ] }),
2128
+ /* @__PURE__ */ jsxs16("div", { className: "eth-agent-safety-panel__summary-item eth-agent-safety-panel__summary-item--pass", children: [
2129
+ /* @__PURE__ */ jsx16("dt", { children: "Passed" }),
2130
+ /* @__PURE__ */ jsx16("dd", { children: summary.pass })
2131
+ ] }),
2132
+ /* @__PURE__ */ jsxs16("div", { className: "eth-agent-safety-panel__summary-item eth-agent-safety-panel__summary-item--warn", children: [
2133
+ /* @__PURE__ */ jsx16("dt", { children: "Review" }),
2134
+ /* @__PURE__ */ jsx16("dd", { children: summary.warn })
2135
+ ] }),
2136
+ /* @__PURE__ */ jsxs16("div", { className: "eth-agent-safety-panel__summary-item eth-agent-safety-panel__summary-item--fail", children: [
2137
+ /* @__PURE__ */ jsx16("dt", { children: "Blocked" }),
2138
+ /* @__PURE__ */ jsx16("dd", { children: summary.fail })
2139
+ ] })
2140
+ ] }),
2141
+ /* @__PURE__ */ jsx16("div", { className: "eth-agent-safety-panel__list", role: "list", children: checks.map((check) => /* @__PURE__ */ jsxs16(
2142
+ "article",
2143
+ {
2144
+ className: clsx16(
2145
+ "eth-agent-safety-panel__check",
2146
+ `eth-agent-safety-panel__check--${check.status}`
2147
+ ),
2148
+ role: "listitem",
2149
+ children: [
2150
+ /* @__PURE__ */ jsx16("span", { className: "eth-agent-safety-panel__indicator", "aria-hidden": "true" }),
2151
+ /* @__PURE__ */ jsxs16("div", { className: "eth-agent-safety-panel__check-content", children: [
2152
+ /* @__PURE__ */ jsxs16("div", { className: "eth-agent-safety-panel__check-main", children: [
2153
+ /* @__PURE__ */ jsx16("h3", { children: check.label }),
2154
+ /* @__PURE__ */ jsx16(Badge9, { severity: safetySeverity(check), children: statusLabel7(check.status) })
2155
+ ] }),
2156
+ /* @__PURE__ */ jsx16("p", { children: check.details ?? statusDescription(check.status) })
2157
+ ] })
2158
+ ]
2159
+ },
2160
+ check.id
2161
+ )) })
2162
+ ] })
2163
+ }
2164
+ );
2165
+ }
2166
+ function summarizeChecks(checks) {
2167
+ return checks.reduce(
2168
+ (summary, check) => {
2169
+ summary.total += 1;
2170
+ summary[check.status] += 1;
2171
+ return summary;
2172
+ },
2173
+ { fail: 0, pass: 0, total: 0, warn: 0 }
2174
+ );
2175
+ }
2176
+ function summaryLabel(summary) {
2177
+ if (summary.total === 0) return "No policy gates are active.";
2178
+ if (summary.fail > 0) return `${summary.fail} blocking ${plural("issue", summary.fail)} found.`;
2179
+ if (summary.warn > 0) {
2180
+ return summary.warn === 1 ? "1 check needs review." : `${summary.warn} checks need review.`;
2181
+ }
2182
+ return "All policy checks passed.";
2183
+ }
2184
+ function statusLabel7(status) {
2185
+ if (status === "pass") return "Passed";
2186
+ if (status === "warn") return "Review needed";
2187
+ return "Blocked";
2188
+ }
2189
+ function statusDescription(status) {
2190
+ if (status === "pass") return "No policy issue detected.";
2191
+ if (status === "warn") return "Review recommended before proceeding.";
2192
+ return "Policy gate blocked this action.";
2193
+ }
2194
+ function plural(label, count) {
2195
+ return count === 1 ? label : `${label}s`;
2196
+ }
2197
+
2198
+ // src/components/AgentInterruptionPanel.tsx
2199
+ import clsx17 from "clsx";
2200
+ import { Button as Button6, InlineNotification as InlineNotification3, Surface as Surface12, Textarea as Textarea4 } from "@echothink-ui/core";
2201
+ import { InterruptIcon as InterruptIcon2 } from "@echothink-ui/icons";
2202
+ import { jsx as jsx17, jsxs as jsxs17 } from "react/jsx-runtime";
2203
+ var defaultMetadata = [
2204
+ { label: "Mode", value: "Steering interrupt" },
2205
+ { label: "Delivery", value: "Before next agent step" }
2206
+ ];
2207
+ function AgentInterruptionPanel({
2208
+ prompt,
2209
+ onChange,
2210
+ onSubmit,
2211
+ disabled,
2212
+ title = "Interrupt agent",
2213
+ subtitle = "Send operator guidance before the agent continues.",
2214
+ metadata = defaultMetadata,
2215
+ promptLabel = "Steering instruction",
2216
+ helperText = "Delivered before the next agent step.",
2217
+ placeholder = "Tell the agent what to change, stop, or prioritize.",
2218
+ submitLabel = "Send interruption",
2219
+ className,
2220
+ ...props
2221
+ }) {
2222
+ const hasPrompt = Boolean(prompt.trim());
2223
+ const submit = () => {
2224
+ if (!disabled && hasPrompt) onSubmit?.(prompt);
2225
+ };
2226
+ return /* @__PURE__ */ jsx17(
2227
+ Surface12,
2228
+ {
2229
+ ...props,
2230
+ className: clsx17("eth-agent-interruption-panel", className),
2231
+ "data-eth-component": "AgentInterruptionPanel",
2232
+ metadata,
2233
+ subtitle,
2234
+ title,
2235
+ children: /* @__PURE__ */ jsxs17("div", { className: "eth-agent-interruption-panel__body", children: [
2236
+ /* @__PURE__ */ jsx17(InlineNotification3, { severity: "warning", title: "Steering interrupt", children: "The agent will receive this instruction before continuing the current run." }),
2237
+ /* @__PURE__ */ jsx17(
2238
+ Textarea4,
2239
+ {
2240
+ className: "eth-agent-interruption-panel__prompt",
2241
+ disabled,
2242
+ helperText,
2243
+ labelText: promptLabel,
2244
+ placeholder,
2245
+ rows: 4,
2246
+ value: prompt,
2247
+ onChange: (event) => onChange(event.currentTarget.value),
2248
+ onKeyDown: (event) => {
2249
+ if ((event.metaKey || event.ctrlKey) && event.key === "Enter") {
2250
+ event.preventDefault();
2251
+ submit();
2252
+ }
2253
+ }
2254
+ }
2255
+ ),
2256
+ /* @__PURE__ */ jsx17("div", { className: "eth-agent-interruption-panel__actions", children: /* @__PURE__ */ jsx17(
2257
+ Button6,
2258
+ {
2259
+ disabled: disabled || !hasPrompt,
2260
+ icon: /* @__PURE__ */ jsx17(InterruptIcon2, { size: 16 }),
2261
+ onClick: submit,
2262
+ children: submitLabel
2263
+ }
2264
+ ) })
2265
+ ] })
2266
+ }
2267
+ );
2268
+ }
2269
+
2270
+ // src/components/AgentHandoffPanel.tsx
2271
+ import * as React10 from "react";
2272
+ import clsx18 from "clsx";
2273
+ import {
2274
+ Badge as Badge10,
2275
+ Button as Button7,
2276
+ EmptyState as EmptyState7,
2277
+ FormField,
2278
+ StatusDot as StatusDot6,
2279
+ Surface as Surface13,
2280
+ Textarea as Textarea5
2281
+ } from "@echothink-ui/core";
2282
+ import { jsx as jsx18, jsxs as jsxs18 } from "react/jsx-runtime";
2283
+ function AgentHandoffPanel({
2284
+ itemRef,
2285
+ agentRef,
2286
+ assigneeOptions = [],
2287
+ selectedAssigneeId,
2288
+ reason,
2289
+ reasonSchema,
2290
+ disabled,
2291
+ onAssigneeChange,
2292
+ onReasonChange,
2293
+ onSubmit,
2294
+ title = "Agent handoff",
2295
+ className,
2296
+ ...props
2297
+ }) {
2298
+ const [internalAssigneeId, setInternalAssigneeId] = React10.useState(selectedAssigneeId);
2299
+ const [internalReason, setInternalReason] = React10.useState(reason ?? "");
2300
+ const assigneeId = selectedAssigneeId ?? internalAssigneeId;
2301
+ const handoffReason = reason ?? internalReason;
2302
+ const reasonRequired = reasonSchema?.required ?? true;
2303
+ const canSubmit = Boolean(assigneeId) && (!reasonRequired || Boolean(handoffReason.trim()));
2304
+ const selectAssignee = (id) => {
2305
+ setInternalAssigneeId(id);
2306
+ onAssigneeChange?.(id);
2307
+ };
2308
+ const changeReason = (value) => {
2309
+ setInternalReason(value);
2310
+ onReasonChange?.(value);
2311
+ };
2312
+ const reasonId = React10.useId();
2313
+ return /* @__PURE__ */ jsx18(
2314
+ Surface13,
2315
+ {
2316
+ ...props,
2317
+ className: clsx18("eth-agent-handoff-panel", className),
2318
+ "data-eth-component": "AgentHandoffPanel",
2319
+ title,
2320
+ subtitle: [agentRef, itemRef].filter(Boolean).join(" \xB7 ") || void 0,
2321
+ children: /* @__PURE__ */ jsxs18("div", { className: "eth-agent-handoff-panel__body", children: [
2322
+ !assigneeOptions.length ? /* @__PURE__ */ jsx18(EmptyState7, { title: "No handoff targets" }) : /* @__PURE__ */ jsx18(
2323
+ "div",
2324
+ {
2325
+ className: "eth-agent-handoff-panel__target-list",
2326
+ role: "listbox",
2327
+ "aria-label": "Handoff targets",
2328
+ children: assigneeOptions.map((target) => /* @__PURE__ */ jsx18(
2329
+ "button",
2330
+ {
2331
+ type: "button",
2332
+ role: "option",
2333
+ "aria-selected": assigneeId === target.id,
2334
+ className: clsx18(
2335
+ "eth-agent-handoff-panel__target",
2336
+ assigneeId === target.id && "eth-agent-handoff-panel__target--selected"
2337
+ ),
2338
+ disabled,
2339
+ onClick: () => selectAssignee(target.id),
2340
+ children: /* @__PURE__ */ jsxs18("span", { className: "eth-agent-handoff-panel__target-main", children: [
2341
+ /* @__PURE__ */ jsxs18("span", { className: "eth-agent-handoff-panel__target-copy", children: [
2342
+ /* @__PURE__ */ jsx18("strong", { className: "eth-agent-handoff-panel__target-label", children: target.label }),
2343
+ target.description ? /* @__PURE__ */ jsx18("span", { className: "eth-agent-handoff-panel__target-description", children: target.description }) : null
2344
+ ] }),
2345
+ /* @__PURE__ */ jsxs18("span", { className: "eth-agent-handoff-panel__target-meta", children: [
2346
+ /* @__PURE__ */ jsx18(Badge10, { severity: "neutral", children: target.type }),
2347
+ target.status ? /* @__PURE__ */ jsx18(
2348
+ StatusDot6,
2349
+ {
2350
+ status: target.status,
2351
+ label: formatHandoffStatus(target.status)
2352
+ }
2353
+ ) : null
2354
+ ] })
2355
+ ] })
2356
+ },
2357
+ target.id
2358
+ ))
2359
+ }
2360
+ ),
2361
+ /* @__PURE__ */ jsx18(
2362
+ FormField,
2363
+ {
2364
+ id: reasonId,
2365
+ label: reasonSchema?.label ?? "Handoff reason",
2366
+ required: reasonRequired,
2367
+ children: /* @__PURE__ */ jsx18(
2368
+ Textarea5,
2369
+ {
2370
+ className: "eth-agent-handoff-panel__reason",
2371
+ disabled,
2372
+ placeholder: reasonSchema?.placeholder ?? "Explain what the next owner should do.",
2373
+ required: reasonRequired,
2374
+ rows: 3,
2375
+ value: handoffReason,
2376
+ onChange: (event) => changeReason(event.currentTarget.value)
2377
+ }
2378
+ )
2379
+ }
2380
+ ),
2381
+ /* @__PURE__ */ jsx18("div", { className: "eth-agent-handoff-panel__actions", children: /* @__PURE__ */ jsx18(
2382
+ Button7,
2383
+ {
2384
+ disabled: disabled || !canSubmit,
2385
+ onClick: () => onSubmit?.({ assigneeId, reason: handoffReason }),
2386
+ children: "Handoff"
2387
+ }
2388
+ ) })
2389
+ ] })
2390
+ }
2391
+ );
2392
+ }
2393
+ function formatHandoffStatus(status) {
2394
+ return status ? status.split("-").map((word) => word.charAt(0).toUpperCase() + word.slice(1)).join(" ") : void 0;
2395
+ }
2396
+
2397
+ // src/components/AgentGeneratedArtifactPanel.tsx
2398
+ import * as React11 from "react";
2399
+ import clsx19 from "clsx";
2400
+ import { Drawer as Drawer2, EmptyState as EmptyState8, LinkButton, Surface as Surface14 } from "@echothink-ui/core";
2401
+ import { Fragment as Fragment6, jsx as jsx19, jsxs as jsxs19 } from "react/jsx-runtime";
2402
+ function AgentGeneratedArtifactPanel({
2403
+ artifacts,
2404
+ onSelect,
2405
+ selectedId,
2406
+ density,
2407
+ title = "Generated artifacts",
2408
+ className,
2409
+ ...props
2410
+ }) {
2411
+ const [internalSelectedId, setInternalSelectedId] = React11.useState(
2412
+ selectedId ?? artifacts[0]?.id
2413
+ );
2414
+ const [previewOpen, setPreviewOpen] = React11.useState(false);
2415
+ const selectedArtifact = artifacts.find((artifact) => artifact.id === (selectedId ?? internalSelectedId)) ?? artifacts[0];
2416
+ const compact = density === "compact";
2417
+ const selectArtifact = (artifact) => {
2418
+ setInternalSelectedId(artifact.id);
2419
+ setPreviewOpen(true);
2420
+ onSelect?.(artifact);
2421
+ };
2422
+ return /* @__PURE__ */ jsxs19(Fragment6, { children: [
2423
+ /* @__PURE__ */ jsx19(
2424
+ Surface14,
2425
+ {
2426
+ ...props,
2427
+ density,
2428
+ className: clsx19("eth-agent-generated-artifact-panel", className),
2429
+ "data-eth-component": "AgentGeneratedArtifactPanel",
2430
+ title,
2431
+ children: !artifacts.length ? /* @__PURE__ */ jsx19(EmptyState8, { title: "No artifacts generated" }) : /* @__PURE__ */ jsxs19(
2432
+ "div",
2433
+ {
2434
+ className: "eth-agent-generated-artifact-panel__layout",
2435
+ style: {
2436
+ gridTemplateColumns: compact ? "1fr" : "minmax(220px, 320px) minmax(0, 1fr)"
2437
+ },
2438
+ children: [
2439
+ /* @__PURE__ */ jsx19(
2440
+ ArtifactList,
2441
+ {
2442
+ artifacts,
2443
+ selectedId: selectedArtifact?.id,
2444
+ onSelect: selectArtifact
2445
+ }
2446
+ ),
2447
+ !compact ? /* @__PURE__ */ jsx19(ArtifactPreview, { artifact: selectedArtifact }) : null
2448
+ ]
2449
+ }
2450
+ )
2451
+ }
2452
+ ),
2453
+ compact ? /* @__PURE__ */ jsx19(
2454
+ Drawer2,
2455
+ {
2456
+ open: previewOpen && Boolean(selectedArtifact),
2457
+ title: selectedArtifact?.label ?? "Artifact preview",
2458
+ onClose: () => setPreviewOpen(false),
2459
+ children: /* @__PURE__ */ jsx19(ArtifactPreview, { artifact: selectedArtifact })
2460
+ }
2461
+ ) : null
2462
+ ] });
2463
+ }
2464
+ function ArtifactList({
2465
+ artifacts,
2466
+ selectedId,
2467
+ onSelect
2468
+ }) {
2469
+ return /* @__PURE__ */ jsx19(
2470
+ "div",
2471
+ {
2472
+ className: "eth-agent-generated-artifact-panel__list",
2473
+ role: "group",
2474
+ "aria-label": "Generated artifacts",
2475
+ children: artifacts.map((artifact) => {
2476
+ const selected = selectedId === artifact.id;
2477
+ return /* @__PURE__ */ jsxs19(
2478
+ "button",
2479
+ {
2480
+ type: "button",
2481
+ "aria-pressed": selected,
2482
+ className: clsx19(
2483
+ "eth-agent-generated-artifact-panel__item",
2484
+ selected && "eth-agent-generated-artifact-panel__item--selected"
2485
+ ),
2486
+ onClick: () => onSelect(artifact),
2487
+ children: [
2488
+ /* @__PURE__ */ jsxs19("span", { className: "eth-agent-generated-artifact-panel__item-topline", children: [
2489
+ /* @__PURE__ */ jsx19("span", { className: "eth-agent-generated-artifact-panel__item-title", children: artifact.label }),
2490
+ /* @__PURE__ */ jsx19("span", { className: "eth-agent-generated-artifact-panel__kind", children: artifactKindLabel(artifact.kind) })
2491
+ ] }),
2492
+ /* @__PURE__ */ jsx19("span", { className: "eth-agent-generated-artifact-panel__item-meta", children: artifactMeta(artifact).join(" \xB7 ") }),
2493
+ /* @__PURE__ */ jsx19("span", { className: "eth-agent-generated-artifact-panel__item-status", children: artifactPreviewStatus(artifact) })
2494
+ ]
2495
+ },
2496
+ artifact.id
2497
+ );
2498
+ })
2499
+ }
2500
+ );
2501
+ }
2502
+ function ArtifactPreview({ artifact }) {
2503
+ const headingId = React11.useId();
2504
+ if (!artifact) return /* @__PURE__ */ jsx19(EmptyState8, { title: "Select an artifact" });
2505
+ return /* @__PURE__ */ jsxs19("section", { className: "eth-agent-generated-artifact-panel__preview", "aria-labelledby": headingId, children: [
2506
+ /* @__PURE__ */ jsxs19("header", { className: "eth-agent-generated-artifact-panel__preview-header", children: [
2507
+ /* @__PURE__ */ jsxs19("div", { className: "eth-agent-generated-artifact-panel__preview-heading", children: [
2508
+ /* @__PURE__ */ jsx19("h3", { id: headingId, children: artifact.label }),
2509
+ /* @__PURE__ */ jsxs19("div", { className: "eth-agent-generated-artifact-panel__preview-meta", children: [
2510
+ artifactMeta(artifact).map((item) => /* @__PURE__ */ jsx19("span", { children: item }, item)),
2511
+ artifact.mimeType ? /* @__PURE__ */ jsx19("span", { children: artifact.mimeType }) : null
2512
+ ] })
2513
+ ] }),
2514
+ artifact.href ? /* @__PURE__ */ jsx19(LinkButton, { href: artifact.href, density: "compact", intent: "secondary", children: "Open" }) : null
2515
+ ] }),
2516
+ /* @__PURE__ */ jsx19("div", { className: "eth-agent-generated-artifact-panel__preview-body", children: /* @__PURE__ */ jsx19(ArtifactPreviewBody, { artifact }) })
2517
+ ] });
2518
+ }
2519
+ function ArtifactPreviewBody({ artifact }) {
2520
+ const content = artifact.content?.trim();
2521
+ if (artifact.kind === "image" && artifact.previewUrl) {
2522
+ return /* @__PURE__ */ jsx19("img", { alt: artifact.label, src: artifact.previewUrl });
2523
+ }
2524
+ if (artifact.kind === "code" && content) {
2525
+ return /* @__PURE__ */ jsx19("pre", { children: /* @__PURE__ */ jsx19("code", { children: content }) });
2526
+ }
2527
+ if (artifact.previewUrl) {
2528
+ return /* @__PURE__ */ jsx19("iframe", { title: artifact.label, src: artifact.previewUrl });
2529
+ }
2530
+ if (content) {
2531
+ return /* @__PURE__ */ jsx19("div", { className: "eth-agent-generated-artifact-panel__text-preview", children: content });
2532
+ }
2533
+ return /* @__PURE__ */ jsxs19("div", { className: "eth-agent-generated-artifact-panel__empty-preview", role: "status", children: [
2534
+ /* @__PURE__ */ jsx19("p", { className: "eth-agent-generated-artifact-panel__empty-title", children: "Preview unavailable" }),
2535
+ /* @__PURE__ */ jsx19("p", { className: "eth-agent-generated-artifact-panel__empty-description", children: artifact.href ? "Open the artifact to inspect the generated output." : "Artifact saved without an inline preview." })
2536
+ ] });
2537
+ }
2538
+ function artifactMeta(artifact) {
2539
+ return [artifact.size, formatDateTime(artifact.createdAt)].filter(
2540
+ (item) => Boolean(item)
2541
+ );
2542
+ }
2543
+ function artifactKindLabel(kind) {
2544
+ switch (kind) {
2545
+ case "chart":
2546
+ return "Chart";
2547
+ case "code":
2548
+ return "Code";
2549
+ case "doc":
2550
+ return "Doc";
2551
+ case "file":
2552
+ return "File";
2553
+ case "image":
2554
+ return "Image";
2555
+ }
2556
+ }
2557
+ function artifactPreviewStatus(artifact) {
2558
+ if (artifact.kind === "image" && artifact.previewUrl) return "Inline image preview";
2559
+ if (artifact.kind === "code" && artifact.content?.trim()) return "Inline code preview";
2560
+ if (artifact.previewUrl) return "Embedded preview";
2561
+ if (artifact.content?.trim()) return "Inline text preview";
2562
+ if (artifact.href) return "Open externally";
2563
+ return "No inline preview";
2564
+ }
2565
+
2566
+ // src/components/AppDomainAgentPanel.tsx
2567
+ import { jsx as jsx20, jsxs as jsxs20 } from "react/jsx-runtime";
2568
+ function AppDomainAgentPanel({
2569
+ appDomainRef,
2570
+ agentRef,
2571
+ projectRef,
2572
+ messages = [],
2573
+ state,
2574
+ prompt = "",
2575
+ onPromptChange,
2576
+ onSubmit,
2577
+ attachments,
2578
+ onAttachmentRemove,
2579
+ runControls,
2580
+ children,
2581
+ ...props
2582
+ }) {
2583
+ return /* @__PURE__ */ jsx20(
2584
+ ChatAgentRail,
2585
+ {
2586
+ ...props,
2587
+ agentRef,
2588
+ projectRef,
2589
+ messages,
2590
+ state,
2591
+ prompt,
2592
+ onPromptChange: onPromptChange ?? (() => void 0),
2593
+ onSubmit,
2594
+ attachments,
2595
+ onAttachmentRemove,
2596
+ runControls,
2597
+ scopeLabel: appDomainRef,
2598
+ header: /* @__PURE__ */ jsxs20("div", { className: "eth-agent-app-domain-panel__header", children: [
2599
+ /* @__PURE__ */ jsx20("p", { className: "eth-agent-app-domain-panel__eyebrow", children: "App domain" }),
2600
+ /* @__PURE__ */ jsx20("h2", { className: "eth-agent-app-domain-panel__title", children: appDomainRef }),
2601
+ agentRef || projectRef ? /* @__PURE__ */ jsxs20("div", { className: "eth-agent-app-domain-panel__meta", "aria-label": "Agent panel scope", children: [
2602
+ agentRef ? /* @__PURE__ */ jsxs20("span", { children: [
2603
+ "Agent ",
2604
+ agentRef
2605
+ ] }) : null,
2606
+ projectRef ? /* @__PURE__ */ jsxs20("span", { children: [
2607
+ "Project ",
2608
+ projectRef
2609
+ ] }) : null
2610
+ ] }) : null,
2611
+ children ? /* @__PURE__ */ jsx20("div", { className: "eth-agent-app-domain-panel__slot", children }) : null
2612
+ ] }),
2613
+ "data-eth-component": "AppDomainAgentPanel"
2614
+ }
2615
+ );
2616
+ }
2617
+
2618
+ // src/index.tsx
2619
+ var AgentComponentNames = [
2620
+ "LeftAgentRail",
2621
+ "ChatAgentRail",
2622
+ "AgentMessageList",
2623
+ "AgentPromptBox",
2624
+ "ScopeAttachmentPanel",
2625
+ "AgentStateBadge",
2626
+ "AgentThinkingPanel",
2627
+ "AgentThinkingChain",
2628
+ "AgentTraceViewer",
2629
+ "AgentToolCallLog",
2630
+ "AgentApprovalGate",
2631
+ "AgentPlanPreview",
2632
+ "AgentPlanDiff",
2633
+ "AgentMemoryPanel",
2634
+ "AgentContextViewer",
2635
+ "AgentRunControls",
2636
+ "AgentSafetyPanel",
2637
+ "AgentInterruptionPanel",
2638
+ "AgentHandoffPanel",
2639
+ "AgentGeneratedArtifactPanel",
2640
+ "AppDomainAgentPanel"
2641
+ ];
2642
+ export {
2643
+ AgentApprovalGate,
2644
+ AgentComponentNames,
2645
+ AgentContextViewer,
2646
+ AgentGeneratedArtifactPanel,
2647
+ AgentHandoffPanel,
2648
+ AgentInterruptionPanel,
2649
+ AgentMemoryPanel,
2650
+ AgentMessageList,
2651
+ AgentPlanDiff,
2652
+ AgentPlanPreview,
2653
+ AgentPromptBox,
2654
+ AgentRunControls,
2655
+ AgentSafetyPanel,
2656
+ AgentStateBadge,
2657
+ AgentThinkingChain,
2658
+ AgentThinkingPanel,
2659
+ AgentToolCallLog,
2660
+ AgentTraceViewer,
2661
+ AppDomainAgentPanel,
2662
+ ChatAgentRail,
2663
+ LeftAgentRail,
2664
+ ScopeAttachmentPanel
2665
+ };
2666
+ //# sourceMappingURL=index.js.map