ethagent 3.3.4 → 4.0.0

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 (322) hide show
  1. package/.claude-plugin/marketplace.json +11 -0
  2. package/.claude-plugin/plugin.json +35 -0
  3. package/LICENSE +1 -1
  4. package/README.md +64 -104
  5. package/commands/ethagent.md +40 -0
  6. package/package.json +16 -16
  7. package/src/app/keybindings/KeybindingProvider.tsx +1 -6
  8. package/src/app/keybindings/types.ts +1 -6
  9. package/src/cli/ResetConfirmView.tsx +54 -53
  10. package/src/cli/demo.ts +86 -0
  11. package/src/cli/hookIo.ts +45 -0
  12. package/src/cli/main.tsx +94 -123
  13. package/src/cli/memoryGuard.ts +49 -0
  14. package/src/cli/reset.ts +28 -70
  15. package/src/cli/sessionStart.ts +33 -0
  16. package/src/cli/status.ts +46 -0
  17. package/src/cli/sync.ts +167 -0
  18. package/src/cli/syncAdapters/claude-code.ts +86 -0
  19. package/src/cli/syncAdapters/codex.ts +66 -0
  20. package/src/cli/syncAdapters/index.ts +45 -0
  21. package/src/cli/syncAdapters/managedBlock.ts +175 -0
  22. package/src/cli/syncAdapters/shared.ts +63 -0
  23. package/src/identity/continuity/envelopeParse.ts +20 -1
  24. package/src/identity/continuity/publicSkills.ts +3 -1
  25. package/src/identity/continuity/skills/publicSkillsSync.ts +2 -1
  26. package/src/identity/continuity/skills/scaffold.ts +5 -2
  27. package/src/identity/continuity/snapshots.ts +12 -5
  28. package/src/identity/continuity/storage/defaults.ts +20 -19
  29. package/src/identity/continuity/storage/status.ts +1 -1
  30. package/src/identity/ens/ensLookup/constants.ts +1 -1
  31. package/src/identity/manager/IdentityManager.tsx +33 -0
  32. package/src/identity/{hub → manager}/OperationalRoutes.tsx +37 -18
  33. package/src/identity/{hub → manager}/Routes.tsx +48 -34
  34. package/src/identity/{hub → manager}/continuity/ContinuityDashboardScreen.tsx +9 -19
  35. package/src/identity/{hub → manager}/continuity/RebackupStorageScreen.tsx +3 -3
  36. package/src/identity/manager/continuity/RecoveryConfirmScreen.tsx +102 -0
  37. package/src/identity/{hub → manager}/continuity/SavePromptScreen.tsx +2 -3
  38. package/src/identity/{hub → manager}/continuity/completion.ts +1 -1
  39. package/src/identity/{hub → manager}/continuity/effects.ts +1 -1
  40. package/src/identity/{hub → manager}/continuity/skills/DeleteSkillConfirmScreen.tsx +2 -2
  41. package/src/identity/{hub → manager}/continuity/skills/NewSkillScreen.tsx +0 -5
  42. package/src/identity/{hub → manager}/continuity/skills/NewSkillVisibilityScreen.tsx +4 -4
  43. package/src/identity/{hub → manager}/continuity/skills/SkillActionsScreen.tsx +6 -22
  44. package/src/identity/{hub → manager}/continuity/skills/SkillsTreeScreen.tsx +5 -17
  45. package/src/identity/{hub → manager}/continuity/snapshot.ts +1 -1
  46. package/src/identity/{hub → manager}/continuity/vault.ts +1 -1
  47. package/src/identity/{hub → manager}/create/CreateFlow.tsx +59 -32
  48. package/src/identity/{hub → manager}/create/effects.ts +19 -10
  49. package/src/identity/manager/create/importScan.ts +122 -0
  50. package/src/identity/{hub → manager}/custody/CustodyEditFlow.tsx +17 -61
  51. package/src/identity/{hub → manager}/custody/actions.ts +1 -15
  52. package/src/identity/{hub → manager}/custody/routes.tsx +20 -40
  53. package/src/identity/{hub → manager}/custody/transactions.ts +1 -0
  54. package/src/identity/{hub → manager}/custody/types.ts +1 -2
  55. package/src/identity/{hub → manager}/custody/useCustodyEffects.ts +1 -1
  56. package/src/identity/{hub → manager}/ens/EnsEditAdvancedScreens.tsx +2 -2
  57. package/src/identity/{hub → manager}/ens/EnsEditMaintenanceScreens.tsx +12 -23
  58. package/src/identity/{hub → manager}/ens/EnsEditReviewScreens.tsx +18 -42
  59. package/src/identity/{hub → manager}/ens/EnsEditRunners.tsx +1 -1
  60. package/src/identity/{hub → manager}/ens/EnsEditShared.tsx +0 -2
  61. package/src/identity/{hub → manager}/ens/EnsEditSimpleScreens.tsx +10 -19
  62. package/src/identity/{hub → manager}/ens/EnsFlow.tsx +133 -41
  63. package/src/identity/{hub → manager}/ens/EnsOperatorWalletsScreen.tsx +14 -19
  64. package/src/identity/{hub → manager}/ens/editCopy.ts +1 -14
  65. package/src/identity/{hub → manager}/profile/EditProfileFlow.tsx +99 -66
  66. package/src/identity/{hub → manager}/profile/effects.ts +1 -3
  67. package/src/identity/{hub → manager}/profile/operatorSave.ts +1 -1
  68. package/src/identity/{hub → manager}/profile/state.ts +1 -1
  69. package/src/identity/{hub/identityHubReducer.ts → manager/reducer.ts} +25 -26
  70. package/src/identity/{hub → manager}/restore/RestoreFlow.tsx +16 -24
  71. package/src/identity/{hub → manager}/restore/apply.ts +1 -1
  72. package/src/identity/{hub → manager}/restore/auth.ts +1 -1
  73. package/src/identity/{hub → manager}/restore/discover.ts +1 -1
  74. package/src/identity/{hub → manager}/restore/fetch.ts +1 -1
  75. package/src/identity/{hub → manager}/restore/restoreAdmin.ts +1 -1
  76. package/src/identity/{hub → manager}/restore/useRestoreEffects.ts +2 -9
  77. package/src/identity/{hub → manager}/settings/StorageCredentialScreen.tsx +10 -25
  78. package/src/identity/{hub → manager}/shared/components/DetailsScreen.tsx +5 -7
  79. package/src/identity/{hub → manager}/shared/components/ErrorScreen.tsx +6 -10
  80. package/src/identity/{hub → manager}/shared/components/FlowTimeline.tsx +4 -3
  81. package/src/identity/{hub → manager}/shared/components/IdentitySummary.tsx +19 -59
  82. package/src/identity/manager/shared/components/LazyMenu.tsx +147 -0
  83. package/src/identity/manager/shared/components/MenuScreen.tsx +220 -0
  84. package/src/identity/manager/shared/components/OperationCompleteScreen.tsx +28 -0
  85. package/src/identity/{hub → manager}/shared/components/UnlinkedIdentityScreen.tsx +9 -10
  86. package/src/identity/{hub → manager}/shared/components/WalletApprovalScreen.tsx +1 -2
  87. package/src/identity/manager/shared/components/Wordmark.tsx +54 -0
  88. package/src/identity/{hub → manager}/shared/components/menuFlagsFromReconciliation.ts +39 -15
  89. package/src/identity/{hub → manager}/shared/effects/profilePrep.ts +1 -1
  90. package/src/identity/manager/shared/effects/types.ts +30 -0
  91. package/src/identity/{hub → manager}/shared/model/copy.ts +0 -4
  92. package/src/identity/{hub → manager}/shared/model/errors.ts +32 -3
  93. package/src/identity/{hub → manager}/shared/model/network.ts +2 -2
  94. package/src/identity/{hub → manager}/shared/reconciliation/agentReconciliation/hook.ts +5 -0
  95. package/src/identity/{hub → manager}/shared/reconciliation/agentReconciliation/run.ts +1 -1
  96. package/src/identity/{hub/shared/reconciliation/useAgentReconciliation.ts → manager/shared/reconciliation/index.ts} +6 -0
  97. package/src/identity/{hub → manager}/shared/utils.ts +6 -10
  98. package/src/identity/{hub → manager}/transfer/TokenTransferFlow.tsx +3 -3
  99. package/src/identity/{hub → manager}/transfer/TokenTransferScreens.tsx +4 -10
  100. package/src/identity/{hub → manager}/transfer/effects.ts +1 -1
  101. package/src/identity/{hub → manager}/types.ts +5 -6
  102. package/src/identity/{hub/useIdentityHubContinuity.ts → manager/useContinuity.ts} +59 -27
  103. package/src/identity/{hub/useIdentityHubController.ts → manager/useController.ts} +38 -35
  104. package/src/identity/{hub/useIdentityHubSideEffects.ts → manager/useSideEffects.ts} +40 -4
  105. package/src/identity/registry/erc8004/discovery.ts +3 -17
  106. package/src/identity/registry/erc8004/utils.ts +1 -1
  107. package/src/identity/storage/ipfs.ts +21 -1
  108. package/src/identity/wallet/browserWallet/html.ts +10 -2
  109. package/src/identity/wallet/browserWallet/http.ts +18 -0
  110. package/src/identity/wallet/browserWallet/requestServer.ts +5 -1
  111. package/src/identity/wallet/browserWallet/requests.ts +10 -28
  112. package/src/identity/wallet/browserWallet/session.ts +26 -33
  113. package/src/identity/wallet/browserWallet/validation.ts +14 -0
  114. package/src/identity/wallet/browserWallet/walletPageSource.ts +22 -40
  115. package/src/identity/wallet/page/boot.ts +43 -0
  116. package/src/identity/wallet/page/config.ts +59 -0
  117. package/src/identity/wallet/page/constants.ts +12 -0
  118. package/src/identity/wallet/page/copy.ts +47 -68
  119. package/src/identity/wallet/page/css.ts +638 -0
  120. package/src/identity/wallet/page/{errorView.ts → errors.ts} +5 -14
  121. package/src/identity/wallet/page/{controller.ts → flow.ts} +4 -71
  122. package/src/identity/wallet/page/markup.ts +44 -34
  123. package/src/identity/wallet/page/{walletProvider.ts → provider.ts} +0 -3
  124. package/src/identity/wallet/page/resize.ts +95 -0
  125. package/src/identity/wallet/page/state.ts +135 -8
  126. package/src/identity/wallet/page/timeline.ts +161 -0
  127. package/src/identity/wallet/page/view.ts +22 -302
  128. package/src/storage/config.ts +30 -80
  129. package/src/storage/reset.ts +31 -0
  130. package/src/storage/secrets.ts +1 -16
  131. package/src/ui/Select.tsx +27 -5
  132. package/src/ui/Spinner.tsx +16 -15
  133. package/src/ui/Surface.tsx +21 -17
  134. package/src/ui/TextArea.tsx +173 -0
  135. package/src/ui/TextInput.tsx +31 -133
  136. package/src/ui/theme.ts +22 -13
  137. package/src/utils/clipboard.ts +0 -140
  138. package/src/app/FirstRun.tsx +0 -577
  139. package/src/app/FirstRunTimeline.tsx +0 -51
  140. package/src/app/firstRunConfig.ts +0 -26
  141. package/src/app/hooks/useCancelRequest.ts +0 -22
  142. package/src/app/hooks/useDoublePress.ts +0 -46
  143. package/src/app/hooks/useExitOnCtrlC.ts +0 -36
  144. package/src/auth/openaiOAuth/credentials.ts +0 -47
  145. package/src/auth/openaiOAuth/crypto.ts +0 -23
  146. package/src/auth/openaiOAuth/index.ts +0 -238
  147. package/src/auth/openaiOAuth/landingPage.ts +0 -116
  148. package/src/auth/openaiOAuth/listener.ts +0 -151
  149. package/src/auth/openaiOAuth/refresh.ts +0 -70
  150. package/src/auth/openaiOAuth/shared.ts +0 -115
  151. package/src/chat/ChatBottomPane.tsx +0 -296
  152. package/src/chat/ChatScreen.tsx +0 -1685
  153. package/src/chat/ConversationStack.tsx +0 -56
  154. package/src/chat/MessageList.tsx +0 -638
  155. package/src/chat/SessionStatus.tsx +0 -53
  156. package/src/chat/chatEnvironment.ts +0 -16
  157. package/src/chat/chatScreenUtils.ts +0 -194
  158. package/src/chat/chatSessionState.ts +0 -146
  159. package/src/chat/chatTurnContext.ts +0 -50
  160. package/src/chat/chatTurnOrchestrator.ts +0 -603
  161. package/src/chat/chatTurnRows.ts +0 -64
  162. package/src/chat/commands.ts +0 -494
  163. package/src/chat/continuityEditReview.ts +0 -42
  164. package/src/chat/display/DiffView.tsx +0 -193
  165. package/src/chat/display/SyntaxText.tsx +0 -192
  166. package/src/chat/display/toolCallDisplay.ts +0 -103
  167. package/src/chat/display/toolResultDisplay.ts +0 -19
  168. package/src/chat/input/ChatInput.tsx +0 -625
  169. package/src/chat/input/chatInputHelpers.ts +0 -62
  170. package/src/chat/input/chatInputState.ts +0 -247
  171. package/src/chat/input/chatPaste.ts +0 -49
  172. package/src/chat/input/imageRefs.ts +0 -30
  173. package/src/chat/input/inputRendering.tsx +0 -93
  174. package/src/chat/input/textCursor.ts +0 -212
  175. package/src/chat/messageMarkdown.ts +0 -220
  176. package/src/chat/messageRows.ts +0 -43
  177. package/src/chat/planImplementation.ts +0 -62
  178. package/src/chat/slashCommandHandlers.ts +0 -122
  179. package/src/chat/slashCommandViews.ts +0 -120
  180. package/src/chat/transcript/TranscriptView.tsx +0 -184
  181. package/src/chat/transcript/transcriptViewport.ts +0 -295
  182. package/src/chat/views/ContextLimitView.tsx +0 -95
  183. package/src/chat/views/ContinuityEditReviewView.tsx +0 -50
  184. package/src/chat/views/CopyPicker.tsx +0 -50
  185. package/src/chat/views/PermissionPrompt.tsx +0 -156
  186. package/src/chat/views/PermissionsView.tsx +0 -165
  187. package/src/chat/views/PlanApprovalView.tsx +0 -91
  188. package/src/chat/views/ResumeView.tsx +0 -273
  189. package/src/chat/views/RewindView.tsx +0 -412
  190. package/src/cli/preview.tsx +0 -14
  191. package/src/cli/updateNotice.ts +0 -54
  192. package/src/identity/continuity/privateEdit/apply.ts +0 -170
  193. package/src/identity/continuity/privateEdit/diff.ts +0 -6
  194. package/src/identity/continuity/privateEdit/files.ts +0 -23
  195. package/src/identity/continuity/privateEdit/types.ts +0 -28
  196. package/src/identity/continuity/privateEdit.ts +0 -46
  197. package/src/identity/hub/IdentityHub.tsx +0 -14
  198. package/src/identity/hub/continuity/RecoveryConfirmScreen.tsx +0 -104
  199. package/src/identity/hub/ens/effects.ts +0 -218
  200. package/src/identity/hub/shared/components/MenuScreen.tsx +0 -241
  201. package/src/identity/hub/shared/effects/types.ts +0 -53
  202. package/src/identity/hub/shared/reconciliation/index.ts +0 -14
  203. package/src/identity/wallet/page/grainient.ts +0 -278
  204. package/src/identity/wallet/page/html.ts +0 -28
  205. package/src/identity/wallet/page/styles/base.ts +0 -260
  206. package/src/identity/wallet/page/styles/components.ts +0 -262
  207. package/src/identity/wallet/page/styles/index.ts +0 -5
  208. package/src/identity/wallet/page/styles/responsive.ts +0 -247
  209. package/src/identity/wallet/page.tsx +0 -38
  210. package/src/mcp/approvals.ts +0 -113
  211. package/src/mcp/config.ts +0 -235
  212. package/src/mcp/manager.ts +0 -482
  213. package/src/mcp/managerHelpers.ts +0 -70
  214. package/src/mcp/names.ts +0 -19
  215. package/src/mcp/output.ts +0 -96
  216. package/src/models/ModelPicker.tsx +0 -1009
  217. package/src/models/catalog.ts +0 -327
  218. package/src/models/huggingface.ts +0 -712
  219. package/src/models/huggingfaceStorage.ts +0 -136
  220. package/src/models/llamacpp.ts +0 -848
  221. package/src/models/llamacppCommands.ts +0 -44
  222. package/src/models/llamacppConfig.ts +0 -34
  223. package/src/models/llamacppDiscovery.ts +0 -176
  224. package/src/models/llamacppOutput.ts +0 -65
  225. package/src/models/llamacppPreflight.ts +0 -158
  226. package/src/models/modelDisplay.ts +0 -180
  227. package/src/models/modelPickerCatalogFlow.ts +0 -56
  228. package/src/models/modelPickerCredentials.ts +0 -166
  229. package/src/models/modelPickerData.ts +0 -41
  230. package/src/models/modelPickerDisplay.tsx +0 -132
  231. package/src/models/modelPickerHfFlow.ts +0 -192
  232. package/src/models/modelPickerLocalRunnerFlow.ts +0 -115
  233. package/src/models/modelPickerOptions.ts +0 -457
  234. package/src/models/modelPickerTypes.ts +0 -69
  235. package/src/models/modelPickerUninstallFlow.ts +0 -48
  236. package/src/models/modelPickerViewHelpers.ts +0 -174
  237. package/src/models/modelRecommendation.ts +0 -139
  238. package/src/models/providerDisplay.ts +0 -16
  239. package/src/models/runtimeDetection.ts +0 -81
  240. package/src/models/uncensoredCatalog.ts +0 -86
  241. package/src/providers/anthropic.ts +0 -290
  242. package/src/providers/contracts.ts +0 -71
  243. package/src/providers/errors.ts +0 -80
  244. package/src/providers/gemini.ts +0 -391
  245. package/src/providers/openai-chat.ts +0 -474
  246. package/src/providers/openai-responses-format.ts +0 -177
  247. package/src/providers/openai-responses.ts +0 -306
  248. package/src/providers/openaiChatWire.ts +0 -124
  249. package/src/providers/registry.ts +0 -120
  250. package/src/providers/retry.ts +0 -58
  251. package/src/providers/sse.ts +0 -93
  252. package/src/runtime/compaction.ts +0 -395
  253. package/src/runtime/cwd.ts +0 -43
  254. package/src/runtime/providerTurn.ts +0 -38
  255. package/src/runtime/sessionMode.ts +0 -55
  256. package/src/runtime/systemPrompt.ts +0 -213
  257. package/src/runtime/textToolParser.ts +0 -161
  258. package/src/runtime/toolClaimGuards.ts +0 -143
  259. package/src/runtime/toolExecution.ts +0 -304
  260. package/src/runtime/toolIntent.ts +0 -143
  261. package/src/runtime/turn.ts +0 -369
  262. package/src/runtime/turnNudges.ts +0 -223
  263. package/src/runtime/turnTypes.ts +0 -86
  264. package/src/storage/factoryReset.ts +0 -127
  265. package/src/storage/history.ts +0 -58
  266. package/src/storage/permissions.ts +0 -76
  267. package/src/storage/rewind.ts +0 -266
  268. package/src/storage/sessionExport.ts +0 -49
  269. package/src/storage/sessions.ts +0 -495
  270. package/src/tools/bashSafety.ts +0 -186
  271. package/src/tools/bashTool.ts +0 -140
  272. package/src/tools/changeDirectoryTool.ts +0 -213
  273. package/src/tools/contracts.ts +0 -192
  274. package/src/tools/deleteFileTool.ts +0 -116
  275. package/src/tools/editTool.ts +0 -165
  276. package/src/tools/editUtils.ts +0 -170
  277. package/src/tools/fileDiff.ts +0 -261
  278. package/src/tools/listDirectoryTool.ts +0 -55
  279. package/src/tools/listSkillFilesTool.ts +0 -77
  280. package/src/tools/listSkillsTool.ts +0 -68
  281. package/src/tools/mcpResourceTools.ts +0 -95
  282. package/src/tools/permissionRules.ts +0 -85
  283. package/src/tools/privateContinuityEditTool.ts +0 -187
  284. package/src/tools/privateContinuityReadTool.ts +0 -106
  285. package/src/tools/readSkillTool.ts +0 -107
  286. package/src/tools/readTool.ts +0 -85
  287. package/src/tools/registry.ts +0 -103
  288. package/src/tools/writeFileTool.ts +0 -167
  289. package/src/ui/BrandSplash.tsx +0 -133
  290. package/src/ui/terminalTitle.ts +0 -30
  291. package/src/utils/images.ts +0 -140
  292. package/src/utils/markdownSegments.ts +0 -51
  293. package/src/utils/messages.ts +0 -37
  294. package/src/utils/withRetry.ts +0 -324
  295. /package/src/identity/{hub → manager}/continuity/state.ts +0 -0
  296. /package/src/identity/{hub → manager}/custody/helpers.ts +0 -0
  297. /package/src/identity/{hub → manager}/custody/preflight.ts +0 -0
  298. /package/src/identity/{hub → manager}/custody/state.ts +0 -0
  299. /package/src/identity/{hub → manager}/custody/useCustodyFlow.tsx +0 -0
  300. /package/src/identity/{hub → manager}/ens/EnsEditFlow.tsx +0 -0
  301. /package/src/identity/{hub → manager}/ens/advancedEnsValidation.ts +0 -0
  302. /package/src/identity/{hub → manager}/ens/state.ts +0 -0
  303. /package/src/identity/{hub → manager}/ens/transactions.ts +0 -0
  304. /package/src/identity/{hub → manager}/ens/types.ts +0 -0
  305. /package/src/identity/{hub → manager}/profile/identity.ts +0 -0
  306. /package/src/identity/{hub → manager}/restore/envelopes.ts +0 -0
  307. /package/src/identity/{hub → manager}/restore/helpers.ts +0 -0
  308. /package/src/identity/{hub → manager}/restore/recovery.ts +0 -0
  309. /package/src/identity/{hub → manager}/restore/resolve.ts +0 -0
  310. /package/src/identity/{hub → manager}/shared/components/BusyScreen.tsx +0 -0
  311. /package/src/identity/{hub → manager}/shared/components/NetworkScreen.tsx +0 -0
  312. /package/src/identity/{hub → manager}/shared/components/PinataJwtInput.tsx +0 -0
  313. /package/src/identity/{hub → manager}/shared/effects/receipts.ts +0 -0
  314. /package/src/identity/{hub → manager}/shared/effects/sync.ts +0 -0
  315. /package/src/identity/{hub → manager}/shared/model/format.ts +0 -0
  316. /package/src/identity/{hub → manager}/shared/operatorWallets.ts +0 -0
  317. /package/src/identity/{hub → manager}/shared/reconciliation/agentReconciliation/ownership.ts +0 -0
  318. /package/src/identity/{hub → manager}/shared/reconciliation/agentReconciliation/types.ts +0 -0
  319. /package/src/identity/{hub → manager}/shared/reconciliation/walletSetup.ts +0 -0
  320. /package/src/identity/{hub → manager}/shared/txGuard.ts +0 -0
  321. /package/src/identity/{hub → manager}/transfer/progress.ts +0 -0
  322. /package/src/identity/{hub → manager}/transfer/state.ts +0 -0
