@nextclaw/ui 0.11.21 → 0.11.23

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.
Files changed (129) hide show
  1. package/CHANGELOG.md +24 -0
  2. package/dist/assets/{ChannelsList-ByHWHkQS.js → ChannelsList-DVDu1xvz.js} +6 -6
  3. package/dist/assets/ChatPage-Z9tRzm_n.js +43 -0
  4. package/dist/assets/DocBrowser-B9OaZjmg.js +1 -0
  5. package/dist/assets/{DocBrowser-3y_NHZ71.js → DocBrowser-BmtBLFU0.js} +1 -1
  6. package/dist/assets/{DocBrowserContext-CVJuwCcw.js → DocBrowserContext-YIKkPb76.js} +1 -1
  7. package/dist/assets/{LogoBadge-D8fyilO-.js → LogoBadge-F7ZWdxLT.js} +1 -1
  8. package/dist/assets/{MarketplacePage-CmhsZXr1.js → MarketplacePage-Buo9HrOz.js} +2 -2
  9. package/dist/assets/MarketplacePage-D6rVQEQR.js +1 -0
  10. package/dist/assets/{McpMarketplacePage-C7PkCYbp.js → McpMarketplacePage-JnkYwK7p.js} +2 -2
  11. package/dist/assets/ModelConfig-BYRhgp0c.js +1 -0
  12. package/dist/assets/ProvidersList-DmLyyHvX.js +1 -0
  13. package/dist/assets/RemoteAccessPage-CDSSvH7Z.js +1 -0
  14. package/dist/assets/RuntimeConfig-v7a7Fe3x.js +1 -0
  15. package/dist/assets/{SearchConfig-Dm7r2yfp.js → SearchConfig-D5f1EkLE.js} +1 -1
  16. package/dist/assets/{SecretsConfig-BBP_mbQh.js → SecretsConfig-D61IKcYt.js} +2 -2
  17. package/dist/assets/{SessionsConfig-6wNJloZN.js → SessionsConfig-BRIxVTEv.js} +2 -2
  18. package/dist/assets/{book-open-B26jGBjY.js → book-open-CXoF5nQC.js} +1 -1
  19. package/dist/assets/chat-session-display-D0WpnuRZ.js +1 -0
  20. package/dist/assets/{chunk-JZWAC4HX-B-4B29RN.js → chunk-JZWAC4HX-CvRWvTy5.js} +1 -1
  21. package/dist/assets/{config-BaC29Qf-.js → config-DJswxxE8.js} +1 -1
  22. package/dist/assets/{createLucideIcon-DiFAvXmK.js → createLucideIcon-CjGHOWb6.js} +1 -1
  23. package/dist/assets/{dist-pCfWPG1A.js → dist-Cl2QB-2y.js} +1 -1
  24. package/dist/assets/{dist-kW_O3kyZ.js → dist-nqTTbVdA.js} +1 -1
  25. package/dist/assets/{external-link-D5-p-Gmm.js → external-link-tIO7zING.js} +1 -1
  26. package/dist/assets/{hash-BlwrSV0q.js → hash-JWUyl1pT.js} +1 -1
  27. package/dist/assets/i18n-CDHMXlRZ.js +1 -0
  28. package/dist/assets/{index-DvKS3L9j.js → index-BuwbBgmT.js} +3 -3
  29. package/dist/assets/index-bZ8cqQIS.css +1 -0
  30. package/dist/assets/{label-RyXfZqkP.js → label-BIpeNu4r.js} +1 -1
  31. package/dist/assets/loader-circle-Cs8XVFTw.js +1 -0
  32. package/dist/assets/{logos-Bpl8QTgI.js → logos-DThdM9lk.js} +1 -1
  33. package/dist/assets/{page-layout--S0YBU0W.js → page-layout-D3Xo605Z.js} +1 -1
  34. package/dist/assets/plus-PHf8q-Ct.js +1 -0
  35. package/dist/assets/{popover-BEjfbEwy.js → popover-BJRUGA_H.js} +1 -1
  36. package/dist/assets/provider-models-bz5y28rq.js +1 -0
  37. package/dist/assets/{react-BuSP2-8B.js → react-7ZHqQtEV.js} +1 -1
  38. package/dist/assets/refresh-ccw-CC6-_QuL.js +1 -0
  39. package/dist/assets/{save-DPPPpD_c.js → save-DJM5RRWW.js} +1 -1
  40. package/dist/assets/search-C91yH_6y.js +1 -0
  41. package/dist/assets/{security-config-6t78Ph-I.js → security-config-DbUyWcQz.js} +1 -1
  42. package/dist/assets/{select-CT50pzod.js → select-DSkTc61S.js} +1 -1
  43. package/dist/assets/skeleton-Dzg-HOiN.js +1 -0
  44. package/dist/assets/{status-dot-BbBqRHfh.js → status-dot-LNBlDu3q.js} +1 -1
  45. package/dist/assets/{switch-D3l6AcCk.js → switch-Bo-Y46HZ.js} +1 -1
  46. package/dist/assets/tabs-custom-DXv507_2.js +1 -0
  47. package/dist/assets/{trash-2-B2_AGVE3.js → trash-2-DFZmW6Gg.js} +1 -1
  48. package/dist/assets/useConfirmDialog-COwYXDKm.js +1 -0
  49. package/dist/assets/{useMutation-BzCrO8j-.js → useMutation-DrZrOgVL.js} +1 -1
  50. package/dist/assets/x-D7Q1yqSF.js +1 -0
  51. package/dist/index.html +18 -18
  52. package/package.json +6 -6
  53. package/src/api/ncp-session.test.ts +37 -0
  54. package/src/api/ncp-session.ts +29 -1
  55. package/src/api/server-path.ts +23 -0
  56. package/src/api/types.ts +45 -0
  57. package/src/components/chat/ChatConversationPanel.test.tsx +53 -9
  58. package/src/components/chat/ChatConversationPanel.tsx +122 -79
  59. package/src/components/chat/ChatSidebar.test.tsx +2 -2
  60. package/src/components/chat/ChatSidebar.tsx +2 -2
  61. package/src/components/chat/adapters/chat-input-bar.adapter.test.ts +1 -0
  62. package/src/components/chat/adapters/chat-input-bar.adapter.ts +7 -2
  63. package/src/components/chat/adapters/chat-message-part.adapter.ts +26 -14
  64. package/src/components/chat/adapters/chat-message.adapter.test.ts +159 -13
  65. package/src/components/chat/adapters/chat-message.session-request-tool-card.ts +191 -0
  66. package/src/components/chat/adapters/{chat-message.file-operation-card.ts → file-operation/card.ts} +74 -181
  67. package/src/components/chat/adapters/{chat-message.file-operation-diff.ts → file-operation/diff.ts} +178 -188
  68. package/src/components/chat/adapters/file-operation/line-builder.ts +249 -0
  69. package/src/components/chat/adapters/file-operation/record-readers.ts +233 -0
  70. package/src/components/chat/chat-child-session-panel.tsx +100 -0
  71. package/src/components/chat/chat-composer-state.ts +3 -3
  72. package/src/components/chat/chat-page-runtime.test.ts +1 -0
  73. package/src/components/chat/chat-session-display.test.ts +22 -0
  74. package/src/components/chat/chat-session-display.ts +6 -1
  75. package/src/components/chat/containers/chat-input-bar.container.tsx +21 -24
  76. package/src/components/chat/containers/chat-message-list.container.tsx +4 -0
  77. package/src/components/chat/hooks/use-chat-session-label.ts +19 -0
  78. package/src/components/chat/hooks/use-chat-session-project.test.tsx +117 -0
  79. package/src/components/chat/hooks/use-chat-session-project.ts +40 -0
  80. package/src/components/chat/{chat-session-label.service.ts → hooks/use-chat-session-update.ts} +11 -7
  81. package/src/components/chat/managers/chat-session-list.manager.ts +5 -1
  82. package/src/components/chat/ncp/NcpChatPage.tsx +219 -116
  83. package/src/components/chat/ncp/ncp-chat-page-data.test.ts +33 -0
  84. package/src/components/chat/ncp/ncp-chat-page-data.ts +21 -15
  85. package/src/components/chat/ncp/ncp-chat-thread.manager.ts +49 -0
  86. package/src/components/chat/ncp/ncp-session-adapter.test.ts +24 -0
  87. package/src/components/chat/ncp/ncp-session-adapter.ts +47 -0
  88. package/src/components/chat/ncp/use-ncp-session-list-view.ts +10 -1
  89. package/src/components/chat/presenter/chat-presenter-context.tsx +4 -1
  90. package/src/components/chat/session-header/chat-session-header-actions.test.tsx +63 -0
  91. package/src/components/chat/session-header/chat-session-header-actions.tsx +95 -0
  92. package/src/components/chat/session-header/chat-session-header-menu-item.tsx +35 -0
  93. package/src/components/chat/session-header/chat-session-project-badge.test.tsx +66 -0
  94. package/src/components/chat/session-header/chat-session-project-badge.tsx +102 -0
  95. package/src/components/chat/session-header/chat-session-project-dialog.tsx +34 -0
  96. package/src/components/chat/stores/chat-input.store.ts +6 -3
  97. package/src/components/chat/stores/chat-thread.store.ts +17 -3
  98. package/src/components/chat/useHydratedNcpAgent.test.tsx +30 -23
  99. package/src/components/path-picker/server-path-picker-dialog.test.tsx +92 -0
  100. package/src/components/path-picker/server-path-picker-dialog.tsx +282 -0
  101. package/src/hooks/server-path/use-server-path-browse.ts +19 -0
  102. package/src/hooks/useConfig.ts +26 -1
  103. package/src/lib/i18n/i18n-language-owner.ts +94 -0
  104. package/src/lib/i18n/i18n.path-picker.ts +12 -0
  105. package/src/lib/i18n.chat.ts +23 -0
  106. package/src/lib/i18n.ts +21 -84
  107. package/src/lib/session-project/session-project.utils.ts +30 -0
  108. package/dist/assets/ChatPage-FdT3pDnw.js +0 -42
  109. package/dist/assets/DocBrowser-CMdPdbZj.js +0 -1
  110. package/dist/assets/MarketplacePage-9oKmxN2n.js +0 -1
  111. package/dist/assets/ModelConfig-DmCY6jWM.js +0 -1
  112. package/dist/assets/ProvidersList-ClT-34aX.js +0 -1
  113. package/dist/assets/RemoteAccessPage-B6hUZl1O.js +0 -1
  114. package/dist/assets/RuntimeConfig-C5aqliGk.js +0 -1
  115. package/dist/assets/chat-session-display-Bjmn4aIZ.js +0 -1
  116. package/dist/assets/i18n-CSytxMFI.js +0 -1
  117. package/dist/assets/index-CUy6doWo.css +0 -1
  118. package/dist/assets/loader-circle-B2J777gj.js +0 -1
  119. package/dist/assets/plus-CM9XJ0Tf.js +0 -1
  120. package/dist/assets/provider-models-C8JQUd1E.js +0 -1
  121. package/dist/assets/search-Ctaw34Kp.js +0 -1
  122. package/dist/assets/skeleton-Bycyb0zU.js +0 -1
  123. package/dist/assets/tabs-custom-TZQ5WPWP.js +0 -1
  124. package/dist/assets/useConfirmDialog-BDpdjfIO.js +0 -1
  125. package/dist/assets/x-CHOBE-63.js +0 -1
  126. package/src/components/chat/adapters/chat-message.subagent-tool-card.ts +0 -154
  127. /package/dist/assets/{config-hints-fGnUjDe9.js → config-hints-WtpHP_DW.js} +0 -0
  128. /package/dist/assets/{config-layout-B-7erZRN.js → config-layout-LQ10ozRC.js} +0 -0
  129. /package/dist/assets/{marketplace-localization-CXeGRf6E.js → marketplace-localization-CxSTG9wr.js} +0 -0
