@nextclaw/ui 0.14.1-beta.0 → 0.14.1-beta.1
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 +18 -0
- package/dist/assets/{api-C6EDHBDR.js → api-dQ6uQSZG.js} +3 -3
- package/dist/assets/{channels-list-page-DKj6m1Hc.js → channels-list-page-DfpjB8XB.js} +2 -2
- package/dist/assets/chat-page-D3QaEqjs.js +105 -0
- package/dist/assets/{config-split-page-CjlmJy8X.js → config-split-page-CeFfbaqc.js} +1 -1
- package/dist/assets/{confirm-dialog-B39X0pYp.js → confirm-dialog-C95Y4QPC.js} +1 -1
- package/dist/assets/{desktop-update-config-DfUQ8nly.js → desktop-update-config-CcK6jiEb.js} +1 -1
- package/dist/assets/{dist-CmMro3nV.js → dist-DTGzeil6.js} +1 -1
- package/dist/assets/{dist-BIYV2-Ia.js → dist-fGogBmPA.js} +1 -1
- package/dist/assets/doc-browser-CuBTcBEZ.js +1 -0
- package/dist/assets/{doc-browser-CDtUtcim.js → doc-browser-DVHhEb96.js} +1 -1
- package/dist/assets/{doc-browser-context-DZbC9zVB.js → doc-browser-context-BfMXwnrz.js} +1 -1
- package/dist/assets/{ellipsis-DDpgTzgx.js → ellipsis-D2F4KMiU.js} +1 -1
- package/dist/assets/{external-link-D2cBOCqn.js → external-link-CcgtBK26.js} +1 -1
- package/dist/assets/index-ByJCbQqr.css +1 -0
- package/dist/assets/index-DjXqiloY.js +103 -0
- package/dist/assets/mcp-marketplace-page-98-V__3u.js +1 -0
- package/dist/assets/mcp-marketplace-page-BNq_PNmO.js +40 -0
- package/dist/assets/model-config-page-aAUkZkSX.js +1 -0
- package/dist/assets/plus-1Rxl5FlV.js +1 -0
- package/dist/assets/provider-scoped-model-input-we4_Z4gP.js +1 -0
- package/dist/assets/providers-config-page-CtMkPSyu.js +1 -0
- package/dist/assets/{react-DYQXXGbH.js → react-CTqdhFMk.js} +1 -1
- package/dist/assets/remote-fQ7N_r8u.js +1 -0
- package/dist/assets/rotate-cw-CzfIeAJj.js +1 -0
- package/dist/assets/runtime-config-page-TD1UrTbG.js +1 -0
- package/dist/assets/{save-BNVTgBVn.js → save-C9fKWfVB.js} +1 -1
- package/dist/assets/{search-CKCzwLId.js → search-D5FQ5q0X.js} +1 -1
- package/dist/assets/{search-config-page-DG5Q2hF1.js → search-config-page-AMEJJNIS.js} +1 -1
- package/dist/assets/secrets-config-page-CcgJnvBO.js +3 -0
- package/dist/assets/{select-CIRwTNP4.js → select-Cu5n0E-3.js} +2 -2
- package/dist/assets/{tag-chip-DKhVFtTE.js → tag-chip-C5aOtjxu.js} +1 -1
- package/dist/assets/use-config-D8TESeo6.js +1 -0
- package/dist/assets/x-1qETdQ70.js +1 -0
- package/dist/index.html +14 -14
- package/package.json +9 -9
- package/src/features/chat/components/conversation/__tests__/chat-conversation-panel.test.tsx +12 -63
- package/src/features/chat/components/conversation/chat-conversation-content.tsx +11 -50
- package/src/features/chat/components/conversation/chat-conversation-panel.tsx +15 -2
- package/src/features/chat/features/input/components/chat-input-bar.container.tsx +84 -6
- package/src/features/chat/features/input/hooks/use-chat-input-bar-query-state.ts +2 -0
- package/src/features/chat/features/input/hooks/use-chat-model-favorites.ts +87 -0
- package/src/features/chat/features/input/utils/__tests__/chat-input-bar.utils.test.ts +64 -24
- package/src/features/chat/features/input/utils/__tests__/ncp-chat-input-availability.utils.test.ts +1 -0
- package/src/features/chat/features/input/utils/chat-input-bar.utils.ts +21 -12
- package/src/features/chat/features/input/utils/chat-input-toolbar.utils.ts +80 -25
- package/src/features/chat/features/message/utils/__tests__/chat-message-file-operation.utils.test.ts +310 -0
- package/src/features/chat/features/message/utils/__tests__/chat-message-test.utils.ts +43 -0
- package/src/features/chat/features/message/utils/__tests__/chat-message.utils.test.ts +1 -346
- package/src/features/chat/features/message/utils/chat-message-tool-card.utils.ts +10 -9
- package/src/features/chat/features/message/utils/file-operation/diff.utils.ts +39 -36
- package/src/features/chat/features/message/utils/file-operation/line-builder.utils.ts +46 -38
- package/src/features/chat/features/message/utils/file-operation/parsed-block.utils.ts +18 -15
- package/src/features/chat/features/session/components/session-header/__tests__/chat-session-project-badge.test.tsx +25 -25
- package/src/features/chat/features/session/components/session-header/chat-session-project-badge.tsx +15 -2
- package/src/features/chat/features/session-type/components/__tests__/chat-sidebar-create-menu.test.tsx +24 -0
- package/src/features/chat/features/session-type/components/chat-sidebar-create-menu.tsx +10 -1
- package/src/features/chat/features/welcome/components/__tests__/chat-conversation-welcome.test.tsx +193 -0
- package/src/features/chat/features/welcome/components/__tests__/chat-welcome.test.tsx +123 -0
- package/src/features/chat/features/welcome/components/chat-conversation-welcome.tsx +104 -0
- package/src/features/chat/features/welcome/components/chat-welcome-agent-picker.tsx +72 -0
- package/src/features/chat/features/welcome/components/chat-welcome-capability-grid.tsx +54 -0
- package/src/features/chat/features/welcome/components/chat-welcome-project-picker.tsx +132 -0
- package/src/features/chat/features/welcome/components/chat-welcome-session-type-picker.tsx +82 -0
- package/src/features/chat/features/welcome/components/chat-welcome.tsx +121 -0
- package/src/features/chat/features/welcome/utils/__tests__/chat-welcome-project-options.utils.test.ts +53 -0
- package/src/features/chat/features/welcome/utils/__tests__/chat-welcome-selection.utils.test.ts +63 -0
- package/src/features/chat/features/welcome/utils/__tests__/chat-welcome-visibility.utils.test.ts +34 -0
- package/src/features/chat/features/welcome/utils/chat-welcome-project-options.utils.ts +71 -0
- package/src/features/chat/features/welcome/utils/chat-welcome-selection.utils.ts +79 -0
- package/src/features/chat/features/welcome/utils/chat-welcome-visibility.utils.ts +17 -0
- package/src/features/chat/managers/__tests__/chat-input.manager.test.ts +65 -0
- package/src/features/chat/managers/chat-input.manager.ts +24 -2
- package/src/features/chat/stores/chat-input.store.ts +2 -0
- package/src/features/chat/types/chat-input-bar.types.ts +5 -0
- package/src/features/marketplace/utils/marketplace-installed-cache.utils.ts +27 -23
- package/src/features/settings/components/config/provider-form.tsx +284 -387
- package/src/features/settings/components/config/provider-status-badge.tsx +4 -4
- package/src/features/settings/components/config/secrets-config-form.tsx +11 -135
- package/src/features/settings/hooks/use-provider-auth-flow.ts +140 -0
- package/src/features/settings/pages/__tests__/model-config-page.test.tsx +16 -0
- package/src/features/settings/pages/secrets-config-page.tsx +2 -1
- package/src/features/settings/utils/__tests__/provider-form-support.utils.test.ts +60 -1
- package/src/features/settings/utils/__tests__/secrets-config-form.utils.test.ts +66 -0
- package/src/features/settings/utils/provider-form-context.utils.ts +131 -0
- package/src/features/settings/utils/provider-form-model.utils.ts +101 -0
- package/src/features/settings/utils/provider-form-support.utils.ts +102 -1
- package/src/features/settings/utils/secrets-config-form.utils.ts +139 -0
- package/src/features/system-status/components/config/runtime-agent-list-card.tsx +17 -11
- package/src/features/system-status/components/config/runtime-binding-list-card.tsx +14 -9
- package/src/features/system-status/components/config/runtime-config-editor.tsx +8 -5
- package/src/features/system-status/components/config/runtime-entry-list-card.tsx +14 -9
- package/src/features/system-status/components/config/runtime-settings-card.tsx +16 -7
- package/src/features/system-status/components/runtime-security-card.tsx +79 -25
- package/src/shared/components/common/__tests__/searchable-model-input.test.tsx +34 -0
- package/src/shared/components/common/provider-scoped-model-input.tsx +1 -0
- package/src/shared/components/common/searchable-model-input.tsx +102 -87
- package/src/shared/components/ui/README.md +7 -0
- package/src/shared/components/ui/popover.tsx +19 -3
- package/src/shared/components/ui/select.tsx +14 -4
- package/src/shared/hooks/use-infinite-scroll-loader.ts +14 -10
- package/src/shared/lib/api/index.ts +2 -0
- package/src/shared/lib/api/preferences/preference.types.ts +22 -0
- package/src/shared/lib/api/preferences/preference.utils.ts +40 -0
- package/src/shared/lib/i18n/locales/en-US/chat.json +16 -1
- package/src/shared/lib/i18n/locales/en-US/core.json +1 -0
- package/src/shared/lib/i18n/locales/zh-CN/chat.json +16 -1
- package/src/shared/lib/i18n/locales/zh-CN/core.json +1 -0
- package/dist/assets/chat-page-BXngLJY6.js +0 -105
- package/dist/assets/doc-browser-B6Wc_TIY.js +0 -1
- package/dist/assets/index-DTb_XVIH.js +0 -103
- package/dist/assets/index-ayiPYhf1.css +0 -1
- package/dist/assets/mcp-marketplace-page-DZ9H0v05.js +0 -1
- package/dist/assets/mcp-marketplace-page-cnVWf7QQ.js +0 -40
- package/dist/assets/model-config-page-Bcb35AVv.js +0 -1
- package/dist/assets/plus-CYE1onU2.js +0 -1
- package/dist/assets/provider-scoped-model-input-kdoNp4HG.js +0 -1
- package/dist/assets/providers-config-page-CQSibSwO.js +0 -1
- package/dist/assets/remote-BlJDbXOI.js +0 -1
- package/dist/assets/rotate-cw-BWbvFDAX.js +0 -1
- package/dist/assets/runtime-config-page-Tn2yLQ0c.js +0 -1
- package/dist/assets/secrets-config-page-BXn5Uuwp.js +0 -3
- package/dist/assets/use-config-DgKM9VIU.js +0 -1
- package/dist/assets/x-Cm3JjYut.js +0 -1
- package/src/features/chat/components/__tests__/chat-welcome.test.tsx +0 -45
- package/src/features/chat/components/chat-welcome.tsx +0 -102
|
@@ -1,42 +1,5 @@
|
|
|
1
1
|
import { ToolInvocationStatus, type UiMessage } from "@nextclaw/agent-chat";
|
|
2
|
-
import {
|
|
3
|
-
import type { ChatMessageSource } from "../chat-message.utils";
|
|
4
|
-
|
|
5
|
-
function toSource(uiMessages: UiMessage[]): ChatMessageSource[] {
|
|
6
|
-
return uiMessages as unknown as ChatMessageSource[];
|
|
7
|
-
}
|
|
8
|
-
|
|
9
|
-
const defaultTexts = {
|
|
10
|
-
roleLabels: {
|
|
11
|
-
user: "You",
|
|
12
|
-
assistant: "Assistant",
|
|
13
|
-
tool: "Tool",
|
|
14
|
-
system: "System",
|
|
15
|
-
fallback: "Message",
|
|
16
|
-
},
|
|
17
|
-
reasoningLabel: "Reasoning",
|
|
18
|
-
toolCallLabel: "Tool Call",
|
|
19
|
-
toolResultLabel: "Tool Result",
|
|
20
|
-
toolInputLabel: "Input",
|
|
21
|
-
toolNoOutputLabel: "No output",
|
|
22
|
-
toolOutputLabel: "Output",
|
|
23
|
-
toolStatusPreparingLabel: "Preparing",
|
|
24
|
-
toolStatusRunningLabel: "Running",
|
|
25
|
-
toolStatusCompletedLabel: "Completed",
|
|
26
|
-
toolStatusFailedLabel: "Failed",
|
|
27
|
-
toolStatusCancelledLabel: "Cancelled",
|
|
28
|
-
imageAttachmentLabel: "Image attachment",
|
|
29
|
-
fileAttachmentLabel: "File attachment",
|
|
30
|
-
unknownPartLabel: "Unknown Part",
|
|
31
|
-
};
|
|
32
|
-
|
|
33
|
-
function adapt(uiMessages: ChatMessageSource[]) {
|
|
34
|
-
return adaptChatMessages({
|
|
35
|
-
uiMessages,
|
|
36
|
-
formatTimestamp: (value) => `formatted:${value}`,
|
|
37
|
-
texts: defaultTexts,
|
|
38
|
-
});
|
|
39
|
-
}
|
|
2
|
+
import { adapt, toSource, type ChatMessageSource } from "./chat-message-test.utils";
|
|
40
3
|
|
|
41
4
|
it("maps markdown, reasoning, and tool parts into UI view models", () => {
|
|
42
5
|
const messages: UiMessage[] = [
|
|
@@ -576,311 +539,3 @@ it("renders asset tool results as previewable files", () => {
|
|
|
576
539
|
},
|
|
577
540
|
});
|
|
578
541
|
});
|
|
579
|
-
|
|
580
|
-
it("builds edit-file previews from structured args before the tool finishes", () => {
|
|
581
|
-
const adapted = adapt([
|
|
582
|
-
{
|
|
583
|
-
id: "assistant-edit-preview",
|
|
584
|
-
role: "assistant",
|
|
585
|
-
parts: [
|
|
586
|
-
{
|
|
587
|
-
type: "tool-invocation",
|
|
588
|
-
toolInvocation: {
|
|
589
|
-
status: ToolInvocationStatus.CALL,
|
|
590
|
-
toolCallId: "edit-call-1",
|
|
591
|
-
toolName: "edit_file",
|
|
592
|
-
args: JSON.stringify({
|
|
593
|
-
path: "src/app.ts",
|
|
594
|
-
oldText: "const color = 'red';",
|
|
595
|
-
newText: "const color = 'blue';",
|
|
596
|
-
}),
|
|
597
|
-
parsedArgs: {
|
|
598
|
-
path: "src/app.ts",
|
|
599
|
-
oldText: "const color = 'red';",
|
|
600
|
-
newText: "const color = 'blue';",
|
|
601
|
-
},
|
|
602
|
-
},
|
|
603
|
-
},
|
|
604
|
-
],
|
|
605
|
-
},
|
|
606
|
-
] as unknown as ChatMessageSource[]);
|
|
607
|
-
|
|
608
|
-
const editLines =
|
|
609
|
-
adapted[0]?.parts[0]?.type === "tool-card"
|
|
610
|
-
? (adapted[0].parts[0].card.fileOperation?.blocks[0]?.lines ?? [])
|
|
611
|
-
: [];
|
|
612
|
-
|
|
613
|
-
expect(adapted[0]?.parts[0]).toMatchObject({
|
|
614
|
-
type: "tool-card",
|
|
615
|
-
card: {
|
|
616
|
-
toolName: "edit_file",
|
|
617
|
-
summary: "src/app.ts",
|
|
618
|
-
statusTone: "running",
|
|
619
|
-
fileOperation: {
|
|
620
|
-
blocks: [
|
|
621
|
-
{
|
|
622
|
-
path: "src/app.ts",
|
|
623
|
-
lines: [
|
|
624
|
-
{
|
|
625
|
-
kind: "remove",
|
|
626
|
-
text: "const color = 'red';",
|
|
627
|
-
},
|
|
628
|
-
{
|
|
629
|
-
kind: "add",
|
|
630
|
-
text: "const color = 'blue';",
|
|
631
|
-
},
|
|
632
|
-
],
|
|
633
|
-
},
|
|
634
|
-
],
|
|
635
|
-
},
|
|
636
|
-
},
|
|
637
|
-
});
|
|
638
|
-
expect(editLines[0]).not.toHaveProperty("oldLineNumber");
|
|
639
|
-
expect(editLines[1]).not.toHaveProperty("newLineNumber");
|
|
640
|
-
});
|
|
641
|
-
|
|
642
|
-
it("uses structured edit-file result line numbers after the tool finishes", () => {
|
|
643
|
-
const adapted = adapt([
|
|
644
|
-
{
|
|
645
|
-
id: "assistant-edit-result",
|
|
646
|
-
role: "assistant",
|
|
647
|
-
parts: [
|
|
648
|
-
{
|
|
649
|
-
type: "tool-invocation",
|
|
650
|
-
toolInvocation: {
|
|
651
|
-
status: ToolInvocationStatus.RESULT,
|
|
652
|
-
toolCallId: "edit-result-1",
|
|
653
|
-
toolName: "edit_file",
|
|
654
|
-
args: JSON.stringify({
|
|
655
|
-
path: "src/app.ts",
|
|
656
|
-
oldText: "const color = 'red';",
|
|
657
|
-
newText: "const color = 'blue';",
|
|
658
|
-
}),
|
|
659
|
-
parsedArgs: {
|
|
660
|
-
path: "src/app.ts",
|
|
661
|
-
oldText: "const color = 'red';",
|
|
662
|
-
newText: "const color = 'blue';",
|
|
663
|
-
},
|
|
664
|
-
result: {
|
|
665
|
-
path: "src/app.ts",
|
|
666
|
-
oldStartLine: 27,
|
|
667
|
-
newStartLine: 27,
|
|
668
|
-
message: "Edited src/app.ts",
|
|
669
|
-
},
|
|
670
|
-
},
|
|
671
|
-
},
|
|
672
|
-
],
|
|
673
|
-
},
|
|
674
|
-
] as unknown as ChatMessageSource[]);
|
|
675
|
-
|
|
676
|
-
expect(adapted[0]?.parts[0]).toMatchObject({
|
|
677
|
-
type: "tool-card",
|
|
678
|
-
card: {
|
|
679
|
-
toolName: "edit_file",
|
|
680
|
-
summary: "src/app.ts",
|
|
681
|
-
statusTone: "success",
|
|
682
|
-
fileOperation: {
|
|
683
|
-
blocks: [
|
|
684
|
-
{
|
|
685
|
-
path: "src/app.ts",
|
|
686
|
-
lines: [
|
|
687
|
-
{
|
|
688
|
-
kind: "remove",
|
|
689
|
-
text: "const color = 'red';",
|
|
690
|
-
oldLineNumber: 27,
|
|
691
|
-
},
|
|
692
|
-
{
|
|
693
|
-
kind: "add",
|
|
694
|
-
text: "const color = 'blue';",
|
|
695
|
-
newLineNumber: 27,
|
|
696
|
-
},
|
|
697
|
-
],
|
|
698
|
-
},
|
|
699
|
-
],
|
|
700
|
-
},
|
|
701
|
-
},
|
|
702
|
-
});
|
|
703
|
-
});
|
|
704
|
-
|
|
705
|
-
it("builds write-file previews from partial native args before the JSON is complete", () => {
|
|
706
|
-
const adapted = adapt([
|
|
707
|
-
{
|
|
708
|
-
id: "assistant-write-preview",
|
|
709
|
-
role: "assistant",
|
|
710
|
-
parts: [
|
|
711
|
-
{
|
|
712
|
-
type: "tool-invocation",
|
|
713
|
-
toolInvocation: {
|
|
714
|
-
status: ToolInvocationStatus.PARTIAL_CALL,
|
|
715
|
-
toolCallId: "write-call-1",
|
|
716
|
-
toolName: "write_file",
|
|
717
|
-
args: '{"path":"games/snake.html","content":"<!DOCTYPE html>\\n<canvas id=\\"game\\"></canvas>\\n<script>const score = 1;',
|
|
718
|
-
},
|
|
719
|
-
},
|
|
720
|
-
],
|
|
721
|
-
},
|
|
722
|
-
] as unknown as ChatMessageSource[]);
|
|
723
|
-
|
|
724
|
-
expect(adapted[0]?.parts[0]).toMatchObject({
|
|
725
|
-
type: "tool-card",
|
|
726
|
-
card: {
|
|
727
|
-
toolName: "write_file",
|
|
728
|
-
summary: "games/snake.html",
|
|
729
|
-
statusTone: "running",
|
|
730
|
-
statusLabel: "Running",
|
|
731
|
-
fileOperation: {
|
|
732
|
-
blocks: [
|
|
733
|
-
{
|
|
734
|
-
display: "preview",
|
|
735
|
-
path: "games/snake.html",
|
|
736
|
-
lines: expect.arrayContaining([
|
|
737
|
-
expect.objectContaining({
|
|
738
|
-
kind: "add",
|
|
739
|
-
text: "<!DOCTYPE html>",
|
|
740
|
-
}),
|
|
741
|
-
expect.objectContaining({
|
|
742
|
-
kind: "add",
|
|
743
|
-
text: '<canvas id="game"></canvas>',
|
|
744
|
-
}),
|
|
745
|
-
]),
|
|
746
|
-
},
|
|
747
|
-
],
|
|
748
|
-
},
|
|
749
|
-
},
|
|
750
|
-
});
|
|
751
|
-
});
|
|
752
|
-
|
|
753
|
-
it("keeps completed write-file cards in preview mode instead of falling back to raw byte summaries", () => {
|
|
754
|
-
const adapted = adapt([
|
|
755
|
-
{
|
|
756
|
-
id: "assistant-write-result",
|
|
757
|
-
role: "assistant",
|
|
758
|
-
parts: [
|
|
759
|
-
{
|
|
760
|
-
type: "tool-invocation",
|
|
761
|
-
toolInvocation: {
|
|
762
|
-
status: ToolInvocationStatus.RESULT,
|
|
763
|
-
toolCallId: "write-result-1",
|
|
764
|
-
toolName: "write_file",
|
|
765
|
-
args: JSON.stringify({
|
|
766
|
-
path: "games/snake.html",
|
|
767
|
-
content: '<!DOCTYPE html>\n<canvas id="game"></canvas>',
|
|
768
|
-
}),
|
|
769
|
-
result: "Wrote 3906 bytes to games/snake.html",
|
|
770
|
-
},
|
|
771
|
-
},
|
|
772
|
-
],
|
|
773
|
-
},
|
|
774
|
-
] as unknown as ChatMessageSource[]);
|
|
775
|
-
|
|
776
|
-
expect(adapted[0]?.parts[0]).toMatchObject({
|
|
777
|
-
type: "tool-card",
|
|
778
|
-
card: {
|
|
779
|
-
toolName: "write_file",
|
|
780
|
-
summary: "games/snake.html",
|
|
781
|
-
statusTone: "success",
|
|
782
|
-
fileOperation: {
|
|
783
|
-
blocks: [
|
|
784
|
-
{
|
|
785
|
-
display: "preview",
|
|
786
|
-
path: "games/snake.html",
|
|
787
|
-
lines: [
|
|
788
|
-
{
|
|
789
|
-
kind: "add",
|
|
790
|
-
text: "<!DOCTYPE html>",
|
|
791
|
-
newLineNumber: 1,
|
|
792
|
-
},
|
|
793
|
-
{
|
|
794
|
-
kind: "add",
|
|
795
|
-
text: '<canvas id="game"></canvas>',
|
|
796
|
-
newLineNumber: 2,
|
|
797
|
-
},
|
|
798
|
-
],
|
|
799
|
-
},
|
|
800
|
-
],
|
|
801
|
-
},
|
|
802
|
-
},
|
|
803
|
-
});
|
|
804
|
-
expect(adapted[0]?.parts[0]).not.toMatchObject({
|
|
805
|
-
type: "tool-card",
|
|
806
|
-
card: {
|
|
807
|
-
output: "Wrote 3906 bytes to games/snake.html",
|
|
808
|
-
},
|
|
809
|
-
});
|
|
810
|
-
});
|
|
811
|
-
|
|
812
|
-
it("renders codex file_change results as structured diff previews", () => {
|
|
813
|
-
const adapted = adapt([
|
|
814
|
-
{
|
|
815
|
-
id: "assistant-file-change",
|
|
816
|
-
role: "assistant",
|
|
817
|
-
parts: [
|
|
818
|
-
{
|
|
819
|
-
type: "tool-invocation",
|
|
820
|
-
toolInvocation: {
|
|
821
|
-
status: ToolInvocationStatus.RESULT,
|
|
822
|
-
toolCallId: "file-change-1",
|
|
823
|
-
toolName: "file_change",
|
|
824
|
-
args: JSON.stringify({
|
|
825
|
-
changes: [
|
|
826
|
-
{
|
|
827
|
-
path: "src/main.ts",
|
|
828
|
-
diff: [
|
|
829
|
-
"--- a/src/main.ts",
|
|
830
|
-
"+++ b/src/main.ts",
|
|
831
|
-
"@@ -109,1 +109,1 @@",
|
|
832
|
-
"-console.log('old');",
|
|
833
|
-
"+console.log('new');",
|
|
834
|
-
].join("\n"),
|
|
835
|
-
},
|
|
836
|
-
],
|
|
837
|
-
}),
|
|
838
|
-
result: {
|
|
839
|
-
status: "completed",
|
|
840
|
-
changes: [
|
|
841
|
-
{
|
|
842
|
-
path: "src/main.ts",
|
|
843
|
-
diff: [
|
|
844
|
-
"--- a/src/main.ts",
|
|
845
|
-
"+++ b/src/main.ts",
|
|
846
|
-
"@@ -109,1 +109,1 @@",
|
|
847
|
-
"-console.log('old');",
|
|
848
|
-
"+console.log('new');",
|
|
849
|
-
].join("\n"),
|
|
850
|
-
},
|
|
851
|
-
],
|
|
852
|
-
},
|
|
853
|
-
},
|
|
854
|
-
},
|
|
855
|
-
],
|
|
856
|
-
},
|
|
857
|
-
] as unknown as ChatMessageSource[]);
|
|
858
|
-
|
|
859
|
-
expect(adapted[0]?.parts[0]).toMatchObject({
|
|
860
|
-
type: "tool-card",
|
|
861
|
-
card: {
|
|
862
|
-
toolName: "file_change",
|
|
863
|
-
summary: "src/main.ts",
|
|
864
|
-
statusTone: "success",
|
|
865
|
-
fileOperation: {
|
|
866
|
-
blocks: [
|
|
867
|
-
{
|
|
868
|
-
path: "src/main.ts",
|
|
869
|
-
lines: [
|
|
870
|
-
{
|
|
871
|
-
kind: "remove",
|
|
872
|
-
text: "console.log('old');",
|
|
873
|
-
oldLineNumber: 109,
|
|
874
|
-
},
|
|
875
|
-
{
|
|
876
|
-
kind: "add",
|
|
877
|
-
text: "console.log('new');",
|
|
878
|
-
newLineNumber: 109,
|
|
879
|
-
},
|
|
880
|
-
],
|
|
881
|
-
},
|
|
882
|
-
],
|
|
883
|
-
},
|
|
884
|
-
},
|
|
885
|
-
});
|
|
886
|
-
});
|
|
@@ -150,17 +150,18 @@ export function resolveToolCardStatus(params: {
|
|
|
150
150
|
ChatToolPartViewModel,
|
|
151
151
|
"kind" | "hasResult" | "statusTone" | "statusLabel"
|
|
152
152
|
> {
|
|
153
|
+
const { cancelled, error, result, status, texts } = params;
|
|
153
154
|
const rawStatus =
|
|
154
|
-
typeof
|
|
155
|
+
typeof status === "string" ? status.trim().toLowerCase() : "";
|
|
155
156
|
const hasError =
|
|
156
|
-
typeof
|
|
157
|
-
const isCancelled =
|
|
157
|
+
typeof error === "string" && error.trim().length > 0;
|
|
158
|
+
const isCancelled = cancelled === true || rawStatus === "cancelled";
|
|
158
159
|
if (isCancelled) {
|
|
159
160
|
return {
|
|
160
161
|
kind: "result",
|
|
161
162
|
hasResult: true,
|
|
162
163
|
statusTone: "cancelled",
|
|
163
|
-
statusLabel:
|
|
164
|
+
statusLabel: texts.toolStatusCancelledLabel,
|
|
164
165
|
};
|
|
165
166
|
}
|
|
166
167
|
if (hasError || rawStatus === "error") {
|
|
@@ -168,15 +169,15 @@ export function resolveToolCardStatus(params: {
|
|
|
168
169
|
kind: "result",
|
|
169
170
|
hasResult: true,
|
|
170
171
|
statusTone: "error",
|
|
171
|
-
statusLabel:
|
|
172
|
+
statusLabel: texts.toolStatusFailedLabel,
|
|
172
173
|
};
|
|
173
174
|
}
|
|
174
|
-
if (rawStatus === "result" ||
|
|
175
|
+
if (rawStatus === "result" || result != null) {
|
|
175
176
|
return {
|
|
176
177
|
kind: "result",
|
|
177
178
|
hasResult: true,
|
|
178
179
|
statusTone: "success",
|
|
179
|
-
statusLabel:
|
|
180
|
+
statusLabel: texts.toolStatusCompletedLabel,
|
|
180
181
|
};
|
|
181
182
|
}
|
|
182
183
|
if (rawStatus === "partial-call") {
|
|
@@ -184,14 +185,14 @@ export function resolveToolCardStatus(params: {
|
|
|
184
185
|
kind: "call",
|
|
185
186
|
hasResult: false,
|
|
186
187
|
statusTone: "running",
|
|
187
|
-
statusLabel:
|
|
188
|
+
statusLabel: texts.toolStatusRunningLabel,
|
|
188
189
|
};
|
|
189
190
|
}
|
|
190
191
|
return {
|
|
191
192
|
kind: "call",
|
|
192
193
|
hasResult: false,
|
|
193
194
|
statusTone: "running",
|
|
194
|
-
statusLabel:
|
|
195
|
+
statusLabel: texts.toolStatusRunningLabel,
|
|
195
196
|
};
|
|
196
197
|
}
|
|
197
198
|
|
|
@@ -24,16 +24,17 @@ export function buildRawPreviewBlock(params: {
|
|
|
24
24
|
oldStartLine?: number | null;
|
|
25
25
|
newStartLine?: number | null;
|
|
26
26
|
}): ParsedBlock | null {
|
|
27
|
-
const
|
|
27
|
+
const { newStartLine: rawNewStartLine, oldStartLine: rawOldStartLine, operation, path, text } = params;
|
|
28
|
+
const previewText = text.trim();
|
|
28
29
|
if (!previewText) {
|
|
29
30
|
return null;
|
|
30
31
|
}
|
|
31
32
|
const previewKind =
|
|
32
|
-
|
|
33
|
+
operation?.trim().toLowerCase() === "write" ? "add" : "context";
|
|
33
34
|
const oldStartLine =
|
|
34
|
-
typeof
|
|
35
|
+
typeof rawOldStartLine === "number" ? rawOldStartLine : 1;
|
|
35
36
|
const newStartLine =
|
|
36
|
-
typeof
|
|
37
|
+
typeof rawNewStartLine === "number" ? rawNewStartLine : 1;
|
|
37
38
|
const lines = buildPreviewLines({
|
|
38
39
|
text: previewText,
|
|
39
40
|
kind: previewKind,
|
|
@@ -41,10 +42,10 @@ export function buildRawPreviewBlock(params: {
|
|
|
41
42
|
newStartLine,
|
|
42
43
|
});
|
|
43
44
|
return {
|
|
44
|
-
path
|
|
45
|
+
path,
|
|
45
46
|
display: "preview",
|
|
46
47
|
caption: buildCaption({
|
|
47
|
-
operation
|
|
48
|
+
operation,
|
|
48
49
|
lines,
|
|
49
50
|
}),
|
|
50
51
|
lines,
|
|
@@ -62,10 +63,11 @@ export function buildFullReplaceBlock(params: {
|
|
|
62
63
|
oldStartLine?: number | null;
|
|
63
64
|
newStartLine?: number | null;
|
|
64
65
|
}): ParsedBlock | null {
|
|
66
|
+
const { afterText, beforeText, operation, path } = params;
|
|
65
67
|
const { oldStartLine, newStartLine } = readDefaultDiffStartLines(params);
|
|
66
68
|
const lines = buildLineDiff({
|
|
67
|
-
beforeText:
|
|
68
|
-
afterText:
|
|
69
|
+
beforeText: beforeText ?? "",
|
|
70
|
+
afterText: afterText ?? "",
|
|
69
71
|
oldStartLine,
|
|
70
72
|
newStartLine,
|
|
71
73
|
});
|
|
@@ -74,16 +76,16 @@ export function buildFullReplaceBlock(params: {
|
|
|
74
76
|
return null;
|
|
75
77
|
}
|
|
76
78
|
return {
|
|
77
|
-
path
|
|
79
|
+
path,
|
|
78
80
|
display: "diff",
|
|
79
81
|
caption: buildCaption({
|
|
80
|
-
operation
|
|
82
|
+
operation,
|
|
81
83
|
lines,
|
|
82
84
|
}),
|
|
83
85
|
lines: limited.lines,
|
|
84
86
|
...(limited.truncated ? { fullLines: lines } : {}),
|
|
85
|
-
...(
|
|
86
|
-
...(
|
|
87
|
+
...(beforeText != null ? { beforeText } : {}),
|
|
88
|
+
...(afterText != null ? { afterText } : {}),
|
|
87
89
|
...(typeof oldStartLine === "number" ? { oldStartLine } : {}),
|
|
88
90
|
...(typeof newStartLine === "number" ? { newStartLine } : {}),
|
|
89
91
|
truncated: limited.truncated,
|
|
@@ -95,23 +97,24 @@ function updateApplyPatchCursor(params: {
|
|
|
95
97
|
flushCurrent: () => void;
|
|
96
98
|
setCurrent: (path: string, operation: string) => void;
|
|
97
99
|
}): boolean {
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
100
|
+
const { flushCurrent, line, setCurrent } = params;
|
|
101
|
+
if (line.startsWith("*** Update File: ")) {
|
|
102
|
+
flushCurrent();
|
|
103
|
+
setCurrent(
|
|
104
|
+
line.slice("*** Update File: ".length).trim(),
|
|
102
105
|
"update",
|
|
103
106
|
);
|
|
104
107
|
return true;
|
|
105
108
|
}
|
|
106
|
-
if (
|
|
107
|
-
|
|
108
|
-
|
|
109
|
+
if (line.startsWith("*** Add File: ")) {
|
|
110
|
+
flushCurrent();
|
|
111
|
+
setCurrent(line.slice("*** Add File: ".length).trim(), "add");
|
|
109
112
|
return true;
|
|
110
113
|
}
|
|
111
|
-
if (
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
114
|
+
if (line.startsWith("*** Delete File: ")) {
|
|
115
|
+
flushCurrent();
|
|
116
|
+
setCurrent(
|
|
117
|
+
line.slice("*** Delete File: ".length).trim(),
|
|
115
118
|
"delete",
|
|
116
119
|
);
|
|
117
120
|
return true;
|
|
@@ -128,18 +131,18 @@ function appendPatchLine(params: {
|
|
|
128
131
|
oldLineNumber?: number;
|
|
129
132
|
newLineNumber?: number;
|
|
130
133
|
} {
|
|
131
|
-
const { currentLines, line } = params;
|
|
134
|
+
const { currentLines, line, newLineNumber, oldLineNumber } = params;
|
|
132
135
|
if (line.startsWith("+")) {
|
|
133
136
|
currentLines.push(
|
|
134
137
|
createLine({
|
|
135
138
|
kind: "add",
|
|
136
139
|
text: line.slice(1),
|
|
137
|
-
newLineNumber
|
|
140
|
+
newLineNumber,
|
|
138
141
|
}),
|
|
139
142
|
);
|
|
140
143
|
return {
|
|
141
|
-
oldLineNumber
|
|
142
|
-
newLineNumber: incrementLineNumber(
|
|
144
|
+
oldLineNumber,
|
|
145
|
+
newLineNumber: incrementLineNumber(newLineNumber),
|
|
143
146
|
};
|
|
144
147
|
}
|
|
145
148
|
if (line.startsWith("-")) {
|
|
@@ -147,12 +150,12 @@ function appendPatchLine(params: {
|
|
|
147
150
|
createLine({
|
|
148
151
|
kind: "remove",
|
|
149
152
|
text: line.slice(1),
|
|
150
|
-
oldLineNumber
|
|
153
|
+
oldLineNumber,
|
|
151
154
|
}),
|
|
152
155
|
);
|
|
153
156
|
return {
|
|
154
|
-
oldLineNumber: incrementLineNumber(
|
|
155
|
-
newLineNumber
|
|
157
|
+
oldLineNumber: incrementLineNumber(oldLineNumber),
|
|
158
|
+
newLineNumber,
|
|
156
159
|
};
|
|
157
160
|
}
|
|
158
161
|
if (line.startsWith(" ")) {
|
|
@@ -160,18 +163,18 @@ function appendPatchLine(params: {
|
|
|
160
163
|
createLine({
|
|
161
164
|
kind: "context",
|
|
162
165
|
text: line.slice(1),
|
|
163
|
-
oldLineNumber
|
|
164
|
-
newLineNumber
|
|
166
|
+
oldLineNumber,
|
|
167
|
+
newLineNumber,
|
|
165
168
|
}),
|
|
166
169
|
);
|
|
167
170
|
return {
|
|
168
|
-
oldLineNumber: incrementLineNumber(
|
|
169
|
-
newLineNumber: incrementLineNumber(
|
|
171
|
+
oldLineNumber: incrementLineNumber(oldLineNumber),
|
|
172
|
+
newLineNumber: incrementLineNumber(newLineNumber),
|
|
170
173
|
};
|
|
171
174
|
}
|
|
172
175
|
return {
|
|
173
|
-
oldLineNumber
|
|
174
|
-
newLineNumber
|
|
176
|
+
oldLineNumber,
|
|
177
|
+
newLineNumber,
|
|
175
178
|
};
|
|
176
179
|
}
|
|
177
180
|
|