@@ -1,193 +0,0 @@
1
- import React from 'react'
2
- import { Box, Text } from 'ink'
3
- import { theme } from '../../ui/theme.js'
4
- import { inferLanguageFromPath, SyntaxLine } from './SyntaxText.js'
5
-
6
- const EMPTY_DIFF_LINE = ' '
7
-
8
- type DiffLineTone = 'added' | 'removed' | 'added-header' | 'removed-header' | 'hunk' | 'context' | 'marker'
9
-
10
- type DiffLineStyle = {
11
- tone: DiffLineTone
12
- color: string
13
- backgroundColor?: string
14
- }
15
-
16
- type NumberedDiffLine = {
17
- line: string
18
- oldLine?: number
19
- newLine?: number
20
- }
21
-
22
- export function diffLineColor(line: string): string {
23
- return diffLineStyle(line).color
24
- }
25
-
26
- export function diffLineStyle(line: string): DiffLineStyle {
27
- if (line.startsWith('+++')) return { tone: 'added-header', color: theme.diffAdded }
28
- if (line.startsWith('---')) return { tone: 'removed-header', color: theme.diffRemoved }
29
- if (line.startsWith('+')) {
30
- return { tone: 'added', color: theme.text, backgroundColor: theme.diffAddedBackground }
31
- }
32
- if (line.startsWith('-')) {
33
- return { tone: 'removed', color: theme.text, backgroundColor: theme.diffRemovedBackground }
34
- }
35
- if (line.startsWith('@@')) return { tone: 'hunk', color: theme.accentPeriwinkle }
36
- if (line.startsWith('...')) return { tone: 'marker', color: theme.dim }
37
- return { tone: 'context', color: theme.textSubtle }
38
- }
39
-
40
- export const DiffView: React.FC<{ diff: string }> = ({ diff }) => (
41
- <DiffLines lines={visibleDiffLines(numberDiffLines(diff))} language={inferDiffLanguage(diff)} />
42
- )
43
-
44
- const DiffLines: React.FC<{ lines: NumberedDiffLine[]; language: string | null }> = ({ lines, language }) => {
45
- const width = lineNumberWidth(lines)
46
- return (
47
- <Box flexDirection="column">
48
- {lines.map((line, index) => (
49
- <DiffLine
50
- key={index}
51
- line={line.line}
52
- oldLine={line.oldLine}
53
- newLine={line.newLine}
54
- width={width}
55
- language={language}
56
- />
57
- ))}
58
- </Box>
59
- )
60
- }
61
-
62
- const DiffLine: React.FC<{
63
- line: string
64
- oldLine?: number
65
- newLine?: number
66
- width: number
67
- language: string | null
68
- }> = ({
69
- line,
70
- oldLine,
71
- newLine,
72
- width,
73
- language,
74
- }) => {
75
- const style = diffLineStyle(line)
76
- const number = renderLineNumber(displayLineNumber(oldLine, newLine, style.tone), width)
77
- if (line.length === 0) {
78
- return <Text color={style.color}>{EMPTY_DIFF_LINE}</Text>
79
- }
80
-
81
- if (style.tone === 'added' || style.tone === 'removed') {
82
- const prefixColor = style.tone === 'added' ? theme.diffAdded : theme.diffRemoved
83
- return (
84
- <Box width="100%" backgroundColor={style.backgroundColor}>
85
- <Text>
86
- {number}
87
- <Text color={prefixColor}>{line.slice(0, 1)} </Text>
88
- <SyntaxLine line={line.slice(1)} lang={language} fallbackColor={style.color} />
89
- </Text>
90
- </Box>
91
- )
92
- }
93
-
94
- if (style.tone === 'context' && line.startsWith(' ')) {
95
- return (
96
- <Text color={style.color}>
97
- {number}
98
- <Text>{' '}</Text>
99
- <SyntaxLine line={line.slice(1)} lang={language} fallbackColor={style.color} />
100
- </Text>
101
- )
102
- }
103
-
104
- return <Text color={style.color}>{line}</Text>
105
- }
106
-
107
- function lineNumberWidth(lines: NumberedDiffLine[]): number {
108
- return Math.max(
109
- 2,
110
- ...lines.map(line => String(displayLineNumber(line.oldLine, line.newLine, diffLineStyle(line.line).tone) ?? '').length),
111
- )
112
- }
113
-
114
- function displayLineNumber(
115
- oldLine: number | undefined,
116
- newLine: number | undefined,
117
- tone: DiffLineTone,
118
- ): number | undefined {
119
- if (tone === 'removed') return oldLine
120
- return newLine ?? oldLine
121
- }
122
-
123
- function renderLineNumber(line: number | undefined, width: number): React.ReactNode {
124
- if (line === undefined) return null
125
- return <Text color={theme.dim}>{String(line).padStart(width, ' ')} </Text>
126
- }
127
-
128
- function visibleDiffLines(lines: NumberedDiffLine[]): NumberedDiffLine[] {
129
- return lines.filter(line => {
130
- const tone = diffLineStyle(line.line).tone
131
- return tone !== 'added-header' && tone !== 'removed-header' && tone !== 'hunk'
132
- })
133
- }
134
-
135
- function inferDiffLanguage(diff: string): string | null {
136
- for (const line of diff.split('\n')) {
137
- if (!line.startsWith('+++ ') || line === '+++ /dev/null') continue
138
- return inferLanguageFromPath(line.slice(4).trim())
139
- }
140
- for (const line of diff.split('\n')) {
141
- if (!line.startsWith('--- ') || line === '--- /dev/null') continue
142
- return inferLanguageFromPath(line.slice(4).trim())
143
- }
144
- return null
145
- }
146
-
147
- export function numberDiffLines(diff: string): NumberedDiffLine[] {
148
- const out: NumberedDiffLine[] = []
149
- let oldLine: number | undefined
150
- let newLine: number | undefined
151
-
152
- for (const line of diff.split('\n')) {
153
- const hunk = parseHunkHeader(line)
154
- if (hunk) {
155
- oldLine = hunk.oldStart
156
- newLine = hunk.newStart
157
- out.push({ line })
158
- continue
159
- }
160
-
161
- if (oldLine !== undefined && newLine !== undefined) {
162
- if (line.startsWith(' ')) {
163
- out.push({ line, oldLine, newLine })
164
- oldLine += 1
165
- newLine += 1
166
- continue
167
- }
168
- if (line.startsWith('-') && !line.startsWith('---')) {
169
- out.push({ line, oldLine })
170
- oldLine += 1
171
- continue
172
- }
173
- if (line.startsWith('+') && !line.startsWith('+++')) {
174
- out.push({ line, newLine })
175
- newLine += 1
176
- continue
177
- }
178
- }
179
-
180
- out.push({ line })
181
- }
182
-
183
- return out
184
- }
185
-
186
- function parseHunkHeader(line: string): { oldStart: number; newStart: number } | null {
187
- const match = line.match(/^@@ -(\d+)(?:,\d+)? \+(\d+)(?:,\d+)? @@/)
188
- if (!match) return null
189
- return {
190
- oldStart: Number(match[1]),
191
- newStart: Number(match[2]),
192
- }
193
- }
@@ -1,192 +0,0 @@
1
- import React from 'react'
2
- import { Text } from 'ink'
3
- import { styledCharsFromTokens, tokenize } from '@alcalzone/ansi-tokenize'
4
- import { highlight, supportsLanguage, type Theme } from 'cli-highlight'
5
- import { theme } from '../../ui/theme.js'
6
-
7
- type Span = {
8
- text: string
9
- color?: string
10
- bold?: boolean
11
- italic?: boolean
12
- }
13
-
14
- const ANSI_RESET_FG = '\x1B[39m'
15
- const ANSI_RESET_BOLD = '\x1B[22m'
16
- const ANSI_RESET_ITALIC = '\x1B[23m'
17
-
18
- const HIGHLIGHT_THEME: Theme = {
19
- keyword: style(theme.codeKeyword, { bold: true }),
20
- built_in: style(theme.codeBuiltin),
21
- type: style(theme.codeType),
22
- literal: style(theme.codeKeyword),
23
- number: style(theme.codeNumber),
24
- regexp: style(theme.codeString),
25
- string: style(theme.codeString),
26
- class: style(theme.codeType),
27
- function: style(theme.codeFunction),
28
- title: style(theme.codeFunction),
29
- comment: style(theme.codeComment, { italic: true }),
30
- doctag: style(theme.codeComment, { italic: true }),
31
- meta: style(theme.dim),
32
- tag: style(theme.codeTag, { bold: true }),
33
- name: style(theme.codeTag, { bold: true }),
34
- attr: style(theme.codeAttribute),
35
- attribute: style(theme.codeProperty),
36
- variable: style(theme.codeProperty),
37
- addition: style(theme.diffAdded),
38
- deletion: style(theme.diffRemoved),
39
- default: style(theme.textSubtle),
40
- }
41
-
42
- const PROGRAMMING_LANGUAGES = new Set([
43
- 'bash',
44
- 'css',
45
- 'go',
46
- 'java',
47
- 'javascript',
48
- 'json',
49
- 'python',
50
- 'rust',
51
- 'solidity',
52
- 'sql',
53
- 'typescript',
54
- 'xml',
55
- 'yaml',
56
- ])
57
-
58
- const LANGUAGE_BY_EXTENSION: Record<string, string> = {
59
- cjs: 'javascript',
60
- css: 'css',
61
- html: 'xml',
62
- js: 'javascript',
63
- json: 'json',
64
- jsonc: 'json',
65
- jsx: 'javascript',
66
- md: 'markdown',
67
- mjs: 'javascript',
68
- py: 'python',
69
- sh: 'bash',
70
- ts: 'typescript',
71
- tsx: 'typescript',
72
- yml: 'yaml',
73
- yaml: 'yaml',
74
- }
75
-
76
- export const SyntaxLine: React.FC<{ line: string; lang?: string | null; fallbackColor?: string }> = ({
77
- line,
78
- lang,
79
- fallbackColor = theme.textSubtle,
80
- }) => (
81
- <>
82
- {syntaxLineSpans(line, lang, fallbackColor).map((span, index) => (
83
- <Text key={index} color={span.color} bold={span.bold} italic={span.italic}>
84
- {span.text}
85
- </Text>
86
- ))}
87
- </>
88
- )
89
-
90
- export function syntaxLineSpans(line: string, lang?: string | null, fallbackColor: string = theme.textSubtle): Span[] {
91
- const code = line.length === 0 ? ' ' : line
92
- const language = supportedLanguage(lang)
93
- if (!language || !PROGRAMMING_LANGUAGES.has(language)) {
94
- return [{ text: code, color: fallbackColor }]
95
- }
96
- const highlighted = highlight(code, {
97
- language: language ?? undefined,
98
- ignoreIllegals: true,
99
- theme: HIGHLIGHT_THEME,
100
- })
101
- const spans = spansFromAnsi(highlighted)
102
- return spans.length > 0 ? spans : [{ text: code, color: fallbackColor }]
103
- }
104
-
105
- export function inferLanguageFromPath(path: string): string | null {
106
- const clean = path
107
- .replace(/^["']|["']$/g, '')
108
- .replace(/^[ab]\//, '')
109
- .replace(/\\/g, '/')
110
- .split('/')
111
- .pop()
112
- const extension = clean?.match(/\.([A-Za-z0-9]+)$/)?.[1]?.toLowerCase()
113
- return extension ? LANGUAGE_BY_EXTENSION[extension] ?? null : null
114
- }
115
-
116
- function supportedLanguage(lang?: string | null): string | null {
117
- if (!lang) return null
118
- const normalized = LANGUAGE_BY_EXTENSION[lang.toLowerCase()] ?? lang.toLowerCase()
119
- return supportsLanguage(normalized) ? normalized : null
120
- }
121
-
122
- function style(color: string, options: { bold?: boolean; italic?: boolean } = {}): (text: string) => string {
123
- return text => [
124
- colorCode(color),
125
- options.bold ? '\x1B[1m' : '',
126
- options.italic ? '\x1B[3m' : '',
127
- text,
128
- options.italic ? ANSI_RESET_ITALIC : '',
129
- options.bold ? ANSI_RESET_BOLD : '',
130
- ANSI_RESET_FG,
131
- ].join('')
132
- }
133
-
134
- function colorCode(hex: string): string {
135
- const [r, g, b] = parseHexColor(hex)
136
- return `\x1B[38;2;${r};${g};${b}m`
137
- }
138
-
139
- function parseHexColor(hex: string): [number, number, number] {
140
- const clean = hex.replace(/^#/, '')
141
- return [
142
- Number.parseInt(clean.slice(0, 2), 16),
143
- Number.parseInt(clean.slice(2, 4), 16),
144
- Number.parseInt(clean.slice(4, 6), 16),
145
- ]
146
- }
147
-
148
- function spansFromAnsi(value: string): Span[] {
149
- const chars = styledCharsFromTokens(tokenize(value))
150
- const spans: Span[] = []
151
- for (const char of chars) {
152
- const span = spanFromCodes(char.value, char.styles.map(styleCode => styleCode.code))
153
- const previous = spans[spans.length - 1]
154
- if (previous && sameStyle(previous, span)) {
155
- previous.text += span.text
156
- } else {
157
- spans.push(span)
158
- }
159
- }
160
- return spans
161
- }
162
-
163
- function spanFromCodes(text: string, codes: string[]): Span {
164
- return {
165
- text,
166
- color: colorFromCodes(codes),
167
- bold: codes.includes('\x1B[1m') || undefined,
168
- italic: codes.includes('\x1B[3m') || undefined,
169
- }
170
- }
171
-
172
- function colorFromCodes(codes: string[]): string | undefined {
173
- for (let index = codes.length - 1; index >= 0; index -= 1) {
174
- const match = codes[index]?.match(/\x1B\[38;2;(\d+);(\d+);(\d+)m/)
175
- if (match) {
176
- return rgbToHex(Number(match[1]), Number(match[2]), Number(match[3]))
177
- }
178
- }
179
- return undefined
180
- }
181
-
182
- function rgbToHex(r: number, g: number, b: number): string {
183
- return `#${hexByte(r)}${hexByte(g)}${hexByte(b)}`
184
- }
185
-
186
- function hexByte(value: number): string {
187
- return Math.max(0, Math.min(255, value)).toString(16).padStart(2, '0')
188
- }
189
-
190
- function sameStyle(a: Span, b: Span): boolean {
191
- return a.color === b.color && a.bold === b.bold && a.italic === b.italic
192
- }
@@ -1,103 +0,0 @@
1
- const MAX_ARG_SUMMARY = 80
2
-
3
- export function formatToolCall(
4
- name: string,
5
- input: Record<string, unknown> | undefined,
6
- ): { displayName: string; argSummary: string } {
7
- const safeInput = isRecord(input) ? input : {}
8
- switch (name) {
9
- case 'read_file':
10
- return { displayName: 'Read', argSummary: readArgs(safeInput) }
11
- case 'list_directory':
12
- return { displayName: 'List', argSummary: pathArg(safeInput, '.') }
13
- case 'run_bash':
14
- return { displayName: 'Bash', argSummary: bashArgs(safeInput) }
15
- case 'edit_file':
16
- return { displayName: 'Edit', argSummary: pathArg(safeInput) }
17
- case 'write_file':
18
- return { displayName: 'Write', argSummary: pathArg(safeInput) }
19
- case 'delete_file':
20
- return { displayName: 'Delete', argSummary: pathArg(safeInput) }
21
- case 'change_directory':
22
- return { displayName: 'Cd', argSummary: pathArg(safeInput) }
23
- case 'read_private_continuity_file':
24
- return { displayName: 'ReadPrivate', argSummary: privateArgs(safeInput) }
25
- case 'propose_private_continuity_edit':
26
- return { displayName: 'EditPrivate', argSummary: stringArg(safeInput, 'file') }
27
- case 'list_mcp_resources':
28
- return { displayName: 'ListMcp', argSummary: stringArg(safeInput, 'server') }
29
- case 'read_mcp_resource':
30
- return { displayName: 'ReadMcp', argSummary: mcpReadArgs(safeInput) }
31
- default:
32
- return { displayName: humanize(name), argSummary: '' }
33
- }
34
- }
35
-
36
- function readArgs(input: Record<string, unknown>): string {
37
- const filePath = pathArg(input)
38
- const start = numberArg(input, 'startLine')
39
- const end = numberArg(input, 'endLine')
40
- if (start || end) {
41
- const range = `lines ${start ?? 1}-${end ?? 'end'}`
42
- return truncate(filePath ? `${filePath} · ${range}` : range)
43
- }
44
- return truncate(filePath)
45
- }
46
-
47
- function privateArgs(input: Record<string, unknown>): string {
48
- const file = stringArg(input, 'file')
49
- const start = numberArg(input, 'startLine')
50
- const end = numberArg(input, 'endLine')
51
- if (start || end) {
52
- return truncate(`${file} · lines ${start ?? 1}-${end ?? 'end'}`)
53
- }
54
- return truncate(file)
55
- }
56
-
57
- function bashArgs(input: Record<string, unknown>): string {
58
- const command = stringArg(input, 'command')
59
- if (!command) return ''
60
- const firstLine = command.split('\n')[0]?.trim() ?? ''
61
- return truncate(firstLine)
62
- }
63
-
64
- function mcpReadArgs(input: Record<string, unknown>): string {
65
- const server = stringArg(input, 'server')
66
- const uri = stringArg(input, 'uri')
67
- if (server && uri) return truncate(`${server} / ${uri}`)
68
- return truncate(server || uri)
69
- }
70
-
71
- function pathArg(input: Record<string, unknown>, fallback = ''): string {
72
- const raw = stringArg(input, 'path')
73
- if (!raw) return fallback
74
- return raw.replace(/\\/g, '/')
75
- }
76
-
77
- function stringArg(input: Record<string, unknown>, key: string): string {
78
- const value = input[key]
79
- return typeof value === 'string' ? value : ''
80
- }
81
-
82
- function numberArg(input: Record<string, unknown>, key: string): number | undefined {
83
- const value = input[key]
84
- return typeof value === 'number' && Number.isFinite(value) ? value : undefined
85
- }
86
-
87
- function truncate(text: string): string {
88
- const flat = text.replace(/\s+/g, ' ').trim()
89
- if (flat.length <= MAX_ARG_SUMMARY) return flat
90
- return `${flat.slice(0, MAX_ARG_SUMMARY - 1)}…`
91
- }
92
-
93
- function humanize(name: string): string {
94
- return name
95
- .split('_')
96
- .filter(part => part.length > 0)
97
- .map(part => part.charAt(0).toUpperCase() + part.slice(1))
98
- .join('')
99
- }
100
-
101
- function isRecord(value: unknown): value is Record<string, unknown> {
102
- return typeof value === 'object' && value !== null && !Array.isArray(value)
103
- }
@@ -1,19 +0,0 @@
1
- import { splitFileChangeResult } from '../../tools/fileDiff.js'
2
-
3
- const COMPACT_SUCCESS_TOOL_RESULTS = new Set([
4
- 'read_file',
5
- 'read_private_continuity_file',
6
- ])
7
-
8
- export function hidesSuccessfulToolResultContent(name: string, isError?: boolean): boolean {
9
- return !isError && COMPACT_SUCCESS_TOOL_RESULTS.has(name)
10
- }
11
-
12
- export function toolResultDiffContent(content: string, isError?: boolean): string | undefined {
13
- if (isError) return undefined
14
- return splitFileChangeResult(content).diff
15
- }
16
-
17
- export function toolResultTextContent(content: string): string {
18
- return splitFileChangeResult(content).content
19
- }