@@ -1,12 +1,23 @@
1
- import type {
2
- ChatFileOperationBlockViewModel,
3
- } from "@nextclaw/agent-chat-ui";
1
+ import type { ChatFileOperationBlockViewModel } from "@nextclaw/agent-chat-ui";
4
2
  import {
5
3
  buildFullReplaceBlock,
6
4
  buildRawPreviewBlock,
7
5
  parsePatchBlocks,
8
6
  type ParsedBlock,
9
- } from "@/components/chat/adapters/chat-message.file-operation-diff";
7
+ } from "@/components/chat/adapters/file-operation/diff";
8
+ import {
9
+ isRecord,
10
+ readAfterText,
11
+ readBeforeText,
12
+ readNewStartLine,
13
+ readNonEmptyString,
14
+ readOldStartLine,
15
+ readOperation,
16
+ readPartialRecordPayload,
17
+ readPatchText,
18
+ readPath,
19
+ readRecordPayload,
20
+ } from "@/components/chat/adapters/file-operation/record-readers";
10
21
  import { readPartialJsonStringField } from "@/components/chat/adapters/chat-message.partial-json";
11
22
 
12
23
  type ToolInvocationSource = {
@@ -33,167 +44,9 @@ const FILE_TOOL_NAMES = new Set([
33
44
  "apply_patch",
34
45
  ]);
35
46
 
36
- function isRecord(value: unknown): value is Record<string, unknown> {
37
- return typeof value === "object" && value !== null && !Array.isArray(value);
38
- }
39
-
40
- function readNonEmptyString(value: unknown): string | null {
41
- if (typeof value !== "string") {
42
- return null;
43
- }
44
- const trimmed = value.trim();
45
- return trimmed.length > 0 ? trimmed : null;
46
- }
47
-
48
- function normalizePath(value: unknown): string | null {
49
- if (typeof value === "string" && value.trim()) {
50
- return value.trim();
51
- }
52
- return null;
53
- }
54
-
55
- function readRecordPayload(value: unknown): Record<string, unknown> | null {
56
- if (isRecord(value)) {
57
- return value;
58
- }
59
- if (typeof value !== "string") {
60
- return null;
61
- }
62
- const trimmed = value.trim();
63
- if (!trimmed.startsWith("{")) {
64
- return null;
65
- }
66
- try {
67
- const parsed = JSON.parse(trimmed) as unknown;
68
- return isRecord(parsed) ? parsed : null;
69
- } catch {
70
- return null;
71
- }
72
- }
73
-
74
- function readPartialRecordPayload(value: unknown): Record<string, unknown> | null {
75
- if (isRecord(value)) {
76
- return value;
77
- }
78
- if (typeof value !== "string") {
79
- return null;
80
- }
81
- const trimmed = value.trim();
82
- if (!trimmed.startsWith("{")) {
83
- return null;
84
- }
85
- const path =
86
- readPartialJsonStringField(trimmed, [
87
- "path",
88
- "filePath",
89
- "file_path",
90
- "targetPath",
91
- "target_path",
92
- "filename",
93
- "name",
94
- ])?.value ?? null;
95
- const content =
96
- readPartialJsonStringField(
97
- trimmed,
98
- ["content", "text", "afterText", "after_text"],
99
- )?.value ?? null;
100
- const oldText =
101
- readPartialJsonStringField(
102
- trimmed,
103
- ["oldText", "beforeText", "before_text"],
104
- )?.value ?? null;
105
- const newText =
106
- readPartialJsonStringField(
107
- trimmed,
108
- ["newText", "afterText", "after_text"],
109
- )?.value ?? null;
110
- const patch =
111
- readPartialJsonStringField(
112
- trimmed,
113
- ["patch", "diff", "unifiedDiff", "unified_diff"],
114
- )?.value ?? null;
115
-
116
- const partialRecord: Record<string, unknown> = {};
117
- if (path) {
118
- partialRecord.path = path;
119
- }
120
- if (content) {
121
- partialRecord.content = content;
122
- }
123
- if (oldText) {
124
- partialRecord.oldText = oldText;
125
- }
126
- if (newText) {
127
- partialRecord.newText = newText;
128
- }
129
- if (patch) {
130
- partialRecord.patch = patch;
131
- }
132
-
133
- return Object.keys(partialRecord).length > 0 ? partialRecord : null;
134
- }
135
-
136
- function readPath(record: Record<string, unknown>): string | null {
137
- return (
138
- normalizePath(record.path) ??
139
- normalizePath(record.filePath) ??
140
- normalizePath(record.file_path) ??
141
- normalizePath(record.targetPath) ??
142
- normalizePath(record.target_path) ??
143
- normalizePath(record.filename) ??
144
- normalizePath(record.name)
145
- );
146
- }
147
-
148
- function readOperation(record: Record<string, unknown>): string | null {
149
- return (
150
- readNonEmptyString(record.operation) ??
151
- readNonEmptyString(record.op) ??
152
- readNonEmptyString(record.action) ??
153
- readNonEmptyString(record.kind) ??
154
- readNonEmptyString(record.type) ??
155
- readNonEmptyString(record.status)
156
- );
157
- }
158
-
159
- function readPatchText(record: Record<string, unknown>): string | null {
160
- return (
161
- readNonEmptyString(record.patch) ??
162
- readNonEmptyString(record.diff) ??
163
- readNonEmptyString(record.unifiedDiff) ??
164
- readNonEmptyString(record.unified_diff)
165
- );
166
- }
167
-
168
- function readBeforeText(record: Record<string, unknown>): string | null {
169
- return (
170
- readNonEmptyString(record.beforeText) ??
171
- readNonEmptyString(record.before_text) ??
172
- readNonEmptyString(record.oldText) ??
173
- readNonEmptyString(record.old_text) ??
174
- readNonEmptyString(record.oldContent) ??
175
- readNonEmptyString(record.old_content) ??
176
- readNonEmptyString(record.before) ??
177
- readNonEmptyString(record.previous)
178
- );
179
- }
180
-
181
- function readAfterText(record: Record<string, unknown>): string | null {
182
- return (
183
- readNonEmptyString(record.afterText) ??
184
- readNonEmptyString(record.after_text) ??
185
- readNonEmptyString(record.newText) ??
186
- readNonEmptyString(record.new_text) ??
187
- readNonEmptyString(record.newContent) ??
188
- readNonEmptyString(record.new_content) ??
189
- readNonEmptyString(record.content) ??
190
- readNonEmptyString(record.text) ??
191
- readNonEmptyString(record.after) ??
192
- readNonEmptyString(record.updated)
193
- );
194
- }
195
-
196
- function finalizeParsedBlocks(blocks: ParsedBlock[]): FileOperationCardData | null {
47
+ function finalizeParsedBlocks(
48
+ blocks: ParsedBlock[],
49
+ ): FileOperationCardData | null {
197
50
  const normalizedBlocks = blocks
198
51
  .map((block, index) => ({
199
52
  key: `${block.path}-${index + 1}`,
@@ -224,9 +77,14 @@ function finalizeParsedBlocks(blocks: ParsedBlock[]): FileOperationCardData | nu
224
77
  };
225
78
  }
226
79
 
227
- function buildBlockFromChangeRecord(record: Record<string, unknown>, fallbackPath: string): ParsedBlock | null {
80
+ function buildBlockFromChangeRecord(
81
+ record: Record<string, unknown>,
82
+ fallbackPath: string,
83
+ ): ParsedBlock | null {
228
84
  const path = readPath(record) ?? fallbackPath;
229
85
  const operation = readOperation(record);
86
+ const oldStartLine = readOldStartLine(record);
87
+ const newStartLine = readNewStartLine(record);
230
88
  const patchText = readPatchText(record);
231
89
  if (patchText) {
232
90
  const parsedBlocks = parsePatchBlocks(patchText);
@@ -243,6 +101,8 @@ function buildBlockFromChangeRecord(record: Record<string, unknown>, fallbackPat
243
101
  beforeText,
244
102
  afterText,
245
103
  operation,
104
+ oldStartLine,
105
+ newStartLine,
246
106
  });
247
107
  }
248
108
 
@@ -252,6 +112,8 @@ function buildBlockFromChangeRecord(record: Record<string, unknown>, fallbackPat
252
112
  path,
253
113
  text: previewText,
254
114
  operation,
115
+ oldStartLine,
116
+ newStartLine,
255
117
  });
256
118
  }
257
119
 
@@ -281,7 +143,9 @@ function buildBlocksFromChanges(changes: unknown): ParsedBlock[] {
281
143
  blocks.push(block);
282
144
  return;
283
145
  }
284
- const nestedChanges = Array.isArray(entry.changes) ? buildBlocksFromChanges(entry.changes) : [];
146
+ const nestedChanges = Array.isArray(entry.changes)
147
+ ? buildBlocksFromChanges(entry.changes)
148
+ : [];
285
149
  if (nestedChanges.length > 0) {
286
150
  blocks.push(...nestedChanges);
287
151
  }
@@ -289,7 +153,9 @@ function buildBlocksFromChanges(changes: unknown): ParsedBlock[] {
289
153
  return blocks;
290
154
  }
291
155
 
292
- function buildFileChangeCardData(invocation: ToolInvocationSource): FileOperationCardData | null {
156
+ function buildFileChangeCardData(
157
+ invocation: ToolInvocationSource,
158
+ ): FileOperationCardData | null {
293
159
  const sourceRecord =
294
160
  readRecordPayload(invocation.result) ??
295
161
  readRecordPayload(invocation.parsedArgs) ??
@@ -301,7 +167,9 @@ function buildFileChangeCardData(invocation: ToolInvocationSource): FileOperatio
301
167
  return finalizeParsedBlocks(blocks);
302
168
  }
303
169
 
304
- function buildReadFileCardData(invocation: ToolInvocationSource): FileOperationCardData | null {
170
+ function buildReadFileCardData(
171
+ invocation: ToolInvocationSource,
172
+ ): FileOperationCardData | null {
305
173
  const argsRecord =
306
174
  readRecordPayload(invocation.parsedArgs) ??
307
175
  readRecordPayload(invocation.args) ??
@@ -322,7 +190,9 @@ function buildReadFileCardData(invocation: ToolInvocationSource): FileOperationC
322
190
  );
323
191
  }
324
192
 
325
- function buildWriteFileCardData(invocation: ToolInvocationSource): FileOperationCardData | null {
193
+ function buildWriteFileCardData(
194
+ invocation: ToolInvocationSource,
195
+ ): FileOperationCardData | null {
326
196
  const isStreamingPartialCall = invocation.status === "partial-call";
327
197
  if (isStreamingPartialCall && typeof invocation.args === "string") {
328
198
  const pathField = readPartialJsonStringField(invocation.args, [
@@ -334,10 +204,12 @@ function buildWriteFileCardData(invocation: ToolInvocationSource): FileOperation
334
204
  "filename",
335
205
  "name",
336
206
  ]);
337
- const contentField = readPartialJsonStringField(
338
- invocation.args,
339
- ["content", "text", "afterText", "after_text"],
340
- );
207
+ const contentField = readPartialJsonStringField(invocation.args, [
208
+ "content",
209
+ "text",
210
+ "afterText",
211
+ "after_text",
212
+ ]);
341
213
  if (pathField?.value && contentField?.value) {
342
214
  const previewBlock = buildRawPreviewBlock({
343
215
  path: pathField.value,
@@ -373,17 +245,32 @@ function buildWriteFileCardData(invocation: ToolInvocationSource): FileOperation
373
245
  );
374
246
  }
375
247
 
376
- function buildEditFileCardData(invocation: ToolInvocationSource): FileOperationCardData | null {
248
+ function buildEditFileCardData(
249
+ invocation: ToolInvocationSource,
250
+ ): FileOperationCardData | null {
251
+ const resultRecord = readRecordPayload(invocation.result);
377
252
  const argsRecord =
378
253
  readRecordPayload(invocation.parsedArgs) ??
379
254
  readRecordPayload(invocation.args) ??
380
255
  readPartialRecordPayload(invocation.args);
381
- if (!argsRecord) {
256
+ if (!resultRecord && !argsRecord) {
382
257
  return null;
383
258
  }
384
- const path = readPath(argsRecord);
385
- const beforeText = readNonEmptyString(argsRecord.oldText) ?? readNonEmptyString(argsRecord.beforeText);
386
- const afterText = readNonEmptyString(argsRecord.newText) ?? readNonEmptyString(argsRecord.afterText);
259
+ const path =
260
+ (resultRecord ? readPath(resultRecord) : null) ??
261
+ (argsRecord ? readPath(argsRecord) : null);
262
+ const beforeText =
263
+ (resultRecord ? readBeforeText(resultRecord) : null) ??
264
+ (argsRecord ? readBeforeText(argsRecord) : null);
265
+ const afterText =
266
+ (resultRecord ? readAfterText(resultRecord) : null) ??
267
+ (argsRecord ? readAfterText(argsRecord) : null);
268
+ const oldStartLine =
269
+ (resultRecord ? readOldStartLine(resultRecord) : null) ??
270
+ (argsRecord ? readOldStartLine(argsRecord) : null);
271
+ const newStartLine =
272
+ (resultRecord ? readNewStartLine(resultRecord) : null) ??
273
+ (argsRecord ? readNewStartLine(argsRecord) : null);
387
274
  if (!path || (beforeText == null && afterText == null)) {
388
275
  return null;
389
276
  }
@@ -394,14 +281,20 @@ function buildEditFileCardData(invocation: ToolInvocationSource): FileOperationC
394
281
  beforeText,
395
282
  afterText,
396
283
  operation: "edit",
284
+ oldStartLine,
285
+ newStartLine,
397
286
  }),
398
287
  ].filter((block): block is ParsedBlock => Boolean(block)),
399
288
  );
400
289
  }
401
290
 
402
- function buildApplyPatchCardData(invocation: ToolInvocationSource): FileOperationCardData | null {
291
+ function buildApplyPatchCardData(
292
+ invocation: ToolInvocationSource,
293
+ ): FileOperationCardData | null {
403
294
  const parsedArgsRecord = readRecordPayload(invocation.parsedArgs);
404
- const argsRecord = readRecordPayload(invocation.args) ?? readPartialRecordPayload(invocation.args);
295
+ const argsRecord =
296
+ readRecordPayload(invocation.args) ??
297
+ readPartialRecordPayload(invocation.args);
405
298
  const patchText =
406
299
  readNonEmptyString(invocation.args) ??
407
300
  (parsedArgsRecord ? readNonEmptyString(parsedArgsRecord.patch) : null) ??