@abacus-ai/cli 1.106.25008 → 2.0.0-canary.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.
Files changed (199) hide show
  1. package/.oxlintrc.json +8 -0
  2. package/dist/index.mjs +12823 -0
  3. package/package.json +7 -39
  4. package/resources/abacus.ico +0 -0
  5. package/resources/entitlements.plist +9 -0
  6. package/src/__e2e__/README.md +196 -0
  7. package/src/__e2e__/agent-interactions.e2e.test.tsx +61 -0
  8. package/src/__e2e__/cli-commands.e2e.test.tsx +77 -0
  9. package/src/__e2e__/conversation-throttle.e2e.test.ts +453 -0
  10. package/src/__e2e__/conversation.e2e.test.tsx +56 -0
  11. package/src/__e2e__/diff-preview.e2e.test.tsx +3399 -0
  12. package/src/__e2e__/file-creation.e2e.test.tsx +149 -0
  13. package/src/__e2e__/helpers/test-helpers.ts +449 -0
  14. package/src/__e2e__/keyboard-navigation.e2e.test.tsx +34 -0
  15. package/src/__e2e__/llm-models.e2e.test.ts +402 -0
  16. package/src/__e2e__/mcp/mcp-callback-flow.e2e.test.tsx +71 -0
  17. package/src/__e2e__/mcp/mcp-full-app-ui.e2e.test.tsx +167 -0
  18. package/src/__e2e__/mcp/mcp-ui-rendering.e2e.test.tsx +185 -0
  19. package/src/__e2e__/repl.e2e.test.tsx +78 -0
  20. package/src/__e2e__/shell-compatibility.e2e.test.tsx +76 -0
  21. package/src/__e2e__/theme-mcp.e2e.test.tsx +98 -0
  22. package/src/__e2e__/tool-permissions.e2e.test.tsx +66 -0
  23. package/src/args.ts +22 -0
  24. package/src/components/__tests__/react-compiler.test.tsx +78 -0
  25. package/src/components/__tests__/status-indicator.test.tsx +403 -0
  26. package/src/components/composer/__tests__/bash-runner.test.tsx +263 -0
  27. package/src/components/composer/agent-mode-indicator.tsx +63 -0
  28. package/src/components/composer/bash-runner.tsx +54 -0
  29. package/src/components/composer/commands/default-commands.tsx +615 -0
  30. package/src/components/composer/commands/handler.tsx +59 -0
  31. package/src/components/composer/commands/picker.tsx +273 -0
  32. package/src/components/composer/commands/registry.ts +233 -0
  33. package/src/components/composer/commands/types.ts +33 -0
  34. package/src/components/composer/context.tsx +88 -0
  35. package/src/components/composer/file-mention-picker.tsx +83 -0
  36. package/src/components/composer/help.tsx +44 -0
  37. package/src/components/composer/index.tsx +1007 -0
  38. package/src/components/composer/mentions.ts +57 -0
  39. package/src/components/composer/message-queue.tsx +70 -0
  40. package/src/components/composer/mode-panel.tsx +35 -0
  41. package/src/components/composer/modes/__tests__/bash-handler.test.tsx +755 -0
  42. package/src/components/composer/modes/__tests__/bash-renderer.test.tsx +1108 -0
  43. package/src/components/composer/modes/bash-handler.tsx +132 -0
  44. package/src/components/composer/modes/bash-renderer.tsx +175 -0
  45. package/src/components/composer/modes/default-handlers.tsx +33 -0
  46. package/src/components/composer/modes/index.ts +41 -0
  47. package/src/components/composer/modes/types.ts +21 -0
  48. package/src/components/composer/persistent-shell.ts +283 -0
  49. package/src/components/composer/process.ts +65 -0
  50. package/src/components/composer/types.ts +9 -0
  51. package/src/components/composer/use-mention-search.ts +68 -0
  52. package/src/components/error-boundry.tsx +60 -0
  53. package/src/components/exit-message.tsx +29 -0
  54. package/src/components/expanded-view.tsx +74 -0
  55. package/src/components/file-completion.tsx +127 -0
  56. package/src/components/header.tsx +47 -0
  57. package/src/components/logo.tsx +37 -0
  58. package/src/components/segments.tsx +356 -0
  59. package/src/components/status-indicator.tsx +306 -0
  60. package/src/components/tool-group-summary.tsx +263 -0
  61. package/src/components/tool-permissions/ask-user-question-permission-ui.tsx +319 -0
  62. package/src/components/tool-permissions/diff-preview.tsx +359 -0
  63. package/src/components/tool-permissions/index.ts +5 -0
  64. package/src/components/tool-permissions/permission-options.tsx +401 -0
  65. package/src/components/tool-permissions/permission-preview-header.tsx +57 -0
  66. package/src/components/tool-permissions/tool-permission-ui.tsx +420 -0
  67. package/src/components/tools/agent/ask-user-question.tsx +107 -0
  68. package/src/components/tools/agent/enter-plan-mode.tsx +55 -0
  69. package/src/components/tools/agent/exit-plan-mode.tsx +83 -0
  70. package/src/components/tools/agent/handoff-to-main.tsx +27 -0
  71. package/src/components/tools/agent/subagent.tsx +37 -0
  72. package/src/components/tools/agent/todo-write.tsx +104 -0
  73. package/src/components/tools/browser/close-tab.tsx +58 -0
  74. package/src/components/tools/browser/computer.tsx +70 -0
  75. package/src/components/tools/browser/get-interactive-elements.tsx +54 -0
  76. package/src/components/tools/browser/get-tab-content.tsx +51 -0
  77. package/src/components/tools/browser/navigate-to.tsx +59 -0
  78. package/src/components/tools/browser/new-tab.tsx +60 -0
  79. package/src/components/tools/browser/perform-action.tsx +63 -0
  80. package/src/components/tools/browser/refresh-tab.tsx +43 -0
  81. package/src/components/tools/browser/switch-tab.tsx +58 -0
  82. package/src/components/tools/filesystem/delete-file.tsx +104 -0
  83. package/src/components/tools/filesystem/edit.tsx +220 -0
  84. package/src/components/tools/filesystem/list-dir.tsx +78 -0
  85. package/src/components/tools/filesystem/read-file.tsx +180 -0
  86. package/src/components/tools/filesystem/upload-image.tsx +76 -0
  87. package/src/components/tools/ide/ide-diagnostics.tsx +62 -0
  88. package/src/components/tools/index.ts +91 -0
  89. package/src/components/tools/mcp/mcp-tool.tsx +158 -0
  90. package/src/components/tools/search/fetch-url.tsx +73 -0
  91. package/src/components/tools/search/file-search.tsx +78 -0
  92. package/src/components/tools/search/grep.tsx +90 -0
  93. package/src/components/tools/search/semantic-search.tsx +66 -0
  94. package/src/components/tools/search/web-search.tsx +71 -0
  95. package/src/components/tools/shared/index.tsx +48 -0
  96. package/src/components/tools/shared/zod-coercion.ts +35 -0
  97. package/src/components/tools/terminal/bash-tool-output.tsx +188 -0
  98. package/src/components/tools/terminal/get-terminal-output.tsx +91 -0
  99. package/src/components/tools/terminal/run-in-terminal.tsx +131 -0
  100. package/src/components/tools/types.ts +16 -0
  101. package/src/components/tools.tsx +68 -0
  102. package/src/components/ui/__tests__/divider.test.tsx +61 -0
  103. package/src/components/ui/__tests__/gradient.test.tsx +125 -0
  104. package/src/components/ui/__tests__/input.test.tsx +166 -0
  105. package/src/components/ui/__tests__/select.test.tsx +273 -0
  106. package/src/components/ui/__tests__/shimmer.test.tsx +99 -0
  107. package/src/components/ui/blinking-indicator.tsx +27 -0
  108. package/src/components/ui/divider.tsx +162 -0
  109. package/src/components/ui/gradient.tsx +56 -0
  110. package/src/components/ui/input.tsx +228 -0
  111. package/src/components/ui/select.tsx +151 -0
  112. package/src/components/ui/shimmer.tsx +76 -0
  113. package/src/context/agent-mode.tsx +95 -0
  114. package/src/context/extension-file.tsx +136 -0
  115. package/src/context/network-activity.tsx +45 -0
  116. package/src/context/notification.tsx +62 -0
  117. package/src/context/shell-size.tsx +49 -0
  118. package/src/context/shell-title.tsx +38 -0
  119. package/src/entrypoints/print-mode.ts +312 -0
  120. package/src/entrypoints/repl.tsx +389 -0
  121. package/src/hooks/use-agent.ts +15 -0
  122. package/src/hooks/use-api-client.ts +1 -0
  123. package/src/hooks/use-available-height.ts +8 -0
  124. package/src/hooks/use-cleanup.ts +29 -0
  125. package/src/hooks/use-interrupt-manager.ts +242 -0
  126. package/src/hooks/use-models.ts +22 -0
  127. package/src/index.ts +217 -0
  128. package/src/lib/__tests__/ansi.test.ts +255 -0
  129. package/src/lib/__tests__/cli.test.ts +122 -0
  130. package/src/lib/__tests__/commands.test.ts +325 -0
  131. package/src/lib/__tests__/constants.test.ts +15 -0
  132. package/src/lib/__tests__/focusables.test.ts +25 -0
  133. package/src/lib/__tests__/fs.test.ts +231 -0
  134. package/src/lib/__tests__/markdown.test.tsx +348 -0
  135. package/src/lib/__tests__/mcpCommandHandler.test.ts +173 -0
  136. package/src/lib/__tests__/mcpManagement.test.ts +38 -0
  137. package/src/lib/__tests__/path-paste.test.ts +144 -0
  138. package/src/lib/__tests__/path.test.ts +300 -0
  139. package/src/lib/__tests__/queries.test.ts +39 -0
  140. package/src/lib/__tests__/standaloneMcpService.test.ts +71 -0
  141. package/src/lib/__tests__/text-buffer.test.ts +328 -0
  142. package/src/lib/__tests__/text-utils.test.ts +32 -0
  143. package/src/lib/__tests__/timing.test.ts +78 -0
  144. package/src/lib/__tests__/utils.test.ts +238 -0
  145. package/src/lib/__tests__/vim-buffer-actions.test.ts +154 -0
  146. package/src/lib/ansi.ts +150 -0
  147. package/src/lib/cli-push-server.ts +112 -0
  148. package/src/lib/cli.ts +44 -0
  149. package/src/lib/clipboard.ts +226 -0
  150. package/src/lib/command-utils.ts +93 -0
  151. package/src/lib/commands.ts +270 -0
  152. package/src/lib/constants.ts +3 -0
  153. package/src/lib/extension-connection.ts +181 -0
  154. package/src/lib/focusables.ts +7 -0
  155. package/src/lib/fs.ts +533 -0
  156. package/src/lib/markdown/code-block.tsx +63 -0
  157. package/src/lib/markdown/index.ts +4 -0
  158. package/src/lib/markdown/link.tsx +19 -0
  159. package/src/lib/markdown/markdown.tsx +372 -0
  160. package/src/lib/markdown/types.ts +15 -0
  161. package/src/lib/mcpCommandHandler.ts +121 -0
  162. package/src/lib/mcpManagement.ts +44 -0
  163. package/src/lib/path-paste.ts +185 -0
  164. package/src/lib/path.ts +179 -0
  165. package/src/lib/queries.ts +15 -0
  166. package/src/lib/standaloneMcpService.ts +688 -0
  167. package/src/lib/status-utils.ts +237 -0
  168. package/src/lib/test-utils.tsx +72 -0
  169. package/src/lib/text-buffer.ts +2415 -0
  170. package/src/lib/text-utils.ts +272 -0
  171. package/src/lib/timing.ts +63 -0
  172. package/src/lib/types.ts +295 -0
  173. package/src/lib/utils.ts +182 -0
  174. package/src/lib/vim-buffer-actions.ts +732 -0
  175. package/src/providers/agent.tsx +1063 -0
  176. package/src/providers/api-client.tsx +43 -0
  177. package/src/services/logger.ts +85 -0
  178. package/src/terminal/detection.ts +187 -0
  179. package/src/terminal/exit.ts +279 -0
  180. package/src/terminal/notification.ts +83 -0
  181. package/src/terminal/progress.ts +201 -0
  182. package/src/terminal/setup.ts +797 -0
  183. package/src/terminal/types.ts +51 -0
  184. package/src/theme/context.tsx +57 -0
  185. package/src/theme/index.ts +4 -0
  186. package/src/theme/themed.tsx +35 -0
  187. package/src/theme/themes.json +546 -0
  188. package/src/theme/types.ts +110 -0
  189. package/src/tools/types.ts +59 -0
  190. package/src/tools/utils/__tests__/zod-coercion.test.ts +33 -0
  191. package/src/tools/utils/tool-ui-components.tsx +649 -0
  192. package/src/tools/utils/zod-coercion.ts +35 -0
  193. package/tsconfig.json +16 -0
  194. package/tsconfig.node.json +29 -0
  195. package/tsconfig.test.json +27 -0
  196. package/tsdown.config.ts +17 -0
  197. package/vitest.config.ts +76 -0
  198. package/README.md +0 -28
  199. package/dist/index.js +0 -26
