@nextclaw/ui 0.15.23 → 0.15.25
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 +38 -0
- package/dist/assets/{api-Glw2OGXK.js → api-FK7tikI1.js} +4 -4
- package/dist/assets/appearance-settings-page-BYbvl2wj.js +1 -0
- package/dist/assets/{channels-list-page-C7E4Sxwd.js → channels-list-page-CocdcIko.js} +2 -2
- package/dist/assets/{chat-page-BT6dNI-4.js → chat-page-C5E-LLVd.js} +1 -1
- package/dist/assets/config-split-page-CA_a0AJ5.js +1 -0
- package/dist/assets/confirm-dialog-CxZfenjK.js +5 -0
- package/dist/assets/desktop-update-config-BEKC8Ly9.js +1 -0
- package/dist/assets/{dist-dv_SUR54.js → dist-BH7W5yCi.js} +1 -1
- package/dist/assets/{dist-CtLyEJeO.js → dist-CaYdVVeO.js} +1 -1
- package/dist/assets/doc-browser-Cl2ldE3f.js +1 -0
- package/dist/assets/doc-browser-DXCSd63E.js +1 -0
- package/dist/assets/{doc-browser-context-BIBjkwfV.js → doc-browser-context-FDPs3gJf.js} +1 -1
- package/dist/assets/form-actions-0c0aw_bl.js +1 -0
- package/dist/assets/i18n-provider-DkITJNz8.js +1 -0
- package/dist/assets/index-CQ2LcI2p.css +1 -0
- package/dist/assets/index-CrdfvBVg.js +107 -0
- package/dist/assets/loader-circle-DHtUxCIA.js +1 -0
- package/dist/assets/mcp-marketplace-page-Bc_jI5iH.js +9 -0
- package/dist/assets/mcp-marketplace-page-CzCieD9r.js +1 -0
- package/dist/assets/model-config-page-C4jw-pcj.js +1 -0
- package/dist/assets/{navigation-link-CB0OQbnY.js → navigation-link-CVy0_kVl.js} +2 -2
- package/dist/assets/plus-CG1RwZQq.js +1 -0
- package/dist/assets/provider-scoped-model-input-CmH4BFvc.js +1 -0
- package/dist/assets/providers-config-page-CJQjwzaw.js +1 -0
- package/dist/assets/react-DjFBVA0n.js +8 -0
- package/dist/assets/{refresh-cw-Ba0LZou4.js → refresh-cw-j2bl79Ea.js} +1 -1
- package/dist/assets/remote-BIlpD3yL.js +1 -0
- package/dist/assets/rotate-cw-bKG8zH8M.js +1 -0
- package/dist/assets/runtime-config-page-B_x2Glz5.js +1 -0
- package/dist/assets/{save-DTOAvqzt.js → save-BKNrtK81.js} +1 -1
- package/dist/assets/{search-D4X5DNMe.js → search-CkOm65W_.js} +1 -1
- package/dist/assets/{search-config-page-Cr6254K5.js → search-config-page-BaIijtmO.js} +1 -1
- package/dist/assets/{secrets-config-page-W2Hx332d.js → secrets-config-page-CJjtdFAl.js} +2 -2
- package/dist/assets/security-config-DB8apj09.js +1 -0
- package/dist/assets/{select-CDv0g2Pj.js → select-Ea7ffKCE.js} +2 -2
- package/dist/assets/{settings-2-CoxzNABp.js → settings-2-CtyN3m_V.js} +1 -1
- package/dist/assets/skeleton-Bt6zxcAB.js +1 -0
- package/dist/assets/{tag-chip-CjkZEoS2.js → tag-chip-C9l4xsKp.js} +1 -1
- package/dist/assets/x-CowtCu9Z.js +1 -0
- package/dist/index.html +20 -20
- package/package.json +8 -8
- package/src/features/chat/features/conversation/components/__tests__/session-conversation-area.test.tsx +30 -1
- package/src/features/chat/features/conversation/components/session-conversation-area.tsx +1 -1
- package/src/features/chat/features/conversation/hooks/__tests__/use-session-provider-model-catalog.test.tsx +54 -2
- package/src/features/chat/features/conversation/hooks/use-chat-composer-reference-intent.ts +10 -1
- package/src/features/chat/features/conversation/hooks/use-session-provider-model-catalog.ts +76 -1
- package/src/features/chat/features/conversation/utils/session-conversation-input-toolbar.utils.ts +6 -1
- package/src/features/chat/features/input/utils/__tests__/chat-inline-token.utils.test.ts +29 -0
- package/src/features/chat/features/input/utils/__tests__/chat-input-bar.utils.test.ts +12 -3
- package/src/features/chat/features/input/utils/chat-composer-token-protocol.utils.ts +5 -0
- package/src/features/chat/features/input/utils/chat-conversation-excerpt-token.utils.ts +59 -0
- package/src/features/chat/features/input/utils/chat-inline-token.utils.ts +42 -16
- package/src/features/chat/features/input/utils/chat-input-toolbar.utils.ts +50 -14
- package/src/features/chat/features/message/components/chat-message-list.container.tsx +40 -0
- package/src/features/chat/features/message/utils/chat-message-texts.utils.ts +5 -0
- package/src/features/chat/features/ncp/hooks/__tests__/use-hydrated-ncp-agent.test.tsx +40 -3
- package/src/features/chat/features/workspace/components/__tests__/chat-session-workspace-file-preview.selection.test.tsx +66 -0
- package/src/features/chat/features/workspace/components/__tests__/chat-session-workspace-file-preview.test.tsx +13 -1
- package/src/features/chat/features/workspace/components/__tests__/chat-session-workspace-panel-content.test.tsx +573 -90
- package/src/features/chat/features/workspace/components/__tests__/workspace-text-selection-menu.test.tsx +11 -4
- package/src/features/chat/features/workspace/components/chat-session-workspace-directory-browser.tsx +389 -288
- package/src/features/chat/features/workspace/components/chat-session-workspace-file-breadcrumbs.tsx +54 -35
- package/src/features/chat/features/workspace/components/chat-session-workspace-file-preview.tsx +79 -148
- package/src/features/chat/features/workspace/components/chat-session-workspace-panel-content.tsx +149 -94
- package/src/features/chat/features/workspace/components/project-files/__tests__/workspace-directory-entry-menu.test.tsx +50 -0
- package/src/features/chat/features/workspace/components/project-files/workspace-directory-entry-menu.tsx +209 -0
- package/src/features/chat/features/workspace/components/project-files/workspace-directory-tree.tsx +411 -0
- package/src/features/chat/features/workspace/components/project-files/workspace-new-folder-tree-item.tsx +112 -0
- package/src/features/chat/features/workspace/components/project-files/workspace-project-files-toolbar.tsx +64 -0
- package/src/features/chat/features/workspace/components/workspace-text-selection-menu.tsx +17 -195
- package/src/features/chat/features/workspace/hooks/use-workspace-explorer-layout.ts +88 -0
- package/src/features/chat/features/workspace/hooks/use-workspace-file-actions.ts +335 -0
- package/src/features/chat/features/workspace/utils/chat-workspace-file-path-mutation.utils.ts +58 -0
- package/src/features/chat/features/workspace/utils/chat-workspace-file-tab.utils.ts +23 -22
- package/src/features/chat/features/workspace/utils/chat-workspace-panel-layout.utils.ts +13 -4
- package/src/features/chat/managers/__tests__/chat-composer-intent.manager.test.ts +94 -45
- package/src/features/chat/managers/__tests__/chat-thread.manager.test.ts +103 -99
- package/src/features/chat/managers/chat-composer-intent.manager.ts +83 -34
- package/src/features/chat/managers/chat-thread.manager.ts +132 -128
- package/src/features/chat/stores/__tests__/chat-thread.store.test.ts +20 -40
- package/src/features/chat/stores/chat-thread.store.ts +47 -74
- package/src/features/chat/types/chat-input-bar.types.ts +3 -0
- package/src/features/side-dock/components/__tests__/side-dock.test.tsx +1 -0
- package/src/features/side-dock/configs/side-dock-built-in-items.config.ts +0 -9
- package/src/shared/components/resizable-right-panel/__tests__/resizable-right-panel.test.tsx +35 -38
- package/src/shared/components/resizable-right-panel/resizable-right-panel.tsx +25 -19
- package/src/shared/components/ui/context-menu/__tests__/context-menu.test.tsx +60 -34
- package/src/shared/components/ui/context-menu/context-menu.tsx +95 -68
- package/src/shared/lib/api/managers/client.manager.ts +31 -17
- package/src/shared/lib/api/server-path/server-path.types.ts +66 -0
- package/src/shared/lib/api/types.ts +145 -116
- package/src/shared/lib/api/utils/server-path.utils.ts +35 -11
- package/src/shared/lib/i18n/locales/en-US/chat.json +49 -1
- package/src/shared/lib/i18n/locales/zh-CN/chat.json +49 -1
- package/dist/assets/appearance-settings-page-Bl_W_9m7.js +0 -1
- package/dist/assets/config-split-page-D5BgtKrm.js +0 -1
- package/dist/assets/confirm-dialog-Bf907Azu.js +0 -5
- package/dist/assets/desktop-update-config-BwuyBPJb.js +0 -1
- package/dist/assets/doc-browser-C23NDGh5.js +0 -1
- package/dist/assets/doc-browser-DlOOhBxI.js +0 -1
- package/dist/assets/form-actions-DAzi68Cn.js +0 -1
- package/dist/assets/index-BLNg2yg0.css +0 -1
- package/dist/assets/index-D3EKjEyK.js +0 -107
- package/dist/assets/loader-circle-BSg5u0r4.js +0 -1
- package/dist/assets/mcp-marketplace-page-ByhvQQj5.js +0 -9
- package/dist/assets/mcp-marketplace-page-CytXwnUs.js +0 -1
- package/dist/assets/model-config-page-bgEx3MjQ.js +0 -1
- package/dist/assets/plus-CNjWdLhZ.js +0 -1
- package/dist/assets/provider-scoped-model-input-8F6JMd2n.js +0 -1
- package/dist/assets/providers-config-page-CxpTjR81.js +0 -1
- package/dist/assets/react-Bk2ydNTe.js +0 -8
- package/dist/assets/remote-Dv38PuMV.js +0 -1
- package/dist/assets/rotate-cw-IkYVk9JX.js +0 -1
- package/dist/assets/runtime-config-page-C0ByyUVr.js +0 -1
- package/dist/assets/security-config-1E8OF4kR.js +0 -1
- package/dist/assets/skeleton-DW018fJv.js +0 -1
- package/dist/assets/use-confirm-dialog-CavtY1vJ.js +0 -1
- package/dist/assets/x-PTXYTEwz.js +0 -1
|
@@ -145,6 +145,8 @@ export function buildChatMessageTexts(
|
|
|
145
145
|
): ChatMessageTexts {
|
|
146
146
|
void language;
|
|
147
147
|
return {
|
|
148
|
+
addSelectionToChatLabel: t("chatWorkspaceAddToChat"),
|
|
149
|
+
selectionTooLongLabel: t("chatWorkspaceExcerptSelectionTooLong"),
|
|
148
150
|
copyCodeLabel: t("chatCodeCopy"),
|
|
149
151
|
copiedCodeLabel: t("chatCodeCopied"),
|
|
150
152
|
copyMessageLabel: t("chatMessageCopy"),
|
|
@@ -154,6 +156,9 @@ export function buildChatMessageTexts(
|
|
|
154
156
|
mermaidExpandLabel: t("chatMermaidExpand"),
|
|
155
157
|
mermaidLoadingLabel: t("chatMermaidLoading"),
|
|
156
158
|
mermaidRenderErrorLabel: t("chatMermaidRenderError"),
|
|
159
|
+
previewZoomInLabel: t("chatPreviewZoomIn"),
|
|
160
|
+
previewZoomOutLabel: t("chatPreviewZoomOut"),
|
|
161
|
+
previewResetZoomLabel: t("chatPreviewResetZoom"),
|
|
157
162
|
typingLabel: t("chatTyping"),
|
|
158
163
|
reasoningCharacterCountTemplates: {
|
|
159
164
|
inProgress: t("chatReasoningInProgressCharacterCount"),
|
|
@@ -248,10 +248,9 @@ describe("useHydratedNcpAgent", () => {
|
|
|
248
248
|
);
|
|
249
249
|
|
|
250
250
|
await vi.waitFor(() => {
|
|
251
|
-
expect(
|
|
252
|
-
"stream disconnected",
|
|
253
|
-
);
|
|
251
|
+
expect(mocks.stream).toHaveBeenCalledTimes(1);
|
|
254
252
|
});
|
|
253
|
+
expect(result.current.hydrateError).toBeNull();
|
|
255
254
|
await act(async () => {
|
|
256
255
|
await vi.runOnlyPendingTimersAsync();
|
|
257
256
|
});
|
|
@@ -268,4 +267,42 @@ describe("useHydratedNcpAgent", () => {
|
|
|
268
267
|
vi.useRealTimers();
|
|
269
268
|
}
|
|
270
269
|
});
|
|
270
|
+
|
|
271
|
+
it("reports a stream error only after repeated immediate recovery failures", async () => {
|
|
272
|
+
vi.useFakeTimers();
|
|
273
|
+
try {
|
|
274
|
+
const client = {
|
|
275
|
+
stop: mocks.stop.mockResolvedValue(undefined),
|
|
276
|
+
stream: mocks.stream.mockRejectedValue(new Error("stream unavailable")),
|
|
277
|
+
subscribe: vi.fn(() => () => {}),
|
|
278
|
+
send: mocks.send,
|
|
279
|
+
} as unknown as NcpAgentClientEndpoint;
|
|
280
|
+
const loadSeed = vi.fn().mockResolvedValue({ messages: [], status: "idle" });
|
|
281
|
+
const { result } = renderHook(() =>
|
|
282
|
+
useHydratedNcpAgent({
|
|
283
|
+
sessionId: "session-offline",
|
|
284
|
+
client: client as never,
|
|
285
|
+
loadSeed,
|
|
286
|
+
}),
|
|
287
|
+
);
|
|
288
|
+
|
|
289
|
+
await vi.waitFor(() => expect(mocks.stream).toHaveBeenCalledTimes(1));
|
|
290
|
+
expect(result.current.hydrateError).toBeNull();
|
|
291
|
+
|
|
292
|
+
await act(async () => {
|
|
293
|
+
await vi.runOnlyPendingTimersAsync();
|
|
294
|
+
});
|
|
295
|
+
await vi.waitFor(() => expect(mocks.stream).toHaveBeenCalledTimes(2));
|
|
296
|
+
expect(result.current.hydrateError).toBeNull();
|
|
297
|
+
|
|
298
|
+
await act(async () => {
|
|
299
|
+
await vi.runOnlyPendingTimersAsync();
|
|
300
|
+
});
|
|
301
|
+
await vi.waitFor(() => {
|
|
302
|
+
expect(result.current.hydrateError?.message).toBe("stream unavailable");
|
|
303
|
+
});
|
|
304
|
+
} finally {
|
|
305
|
+
vi.useRealTimers();
|
|
306
|
+
}
|
|
307
|
+
});
|
|
271
308
|
});
|
|
@@ -0,0 +1,66 @@
|
|
|
1
|
+
import type { ReactNode } from "react";
|
|
2
|
+
import { fireEvent, render, screen } from "@testing-library/react";
|
|
3
|
+
import { describe, expect, it, vi } from "vitest";
|
|
4
|
+
import { ChatSessionWorkspaceFilePreview } from "@/features/chat/features/workspace/components/chat-session-workspace-file-preview";
|
|
5
|
+
|
|
6
|
+
const onTextExcerptAdd = vi.fn();
|
|
7
|
+
|
|
8
|
+
vi.mock("@/shared/hooks/use-server-path-read", () => ({
|
|
9
|
+
useServerPathRead: () => ({
|
|
10
|
+
isLoading: false,
|
|
11
|
+
error: null,
|
|
12
|
+
data: {
|
|
13
|
+
kind: "markdown",
|
|
14
|
+
resolvedPath: "/Users/demo/.nextclaw/workspace/BOOT.md",
|
|
15
|
+
startLine: 1,
|
|
16
|
+
text: "Add short, explicit startup instructions.",
|
|
17
|
+
truncated: false,
|
|
18
|
+
},
|
|
19
|
+
}),
|
|
20
|
+
}));
|
|
21
|
+
|
|
22
|
+
vi.mock("@/shared/hooks/use-server-path-browse", () => ({
|
|
23
|
+
useServerPathBrowse: () => ({ isLoading: false, error: new Error("not a directory"), data: null }),
|
|
24
|
+
}));
|
|
25
|
+
|
|
26
|
+
vi.mock("@nextclaw/agent-chat-ui", () => ({
|
|
27
|
+
ChatMessageMarkdown: ({ text }: { text: string }) => <div>{text}</div>,
|
|
28
|
+
FileOperationCodeSurface: () => null,
|
|
29
|
+
ChatTextSelectionAction: ({ children, onAddToChat }: { children: ReactNode; onAddToChat: (value: { text: string }) => void }) => (
|
|
30
|
+
<div>
|
|
31
|
+
{children}
|
|
32
|
+
<button type="button" onClick={() => onAddToChat({ text: "Add short, explicit startup instructions." })}>
|
|
33
|
+
select excerpt
|
|
34
|
+
</button>
|
|
35
|
+
</div>
|
|
36
|
+
),
|
|
37
|
+
}));
|
|
38
|
+
|
|
39
|
+
describe("ChatSessionWorkspaceFilePreview selection", () => {
|
|
40
|
+
it("uses the resolved absolute path when a shell-style workspace root cannot be compared in the browser", () => {
|
|
41
|
+
render(
|
|
42
|
+
<ChatSessionWorkspaceFilePreview
|
|
43
|
+
file={{
|
|
44
|
+
key: "boot",
|
|
45
|
+
parentSessionKey: null,
|
|
46
|
+
path: "/Users/demo/.nextclaw/workspace/BOOT.md",
|
|
47
|
+
label: "BOOT.md",
|
|
48
|
+
viewMode: "preview",
|
|
49
|
+
}}
|
|
50
|
+
sessionProjectRoot="~/.nextclaw/workspace"
|
|
51
|
+
sessionWorkingDir="~/.nextclaw/workspace"
|
|
52
|
+
onFileOpen={vi.fn()}
|
|
53
|
+
onTextExcerptAdd={onTextExcerptAdd}
|
|
54
|
+
/>,
|
|
55
|
+
);
|
|
56
|
+
|
|
57
|
+
fireEvent.click(screen.getByRole("button", { name: "select excerpt" }));
|
|
58
|
+
expect(onTextExcerptAdd).toHaveBeenCalledWith({
|
|
59
|
+
path: "/Users/demo/.nextclaw/workspace/BOOT.md",
|
|
60
|
+
label: "BOOT.md",
|
|
61
|
+
excerpt: "Add short, explicit startup instructions.",
|
|
62
|
+
startLine: 1,
|
|
63
|
+
endLine: 1,
|
|
64
|
+
});
|
|
65
|
+
});
|
|
66
|
+
});
|
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import { fireEvent, render, screen, waitFor } from "@testing-library/react";
|
|
2
|
+
import type { ReactNode } from "react";
|
|
2
3
|
import { afterEach, beforeEach, describe, expect, it, vi } from "vitest";
|
|
3
4
|
import type {
|
|
4
5
|
ChatFileOpenActionViewModel,
|
|
@@ -38,6 +39,7 @@ vi.mock("@/shared/hooks/use-server-path-browse", () => ({
|
|
|
38
39
|
}));
|
|
39
40
|
|
|
40
41
|
vi.mock("@nextclaw/agent-chat-ui", () => ({
|
|
42
|
+
ChatTextSelectionAction: ({ children }: { children: ReactNode }) => children,
|
|
41
43
|
ChatMessageMarkdown: ({ text }: { text: string }) => (
|
|
42
44
|
<div data-testid="markdown-preview">{text}</div>
|
|
43
45
|
),
|
|
@@ -56,6 +58,16 @@ vi.mock("@nextclaw/agent-chat-ui", () => ({
|
|
|
56
58
|
),
|
|
57
59
|
}));
|
|
58
60
|
|
|
61
|
+
vi.mock("@/features/chat/components/providers/chat-presenter.provider", () => ({
|
|
62
|
+
usePresenter: () => ({
|
|
63
|
+
chatThreadManager: { removeWorkspacePath: vi.fn(), renameWorkspacePath: vi.fn() },
|
|
64
|
+
chatComposerIntentManager: {
|
|
65
|
+
requestDirectoryReference: vi.fn(),
|
|
66
|
+
requestFileReference: vi.fn(),
|
|
67
|
+
},
|
|
68
|
+
}),
|
|
69
|
+
}));
|
|
70
|
+
|
|
59
71
|
vi.mock("docx-preview", () => ({
|
|
60
72
|
renderAsync: (...args: unknown[]) => renderDocxMock(...args),
|
|
61
73
|
}));
|
|
@@ -787,7 +799,7 @@ describe("ChatSessionWorkspaceFilePreview breadcrumbs", () => {
|
|
|
787
799
|
screen.getByTestId("workspace-file-breadcrumb-scroll").className,
|
|
788
800
|
).toContain("py-1.5");
|
|
789
801
|
expect(
|
|
790
|
-
screen.getByTestId("workspace-file-
|
|
802
|
+
screen.getByTestId("workspace-file-breadcrumb-scroll").className,
|
|
791
803
|
).toContain("workspace-horizontal-scrollbar");
|
|
792
804
|
});
|
|
793
805
|
|