@steerable/agent-ui 0.2.3 → 0.2.5
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/cards/ActionSegmentCard.d.ts +18 -0
- package/dist/cards/ActionSegmentCard.d.ts.map +1 -0
- package/dist/cards/ActionSegmentCard.js +26 -0
- package/dist/cards/ActionSegmentCard.js.map +1 -0
- package/dist/cards/AnalysisDocumentCard.d.ts +33 -0
- package/dist/cards/AnalysisDocumentCard.d.ts.map +1 -0
- package/dist/cards/AnalysisDocumentCard.js +11 -0
- package/dist/cards/AnalysisDocumentCard.js.map +1 -0
- package/dist/cards/AskUserQuestionsCard.d.ts +43 -0
- package/dist/cards/AskUserQuestionsCard.d.ts.map +1 -0
- package/dist/cards/AskUserQuestionsCard.js +171 -0
- package/dist/cards/AskUserQuestionsCard.js.map +1 -0
- package/dist/cards/CoverageReportCard.d.ts +41 -0
- package/dist/cards/CoverageReportCard.d.ts.map +1 -0
- package/dist/cards/CoverageReportCard.js +55 -0
- package/dist/cards/CoverageReportCard.js.map +1 -0
- package/dist/cards/OrchestrationPlanCard.d.ts +60 -0
- package/dist/cards/OrchestrationPlanCard.d.ts.map +1 -0
- package/dist/cards/OrchestrationPlanCard.js +103 -0
- package/dist/cards/OrchestrationPlanCard.js.map +1 -0
- package/dist/cards/PlanSelectorCard.d.ts +40 -0
- package/dist/cards/PlanSelectorCard.d.ts.map +1 -0
- package/dist/cards/PlanSelectorCard.js +106 -0
- package/dist/cards/PlanSelectorCard.js.map +1 -0
- package/dist/cards/PlanStepsCard.d.ts +18 -0
- package/dist/cards/PlanStepsCard.d.ts.map +1 -0
- package/dist/cards/PlanStepsCard.js +25 -0
- package/dist/cards/PlanStepsCard.js.map +1 -0
- package/dist/cards/QuizCard.d.ts +44 -0
- package/dist/cards/QuizCard.d.ts.map +1 -0
- package/dist/cards/QuizCard.js +113 -0
- package/dist/cards/QuizCard.js.map +1 -0
- package/dist/cards/ResearchPlanCard.d.ts +23 -0
- package/dist/cards/ResearchPlanCard.d.ts.map +1 -0
- package/dist/cards/ResearchPlanCard.js +50 -0
- package/dist/cards/ResearchPlanCard.js.map +1 -0
- package/dist/cards/SearchSourcesCard.d.ts +29 -0
- package/dist/cards/SearchSourcesCard.d.ts.map +1 -0
- package/dist/cards/SearchSourcesCard.js +83 -0
- package/dist/cards/SearchSourcesCard.js.map +1 -0
- package/dist/cards/SuggestedRepliesCard.d.ts +18 -0
- package/dist/cards/SuggestedRepliesCard.d.ts.map +1 -0
- package/dist/cards/SuggestedRepliesCard.js +14 -0
- package/dist/cards/SuggestedRepliesCard.js.map +1 -0
- package/dist/cards/SummaryMessageCard.d.ts +40 -0
- package/dist/cards/SummaryMessageCard.d.ts.map +1 -0
- package/dist/cards/SummaryMessageCard.js +56 -0
- package/dist/cards/SummaryMessageCard.js.map +1 -0
- package/dist/cards/ThinkingProcessCard.d.ts +46 -0
- package/dist/cards/ThinkingProcessCard.d.ts.map +1 -0
- package/dist/cards/ThinkingProcessCard.js +79 -0
- package/dist/cards/ThinkingProcessCard.js.map +1 -0
- package/dist/cards/ToolExecutionCard.d.ts +21 -0
- package/dist/cards/ToolExecutionCard.d.ts.map +1 -0
- package/dist/cards/ToolExecutionCard.js +65 -0
- package/dist/cards/ToolExecutionCard.js.map +1 -0
- package/dist/cards/icons.d.ts +38 -0
- package/dist/cards/icons.d.ts.map +1 -0
- package/dist/cards/icons.js +87 -0
- package/dist/cards/icons.js.map +1 -0
- package/dist/cards/index.d.ts +38 -0
- package/dist/cards/index.d.ts.map +1 -0
- package/dist/cards/index.js +24 -0
- package/dist/cards/index.js.map +1 -0
- package/dist/cards/types.d.ts +24 -0
- package/dist/cards/types.d.ts.map +1 -0
- package/dist/cards/types.js +7 -0
- package/dist/cards/types.js.map +1 -0
- package/dist/components/AgentSelector.d.ts +23 -0
- package/dist/components/AgentSelector.d.ts.map +1 -0
- package/dist/components/AgentSelector.js +63 -0
- package/dist/components/AgentSelector.js.map +1 -0
- package/dist/components/AgentSelector.stories.d.ts +12 -0
- package/dist/components/AgentSelector.stories.d.ts.map +1 -0
- package/dist/components/AgentSelector.stories.js +95 -0
- package/dist/components/AgentSelector.stories.js.map +1 -0
- package/dist/components/ChatPanel.d.ts +138 -21
- package/dist/components/ChatPanel.d.ts.map +1 -1
- package/dist/components/ChatPanel.js +181 -26
- package/dist/components/ChatPanel.js.map +1 -1
- package/dist/components/index.d.ts +3 -1
- package/dist/components/index.d.ts.map +1 -1
- package/dist/components/index.js +1 -0
- package/dist/components/index.js.map +1 -1
- package/dist/hooks/useChatStream.d.ts +15 -0
- package/dist/hooks/useChatStream.d.ts.map +1 -1
- package/dist/hooks/useChatStream.js +13 -1
- package/dist/hooks/useChatStream.js.map +1 -1
- package/dist/index.d.ts +2 -0
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +5 -0
- package/dist/index.js.map +1 -1
- package/dist/state/ChatSessionProvider.d.ts +59 -0
- package/dist/state/ChatSessionProvider.d.ts.map +1 -0
- package/dist/state/ChatSessionProvider.js +71 -0
- package/dist/state/ChatSessionProvider.js.map +1 -0
- package/dist/state/MockChatStreamTransport.d.ts +54 -0
- package/dist/state/MockChatStreamTransport.d.ts.map +1 -0
- package/dist/state/MockChatStreamTransport.js +86 -0
- package/dist/state/MockChatStreamTransport.js.map +1 -0
- package/dist/state/MockChatStreamTransport.stories.d.ts +13 -0
- package/dist/state/MockChatStreamTransport.stories.d.ts.map +1 -0
- package/dist/state/MockChatStreamTransport.stories.js +60 -0
- package/dist/state/MockChatStreamTransport.stories.js.map +1 -0
- package/dist/state/bridgeLegacySSE.d.ts +42 -0
- package/dist/state/bridgeLegacySSE.d.ts.map +1 -0
- package/dist/state/bridgeLegacySSE.js +102 -0
- package/dist/state/bridgeLegacySSE.js.map +1 -0
- package/dist/state/index.d.ts +32 -0
- package/dist/state/index.d.ts.map +1 -0
- package/dist/state/index.js +24 -0
- package/dist/state/index.js.map +1 -0
- package/dist/state/parseSSE.d.ts +50 -0
- package/dist/state/parseSSE.d.ts.map +1 -0
- package/dist/state/parseSSE.js +112 -0
- package/dist/state/parseSSE.js.map +1 -0
- package/dist/state/useChatComposer.d.ts +51 -0
- package/dist/state/useChatComposer.d.ts.map +1 -0
- package/dist/state/useChatComposer.js +82 -0
- package/dist/state/useChatComposer.js.map +1 -0
- package/dist/state/useChatList.d.ts +73 -0
- package/dist/state/useChatList.d.ts.map +1 -0
- package/dist/state/useChatList.js +161 -0
- package/dist/state/useChatList.js.map +1 -0
- package/dist/state/useChatSession.d.ts +29 -0
- package/dist/state/useChatSession.d.ts.map +1 -0
- package/dist/state/useChatSession.js +37 -0
- package/dist/state/useChatSession.js.map +1 -0
- package/dist/state/useScrollLock.d.ts +35 -0
- package/dist/state/useScrollLock.d.ts.map +1 -0
- package/dist/state/useScrollLock.js +74 -0
- package/dist/state/useScrollLock.js.map +1 -0
- package/dist/state/useToolCallStream.d.ts +38 -0
- package/dist/state/useToolCallStream.d.ts.map +1 -0
- package/dist/state/useToolCallStream.js +74 -0
- package/dist/state/useToolCallStream.js.map +1 -0
- package/package.json +11 -3
- package/src/cards/ActionSegmentCard.tsx +60 -0
- package/src/cards/AnalysisDocumentCard.tsx +81 -0
- package/src/cards/AskUserQuestionsCard.tsx +354 -0
- package/src/cards/CoverageReportCard.tsx +215 -0
- package/src/cards/OrchestrationPlanCard.tsx +328 -0
- package/src/cards/PlanSelectorCard.tsx +312 -0
- package/src/cards/PlanStepsCard.tsx +52 -0
- package/src/cards/QuizCard.tsx +309 -0
- package/src/cards/ResearchPlanCard.tsx +169 -0
- package/src/cards/SearchSourcesCard.tsx +244 -0
- package/src/cards/SuggestedRepliesCard.tsx +48 -0
- package/src/cards/SummaryMessageCard.tsx +145 -0
- package/src/cards/ThinkingProcessCard.tsx +155 -0
- package/src/cards/ToolExecutionCard.tsx +152 -0
- package/src/cards/cards.test.tsx +492 -0
- package/src/cards/icons.tsx +249 -0
- package/src/cards/index.ts +53 -0
- package/src/cards/types.ts +27 -0
- package/src/components/AgentSelector.stories.tsx +113 -0
- package/src/components/AgentSelector.test.tsx +70 -0
- package/src/components/AgentSelector.tsx +147 -0
- package/src/components/ChatPanel.test.tsx +130 -0
- package/src/components/ChatPanel.tsx +612 -138
- package/src/components/index.ts +13 -1
- package/src/hooks/useChatStream.test.ts +78 -0
- package/src/hooks/useChatStream.ts +32 -1
- package/src/index.ts +43 -0
- package/src/state/ChatSessionProvider.test.tsx +85 -0
- package/src/state/ChatSessionProvider.tsx +98 -0
- package/src/state/MockChatStreamTransport.stories.tsx +95 -0
- package/src/state/MockChatStreamTransport.test.ts +163 -0
- package/src/state/MockChatStreamTransport.ts +123 -0
- package/src/state/bridgeLegacySSE.test.ts +134 -0
- package/src/state/bridgeLegacySSE.ts +134 -0
- package/src/state/index.ts +82 -0
- package/src/state/parseSSE.test.ts +123 -0
- package/src/state/parseSSE.ts +123 -0
- package/src/state/useChatComposer.test.ts +145 -0
- package/src/state/useChatComposer.ts +117 -0
- package/src/state/useChatList.test.ts +135 -0
- package/src/state/useChatList.ts +220 -0
- package/src/state/useChatSession.test.ts +61 -0
- package/src/state/useChatSession.ts +64 -0
- package/src/state/useScrollLock.test.ts +99 -0
- package/src/state/useScrollLock.ts +105 -0
- package/src/state/useToolCallStream.test.ts +86 -0
- package/src/state/useToolCallStream.ts +110 -0
|
@@ -0,0 +1,130 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Tests for the compound `ChatPanel` API.
|
|
3
|
+
*
|
|
4
|
+
* The structural test surface is small — the heavy lifting is in MessageList
|
|
5
|
+
* and the state hooks — but we want to lock in the contract that the
|
|
6
|
+
* compound parts hang off `ChatPanel` AND that the monolithic alias still
|
|
7
|
+
* renders messages + a draftable input.
|
|
8
|
+
*/
|
|
9
|
+
|
|
10
|
+
import { describe, expect, it, vi } from 'vitest';
|
|
11
|
+
import { useState } from 'react';
|
|
12
|
+
import { render, screen, fireEvent } from '@testing-library/react';
|
|
13
|
+
import type { ChatMessage } from '@steerable/agent-protocol';
|
|
14
|
+
import { ChatPanel } from './ChatPanel';
|
|
15
|
+
|
|
16
|
+
const NOW = '2026-05-15T00:00:00Z';
|
|
17
|
+
const sample: ChatMessage[] = [
|
|
18
|
+
{ id: 'u1', role: 'user', content: 'hello', createdAt: NOW },
|
|
19
|
+
{ id: 'a1', role: 'assistant', content: 'hi there', createdAt: NOW },
|
|
20
|
+
];
|
|
21
|
+
|
|
22
|
+
function CompoundDemo({ onSubmit }: { onSubmit: () => void }) {
|
|
23
|
+
const [draft, setDraft] = useState('');
|
|
24
|
+
return (
|
|
25
|
+
<ChatPanel.Root>
|
|
26
|
+
<ChatPanel.Messages messages={sample} />
|
|
27
|
+
<ChatPanel.Input
|
|
28
|
+
value={draft}
|
|
29
|
+
onChange={setDraft}
|
|
30
|
+
onSubmit={() => {
|
|
31
|
+
onSubmit();
|
|
32
|
+
setDraft('');
|
|
33
|
+
}}
|
|
34
|
+
/>
|
|
35
|
+
</ChatPanel.Root>
|
|
36
|
+
);
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
describe('ChatPanel compound', () => {
|
|
40
|
+
it('exposes Root, Header, Messages, Input, Empty, StreamingStatus as attached subs', () => {
|
|
41
|
+
// forwardRef components are objects with a render fn; plain components
|
|
42
|
+
// are functions. We assert "callable-ish" rather than pinning the kind.
|
|
43
|
+
for (const sub of [
|
|
44
|
+
ChatPanel.Root,
|
|
45
|
+
ChatPanel.Header,
|
|
46
|
+
ChatPanel.Messages,
|
|
47
|
+
ChatPanel.Input,
|
|
48
|
+
ChatPanel.Empty,
|
|
49
|
+
ChatPanel.StreamingStatus,
|
|
50
|
+
]) {
|
|
51
|
+
expect(sub).toBeDefined();
|
|
52
|
+
}
|
|
53
|
+
});
|
|
54
|
+
|
|
55
|
+
it('Root + Messages + Input compose into a working shell', () => {
|
|
56
|
+
render(<CompoundDemo onSubmit={() => {}} />);
|
|
57
|
+
expect(screen.getByText('hello')).toBeTruthy();
|
|
58
|
+
expect(screen.getByText('hi there')).toBeTruthy();
|
|
59
|
+
});
|
|
60
|
+
|
|
61
|
+
it('Empty slot renders prompts and fires onSelectPrompt on click', () => {
|
|
62
|
+
const onSelectPrompt = vi.fn();
|
|
63
|
+
render(
|
|
64
|
+
<ChatPanel.Empty
|
|
65
|
+
title="Try a prompt"
|
|
66
|
+
prompts={['plan my day', 'summarise']}
|
|
67
|
+
onSelectPrompt={onSelectPrompt}
|
|
68
|
+
/>,
|
|
69
|
+
);
|
|
70
|
+
expect(screen.getByText('Try a prompt')).toBeTruthy();
|
|
71
|
+
fireEvent.click(screen.getByText('plan my day'));
|
|
72
|
+
expect(onSelectPrompt).toHaveBeenCalledWith('plan my day');
|
|
73
|
+
});
|
|
74
|
+
|
|
75
|
+
it('StreamingStatus hides when hasContent=true and renders text otherwise', () => {
|
|
76
|
+
const { rerender, queryByText } = render(
|
|
77
|
+
<ChatPanel.StreamingStatus hasContent={true} round={1} actionCount={0} />,
|
|
78
|
+
);
|
|
79
|
+
expect(queryByText('Thinking…')).toBeNull();
|
|
80
|
+
rerender(
|
|
81
|
+
<ChatPanel.StreamingStatus hasContent={false} round={1} actionCount={0} />,
|
|
82
|
+
);
|
|
83
|
+
expect(queryByText('Thinking…')).toBeTruthy();
|
|
84
|
+
});
|
|
85
|
+
|
|
86
|
+
it('monolithic alias still renders messages + accepts onSubmit prop', () => {
|
|
87
|
+
const onSubmit = vi.fn();
|
|
88
|
+
render(<ChatPanel messages={sample} onSubmit={onSubmit} />);
|
|
89
|
+
expect(screen.getByText('hello')).toBeTruthy();
|
|
90
|
+
expect(screen.getByText('hi there')).toBeTruthy();
|
|
91
|
+
});
|
|
92
|
+
|
|
93
|
+
it('Input with keyMode=enter sends on plain Enter and inserts newline on Shift+Enter', () => {
|
|
94
|
+
const onSubmit = vi.fn();
|
|
95
|
+
function Demo() {
|
|
96
|
+
const [draft, setDraft] = useState('ping');
|
|
97
|
+
return (
|
|
98
|
+
<ChatPanel.Input
|
|
99
|
+
value={draft}
|
|
100
|
+
onChange={setDraft}
|
|
101
|
+
onSubmit={() => onSubmit()}
|
|
102
|
+
keyMode="enter"
|
|
103
|
+
/>
|
|
104
|
+
);
|
|
105
|
+
}
|
|
106
|
+
render(<Demo />);
|
|
107
|
+
const textarea = screen.getByRole('textbox') as HTMLTextAreaElement;
|
|
108
|
+
fireEvent.keyDown(textarea, { key: 'Enter' });
|
|
109
|
+
expect(onSubmit).toHaveBeenCalledOnce();
|
|
110
|
+
onSubmit.mockClear();
|
|
111
|
+
fireEvent.keyDown(textarea, { key: 'Enter', shiftKey: true });
|
|
112
|
+
expect(onSubmit).not.toHaveBeenCalled();
|
|
113
|
+
});
|
|
114
|
+
|
|
115
|
+
it('Input toggles to a Stop button while streaming, fires onCancel on click', () => {
|
|
116
|
+
const onCancel = vi.fn();
|
|
117
|
+
render(
|
|
118
|
+
<ChatPanel.Input
|
|
119
|
+
value=""
|
|
120
|
+
onChange={() => {}}
|
|
121
|
+
onSubmit={() => {}}
|
|
122
|
+
onCancel={onCancel}
|
|
123
|
+
isStreaming
|
|
124
|
+
/>,
|
|
125
|
+
);
|
|
126
|
+
const stopBtn = screen.getByLabelText('Stop generating');
|
|
127
|
+
fireEvent.click(stopBtn);
|
|
128
|
+
expect(onCancel).toHaveBeenCalledOnce();
|
|
129
|
+
});
|
|
130
|
+
});
|