@nextclaw/ui 0.12.25 → 0.12.26
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/CHANGELOG.md +68 -0
- package/dist/assets/{channels-list-page-FJDuPwU6.js → channels-list-page-HgLgrEg4.js} +1 -1
- package/dist/assets/chat-page-DAKMFDrS.js +1 -0
- package/dist/assets/{desktop-kk7qvZ-v.js → desktop-DVUbOWbR.js} +1 -1
- package/dist/assets/{index-D-AAMKCt.js → index-Cuwst6cc.js} +34 -37
- package/dist/assets/index-dlcqieQ0.css +1 -0
- package/dist/assets/{marketplace-page-BrCLRIc4.js → marketplace-page-BeFbwxR-.js} +2 -2
- package/dist/assets/marketplace-page-CR4xq-TM.js +1 -0
- package/dist/assets/mcp-marketplace-page-DlRrSCj3.js +1 -0
- package/dist/assets/{mcp-marketplace-page-DIq_SpMe.js → mcp-marketplace-page-DwnaLNTx.js} +1 -1
- package/dist/assets/{model-config-Bc6VVnxy.js → model-config-L2l6YAlQ.js} +1 -1
- package/dist/assets/{providers-list-DN0tvISH.js → providers-list-DYAEunOp.js} +1 -1
- package/dist/assets/{runtime-config-page-CRWOwBbl.js → runtime-config-page-BdeU8PEK.js} +1 -1
- package/dist/assets/{search-config-C4c1yZSP.js → search-config-CQUhd5RU.js} +1 -1
- package/dist/assets/{secrets-config-zAF30YfO.js → secrets-config-D-NWlW9q.js} +1 -1
- package/dist/assets/{use-infinite-scroll-loader-Cvz8ZteY.js → use-infinite-scroll-loader-CFVdPpNv.js} +1 -1
- package/dist/index.html +3 -3
- package/package.json +9 -9
- package/src/features/agents/components/agents-page.test.tsx +1 -1
- package/src/features/agents/components/agents-page.tsx +1 -1
- package/src/features/chat/components/chat-session-workspace-panel.tsx +31 -45
- package/src/features/chat/components/chat-sidebar-session-item.tsx +7 -9
- package/src/features/chat/components/conversation/chat-conversation-header.test.tsx +5 -2
- package/src/features/chat/components/conversation/chat-conversation-header.tsx +2 -2
- package/src/features/chat/components/conversation/chat-conversation-panel.test.tsx +106 -78
- package/src/features/chat/components/conversation/chat-conversation-panel.tsx +172 -167
- package/src/features/chat/components/conversation/chat-input-bar.container.tsx +11 -1
- package/src/features/chat/components/conversation/session-header/chat-session-header-actions.tsx +2 -2
- package/src/features/chat/components/providers/chat-presenter.provider.tsx +2 -0
- package/src/features/chat/hooks/use-ncp-agent-runtime.test.tsx +147 -88
- package/src/features/chat/managers/ncp-chat-input.manager.test.ts +20 -0
- package/src/features/chat/managers/ncp-chat-input.manager.ts +18 -0
- package/src/features/chat/managers/ncp-chat-presenter.manager.ts +1 -0
- package/src/features/chat/pages/ncp-chat-page.tsx +4 -1
- package/src/features/chat/stores/chat-input.store.ts +3 -1
- package/src/features/chat/utils/ncp-chat-input-availability.utils.test.ts +1 -0
- package/src/platforms/desktop/components/desktop-app-shell.test.tsx +1 -0
- package/src/platforms/desktop/components/desktop-app-shell.tsx +1 -1
- package/dist/assets/chat-page-D1fMNBrT.js +0 -1
- package/dist/assets/index-DnBeV2Xm.css +0 -1
- package/dist/assets/marketplace-page-odDpPYEs.js +0 -1
- package/dist/assets/mcp-marketplace-page-CfbOBgKK.js +0 -1
|
@@ -48,33 +48,40 @@ vi.mock("@nextclaw/agent-chat-ui", async (importOriginal) => {
|
|
|
48
48
|
};
|
|
49
49
|
});
|
|
50
50
|
|
|
51
|
-
vi.mock(
|
|
52
|
-
|
|
53
|
-
|
|
51
|
+
vi.mock(
|
|
52
|
+
"@/features/chat/components/conversation/chat-input-bar.container",
|
|
53
|
+
() => ({
|
|
54
|
+
ChatInputBarContainer: () => <div data-testid="chat-input-bar" />,
|
|
55
|
+
}),
|
|
56
|
+
);
|
|
54
57
|
|
|
55
|
-
vi.mock(
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
58
|
+
vi.mock(
|
|
59
|
+
"@/features/chat/components/conversation/chat-message-list.container",
|
|
60
|
+
() => ({
|
|
61
|
+
ChatMessageListContainer: ({
|
|
62
|
+
isSending,
|
|
63
|
+
messages,
|
|
64
|
+
}: {
|
|
65
|
+
isSending: boolean;
|
|
66
|
+
messages: readonly unknown[];
|
|
67
|
+
}) => (
|
|
68
|
+
<div
|
|
69
|
+
data-testid="chat-message-list"
|
|
70
|
+
data-message-count={String(messages.length)}
|
|
71
|
+
data-sending={String(isSending)}
|
|
72
|
+
/>
|
|
73
|
+
),
|
|
74
|
+
}),
|
|
75
|
+
);
|
|
70
76
|
|
|
71
|
-
vi.mock(
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
})
|
|
77
|
+
vi.mock(
|
|
78
|
+
"@/features/chat/components/chat-session-workspace-file-preview",
|
|
79
|
+
() => ({
|
|
80
|
+
ChatSessionWorkspaceFilePreview: ({ file }: { file: { path: string } }) => (
|
|
81
|
+
<div data-testid="workspace-file-preview">{file.path}</div>
|
|
82
|
+
),
|
|
83
|
+
}),
|
|
84
|
+
);
|
|
78
85
|
|
|
79
86
|
vi.mock("@/features/chat/components/chat-welcome", () => ({
|
|
80
87
|
ChatWelcome: ({
|
|
@@ -123,10 +130,9 @@ vi.mock("@/features/chat/components/providers/chat-presenter.provider", () => ({
|
|
|
123
130
|
readAt: string | null | undefined,
|
|
124
131
|
) =>
|
|
125
132
|
sessionKey
|
|
126
|
-
? useChatSessionListStore
|
|
127
|
-
|
|
128
|
-
readAt
|
|
129
|
-
)
|
|
133
|
+
? useChatSessionListStore
|
|
134
|
+
.getState()
|
|
135
|
+
.markSessionRead(sessionKey, readAt)
|
|
130
136
|
: undefined,
|
|
131
137
|
},
|
|
132
138
|
chatInputManager: {
|
|
@@ -136,42 +142,44 @@ vi.mock("@/features/chat/components/providers/chat-presenter.provider", () => ({
|
|
|
136
142
|
}));
|
|
137
143
|
|
|
138
144
|
vi.mock("@/shared/hooks/use-config", () => ({
|
|
139
|
-
useCronJobs: () => ({
|
|
145
|
+
useCronJobs: () => ({
|
|
146
|
+
data: { jobs: mocks.cronJobs, total: mocks.cronJobs.length },
|
|
147
|
+
}),
|
|
140
148
|
useDeleteCronJob: () => ({
|
|
141
149
|
mutate: mocks.deleteCronJob,
|
|
142
150
|
isPending: false,
|
|
143
151
|
}),
|
|
144
152
|
}));
|
|
145
153
|
|
|
146
|
-
vi.mock("@/features/chat/components/conversation/session-header/chat-session-header-actions", () => ({
|
|
147
|
-
ChatSessionHeaderActions: () => <button aria-label="More actions" />,
|
|
148
|
-
}));
|
|
149
|
-
|
|
150
|
-
vi.mock("@/features/chat/components/conversation/session-header/chat-session-project-badge", () => ({
|
|
151
|
-
ChatSessionProjectBadge: ({ projectName }: { projectName: string }) => (
|
|
152
|
-
<button>{projectName}</button>
|
|
153
|
-
),
|
|
154
|
-
}));
|
|
155
|
-
|
|
156
154
|
vi.mock(
|
|
157
|
-
"@/features/chat/
|
|
155
|
+
"@/features/chat/components/conversation/session-header/chat-session-header-actions",
|
|
158
156
|
() => ({
|
|
159
|
-
|
|
157
|
+
ChatSessionHeaderActions: () => <button aria-label="More actions" />,
|
|
160
158
|
}),
|
|
161
159
|
);
|
|
162
160
|
|
|
163
161
|
vi.mock(
|
|
164
|
-
"@/features/chat/
|
|
162
|
+
"@/features/chat/components/conversation/session-header/chat-session-project-badge",
|
|
165
163
|
() => ({
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
hydrateError: null,
|
|
170
|
-
isRunning: false,
|
|
171
|
-
}),
|
|
164
|
+
ChatSessionProjectBadge: ({ projectName }: { projectName: string }) => (
|
|
165
|
+
<button>{projectName}</button>
|
|
166
|
+
),
|
|
172
167
|
}),
|
|
173
168
|
);
|
|
174
169
|
|
|
170
|
+
vi.mock("@/features/chat/hooks/use-ncp-child-session-tabs-view", () => ({
|
|
171
|
+
useNcpChildSessionTabsView: () => mocks.resolvedChildTabs,
|
|
172
|
+
}));
|
|
173
|
+
|
|
174
|
+
vi.mock("@/features/chat/hooks/use-ncp-session-conversation", () => ({
|
|
175
|
+
useNcpSessionConversation: () => ({
|
|
176
|
+
visibleMessages: [],
|
|
177
|
+
isHydrating: false,
|
|
178
|
+
hydrateError: null,
|
|
179
|
+
isRunning: false,
|
|
180
|
+
}),
|
|
181
|
+
}));
|
|
182
|
+
|
|
175
183
|
vi.mock("@/shared/components/common/agent-avatar", () => ({
|
|
176
184
|
AgentAvatar: ({ agentId }: { agentId: string }) => (
|
|
177
185
|
<div data-testid="agent-avatar">{agentId}</div>
|
|
@@ -278,7 +286,9 @@ describe("ChatConversationPanel", () => {
|
|
|
278
286
|
|
|
279
287
|
render(<ChatConversationPanel layoutMode="mobile" />);
|
|
280
288
|
|
|
281
|
-
await user.click(
|
|
289
|
+
await user.click(
|
|
290
|
+
screen.getByRole("button", { name: "create draft session" }),
|
|
291
|
+
);
|
|
282
292
|
|
|
283
293
|
expect(mocks.createSession).toHaveBeenCalledWith("native");
|
|
284
294
|
expect(mocks.goToChatRoot).toHaveBeenCalledTimes(1);
|
|
@@ -365,13 +375,47 @@ describe("ChatConversationPanel", () => {
|
|
|
365
375
|
expect(
|
|
366
376
|
screen.queryByRole("status", { name: "Loading session history..." }),
|
|
367
377
|
).toBeNull();
|
|
368
|
-
expect(
|
|
378
|
+
expect(
|
|
379
|
+
screen.queryByText("No messages yet. Send one to start."),
|
|
380
|
+
).toBeNull();
|
|
369
381
|
});
|
|
370
382
|
|
|
371
383
|
it("keeps the message list mounted while waiting for the first assistant token", () => {
|
|
372
384
|
useChatThreadStore.setState({
|
|
373
385
|
snapshot: {
|
|
374
386
|
...useChatThreadStore.getState().snapshot,
|
|
387
|
+
sessionKey: "session-1",
|
|
388
|
+
messages: [
|
|
389
|
+
{
|
|
390
|
+
id: "user-1",
|
|
391
|
+
sessionId: "session-1",
|
|
392
|
+
role: "user",
|
|
393
|
+
status: "final",
|
|
394
|
+
parts: [{ type: "text", text: "hello" }],
|
|
395
|
+
timestamp: "2026-05-19T00:00:00.000Z",
|
|
396
|
+
} as never,
|
|
397
|
+
],
|
|
398
|
+
isSending: true,
|
|
399
|
+
isAwaitingAssistantOutput: true,
|
|
400
|
+
},
|
|
401
|
+
});
|
|
402
|
+
|
|
403
|
+
render(<ChatConversationPanel />);
|
|
404
|
+
|
|
405
|
+
expect(screen.getByTestId("chat-message-list").dataset).toMatchObject({
|
|
406
|
+
messageCount: "1",
|
|
407
|
+
sending: "true",
|
|
408
|
+
});
|
|
409
|
+
expect(
|
|
410
|
+
screen.queryByText("No messages yet. Send one to start."),
|
|
411
|
+
).toBeNull();
|
|
412
|
+
});
|
|
413
|
+
|
|
414
|
+
it("does not show assistant waiting copy before the first message is visible", () => {
|
|
415
|
+
useChatThreadStore.setState({
|
|
416
|
+
snapshot: {
|
|
417
|
+
...useChatThreadStore.getState().snapshot,
|
|
418
|
+
sessionKey: "session-1",
|
|
375
419
|
messages: [],
|
|
376
420
|
isSending: true,
|
|
377
421
|
isAwaitingAssistantOutput: true,
|
|
@@ -380,8 +424,10 @@ describe("ChatConversationPanel", () => {
|
|
|
380
424
|
|
|
381
425
|
render(<ChatConversationPanel />);
|
|
382
426
|
|
|
383
|
-
expect(screen.
|
|
384
|
-
expect(
|
|
427
|
+
expect(screen.queryByTestId("chat-message-list")).toBeNull();
|
|
428
|
+
expect(
|
|
429
|
+
screen.queryByText("No messages yet. Send one to start."),
|
|
430
|
+
).toBeNull();
|
|
385
431
|
});
|
|
386
432
|
|
|
387
433
|
it("does not reopen the welcome panel after a root draft send fails", () => {
|
|
@@ -399,7 +445,9 @@ describe("ChatConversationPanel", () => {
|
|
|
399
445
|
render(<ChatConversationPanel />);
|
|
400
446
|
|
|
401
447
|
expect(screen.queryByTestId("chat-welcome")).toBeNull();
|
|
402
|
-
expect(
|
|
448
|
+
expect(
|
|
449
|
+
screen.queryByText("No messages yet. Send one to start."),
|
|
450
|
+
).toBeNull();
|
|
403
451
|
});
|
|
404
452
|
|
|
405
453
|
it("does not render runtime lifecycle copy in the conversation alert strip", () => {
|
|
@@ -491,6 +539,7 @@ describe("ChatSessionWorkspacePanel", () => {
|
|
|
491
539
|
|
|
492
540
|
render(
|
|
493
541
|
<ChatSessionWorkspacePanel
|
|
542
|
+
sessionKey="parent-session-1"
|
|
494
543
|
childSessionTabs={[
|
|
495
544
|
{
|
|
496
545
|
sessionKey: "child-session-1",
|
|
@@ -503,12 +552,6 @@ describe("ChatSessionWorkspacePanel", () => {
|
|
|
503
552
|
workspaceFileTabs={[]}
|
|
504
553
|
activeWorkspaceFileKey={null}
|
|
505
554
|
sessionProjectRoot="/Users/demo/project-alpha"
|
|
506
|
-
onSelectSession={vi.fn()}
|
|
507
|
-
onSelectFile={vi.fn()}
|
|
508
|
-
onCloseFile={vi.fn()}
|
|
509
|
-
onClose={vi.fn()}
|
|
510
|
-
onBackToParent={vi.fn()}
|
|
511
|
-
onFileOpen={vi.fn()}
|
|
512
555
|
/>,
|
|
513
556
|
);
|
|
514
557
|
|
|
@@ -559,6 +602,7 @@ describe("ChatSessionWorkspacePanel", () => {
|
|
|
559
602
|
|
|
560
603
|
render(
|
|
561
604
|
<ChatSessionWorkspacePanel
|
|
605
|
+
sessionKey="parent-session-1"
|
|
562
606
|
childSessionTabs={[
|
|
563
607
|
{
|
|
564
608
|
sessionKey: "child-session-1",
|
|
@@ -577,12 +621,6 @@ describe("ChatSessionWorkspacePanel", () => {
|
|
|
577
621
|
workspaceFileTabs={[]}
|
|
578
622
|
activeWorkspaceFileKey={null}
|
|
579
623
|
sessionProjectRoot="/Users/demo/project-alpha"
|
|
580
|
-
onSelectSession={vi.fn()}
|
|
581
|
-
onSelectFile={vi.fn()}
|
|
582
|
-
onCloseFile={vi.fn()}
|
|
583
|
-
onClose={vi.fn()}
|
|
584
|
-
onBackToParent={vi.fn()}
|
|
585
|
-
onFileOpen={vi.fn()}
|
|
586
624
|
/>,
|
|
587
625
|
);
|
|
588
626
|
|
|
@@ -592,6 +630,7 @@ describe("ChatSessionWorkspacePanel", () => {
|
|
|
592
630
|
it("shows opened files as top tabs and renders the file preview pane", () => {
|
|
593
631
|
render(
|
|
594
632
|
<ChatSessionWorkspacePanel
|
|
633
|
+
sessionKey="parent-session-1"
|
|
595
634
|
childSessionTabs={[]}
|
|
596
635
|
activeChildSessionKey={null}
|
|
597
636
|
workspaceFileTabs={[
|
|
@@ -605,12 +644,6 @@ describe("ChatSessionWorkspacePanel", () => {
|
|
|
605
644
|
]}
|
|
606
645
|
activeWorkspaceFileKey="parent-session-1::preview::README.md"
|
|
607
646
|
sessionProjectRoot="/Users/demo/project-alpha"
|
|
608
|
-
onSelectSession={vi.fn()}
|
|
609
|
-
onSelectFile={vi.fn()}
|
|
610
|
-
onCloseFile={vi.fn()}
|
|
611
|
-
onClose={vi.fn()}
|
|
612
|
-
onBackToParent={vi.fn()}
|
|
613
|
-
onFileOpen={vi.fn()}
|
|
614
647
|
/>,
|
|
615
648
|
);
|
|
616
649
|
|
|
@@ -649,6 +682,7 @@ describe("ChatSessionWorkspacePanel", () => {
|
|
|
649
682
|
|
|
650
683
|
render(
|
|
651
684
|
<ChatSessionWorkspacePanel
|
|
685
|
+
sessionKey="parent-session-1"
|
|
652
686
|
childSessionTabs={[]}
|
|
653
687
|
activeChildSessionKey={null}
|
|
654
688
|
workspaceFileTabs={[]}
|
|
@@ -656,12 +690,6 @@ describe("ChatSessionWorkspacePanel", () => {
|
|
|
656
690
|
activePanelKind="cron"
|
|
657
691
|
sessionCronJobs={[job]}
|
|
658
692
|
sessionProjectRoot="/Users/demo/project-alpha"
|
|
659
|
-
onSelectSession={vi.fn()}
|
|
660
|
-
onSelectFile={vi.fn()}
|
|
661
|
-
onCloseFile={vi.fn()}
|
|
662
|
-
onClose={vi.fn()}
|
|
663
|
-
onBackToParent={vi.fn()}
|
|
664
|
-
onFileOpen={vi.fn()}
|
|
665
693
|
/>,
|
|
666
694
|
);
|
|
667
695
|
|