@@ -0,0 +1,359 @@
1
+ import type { StructuredPatchHunk } from "diff";
2
+ import type { ComponentProps } from "react";
3
+
4
+ import { View, Text } from "@codellm/jar";
5
+ import { structuredPatch, diffWordsWithSpace } from "diff";
6
+ import { memo, useMemo, useEffect, useState } from "react";
7
+
8
+ import { useTheme } from "../../theme/index.js";
9
+ import { highlightLines } from "../../tools/utils/tool-ui-components.js";
10
+
11
+ type DiffPreviewProps = Omit<ComponentProps<typeof View>, "children"> & {
12
+ filePath: string;
13
+ originalContent: string;
14
+ newContent: string;
15
+ dimmed?: boolean;
16
+ };
17
+
18
+ interface DiffLine {
19
+ type: "added" | "removed" | "unchanged" | "separator";
20
+ content: string;
21
+ highlightedContent?: string;
22
+ originalLineNumber?: number;
23
+ newLineNumber?: number;
24
+ skippedLines?: number;
25
+ }
26
+
27
+ interface WordPart {
28
+ value: string;
29
+ added?: boolean;
30
+ removed?: boolean;
31
+ }
32
+
33
+ function getWordDiff(oldLine: string, newLine: string): WordPart[] {
34
+ return diffWordsWithSpace(oldLine, newLine);
35
+ }
36
+
37
+ const DiffLineContent = memo(
38
+ ({
39
+ line,
40
+ pairedLine,
41
+ lineNumber,
42
+ dimmed = false,
43
+ }: {
44
+ line: DiffLine;
45
+ pairedLine?: DiffLine;
46
+ lineNumber: string;
47
+ dimmed?: boolean;
48
+ }) => {
49
+ const { colors } = useTheme();
50
+
51
+ if (line.type === "separator") {
52
+ return (
53
+ <View flexDirection="row">
54
+ <Text dimColor>{lineNumber} </Text>
55
+ <Text dimColor>⋮ {line.skippedLines} unchanged lines</Text>
56
+ </View>
57
+ );
58
+ }
59
+
60
+ if (line.type === "unchanged") {
61
+ return (
62
+ <View flexDirection="row">
63
+ <Text dimColor>{lineNumber} </Text>
64
+ <View flexShrink={1}>
65
+ <Text dimColor wrap="wrap">
66
+ {line.highlightedContent ?? line.content}
67
+ </Text>
68
+ </View>
69
+ </View>
70
+ );
71
+ }
72
+
73
+ if (line.type === "removed") {
74
+ const wdiff =
75
+ pairedLine?.type === "added" ? getWordDiff(line.content, pairedLine.content) : null;
76
+ return (
77
+ <View flexDirection="row" backgroundColor={colors.diffRemoved}>
78
+ <Text
79
+ backgroundColor={colors.diffRemoved}
80
+ color={colors.diffRemovedText}
81
+ dimColor={dimmed}
82
+ >
83
+ {lineNumber} -{" "}
84
+ </Text>
85
+ <View flexShrink={1}>
86
+ <Text color={colors.diffRemovedText} dimColor={dimmed} wrap="wrap">
87
+ {wdiff ? (
88
+ wdiff.map((part, i) =>
89
+ part.removed ? (
90
+ <Text key={i} backgroundColor={colors.diffRemovedHighlight} dimColor={dimmed}>
91
+ {part.value}
92
+ </Text>
93
+ ) : part.added ? null : (
94
+ <Text key={i} backgroundColor={colors.diffRemoved} dimColor={dimmed}>
95
+ {part.value}
96
+ </Text>
97
+ ),
98
+ )
99
+ ) : (
100
+ <Text backgroundColor={colors.diffRemoved} dimColor={dimmed}>
101
+ {line.highlightedContent ?? line.content}
102
+ </Text>
103
+ )}
104
+ </Text>
105
+ </View>
106
+ </View>
107
+ );
108
+ }
109
+
110
+ if (line.type === "added") {
111
+ const wdiff =
112
+ pairedLine?.type === "removed" ? getWordDiff(pairedLine.content, line.content) : null;
113
+ return (
114
+ <View flexDirection="row" backgroundColor={colors.diffAdded}>
115
+ <Text backgroundColor={colors.diffAdded} color={colors.diffAddedText} dimColor={dimmed}>
116
+ {lineNumber} +{" "}
117
+ </Text>
118
+ <View flexShrink={1}>
119
+ <Text color={colors.diffAddedText} dimColor={dimmed} wrap="wrap">
120
+ {wdiff ? (
121
+ wdiff.map((part, i) =>
122
+ part.added ? (
123
+ <Text key={i} backgroundColor={colors.diffAddedHighlight} dimColor={dimmed}>
124
+ {part.value}
125
+ </Text>
126
+ ) : part.removed ? null : (
127
+ <Text key={i} backgroundColor={colors.diffAdded} dimColor={dimmed}>
128
+ {part.value}
129
+ </Text>
130
+ ),
131
+ )
132
+ ) : (
133
+ <Text backgroundColor={colors.diffAdded} dimColor={dimmed}>
134
+ {line.highlightedContent ?? line.content}
135
+ </Text>
136
+ )}
137
+ </Text>
138
+ </View>
139
+ </View>
140
+ );
141
+ }
142
+
143
+ return null;
144
+ },
145
+ );
146
+ DiffLineContent.displayName = "DiffLineContent";
147
+
148
+ export const DiffPreviewTitle = memo(
149
+ ({ filePath, hunks }: { filePath: string; hunks: StructuredPatchHunk[] }) => {
150
+ const { colors } = useTheme();
151
+ const numAdditions = hunks.reduce(
152
+ (count, hunk) => count + hunk.lines.filter((l) => l.startsWith("+")).length,
153
+ 0,
154
+ );
155
+ const numRemovals = hunks.reduce(
156
+ (count, hunk) => count + hunk.lines.filter((l) => l.startsWith("-")).length,
157
+ 0,
158
+ );
159
+
160
+ return (
161
+ <View flexDirection="row" gap={1}>
162
+ <Text bold>{filePath}</Text>
163
+ {(numAdditions > 0 || numRemovals > 0) && (
164
+ <Text dimColor>
165
+ {numAdditions > 0 && <Text color={colors.diffAddedText}>+{numAdditions}</Text>}
166
+ {numAdditions > 0 && numRemovals > 0 && <Text> </Text>}
167
+ {numRemovals > 0 && <Text color={colors.diffRemovedText}>-{numRemovals}</Text>}
168
+ </Text>
169
+ )}
170
+ </View>
171
+ );
172
+ },
173
+ );
174
+ DiffPreviewTitle.displayName = "DiffPreviewTitle";
175
+
176
+ export const DiffPreview = memo(
177
+ ({ filePath, originalContent, newContent, dimmed = false, ...viewProps }: DiffPreviewProps) => {
178
+ // Defer heavy diff computation off the render cycle via setTimeout(0) to avoid
179
+ // blocking the event loop (and React's concurrent scheduler) on large files.
180
+ const [computedContent, setComputedContent] = useState(newContent);
181
+ const isProcessing = computedContent !== newContent;
182
+
183
+ useEffect(() => {
184
+ if (computedContent === newContent) return;
185
+ const id = setTimeout(() => setComputedContent(newContent), 0);
186
+ return () => clearTimeout(id);
187
+ }, [newContent, computedContent]);
188
+
189
+ const { diffLines, totalOriginalLines } = useMemo(() => {
190
+ const hlOrig = highlightLines(originalContent, filePath);
191
+ const hlNew = highlightLines(computedContent, filePath);
192
+
193
+ const patch = structuredPatch(
194
+ filePath,
195
+ filePath,
196
+ originalContent,
197
+ computedContent,
198
+ undefined,
199
+ undefined,
200
+ { context: 1 },
201
+ );
202
+
203
+ const lines: DiffLine[] = [];
204
+ let lastEndLine = 0;
205
+
206
+ for (let hunkIdx = 0; hunkIdx < patch.hunks.length; hunkIdx++) {
207
+ const hunk = patch.hunks[hunkIdx];
208
+ if (!hunk) continue;
209
+
210
+ const hunkStartLine = hunk.oldStart;
211
+
212
+ if (hunkIdx > 0 && hunkStartLine > lastEndLine + 1) {
213
+ const skipped = hunkStartLine - lastEndLine - 1;
214
+ if (skipped > 0) {
215
+ lines.push({
216
+ type: "separator",
217
+ content: "",
218
+ skippedLines: skipped,
219
+ });
220
+ }
221
+ }
222
+
223
+ let oldLineNum = hunk.oldStart;
224
+ let newLineNum = hunk.newStart;
225
+
226
+ for (const line of hunk.lines) {
227
+ const prefix = line[0];
228
+ const content = line.slice(1);
229
+
230
+ if (prefix === "\\") {
231
+ continue;
232
+ }
233
+
234
+ if (prefix === "+") {
235
+ lines.push({
236
+ type: "added",
237
+ content,
238
+ highlightedContent: hlNew[newLineNum - 1],
239
+ newLineNumber: newLineNum++,
240
+ });
241
+ } else if (prefix === "-") {
242
+ lines.push({
243
+ type: "removed",
244
+ content,
245
+ highlightedContent: hlOrig[oldLineNum - 1],
246
+ originalLineNumber: oldLineNum++,
247
+ });
248
+ } else {
249
+ lines.push({
250
+ type: "unchanged",
251
+ content,
252
+ highlightedContent: hlOrig[oldLineNum - 1],
253
+ originalLineNumber: oldLineNum++,
254
+ newLineNumber: newLineNum++,
255
+ });
256
+ }
257
+ }
258
+
259
+ lastEndLine = oldLineNum - 1;
260
+ }
261
+
262
+ const originalLines = originalContent.split("\n").length;
263
+
264
+ return {
265
+ diffLines: lines,
266
+ totalOriginalLines: originalLines,
267
+ };
268
+ }, [filePath, originalContent, computedContent]);
269
+
270
+ const linePairs = useMemo(() => {
271
+ const pairs = new Map<number, DiffLine>();
272
+ for (let i = 0; i < diffLines.length; i++) {
273
+ const current = diffLines[i];
274
+ if (!current) continue;
275
+
276
+ if (current.type === "removed") {
277
+ const next = diffLines[i + 1];
278
+ if (next && next.type === "added") {
279
+ pairs.set(i, next);
280
+ pairs.set(i + 1, current);
281
+ }
282
+ }
283
+ }
284
+ return pairs;
285
+ }, [diffLines]);
286
+
287
+ if (diffLines.length === 0) {
288
+ return (
289
+ <View flexDirection="column" {...viewProps}>
290
+ <View
291
+ borderStyle="singleDouble"
292
+ width="100%"
293
+ borderTop={false}
294
+ borderLeft={false}
295
+ borderRight={false}
296
+ borderBottom
297
+ />
298
+ <Text dimColor>No changes detected</Text>
299
+ <View
300
+ borderStyle="singleDouble"
301
+ width="100%"
302
+ borderTop={false}
303
+ borderLeft={false}
304
+ borderRight={false}
305
+ borderBottom
306
+ />
307
+ </View>
308
+ );
309
+ }
310
+
311
+ const maxLineNumber = Math.max(
312
+ totalOriginalLines,
313
+ ...diffLines
314
+ .filter((l) => l.type !== "separator")
315
+ .map((l) => l.originalLineNumber || l.newLineNumber || 0),
316
+ );
317
+ const maxLineNumberWidth = maxLineNumber.toString().length;
318
+
319
+ return (
320
+ <View flexDirection="column" {...viewProps}>
321
+ {isProcessing && (
322
+ <View marginBottom={0}>
323
+ <Text dimColor>Processing diff...</Text>
324
+ </View>
325
+ )}
326
+ <View flexDirection="column">
327
+ {diffLines.map((line, idx) => {
328
+ const pairedLine = linePairs.get(idx);
329
+
330
+ if (line.type === "separator") {
331
+ return (
332
+ <DiffLineContent
333
+ key={`sep-${idx}`}
334
+ line={line}
335
+ lineNumber={" ".repeat(maxLineNumberWidth)}
336
+ dimmed={dimmed}
337
+ />
338
+ );
339
+ }
340
+
341
+ const lineNum = line.originalLineNumber || line.newLineNumber || "";
342
+ const paddedLineNum = String(lineNum).padStart(maxLineNumberWidth, " ");
343
+
344
+ return (
345
+ <DiffLineContent
346
+ key={idx}
347
+ line={line}
348
+ pairedLine={pairedLine}
349
+ lineNumber={paddedLineNum}
350
+ dimmed={dimmed}
351
+ />
352
+ );
353
+ })}
354
+ </View>
355
+ </View>
356
+ );
357
+ },
358
+ );
359
+ DiffPreview.displayName = "DiffPreview";
@@ -0,0 +1,5 @@
1
+ export { DiffPreview, DiffPreviewTitle } from "./diff-preview.js";
2
+ export { PermissionOptions } from "./permission-options.js";
3
+ export type { PermissionOption } from "./permission-options.js";
4
+ export { ToolPermissionUI } from "./tool-permission-ui.js";
5
+ export type { ToolPermissionResult } from "../../tools/types.js";