@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
@@ -0,0 +1,212 @@
1
+ import { fireEvent, render, screen } from "@testing-library/react";
2
+ import { describe, expect, it, vi } from "vitest";
3
+ import {
4
+ AgentMemoryPanel,
5
+ AgentPlanDiff,
6
+ AgentPromptBox,
7
+ ScopeAttachmentPanel,
8
+ AgentToolCallLog,
9
+ LeftAgentRail
10
+ } from "./index";
11
+
12
+ globalThis.ResizeObserver ??= vi.fn(() => ({
13
+ disconnect: vi.fn(),
14
+ observe: vi.fn(),
15
+ unobserve: vi.fn()
16
+ })) as unknown as typeof ResizeObserver;
17
+
18
+ describe("@echothink-ui/agent AgentPromptBox", () => {
19
+ it("renders prompt context and submits entered text", () => {
20
+ const onSubmit = vi.fn();
21
+
22
+ render(
23
+ <AgentPromptBox
24
+ value="Draft a reply"
25
+ onChange={vi.fn()}
26
+ onSubmit={onSubmit}
27
+ scopeLabel="Marketing drafts"
28
+ attachments={[{ id: "brief", label: "Q3 brief", kind: "document", status: "synced" }]}
29
+ />
30
+ );
31
+
32
+ expect(screen.getByText("Scope")).toBeTruthy();
33
+ expect(screen.getByText("Marketing drafts")).toBeTruthy();
34
+ expect(screen.getByText("Q3 brief")).toBeTruthy();
35
+
36
+ fireEvent.click(screen.getByRole("button", { name: "Submit prompt" }));
37
+ expect(onSubmit).toHaveBeenCalledWith("Draft a reply");
38
+ });
39
+
40
+ it("keeps attachment action disabled without a handler", () => {
41
+ render(<AgentPromptBox value="" onChange={vi.fn()} />);
42
+
43
+ expect(
44
+ screen.getByRole("button", { name: "Attach scope or file" }).hasAttribute("disabled")
45
+ ).toBe(true);
46
+ });
47
+ });
48
+
49
+ describe("@echothink-ui/agent LeftAgentRail", () => {
50
+ it("renders the left rail component contract", () => {
51
+ render(
52
+ <LeftAgentRail
53
+ messages={[]}
54
+ prompt=""
55
+ onPromptChange={vi.fn()}
56
+ aria-label="Workspace agent rail"
57
+ />
58
+ );
59
+
60
+ const rail = screen.getByLabelText("Workspace agent rail");
61
+ expect(rail.getAttribute("data-eth-component")).toBe("LeftAgentRail");
62
+ expect(rail.getAttribute("data-placement")).toBe("left");
63
+ expect(rail.className).toContain("eth-left-agent-rail");
64
+ });
65
+ });
66
+
67
+ describe("@echothink-ui/agent ScopeAttachmentPanel", () => {
68
+ it("renders attached context as a readable panel with removable items", () => {
69
+ const onRemove = vi.fn();
70
+
71
+ render(
72
+ <ScopeAttachmentPanel
73
+ attachments={[
74
+ { id: "brief", label: "Brief.md", kind: "document", status: "synced" },
75
+ { id: "project", label: "Marketing project", kind: "project", status: "active" },
76
+ { id: "cms", label: "CMS workspace", kind: "app-domain", status: "warning" }
77
+ ]}
78
+ onRemove={onRemove}
79
+ />
80
+ );
81
+
82
+ expect(screen.getByRole("heading", { name: "Attached context" })).toBeTruthy();
83
+ expect(screen.getByRole("list", { name: "Attached context items" })).toBeTruthy();
84
+ expect(screen.getByText("Brief.md")).toBeTruthy();
85
+ expect(screen.getByText("Source document")).toBeTruthy();
86
+ expect(screen.getByText("Synced")).toBeTruthy();
87
+ expect(screen.getByText("Warning")).toBeTruthy();
88
+
89
+ fireEvent.click(screen.getByRole("button", { name: "Remove Brief.md" }));
90
+
91
+ expect(onRemove).toHaveBeenCalledWith("brief");
92
+ });
93
+ });
94
+
95
+ describe("@echothink-ui/agent AgentMemoryPanel", () => {
96
+ it("renders grouped memory metadata and action callbacks", () => {
97
+ const onPin = vi.fn();
98
+ const onEdit = vi.fn();
99
+
100
+ render(
101
+ <AgentMemoryPanel
102
+ entries={[
103
+ {
104
+ id: "tone",
105
+ kind: "user",
106
+ key: "preferred-tone",
107
+ value: "Concise, direct",
108
+ pinned: true,
109
+ lastUpdatedAt: "2026-05-28T12:00:00Z"
110
+ },
111
+ {
112
+ id: "policy",
113
+ kind: "reference",
114
+ key: "source-policy",
115
+ value: "Use governance checklist"
116
+ }
117
+ ]}
118
+ onEdit={onEdit}
119
+ onPin={onPin}
120
+ />
121
+ );
122
+
123
+ expect(screen.getByText("User")).toBeTruthy();
124
+ expect(screen.getByText("Reference")).toBeTruthy();
125
+ expect(screen.getByText("preferred-tone")).toBeTruthy();
126
+ expect(screen.getAllByText("Pinned").length).toBeGreaterThan(0);
127
+
128
+ fireEvent.click(screen.getByRole("button", { name: "Unpin preferred-tone" }));
129
+ fireEvent.click(screen.getByRole("button", { name: "Edit source-policy" }));
130
+
131
+ expect(onPin).toHaveBeenCalledWith("tone");
132
+ expect(onEdit).toHaveBeenCalledWith("policy");
133
+ });
134
+ });
135
+
136
+ describe("@echothink-ui/agent AgentToolCallLog", () => {
137
+ it("renders readable tool call state and opens inspection details", () => {
138
+ const onSelect = vi.fn();
139
+
140
+ render(
141
+ <AgentToolCallLog
142
+ calls={[
143
+ {
144
+ id: "search",
145
+ toolName: "search.docs",
146
+ args: { q: "approval policy" },
147
+ result: { documents: 3 },
148
+ status: "completed",
149
+ startedAt: "10:40:01",
150
+ durationMs: 120
151
+ },
152
+ {
153
+ id: "send",
154
+ toolName: "send.email",
155
+ args: { to: "customer@example.com" },
156
+ result: { id: "msg_1" },
157
+ status: "approval-required",
158
+ startedAt: "10:40:05",
159
+ redacted: true
160
+ }
161
+ ]}
162
+ onSelect={onSelect}
163
+ />
164
+ );
165
+
166
+ expect(screen.getByText("Completed")).toBeTruthy();
167
+ expect(screen.getByText("Approval Required")).toBeTruthy();
168
+ expect(screen.getAllByText("Redacted").length).toBeGreaterThan(0);
169
+
170
+ fireEvent.click(screen.getByRole("button", { name: "Inspect search.docs tool call" }));
171
+
172
+ expect(onSelect).toHaveBeenCalledWith(expect.objectContaining({ id: "search" }));
173
+ expect(screen.getByText("Started")).toBeTruthy();
174
+ expect(screen.getAllByText("Duration").length).toBeGreaterThan(0);
175
+ expect(screen.getByText("Arguments")).toBeTruthy();
176
+ expect(screen.getAllByText("Result").length).toBeGreaterThan(0);
177
+ });
178
+ });
179
+
180
+ describe("@echothink-ui/agent AgentPlanDiff", () => {
181
+ it("renders plan changes in proposed execution order", () => {
182
+ render(
183
+ <AgentPlanDiff
184
+ before={[
185
+ { id: "1", description: "Draft reply", durationEstimate: "20s" },
186
+ { id: "2", description: "Send draft", risks: ["external send"] },
187
+ { id: "4", description: "Notify campaign owner" }
188
+ ]}
189
+ after={[
190
+ { id: "1", description: "Draft reply", durationEstimate: "20s" },
191
+ { id: "3", description: "Summarize for inspector", durationEstimate: "15s" },
192
+ { id: "2", description: "Send draft after human approval", risks: ["approval gate"] }
193
+ ]}
194
+ />
195
+ );
196
+
197
+ const changes = screen.getAllByRole("listitem");
198
+ expect(changes.length).toBe(4);
199
+ expect(changes[0]?.textContent).toContain("Step 1");
200
+ expect(changes[0]?.textContent).toContain("Unchanged");
201
+ expect(changes[1]?.textContent).toContain("Step 3");
202
+ expect(changes[1]?.textContent).toContain("Added");
203
+ expect(changes[2]?.textContent).toContain("Step 2");
204
+ expect(changes[2]?.textContent).toContain("Before");
205
+ expect(changes[2]?.textContent).toContain("After");
206
+ expect(changes[3]?.textContent).toContain("Step 4");
207
+ expect(changes[3]?.textContent).toContain("Removed");
208
+ expect(screen.getByLabelText("Plan diff summary").textContent).toBe(
209
+ "Added1Modified1Removed1Unchanged1"
210
+ );
211
+ });
212
+ });
package/src/index.tsx ADDED
@@ -0,0 +1,88 @@
1
+ import "./styles.css";
2
+
3
+ export { ChatAgentRail, LeftAgentRail } from "./components/ChatAgentRail";
4
+ export type { ChatAgentRailProps, LeftAgentRailProps } from "./components/ChatAgentRail";
5
+ export { AgentMessageList } from "./components/AgentMessageList";
6
+ export type { AgentMessageListProps } from "./components/AgentMessageList";
7
+ export { AgentPromptBox } from "./components/AgentPromptBox";
8
+ export type { AgentPromptBoxProps } from "./components/AgentPromptBox";
9
+ export { ScopeAttachmentPanel } from "./components/ScopeAttachmentPanel";
10
+ export type { ScopeAttachmentPanelProps } from "./components/ScopeAttachmentPanel";
11
+ export { AgentStateBadge } from "./components/AgentStateBadge";
12
+ export type { AgentStateBadgeProps } from "./components/AgentStateBadge";
13
+ export { AgentThinkingPanel } from "./components/AgentThinkingPanel";
14
+ export type { AgentThinkingPanelProps } from "./components/AgentThinkingPanel";
15
+ export { AgentThinkingChain } from "./components/AgentThinkingChain";
16
+ export type { AgentThinkingChainProps } from "./components/AgentThinkingChain";
17
+ export { AgentTraceViewer } from "./components/AgentTraceViewer";
18
+ export type { AgentTraceViewerProps } from "./components/AgentTraceViewer";
19
+ export { AgentToolCallLog } from "./components/AgentToolCallLog";
20
+ export type { AgentToolCallLogProps } from "./components/AgentToolCallLog";
21
+ export { AgentApprovalGate } from "./components/AgentApprovalGate";
22
+ export type { AgentApprovalGateProps } from "./components/AgentApprovalGate";
23
+ export { AgentPlanPreview } from "./components/AgentPlanPreview";
24
+ export type { AgentPlanPreviewProps } from "./components/AgentPlanPreview";
25
+ export { AgentPlanDiff } from "./components/AgentPlanDiff";
26
+ export type { AgentPlanDiffProps } from "./components/AgentPlanDiff";
27
+ export { AgentMemoryPanel } from "./components/AgentMemoryPanel";
28
+ export type { AgentMemoryPanelProps } from "./components/AgentMemoryPanel";
29
+ export { AgentContextViewer } from "./components/AgentContextViewer";
30
+ export type { AgentContextViewerProps } from "./components/AgentContextViewer";
31
+ export { AgentRunControls } from "./components/AgentRunControls";
32
+ export type { AgentRunControlsProps } from "./components/AgentRunControls";
33
+ export { AgentSafetyPanel } from "./components/AgentSafetyPanel";
34
+ export type { AgentSafetyPanelProps } from "./components/AgentSafetyPanel";
35
+ export { AgentInterruptionPanel } from "./components/AgentInterruptionPanel";
36
+ export type { AgentInterruptionPanelProps } from "./components/AgentInterruptionPanel";
37
+ export { AgentHandoffPanel } from "./components/AgentHandoffPanel";
38
+ export type { AgentHandoffPanelProps } from "./components/AgentHandoffPanel";
39
+ export { AgentGeneratedArtifactPanel } from "./components/AgentGeneratedArtifactPanel";
40
+ export type { AgentGeneratedArtifactPanelProps } from "./components/AgentGeneratedArtifactPanel";
41
+ export { AppDomainAgentPanel } from "./components/AppDomainAgentPanel";
42
+ export type { AppDomainAgentPanelProps } from "./components/AppDomainAgentPanel";
43
+
44
+ export type {
45
+ AgentApprovalAction,
46
+ AgentCitation,
47
+ AgentComponentSurfaceProps,
48
+ AgentContextSource,
49
+ AgentDiffItem,
50
+ AgentGeneratedArtifact,
51
+ AgentHandoffTarget,
52
+ AgentMemoryEntry,
53
+ AgentMessage,
54
+ AgentPlan,
55
+ AgentPlanStep,
56
+ AgentRunState,
57
+ AgentSafetyCheck,
58
+ AgentScopeAttachment,
59
+ AgentStep,
60
+ AgentToolCall,
61
+ AgentTraceSpan,
62
+ ChatAgentRailAttachment
63
+ } from "./types";
64
+
65
+ export const AgentComponentNames = [
66
+ "LeftAgentRail",
67
+ "ChatAgentRail",
68
+ "AgentMessageList",
69
+ "AgentPromptBox",
70
+ "ScopeAttachmentPanel",
71
+ "AgentStateBadge",
72
+ "AgentThinkingPanel",
73
+ "AgentThinkingChain",
74
+ "AgentTraceViewer",
75
+ "AgentToolCallLog",
76
+ "AgentApprovalGate",
77
+ "AgentPlanPreview",
78
+ "AgentPlanDiff",
79
+ "AgentMemoryPanel",
80
+ "AgentContextViewer",
81
+ "AgentRunControls",
82
+ "AgentSafetyPanel",
83
+ "AgentInterruptionPanel",
84
+ "AgentHandoffPanel",
85
+ "AgentGeneratedArtifactPanel",
86
+ "AppDomainAgentPanel"
87
+ ] as const;
88
+ export type AgentComponentName = (typeof AgentComponentNames)[number];