@assistant-ui/react-ink 0.0.2 → 0.0.4
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +86 -0
- package/dist/context/AssistantContext.d.ts +1 -7
- package/dist/context/AssistantContext.d.ts.map +1 -1
- package/dist/context/AssistantContext.js +1 -15
- package/dist/context/AssistantContext.js.map +1 -1
- package/dist/context/index.d.ts +1 -1
- package/dist/context/index.d.ts.map +1 -1
- package/dist/context/index.js +1 -1
- package/dist/context/index.js.map +1 -1
- package/dist/index.d.ts +13 -14
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +13 -16
- package/dist/index.js.map +1 -1
- package/dist/primitives/actionBar/ActionBarCopy.d.ts +1 -1
- package/dist/primitives/actionBar/ActionBarCopy.d.ts.map +1 -1
- package/dist/primitives/actionBar/ActionBarCopy.js +1 -1
- package/dist/primitives/actionBar/ActionBarCopy.js.map +1 -1
- package/dist/primitives/actionBar/ActionBarEdit.js +1 -1
- package/dist/primitives/actionBar/ActionBarEdit.js.map +1 -1
- package/dist/primitives/actionBar/ActionBarFeedbackNegative.js +1 -1
- package/dist/primitives/actionBar/ActionBarFeedbackNegative.js.map +1 -1
- package/dist/primitives/actionBar/ActionBarFeedbackPositive.js +1 -1
- package/dist/primitives/actionBar/ActionBarFeedbackPositive.js.map +1 -1
- package/dist/primitives/actionBar/ActionBarReload.js +1 -1
- package/dist/primitives/actionBar/ActionBarReload.js.map +1 -1
- package/dist/primitives/actionBar/index.d.ts +5 -5
- package/dist/primitives/actionBar/index.d.ts.map +1 -1
- package/dist/primitives/actionBar/index.js +5 -5
- package/dist/primitives/actionBar/index.js.map +1 -1
- package/dist/primitives/attachment/index.d.ts +4 -4
- package/dist/primitives/attachment/index.d.ts.map +1 -1
- package/dist/primitives/attachment/index.js +4 -4
- package/dist/primitives/attachment/index.js.map +1 -1
- package/dist/primitives/branchPicker/index.d.ts +4 -4
- package/dist/primitives/branchPicker/index.d.ts.map +1 -1
- package/dist/primitives/branchPicker/index.js +4 -4
- package/dist/primitives/branchPicker/index.js.map +1 -1
- package/dist/primitives/chainOfThought/index.d.ts +3 -3
- package/dist/primitives/chainOfThought/index.d.ts.map +1 -1
- package/dist/primitives/chainOfThought/index.js +3 -3
- package/dist/primitives/chainOfThought/index.js.map +1 -1
- package/dist/primitives/composer/ComposerAddAttachment.d.ts.map +1 -1
- package/dist/primitives/composer/ComposerAddAttachment.js +3 -5
- package/dist/primitives/composer/ComposerAddAttachment.js.map +1 -1
- package/dist/primitives/composer/ComposerCancel.js +3 -3
- package/dist/primitives/composer/ComposerCancel.js.map +1 -1
- package/dist/primitives/composer/ComposerSend.js +3 -3
- package/dist/primitives/composer/ComposerSend.js.map +1 -1
- package/dist/primitives/composer/index.d.ts +7 -10
- package/dist/primitives/composer/index.d.ts.map +1 -1
- package/dist/primitives/composer/index.js +7 -10
- package/dist/primitives/composer/index.js.map +1 -1
- package/dist/primitives/message/MessageContent.d.ts.map +1 -1
- package/dist/primitives/message/MessageContent.js +9 -3
- package/dist/primitives/message/MessageContent.js.map +1 -1
- package/dist/primitives/message/index.d.ts +5 -5
- package/dist/primitives/message/index.d.ts.map +1 -1
- package/dist/primitives/message/index.js +5 -5
- package/dist/primitives/message/index.js.map +1 -1
- package/dist/primitives/suggestion/index.d.ts +3 -3
- package/dist/primitives/suggestion/index.d.ts.map +1 -1
- package/dist/primitives/suggestion/index.js +3 -3
- package/dist/primitives/suggestion/index.js.map +1 -1
- package/dist/primitives/thread/ThreadEmpty.js +1 -1
- package/dist/primitives/thread/ThreadEmpty.js.map +1 -1
- package/dist/primitives/thread/ThreadMessages.d.ts +23 -7
- package/dist/primitives/thread/ThreadMessages.d.ts.map +1 -1
- package/dist/primitives/thread/ThreadMessages.js +67 -13
- package/dist/primitives/thread/ThreadMessages.js.map +1 -1
- package/dist/primitives/thread/index.d.ts +7 -7
- package/dist/primitives/thread/index.d.ts.map +1 -1
- package/dist/primitives/thread/index.js +7 -7
- package/dist/primitives/thread/index.js.map +1 -1
- package/dist/primitives/threadList/index.d.ts +3 -3
- package/dist/primitives/threadList/index.d.ts.map +1 -1
- package/dist/primitives/threadList/index.js +3 -3
- package/dist/primitives/threadList/index.js.map +1 -1
- package/dist/primitives/threadListItem/index.d.ts +6 -6
- package/dist/primitives/threadListItem/index.d.ts.map +1 -1
- package/dist/primitives/threadListItem/index.js +6 -6
- package/dist/primitives/threadListItem/index.js.map +1 -1
- package/dist/primitives/toolCall/ToolFallback.d.ts +33 -0
- package/dist/primitives/toolCall/ToolFallback.d.ts.map +1 -0
- package/dist/primitives/toolCall/ToolFallback.js +103 -0
- package/dist/primitives/toolCall/ToolFallback.js.map +1 -0
- package/dist/primitives/toolCall/index.d.ts +2 -0
- package/dist/primitives/toolCall/index.d.ts.map +1 -0
- package/dist/primitives/toolCall/index.js +2 -0
- package/dist/primitives/toolCall/index.js.map +1 -0
- package/dist/runtimes/useLocalRuntime.d.ts +1 -17
- package/dist/runtimes/useLocalRuntime.d.ts.map +1 -1
- package/dist/runtimes/useLocalRuntime.js +1 -61
- package/dist/runtimes/useLocalRuntime.js.map +1 -1
- package/package.json +5 -3
- package/src/context/AssistantContext.tsx +4 -31
- package/src/context/index.ts +4 -1
- package/src/index.ts +13 -39
- package/src/primitives/actionBar/ActionBarCopy.tsx +1 -1
- package/src/primitives/actionBar/ActionBarEdit.tsx +1 -1
- package/src/primitives/actionBar/ActionBarFeedbackNegative.tsx +1 -1
- package/src/primitives/actionBar/ActionBarFeedbackPositive.tsx +1 -1
- package/src/primitives/actionBar/ActionBarReload.tsx +1 -1
- package/src/primitives/actionBar/index.ts +16 -7
- package/src/primitives/attachment/index.ts +14 -5
- package/src/primitives/branchPicker/index.ts +8 -8
- package/src/primitives/chainOfThought/index.ts +5 -5
- package/src/primitives/composer/ComposerAddAttachment.tsx +3 -5
- package/src/primitives/composer/ComposerCancel.tsx +3 -3
- package/src/primitives/composer/ComposerSend.tsx +3 -3
- package/src/primitives/composer/index.ts +19 -19
- package/src/primitives/message/MessageContent.test.tsx +83 -0
- package/src/primitives/message/MessageContent.tsx +21 -15
- package/src/primitives/message/index.ts +13 -7
- package/src/primitives/suggestion/index.ts +6 -6
- package/src/primitives/thread/ThreadEmpty.tsx +1 -1
- package/src/primitives/thread/ThreadMessages.tsx +122 -27
- package/src/primitives/thread/index.ts +17 -11
- package/src/primitives/threadList/index.ts +12 -3
- package/src/primitives/threadListItem/index.ts +11 -11
- package/src/primitives/toolCall/ToolFallback.test.tsx +40 -0
- package/src/primitives/toolCall/ToolFallback.tsx +227 -0
- package/src/primitives/toolCall/index.ts +5 -0
- package/src/runtimes/useLocalRuntime.ts +4 -105
- package/dist/adapters/LocalStorageThreadListAdapter.d.ts +0 -15
- package/dist/adapters/LocalStorageThreadListAdapter.d.ts.map +0 -1
- package/dist/adapters/LocalStorageThreadListAdapter.js +0 -154
- package/dist/adapters/LocalStorageThreadListAdapter.js.map +0 -1
- package/dist/adapters/TitleGenerationAdapter.d.ts +0 -6
- package/dist/adapters/TitleGenerationAdapter.d.ts.map +0 -1
- package/dist/adapters/TitleGenerationAdapter.js +0 -15
- package/dist/adapters/TitleGenerationAdapter.js.map +0 -1
- package/dist/adapters/index.d.ts +0 -3
- package/dist/adapters/index.d.ts.map +0 -1
- package/dist/adapters/index.js +0 -3
- package/dist/adapters/index.js.map +0 -1
- package/dist/primitive-hooks/index.d.ts +0 -15
- package/dist/primitive-hooks/index.d.ts.map +0 -1
- package/dist/primitive-hooks/index.js +0 -15
- package/dist/primitive-hooks/index.js.map +0 -1
- package/dist/primitive-hooks/useActionBarCopy.d.ts +0 -10
- package/dist/primitive-hooks/useActionBarCopy.d.ts.map +0 -1
- package/dist/primitive-hooks/useActionBarCopy.js +0 -26
- package/dist/primitive-hooks/useActionBarCopy.js.map +0 -1
- package/dist/primitive-hooks/useActionBarEdit.d.ts +0 -5
- package/dist/primitive-hooks/useActionBarEdit.d.ts.map +0 -1
- package/dist/primitive-hooks/useActionBarEdit.js +0 -11
- package/dist/primitive-hooks/useActionBarEdit.js.map +0 -1
- package/dist/primitive-hooks/useActionBarFeedback.d.ts +0 -9
- package/dist/primitive-hooks/useActionBarFeedback.d.ts.map +0 -1
- package/dist/primitive-hooks/useActionBarFeedback.js +0 -19
- package/dist/primitive-hooks/useActionBarFeedback.js.map +0 -1
- package/dist/primitive-hooks/useActionBarReload.d.ts +0 -5
- package/dist/primitive-hooks/useActionBarReload.d.ts.map +0 -1
- package/dist/primitive-hooks/useActionBarReload.js +0 -13
- package/dist/primitive-hooks/useActionBarReload.js.map +0 -1
- package/dist/primitive-hooks/useComposerAddAttachment.d.ts +0 -5
- package/dist/primitive-hooks/useComposerAddAttachment.d.ts.map +0 -1
- package/dist/primitive-hooks/useComposerAddAttachment.js +0 -10
- package/dist/primitive-hooks/useComposerAddAttachment.js.map +0 -1
- package/dist/primitive-hooks/useComposerCancel.d.ts +0 -5
- package/dist/primitive-hooks/useComposerCancel.d.ts.map +0 -1
- package/dist/primitive-hooks/useComposerCancel.js +0 -11
- package/dist/primitive-hooks/useComposerCancel.js.map +0 -1
- package/dist/primitive-hooks/useComposerSend.d.ts +0 -5
- package/dist/primitive-hooks/useComposerSend.d.ts.map +0 -1
- package/dist/primitive-hooks/useComposerSend.js +0 -11
- package/dist/primitive-hooks/useComposerSend.js.map +0 -1
- package/dist/primitive-hooks/useEditComposerCancel.d.ts +0 -4
- package/dist/primitive-hooks/useEditComposerCancel.d.ts.map +0 -1
- package/dist/primitive-hooks/useEditComposerCancel.js +0 -10
- package/dist/primitive-hooks/useEditComposerCancel.js.map +0 -1
- package/dist/primitive-hooks/useEditComposerSend.d.ts +0 -5
- package/dist/primitive-hooks/useEditComposerSend.d.ts.map +0 -1
- package/dist/primitive-hooks/useEditComposerSend.js +0 -11
- package/dist/primitive-hooks/useEditComposerSend.js.map +0 -1
- package/dist/primitive-hooks/useMessageBranching.d.ts +0 -7
- package/dist/primitive-hooks/useMessageBranching.d.ts.map +0 -1
- package/dist/primitive-hooks/useMessageBranching.js +0 -15
- package/dist/primitive-hooks/useMessageBranching.js.map +0 -1
- package/dist/primitive-hooks/useMessageReload.d.ts +0 -5
- package/dist/primitive-hooks/useMessageReload.d.ts.map +0 -1
- package/dist/primitive-hooks/useMessageReload.js +0 -11
- package/dist/primitive-hooks/useMessageReload.js.map +0 -1
- package/dist/primitive-hooks/useThreadIsEmpty.d.ts +0 -2
- package/dist/primitive-hooks/useThreadIsEmpty.d.ts.map +0 -1
- package/dist/primitive-hooks/useThreadIsEmpty.js +0 -5
- package/dist/primitive-hooks/useThreadIsEmpty.js.map +0 -1
- package/dist/primitive-hooks/useThreadIsRunning.d.ts +0 -2
- package/dist/primitive-hooks/useThreadIsRunning.d.ts.map +0 -1
- package/dist/primitive-hooks/useThreadIsRunning.js +0 -5
- package/dist/primitive-hooks/useThreadIsRunning.js.map +0 -1
- package/dist/primitive-hooks/useThreadMessages.d.ts +0 -3
- package/dist/primitive-hooks/useThreadMessages.d.ts.map +0 -1
- package/dist/primitive-hooks/useThreadMessages.js +0 -5
- package/dist/primitive-hooks/useThreadMessages.js.map +0 -1
- package/dist/primitives/composer/EditComposerCancel.d.ts +0 -7
- package/dist/primitives/composer/EditComposerCancel.d.ts.map +0 -1
- package/dist/primitives/composer/EditComposerCancel.js +0 -8
- package/dist/primitives/composer/EditComposerCancel.js.map +0 -1
- package/dist/primitives/composer/EditComposerInput.d.ts +0 -10
- package/dist/primitives/composer/EditComposerInput.d.ts.map +0 -1
- package/dist/primitives/composer/EditComposerInput.js +0 -19
- package/dist/primitives/composer/EditComposerInput.js.map +0 -1
- package/dist/primitives/composer/EditComposerSend.d.ts +0 -7
- package/dist/primitives/composer/EditComposerSend.d.ts.map +0 -1
- package/dist/primitives/composer/EditComposerSend.js +0 -8
- package/dist/primitives/composer/EditComposerSend.js.map +0 -1
- package/src/adapters/LocalStorageThreadListAdapter.tsx +0 -227
- package/src/adapters/TitleGenerationAdapter.ts +0 -20
- package/src/adapters/index.ts +0 -5
- package/src/primitive-hooks/index.ts +0 -20
- package/src/primitive-hooks/useActionBarCopy.ts +0 -38
- package/src/primitive-hooks/useActionBarEdit.ts +0 -13
- package/src/primitive-hooks/useActionBarFeedback.ts +0 -28
- package/src/primitive-hooks/useActionBarReload.ts +0 -18
- package/src/primitive-hooks/useComposerAddAttachment.ts +0 -16
- package/src/primitive-hooks/useComposerCancel.ts +0 -13
- package/src/primitive-hooks/useComposerSend.ts +0 -13
- package/src/primitive-hooks/useEditComposerCancel.ts +0 -12
- package/src/primitive-hooks/useEditComposerSend.ts +0 -13
- package/src/primitive-hooks/useMessageBranching.ts +0 -18
- package/src/primitive-hooks/useMessageReload.ts +0 -13
- package/src/primitive-hooks/useThreadIsEmpty.ts +0 -5
- package/src/primitive-hooks/useThreadIsRunning.ts +0 -5
- package/src/primitive-hooks/useThreadMessages.ts +0 -6
- package/src/primitives/composer/EditComposerCancel.tsx +0 -20
- package/src/primitives/composer/EditComposerInput.tsx +0 -40
- package/src/primitives/composer/EditComposerSend.tsx +0 -25
|
@@ -0,0 +1,83 @@
|
|
|
1
|
+
import type { ReactElement } from "react";
|
|
2
|
+
import { afterEach, describe, expect, it, vi } from "vitest";
|
|
3
|
+
import { cleanup, render } from "ink-testing-library";
|
|
4
|
+
import { MessageContent } from "./MessageContent";
|
|
5
|
+
|
|
6
|
+
const mockUseAui = vi.fn();
|
|
7
|
+
const mockUseAuiState = vi.fn();
|
|
8
|
+
|
|
9
|
+
type UseAuiStateSelector = Parameters<
|
|
10
|
+
typeof import("@assistant-ui/store")["useAuiState"]
|
|
11
|
+
>[0];
|
|
12
|
+
|
|
13
|
+
vi.mock("@assistant-ui/store", async (importOriginal) => {
|
|
14
|
+
const actual = await importOriginal<typeof import("@assistant-ui/store")>();
|
|
15
|
+
return {
|
|
16
|
+
...actual,
|
|
17
|
+
useAui: () => mockUseAui(),
|
|
18
|
+
useAuiState: (selector: UseAuiStateSelector) => mockUseAuiState(selector),
|
|
19
|
+
};
|
|
20
|
+
});
|
|
21
|
+
|
|
22
|
+
const renderFrame = async (node: ReactElement) => {
|
|
23
|
+
const instance = render(node);
|
|
24
|
+
await new Promise((resolve) => setTimeout(resolve, 0));
|
|
25
|
+
return instance.lastFrame() ?? "";
|
|
26
|
+
};
|
|
27
|
+
|
|
28
|
+
afterEach(() => {
|
|
29
|
+
cleanup();
|
|
30
|
+
vi.clearAllMocks();
|
|
31
|
+
});
|
|
32
|
+
|
|
33
|
+
describe("MessageContent", () => {
|
|
34
|
+
it("renders incomplete tool calls as errors instead of running forever", async () => {
|
|
35
|
+
const state = {
|
|
36
|
+
tools: { tools: {} },
|
|
37
|
+
message: {
|
|
38
|
+
content: [
|
|
39
|
+
{
|
|
40
|
+
type: "tool-call",
|
|
41
|
+
toolCallId: "tool-call-1",
|
|
42
|
+
toolName: "search",
|
|
43
|
+
args: { query: "weather" },
|
|
44
|
+
argsText: '{"query":"weather"}',
|
|
45
|
+
},
|
|
46
|
+
],
|
|
47
|
+
parts: [
|
|
48
|
+
{
|
|
49
|
+
type: "tool-call",
|
|
50
|
+
toolCallId: "tool-call-1",
|
|
51
|
+
toolName: "search",
|
|
52
|
+
args: { query: "weather" },
|
|
53
|
+
argsText: '{"query":"weather"}',
|
|
54
|
+
status: {
|
|
55
|
+
type: "incomplete",
|
|
56
|
+
reason: "error",
|
|
57
|
+
error: "request failed",
|
|
58
|
+
},
|
|
59
|
+
},
|
|
60
|
+
],
|
|
61
|
+
},
|
|
62
|
+
};
|
|
63
|
+
|
|
64
|
+
mockUseAuiState.mockImplementation((selector: UseAuiStateSelector) =>
|
|
65
|
+
selector(state as never),
|
|
66
|
+
);
|
|
67
|
+
mockUseAui.mockReturnValue({
|
|
68
|
+
message: () => ({
|
|
69
|
+
part: () => ({
|
|
70
|
+
addToolResult: vi.fn(),
|
|
71
|
+
resumeToolCall: vi.fn(),
|
|
72
|
+
}),
|
|
73
|
+
}),
|
|
74
|
+
});
|
|
75
|
+
|
|
76
|
+
const frame = await renderFrame(<MessageContent />);
|
|
77
|
+
|
|
78
|
+
expect(frame).toContain("search");
|
|
79
|
+
expect(frame).toContain("Error:");
|
|
80
|
+
expect(frame).toContain("request failed");
|
|
81
|
+
expect(frame).not.toContain("Running...");
|
|
82
|
+
});
|
|
83
|
+
});
|
|
@@ -3,16 +3,17 @@ import { Text } from "ink";
|
|
|
3
3
|
import type {
|
|
4
4
|
ThreadUserMessagePart,
|
|
5
5
|
ThreadAssistantMessagePart,
|
|
6
|
-
|
|
7
|
-
DataMessagePart,
|
|
6
|
+
MessagePartState,
|
|
8
7
|
} from "@assistant-ui/core";
|
|
9
8
|
import { useAui, useAuiState } from "@assistant-ui/store";
|
|
10
9
|
import type {
|
|
11
10
|
ToolCallMessagePartProps,
|
|
12
11
|
DataMessagePartProps,
|
|
13
12
|
} from "../../types";
|
|
13
|
+
import { ToolFallback } from "../toolCall/ToolFallback";
|
|
14
14
|
|
|
15
15
|
type MessageContentPart = ThreadUserMessagePart | ThreadAssistantMessagePart;
|
|
16
|
+
type MessageContentStatePart = MessagePartState;
|
|
16
17
|
|
|
17
18
|
export type MessageContentProps = {
|
|
18
19
|
renderText?: (props: {
|
|
@@ -59,9 +60,12 @@ const ToolUIDisplay = ({
|
|
|
59
60
|
index,
|
|
60
61
|
}: {
|
|
61
62
|
Fallback:
|
|
62
|
-
| ((props: {
|
|
63
|
+
| ((props: {
|
|
64
|
+
part: Extract<MessageContentPart, { type: "tool-call" }>;
|
|
65
|
+
index: number;
|
|
66
|
+
}) => ReactElement)
|
|
63
67
|
| undefined;
|
|
64
|
-
part:
|
|
68
|
+
part: Extract<MessageContentStatePart, { type: "tool-call" }>;
|
|
65
69
|
index: number;
|
|
66
70
|
}) => {
|
|
67
71
|
const aui = useAui();
|
|
@@ -75,18 +79,17 @@ const ToolUIDisplay = ({
|
|
|
75
79
|
() => aui.message().part({ index }),
|
|
76
80
|
[aui, index],
|
|
77
81
|
);
|
|
82
|
+
const toolProps = {
|
|
83
|
+
...(part as ToolCallMessagePartProps),
|
|
84
|
+
addResult: partMethods.addToolResult,
|
|
85
|
+
resume: partMethods.resumeToolCall,
|
|
86
|
+
};
|
|
78
87
|
|
|
79
88
|
if (Render) {
|
|
80
|
-
return
|
|
81
|
-
<Render
|
|
82
|
-
{...(part as ToolCallMessagePartProps)}
|
|
83
|
-
addResult={partMethods.addToolResult}
|
|
84
|
-
resume={partMethods.resumeToolCall}
|
|
85
|
-
/>
|
|
86
|
-
);
|
|
89
|
+
return <Render {...toolProps} />;
|
|
87
90
|
}
|
|
88
91
|
if (Fallback) return <Fallback part={part} index={index} />;
|
|
89
|
-
return
|
|
92
|
+
return <ToolFallback {...toolProps} />;
|
|
90
93
|
};
|
|
91
94
|
|
|
92
95
|
const DataUIDisplay = ({
|
|
@@ -95,9 +98,12 @@ const DataUIDisplay = ({
|
|
|
95
98
|
index,
|
|
96
99
|
}: {
|
|
97
100
|
Fallback:
|
|
98
|
-
| ((props: {
|
|
101
|
+
| ((props: {
|
|
102
|
+
part: Extract<MessageContentPart, { type: "data" }>;
|
|
103
|
+
index: number;
|
|
104
|
+
}) => ReactElement)
|
|
99
105
|
| undefined;
|
|
100
|
-
part:
|
|
106
|
+
part: Extract<MessageContentStatePart, { type: "data" }>;
|
|
101
107
|
index: number;
|
|
102
108
|
}) => {
|
|
103
109
|
const Render = useAuiState((s) => {
|
|
@@ -119,7 +125,7 @@ export const MessageContent = ({
|
|
|
119
125
|
renderFile,
|
|
120
126
|
renderData,
|
|
121
127
|
}: MessageContentProps) => {
|
|
122
|
-
const content = useAuiState((s) => s.message.
|
|
128
|
+
const content = useAuiState((s) => s.message.parts);
|
|
123
129
|
|
|
124
130
|
return (
|
|
125
131
|
<>
|
|
@@ -1,11 +1,17 @@
|
|
|
1
|
-
export { MessageRoot, type MessageRootProps } from "./MessageRoot";
|
|
2
|
-
export { MessageContent, type MessageContentProps } from "./MessageContent";
|
|
3
1
|
export {
|
|
4
|
-
|
|
5
|
-
|
|
2
|
+
MessageRoot as Root,
|
|
3
|
+
type MessageRootProps as RootProps,
|
|
4
|
+
} from "./MessageRoot";
|
|
5
|
+
export {
|
|
6
|
+
MessageContent as Content,
|
|
7
|
+
type MessageContentProps as ContentProps,
|
|
8
|
+
} from "./MessageContent";
|
|
9
|
+
export {
|
|
10
|
+
MessagePrimitiveParts as Parts,
|
|
11
|
+
MessagePrimitivePartByIndex as PartByIndex,
|
|
6
12
|
} from "./MessageParts";
|
|
7
|
-
export { MessageIf, type MessageIfProps } from "./MessageIf";
|
|
13
|
+
export { MessageIf as If, type MessageIfProps as IfProps } from "./MessageIf";
|
|
8
14
|
export {
|
|
9
|
-
MessageAttachments,
|
|
10
|
-
MessageAttachmentByIndex,
|
|
15
|
+
MessageAttachments as Attachments,
|
|
16
|
+
MessageAttachmentByIndex as AttachmentByIndex,
|
|
11
17
|
} from "./MessageAttachments";
|
|
@@ -1,12 +1,12 @@
|
|
|
1
1
|
export {
|
|
2
|
-
SuggestionTitle,
|
|
3
|
-
type SuggestionTitleProps,
|
|
2
|
+
SuggestionTitle as Title,
|
|
3
|
+
type SuggestionTitleProps as TitleProps,
|
|
4
4
|
} from "./SuggestionTitle";
|
|
5
5
|
export {
|
|
6
|
-
SuggestionDescription,
|
|
7
|
-
type SuggestionDescriptionProps,
|
|
6
|
+
SuggestionDescription as Description,
|
|
7
|
+
type SuggestionDescriptionProps as DescriptionProps,
|
|
8
8
|
} from "./SuggestionDescription";
|
|
9
9
|
export {
|
|
10
|
-
SuggestionTrigger,
|
|
11
|
-
type SuggestionTriggerProps,
|
|
10
|
+
SuggestionTrigger as Trigger,
|
|
11
|
+
type SuggestionTriggerProps as TriggerProps,
|
|
12
12
|
} from "./SuggestionTrigger";
|
|
@@ -1,42 +1,137 @@
|
|
|
1
|
-
import { type
|
|
1
|
+
import { type ComponentType, type FC, memo } from "react";
|
|
2
2
|
import { Box } from "ink";
|
|
3
3
|
import type { ThreadMessage } from "@assistant-ui/core";
|
|
4
|
-
import {
|
|
4
|
+
import { useAuiState } from "@assistant-ui/store";
|
|
5
|
+
import { MessageByIndexProvider } from "@assistant-ui/core/react";
|
|
6
|
+
|
|
7
|
+
type MessageComponents =
|
|
8
|
+
| {
|
|
9
|
+
Message: ComponentType;
|
|
10
|
+
EditComposer?: ComponentType | undefined;
|
|
11
|
+
UserEditComposer?: ComponentType | undefined;
|
|
12
|
+
AssistantEditComposer?: ComponentType | undefined;
|
|
13
|
+
SystemEditComposer?: ComponentType | undefined;
|
|
14
|
+
UserMessage?: ComponentType | undefined;
|
|
15
|
+
AssistantMessage?: ComponentType | undefined;
|
|
16
|
+
SystemMessage?: ComponentType | undefined;
|
|
17
|
+
}
|
|
18
|
+
| {
|
|
19
|
+
Message?: ComponentType | undefined;
|
|
20
|
+
EditComposer?: ComponentType | undefined;
|
|
21
|
+
UserEditComposer?: ComponentType | undefined;
|
|
22
|
+
AssistantEditComposer?: ComponentType | undefined;
|
|
23
|
+
SystemEditComposer?: ComponentType | undefined;
|
|
24
|
+
UserMessage: ComponentType;
|
|
25
|
+
AssistantMessage: ComponentType;
|
|
26
|
+
SystemMessage?: ComponentType | undefined;
|
|
27
|
+
};
|
|
5
28
|
|
|
6
29
|
export type ThreadMessagesProps = {
|
|
7
|
-
|
|
8
|
-
message: ThreadMessage;
|
|
9
|
-
index: number;
|
|
10
|
-
}) => ReactElement;
|
|
30
|
+
components: MessageComponents;
|
|
11
31
|
};
|
|
12
32
|
|
|
13
|
-
const
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
33
|
+
const DEFAULT_SYSTEM_MESSAGE = () => null;
|
|
34
|
+
|
|
35
|
+
const getComponent = (
|
|
36
|
+
components: MessageComponents,
|
|
37
|
+
role: ThreadMessage["role"],
|
|
38
|
+
isEditing: boolean,
|
|
39
|
+
) => {
|
|
40
|
+
switch (role) {
|
|
41
|
+
case "user":
|
|
42
|
+
if (isEditing) {
|
|
43
|
+
return (
|
|
44
|
+
components.UserEditComposer ??
|
|
45
|
+
components.EditComposer ??
|
|
46
|
+
components.UserMessage ??
|
|
47
|
+
(components.Message as ComponentType)
|
|
48
|
+
);
|
|
49
|
+
} else {
|
|
50
|
+
return components.UserMessage ?? (components.Message as ComponentType);
|
|
51
|
+
}
|
|
52
|
+
case "assistant":
|
|
53
|
+
if (isEditing) {
|
|
54
|
+
return (
|
|
55
|
+
components.AssistantEditComposer ??
|
|
56
|
+
components.EditComposer ??
|
|
57
|
+
components.AssistantMessage ??
|
|
58
|
+
(components.Message as ComponentType)
|
|
59
|
+
);
|
|
60
|
+
} else {
|
|
61
|
+
return (
|
|
62
|
+
components.AssistantMessage ?? (components.Message as ComponentType)
|
|
63
|
+
);
|
|
64
|
+
}
|
|
65
|
+
case "system":
|
|
66
|
+
if (isEditing) {
|
|
67
|
+
return (
|
|
68
|
+
components.SystemEditComposer ??
|
|
69
|
+
components.EditComposer ??
|
|
70
|
+
components.SystemMessage ??
|
|
71
|
+
(components.Message as ComponentType) ??
|
|
72
|
+
DEFAULT_SYSTEM_MESSAGE
|
|
73
|
+
);
|
|
74
|
+
} else {
|
|
75
|
+
return (
|
|
76
|
+
components.SystemMessage ??
|
|
77
|
+
(components.Message as ComponentType) ??
|
|
78
|
+
DEFAULT_SYSTEM_MESSAGE
|
|
79
|
+
);
|
|
80
|
+
}
|
|
81
|
+
default: {
|
|
82
|
+
const _exhaustiveCheck: never = role;
|
|
83
|
+
throw new Error(`Unknown message role: ${_exhaustiveCheck}`);
|
|
84
|
+
}
|
|
85
|
+
}
|
|
86
|
+
};
|
|
87
|
+
|
|
88
|
+
const ThreadMessageComponent: FC<{ components: MessageComponents }> = ({
|
|
89
|
+
components,
|
|
19
90
|
}) => {
|
|
20
|
-
const
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
}),
|
|
26
|
-
});
|
|
27
|
-
|
|
28
|
-
return <AuiProvider value={aui}>{children}</AuiProvider>;
|
|
91
|
+
const role = useAuiState((s) => s.message.role);
|
|
92
|
+
const isEditing = useAuiState((s) => s.message.composer.isEditing);
|
|
93
|
+
const Component = getComponent(components, role, isEditing);
|
|
94
|
+
|
|
95
|
+
return <Component />;
|
|
29
96
|
};
|
|
30
97
|
|
|
31
|
-
|
|
32
|
-
|
|
98
|
+
const isComponentsSame = (prev: MessageComponents, next: MessageComponents) => {
|
|
99
|
+
return (
|
|
100
|
+
prev.Message === next.Message &&
|
|
101
|
+
prev.EditComposer === next.EditComposer &&
|
|
102
|
+
prev.UserEditComposer === next.UserEditComposer &&
|
|
103
|
+
prev.AssistantEditComposer === next.AssistantEditComposer &&
|
|
104
|
+
prev.SystemEditComposer === next.SystemEditComposer &&
|
|
105
|
+
prev.UserMessage === next.UserMessage &&
|
|
106
|
+
prev.AssistantMessage === next.AssistantMessage &&
|
|
107
|
+
prev.SystemMessage === next.SystemMessage
|
|
108
|
+
);
|
|
109
|
+
};
|
|
110
|
+
|
|
111
|
+
const ThreadMessageByIndex = memo(
|
|
112
|
+
({ index, components }: { index: number; components: MessageComponents }) => {
|
|
113
|
+
return (
|
|
114
|
+
<MessageByIndexProvider index={index}>
|
|
115
|
+
<ThreadMessageComponent components={components} />
|
|
116
|
+
</MessageByIndexProvider>
|
|
117
|
+
);
|
|
118
|
+
},
|
|
119
|
+
(prev, next) =>
|
|
120
|
+
prev.index === next.index &&
|
|
121
|
+
isComponentsSame(prev.components, next.components),
|
|
122
|
+
);
|
|
123
|
+
|
|
124
|
+
export const ThreadMessages = ({ components }: ThreadMessagesProps) => {
|
|
125
|
+
const messagesLength = useAuiState((s) => s.thread.messages.length);
|
|
33
126
|
|
|
34
127
|
return (
|
|
35
128
|
<Box flexDirection="column">
|
|
36
|
-
{(
|
|
37
|
-
<
|
|
38
|
-
{
|
|
39
|
-
|
|
129
|
+
{Array.from({ length: messagesLength }, (_, index) => (
|
|
130
|
+
<ThreadMessageByIndex
|
|
131
|
+
key={index}
|
|
132
|
+
index={index}
|
|
133
|
+
components={components}
|
|
134
|
+
/>
|
|
40
135
|
))}
|
|
41
136
|
</Box>
|
|
42
137
|
);
|
|
@@ -1,16 +1,22 @@
|
|
|
1
|
-
export { ThreadRoot, type ThreadRootProps } from "./ThreadRoot";
|
|
2
|
-
export { ThreadMessages, type ThreadMessagesProps } from "./ThreadMessages";
|
|
3
1
|
export {
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
} from "
|
|
7
|
-
export {
|
|
8
|
-
|
|
2
|
+
ThreadRoot as Root,
|
|
3
|
+
type ThreadRootProps as RootProps,
|
|
4
|
+
} from "./ThreadRoot";
|
|
5
|
+
export {
|
|
6
|
+
ThreadMessages as Messages,
|
|
7
|
+
type ThreadMessagesProps as MessagesProps,
|
|
8
|
+
} from "./ThreadMessages";
|
|
9
|
+
export { ThreadPrimitiveMessageByIndex as MessageByIndex } from "@assistant-ui/core/react";
|
|
10
|
+
export {
|
|
11
|
+
ThreadEmpty as Empty,
|
|
12
|
+
type ThreadEmptyProps as EmptyProps,
|
|
13
|
+
} from "./ThreadEmpty";
|
|
14
|
+
export { ThreadIf as If, type ThreadIfProps as IfProps } from "./ThreadIf";
|
|
9
15
|
export {
|
|
10
|
-
ThreadSuggestion,
|
|
11
|
-
type ThreadSuggestionProps,
|
|
16
|
+
ThreadSuggestion as Suggestion,
|
|
17
|
+
type ThreadSuggestionProps as SuggestionProps,
|
|
12
18
|
} from "./ThreadSuggestion";
|
|
13
19
|
export {
|
|
14
|
-
ThreadPrimitiveSuggestions,
|
|
15
|
-
ThreadPrimitiveSuggestionByIndex,
|
|
20
|
+
ThreadPrimitiveSuggestions as Suggestions,
|
|
21
|
+
ThreadPrimitiveSuggestionByIndex as SuggestionByIndex,
|
|
16
22
|
} from "@assistant-ui/core/react";
|
|
@@ -1,3 +1,12 @@
|
|
|
1
|
-
export {
|
|
2
|
-
|
|
3
|
-
|
|
1
|
+
export {
|
|
2
|
+
ThreadListRoot as Root,
|
|
3
|
+
type ThreadListRootProps as RootProps,
|
|
4
|
+
} from "./ThreadListRoot";
|
|
5
|
+
export {
|
|
6
|
+
ThreadListItems as Items,
|
|
7
|
+
type ThreadListItemsProps as ItemsProps,
|
|
8
|
+
} from "./ThreadListItems";
|
|
9
|
+
export {
|
|
10
|
+
ThreadListNew as New,
|
|
11
|
+
type ThreadListNewProps as NewProps,
|
|
12
|
+
} from "./ThreadListNew";
|
|
@@ -1,21 +1,21 @@
|
|
|
1
1
|
export {
|
|
2
|
-
ThreadListItemRoot,
|
|
3
|
-
type ThreadListItemRootProps,
|
|
2
|
+
ThreadListItemRoot as Root,
|
|
3
|
+
type ThreadListItemRootProps as RootProps,
|
|
4
4
|
} from "./ThreadListItemRoot";
|
|
5
|
-
export { ThreadListItemPrimitiveTitle as
|
|
5
|
+
export { ThreadListItemPrimitiveTitle as Title } from "@assistant-ui/core/react";
|
|
6
6
|
export {
|
|
7
|
-
ThreadListItemTrigger,
|
|
8
|
-
type ThreadListItemTriggerProps,
|
|
7
|
+
ThreadListItemTrigger as Trigger,
|
|
8
|
+
type ThreadListItemTriggerProps as TriggerProps,
|
|
9
9
|
} from "./ThreadListItemTrigger";
|
|
10
10
|
export {
|
|
11
|
-
ThreadListItemDelete,
|
|
12
|
-
type ThreadListItemDeleteProps,
|
|
11
|
+
ThreadListItemDelete as Delete,
|
|
12
|
+
type ThreadListItemDeleteProps as DeleteProps,
|
|
13
13
|
} from "./ThreadListItemDelete";
|
|
14
14
|
export {
|
|
15
|
-
ThreadListItemArchive,
|
|
16
|
-
type ThreadListItemArchiveProps,
|
|
15
|
+
ThreadListItemArchive as Archive,
|
|
16
|
+
type ThreadListItemArchiveProps as ArchiveProps,
|
|
17
17
|
} from "./ThreadListItemArchive";
|
|
18
18
|
export {
|
|
19
|
-
ThreadListItemUnarchive,
|
|
20
|
-
type ThreadListItemUnarchiveProps,
|
|
19
|
+
ThreadListItemUnarchive as Unarchive,
|
|
20
|
+
type ThreadListItemUnarchiveProps as UnarchiveProps,
|
|
21
21
|
} from "./ThreadListItemUnarchive";
|
|
@@ -0,0 +1,40 @@
|
|
|
1
|
+
import type { ReactElement } from "react";
|
|
2
|
+
import { afterEach, describe, expect, it } from "vitest";
|
|
3
|
+
import { cleanup, render } from "ink-testing-library";
|
|
4
|
+
import { ToolFallback } from "./ToolFallback";
|
|
5
|
+
|
|
6
|
+
const renderFrame = async (node: ReactElement) => {
|
|
7
|
+
const instance = render(node);
|
|
8
|
+
await new Promise((resolve) => setTimeout(resolve, 0));
|
|
9
|
+
return instance.lastFrame() ?? "";
|
|
10
|
+
};
|
|
11
|
+
|
|
12
|
+
afterEach(() => {
|
|
13
|
+
cleanup();
|
|
14
|
+
});
|
|
15
|
+
|
|
16
|
+
describe("ToolFallback", () => {
|
|
17
|
+
it("truncates expanded error output with maxResultLines", async () => {
|
|
18
|
+
const frame = await renderFrame(
|
|
19
|
+
<ToolFallback
|
|
20
|
+
expanded
|
|
21
|
+
maxResultLines={2}
|
|
22
|
+
type="tool-call"
|
|
23
|
+
toolCallId="tool-call-1"
|
|
24
|
+
toolName="search"
|
|
25
|
+
args={{}}
|
|
26
|
+
argsText="{}"
|
|
27
|
+
result={"line 1\nline 2\nline 3\nline 4"}
|
|
28
|
+
isError
|
|
29
|
+
status={{ type: "incomplete", reason: "error", error: "boom" }}
|
|
30
|
+
/>,
|
|
31
|
+
);
|
|
32
|
+
|
|
33
|
+
expect(frame).toContain("Error:");
|
|
34
|
+
expect(frame).toContain("line 1");
|
|
35
|
+
expect(frame).toContain("line 2");
|
|
36
|
+
expect(frame).toContain("... (2 more lines)");
|
|
37
|
+
expect(frame).not.toContain("line 3");
|
|
38
|
+
expect(frame).not.toContain("line 4");
|
|
39
|
+
});
|
|
40
|
+
});
|