@iaforged/context-code 1.0.63 → 1.0.67

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 (2000) hide show
  1. package/LICENSE.md +1 -1
  2. package/README.md +637 -9
  3. package/context-bootstrap.js +28 -28
  4. package/package.json +169 -170
  5. package/dist/src/QueryEngine.js +0 -928
  6. package/dist/src/Task.js +0 -49
  7. package/dist/src/Tool.js +0 -56
  8. package/dist/src/assistant/AssistantSessionChooser.js +0 -16
  9. package/dist/src/assistant/index.js +0 -16
  10. package/dist/src/assistant/sessionDiscovery.js +0 -16
  11. package/dist/src/assistant/sessionHistory.js +0 -47
  12. package/dist/src/bootstrap/state.js +0 -1165
  13. package/dist/src/bridge/bridgeApi.js +0 -304
  14. package/dist/src/bridge/bridgeConfig.js +0 -39
  15. package/dist/src/bridge/bridgeDebug.js +0 -73
  16. package/dist/src/bridge/bridgeEnabled.js +0 -187
  17. package/dist/src/bridge/bridgeMain.js +0 -2289
  18. package/dist/src/bridge/bridgeMessaging.js +0 -353
  19. package/dist/src/bridge/bridgePermissionCallbacks.js +0 -10
  20. package/dist/src/bridge/bridgePointer.js +0 -175
  21. package/dist/src/bridge/bridgeStatusUtil.js +0 -105
  22. package/dist/src/bridge/bridgeUI.js +0 -412
  23. package/dist/src/bridge/capacityWake.js +0 -35
  24. package/dist/src/bridge/codeSessionApi.js +0 -111
  25. package/dist/src/bridge/createSession.js +0 -273
  26. package/dist/src/bridge/debugUtils.js +0 -115
  27. package/dist/src/bridge/envLessBridgeConfig.js +0 -121
  28. package/dist/src/bridge/flushGate.js +0 -65
  29. package/dist/src/bridge/inboundAttachments.js +0 -152
  30. package/dist/src/bridge/inboundMessages.js +0 -63
  31. package/dist/src/bridge/initReplBridge.js +0 -428
  32. package/dist/src/bridge/jwtUtils.js +0 -185
  33. package/dist/src/bridge/pollConfig.js +0 -85
  34. package/dist/src/bridge/pollConfigDefaults.js +0 -62
  35. package/dist/src/bridge/remoteBridgeCore.js +0 -712
  36. package/dist/src/bridge/replBridge.js +0 -1720
  37. package/dist/src/bridge/replBridgeHandle.js +0 -30
  38. package/dist/src/bridge/replBridgeTransport.js +0 -236
  39. package/dist/src/bridge/sessionIdCompat.js +0 -56
  40. package/dist/src/bridge/sessionRunner.js +0 -421
  41. package/dist/src/bridge/trustedDevice.js +0 -172
  42. package/dist/src/bridge/types.js +0 -9
  43. package/dist/src/bridge/workSecret.js +0 -99
  44. package/dist/src/buddy/CompanionSprite.js +0 -349
  45. package/dist/src/buddy/companion.js +0 -107
  46. package/dist/src/buddy/prompt.js +0 -33
  47. package/dist/src/buddy/sprites.js +0 -488
  48. package/dist/src/buddy/types.js +0 -90
  49. package/dist/src/buddy/useBuddyNotification.js +0 -90
  50. package/dist/src/cli/bg.js +0 -16
  51. package/dist/src/cli/exit.js +0 -30
  52. package/dist/src/cli/handlers/agents.js +0 -55
  53. package/dist/src/cli/handlers/ant.js +0 -16
  54. package/dist/src/cli/handlers/auth.js +0 -312
  55. package/dist/src/cli/handlers/autoMode.js +0 -128
  56. package/dist/src/cli/handlers/mcp.js +0 -334
  57. package/dist/src/cli/handlers/plugins.js +0 -634
  58. package/dist/src/cli/handlers/projects_bridge.js +0 -40
  59. package/dist/src/cli/handlers/templateJobs.js +0 -16
  60. package/dist/src/cli/handlers/util.js +0 -76
  61. package/dist/src/cli/ndjsonSafeStringify.js +0 -27
  62. package/dist/src/cli/print.js +0 -4225
  63. package/dist/src/cli/remoteIO.js +0 -208
  64. package/dist/src/cli/rollback.js +0 -16
  65. package/dist/src/cli/structuredIO.js +0 -644
  66. package/dist/src/cli/transports/HybridTransport.js +0 -233
  67. package/dist/src/cli/transports/SSETransport.js +0 -538
  68. package/dist/src/cli/transports/SerialBatchEventUploader.js +0 -224
  69. package/dist/src/cli/transports/Transport.js +0 -1
  70. package/dist/src/cli/transports/WebSocketTransport.js +0 -613
  71. package/dist/src/cli/transports/WorkerStateUploader.js +0 -88
  72. package/dist/src/cli/transports/ccrClient.js +0 -711
  73. package/dist/src/cli/transports/transportUtils.js +0 -39
  74. package/dist/src/cli/up.js +0 -16
  75. package/dist/src/cli/update.js +0 -315
  76. package/dist/src/commands/add-dir/add-dir.js +0 -121
  77. package/dist/src/commands/add-dir/index.js +0 -8
  78. package/dist/src/commands/add-dir/validation.js +0 -76
  79. package/dist/src/commands/advisor.js +0 -88
  80. package/dist/src/commands/agents/agents.js +0 -9
  81. package/dist/src/commands/agents/index.js +0 -7
  82. package/dist/src/commands/ant-trace/index.js +0 -1
  83. package/dist/src/commands/assistant/assistant.js +0 -16
  84. package/dist/src/commands/autofix-pr/index.js +0 -1
  85. package/dist/src/commands/backfill-sessions/index.js +0 -1
  86. package/dist/src/commands/branch/branch.js +0 -205
  87. package/dist/src/commands/branch/index.js +0 -11
  88. package/dist/src/commands/break-cache/index.js +0 -1
  89. package/dist/src/commands/bridge/bridge.js +0 -512
  90. package/dist/src/commands/bridge/index.js +0 -22
  91. package/dist/src/commands/bridge-kick.js +0 -179
  92. package/dist/src/commands/brief.js +0 -94
  93. package/dist/src/commands/btw/btw.js +0 -234
  94. package/dist/src/commands/btw/index.js +0 -9
  95. package/dist/src/commands/bughunter/index.js +0 -1
  96. package/dist/src/commands/chrome/chrome.js +0 -291
  97. package/dist/src/commands/chrome/index.js +0 -10
  98. package/dist/src/commands/clear/caches.js +0 -116
  99. package/dist/src/commands/clear/clear.js +0 -5
  100. package/dist/src/commands/clear/conversation.js +0 -191
  101. package/dist/src/commands/clear/index.js +0 -9
  102. package/dist/src/commands/color/color.js +0 -58
  103. package/dist/src/commands/color/index.js +0 -9
  104. package/dist/src/commands/commit-push-pr.js +0 -137
  105. package/dist/src/commands/commit.js +0 -80
  106. package/dist/src/commands/compact/compact.js +0 -196
  107. package/dist/src/commands/compact/index.js +0 -11
  108. package/dist/src/commands/config/config.js +0 -5
  109. package/dist/src/commands/config/index.js +0 -8
  110. package/dist/src/commands/context/context-noninteractive.js +0 -221
  111. package/dist/src/commands/context/context.js +0 -46
  112. package/dist/src/commands/context/index.js +0 -21
  113. package/dist/src/commands/copy/copy.js +0 -366
  114. package/dist/src/commands/copy/index.js +0 -7
  115. package/dist/src/commands/cost/cost.js +0 -21
  116. package/dist/src/commands/cost/index.js +0 -16
  117. package/dist/src/commands/createMovedToPluginCommand.js +0 -33
  118. package/dist/src/commands/ctx_viz/index.js +0 -1
  119. package/dist/src/commands/debug-tool-call/index.js +0 -1
  120. package/dist/src/commands/desktop/desktop.js +0 -5
  121. package/dist/src/commands/desktop/index.js +0 -22
  122. package/dist/src/commands/diff/diff.js +0 -5
  123. package/dist/src/commands/diff/index.js +0 -6
  124. package/dist/src/commands/doctor/doctor.js +0 -5
  125. package/dist/src/commands/doctor/index.js +0 -9
  126. package/dist/src/commands/effort/effort.js +0 -166
  127. package/dist/src/commands/effort/index.js +0 -11
  128. package/dist/src/commands/env/index.js +0 -1
  129. package/dist/src/commands/exit/exit.js +0 -31
  130. package/dist/src/commands/exit/index.js +0 -9
  131. package/dist/src/commands/export/export.js +0 -86
  132. package/dist/src/commands/export/index.js +0 -8
  133. package/dist/src/commands/extra-usage/extra-usage-core.js +0 -99
  134. package/dist/src/commands/extra-usage/extra-usage-noninteractive.js +0 -13
  135. package/dist/src/commands/extra-usage/extra-usage.js +0 -14
  136. package/dist/src/commands/extra-usage/index.js +0 -27
  137. package/dist/src/commands/fast/fast.js +0 -275
  138. package/dist/src/commands/fast/index.js +0 -20
  139. package/dist/src/commands/feedback/feedback.js +0 -10
  140. package/dist/src/commands/feedback/index.js +0 -20
  141. package/dist/src/commands/files/files.js +0 -11
  142. package/dist/src/commands/files/index.js +0 -9
  143. package/dist/src/commands/good-claude/index.js +0 -1
  144. package/dist/src/commands/heapdump/heapdump.js +0 -14
  145. package/dist/src/commands/heapdump/index.js +0 -9
  146. package/dist/src/commands/help/help.js +0 -5
  147. package/dist/src/commands/help/index.js +0 -7
  148. package/dist/src/commands/hooks/hooks.js +0 -11
  149. package/dist/src/commands/hooks/index.js +0 -8
  150. package/dist/src/commands/ide/ide.js +0 -615
  151. package/dist/src/commands/ide/index.js +0 -8
  152. package/dist/src/commands/init-verifiers.js +0 -258
  153. package/dist/src/commands/init.js +0 -249
  154. package/dist/src/commands/insights.js +0 -2555
  155. package/dist/src/commands/install-github-app/ApiKeyStep.js +0 -230
  156. package/dist/src/commands/install-github-app/CheckExistingSecretStep.js +0 -194
  157. package/dist/src/commands/install-github-app/CheckGitHubStep.js +0 -15
  158. package/dist/src/commands/install-github-app/ChooseRepoStep.js +0 -211
  159. package/dist/src/commands/install-github-app/CreatingStep.js +0 -52
  160. package/dist/src/commands/install-github-app/ErrorStep.js +0 -83
  161. package/dist/src/commands/install-github-app/ExistingWorkflowStep.js +0 -104
  162. package/dist/src/commands/install-github-app/InstallAppStep.js +0 -96
  163. package/dist/src/commands/install-github-app/OAuthFlowStep.js +0 -190
  164. package/dist/src/commands/install-github-app/SuccessStep.js +0 -93
  165. package/dist/src/commands/install-github-app/WarningsStep.js +0 -70
  166. package/dist/src/commands/install-github-app/index.js +0 -10
  167. package/dist/src/commands/install-github-app/install-github-app.js +0 -593
  168. package/dist/src/commands/install-github-app/setupGitHubActions.js +0 -227
  169. package/dist/src/commands/install-slack-app/index.js +0 -9
  170. package/dist/src/commands/install-slack-app/install-slack-app.js +0 -25
  171. package/dist/src/commands/install.js +0 -118
  172. package/dist/src/commands/issue/index.js +0 -1
  173. package/dist/src/commands/keybindings/index.js +0 -10
  174. package/dist/src/commands/keybindings/keybindings.js +0 -47
  175. package/dist/src/commands/login/index.js +0 -11
  176. package/dist/src/commands/login/login.js +0 -99
  177. package/dist/src/commands/login-openai/index.js +0 -7
  178. package/dist/src/commands/login-openai/login-openai.js +0 -54
  179. package/dist/src/commands/logout/index.js +0 -8
  180. package/dist/src/commands/logout/logout.js +0 -72
  181. package/dist/src/commands/mcp/addCommand.js +0 -183
  182. package/dist/src/commands/mcp/index.js +0 -9
  183. package/dist/src/commands/mcp/mcp.js +0 -78
  184. package/dist/src/commands/mcp/xaaIdpCommand.js +0 -193
  185. package/dist/src/commands/memory/index.js +0 -7
  186. package/dist/src/commands/memory/memory.js +0 -71
  187. package/dist/src/commands/mobile/index.js +0 -8
  188. package/dist/src/commands/mobile/mobile.js +0 -278
  189. package/dist/src/commands/mock-limits/index.js +0 -1
  190. package/dist/src/commands/model/index.js +0 -14
  191. package/dist/src/commands/model/model.js +0 -297
  192. package/dist/src/commands/oauth-refresh/index.js +0 -1
  193. package/dist/src/commands/onboarding/index.js +0 -1
  194. package/dist/src/commands/output-style/index.js +0 -8
  195. package/dist/src/commands/output-style/output-style.js +0 -6
  196. package/dist/src/commands/passes/index.js +0 -17
  197. package/dist/src/commands/passes/passes.js +0 -22
  198. package/dist/src/commands/perf-issue/index.js +0 -1
  199. package/dist/src/commands/permissions/index.js +0 -8
  200. package/dist/src/commands/permissions/permissions.js +0 -8
  201. package/dist/src/commands/plan/index.js +0 -8
  202. package/dist/src/commands/plan/plan.js +0 -115
  203. package/dist/src/commands/plugin/AddMarketplace.js +0 -95
  204. package/dist/src/commands/plugin/BrowseMarketplace.js +0 -576
  205. package/dist/src/commands/plugin/DiscoverPlugins.js +0 -613
  206. package/dist/src/commands/plugin/ManageMarketplaces.js +0 -582
  207. package/dist/src/commands/plugin/ManagePlugins.js +0 -1783
  208. package/dist/src/commands/plugin/PluginErrors.js +0 -124
  209. package/dist/src/commands/plugin/PluginOptionsDialog.js +0 -367
  210. package/dist/src/commands/plugin/PluginOptionsFlow.js +0 -97
  211. package/dist/src/commands/plugin/PluginSettings.js +0 -1042
  212. package/dist/src/commands/plugin/PluginTrustWarning.js +0 -34
  213. package/dist/src/commands/plugin/UnifiedInstalledCell.js +0 -615
  214. package/dist/src/commands/plugin/ValidatePlugin.js +0 -95
  215. package/dist/src/commands/plugin/index.js +0 -10
  216. package/dist/src/commands/plugin/parseArgs.js +0 -71
  217. package/dist/src/commands/plugin/plugin.js +0 -5
  218. package/dist/src/commands/plugin/pluginDetailsHelpers.js +0 -89
  219. package/dist/src/commands/plugin/usePagination.js +0 -89
  220. package/dist/src/commands/pr_comments/index.js +0 -49
  221. package/dist/src/commands/privacy-settings/index.js +0 -11
  222. package/dist/src/commands/privacy-settings/privacy-settings.js +0 -54
  223. package/dist/src/commands/profile/index.js +0 -9
  224. package/dist/src/commands/profile/profile.js +0 -426
  225. package/dist/src/commands/provider/index.js +0 -8
  226. package/dist/src/commands/provider/provider.js +0 -349
  227. package/dist/src/commands/rate-limit-options/index.js +0 -15
  228. package/dist/src/commands/rate-limit-options/rate-limit-options.js +0 -213
  229. package/dist/src/commands/release-notes/index.js +0 -8
  230. package/dist/src/commands/release-notes/release-notes.js +0 -38
  231. package/dist/src/commands/reload-plugins/index.js +0 -11
  232. package/dist/src/commands/reload-plugins/reload-plugins.js +0 -52
  233. package/dist/src/commands/remote-env/index.js +0 -12
  234. package/dist/src/commands/remote-env/remote-env.js +0 -5
  235. package/dist/src/commands/remote-setup/api.js +0 -155
  236. package/dist/src/commands/remote-setup/index.js +0 -15
  237. package/dist/src/commands/remote-setup/remote-setup.js +0 -149
  238. package/dist/src/commands/rename/generateSessionName.js +0 -58
  239. package/dist/src/commands/rename/index.js +0 -9
  240. package/dist/src/commands/rename/rename.js +0 -52
  241. package/dist/src/commands/reset-limits/index.js +0 -4
  242. package/dist/src/commands/resume/index.js +0 -9
  243. package/dist/src/commands/resume/resume.js +0 -239
  244. package/dist/src/commands/review/UltrareviewOverageDialog.js +0 -97
  245. package/dist/src/commands/review/reviewRemote.js +0 -259
  246. package/dist/src/commands/review/ultrareviewCommand.js +0 -57
  247. package/dist/src/commands/review/ultrareviewEnabled.js +0 -10
  248. package/dist/src/commands/review.js +0 -50
  249. package/dist/src/commands/rewind/index.js +0 -10
  250. package/dist/src/commands/rewind/rewind.js +0 -7
  251. package/dist/src/commands/sandbox-toggle/index.js +0 -41
  252. package/dist/src/commands/sandbox-toggle/sandbox-toggle.js +0 -72
  253. package/dist/src/commands/security-review.js +0 -231
  254. package/dist/src/commands/session/index.js +0 -13
  255. package/dist/src/commands/session/session.js +0 -142
  256. package/dist/src/commands/share/index.js +0 -1
  257. package/dist/src/commands/skills/index.js +0 -7
  258. package/dist/src/commands/skills/skills.js +0 -5
  259. package/dist/src/commands/stats/index.js +0 -7
  260. package/dist/src/commands/stats/stats.js +0 -5
  261. package/dist/src/commands/status/index.js +0 -8
  262. package/dist/src/commands/status/status.js +0 -5
  263. package/dist/src/commands/statusline.js +0 -22
  264. package/dist/src/commands/stickers/index.js +0 -8
  265. package/dist/src/commands/stickers/stickers.js +0 -14
  266. package/dist/src/commands/summary/index.js +0 -1
  267. package/dist/src/commands/tag/index.js +0 -9
  268. package/dist/src/commands/tag/tag.js +0 -215
  269. package/dist/src/commands/tasks/index.js +0 -8
  270. package/dist/src/commands/tasks/tasks.js +0 -5
  271. package/dist/src/commands/telegram/index.js +0 -9
  272. package/dist/src/commands/telegram/telegram.js +0 -118
  273. package/dist/src/commands/teleport/index.js +0 -1
  274. package/dist/src/commands/terminalSetup/index.js +0 -18
  275. package/dist/src/commands/terminalSetup/terminalSetup.js +0 -491
  276. package/dist/src/commands/theme/index.js +0 -7
  277. package/dist/src/commands/theme/theme.js +0 -50
  278. package/dist/src/commands/thinkback/index.js +0 -9
  279. package/dist/src/commands/thinkback/thinkback.js +0 -527
  280. package/dist/src/commands/thinkback-play/index.js +0 -13
  281. package/dist/src/commands/thinkback-play/thinkback-play.js +0 -34
  282. package/dist/src/commands/ultraplan.js +0 -418
  283. package/dist/src/commands/upgrade/index.js +0 -12
  284. package/dist/src/commands/upgrade/upgrade.js +0 -37
  285. package/dist/src/commands/usage/index.js +0 -7
  286. package/dist/src/commands/usage/usage.js +0 -5
  287. package/dist/src/commands/version.js +0 -18
  288. package/dist/src/commands/vim/index.js +0 -8
  289. package/dist/src/commands/vim/vim.js +0 -25
  290. package/dist/src/commands/voice/index.js +0 -14
  291. package/dist/src/commands/voice/voice.js +0 -130
  292. package/dist/src/commands/whatsapp/index.js +0 -9
  293. package/dist/src/commands/whatsapp/whatsapp.js +0 -326
  294. package/dist/src/commands.js +0 -646
  295. package/dist/src/components/AgentProgressLine.js +0 -111
  296. package/dist/src/components/App.js +0 -45
  297. package/dist/src/components/ApproveApiKey.js +0 -124
  298. package/dist/src/components/AutoModeOptInDialog.js +0 -140
  299. package/dist/src/components/AutoUpdater.js +0 -157
  300. package/dist/src/components/AutoUpdaterWrapper.js +0 -78
  301. package/dist/src/components/AwsAuthStatusBox.js +0 -88
  302. package/dist/src/components/BaseTextInput.js +0 -105
  303. package/dist/src/components/BashModeProgress.js +0 -48
  304. package/dist/src/components/BridgeDialog.js +0 -414
  305. package/dist/src/components/BypassPermissionsModeDialog.js +0 -87
  306. package/dist/src/components/ChannelDowngradeDialog.js +0 -100
  307. package/dist/src/components/ClaudeCodeHint/PluginHintMenu.js +0 -37
  308. package/dist/src/components/ClaudeInChromeOnboarding.js +0 -126
  309. package/dist/src/components/ClaudeMdExternalIncludesDialog.js +0 -137
  310. package/dist/src/components/ClickableImageRef.js +0 -64
  311. package/dist/src/components/CompactSummary.js +0 -119
  312. package/dist/src/components/ConfigurableShortcutHint.js +0 -34
  313. package/dist/src/components/ConsoleOAuthFlow.js +0 -756
  314. package/dist/src/components/ContextSuggestions.js +0 -43
  315. package/dist/src/components/ContextVisualization.js +0 -483
  316. package/dist/src/components/CoordinatorAgentStatus.js +0 -261
  317. package/dist/src/components/CostThresholdDialog.js +0 -48
  318. package/dist/src/components/CtrlOToExpand.js +0 -50
  319. package/dist/src/components/CustomSelect/SelectMulti.js +0 -149
  320. package/dist/src/components/CustomSelect/index.js +0 -2
  321. package/dist/src/components/CustomSelect/option-map.js +0 -32
  322. package/dist/src/components/CustomSelect/select-input-option.js +0 -426
  323. package/dist/src/components/CustomSelect/select-option.js +0 -23
  324. package/dist/src/components/CustomSelect/select.js +0 -518
  325. package/dist/src/components/CustomSelect/use-multi-select-state.js +0 -214
  326. package/dist/src/components/CustomSelect/use-select-input.js +0 -170
  327. package/dist/src/components/CustomSelect/use-select-navigation.js +0 -366
  328. package/dist/src/components/CustomSelect/use-select-state.js +0 -22
  329. package/dist/src/components/DesktopHandoff.js +0 -195
  330. package/dist/src/components/DesktopUpsell/DesktopUpsellStartup.js +0 -173
  331. package/dist/src/components/DevBar.js +0 -50
  332. package/dist/src/components/DevChannelsDialog.js +0 -103
  333. package/dist/src/components/DiagnosticsDisplay.js +0 -91
  334. package/dist/src/components/EffortCallout.js +0 -264
  335. package/dist/src/components/EffortIndicator.js +0 -29
  336. package/dist/src/components/ExitFlow.js +0 -40
  337. package/dist/src/components/ExportDialog.js +0 -101
  338. package/dist/src/components/FallbackToolUseErrorMessage.js +0 -115
  339. package/dist/src/components/FallbackToolUseRejectedMessage.js +0 -16
  340. package/dist/src/components/FastIcon.js +0 -42
  341. package/dist/src/components/Feedback.js +0 -439
  342. package/dist/src/components/FeedbackSurvey/FeedbackSurvey.js +0 -150
  343. package/dist/src/components/FeedbackSurvey/FeedbackSurveyView.js +0 -103
  344. package/dist/src/components/FeedbackSurvey/TranscriptSharePrompt.js +0 -83
  345. package/dist/src/components/FeedbackSurvey/submitTranscriptShare.js +0 -75
  346. package/dist/src/components/FeedbackSurvey/useDebouncedDigitInput.js +0 -51
  347. package/dist/src/components/FeedbackSurvey/useFeedbackSurvey.js +0 -258
  348. package/dist/src/components/FeedbackSurvey/useMemorySurvey.js +0 -191
  349. package/dist/src/components/FeedbackSurvey/usePostCompactSurvey.js +0 -202
  350. package/dist/src/components/FeedbackSurvey/useSurveyState.js +0 -80
  351. package/dist/src/components/FileEditToolDiff.js +0 -166
  352. package/dist/src/components/FileEditToolUpdatedMessage.js +0 -111
  353. package/dist/src/components/FileEditToolUseRejectedMessage.js +0 -157
  354. package/dist/src/components/FilePathLink.js +0 -34
  355. package/dist/src/components/FullscreenLayout.js +0 -578
  356. package/dist/src/components/GlobalSearchDialog.js +0 -339
  357. package/dist/src/components/HelpV2/Commands.js +0 -65
  358. package/dist/src/components/HelpV2/General.js +0 -24
  359. package/dist/src/components/HelpV2/HelpV2.js +0 -186
  360. package/dist/src/components/HighlightedCode/Fallback.js +0 -193
  361. package/dist/src/components/HighlightedCode.js +0 -184
  362. package/dist/src/components/HistorySearchDialog.js +0 -92
  363. package/dist/src/components/IdeAutoConnectDialog.js +0 -153
  364. package/dist/src/components/IdeOnboardingDialog.js +0 -174
  365. package/dist/src/components/IdeStatusIndicator.js +0 -49
  366. package/dist/src/components/IdleReturnDialog.js +0 -116
  367. package/dist/src/components/InterruptedByUser.js +0 -15
  368. package/dist/src/components/InvalidConfigDialog.js +0 -134
  369. package/dist/src/components/InvalidSettingsDialog.js +0 -84
  370. package/dist/src/components/KeybindingWarnings.js +0 -54
  371. package/dist/src/components/LanguagePicker.js +0 -84
  372. package/dist/src/components/LogSelector.js +0 -1579
  373. package/dist/src/components/LogoV2/AnimatedAsterisk.js +0 -42
  374. package/dist/src/components/LogoV2/AnimatedClawd.js +0 -111
  375. package/dist/src/components/LogoV2/ChannelsNotice.js +0 -258
  376. package/dist/src/components/LogoV2/Clawd.js +0 -5
  377. package/dist/src/components/LogoV2/CondensedLogo.js +0 -159
  378. package/dist/src/components/LogoV2/EmergencyTip.js +0 -47
  379. package/dist/src/components/LogoV2/Feed.js +0 -84
  380. package/dist/src/components/LogoV2/FeedColumn.js +0 -55
  381. package/dist/src/components/LogoV2/GuestPassesUpsell.js +0 -71
  382. package/dist/src/components/LogoV2/LogoV2.js +0 -565
  383. package/dist/src/components/LogoV2/Opus1mMergeNotice.js +0 -56
  384. package/dist/src/components/LogoV2/OverageCreditUpsell.js +0 -160
  385. package/dist/src/components/LogoV2/VoiceModeNotice.js +0 -70
  386. package/dist/src/components/LogoV2/WelcomeV2.js +0 -461
  387. package/dist/src/components/LogoV2/feedConfigs.js +0 -78
  388. package/dist/src/components/LspRecommendation/LspRecommendationMenu.js +0 -46
  389. package/dist/src/components/MCPServerApprovalDialog.js +0 -113
  390. package/dist/src/components/MCPServerDesktopImportDialog.js +0 -206
  391. package/dist/src/components/MCPServerDialogCopy.js +0 -15
  392. package/dist/src/components/MCPServerMultiselectDialog.js +0 -133
  393. package/dist/src/components/ManagedSettingsSecurityDialog/ManagedSettingsSecurityDialog.js +0 -149
  394. package/dist/src/components/ManagedSettingsSecurityDialog/utils.js +0 -105
  395. package/dist/src/components/Markdown.js +0 -217
  396. package/dist/src/components/MarkdownTable.js +0 -279
  397. package/dist/src/components/MemoryUsageIndicator.js +0 -27
  398. package/dist/src/components/Message.js +0 -566
  399. package/dist/src/components/MessageModel.js +0 -36
  400. package/dist/src/components/MessageResponse.js +0 -73
  401. package/dist/src/components/MessageRow.js +0 -346
  402. package/dist/src/components/MessageSelector.js +0 -743
  403. package/dist/src/components/MessageTimestamp.js +0 -57
  404. package/dist/src/components/Messages.js +0 -637
  405. package/dist/src/components/ModelPicker.js +0 -484
  406. package/dist/src/components/NativeAutoUpdater.js +0 -153
  407. package/dist/src/components/NotebookEditToolUseRejectedMessage.js +0 -83
  408. package/dist/src/components/OffscreenFreeze.js +0 -35
  409. package/dist/src/components/Onboarding.js +0 -174
  410. package/dist/src/components/OutputStylePicker.js +0 -102
  411. package/dist/src/components/PackageManagerAutoUpdater.js +0 -100
  412. package/dist/src/components/Passes/Passes.js +0 -113
  413. package/dist/src/components/PrBadge.js +0 -90
  414. package/dist/src/components/PressEnterToContinue.js +0 -15
  415. package/dist/src/components/PromptInput/HistorySearchInput.js +0 -44
  416. package/dist/src/components/PromptInput/IssueFlagBanner.js +0 -8
  417. package/dist/src/components/PromptInput/Notifications.js +0 -221
  418. package/dist/src/components/PromptInput/PromptInput.js +0 -1998
  419. package/dist/src/components/PromptInput/PromptInputFooter.js +0 -84
  420. package/dist/src/components/PromptInput/PromptInputFooterLeftSide.js +0 -409
  421. package/dist/src/components/PromptInput/PromptInputFooterSuggestions.js +0 -280
  422. package/dist/src/components/PromptInput/PromptInputHelpMenu.js +0 -379
  423. package/dist/src/components/PromptInput/PromptInputModeIndicator.js +0 -72
  424. package/dist/src/components/PromptInput/PromptInputQueuedCommands.js +0 -105
  425. package/dist/src/components/PromptInput/PromptInputStashNotice.js +0 -20
  426. package/dist/src/components/PromptInput/SandboxPromptFooterHint.js +0 -65
  427. package/dist/src/components/PromptInput/ShimmeredInput.js +0 -132
  428. package/dist/src/components/PromptInput/VoiceIndicator.js +0 -136
  429. package/dist/src/components/PromptInput/inputModes.js +0 -24
  430. package/dist/src/components/PromptInput/inputPaste.js +0 -62
  431. package/dist/src/components/PromptInput/useMaybeTruncateInput.js +0 -33
  432. package/dist/src/components/PromptInput/usePromptInputPlaceholder.js +0 -55
  433. package/dist/src/components/PromptInput/useShowFastIconHint.js +0 -23
  434. package/dist/src/components/PromptInput/useSwarmBanner.js +0 -112
  435. package/dist/src/components/PromptInput/utils.js +0 -50
  436. package/dist/src/components/QuickOpenDialog.js +0 -243
  437. package/dist/src/components/RemoteCallout.js +0 -53
  438. package/dist/src/components/RemoteEnvironmentDialog.js +0 -345
  439. package/dist/src/components/ResumeTask.js +0 -173
  440. package/dist/src/components/SandboxViolationExpandedView.js +0 -102
  441. package/dist/src/components/ScrollKeybindingHandler.js +0 -982
  442. package/dist/src/components/SearchBox.js +0 -55
  443. package/dist/src/components/SentryErrorBoundary.js +0 -16
  444. package/dist/src/components/SessionBackgroundHint.js +0 -104
  445. package/dist/src/components/SessionPreview.js +0 -200
  446. package/dist/src/components/Settings/Config.js +0 -1628
  447. package/dist/src/components/Settings/Settings.js +0 -129
  448. package/dist/src/components/Settings/Status.js +0 -230
  449. package/dist/src/components/Settings/Usage.js +0 -341
  450. package/dist/src/components/ShowInIDEPrompt.js +0 -151
  451. package/dist/src/components/SkillImprovementSurvey.js +0 -130
  452. package/dist/src/components/Spinner/FlashingChar.js +0 -51
  453. package/dist/src/components/Spinner/GlimmerMessage.js +0 -328
  454. package/dist/src/components/Spinner/ShimmerChar.js +0 -22
  455. package/dist/src/components/Spinner/SpinnerAnimationRow.js +0 -169
  456. package/dist/src/components/Spinner/SpinnerGlyph.js +0 -69
  457. package/dist/src/components/Spinner/TeammateSpinnerLine.js +0 -170
  458. package/dist/src/components/Spinner/TeammateSpinnerTree.js +0 -268
  459. package/dist/src/components/Spinner/index.js +0 -11
  460. package/dist/src/components/Spinner/teammateSelectHint.js +0 -1
  461. package/dist/src/components/Spinner/useShimmerAnimation.js +0 -22
  462. package/dist/src/components/Spinner/useStalledAnimation.js +0 -63
  463. package/dist/src/components/Spinner/utils.js +0 -77
  464. package/dist/src/components/Spinner.js +0 -470
  465. package/dist/src/components/Stats.js +0 -1000
  466. package/dist/src/components/StatusLine.js +0 -285
  467. package/dist/src/components/StatusNotices.js +0 -50
  468. package/dist/src/components/StructuredDiff/Fallback.js +0 -335
  469. package/dist/src/components/StructuredDiff/colorDiff.js +0 -26
  470. package/dist/src/components/StructuredDiff.js +0 -152
  471. package/dist/src/components/StructuredDiffList.js +0 -8
  472. package/dist/src/components/TagTabs.js +0 -100
  473. package/dist/src/components/TaskListV2.js +0 -333
  474. package/dist/src/components/TeammateViewHeader.js +0 -87
  475. package/dist/src/components/TeleportError.js +0 -191
  476. package/dist/src/components/TeleportProgress.js +0 -130
  477. package/dist/src/components/TeleportRepoMismatchDialog.js +0 -98
  478. package/dist/src/components/TeleportResumeWrapper.js +0 -158
  479. package/dist/src/components/TeleportStash.js +0 -82
  480. package/dist/src/components/TextInput.js +0 -108
  481. package/dist/src/components/ThemePicker.js +0 -330
  482. package/dist/src/components/ThinkingToggle.js +0 -153
  483. package/dist/src/components/TokenWarning.js +0 -172
  484. package/dist/src/components/ToolUseLoader.js +0 -34
  485. package/dist/src/components/TrustDialog/TrustDialog.js +0 -301
  486. package/dist/src/components/TrustDialog/utils.js +0 -199
  487. package/dist/src/components/ValidationErrorsList.js +0 -146
  488. package/dist/src/components/VimTextInput.js +0 -136
  489. package/dist/src/components/VirtualMessageList.js +0 -892
  490. package/dist/src/components/WorkflowMultiselectDialog.js +0 -118
  491. package/dist/src/components/WorktreeExitDialog.js +0 -222
  492. package/dist/src/components/agents/AgentDetail.js +0 -226
  493. package/dist/src/components/agents/AgentEditor.js +0 -146
  494. package/dist/src/components/agents/AgentNavigationFooter.js +0 -21
  495. package/dist/src/components/agents/AgentsList.js +0 -436
  496. package/dist/src/components/agents/AgentsMenu.js +0 -848
  497. package/dist/src/components/agents/ColorPicker.js +0 -110
  498. package/dist/src/components/agents/ModelSelector.js +0 -62
  499. package/dist/src/components/agents/SnapshotUpdateDialog.js +0 -16
  500. package/dist/src/components/agents/ToolSelector.js +0 -557
  501. package/dist/src/components/agents/agentFileUtils.js +0 -179
  502. package/dist/src/components/agents/generateAgent.js +0 -161
  503. package/dist/src/components/agents/new-agent-creation/CreateAgentWizard.js +0 -88
  504. package/dist/src/components/agents/new-agent-creation/wizard-steps/ColorStep.js +0 -80
  505. package/dist/src/components/agents/new-agent-creation/wizard-steps/ConfirmStep.js +0 -386
  506. package/dist/src/components/agents/new-agent-creation/wizard-steps/ConfirmStepWrapper.js +0 -63
  507. package/dist/src/components/agents/new-agent-creation/wizard-steps/DescriptionStep.js +0 -126
  508. package/dist/src/components/agents/new-agent-creation/wizard-steps/GenerateStep.js +0 -118
  509. package/dist/src/components/agents/new-agent-creation/wizard-steps/LocationStep.js +0 -79
  510. package/dist/src/components/agents/new-agent-creation/wizard-steps/MemoryStep.js +0 -107
  511. package/dist/src/components/agents/new-agent-creation/wizard-steps/MethodStep.js +0 -79
  512. package/dist/src/components/agents/new-agent-creation/wizard-steps/ModelStep.js +0 -48
  513. package/dist/src/components/agents/new-agent-creation/wizard-steps/PromptStep.js +0 -131
  514. package/dist/src/components/agents/new-agent-creation/wizard-steps/ToolsStep.js +0 -51
  515. package/dist/src/components/agents/new-agent-creation/wizard-steps/TypeStep.js +0 -100
  516. package/dist/src/components/agents/types.js +0 -4
  517. package/dist/src/components/agents/utils.js +0 -14
  518. package/dist/src/components/agents/validateAgent.js +0 -79
  519. package/dist/src/components/design-system/Byline.js +0 -72
  520. package/dist/src/components/design-system/Dialog.js +0 -116
  521. package/dist/src/components/design-system/Divider.js +0 -109
  522. package/dist/src/components/design-system/FuzzyPicker.js +0 -187
  523. package/dist/src/components/design-system/KeyboardShortcutHint.js +0 -67
  524. package/dist/src/components/design-system/ListItem.js +0 -183
  525. package/dist/src/components/design-system/LoadingState.js +0 -68
  526. package/dist/src/components/design-system/Pane.js +0 -68
  527. package/dist/src/components/design-system/ProgressBar.js +0 -62
  528. package/dist/src/components/design-system/Ratchet.js +0 -71
  529. package/dist/src/components/design-system/StatusIcon.js +0 -69
  530. package/dist/src/components/design-system/Tabs.js +0 -269
  531. package/dist/src/components/design-system/ThemeProvider.js +0 -137
  532. package/dist/src/components/design-system/ThemedBox.js +0 -125
  533. package/dist/src/components/design-system/ThemedText.js +0 -60
  534. package/dist/src/components/design-system/color.js +0 -22
  535. package/dist/src/components/diff/DiffDetailView.js +0 -284
  536. package/dist/src/components/diff/DiffDialog.js +0 -387
  537. package/dist/src/components/diff/DiffFileList.js +0 -291
  538. package/dist/src/components/grove/Grove.js +0 -483
  539. package/dist/src/components/hooks/HooksConfigMenu.js +0 -570
  540. package/dist/src/components/hooks/PromptDialog.js +0 -81
  541. package/dist/src/components/hooks/SelectEventMode.js +0 -117
  542. package/dist/src/components/hooks/SelectHookMode.js +0 -93
  543. package/dist/src/components/hooks/SelectMatcherMode.js +0 -124
  544. package/dist/src/components/hooks/ViewHookMode.js +0 -197
  545. package/dist/src/components/mcp/CapabilitiesSection.js +0 -55
  546. package/dist/src/components/mcp/ElicitationDialog.js +0 -945
  547. package/dist/src/components/mcp/MCPAgentServerMenu.js +0 -95
  548. package/dist/src/components/mcp/MCPListPanel.js +0 -504
  549. package/dist/src/components/mcp/MCPReconnect.js +0 -168
  550. package/dist/src/components/mcp/MCPRemoteServerMenu.js +0 -460
  551. package/dist/src/components/mcp/MCPSettings.js +0 -414
  552. package/dist/src/components/mcp/MCPStdioServerMenu.js +0 -95
  553. package/dist/src/components/mcp/MCPToolDetailView.js +0 -219
  554. package/dist/src/components/mcp/MCPToolListView.js +0 -136
  555. package/dist/src/components/mcp/McpParsingWarnings.js +0 -211
  556. package/dist/src/components/mcp/index.js +0 -8
  557. package/dist/src/components/mcp/types.js +0 -3
  558. package/dist/src/components/mcp/utils/reconnectHelpers.js +0 -35
  559. package/dist/src/components/memory/MemoryFileSelector.js +0 -455
  560. package/dist/src/components/memory/MemoryUpdateNotification.js +0 -42
  561. package/dist/src/components/messageActions.js +0 -418
  562. package/dist/src/components/messages/AdvisorMessage.js +0 -151
  563. package/dist/src/components/messages/AssistantRedactedThinkingMessage.js +0 -27
  564. package/dist/src/components/messages/AssistantTextMessage.js +0 -274
  565. package/dist/src/components/messages/AssistantThinkingMessage.js +0 -69
  566. package/dist/src/components/messages/AssistantToolUseMessage.js +0 -323
  567. package/dist/src/components/messages/AttachmentMessage.js +0 -418
  568. package/dist/src/components/messages/CollapsedReadSearchContent.js +0 -362
  569. package/dist/src/components/messages/CompactBoundaryMessage.js +0 -18
  570. package/dist/src/components/messages/GroupedToolUseContent.js +0 -37
  571. package/dist/src/components/messages/HighlightedThinkingText.js +0 -164
  572. package/dist/src/components/messages/HookProgressMessage.js +0 -110
  573. package/dist/src/components/messages/PlanApprovalMessage.js +0 -212
  574. package/dist/src/components/messages/RateLimitMessage.js +0 -149
  575. package/dist/src/components/messages/ShutdownMessage.js +0 -123
  576. package/dist/src/components/messages/SystemAPIErrorMessage.js +0 -135
  577. package/dist/src/components/messages/SystemTextMessage.js +0 -843
  578. package/dist/src/components/messages/TaskAssignmentMessage.js +0 -71
  579. package/dist/src/components/messages/UserAgentNotificationMessage.js +0 -77
  580. package/dist/src/components/messages/UserBashInputMessage.js +0 -51
  581. package/dist/src/components/messages/UserBashOutputMessage.js +0 -54
  582. package/dist/src/components/messages/UserChannelMessage.js +0 -129
  583. package/dist/src/components/messages/UserCommandMessage.js +0 -106
  584. package/dist/src/components/messages/UserImageMessage.js +0 -53
  585. package/dist/src/components/messages/UserLocalCommandOutputMessage.js +0 -169
  586. package/dist/src/components/messages/UserMemoryInputMessage.js +0 -72
  587. package/dist/src/components/messages/UserPlanMessage.js +0 -37
  588. package/dist/src/components/messages/UserPromptMessage.js +0 -63
  589. package/dist/src/components/messages/UserResourceUpdateMessage.js +0 -101
  590. package/dist/src/components/messages/UserTeammateMessage.js +0 -156
  591. package/dist/src/components/messages/UserTextMessage.js +0 -271
  592. package/dist/src/components/messages/UserToolResultMessage/RejectedPlanMessage.js +0 -27
  593. package/dist/src/components/messages/UserToolResultMessage/RejectedToolUseMessage.js +0 -16
  594. package/dist/src/components/messages/UserToolResultMessage/UserToolCanceledMessage.js +0 -16
  595. package/dist/src/components/messages/UserToolResultMessage/UserToolErrorMessage.js +0 -91
  596. package/dist/src/components/messages/UserToolResultMessage/UserToolRejectMessage.js +0 -73
  597. package/dist/src/components/messages/UserToolResultMessage/UserToolResultMessage.js +0 -83
  598. package/dist/src/components/messages/UserToolResultMessage/UserToolSuccessMessage.js +0 -58
  599. package/dist/src/components/messages/UserToolResultMessage/utils.js +0 -43
  600. package/dist/src/components/messages/nullRenderingAttachments.js +0 -58
  601. package/dist/src/components/messages/teamMemCollapsed.js +0 -142
  602. package/dist/src/components/messages/teamMemSaved.js +0 -17
  603. package/dist/src/components/permissions/AskUserQuestionPermissionRequest/AskUserQuestionPermissionRequest.js +0 -654
  604. package/dist/src/components/permissions/AskUserQuestionPermissionRequest/PreviewBox.js +0 -219
  605. package/dist/src/components/permissions/AskUserQuestionPermissionRequest/PreviewQuestionView.js +0 -227
  606. package/dist/src/components/permissions/AskUserQuestionPermissionRequest/QuestionNavigationBar.js +0 -174
  607. package/dist/src/components/permissions/AskUserQuestionPermissionRequest/QuestionView.js +0 -444
  608. package/dist/src/components/permissions/AskUserQuestionPermissionRequest/SubmitQuestionsView.js +0 -136
  609. package/dist/src/components/permissions/AskUserQuestionPermissionRequest/use-multiple-choice-state.js +0 -100
  610. package/dist/src/components/permissions/BashPermissionRequest/BashPermissionRequest.js +0 -404
  611. package/dist/src/components/permissions/BashPermissionRequest/bashToolUseOptions.js +0 -110
  612. package/dist/src/components/permissions/ComputerUseApproval/ComputerUseApproval.js +0 -448
  613. package/dist/src/components/permissions/EnterPlanModePermissionRequest/EnterPlanModePermissionRequest.js +0 -125
  614. package/dist/src/components/permissions/ExitPlanModePermissionRequest/ExitPlanModePermissionRequest.js +0 -650
  615. package/dist/src/components/permissions/FallbackPermissionRequest.js +0 -348
  616. package/dist/src/components/permissions/FileEditPermissionRequest/FileEditPermissionRequest.js +0 -184
  617. package/dist/src/components/permissions/FilePermissionDialog/FilePermissionDialog.js +0 -108
  618. package/dist/src/components/permissions/FilePermissionDialog/ideDiffConfig.js +0 -13
  619. package/dist/src/components/permissions/FilePermissionDialog/permissionOptions.js +0 -136
  620. package/dist/src/components/permissions/FilePermissionDialog/useFilePermissionDialog.js +0 -131
  621. package/dist/src/components/permissions/FilePermissionDialog/usePermissionHandler.js +0 -86
  622. package/dist/src/components/permissions/FileWritePermissionRequest/FileWritePermissionRequest.js +0 -163
  623. package/dist/src/components/permissions/FileWritePermissionRequest/FileWriteToolDiff.js +0 -78
  624. package/dist/src/components/permissions/FilesystemPermissionRequest/FilesystemPermissionRequest.js +0 -112
  625. package/dist/src/components/permissions/NotebookEditPermissionRequest/NotebookEditPermissionRequest.js +0 -163
  626. package/dist/src/components/permissions/NotebookEditPermissionRequest/NotebookEditToolDiff.js +0 -217
  627. package/dist/src/components/permissions/PermissionDecisionDebugInfo.js +0 -466
  628. package/dist/src/components/permissions/PermissionDialog.js +0 -54
  629. package/dist/src/components/permissions/PermissionExplanation.js +0 -269
  630. package/dist/src/components/permissions/PermissionPrompt.js +0 -316
  631. package/dist/src/components/permissions/PermissionRequest.js +0 -160
  632. package/dist/src/components/permissions/PermissionRequestTitle.js +0 -57
  633. package/dist/src/components/permissions/PermissionRuleExplanation.js +0 -109
  634. package/dist/src/components/permissions/PowerShellPermissionRequest/PowerShellPermissionRequest.js +0 -178
  635. package/dist/src/components/permissions/PowerShellPermissionRequest/powershellToolUseOptions.js +0 -73
  636. package/dist/src/components/permissions/SandboxPermissionRequest.js +0 -161
  637. package/dist/src/components/permissions/SedEditPermissionRequest/SedEditPermissionRequest.js +0 -228
  638. package/dist/src/components/permissions/SkillPermissionRequest/SkillPermissionRequest.js +0 -384
  639. package/dist/src/components/permissions/WebFetchPermissionRequest/WebFetchPermissionRequest.js +0 -258
  640. package/dist/src/components/permissions/WorkerBadge.js +0 -43
  641. package/dist/src/components/permissions/WorkerPendingPermission.js +0 -106
  642. package/dist/src/components/permissions/hooks.js +0 -163
  643. package/dist/src/components/permissions/rules/AddPermissionRules.js +0 -170
  644. package/dist/src/components/permissions/rules/AddWorkspaceDirectory.js +0 -334
  645. package/dist/src/components/permissions/rules/PermissionRuleDescription.js +0 -77
  646. package/dist/src/components/permissions/rules/PermissionRuleInput.js +0 -135
  647. package/dist/src/components/permissions/rules/PermissionRuleList.js +0 -1189
  648. package/dist/src/components/permissions/rules/RecentDenialsTab.js +0 -204
  649. package/dist/src/components/permissions/rules/RemoveWorkspaceDirectory.js +0 -102
  650. package/dist/src/components/permissions/rules/WorkspaceTab.js +0 -132
  651. package/dist/src/components/permissions/shellPermissionHelpers.js +0 -111
  652. package/dist/src/components/permissions/useShellPermissionFeedback.js +0 -108
  653. package/dist/src/components/permissions/utils.js +0 -14
  654. package/dist/src/components/sandbox/SandboxConfigTab.js +0 -47
  655. package/dist/src/components/sandbox/SandboxDependenciesTab.js +0 -122
  656. package/dist/src/components/sandbox/SandboxDoctorSection.js +0 -46
  657. package/dist/src/components/sandbox/SandboxOverridesTab.js +0 -192
  658. package/dist/src/components/sandbox/SandboxSettings.js +0 -296
  659. package/dist/src/components/shell/ExpandShellOutputContext.js +0 -33
  660. package/dist/src/components/shell/OutputLine.js +0 -110
  661. package/dist/src/components/shell/ShellProgressMessage.js +0 -143
  662. package/dist/src/components/shell/ShellTimeDisplay.js +0 -71
  663. package/dist/src/components/skills/SkillsMenu.js +0 -238
  664. package/dist/src/components/tasks/AsyncAgentDetailDialog.js +0 -234
  665. package/dist/src/components/tasks/BackgroundTask.js +0 -363
  666. package/dist/src/components/tasks/BackgroundTaskStatus.js +0 -419
  667. package/dist/src/components/tasks/BackgroundTasksDialog.js +0 -496
  668. package/dist/src/components/tasks/DreamDetailDialog.js +0 -250
  669. package/dist/src/components/tasks/InProcessTeammateDetailDialog.js +0 -274
  670. package/dist/src/components/tasks/RemoteSessionDetailDialog.js +0 -868
  671. package/dist/src/components/tasks/RemoteSessionProgress.js +0 -249
  672. package/dist/src/components/tasks/ShellDetailDialog.js +0 -403
  673. package/dist/src/components/tasks/ShellProgress.js +0 -76
  674. package/dist/src/components/tasks/renderToolActivity.js +0 -28
  675. package/dist/src/components/tasks/taskStatusUtils.js +0 -94
  676. package/dist/src/components/teams/TeamStatus.js +0 -76
  677. package/dist/src/components/teams/TeamsDialog.js +0 -672
  678. package/dist/src/components/ui/OrderedList.js +0 -66
  679. package/dist/src/components/ui/OrderedListItem.js +0 -41
  680. package/dist/src/components/ui/TreeSelect.js +0 -300
  681. package/dist/src/components/wizard/WizardDialogLayout.js +0 -47
  682. package/dist/src/components/wizard/WizardNavigationFooter.js +0 -10
  683. package/dist/src/components/wizard/WizardProvider.js +0 -217
  684. package/dist/src/components/wizard/index.js +0 -4
  685. package/dist/src/components/wizard/useWizard.js +0 -9
  686. package/dist/src/constants/apiLimits.js +0 -81
  687. package/dist/src/constants/betas.js +0 -45
  688. package/dist/src/constants/common.js +0 -29
  689. package/dist/src/constants/cyberRiskInstruction.js +0 -24
  690. package/dist/src/constants/errorIds.js +0 -14
  691. package/dist/src/constants/figures.js +0 -38
  692. package/dist/src/constants/files.js +0 -150
  693. package/dist/src/constants/github-app.js +0 -139
  694. package/dist/src/constants/keys.js +0 -10
  695. package/dist/src/constants/messages.js +0 -1
  696. package/dist/src/constants/oauth.js +0 -221
  697. package/dist/src/constants/outputStyles.js +0 -162
  698. package/dist/src/constants/product.js +0 -56
  699. package/dist/src/constants/prompts.js +0 -752
  700. package/dist/src/constants/spinnerVerbs.js +0 -202
  701. package/dist/src/constants/system.js +0 -77
  702. package/dist/src/constants/systemPromptSections.js +0 -39
  703. package/dist/src/constants/toolLimits.js +0 -50
  704. package/dist/src/constants/tools.js +0 -103
  705. package/dist/src/constants/turnCompletionVerbs.js +0 -12
  706. package/dist/src/constants/xml.js +0 -73
  707. package/dist/src/context/QueuedMessageContext.js +0 -51
  708. package/dist/src/context/fpsMetrics.js +0 -22
  709. package/dist/src/context/mailbox.js +0 -35
  710. package/dist/src/context/modalContext.js +0 -34
  711. package/dist/src/context/notifications.js +0 -199
  712. package/dist/src/context/overlayContext.js +0 -149
  713. package/dist/src/context/promptOverlayContext.js +0 -118
  714. package/dist/src/context/stats.js +0 -207
  715. package/dist/src/context/voice.js +0 -74
  716. package/dist/src/context.js +0 -146
  717. package/dist/src/coordinator/coordinatorMode.js +0 -345
  718. package/dist/src/cost-tracker.js +0 -208
  719. package/dist/src/costHook.js +0 -17
  720. package/dist/src/daemon/main.js +0 -16
  721. package/dist/src/daemon/workerRegistry.js +0 -16
  722. package/dist/src/dialogLaunchers.js +0 -68
  723. package/dist/src/entrypoints/agentSdkTypes.js +0 -202
  724. package/dist/src/entrypoints/cli.js +0 -237
  725. package/dist/src/entrypoints/init.js +0 -265
  726. package/dist/src/entrypoints/mcp.js +0 -142
  727. package/dist/src/entrypoints/sandboxTypes.js +0 -112
  728. package/dist/src/entrypoints/sdk/controlSchemas.js +0 -452
  729. package/dist/src/entrypoints/sdk/controlTypes.js +0 -1
  730. package/dist/src/entrypoints/sdk/coreSchemas.js +0 -1331
  731. package/dist/src/entrypoints/sdk/coreTypes.generated.js +0 -1
  732. package/dist/src/entrypoints/sdk/coreTypes.js +0 -49
  733. package/dist/src/entrypoints/sdk/runtimeTypes.js +0 -1
  734. package/dist/src/entrypoints/sdk/toolTypes.js +0 -1
  735. package/dist/src/environment-runner/main.js +0 -16
  736. package/dist/src/history.js +0 -386
  737. package/dist/src/hooks/fileSuggestions.js +0 -635
  738. package/dist/src/hooks/notifs/useAutoModeUnavailableNotification.js +0 -47
  739. package/dist/src/hooks/notifs/useCanSwitchToExistingSubscription.js +0 -57
  740. package/dist/src/hooks/notifs/useDeprecationWarningNotification.js +0 -43
  741. package/dist/src/hooks/notifs/useFastModeNotification.js +0 -164
  742. package/dist/src/hooks/notifs/useIDEStatusIndicator.js +0 -174
  743. package/dist/src/hooks/notifs/useInstallMessages.js +0 -27
  744. package/dist/src/hooks/notifs/useLspInitializationNotification.js +0 -144
  745. package/dist/src/hooks/notifs/useMcpConnectivityStatus.js +0 -80
  746. package/dist/src/hooks/notifs/useModelMigrationNotifications.js +0 -53
  747. package/dist/src/hooks/notifs/useNpmDeprecationNotification.js +0 -24
  748. package/dist/src/hooks/notifs/usePluginAutoupdateNotification.js +0 -82
  749. package/dist/src/hooks/notifs/usePluginInstallationStatus.js +0 -127
  750. package/dist/src/hooks/notifs/useRateLimitWarningNotification.js +0 -118
  751. package/dist/src/hooks/notifs/useSettingsErrors.js +0 -64
  752. package/dist/src/hooks/notifs/useStartupNotification.js +0 -33
  753. package/dist/src/hooks/notifs/useTeammateShutdownNotification.js +0 -64
  754. package/dist/src/hooks/renderPlaceholder.js +0 -26
  755. package/dist/src/hooks/toolPermission/PermissionContext.js +0 -211
  756. package/dist/src/hooks/toolPermission/handlers/coordinatorHandler.js +0 -44
  757. package/dist/src/hooks/toolPermission/handlers/interactiveHandler.js +0 -397
  758. package/dist/src/hooks/toolPermission/handlers/swarmWorkerHandler.js +0 -108
  759. package/dist/src/hooks/toolPermission/permissionLogging.js +0 -145
  760. package/dist/src/hooks/unifiedSuggestions.js +0 -130
  761. package/dist/src/hooks/useAfterFirstRender.js +0 -12
  762. package/dist/src/hooks/useApiKeyVerification.js +0 -63
  763. package/dist/src/hooks/useArrowKeyHistory.js +0 -203
  764. package/dist/src/hooks/useAssistantHistory.js +0 -194
  765. package/dist/src/hooks/useAwaySummary.js +0 -105
  766. package/dist/src/hooks/useBackgroundTaskNavigation.js +0 -204
  767. package/dist/src/hooks/useBlink.js +0 -28
  768. package/dist/src/hooks/useCanUseTool.js +0 -192
  769. package/dist/src/hooks/useCancelRequest.js +0 -195
  770. package/dist/src/hooks/useChromeExtensionNotification.js +0 -49
  771. package/dist/src/hooks/useClaudeCodeHintRecommendation.js +0 -117
  772. package/dist/src/hooks/useClipboardImageHint.js +0 -59
  773. package/dist/src/hooks/useCommandKeybindings.js +0 -87
  774. package/dist/src/hooks/useCommandQueue.js +0 -10
  775. package/dist/src/hooks/useCopyOnSelect.js +0 -88
  776. package/dist/src/hooks/useDeferredHookMessages.js +0 -43
  777. package/dist/src/hooks/useDiffData.js +0 -69
  778. package/dist/src/hooks/useDiffInIDE.js +0 -252
  779. package/dist/src/hooks/useDirectConnect.js +0 -150
  780. package/dist/src/hooks/useDoublePress.js +0 -44
  781. package/dist/src/hooks/useDynamicConfig.js +0 -17
  782. package/dist/src/hooks/useElapsedTime.js +0 -25
  783. package/dist/src/hooks/useExitOnCtrlCD.js +0 -57
  784. package/dist/src/hooks/useExitOnCtrlCDWithKeybindings.js +0 -17
  785. package/dist/src/hooks/useFileHistorySnapshotInit.js +0 -14
  786. package/dist/src/hooks/useGlobalKeybindings.js +0 -215
  787. package/dist/src/hooks/useHistorySearch.js +0 -241
  788. package/dist/src/hooks/useIDEIntegration.js +0 -56
  789. package/dist/src/hooks/useIdeAtMentioned.js +0 -51
  790. package/dist/src/hooks/useIdeConnectionStatus.js +0 -21
  791. package/dist/src/hooks/useIdeLogging.js +0 -29
  792. package/dist/src/hooks/useIdeSelection.js +0 -106
  793. package/dist/src/hooks/useInboxPoller.js +0 -709
  794. package/dist/src/hooks/useInputBuffer.js +0 -73
  795. package/dist/src/hooks/useIssueFlagBanner.js +0 -115
  796. package/dist/src/hooks/useLogMessages.js +0 -98
  797. package/dist/src/hooks/useLspPluginRecommendation.js +0 -176
  798. package/dist/src/hooks/useMailboxBridge.js +0 -15
  799. package/dist/src/hooks/useMainLoopModel.js +0 -25
  800. package/dist/src/hooks/useManagePlugins.js +0 -261
  801. package/dist/src/hooks/useMemoryUsage.js +0 -28
  802. package/dist/src/hooks/useMergedClients.js +0 -11
  803. package/dist/src/hooks/useMergedCommands.js +0 -10
  804. package/dist/src/hooks/useMergedTools.js +0 -32
  805. package/dist/src/hooks/useMinDisplayTime.js +0 -26
  806. package/dist/src/hooks/useNotifyAfterTimeout.js +0 -51
  807. package/dist/src/hooks/useOfficialMarketplaceNotification.js +0 -46
  808. package/dist/src/hooks/usePasteHandler.js +0 -188
  809. package/dist/src/hooks/usePluginRecommendationBase.js +0 -101
  810. package/dist/src/hooks/usePrStatus.js +0 -91
  811. package/dist/src/hooks/usePromptSuggestion.js +0 -128
  812. package/dist/src/hooks/usePromptsFromClaudeInChrome.js +0 -66
  813. package/dist/src/hooks/useQueueProcessor.js +0 -46
  814. package/dist/src/hooks/useRemoteSession.js +0 -431
  815. package/dist/src/hooks/useReplBridge.js +0 -717
  816. package/dist/src/hooks/useSSHSession.js +0 -167
  817. package/dist/src/hooks/useScheduledTasks.js +0 -104
  818. package/dist/src/hooks/useSearchInput.js +0 -302
  819. package/dist/src/hooks/useSessionBackgrounding.js +0 -132
  820. package/dist/src/hooks/useSettings.js +0 -10
  821. package/dist/src/hooks/useSettingsChange.js +0 -13
  822. package/dist/src/hooks/useSkillImprovementSurvey.js +0 -69
  823. package/dist/src/hooks/useSkillsChange.js +0 -51
  824. package/dist/src/hooks/useSwarmInitialization.js +0 -67
  825. package/dist/src/hooks/useSwarmPermissionPoller.js +0 -215
  826. package/dist/src/hooks/useTaskListWatcher.js +0 -157
  827. package/dist/src/hooks/useTasksV2.js +0 -220
  828. package/dist/src/hooks/useTeammateViewAutoExit.js +0 -55
  829. package/dist/src/hooks/useTelegramMirror.js +0 -47
  830. package/dist/src/hooks/useTeleportResume.js +0 -81
  831. package/dist/src/hooks/useTerminalSize.js +0 -9
  832. package/dist/src/hooks/useTextInput.js +0 -397
  833. package/dist/src/hooks/useTimeout.js +0 -10
  834. package/dist/src/hooks/useTurnDiffs.js +0 -160
  835. package/dist/src/hooks/useTypeahead.js +0 -1392
  836. package/dist/src/hooks/useUpdateNotification.js +0 -22
  837. package/dist/src/hooks/useVimInput.js +0 -232
  838. package/dist/src/hooks/useVirtualScroll.js +0 -627
  839. package/dist/src/hooks/useVoice.js +0 -954
  840. package/dist/src/hooks/useVoiceEnabled.js +0 -21
  841. package/dist/src/hooks/useVoiceIntegration.js +0 -631
  842. package/dist/src/hooks/useWhatsAppMirror.js +0 -46
  843. package/dist/src/index.js +0 -18
  844. package/dist/src/ink/Ansi.js +0 -269
  845. package/dist/src/ink/bidi.js +0 -117
  846. package/dist/src/ink/clearTerminal.js +0 -58
  847. package/dist/src/ink/colorize.js +0 -198
  848. package/dist/src/ink/components/AlternateScreen.js +0 -74
  849. package/dist/src/ink/components/App.js +0 -558
  850. package/dist/src/ink/components/AppContext.js +0 -11
  851. package/dist/src/ink/components/Box.js +0 -153
  852. package/dist/src/ink/components/Button.js +0 -166
  853. package/dist/src/ink/components/ClockContext.js +0 -108
  854. package/dist/src/ink/components/CursorDeclarationContext.js +0 -3
  855. package/dist/src/ink/components/ErrorOverview.js +0 -49
  856. package/dist/src/ink/components/Link.js +0 -33
  857. package/dist/src/ink/components/Newline.js +0 -29
  858. package/dist/src/ink/components/NoSelect.js +0 -56
  859. package/dist/src/ink/components/RawAnsi.js +0 -45
  860. package/dist/src/ink/components/ScrollBox.js +0 -170
  861. package/dist/src/ink/components/Spacer.js +0 -19
  862. package/dist/src/ink/components/StdinContext.js +0 -16
  863. package/dist/src/ink/components/TerminalFocusContext.js +0 -45
  864. package/dist/src/ink/components/TerminalSizeContext.js +0 -3
  865. package/dist/src/ink/components/Text.js +0 -194
  866. package/dist/src/ink/constants.js +0 -2
  867. package/dist/src/ink/devtools.js +0 -16
  868. package/dist/src/ink/dom.js +0 -298
  869. package/dist/src/ink/events/click-event.js +0 -36
  870. package/dist/src/ink/events/dispatcher.js +0 -172
  871. package/dist/src/ink/events/emitter.js +0 -31
  872. package/dist/src/ink/events/event-handlers.js +0 -30
  873. package/dist/src/ink/events/event.js +0 -9
  874. package/dist/src/ink/events/focus-event.js +0 -16
  875. package/dist/src/ink/events/input-event.js +0 -161
  876. package/dist/src/ink/events/keyboard-event.js +0 -45
  877. package/dist/src/ink/events/terminal-event.js +0 -78
  878. package/dist/src/ink/events/terminal-focus-event.js +0 -15
  879. package/dist/src/ink/focus.js +0 -158
  880. package/dist/src/ink/frame.js +0 -30
  881. package/dist/src/ink/get-max-width.js +0 -23
  882. package/dist/src/ink/hit-test.js +0 -113
  883. package/dist/src/ink/hooks/use-animation-frame.js +0 -48
  884. package/dist/src/ink/hooks/use-app.js +0 -7
  885. package/dist/src/ink/hooks/use-declared-cursor.js +0 -60
  886. package/dist/src/ink/hooks/use-input.js +0 -70
  887. package/dist/src/ink/hooks/use-interval.js +0 -54
  888. package/dist/src/ink/hooks/use-search-highlight.js +0 -32
  889. package/dist/src/ink/hooks/use-selection.js +0 -60
  890. package/dist/src/ink/hooks/use-stdin.js +0 -7
  891. package/dist/src/ink/hooks/use-tab-status.js +0 -57
  892. package/dist/src/ink/hooks/use-terminal-focus.js +0 -15
  893. package/dist/src/ink/hooks/use-terminal-title.js +0 -29
  894. package/dist/src/ink/hooks/use-terminal-viewport.js +0 -77
  895. package/dist/src/ink/ink.js +0 -1644
  896. package/dist/src/ink/instances.js +0 -7
  897. package/dist/src/ink/layout/engine.js +0 -4
  898. package/dist/src/ink/layout/geometry.js +0 -61
  899. package/dist/src/ink/layout/node.js +0 -62
  900. package/dist/src/ink/layout/yoga.js +0 -237
  901. package/dist/src/ink/line-width-cache.js +0 -19
  902. package/dist/src/ink/log-update.js +0 -583
  903. package/dist/src/ink/measure-element.js +0 -8
  904. package/dist/src/ink/measure-text.js +0 -35
  905. package/dist/src/ink/node-cache.js +0 -30
  906. package/dist/src/ink/optimizer.js +0 -81
  907. package/dist/src/ink/output.js +0 -556
  908. package/dist/src/ink/parse-keypress.js +0 -695
  909. package/dist/src/ink/reconciler.js +0 -384
  910. package/dist/src/ink/render-border.js +0 -134
  911. package/dist/src/ink/render-node-to-output.js +0 -1216
  912. package/dist/src/ink/render-to-screen.js +0 -171
  913. package/dist/src/ink/renderer.js +0 -129
  914. package/dist/src/ink/root.js +0 -80
  915. package/dist/src/ink/screen.js +0 -1132
  916. package/dist/src/ink/searchHighlight.js +0 -78
  917. package/dist/src/ink/selection.js +0 -792
  918. package/dist/src/ink/squash-text-nodes.js +0 -56
  919. package/dist/src/ink/stringWidth.js +0 -200
  920. package/dist/src/ink/styles.js +0 -299
  921. package/dist/src/ink/supports-hyperlinks.js +0 -40
  922. package/dist/src/ink/tabstops.js +0 -39
  923. package/dist/src/ink/terminal-focus-state.js +0 -35
  924. package/dist/src/ink/terminal-querier.js +0 -173
  925. package/dist/src/ink/terminal.js +0 -208
  926. package/dist/src/ink/termio/ansi.js +0 -70
  927. package/dist/src/ink/termio/csi.js +0 -260
  928. package/dist/src/ink/termio/dec.js +0 -53
  929. package/dist/src/ink/termio/esc.js +0 -55
  930. package/dist/src/ink/termio/osc.js +0 -432
  931. package/dist/src/ink/termio/parser.js +0 -356
  932. package/dist/src/ink/termio/sgr.js +0 -292
  933. package/dist/src/ink/termio/tokenize.js +0 -264
  934. package/dist/src/ink/termio/types.js +0 -55
  935. package/dist/src/ink/termio.js +0 -24
  936. package/dist/src/ink/useTerminalNotification.js +0 -57
  937. package/dist/src/ink/warn.js +0 -10
  938. package/dist/src/ink/widest-line.js +0 -14
  939. package/dist/src/ink/wrap-text.js +0 -54
  940. package/dist/src/ink/wrapAnsi.js +0 -6
  941. package/dist/src/ink.js +0 -50
  942. package/dist/src/interactiveHelpers.js +0 -317
  943. package/dist/src/keybindings/KeybindingContext.js +0 -184
  944. package/dist/src/keybindings/KeybindingProviderSetup.js +0 -259
  945. package/dist/src/keybindings/defaultBindings.js +0 -333
  946. package/dist/src/keybindings/loadUserBindings.js +0 -393
  947. package/dist/src/keybindings/match.js +0 -111
  948. package/dist/src/keybindings/parser.js +0 -184
  949. package/dist/src/keybindings/reservedShortcuts.js +0 -109
  950. package/dist/src/keybindings/resolver.js +0 -182
  951. package/dist/src/keybindings/schema.js +0 -205
  952. package/dist/src/keybindings/shortcutFormat.js +0 -48
  953. package/dist/src/keybindings/template.js +0 -40
  954. package/dist/src/keybindings/useKeybinding.js +0 -161
  955. package/dist/src/keybindings/useShortcutDisplay.js +0 -43
  956. package/dist/src/keybindings/validate.js +0 -395
  957. package/dist/src/main.js +0 -4073
  958. package/dist/src/memdir/findRelevantMemories.js +0 -101
  959. package/dist/src/memdir/memdir.js +0 -408
  960. package/dist/src/memdir/memoryAge.js +0 -52
  961. package/dist/src/memdir/memoryScan.js +0 -65
  962. package/dist/src/memdir/memoryTypes.js +0 -260
  963. package/dist/src/memdir/paths.js +0 -236
  964. package/dist/src/memdir/teamMemPaths.js +0 -261
  965. package/dist/src/memdir/teamMemPrompts.js +0 -82
  966. package/dist/src/migrations/migrateAutoUpdatesToSettings.js +0 -47
  967. package/dist/src/migrations/migrateBypassPermissionsAcceptedToSettings.js +0 -32
  968. package/dist/src/migrations/migrateEnableAllProjectMcpServersToSettings.js +0 -83
  969. package/dist/src/migrations/migrateFennecToOpus.js +0 -39
  970. package/dist/src/migrations/migrateLegacyOpusToCurrent.js +0 -44
  971. package/dist/src/migrations/migrateOpusToOpus1m.js +0 -31
  972. package/dist/src/migrations/migrateReplBridgeEnabledToRemoteControlAtStartup.js +0 -23
  973. package/dist/src/migrations/migrateSonnet1mToSonnet45.js +0 -38
  974. package/dist/src/migrations/migrateSonnet45ToSonnet46.js +0 -48
  975. package/dist/src/migrations/resetAutoModeOptInForDefaultOffer.js +0 -47
  976. package/dist/src/migrations/resetProToOpusDefault.js +0 -46
  977. package/dist/src/mirrors/shared.js +0 -186
  978. package/dist/src/moreright/useMoreRight.js +0 -13
  979. package/dist/src/native-ts/color-diff/index.js +0 -821
  980. package/dist/src/native-ts/file-index/index.js +0 -328
  981. package/dist/src/native-ts/yoga-layout/enums.js +0 -101
  982. package/dist/src/native-ts/yoga-layout/index.js +0 -2113
  983. package/dist/src/outputStyles/loadOutputStylesDir.js +0 -71
  984. package/dist/src/plugins/builtinPlugins.js +0 -132
  985. package/dist/src/plugins/bundled/index.js +0 -22
  986. package/dist/src/projectOnboardingState.js +0 -61
  987. package/dist/src/query/config.js +0 -17
  988. package/dist/src/query/deps.js +0 -12
  989. package/dist/src/query/stopHooks.js +0 -334
  990. package/dist/src/query/tokenBudget.js +0 -49
  991. package/dist/src/query.js +0 -1330
  992. package/dist/src/recovery/bunBundleShim.js +0 -11
  993. package/dist/src/remote/RemoteSessionManager.js +0 -195
  994. package/dist/src/remote/SessionsWebSocket.js +0 -305
  995. package/dist/src/remote/remotePermissionBridge.js +0 -70
  996. package/dist/src/remote/sdkMessageAdapter.js +0 -227
  997. package/dist/src/replLauncher.js +0 -6
  998. package/dist/src/schemas/hooks.js +0 -174
  999. package/dist/src/screens/Doctor.js +0 -580
  1000. package/dist/src/screens/REPL.js +0 -4434
  1001. package/dist/src/screens/ResumeConversation.js +0 -341
  1002. package/dist/src/self-hosted-runner/main.js +0 -16
  1003. package/dist/src/server/backends/dangerousBackend.js +0 -16
  1004. package/dist/src/server/connectHeadless.js +0 -16
  1005. package/dist/src/server/createDirectConnectSession.js +0 -62
  1006. package/dist/src/server/directConnectManager.js +0 -153
  1007. package/dist/src/server/lockfile.js +0 -16
  1008. package/dist/src/server/parseConnectUrl.js +0 -16
  1009. package/dist/src/server/server.js +0 -16
  1010. package/dist/src/server/serverBanner.js +0 -16
  1011. package/dist/src/server/serverLog.js +0 -16
  1012. package/dist/src/server/sessionManager.js +0 -16
  1013. package/dist/src/server/types.js +0 -7
  1014. package/dist/src/services/AgentSummary/agentSummary.js +0 -147
  1015. package/dist/src/services/MagicDocs/magicDocs.js +0 -193
  1016. package/dist/src/services/MagicDocs/prompts.js +0 -110
  1017. package/dist/src/services/PromptSuggestion/promptSuggestion.js +0 -402
  1018. package/dist/src/services/PromptSuggestion/speculation.js +0 -643
  1019. package/dist/src/services/SessionMemory/prompts.js +0 -254
  1020. package/dist/src/services/SessionMemory/sessionMemory.js +0 -358
  1021. package/dist/src/services/SessionMemory/sessionMemoryUtils.js +0 -157
  1022. package/dist/src/services/analytics/config.js +0 -33
  1023. package/dist/src/services/analytics/datadog.js +0 -259
  1024. package/dist/src/services/analytics/firstPartyEventLogger.js +0 -342
  1025. package/dist/src/services/analytics/firstPartyEventLoggingExporter.js +0 -594
  1026. package/dist/src/services/analytics/growthbook.js +0 -952
  1027. package/dist/src/services/analytics/index.js +0 -114
  1028. package/dist/src/services/analytics/metadata.js +0 -698
  1029. package/dist/src/services/analytics/sink.js +0 -95
  1030. package/dist/src/services/analytics/sinkKillswitch.js +0 -19
  1031. package/dist/src/services/api/adminRequests.js +0 -57
  1032. package/dist/src/services/api/bootstrap.js +0 -149
  1033. package/dist/src/services/api/claude.js +0 -2461
  1034. package/dist/src/services/api/client.js +0 -325
  1035. package/dist/src/services/api/dumpPrompts.js +0 -174
  1036. package/dist/src/services/api/emptyUsage.js +0 -20
  1037. package/dist/src/services/api/errorUtils.js +0 -203
  1038. package/dist/src/services/api/errors.js +0 -934
  1039. package/dist/src/services/api/filesApi.js +0 -523
  1040. package/dist/src/services/api/firstTokenDate.js +0 -49
  1041. package/dist/src/services/api/grove.js +0 -272
  1042. package/dist/src/services/api/index.js +0 -23
  1043. package/dist/src/services/api/logging.js +0 -484
  1044. package/dist/src/services/api/metricsOptOut.js +0 -127
  1045. package/dist/src/services/api/openai.js +0 -1187
  1046. package/dist/src/services/api/openrouter.js +0 -30
  1047. package/dist/src/services/api/overageCreditGrant.js +0 -123
  1048. package/dist/src/services/api/promptCacheBreakDetection.js +0 -510
  1049. package/dist/src/services/api/referral.js +0 -219
  1050. package/dist/src/services/api/sessionIngress.js +0 -358
  1051. package/dist/src/services/api/ultrareviewQuota.js +0 -29
  1052. package/dist/src/services/api/usage.js +0 -31
  1053. package/dist/src/services/api/withRetry.js +0 -599
  1054. package/dist/src/services/autoDream/autoDream.js +0 -244
  1055. package/dist/src/services/autoDream/config.js +0 -17
  1056. package/dist/src/services/autoDream/consolidationLock.js +0 -122
  1057. package/dist/src/services/autoDream/consolidationPrompt.js +0 -56
  1058. package/dist/src/services/awaySummary.js +0 -61
  1059. package/dist/src/services/claudeAiLimits.js +0 -331
  1060. package/dist/src/services/claudeAiLimitsHook.js +0 -15
  1061. package/dist/src/services/compact/apiMicrocompact.js +0 -97
  1062. package/dist/src/services/compact/autoCompact.js +0 -236
  1063. package/dist/src/services/compact/cachedMicrocompact.js +0 -16
  1064. package/dist/src/services/compact/compact.js +0 -1258
  1065. package/dist/src/services/compact/compactWarningHook.js +0 -12
  1066. package/dist/src/services/compact/compactWarningState.js +0 -15
  1067. package/dist/src/services/compact/grouping.js +0 -58
  1068. package/dist/src/services/compact/microCompact.js +0 -414
  1069. package/dist/src/services/compact/postCompactCleanup.js +0 -72
  1070. package/dist/src/services/compact/prompt.js +0 -327
  1071. package/dist/src/services/compact/sessionMemoryCompact.js +0 -467
  1072. package/dist/src/services/compact/timeBasedMCConfig.js +0 -11
  1073. package/dist/src/services/diagnosticTracking.js +0 -282
  1074. package/dist/src/services/extractMemories/extractMemories.js +0 -444
  1075. package/dist/src/services/extractMemories/prompts.js +0 -129
  1076. package/dist/src/services/internalLogging.js +0 -68
  1077. package/dist/src/services/lsp/LSPClient.js +0 -306
  1078. package/dist/src/services/lsp/LSPDiagnosticRegistry.js +0 -277
  1079. package/dist/src/services/lsp/LSPServerInstance.js +0 -390
  1080. package/dist/src/services/lsp/LSPServerManager.js +0 -305
  1081. package/dist/src/services/lsp/config.js +0 -57
  1082. package/dist/src/services/lsp/manager.js +0 -246
  1083. package/dist/src/services/lsp/passiveFeedback.js +0 -226
  1084. package/dist/src/services/mcp/InProcessTransport.js +0 -54
  1085. package/dist/src/services/mcp/MCPConnectionManager.js +0 -50
  1086. package/dist/src/services/mcp/SdkControlTransport.js +0 -115
  1087. package/dist/src/services/mcp/auth.js +0 -1882
  1088. package/dist/src/services/mcp/channelAllowlist.js +0 -57
  1089. package/dist/src/services/mcp/channelNotification.js +0 -236
  1090. package/dist/src/services/mcp/channelPermissions.js +0 -192
  1091. package/dist/src/services/mcp/claudeai.js +0 -123
  1092. package/dist/src/services/mcp/client.js +0 -2480
  1093. package/dist/src/services/mcp/config.js +0 -1277
  1094. package/dist/src/services/mcp/elicitationHandler.js +0 -192
  1095. package/dist/src/services/mcp/envExpansion.js +0 -30
  1096. package/dist/src/services/mcp/headersHelper.js +0 -94
  1097. package/dist/src/services/mcp/mcpStringUtils.js +0 -85
  1098. package/dist/src/services/mcp/normalization.js +0 -21
  1099. package/dist/src/services/mcp/oauthPort.js +0 -69
  1100. package/dist/src/services/mcp/officialRegistry.js +0 -54
  1101. package/dist/src/services/mcp/types.js +0 -94
  1102. package/dist/src/services/mcp/useManageMCPConnections.js +0 -820
  1103. package/dist/src/services/mcp/utils.js +0 -433
  1104. package/dist/src/services/mcp/vscodeSdkMcp.js +0 -69
  1105. package/dist/src/services/mcp/xaa.js +0 -342
  1106. package/dist/src/services/mcp/xaaIdpLogin.js +0 -377
  1107. package/dist/src/services/mcpServerApproval.js +0 -29
  1108. package/dist/src/services/mockRateLimits.js +0 -666
  1109. package/dist/src/services/notifier.js +0 -114
  1110. package/dist/src/services/oauth/auth-code-listener.js +0 -236
  1111. package/dist/src/services/oauth/client.js +0 -545
  1112. package/dist/src/services/oauth/crypto.js +0 -19
  1113. package/dist/src/services/oauth/getOauthProfile.js +0 -48
  1114. package/dist/src/services/oauth/index.js +0 -152
  1115. package/dist/src/services/oauth/types.js +0 -1
  1116. package/dist/src/services/plugins/PluginInstallationManager.js +0 -139
  1117. package/dist/src/services/plugins/pluginCliCommands.js +0 -230
  1118. package/dist/src/services/plugins/pluginOperations.js +0 -826
  1119. package/dist/src/services/policyLimits/index.js +0 -547
  1120. package/dist/src/services/policyLimits/types.js +0 -9
  1121. package/dist/src/services/preventSleep.js +0 -143
  1122. package/dist/src/services/rateLimitMessages.js +0 -271
  1123. package/dist/src/services/rateLimitMocking.js +0 -91
  1124. package/dist/src/services/remoteManagedSettings/index.js +0 -534
  1125. package/dist/src/services/remoteManagedSettings/securityCheck.js +0 -59
  1126. package/dist/src/services/remoteManagedSettings/syncCache.js +0 -90
  1127. package/dist/src/services/remoteManagedSettings/syncCacheState.js +0 -89
  1128. package/dist/src/services/remoteManagedSettings/types.js +0 -12
  1129. package/dist/src/services/settingsSync/index.js +0 -478
  1130. package/dist/src/services/settingsSync/types.js +0 -35
  1131. package/dist/src/services/teamMemorySync/index.js +0 -976
  1132. package/dist/src/services/teamMemorySync/secretScanner.js +0 -275
  1133. package/dist/src/services/teamMemorySync/teamMemSecretGuard.js +0 -35
  1134. package/dist/src/services/teamMemorySync/types.js +0 -47
  1135. package/dist/src/services/teamMemorySync/watcher.js +0 -326
  1136. package/dist/src/services/tips/tipHistory.js +0 -17
  1137. package/dist/src/services/tips/tipRegistry.js +0 -589
  1138. package/dist/src/services/tips/tipScheduler.js +0 -40
  1139. package/dist/src/services/tokenEstimation.js +0 -365
  1140. package/dist/src/services/toolUseSummary/toolUseSummaryGenerator.js +0 -87
  1141. package/dist/src/services/tools/StreamingToolExecutor.js +0 -413
  1142. package/dist/src/services/tools/toolExecution.js +0 -1218
  1143. package/dist/src/services/tools/toolHooks.js +0 -454
  1144. package/dist/src/services/tools/toolOrchestration.js +0 -110
  1145. package/dist/src/services/vcr.js +0 -291
  1146. package/dist/src/services/voice.js +0 -394
  1147. package/dist/src/services/voiceKeyterms.js +0 -94
  1148. package/dist/src/services/voiceStreamSTT.js +0 -406
  1149. package/dist/src/setup.js +0 -349
  1150. package/dist/src/skills/bundled/batch.js +0 -114
  1151. package/dist/src/skills/bundled/claudeApi.js +0 -145
  1152. package/dist/src/skills/bundled/claudeApiContent.js +0 -14
  1153. package/dist/src/skills/bundled/claudeInChrome.js +0 -27
  1154. package/dist/src/skills/bundled/debug.js +0 -99
  1155. package/dist/src/skills/bundled/index.js +0 -5
  1156. package/dist/src/skills/bundled/keybindings.js +0 -292
  1157. package/dist/src/skills/bundled/loop.js +0 -81
  1158. package/dist/src/skills/bundled/loremIpsum.js +0 -266
  1159. package/dist/src/skills/bundled/remember.js +0 -75
  1160. package/dist/src/skills/bundled/scheduleRemoteAgents.js +0 -373
  1161. package/dist/src/skills/bundled/simplify.js +0 -66
  1162. package/dist/src/skills/bundled/skillify.js +0 -184
  1163. package/dist/src/skills/bundled/stuck.js +0 -75
  1164. package/dist/src/skills/bundled/updateConfig.js +0 -463
  1165. package/dist/src/skills/bundled/verify.js +0 -25
  1166. package/dist/src/skills/bundled/verifyContent.js +0 -7
  1167. package/dist/src/skills/bundledSkills.js +0 -159
  1168. package/dist/src/skills/loadSkillsDir.js +0 -736
  1169. package/dist/src/skills/mcpSkillBuilders.js +0 -10
  1170. package/dist/src/ssh/createSSHSession.js +0 -16
  1171. package/dist/src/state/AppState.js +0 -184
  1172. package/dist/src/state/AppStateStore.js +0 -119
  1173. package/dist/src/state/onChangeAppState.js +0 -132
  1174. package/dist/src/state/selectors.js +0 -51
  1175. package/dist/src/state/store.js +0 -21
  1176. package/dist/src/state/teammateViewHelpers.js +0 -124
  1177. package/dist/src/tasks/DreamTask/DreamTask.js +0 -99
  1178. package/dist/src/tasks/InProcessTeammateTask/InProcessTeammateTask.js +0 -116
  1179. package/dist/src/tasks/InProcessTeammateTask/types.js +0 -35
  1180. package/dist/src/tasks/LocalAgentTask/LocalAgentTask.js +0 -507
  1181. package/dist/src/tasks/LocalMainSessionTask.js +0 -338
  1182. package/dist/src/tasks/LocalShellTask/LocalShellTask.js +0 -475
  1183. package/dist/src/tasks/LocalShellTask/guards.js +0 -9
  1184. package/dist/src/tasks/LocalShellTask/killShellTasks.js +0 -59
  1185. package/dist/src/tasks/RemoteAgentTask/RemoteAgentTask.js +0 -742
  1186. package/dist/src/tasks/pillLabel.js +0 -69
  1187. package/dist/src/tasks/stopTask.js +0 -67
  1188. package/dist/src/tasks/types.js +0 -18
  1189. package/dist/src/tasks.js +0 -39
  1190. package/dist/src/telegram/bridge.js +0 -334
  1191. package/dist/src/telegram/config.js +0 -57
  1192. package/dist/src/telegram/mirror.js +0 -91
  1193. package/dist/src/tools/AgentTool/AgentTool.js +0 -1222
  1194. package/dist/src/tools/AgentTool/UI.js +0 -592
  1195. package/dist/src/tools/AgentTool/agentColorManager.js +0 -43
  1196. package/dist/src/tools/AgentTool/agentDisplay.js +0 -72
  1197. package/dist/src/tools/AgentTool/agentMemory.js +0 -125
  1198. package/dist/src/tools/AgentTool/agentMemorySnapshot.js +0 -136
  1199. package/dist/src/tools/AgentTool/agentToolUtils.js +0 -456
  1200. package/dist/src/tools/AgentTool/built-in/claudeCodeGuideAgent.js +0 -175
  1201. package/dist/src/tools/AgentTool/built-in/exploreAgent.js +0 -76
  1202. package/dist/src/tools/AgentTool/built-in/generalPurposeAgent.js +0 -28
  1203. package/dist/src/tools/AgentTool/built-in/planAgent.js +0 -87
  1204. package/dist/src/tools/AgentTool/built-in/statuslineSetup.js +0 -140
  1205. package/dist/src/tools/AgentTool/built-in/verificationAgent.js +0 -146
  1206. package/dist/src/tools/AgentTool/builtInAgents.js +0 -58
  1207. package/dist/src/tools/AgentTool/constants.js +0 -11
  1208. package/dist/src/tools/AgentTool/forkSubagent.js +0 -177
  1209. package/dist/src/tools/AgentTool/loadAgentsDir.js +0 -497
  1210. package/dist/src/tools/AgentTool/prompt.js +0 -260
  1211. package/dist/src/tools/AgentTool/resumeAgent.js +0 -182
  1212. package/dist/src/tools/AgentTool/runAgent.js +0 -629
  1213. package/dist/src/tools/AskUserQuestionTool/AskUserQuestionTool.js +0 -237
  1214. package/dist/src/tools/AskUserQuestionTool/prompt.js +0 -38
  1215. package/dist/src/tools/BashTool/BashTool.js +0 -1008
  1216. package/dist/src/tools/BashTool/BashToolResultMessage.js +0 -168
  1217. package/dist/src/tools/BashTool/UI.js +0 -133
  1218. package/dist/src/tools/BashTool/bashCommandHelpers.js +0 -184
  1219. package/dist/src/tools/BashTool/bashPermissions.js +0 -2023
  1220. package/dist/src/tools/BashTool/bashSecurity.js +0 -2267
  1221. package/dist/src/tools/BashTool/commandSemantics.js +0 -105
  1222. package/dist/src/tools/BashTool/commentLabel.js +0 -14
  1223. package/dist/src/tools/BashTool/destructiveCommandWarning.js +0 -88
  1224. package/dist/src/tools/BashTool/modeValidation.js +0 -86
  1225. package/dist/src/tools/BashTool/pathValidation.js +0 -1080
  1226. package/dist/src/tools/BashTool/prompt.js +0 -333
  1227. package/dist/src/tools/BashTool/readOnlyValidation.js +0 -1794
  1228. package/dist/src/tools/BashTool/sedEditParser.js +0 -282
  1229. package/dist/src/tools/BashTool/sedValidation.js +0 -580
  1230. package/dist/src/tools/BashTool/shouldUseSandbox.js +0 -125
  1231. package/dist/src/tools/BashTool/toolName.js +0 -2
  1232. package/dist/src/tools/BashTool/utils.js +0 -180
  1233. package/dist/src/tools/BriefTool/BriefTool.js +0 -172
  1234. package/dist/src/tools/BriefTool/UI.js +0 -66
  1235. package/dist/src/tools/BriefTool/attachments.js +0 -86
  1236. package/dist/src/tools/BriefTool/prompt.js +0 -19
  1237. package/dist/src/tools/BriefTool/upload.js +0 -136
  1238. package/dist/src/tools/ConfigTool/ConfigTool.js +0 -398
  1239. package/dist/src/tools/ConfigTool/UI.js +0 -24
  1240. package/dist/src/tools/ConfigTool/constants.js +0 -1
  1241. package/dist/src/tools/ConfigTool/prompt.js +0 -82
  1242. package/dist/src/tools/ConfigTool/supportedSettings.js +0 -180
  1243. package/dist/src/tools/EnterPlanModeTool/EnterPlanModeTool.js +0 -98
  1244. package/dist/src/tools/EnterPlanModeTool/UI.js +0 -13
  1245. package/dist/src/tools/EnterPlanModeTool/constants.js +0 -1
  1246. package/dist/src/tools/EnterPlanModeTool/prompt.js +0 -164
  1247. package/dist/src/tools/EnterWorktreeTool/EnterWorktreeTool.js +0 -104
  1248. package/dist/src/tools/EnterWorktreeTool/UI.js +0 -8
  1249. package/dist/src/tools/EnterWorktreeTool/constants.js +0 -1
  1250. package/dist/src/tools/EnterWorktreeTool/prompt.js +0 -30
  1251. package/dist/src/tools/ExitPlanModeTool/ExitPlanModeV2Tool.js +0 -385
  1252. package/dist/src/tools/ExitPlanModeTool/UI.js +0 -31
  1253. package/dist/src/tools/ExitPlanModeTool/constants.js +0 -2
  1254. package/dist/src/tools/ExitPlanModeTool/prompt.js +0 -27
  1255. package/dist/src/tools/ExitWorktreeTool/ExitWorktreeTool.js +0 -257
  1256. package/dist/src/tools/ExitWorktreeTool/UI.js +0 -9
  1257. package/dist/src/tools/ExitWorktreeTool/constants.js +0 -1
  1258. package/dist/src/tools/ExitWorktreeTool/prompt.js +0 -32
  1259. package/dist/src/tools/FileEditTool/FileEditTool.js +0 -480
  1260. package/dist/src/tools/FileEditTool/UI.js +0 -201
  1261. package/dist/src/tools/FileEditTool/constants.js +0 -7
  1262. package/dist/src/tools/FileEditTool/prompt.js +0 -24
  1263. package/dist/src/tools/FileEditTool/types.js +0 -50
  1264. package/dist/src/tools/FileEditTool/utils.js +0 -579
  1265. package/dist/src/tools/FileReadTool/FileReadTool.js +0 -889
  1266. package/dist/src/tools/FileReadTool/UI.js +0 -125
  1267. package/dist/src/tools/FileReadTool/imageProcessor.js +0 -46
  1268. package/dist/src/tools/FileReadTool/limits.js +0 -70
  1269. package/dist/src/tools/FileReadTool/prompt.js +0 -31
  1270. package/dist/src/tools/FileWriteTool/FileWriteTool.js +0 -341
  1271. package/dist/src/tools/FileWriteTool/UI.js +0 -338
  1272. package/dist/src/tools/FileWriteTool/prompt.js +0 -15
  1273. package/dist/src/tools/GlobTool/GlobTool.js +0 -161
  1274. package/dist/src/tools/GlobTool/UI.js +0 -39
  1275. package/dist/src/tools/GlobTool/prompt.js +0 -6
  1276. package/dist/src/tools/GrepTool/GrepTool.js +0 -439
  1277. package/dist/src/tools/GrepTool/UI.js +0 -154
  1278. package/dist/src/tools/GrepTool/prompt.js +0 -16
  1279. package/dist/src/tools/LSPTool/LSPTool.js +0 -660
  1280. package/dist/src/tools/LSPTool/UI.js +0 -204
  1281. package/dist/src/tools/LSPTool/formatters.js +0 -445
  1282. package/dist/src/tools/LSPTool/prompt.js +0 -20
  1283. package/dist/src/tools/LSPTool/schemas.js +0 -197
  1284. package/dist/src/tools/LSPTool/symbolContext.js +0 -75
  1285. package/dist/src/tools/ListMcpResourcesTool/ListMcpResourcesTool.js +0 -100
  1286. package/dist/src/tools/ListMcpResourcesTool/UI.js +0 -16
  1287. package/dist/src/tools/ListMcpResourcesTool/prompt.js +0 -18
  1288. package/dist/src/tools/MCPTool/MCPTool.js +0 -60
  1289. package/dist/src/tools/MCPTool/UI.js +0 -342
  1290. package/dist/src/tools/MCPTool/classifyForCollapse.js +0 -597
  1291. package/dist/src/tools/MCPTool/prompt.js +0 -3
  1292. package/dist/src/tools/McpAuthTool/McpAuthTool.js +0 -162
  1293. package/dist/src/tools/NotebookEditTool/NotebookEditTool.js +0 -421
  1294. package/dist/src/tools/NotebookEditTool/UI.js +0 -40
  1295. package/dist/src/tools/NotebookEditTool/constants.js +0 -2
  1296. package/dist/src/tools/NotebookEditTool/prompt.js +0 -2
  1297. package/dist/src/tools/PowerShellTool/PowerShellTool.js +0 -899
  1298. package/dist/src/tools/PowerShellTool/UI.js +0 -57
  1299. package/dist/src/tools/PowerShellTool/clmTypes.js +0 -207
  1300. package/dist/src/tools/PowerShellTool/commandSemantics.js +0 -115
  1301. package/dist/src/tools/PowerShellTool/commonParameters.js +0 -27
  1302. package/dist/src/tools/PowerShellTool/destructiveCommandWarning.js +0 -92
  1303. package/dist/src/tools/PowerShellTool/gitSafety.js +0 -185
  1304. package/dist/src/tools/PowerShellTool/modeValidation.js +0 -357
  1305. package/dist/src/tools/PowerShellTool/pathValidation.js +0 -1712
  1306. package/dist/src/tools/PowerShellTool/powershellPermissions.js +0 -1351
  1307. package/dist/src/tools/PowerShellTool/powershellSecurity.js +0 -942
  1308. package/dist/src/tools/PowerShellTool/prompt.js +0 -132
  1309. package/dist/src/tools/PowerShellTool/readOnlyValidation.js +0 -1633
  1310. package/dist/src/tools/PowerShellTool/toolName.js +0 -2
  1311. package/dist/src/tools/REPLTool/constants.js +0 -43
  1312. package/dist/src/tools/REPLTool/primitiveTools.js +0 -36
  1313. package/dist/src/tools/ReadMcpResourceTool/ReadMcpResourceTool.js +0 -112
  1314. package/dist/src/tools/ReadMcpResourceTool/UI.js +0 -23
  1315. package/dist/src/tools/ReadMcpResourceTool/prompt.js +0 -15
  1316. package/dist/src/tools/RemoteTriggerTool/RemoteTriggerTool.js +0 -142
  1317. package/dist/src/tools/RemoteTriggerTool/UI.js +0 -11
  1318. package/dist/src/tools/RemoteTriggerTool/prompt.js +0 -12
  1319. package/dist/src/tools/ScheduleCronTool/CronCreateTool.js +0 -120
  1320. package/dist/src/tools/ScheduleCronTool/CronDeleteTool.js +0 -74
  1321. package/dist/src/tools/ScheduleCronTool/CronListTool.js +0 -77
  1322. package/dist/src/tools/ScheduleCronTool/UI.js +0 -28
  1323. package/dist/src/tools/ScheduleCronTool/prompt.js +0 -115
  1324. package/dist/src/tools/SendMessageTool/SendMessageTool.js +0 -675
  1325. package/dist/src/tools/SendMessageTool/UI.js +0 -23
  1326. package/dist/src/tools/SendMessageTool/constants.js +0 -1
  1327. package/dist/src/tools/SendMessageTool/prompt.js +0 -47
  1328. package/dist/src/tools/SkillTool/SkillTool.js +0 -827
  1329. package/dist/src/tools/SkillTool/UI.js +0 -60
  1330. package/dist/src/tools/SkillTool/constants.js +0 -1
  1331. package/dist/src/tools/SkillTool/prompt.js +0 -184
  1332. package/dist/src/tools/SleepTool/prompt.js +0 -14
  1333. package/dist/src/tools/SyntheticOutputTool/SyntheticOutputTool.js +0 -138
  1334. package/dist/src/tools/TaskCreateTool/TaskCreateTool.js +0 -104
  1335. package/dist/src/tools/TaskCreateTool/constants.js +0 -1
  1336. package/dist/src/tools/TaskCreateTool/prompt.js +0 -52
  1337. package/dist/src/tools/TaskGetTool/TaskGetTool.js +0 -106
  1338. package/dist/src/tools/TaskGetTool/constants.js +0 -1
  1339. package/dist/src/tools/TaskGetTool/prompt.js +0 -23
  1340. package/dist/src/tools/TaskListTool/TaskListTool.js +0 -89
  1341. package/dist/src/tools/TaskListTool/constants.js +0 -1
  1342. package/dist/src/tools/TaskListTool/prompt.js +0 -44
  1343. package/dist/src/tools/TaskOutputTool/TaskOutputTool.js +0 -535
  1344. package/dist/src/tools/TaskOutputTool/constants.js +0 -1
  1345. package/dist/src/tools/TaskStopTool/TaskStopTool.js +0 -110
  1346. package/dist/src/tools/TaskStopTool/UI.js +0 -30
  1347. package/dist/src/tools/TaskStopTool/prompt.js +0 -7
  1348. package/dist/src/tools/TaskUpdateTool/TaskUpdateTool.js +0 -301
  1349. package/dist/src/tools/TaskUpdateTool/constants.js +0 -1
  1350. package/dist/src/tools/TaskUpdateTool/prompt.js +0 -76
  1351. package/dist/src/tools/TeamCreateTool/TeamCreateTool.js +0 -177
  1352. package/dist/src/tools/TeamCreateTool/UI.js +0 -4
  1353. package/dist/src/tools/TeamCreateTool/constants.js +0 -1
  1354. package/dist/src/tools/TeamCreateTool/prompt.js +0 -113
  1355. package/dist/src/tools/TeamDeleteTool/TeamDeleteTool.js +0 -102
  1356. package/dist/src/tools/TeamDeleteTool/UI.js +0 -13
  1357. package/dist/src/tools/TeamDeleteTool/constants.js +0 -1
  1358. package/dist/src/tools/TeamDeleteTool/prompt.js +0 -16
  1359. package/dist/src/tools/TodoWriteTool/TodoWriteTool.js +0 -99
  1360. package/dist/src/tools/TodoWriteTool/constants.js +0 -1
  1361. package/dist/src/tools/TodoWriteTool/prompt.js +0 -181
  1362. package/dist/src/tools/ToolSearchTool/ToolSearchTool.js +0 -357
  1363. package/dist/src/tools/ToolSearchTool/constants.js +0 -1
  1364. package/dist/src/tools/ToolSearchTool/prompt.js +0 -99
  1365. package/dist/src/tools/TungstenTool/TungstenLiveMonitor.js +0 -7
  1366. package/dist/src/tools/TungstenTool/TungstenTool.js +0 -3
  1367. package/dist/src/tools/WebFetchTool/UI.js +0 -30
  1368. package/dist/src/tools/WebFetchTool/WebFetchTool.js +0 -246
  1369. package/dist/src/tools/WebFetchTool/preapproved.js +0 -155
  1370. package/dist/src/tools/WebFetchTool/prompt.js +0 -39
  1371. package/dist/src/tools/WebFetchTool/utils.js +0 -381
  1372. package/dist/src/tools/WebSearchTool/UI.js +0 -66
  1373. package/dist/src/tools/WebSearchTool/WebSearchTool.js +0 -352
  1374. package/dist/src/tools/WebSearchTool/prompt.js +0 -32
  1375. package/dist/src/tools/WorkflowTool/constants.js +0 -2
  1376. package/dist/src/tools/shared/gitOperationTracking.js +0 -220
  1377. package/dist/src/tools/shared/spawnMultiAgent.js +0 -805
  1378. package/dist/src/tools/testing/TestingPermissionTool.js +0 -72
  1379. package/dist/src/tools/utils.js +0 -24
  1380. package/dist/src/tools.js +0 -332
  1381. package/dist/src/types/command.js +0 -10
  1382. package/dist/src/types/connectorText.js +0 -2
  1383. package/dist/src/types/generated/events_mono/claude_code/v1/claude_code_internal_event.js +0 -673
  1384. package/dist/src/types/generated/events_mono/common/v1/auth.js +0 -49
  1385. package/dist/src/types/generated/events_mono/growthbook/v1/growthbook_experiment_event.js +0 -147
  1386. package/dist/src/types/generated/google/protobuf/timestamp.js +0 -38
  1387. package/dist/src/types/hooks.js +0 -153
  1388. package/dist/src/types/ids.js +0 -27
  1389. package/dist/src/types/logs.js +0 -11
  1390. package/dist/src/types/message.js +0 -1
  1391. package/dist/src/types/permissions.js +0 -25
  1392. package/dist/src/types/plugin.js +0 -72
  1393. package/dist/src/types/textInputTypes.js +0 -20
  1394. package/dist/src/types/utils.js +0 -5
  1395. package/dist/src/upstreamproxy/relay.js +0 -346
  1396. package/dist/src/upstreamproxy/upstreamproxy.js +0 -236
  1397. package/dist/src/utils/CircularBuffer.js +0 -75
  1398. package/dist/src/utils/Cursor.js +0 -1229
  1399. package/dist/src/utils/QueryGuard.js +0 -115
  1400. package/dist/src/utils/Shell.js +0 -374
  1401. package/dist/src/utils/ShellCommand.js +0 -338
  1402. package/dist/src/utils/abortController.js +0 -74
  1403. package/dist/src/utils/activityManager.js +0 -127
  1404. package/dist/src/utils/advisor.js +0 -77
  1405. package/dist/src/utils/agentContext.js +0 -91
  1406. package/dist/src/utils/agentId.js +0 -83
  1407. package/dist/src/utils/agentSwarmsEnabled.js +0 -37
  1408. package/dist/src/utils/agenticSessionSearch.js +0 -255
  1409. package/dist/src/utils/analyzeContext.js +0 -848
  1410. package/dist/src/utils/ansiToPng.js +0 -259
  1411. package/dist/src/utils/ansiToSvg.js +0 -207
  1412. package/dist/src/utils/api.js +0 -555
  1413. package/dist/src/utils/apiPreconnect.js +0 -62
  1414. package/dist/src/utils/appleTerminalBackup.js +0 -95
  1415. package/dist/src/utils/argumentSubstitution.js +0 -114
  1416. package/dist/src/utils/array.js +0 -12
  1417. package/dist/src/utils/asciicast.js +0 -200
  1418. package/dist/src/utils/attachments.js +0 -2514
  1419. package/dist/src/utils/attribution.js +0 -308
  1420. package/dist/src/utils/attributionHooks.js +0 -16
  1421. package/dist/src/utils/attributionTrailer.js +0 -16
  1422. package/dist/src/utils/auth.js +0 -2020
  1423. package/dist/src/utils/authFileDescriptor.js +0 -152
  1424. package/dist/src/utils/authPortable.js +0 -14
  1425. package/dist/src/utils/autoModeDenials.js +0 -15
  1426. package/dist/src/utils/autoRunIssue.js +0 -112
  1427. package/dist/src/utils/autoUpdater.js +0 -461
  1428. package/dist/src/utils/aws.js +0 -44
  1429. package/dist/src/utils/awsAuthStatusManager.js +0 -66
  1430. package/dist/src/utils/background/remote/preconditions.js +0 -175
  1431. package/dist/src/utils/background/remote/remoteSession.js +0 -53
  1432. package/dist/src/utils/backgroundHousekeeping.js +0 -66
  1433. package/dist/src/utils/bash/ParsedCommand.js +0 -241
  1434. package/dist/src/utils/bash/ShellSnapshot.js +0 -489
  1435. package/dist/src/utils/bash/ast.js +0 -2590
  1436. package/dist/src/utils/bash/bashParser.js +0 -4355
  1437. package/dist/src/utils/bash/bashPipeCommand.js +0 -249
  1438. package/dist/src/utils/bash/commands.js +0 -1131
  1439. package/dist/src/utils/bash/heredoc.js +0 -647
  1440. package/dist/src/utils/bash/parser.js +0 -195
  1441. package/dist/src/utils/bash/prefix.js +0 -154
  1442. package/dist/src/utils/bash/registry.js +0 -23
  1443. package/dist/src/utils/bash/shellCompletion.js +0 -196
  1444. package/dist/src/utils/bash/shellPrefix.js +0 -25
  1445. package/dist/src/utils/bash/shellQuote.js +0 -253
  1446. package/dist/src/utils/bash/shellQuoting.js +0 -106
  1447. package/dist/src/utils/bash/specs/alias.js +0 -11
  1448. package/dist/src/utils/bash/specs/index.js +0 -16
  1449. package/dist/src/utils/bash/specs/nohup.js +0 -10
  1450. package/dist/src/utils/bash/specs/pyright.js +0 -88
  1451. package/dist/src/utils/bash/specs/sleep.js +0 -10
  1452. package/dist/src/utils/bash/specs/srun.js +0 -28
  1453. package/dist/src/utils/bash/specs/time.js +0 -10
  1454. package/dist/src/utils/bash/specs/timeout.js +0 -17
  1455. package/dist/src/utils/bash/treeSitterAnalysis.js +0 -407
  1456. package/dist/src/utils/betas.js +0 -332
  1457. package/dist/src/utils/billing.js +0 -54
  1458. package/dist/src/utils/binaryCheck.js +0 -40
  1459. package/dist/src/utils/browser.js +0 -58
  1460. package/dist/src/utils/bufferedWriter.js +0 -77
  1461. package/dist/src/utils/bundledMode.js +0 -19
  1462. package/dist/src/utils/caCerts.js +0 -93
  1463. package/dist/src/utils/caCertsConfig.js +0 -77
  1464. package/dist/src/utils/cachePaths.js +0 -28
  1465. package/dist/src/utils/ccshareResume.js +0 -16
  1466. package/dist/src/utils/classifierApprovals.js +0 -66
  1467. package/dist/src/utils/classifierApprovalsHook.js +0 -10
  1468. package/dist/src/utils/claudeCodeHints.js +0 -142
  1469. package/dist/src/utils/claudeDesktop.js +0 -108
  1470. package/dist/src/utils/claudeInChrome/chromeNativeHost.js +0 -416
  1471. package/dist/src/utils/claudeInChrome/common.js +0 -466
  1472. package/dist/src/utils/claudeInChrome/mcpServer.js +0 -237
  1473. package/dist/src/utils/claudeInChrome/prompt.js +0 -79
  1474. package/dist/src/utils/claudeInChrome/setup.js +0 -320
  1475. package/dist/src/utils/claudeInChrome/setupPortable.js +0 -172
  1476. package/dist/src/utils/claudeInChrome/toolRendering.js +0 -234
  1477. package/dist/src/utils/claudemd.js +0 -1054
  1478. package/dist/src/utils/cleanup.js +0 -514
  1479. package/dist/src/utils/cleanupRegistry.js +0 -22
  1480. package/dist/src/utils/cliArgs.js +0 -53
  1481. package/dist/src/utils/cliHighlight.js +0 -45
  1482. package/dist/src/utils/codeIndexing.js +0 -149
  1483. package/dist/src/utils/collapseBackgroundBashNotifications.js +0 -70
  1484. package/dist/src/utils/collapseHookSummaries.js +0 -48
  1485. package/dist/src/utils/collapseReadSearch.js +0 -871
  1486. package/dist/src/utils/collapseTeammateShutdowns.js +0 -44
  1487. package/dist/src/utils/combinedAbortSignal.js +0 -40
  1488. package/dist/src/utils/commandLifecycle.js +0 -7
  1489. package/dist/src/utils/commitAttribution.js +0 -720
  1490. package/dist/src/utils/completionCache.js +0 -138
  1491. package/dist/src/utils/computerUse/appNames.js +0 -170
  1492. package/dist/src/utils/computerUse/cleanup.js +0 -66
  1493. package/dist/src/utils/computerUse/common.js +0 -56
  1494. package/dist/src/utils/computerUse/computerUseLock.js +0 -183
  1495. package/dist/src/utils/computerUse/drainRunLoop.js +0 -71
  1496. package/dist/src/utils/computerUse/escHotkey.js +0 -53
  1497. package/dist/src/utils/computerUse/executor.js +0 -480
  1498. package/dist/src/utils/computerUse/gates.js +0 -55
  1499. package/dist/src/utils/computerUse/hostAdapter.js +0 -62
  1500. package/dist/src/utils/computerUse/inputLoader.js +0 -27
  1501. package/dist/src/utils/computerUse/mcpServer.js +0 -84
  1502. package/dist/src/utils/computerUse/setup.js +0 -42
  1503. package/dist/src/utils/computerUse/swiftLoader.js +0 -20
  1504. package/dist/src/utils/computerUse/toolRendering.js +0 -100
  1505. package/dist/src/utils/computerUse/wrapper.js +0 -318
  1506. package/dist/src/utils/concurrentSessions.js +0 -179
  1507. package/dist/src/utils/config.js +0 -1084
  1508. package/dist/src/utils/configConstants.js +0 -18
  1509. package/dist/src/utils/contentArray.js +0 -45
  1510. package/dist/src/utils/context.js +0 -185
  1511. package/dist/src/utils/contextAnalysis.js +0 -171
  1512. package/dist/src/utils/contextSuggestions.js +0 -158
  1513. package/dist/src/utils/controlMessageCompat.js +0 -31
  1514. package/dist/src/utils/conversationRecovery.js +0 -436
  1515. package/dist/src/utils/cron.js +0 -260
  1516. package/dist/src/utils/cronJitterConfig.js +0 -62
  1517. package/dist/src/utils/cronScheduler.js +0 -388
  1518. package/dist/src/utils/cronTasks.js +0 -328
  1519. package/dist/src/utils/cronTasksLock.js +0 -159
  1520. package/dist/src/utils/crossProjectResume.js +0 -46
  1521. package/dist/src/utils/crypto.js +0 -13
  1522. package/dist/src/utils/cwd.js +0 -29
  1523. package/dist/src/utils/databaseMcp/common.js +0 -48
  1524. package/dist/src/utils/databaseMcp/mcpServer.js +0 -2
  1525. package/dist/src/utils/databaseMcp/server/connection.js +0 -243
  1526. package/dist/src/utils/databaseMcp/server/index.js +0 -1442
  1527. package/dist/src/utils/databaseMcp/server/queries.js +0 -683
  1528. package/dist/src/utils/databaseMcp/server/types.js +0 -7
  1529. package/dist/src/utils/databaseMcp/setup.js +0 -28
  1530. package/dist/src/utils/debug.js +0 -220
  1531. package/dist/src/utils/debugFilter.js +0 -125
  1532. package/dist/src/utils/deepLink/banner.js +0 -103
  1533. package/dist/src/utils/deepLink/parseDeepLink.js +0 -138
  1534. package/dist/src/utils/deepLink/protocolHandler.js +0 -119
  1535. package/dist/src/utils/deepLink/registerProtocol.js +0 -291
  1536. package/dist/src/utils/deepLink/terminalLauncher.js +0 -455
  1537. package/dist/src/utils/deepLink/terminalPreference.js +0 -51
  1538. package/dist/src/utils/desktopDeepLink.js +0 -208
  1539. package/dist/src/utils/detectRepository.js +0 -157
  1540. package/dist/src/utils/diagLogs.js +0 -74
  1541. package/dist/src/utils/diff.js +0 -108
  1542. package/dist/src/utils/directMemberMessage.js +0 -34
  1543. package/dist/src/utils/displayTags.js +0 -46
  1544. package/dist/src/utils/doctorContextWarnings.js +0 -179
  1545. package/dist/src/utils/doctorDiagnostic.js +0 -495
  1546. package/dist/src/utils/dxt/helpers.js +0 -64
  1547. package/dist/src/utils/dxt/zip.js +0 -167
  1548. package/dist/src/utils/earlyInput.js +0 -166
  1549. package/dist/src/utils/editor.js +0 -163
  1550. package/dist/src/utils/effort.js +0 -278
  1551. package/dist/src/utils/embeddedTools.js +0 -26
  1552. package/dist/src/utils/env.js +0 -358
  1553. package/dist/src/utils/envDynamic.js +0 -130
  1554. package/dist/src/utils/envUtils.js +0 -154
  1555. package/dist/src/utils/envValidation.js +0 -26
  1556. package/dist/src/utils/errorLogSink.js +0 -197
  1557. package/dist/src/utils/errors.js +0 -207
  1558. package/dist/src/utils/eventLoopStallDetector.js +0 -16
  1559. package/dist/src/utils/exampleCommands.js +0 -165
  1560. package/dist/src/utils/execFileNoThrow.js +0 -93
  1561. package/dist/src/utils/execFileNoThrowPortable.js +0 -111
  1562. package/dist/src/utils/execSyncWrapper.js +0 -68
  1563. package/dist/src/utils/exportRenderer.js +0 -71
  1564. package/dist/src/utils/extraUsage.js +0 -19
  1565. package/dist/src/utils/fastMode.js +0 -393
  1566. package/dist/src/utils/file.js +0 -467
  1567. package/dist/src/utils/fileHistory.js +0 -851
  1568. package/dist/src/utils/fileOperationAnalytics.js +0 -45
  1569. package/dist/src/utils/filePersistence/filePersistence.js +0 -212
  1570. package/dist/src/utils/filePersistence/outputsScanner.js +0 -104
  1571. package/dist/src/utils/filePersistence/types.js +0 -5
  1572. package/dist/src/utils/fileRead.js +0 -81
  1573. package/dist/src/utils/fileReadCache.js +0 -78
  1574. package/dist/src/utils/fileStateCache.js +0 -99
  1575. package/dist/src/utils/findExecutable.js +0 -13
  1576. package/dist/src/utils/fingerprint.js +0 -59
  1577. package/dist/src/utils/forkedAgent.js +0 -410
  1578. package/dist/src/utils/format.js +0 -238
  1579. package/dist/src/utils/formatBriefTimestamp.js +0 -72
  1580. package/dist/src/utils/fpsTracker.js +0 -34
  1581. package/dist/src/utils/frontmatterParser.js +0 -260
  1582. package/dist/src/utils/fsOperations.js +0 -834
  1583. package/dist/src/utils/fullscreen.js +0 -194
  1584. package/dist/src/utils/generatedFiles.js +0 -122
  1585. package/dist/src/utils/generators.js +0 -67
  1586. package/dist/src/utils/genericProcessUtils.js +0 -155
  1587. package/dist/src/utils/getWorktreePaths.js +0 -56
  1588. package/dist/src/utils/getWorktreePathsPortable.js +0 -23
  1589. package/dist/src/utils/ghPrStatus.js +0 -71
  1590. package/dist/src/utils/git/gitConfigParser.js +0 -226
  1591. package/dist/src/utils/git/gitFilesystem.js +0 -606
  1592. package/dist/src/utils/git/gitignore.js +0 -84
  1593. package/dist/src/utils/git.js +0 -725
  1594. package/dist/src/utils/gitDiff.js +0 -395
  1595. package/dist/src/utils/gitSettings.js +0 -18
  1596. package/dist/src/utils/github/ghAuthStatus.js +0 -23
  1597. package/dist/src/utils/githubRepoPathMapping.js +0 -135
  1598. package/dist/src/utils/glob.js +0 -90
  1599. package/dist/src/utils/gracefulShutdown.js +0 -447
  1600. package/dist/src/utils/groupToolUses.js +0 -126
  1601. package/dist/src/utils/handlePromptSubmit.js +0 -398
  1602. package/dist/src/utils/hash.js +0 -46
  1603. package/dist/src/utils/headlessProfiler.js +0 -147
  1604. package/dist/src/utils/heapDumpService.js +0 -202
  1605. package/dist/src/utils/heatmap.js +0 -151
  1606. package/dist/src/utils/highlightMatch.js +0 -28
  1607. package/dist/src/utils/hooks/AsyncHookRegistry.js +0 -187
  1608. package/dist/src/utils/hooks/apiQueryHookHelper.js +0 -77
  1609. package/dist/src/utils/hooks/execAgentHook.js +0 -257
  1610. package/dist/src/utils/hooks/execHttpHook.js +0 -184
  1611. package/dist/src/utils/hooks/execPromptHook.js +0 -171
  1612. package/dist/src/utils/hooks/fileChangedWatcher.js +0 -161
  1613. package/dist/src/utils/hooks/hookEvents.js +0 -111
  1614. package/dist/src/utils/hooks/hookHelpers.js +0 -60
  1615. package/dist/src/utils/hooks/hooksConfigManager.js +0 -323
  1616. package/dist/src/utils/hooks/hooksConfigSnapshot.js +0 -114
  1617. package/dist/src/utils/hooks/hooksSettings.js +0 -204
  1618. package/dist/src/utils/hooks/postSamplingHooks.js +0 -39
  1619. package/dist/src/utils/hooks/registerFrontmatterHooks.js +0 -47
  1620. package/dist/src/utils/hooks/registerSkillHooks.js +0 -40
  1621. package/dist/src/utils/hooks/sessionHooks.js +0 -252
  1622. package/dist/src/utils/hooks/skillImprovement.js +0 -211
  1623. package/dist/src/utils/hooks/ssrfGuard.js +0 -258
  1624. package/dist/src/utils/hooks.js +0 -3668
  1625. package/dist/src/utils/horizontalScroll.js +0 -108
  1626. package/dist/src/utils/http.js +0 -121
  1627. package/dist/src/utils/hyperlink.js +0 -28
  1628. package/dist/src/utils/iTermBackup.js +0 -48
  1629. package/dist/src/utils/ide.js +0 -1198
  1630. package/dist/src/utils/idePathConversion.js +0 -66
  1631. package/dist/src/utils/idleTimeout.js +0 -44
  1632. package/dist/src/utils/imagePaste.js +0 -329
  1633. package/dist/src/utils/imageResizer.js +0 -664
  1634. package/dist/src/utils/imageStore.js +0 -150
  1635. package/dist/src/utils/imageValidation.js +0 -92
  1636. package/dist/src/utils/immediateCommand.js +0 -12
  1637. package/dist/src/utils/inProcessTeammateHelpers.js +0 -71
  1638. package/dist/src/utils/ink.js +0 -20
  1639. package/dist/src/utils/intl.js +0 -83
  1640. package/dist/src/utils/jetbrains.js +0 -152
  1641. package/dist/src/utils/json.js +0 -295
  1642. package/dist/src/utils/jsonRead.js +0 -14
  1643. package/dist/src/utils/keyboardShortcuts.js +0 -11
  1644. package/dist/src/utils/lazySchema.js +0 -8
  1645. package/dist/src/utils/listSessionsImpl.js +0 -332
  1646. package/dist/src/utils/localInstaller.js +0 -131
  1647. package/dist/src/utils/lockfile.js +0 -22
  1648. package/dist/src/utils/log.js +0 -280
  1649. package/dist/src/utils/logoV2Utils.js +0 -288
  1650. package/dist/src/utils/mailbox.js +0 -50
  1651. package/dist/src/utils/managedEnv.js +0 -160
  1652. package/dist/src/utils/managedEnvConstants.js +0 -187
  1653. package/dist/src/utils/markdown.js +0 -300
  1654. package/dist/src/utils/markdownConfigLoader.js +0 -480
  1655. package/dist/src/utils/mcp/dateTimeParser.js +0 -102
  1656. package/dist/src/utils/mcp/elicitationValidation.js +0 -259
  1657. package/dist/src/utils/mcpInstructionsDelta.js +0 -97
  1658. package/dist/src/utils/mcpOutputStorage.js +0 -159
  1659. package/dist/src/utils/mcpValidation.js +0 -165
  1660. package/dist/src/utils/mcpWebSocketTransport.js +0 -180
  1661. package/dist/src/utils/memoize.js +0 -205
  1662. package/dist/src/utils/memory/types.js +0 -9
  1663. package/dist/src/utils/memory/versions.js +0 -7
  1664. package/dist/src/utils/memoryFileDetection.js +0 -247
  1665. package/dist/src/utils/messagePredicates.js +0 -6
  1666. package/dist/src/utils/messageQueueManager.js +0 -430
  1667. package/dist/src/utils/messages/mappers.js +0 -240
  1668. package/dist/src/utils/messages/systemInit.js +0 -74
  1669. package/dist/src/utils/messages.js +0 -4273
  1670. package/dist/src/utils/model/agent.js +0 -128
  1671. package/dist/src/utils/model/aliases.js +0 -21
  1672. package/dist/src/utils/model/antModels.js +0 -25
  1673. package/dist/src/utils/model/bedrock.js +0 -220
  1674. package/dist/src/utils/model/check1mAccess.js +0 -64
  1675. package/dist/src/utils/model/configs.js +0 -93
  1676. package/dist/src/utils/model/contextWindowUpgradeCheck.js +0 -41
  1677. package/dist/src/utils/model/deprecation.js +0 -72
  1678. package/dist/src/utils/model/model.js +0 -635
  1679. package/dist/src/utils/model/modelAllowlist.js +0 -148
  1680. package/dist/src/utils/model/modelCapabilities.js +0 -107
  1681. package/dist/src/utils/model/modelOptions.js +0 -627
  1682. package/dist/src/utils/model/modelStrings.js +0 -144
  1683. package/dist/src/utils/model/modelSupportOverrides.js +0 -40
  1684. package/dist/src/utils/model/openrouter.js +0 -51
  1685. package/dist/src/utils/model/providerBaseUrls.js +0 -77
  1686. package/dist/src/utils/model/providerCatalog.js +0 -81
  1687. package/dist/src/utils/model/providerModels.js +0 -334
  1688. package/dist/src/utils/model/providerProfiles.js +0 -392
  1689. package/dist/src/utils/model/providerProfilesDb.js +0 -556
  1690. package/dist/src/utils/model/providerSwitch.js +0 -68
  1691. package/dist/src/utils/model/providers.js +0 -199
  1692. package/dist/src/utils/model/validateModel.js +0 -257
  1693. package/dist/src/utils/modelCost.js +0 -160
  1694. package/dist/src/utils/modifiers.js +0 -35
  1695. package/dist/src/utils/mtls.js +0 -134
  1696. package/dist/src/utils/nativeInstaller/download.js +0 -370
  1697. package/dist/src/utils/nativeInstaller/index.js +0 -8
  1698. package/dist/src/utils/nativeInstaller/installer.js +0 -1396
  1699. package/dist/src/utils/nativeInstaller/packageManagers.js +0 -258
  1700. package/dist/src/utils/nativeInstaller/pidLock.js +0 -347
  1701. package/dist/src/utils/notebook.js +0 -176
  1702. package/dist/src/utils/objectGroupBy.js +0 -15
  1703. package/dist/src/utils/pasteStore.js +0 -93
  1704. package/dist/src/utils/path.js +0 -140
  1705. package/dist/src/utils/pdf.js +0 -236
  1706. package/dist/src/utils/pdfUtils.js +0 -61
  1707. package/dist/src/utils/peerAddress.js +0 -20
  1708. package/dist/src/utils/permissions/PermissionMode.js +0 -95
  1709. package/dist/src/utils/permissions/PermissionPromptToolResultSchema.js +0 -85
  1710. package/dist/src/utils/permissions/PermissionResult.js +0 -11
  1711. package/dist/src/utils/permissions/PermissionRule.js +0 -19
  1712. package/dist/src/utils/permissions/PermissionUpdate.js +0 -268
  1713. package/dist/src/utils/permissions/PermissionUpdateSchema.js +0 -61
  1714. package/dist/src/utils/permissions/autoModeState.js +0 -34
  1715. package/dist/src/utils/permissions/bashClassifier.js +0 -30
  1716. package/dist/src/utils/permissions/bypassPermissionsKillswitch.js +0 -115
  1717. package/dist/src/utils/permissions/classifierDecision.js +0 -88
  1718. package/dist/src/utils/permissions/classifierShared.js +0 -28
  1719. package/dist/src/utils/permissions/dangerousPatterns.js +0 -78
  1720. package/dist/src/utils/permissions/denialTracking.js +0 -34
  1721. package/dist/src/utils/permissions/filesystem.js +0 -1411
  1722. package/dist/src/utils/permissions/getNextPermissionMode.js +0 -74
  1723. package/dist/src/utils/permissions/pathValidation.js +0 -351
  1724. package/dist/src/utils/permissions/permissionExplainer.js +0 -188
  1725. package/dist/src/utils/permissions/permissionRuleParser.js +0 -177
  1726. package/dist/src/utils/permissions/permissionSetup.js +0 -1164
  1727. package/dist/src/utils/permissions/permissions.js +0 -1065
  1728. package/dist/src/utils/permissions/permissionsLoader.js +0 -217
  1729. package/dist/src/utils/permissions/shadowedRuleDetection.js +0 -149
  1730. package/dist/src/utils/permissions/shellRuleMatching.js +0 -174
  1731. package/dist/src/utils/permissions/yoloClassifier.js +0 -1195
  1732. package/dist/src/utils/planModeV2.js +0 -75
  1733. package/dist/src/utils/plans.js +0 -334
  1734. package/dist/src/utils/platform.js +0 -122
  1735. package/dist/src/utils/plugins/addDirPluginSettings.js +0 -53
  1736. package/dist/src/utils/plugins/cacheUtils.js +0 -174
  1737. package/dist/src/utils/plugins/dependencyResolver.js +0 -244
  1738. package/dist/src/utils/plugins/fetchTelemetry.js +0 -108
  1739. package/dist/src/utils/plugins/gitAvailability.js +0 -65
  1740. package/dist/src/utils/plugins/headlessPluginInstall.js +0 -136
  1741. package/dist/src/utils/plugins/hintRecommendation.js +0 -136
  1742. package/dist/src/utils/plugins/installCounts.js +0 -218
  1743. package/dist/src/utils/plugins/installedPluginsManager.js +0 -1003
  1744. package/dist/src/utils/plugins/loadPluginAgents.js +0 -219
  1745. package/dist/src/utils/plugins/loadPluginCommands.js +0 -595
  1746. package/dist/src/utils/plugins/loadPluginHooks.js +0 -239
  1747. package/dist/src/utils/plugins/loadPluginOutputStyles.js +0 -112
  1748. package/dist/src/utils/plugins/lspPluginIntegration.js +0 -293
  1749. package/dist/src/utils/plugins/lspRecommendation.js +0 -278
  1750. package/dist/src/utils/plugins/managedPlugins.js +0 -26
  1751. package/dist/src/utils/plugins/marketplaceHelpers.js +0 -470
  1752. package/dist/src/utils/plugins/marketplaceManager.js +0 -1939
  1753. package/dist/src/utils/plugins/mcpPluginIntegration.js +0 -465
  1754. package/dist/src/utils/plugins/mcpbHandler.js +0 -708
  1755. package/dist/src/utils/plugins/officialMarketplace.js +0 -21
  1756. package/dist/src/utils/plugins/officialMarketplaceGcs.js +0 -195
  1757. package/dist/src/utils/plugins/officialMarketplaceStartupCheck.js +0 -338
  1758. package/dist/src/utils/plugins/orphanedPluginFilter.js +0 -96
  1759. package/dist/src/utils/plugins/parseMarketplaceInput.js +0 -143
  1760. package/dist/src/utils/plugins/performStartupChecks.js +0 -66
  1761. package/dist/src/utils/plugins/pluginAutoupdate.js +0 -210
  1762. package/dist/src/utils/plugins/pluginBlocklist.js +0 -93
  1763. package/dist/src/utils/plugins/pluginDirectories.js +0 -170
  1764. package/dist/src/utils/plugins/pluginFlagging.js +0 -173
  1765. package/dist/src/utils/plugins/pluginIdentifier.js +0 -78
  1766. package/dist/src/utils/plugins/pluginInstallationHelpers.js +0 -400
  1767. package/dist/src/utils/plugins/pluginLoader.js +0 -2426
  1768. package/dist/src/utils/plugins/pluginOptionsStorage.js +0 -311
  1769. package/dist/src/utils/plugins/pluginPolicy.js +0 -18
  1770. package/dist/src/utils/plugins/pluginStartupCheck.js +0 -261
  1771. package/dist/src/utils/plugins/pluginVersioning.js +0 -128
  1772. package/dist/src/utils/plugins/reconciler.js +0 -181
  1773. package/dist/src/utils/plugins/refresh.js +0 -162
  1774. package/dist/src/utils/plugins/schemas.js +0 -1283
  1775. package/dist/src/utils/plugins/validatePlugin.js +0 -765
  1776. package/dist/src/utils/plugins/walkPluginMarkdown.js +0 -49
  1777. package/dist/src/utils/plugins/zipCache.js +0 -346
  1778. package/dist/src/utils/plugins/zipCacheAdapters.js +0 -133
  1779. package/dist/src/utils/postCommitAttribution.js +0 -16
  1780. package/dist/src/utils/powershell/dangerousCmdlets.js +0 -174
  1781. package/dist/src/utils/powershell/parser.js +0 -1357
  1782. package/dist/src/utils/powershell/staticPrefix.js +0 -277
  1783. package/dist/src/utils/preflightChecks.js +0 -147
  1784. package/dist/src/utils/privacyLevel.js +0 -49
  1785. package/dist/src/utils/process.js +0 -56
  1786. package/dist/src/utils/processUserInput/processBashCommand.js +0 -119
  1787. package/dist/src/utils/processUserInput/processSlashCommand.js +0 -845
  1788. package/dist/src/utils/processUserInput/processTextPrompt.js +0 -68
  1789. package/dist/src/utils/processUserInput/processUserInput.js +0 -326
  1790. package/dist/src/utils/profilerBase.js +0 -29
  1791. package/dist/src/utils/promptCategory.js +0 -39
  1792. package/dist/src/utils/promptEditor.js +0 -151
  1793. package/dist/src/utils/promptShellExecution.js +0 -119
  1794. package/dist/src/utils/proxy.js +0 -347
  1795. package/dist/src/utils/queryContext.js +0 -110
  1796. package/dist/src/utils/queryHelpers.js +0 -436
  1797. package/dist/src/utils/queryProfiler.js +0 -242
  1798. package/dist/src/utils/queueProcessor.js +0 -70
  1799. package/dist/src/utils/readEditContext.js +0 -176
  1800. package/dist/src/utils/readFileInRange.js +0 -278
  1801. package/dist/src/utils/releaseNotes.js +0 -304
  1802. package/dist/src/utils/renderOptions.js +0 -67
  1803. package/dist/src/utils/ripgrep.js +0 -540
  1804. package/dist/src/utils/sandbox/sandbox-adapter.js +0 -749
  1805. package/dist/src/utils/sandbox/sandbox-ui-utils.js +0 -11
  1806. package/dist/src/utils/sanitization.js +0 -72
  1807. package/dist/src/utils/screenshotClipboard.js +0 -89
  1808. package/dist/src/utils/sdkEventQueue.js +0 -49
  1809. package/dist/src/utils/sdkHeapDumpMonitor.js +0 -16
  1810. package/dist/src/utils/secureStorage/fallbackStorage.js +0 -59
  1811. package/dist/src/utils/secureStorage/index.js +0 -14
  1812. package/dist/src/utils/secureStorage/keychainPrefetch.js +0 -91
  1813. package/dist/src/utils/secureStorage/macOsKeychainHelpers.js +0 -91
  1814. package/dist/src/utils/secureStorage/macOsKeychainStorage.js +0 -192
  1815. package/dist/src/utils/secureStorage/plainTextStorage.js +0 -81
  1816. package/dist/src/utils/secureStorage/secureStoreDefs.js +0 -1
  1817. package/dist/src/utils/secureStorage/sqliteStorage.js +0 -217
  1818. package/dist/src/utils/secureStorage/types.js +0 -1
  1819. package/dist/src/utils/semanticBoolean.js +0 -23
  1820. package/dist/src/utils/semanticNumber.js +0 -34
  1821. package/dist/src/utils/semver.js +0 -53
  1822. package/dist/src/utils/sequential.js +0 -43
  1823. package/dist/src/utils/sessionActivity.js +0 -120
  1824. package/dist/src/utils/sessionDataUploader.js +0 -16
  1825. package/dist/src/utils/sessionEnvVars.js +0 -18
  1826. package/dist/src/utils/sessionEnvironment.js +0 -131
  1827. package/dist/src/utils/sessionFileAccessHooks.js +0 -207
  1828. package/dist/src/utils/sessionIngressAuth.js +0 -113
  1829. package/dist/src/utils/sessionRestore.js +0 -359
  1830. package/dist/src/utils/sessionStart.js +0 -165
  1831. package/dist/src/utils/sessionState.js +0 -76
  1832. package/dist/src/utils/sessionStorage.js +0 -4162
  1833. package/dist/src/utils/sessionStoragePortable.js +0 -665
  1834. package/dist/src/utils/sessionTitle.js +0 -120
  1835. package/dist/src/utils/sessionUrl.js +0 -50
  1836. package/dist/src/utils/set.js +0 -50
  1837. package/dist/src/utils/settings/allErrors.js +0 -29
  1838. package/dist/src/utils/settings/applySettingsChange.js +0 -65
  1839. package/dist/src/utils/settings/changeDetector.js +0 -409
  1840. package/dist/src/utils/settings/constants.js +0 -166
  1841. package/dist/src/utils/settings/internalWrites.js +0 -33
  1842. package/dist/src/utils/settings/managedPath.js +0 -29
  1843. package/dist/src/utils/settings/mdm/constants.js +0 -62
  1844. package/dist/src/utils/settings/mdm/rawRead.js +0 -97
  1845. package/dist/src/utils/settings/mdm/settings.js +0 -254
  1846. package/dist/src/utils/settings/permissionValidation.js +0 -224
  1847. package/dist/src/utils/settings/pluginOnlyPolicy.js +0 -53
  1848. package/dist/src/utils/settings/schemaOutput.js +0 -7
  1849. package/dist/src/utils/settings/settings.js +0 -791
  1850. package/dist/src/utils/settings/settingsCache.js +0 -47
  1851. package/dist/src/utils/settings/toolValidationConfig.js +0 -76
  1852. package/dist/src/utils/settings/types.js +0 -846
  1853. package/dist/src/utils/settings/validateEditTool.js +0 -34
  1854. package/dist/src/utils/settings/validation.js +0 -192
  1855. package/dist/src/utils/settings/validationTips.js +0 -111
  1856. package/dist/src/utils/shell/bashProvider.js +0 -202
  1857. package/dist/src/utils/shell/outputLimits.js +0 -7
  1858. package/dist/src/utils/shell/powershellDetection.js +0 -96
  1859. package/dist/src/utils/shell/powershellProvider.js +0 -104
  1860. package/dist/src/utils/shell/prefix.js +0 -246
  1861. package/dist/src/utils/shell/readOnlyCommandValidation.js +0 -1776
  1862. package/dist/src/utils/shell/resolveDefaultShell.js +0 -13
  1863. package/dist/src/utils/shell/shellProvider.js +0 -2
  1864. package/dist/src/utils/shell/shellToolUtils.js +0 -21
  1865. package/dist/src/utils/shell/specPrefix.js +0 -198
  1866. package/dist/src/utils/shellConfig.js +0 -136
  1867. package/dist/src/utils/sideQuery.js +0 -195
  1868. package/dist/src/utils/sideQuestion.js +0 -121
  1869. package/dist/src/utils/signal.js +0 -34
  1870. package/dist/src/utils/sinks.js +0 -15
  1871. package/dist/src/utils/skills/skillChangeDetector.js +0 -264
  1872. package/dist/src/utils/slashCommandParsing.js +0 -46
  1873. package/dist/src/utils/sleep.js +0 -72
  1874. package/dist/src/utils/sliceAnsi.js +0 -74
  1875. package/dist/src/utils/slowOperations.js +0 -323
  1876. package/dist/src/utils/standaloneAgent.js +0 -20
  1877. package/dist/src/utils/startupProfiler.js +0 -158
  1878. package/dist/src/utils/staticRender.js +0 -103
  1879. package/dist/src/utils/stats.js +0 -802
  1880. package/dist/src/utils/statsCache.js +0 -330
  1881. package/dist/src/utils/status.js +0 -544
  1882. package/dist/src/utils/statusNoticeDefinitions.js +0 -112
  1883. package/dist/src/utils/statusNoticeHelpers.js +0 -15
  1884. package/dist/src/utils/stream.js +0 -73
  1885. package/dist/src/utils/streamJsonStdoutGuard.js +0 -107
  1886. package/dist/src/utils/streamlinedTransform.js +0 -162
  1887. package/dist/src/utils/stringUtils.js +0 -202
  1888. package/dist/src/utils/subprocessEnv.js +0 -87
  1889. package/dist/src/utils/suggestions/commandSuggestions.js +0 -458
  1890. package/dist/src/utils/suggestions/directoryCompletion.js +0 -191
  1891. package/dist/src/utils/suggestions/shellHistoryCompletion.js +0 -95
  1892. package/dist/src/utils/suggestions/skillUsageTracking.js +0 -50
  1893. package/dist/src/utils/suggestions/slackChannelSuggestions.js +0 -169
  1894. package/dist/src/utils/swarm/It2SetupPrompt.js +0 -386
  1895. package/dist/src/utils/swarm/backends/ITermBackend.js +0 -276
  1896. package/dist/src/utils/swarm/backends/InProcessBackend.js +0 -237
  1897. package/dist/src/utils/swarm/backends/PaneBackendExecutor.js +0 -250
  1898. package/dist/src/utils/swarm/backends/TmuxBackend.js +0 -574
  1899. package/dist/src/utils/swarm/backends/detection.js +0 -112
  1900. package/dist/src/utils/swarm/backends/it2Setup.js +0 -185
  1901. package/dist/src/utils/swarm/backends/registry.js +0 -369
  1902. package/dist/src/utils/swarm/backends/teammateModeSnapshot.js +0 -68
  1903. package/dist/src/utils/swarm/backends/types.js +0 -9
  1904. package/dist/src/utils/swarm/constants.js +0 -29
  1905. package/dist/src/utils/swarm/inProcessRunner.js +0 -1021
  1906. package/dist/src/utils/swarm/leaderPermissionBridge.js +0 -31
  1907. package/dist/src/utils/swarm/permissionSync.js +0 -667
  1908. package/dist/src/utils/swarm/reconnection.js +0 -82
  1909. package/dist/src/utils/swarm/spawnInProcess.js +0 -218
  1910. package/dist/src/utils/swarm/spawnUtils.js +0 -123
  1911. package/dist/src/utils/swarm/teamHelpers.js +0 -484
  1912. package/dist/src/utils/swarm/teammateInit.js +0 -87
  1913. package/dist/src/utils/swarm/teammateLayoutManager.js +0 -82
  1914. package/dist/src/utils/swarm/teammateModel.js +0 -9
  1915. package/dist/src/utils/swarm/teammatePromptAddendum.js +0 -17
  1916. package/dist/src/utils/systemDirectories.js +0 -51
  1917. package/dist/src/utils/systemPrompt.js +0 -90
  1918. package/dist/src/utils/systemPromptType.js +0 -9
  1919. package/dist/src/utils/systemTheme.js +0 -108
  1920. package/dist/src/utils/systemThemeWatcher.js +0 -16
  1921. package/dist/src/utils/taggedId.js +0 -49
  1922. package/dist/src/utils/task/TaskOutput.js +0 -320
  1923. package/dist/src/utils/task/diskOutput.js +0 -387
  1924. package/dist/src/utils/task/framework.js +0 -236
  1925. package/dist/src/utils/task/outputFormatting.js +0 -24
  1926. package/dist/src/utils/task/sdkProgress.js +0 -24
  1927. package/dist/src/utils/tasks.js +0 -672
  1928. package/dist/src/utils/teamDiscovery.js +0 -48
  1929. package/dist/src/utils/teamMemoryOps.js +0 -67
  1930. package/dist/src/utils/teammate.js +0 -237
  1931. package/dist/src/utils/teammateContext.js +0 -56
  1932. package/dist/src/utils/teammateMailbox.js +0 -793
  1933. package/dist/src/utils/telemetry/betaSessionTracing.js +0 -371
  1934. package/dist/src/utils/telemetry/bigqueryExporter.js +0 -178
  1935. package/dist/src/utils/telemetry/events.js +0 -57
  1936. package/dist/src/utils/telemetry/instrumentation.js +0 -617
  1937. package/dist/src/utils/telemetry/logger.js +0 -25
  1938. package/dist/src/utils/telemetry/perfettoTracing.js +0 -882
  1939. package/dist/src/utils/telemetry/pluginTelemetry.js +0 -157
  1940. package/dist/src/utils/telemetry/sessionTracing.js +0 -693
  1941. package/dist/src/utils/telemetry/skillLoadedEvent.js +0 -26
  1942. package/dist/src/utils/telemetryAttributes.js +0 -57
  1943. package/dist/src/utils/teleport/api.js +0 -299
  1944. package/dist/src/utils/teleport/environmentSelection.js +0 -55
  1945. package/dist/src/utils/teleport/environments.js +0 -84
  1946. package/dist/src/utils/teleport/gitBundle.js +0 -192
  1947. package/dist/src/utils/teleport.js +0 -1041
  1948. package/dist/src/utils/tempfile.js +0 -26
  1949. package/dist/src/utils/terminal.js +0 -105
  1950. package/dist/src/utils/terminalPanel.js +0 -155
  1951. package/dist/src/utils/textHighlighting.js +0 -113
  1952. package/dist/src/utils/theme.js +0 -525
  1953. package/dist/src/utils/thinking.js +0 -130
  1954. package/dist/src/utils/timeouts.js +0 -35
  1955. package/dist/src/utils/tmuxSocket.js +0 -373
  1956. package/dist/src/utils/todo/types.js +0 -9
  1957. package/dist/src/utils/tokenBudget.js +0 -62
  1958. package/dist/src/utils/tokens.js +0 -223
  1959. package/dist/src/utils/toolErrors.js +0 -101
  1960. package/dist/src/utils/toolPool.js +0 -63
  1961. package/dist/src/utils/toolResultStorage.js +0 -769
  1962. package/dist/src/utils/toolSchemaCache.js +0 -7
  1963. package/dist/src/utils/toolSearch.js +0 -551
  1964. package/dist/src/utils/transcriptSearch.js +0 -200
  1965. package/dist/src/utils/treeify.js +0 -111
  1966. package/dist/src/utils/truncate.js +0 -164
  1967. package/dist/src/utils/udsClient.js +0 -16
  1968. package/dist/src/utils/udsMessaging.js +0 -16
  1969. package/dist/src/utils/ultraplan/ccrSession.js +0 -264
  1970. package/dist/src/utils/ultraplan/keyword.js +0 -122
  1971. package/dist/src/utils/ultraplan/prompt.txt +0 -1
  1972. package/dist/src/utils/unaryLogging.js +0 -16
  1973. package/dist/src/utils/undercover.js +0 -89
  1974. package/dist/src/utils/user.js +0 -138
  1975. package/dist/src/utils/userAgent.js +0 -13
  1976. package/dist/src/utils/userPromptKeywords.js +0 -21
  1977. package/dist/src/utils/uuid.js +0 -22
  1978. package/dist/src/utils/warningHandler.js +0 -97
  1979. package/dist/src/utils/which.js +0 -75
  1980. package/dist/src/utils/windowsPaths.js +0 -146
  1981. package/dist/src/utils/withResolvers.js +0 -13
  1982. package/dist/src/utils/words.js +0 -793
  1983. package/dist/src/utils/workloadContext.js +0 -42
  1984. package/dist/src/utils/worktree.js +0 -1142
  1985. package/dist/src/utils/worktreeModeEnabled.js +0 -11
  1986. package/dist/src/utils/xdg.js +0 -52
  1987. package/dist/src/utils/xml.js +0 -15
  1988. package/dist/src/utils/yaml.js +0 -16
  1989. package/dist/src/utils/zodToJsonSchema.js +0 -19
  1990. package/dist/src/vim/motions.js +0 -73
  1991. package/dist/src/vim/operators.js +0 -401
  1992. package/dist/src/vim/textObjects.js +0 -153
  1993. package/dist/src/vim/transitions.js +0 -340
  1994. package/dist/src/vim/types.js +0 -93
  1995. package/dist/src/voice/voiceModeEnabled.js +0 -48
  1996. package/dist/src/whatsapp/bridge.js +0 -267
  1997. package/dist/src/whatsapp/config.js +0 -128
  1998. package/dist/src/whatsapp/markdown.js +0 -37
  1999. package/dist/src/whatsapp/mirror.js +0 -74
  2000. package/dist/src/whatsapp/session.js +0 -142
@@ -1,4162 +0,0 @@
1
- import { MACRO, feature } from '../recovery/bunBundleShim.js';
2
- // Sync fs primitives for readFileTailSync — separate from fs/promises
3
- // imports above. Named (not wildcard) per CLAUDE.md style; no collisions
4
- // with the async-suffixed names.
5
- import { closeSync, fstatSync, openSync, readSync } from 'fs';
6
- import { appendFile as fsAppendFile, open as fsOpen, mkdir, readdir, readFile, stat, unlink, writeFile, } from 'fs/promises';
7
- import memoize from 'lodash-es/memoize.js';
8
- import { basename, dirname, join } from 'path';
9
- import { logEvent, } from '../services/analytics/index.js';
10
- import { getOriginalCwd, getPlanSlugCache, getPromptId, getSessionId, getSessionProjectDir, isSessionPersistenceDisabled, switchSession, } from '../bootstrap/state.js';
11
- import { builtInCommandNames } from '../commands.js';
12
- import { COMMAND_NAME_TAG, TICK_TAG } from '../constants/xml.js';
13
- import { getFeatureValue_CACHED_MAY_BE_STALE } from '../services/analytics/growthbook.js';
14
- import * as sessionIngress from '../services/api/sessionIngress.js';
15
- import { REPL_TOOL_NAME } from '../tools/REPLTool/constants.js';
16
- import { asAgentId, asSessionId, } from '../types/ids.js';
17
- import { sortLogs, } from '../types/logs.js';
18
- import { uniq } from './array.js';
19
- import { registerCleanup } from './cleanupRegistry.js';
20
- import { updateSessionName } from './concurrentSessions.js';
21
- import { getCwd } from './cwd.js';
22
- import { logForDebugging } from './debug.js';
23
- import { logForDiagnosticsNoPII } from './diagLogs.js';
24
- import { getClaudeConfigHomeDir, isEnvTruthy } from './envUtils.js';
25
- import { isFsInaccessible } from './errors.js';
26
- import { formatFileSize } from './format.js';
27
- import { getFsImplementation } from './fsOperations.js';
28
- import { getWorktreePaths } from './getWorktreePaths.js';
29
- import { getBranch } from './git.js';
30
- import { gracefulShutdownSync, isShuttingDown } from './gracefulShutdown.js';
31
- import { parseJSONL } from './json.js';
32
- import { logError } from './log.js';
33
- import { extractTag, isCompactBoundaryMessage } from './messages.js';
34
- import { sanitizePath } from './path.js';
35
- import { extractJsonStringField, extractLastJsonStringField, LITE_READ_BUF_SIZE, readHeadAndTail, readTranscriptForLoad, SKIP_PRECOMPACT_THRESHOLD, } from './sessionStoragePortable.js';
36
- import { getSettings_DEPRECATED } from './settings/settings.js';
37
- import { jsonParse, jsonStringify } from './slowOperations.js';
38
- import { validateUuid } from './uuid.js';
39
- // Cache MACRO.VERSION at module level to work around bun --define bug in async contexts
40
- // See: https://github.com/oven-sh/bun/issues/26168
41
- const VERSION = typeof MACRO !== 'undefined' ? MACRO.VERSION : 'unknown';
42
- // Use getOriginalCwd() at each call site instead of capturing at module load
43
- // time. getCwd() at import time may run before bootstrap resolves symlinks via
44
- // realpathSync, causing a different sanitized project directory than what
45
- // getOriginalCwd() returns after bootstrap. This split-brain made sessions
46
- // saved under one path invisible when loaded via the other.
47
- /**
48
- * Pre-compiled regex to skip non-meaningful messages when extracting first prompt.
49
- * Matches anything starting with a lowercase XML-like tag (IDE context, hook
50
- * output, task notifications, channel messages, etc.) or a synthetic interrupt
51
- * marker. Kept in sync with sessionStoragePortable.ts — generic pattern avoids
52
- * an ever-growing allowlist that falls behind as new notification types ship.
53
- */
54
- // 50MB — prevents OOM in the tombstone slow path which reads + rewrites the
55
- // entire session file. Session files can grow to multiple GB (inc-3930).
56
- const MAX_TOMBSTONE_REWRITE_BYTES = 50 * 1024 * 1024;
57
- const SKIP_FIRST_PROMPT_PATTERN = /^(?:\s*<[a-z][\w-]*[\s>]|\[Request interrupted by user[^\]]*\])/;
58
- /**
59
- * Type guard to check if an entry is a transcript message.
60
- * Transcript messages include user, assistant, attachment, and system messages.
61
- * IMPORTANT: This is the single source of truth for what constitutes a transcript message.
62
- * loadTranscriptFile() uses this to determine which messages to load into the chain.
63
- *
64
- * Progress messages are NOT transcript messages. They are ephemeral UI state
65
- * and must not be persisted to the JSONL or participate in the parentUuid
66
- * chain. Including them caused chain forks that orphaned real conversation
67
- * messages on resume (see #14373, #23537).
68
- */
69
- export function isTranscriptMessage(entry) {
70
- return (entry.type === 'user' ||
71
- entry.type === 'assistant' ||
72
- entry.type === 'attachment' ||
73
- entry.type === 'system');
74
- }
75
- /**
76
- * Entries that participate in the parentUuid chain. Used on the write path
77
- * (insertMessageChain, useLogMessages) to skip progress when assigning
78
- * parentUuid. Old transcripts with progress already in the chain are handled
79
- * by the progressBridge rewrite in loadTranscriptFile.
80
- */
81
- export function isChainParticipant(m) {
82
- return m.type !== 'progress';
83
- }
84
- /**
85
- * Progress entries in transcripts written before PR #24099. They are not
86
- * in the Entry type union anymore but still exist on disk with uuid and
87
- * parentUuid fields. loadTranscriptFile bridges the chain across them.
88
- */
89
- function isLegacyProgressEntry(entry) {
90
- return (typeof entry === 'object' &&
91
- entry !== null &&
92
- 'type' in entry &&
93
- entry.type === 'progress' &&
94
- 'uuid' in entry &&
95
- typeof entry.uuid === 'string');
96
- }
97
- /**
98
- * High-frequency tool progress ticks (1/sec for Sleep, per-chunk for Bash).
99
- * These are UI-only: not sent to the API, not rendered after the tool
100
- * completes. Used by REPL.tsx to replace-in-place instead of appending, and
101
- * by loadTranscriptFile to skip legacy entries from old transcripts.
102
- */
103
- const EPHEMERAL_PROGRESS_TYPES = new Set([
104
- 'bash_progress',
105
- 'powershell_progress',
106
- 'mcp_progress',
107
- ...(feature('PROACTIVE') || feature('KAIROS')
108
- ? ['sleep_progress']
109
- : []),
110
- ]);
111
- export function isEphemeralToolProgress(dataType) {
112
- return typeof dataType === 'string' && EPHEMERAL_PROGRESS_TYPES.has(dataType);
113
- }
114
- export function getProjectsDir() {
115
- return join(getClaudeConfigHomeDir(), 'projects');
116
- }
117
- export function getTranscriptPath() {
118
- const projectDir = getSessionProjectDir() ?? getProjectDir(getOriginalCwd());
119
- return join(projectDir, `${getSessionId()}.jsonl`);
120
- }
121
- export function getTranscriptPathForSession(sessionId) {
122
- // When asking for the CURRENT session's transcript, honor sessionProjectDir
123
- // the same way getTranscriptPath() does. Without this, hooks get a
124
- // transcript_path computed from originalCwd while the actual file was
125
- // written to sessionProjectDir (set by switchActiveSession on resume/branch)
126
- // — different directories, so the hook sees MISSING (gh-30217). CC-34
127
- // made sessionId + sessionProjectDir atomic precisely to prevent this
128
- // kind of drift; this function just wasn't updated to read both.
129
- //
130
- // For OTHER session IDs we can only guess via originalCwd — we don't
131
- // track a sessionId→projectDir map. Callers wanting a specific other
132
- // session's path should pass fullPath explicitly (most save* functions
133
- // already accept this).
134
- if (sessionId === getSessionId()) {
135
- return getTranscriptPath();
136
- }
137
- const projectDir = getProjectDir(getOriginalCwd());
138
- return join(projectDir, `${sessionId}.jsonl`);
139
- }
140
- // 50 MB — session JSONL can grow to multiple GB (inc-3930). Callers that
141
- // read the raw transcript must bail out above this threshold to avoid OOM.
142
- export const MAX_TRANSCRIPT_READ_BYTES = 50 * 1024 * 1024;
143
- // In-memory map of agentId → subdirectory for grouping related subagent
144
- // transcripts (e.g. workflow runs write to subagents/workflows/<runId>/).
145
- // Populated before the agent runs; consulted by getAgentTranscriptPath.
146
- const agentTranscriptSubdirs = new Map();
147
- export function setAgentTranscriptSubdir(agentId, subdir) {
148
- agentTranscriptSubdirs.set(agentId, subdir);
149
- }
150
- export function clearAgentTranscriptSubdir(agentId) {
151
- agentTranscriptSubdirs.delete(agentId);
152
- }
153
- export function getAgentTranscriptPath(agentId) {
154
- // Same sessionProjectDir consistency as getTranscriptPathForSession —
155
- // subagent transcripts live under the session dir, so if the session
156
- // transcript is at sessionProjectDir, subagent transcripts are too.
157
- const projectDir = getSessionProjectDir() ?? getProjectDir(getOriginalCwd());
158
- const sessionId = getSessionId();
159
- const subdir = agentTranscriptSubdirs.get(agentId);
160
- const base = subdir
161
- ? join(projectDir, sessionId, 'subagents', subdir)
162
- : join(projectDir, sessionId, 'subagents');
163
- return join(base, `agent-${agentId}.jsonl`);
164
- }
165
- function getAgentMetadataPath(agentId) {
166
- return getAgentTranscriptPath(agentId).replace(/\.jsonl$/, '.meta.json');
167
- }
168
- /**
169
- * Persist the agentType used to launch a subagent. Read by resume to
170
- * route correctly when subagent_type is omitted — without this, resuming
171
- * a fork silently degrades to general-purpose (4KB system prompt, no
172
- * inherited history). Sidecar file avoids JSONL schema changes.
173
- *
174
- * Also stores the worktreePath when the agent was spawned with worktree
175
- * isolation, enabling resume to restore the correct cwd.
176
- */
177
- export async function writeAgentMetadata(agentId, metadata) {
178
- const path = getAgentMetadataPath(agentId);
179
- await mkdir(dirname(path), { recursive: true });
180
- await writeFile(path, JSON.stringify(metadata));
181
- }
182
- export async function readAgentMetadata(agentId) {
183
- const path = getAgentMetadataPath(agentId);
184
- try {
185
- const raw = await readFile(path, 'utf-8');
186
- return JSON.parse(raw);
187
- }
188
- catch (e) {
189
- if (isFsInaccessible(e))
190
- return null;
191
- throw e;
192
- }
193
- }
194
- function getRemoteAgentsDir() {
195
- // Same sessionProjectDir fallback as getAgentTranscriptPath — the project
196
- // dir (containing the .jsonl), not the session dir, so sessionId is joined.
197
- const projectDir = getSessionProjectDir() ?? getProjectDir(getOriginalCwd());
198
- return join(projectDir, getSessionId(), 'remote-agents');
199
- }
200
- function getRemoteAgentMetadataPath(taskId) {
201
- return join(getRemoteAgentsDir(), `remote-agent-${taskId}.meta.json`);
202
- }
203
- /**
204
- * Persist metadata for a remote-agent task so it can be restored on session
205
- * resume. Per-task sidecar file (sibling dir to subagents/) survives
206
- * hydrateSessionFromRemote's .jsonl wipe; status is always fetched fresh
207
- * from CCR on restore — only identity is persisted locally.
208
- */
209
- export async function writeRemoteAgentMetadata(taskId, metadata) {
210
- const path = getRemoteAgentMetadataPath(taskId);
211
- await mkdir(dirname(path), { recursive: true });
212
- await writeFile(path, JSON.stringify(metadata));
213
- }
214
- export async function readRemoteAgentMetadata(taskId) {
215
- const path = getRemoteAgentMetadataPath(taskId);
216
- try {
217
- const raw = await readFile(path, 'utf-8');
218
- return JSON.parse(raw);
219
- }
220
- catch (e) {
221
- if (isFsInaccessible(e))
222
- return null;
223
- throw e;
224
- }
225
- }
226
- export async function deleteRemoteAgentMetadata(taskId) {
227
- const path = getRemoteAgentMetadataPath(taskId);
228
- try {
229
- await unlink(path);
230
- }
231
- catch (e) {
232
- if (isFsInaccessible(e))
233
- return;
234
- throw e;
235
- }
236
- }
237
- /**
238
- * Scan the remote-agents/ directory for all persisted metadata files.
239
- * Used by restoreRemoteAgentTasks to reconnect to still-running CCR sessions.
240
- */
241
- export async function listRemoteAgentMetadata() {
242
- const dir = getRemoteAgentsDir();
243
- let entries;
244
- try {
245
- entries = await readdir(dir, { withFileTypes: true });
246
- }
247
- catch (e) {
248
- if (isFsInaccessible(e))
249
- return [];
250
- throw e;
251
- }
252
- const results = [];
253
- for (const entry of entries) {
254
- if (!entry.isFile() || !entry.name.endsWith('.meta.json'))
255
- continue;
256
- try {
257
- const raw = await readFile(join(dir, entry.name), 'utf-8');
258
- results.push(JSON.parse(raw));
259
- }
260
- catch (e) {
261
- // Skip unreadable or corrupt files — a partial write from a crashed
262
- // fire-and-forget persist shouldn't take down the whole restore.
263
- logForDebugging(`listRemoteAgentMetadata: skipping ${entry.name}: ${String(e)}`);
264
- }
265
- }
266
- return results;
267
- }
268
- export function sessionIdExists(sessionId) {
269
- const projectDir = getProjectDir(getOriginalCwd());
270
- const sessionFile = join(projectDir, `${sessionId}.jsonl`);
271
- const fs = getFsImplementation();
272
- try {
273
- fs.statSync(sessionFile);
274
- return true;
275
- }
276
- catch {
277
- return false;
278
- }
279
- }
280
- // exported for testing
281
- export function getNodeEnv() {
282
- return process.env.NODE_ENV || 'development';
283
- }
284
- // exported for testing
285
- export function getUserType() {
286
- return process.env.USER_TYPE || 'external';
287
- }
288
- function getEntrypoint() {
289
- return process.env.CLAUDE_CODE_ENTRYPOINT;
290
- }
291
- export function isCustomTitleEnabled() {
292
- return true;
293
- }
294
- // Memoized: called 12+ times per turn via hooks.ts createBaseHookInput
295
- // (PostToolUse path, 5×/turn) + various save* functions. Input is a cwd
296
- // string; homedir/env/regex are all session-invariant so the result is
297
- // stable for a given input. Worktree switches just change the key — no
298
- // cache clear needed.
299
- export const getProjectDir = memoize((projectDir) => {
300
- return join(getProjectsDir(), sanitizePath(projectDir));
301
- });
302
- let project = null;
303
- let cleanupRegistered = false;
304
- function getProject() {
305
- if (!project) {
306
- project = new Project();
307
- // Register flush as a cleanup handler (only once)
308
- if (!cleanupRegistered) {
309
- registerCleanup(async () => {
310
- // Flush queued writes first, then re-append session metadata
311
- // (customTitle, tag) so they always appear in the last 64KB tail
312
- // window. readLiteMetadata only reads the tail to extract these
313
- // fields — if enough messages are appended after a /rename, the
314
- // custom-title entry gets pushed outside the window and --resume
315
- // shows the auto-generated firstPrompt instead.
316
- await project?.flush();
317
- try {
318
- project?.reAppendSessionMetadata();
319
- }
320
- catch {
321
- // Best-effort — don't let metadata re-append crash the cleanup
322
- }
323
- });
324
- cleanupRegistered = true;
325
- }
326
- }
327
- return project;
328
- }
329
- /**
330
- * Reset the Project singleton's flush state for testing.
331
- * This ensures tests don't interfere with each other via shared counter state.
332
- */
333
- export function resetProjectFlushStateForTesting() {
334
- project?._resetFlushState();
335
- }
336
- /**
337
- * Reset the entire Project singleton for testing.
338
- * This ensures tests with different CLAUDE_CONFIG_DIR values
339
- * don't share stale sessionFile paths.
340
- */
341
- export function resetProjectForTesting() {
342
- project = null;
343
- }
344
- export function setSessionFileForTesting(path) {
345
- getProject().sessionFile = path;
346
- }
347
- /**
348
- * Register a CCR v2 internal event writer for transcript persistence.
349
- * When set, transcript messages are written as internal worker events
350
- * instead of going through v1 Session Ingress.
351
- */
352
- export function setInternalEventWriter(writer) {
353
- getProject().setInternalEventWriter(writer);
354
- }
355
- /**
356
- * Register a CCR v2 internal event reader for session resume.
357
- * When set, hydrateFromCCRv2InternalEvents() can fetch foreground and
358
- * subagent internal events to reconstruct conversation state on reconnection.
359
- */
360
- export function setInternalEventReader(reader, subagentReader) {
361
- getProject().setInternalEventReader(reader);
362
- getProject().setInternalSubagentEventReader(subagentReader);
363
- }
364
- /**
365
- * Set the remote ingress URL on the current Project for testing.
366
- * This simulates what hydrateRemoteSession does in production.
367
- */
368
- export function setRemoteIngressUrlForTesting(url) {
369
- getProject().setRemoteIngressUrl(url);
370
- }
371
- const REMOTE_FLUSH_INTERVAL_MS = 10;
372
- class Project {
373
- // Minimal cache for current session only (not all sessions)
374
- currentSessionTag;
375
- currentSessionTitle;
376
- currentSessionAgentName;
377
- currentSessionAgentColor;
378
- currentSessionLastPrompt;
379
- currentSessionAgentSetting;
380
- currentSessionMode;
381
- // Tri-state: undefined = never touched (don't write), null = exited worktree,
382
- // object = currently in worktree. reAppendSessionMetadata writes null so
383
- // --resume knows the session exited (vs. crashed while inside).
384
- currentSessionWorktree;
385
- currentSessionPrNumber;
386
- currentSessionPrUrl;
387
- currentSessionPrRepository;
388
- sessionFile = null;
389
- // Entries buffered while sessionFile is null. Flushed by materializeSessionFile
390
- // on the first user/assistant message — prevents metadata-only session files.
391
- pendingEntries = [];
392
- remoteIngressUrl = null;
393
- internalEventWriter = null;
394
- internalEventReader = null;
395
- internalSubagentEventReader = null;
396
- pendingWriteCount = 0;
397
- flushResolvers = [];
398
- // Per-file write queues. Each entry carries a resolve callback so
399
- // callers of enqueueWrite can optionally await their specific write.
400
- writeQueues = new Map();
401
- flushTimer = null;
402
- activeDrain = null;
403
- FLUSH_INTERVAL_MS = 100;
404
- MAX_CHUNK_BYTES = 100 * 1024 * 1024;
405
- constructor() { }
406
- /** @internal Reset flush/queue state for testing. */
407
- _resetFlushState() {
408
- this.pendingWriteCount = 0;
409
- this.flushResolvers = [];
410
- if (this.flushTimer)
411
- clearTimeout(this.flushTimer);
412
- this.flushTimer = null;
413
- this.activeDrain = null;
414
- this.writeQueues = new Map();
415
- }
416
- incrementPendingWrites() {
417
- this.pendingWriteCount++;
418
- }
419
- decrementPendingWrites() {
420
- this.pendingWriteCount--;
421
- if (this.pendingWriteCount === 0) {
422
- // Resolve all waiting flush promises
423
- for (const resolve of this.flushResolvers) {
424
- resolve();
425
- }
426
- this.flushResolvers = [];
427
- }
428
- }
429
- async trackWrite(fn) {
430
- this.incrementPendingWrites();
431
- try {
432
- return await fn();
433
- }
434
- finally {
435
- this.decrementPendingWrites();
436
- }
437
- }
438
- enqueueWrite(filePath, entry) {
439
- return new Promise(resolve => {
440
- let queue = this.writeQueues.get(filePath);
441
- if (!queue) {
442
- queue = [];
443
- this.writeQueues.set(filePath, queue);
444
- }
445
- queue.push({ entry, resolve });
446
- this.scheduleDrain();
447
- });
448
- }
449
- scheduleDrain() {
450
- if (this.flushTimer) {
451
- return;
452
- }
453
- this.flushTimer = setTimeout(async () => {
454
- this.flushTimer = null;
455
- this.activeDrain = this.drainWriteQueue();
456
- await this.activeDrain;
457
- this.activeDrain = null;
458
- // If more items arrived during drain, schedule again
459
- if (this.writeQueues.size > 0) {
460
- this.scheduleDrain();
461
- }
462
- }, this.FLUSH_INTERVAL_MS);
463
- }
464
- async appendToFile(filePath, data) {
465
- try {
466
- await fsAppendFile(filePath, data, { mode: 0o600 });
467
- }
468
- catch {
469
- // Directory may not exist — some NFS-like filesystems return
470
- // unexpected error codes, so don't discriminate on code.
471
- await mkdir(dirname(filePath), { recursive: true, mode: 0o700 });
472
- await fsAppendFile(filePath, data, { mode: 0o600 });
473
- }
474
- }
475
- async drainWriteQueue() {
476
- for (const [filePath, queue] of this.writeQueues) {
477
- if (queue.length === 0) {
478
- continue;
479
- }
480
- const batch = queue.splice(0);
481
- let content = '';
482
- const resolvers = [];
483
- for (const { entry, resolve } of batch) {
484
- const line = jsonStringify(entry) + '\n';
485
- if (content.length + line.length >= this.MAX_CHUNK_BYTES) {
486
- // Flush chunk and resolve its entries before starting a new one
487
- await this.appendToFile(filePath, content);
488
- for (const r of resolvers) {
489
- r();
490
- }
491
- resolvers.length = 0;
492
- content = '';
493
- }
494
- content += line;
495
- resolvers.push(resolve);
496
- }
497
- if (content.length > 0) {
498
- await this.appendToFile(filePath, content);
499
- for (const r of resolvers) {
500
- r();
501
- }
502
- }
503
- }
504
- // Clean up empty queues
505
- for (const [filePath, queue] of this.writeQueues) {
506
- if (queue.length === 0) {
507
- this.writeQueues.delete(filePath);
508
- }
509
- }
510
- }
511
- resetSessionFile() {
512
- this.sessionFile = null;
513
- this.pendingEntries = [];
514
- }
515
- /**
516
- * Re-append cached session metadata to the end of the transcript file.
517
- * This ensures metadata stays within the tail window that readLiteMetadata
518
- * reads during progressive loading.
519
- *
520
- * Called from two contexts with different file-ordering implications:
521
- * - During compaction (compact.ts, reactiveCompact.ts): writes metadata
522
- * just before the boundary marker is emitted - these entries end up
523
- * before the boundary and are recovered by scanPreBoundaryMetadata.
524
- * - On session exit (cleanup handler): writes metadata at EOF after all
525
- * boundaries - this is what enables loadTranscriptFile's pre-compact
526
- * skip to find metadata without a forward scan.
527
- *
528
- * External-writer safety for SDK-mutable fields (custom-title, tag):
529
- * before re-appending, refresh the cache from the tail scan window. If an
530
- * external process (SDK renameSession/tagSession) wrote a fresher value,
531
- * our stale cache absorbs it and the re-append below persists it — not
532
- * the stale CLI value. If no entry is in the tail (evicted, or never
533
- * written by the SDK), the cache is the only source of truth and is
534
- * re-appended as-is.
535
- *
536
- * Re-append is unconditional (even when the value is already in the
537
- * tail): during compaction, a title 40KB from EOF is inside the current
538
- * tail window but will fall out once the post-compaction session grows.
539
- * Skipping the re-append would defeat the purpose of this call. Fields
540
- * the SDK cannot touch (last-prompt, agent-*, mode, pr-link) have no
541
- * external-writer concern — their caches are authoritative.
542
- */
543
- reAppendSessionMetadata(skipTitleRefresh = false) {
544
- if (!this.sessionFile)
545
- return;
546
- const sessionId = getSessionId();
547
- if (!sessionId)
548
- return;
549
- // One sync tail read to refresh SDK-mutable fields. Same
550
- // LITE_READ_BUF_SIZE window readLiteMetadata uses. Empty string on
551
- // failure → extract returns null → cache is the only source of truth.
552
- const tail = readFileTailSync(this.sessionFile);
553
- // Absorb any fresher SDK-written title/tag into our cache. If the SDK
554
- // wrote while we had the session open, our cache is stale — the tail
555
- // value is authoritative. If the tail has nothing (evicted or never
556
- // written externally), the cache stands.
557
- //
558
- // Filter with startsWith to match only top-level JSONL entries (col 0)
559
- // and not "type":"tag" appearing inside a nested tool_use input that
560
- // happens to be JSON-serialized into a message.
561
- const tailLines = tail.split('\n');
562
- if (!skipTitleRefresh) {
563
- const titleLine = tailLines.findLast(l => l.startsWith('{"type":"custom-title"'));
564
- if (titleLine) {
565
- const tailTitle = extractLastJsonStringField(titleLine, 'customTitle');
566
- // `!== undefined` distinguishes no-match from empty-string match.
567
- // renameSession rejects empty titles, but the CLI is defensive: an
568
- // external writer with customTitle:"" should clear the cache so the
569
- // re-append below skips it (instead of resurrecting a stale title).
570
- if (tailTitle !== undefined) {
571
- this.currentSessionTitle = tailTitle || undefined;
572
- }
573
- }
574
- }
575
- const tagLine = tailLines.findLast(l => l.startsWith('{"type":"tag"'));
576
- if (tagLine) {
577
- const tailTag = extractLastJsonStringField(tagLine, 'tag');
578
- // Same: tagSession(id, null) writes `tag:""` to clear.
579
- if (tailTag !== undefined) {
580
- this.currentSessionTag = tailTag || undefined;
581
- }
582
- }
583
- // lastPrompt is re-appended so readLiteMetadata can show what the
584
- // user was most recently doing. Written first so customTitle/tag/etc
585
- // land closer to EOF (they're the more critical fields for tail reads).
586
- if (this.currentSessionLastPrompt) {
587
- appendEntryToFile(this.sessionFile, {
588
- type: 'last-prompt',
589
- lastPrompt: this.currentSessionLastPrompt,
590
- sessionId,
591
- });
592
- }
593
- // Unconditional: cache was refreshed from tail above; re-append keeps
594
- // the entry at EOF so compaction-pushed content doesn't evict it.
595
- if (this.currentSessionTitle) {
596
- appendEntryToFile(this.sessionFile, {
597
- type: 'custom-title',
598
- customTitle: this.currentSessionTitle,
599
- sessionId,
600
- });
601
- }
602
- if (this.currentSessionTag) {
603
- appendEntryToFile(this.sessionFile, {
604
- type: 'tag',
605
- tag: this.currentSessionTag,
606
- sessionId,
607
- });
608
- }
609
- if (this.currentSessionAgentName) {
610
- appendEntryToFile(this.sessionFile, {
611
- type: 'agent-name',
612
- agentName: this.currentSessionAgentName,
613
- sessionId,
614
- });
615
- }
616
- if (this.currentSessionAgentColor) {
617
- appendEntryToFile(this.sessionFile, {
618
- type: 'agent-color',
619
- agentColor: this.currentSessionAgentColor,
620
- sessionId,
621
- });
622
- }
623
- if (this.currentSessionAgentSetting) {
624
- appendEntryToFile(this.sessionFile, {
625
- type: 'agent-setting',
626
- agentSetting: this.currentSessionAgentSetting,
627
- sessionId,
628
- });
629
- }
630
- if (this.currentSessionMode) {
631
- appendEntryToFile(this.sessionFile, {
632
- type: 'mode',
633
- mode: this.currentSessionMode,
634
- sessionId,
635
- });
636
- }
637
- if (this.currentSessionWorktree !== undefined) {
638
- appendEntryToFile(this.sessionFile, {
639
- type: 'worktree-state',
640
- worktreeSession: this.currentSessionWorktree,
641
- sessionId,
642
- });
643
- }
644
- if (this.currentSessionPrNumber !== undefined &&
645
- this.currentSessionPrUrl &&
646
- this.currentSessionPrRepository) {
647
- appendEntryToFile(this.sessionFile, {
648
- type: 'pr-link',
649
- sessionId,
650
- prNumber: this.currentSessionPrNumber,
651
- prUrl: this.currentSessionPrUrl,
652
- prRepository: this.currentSessionPrRepository,
653
- timestamp: new Date().toISOString(),
654
- });
655
- }
656
- }
657
- async flush() {
658
- // Cancel pending timer
659
- if (this.flushTimer) {
660
- clearTimeout(this.flushTimer);
661
- this.flushTimer = null;
662
- }
663
- // Wait for any in-flight drain to finish
664
- if (this.activeDrain) {
665
- await this.activeDrain;
666
- }
667
- // Drain anything remaining in the queues
668
- await this.drainWriteQueue();
669
- // Wait for non-queue tracked operations (e.g. removeMessageByUuid)
670
- if (this.pendingWriteCount === 0) {
671
- return;
672
- }
673
- return new Promise(resolve => {
674
- this.flushResolvers.push(resolve);
675
- });
676
- }
677
- /**
678
- * Remove a message from the transcript by UUID.
679
- * Used for tombstoning orphaned messages from failed streaming attempts.
680
- *
681
- * The target is almost always the most recently appended entry, so we
682
- * read only the tail, locate the line, and splice it out with a
683
- * positional write + truncate instead of rewriting the whole file.
684
- */
685
- async removeMessageByUuid(targetUuid) {
686
- return this.trackWrite(async () => {
687
- if (this.sessionFile === null)
688
- return;
689
- try {
690
- let fileSize = 0;
691
- const fh = await fsOpen(this.sessionFile, 'r+');
692
- try {
693
- const { size } = await fh.stat();
694
- fileSize = size;
695
- if (size === 0)
696
- return;
697
- const chunkLen = Math.min(size, LITE_READ_BUF_SIZE);
698
- const tailStart = size - chunkLen;
699
- const buf = Buffer.allocUnsafe(chunkLen);
700
- const { bytesRead } = await fh.read(buf, 0, chunkLen, tailStart);
701
- const tail = buf.subarray(0, bytesRead);
702
- // Entries are serialized via JSON.stringify (no key-value
703
- // whitespace). Search for the full `"uuid":"..."` pattern, not
704
- // just the bare UUID, so we do not match the same value sitting
705
- // in `parentUuid` of a child entry. UUIDs are pure ASCII so a
706
- // byte-level search is correct.
707
- const needle = `"uuid":"${targetUuid}"`;
708
- const matchIdx = tail.lastIndexOf(needle);
709
- if (matchIdx >= 0) {
710
- // 0x0a never appears inside a UTF-8 multi-byte sequence, so
711
- // byte-scanning for line boundaries is safe even if the chunk
712
- // starts mid-character.
713
- const prevNl = tail.lastIndexOf(0x0a, matchIdx);
714
- // If the preceding newline is outside our chunk and we did not
715
- // read from the start of the file, the line is longer than the
716
- // window - fall through to the slow path.
717
- if (prevNl >= 0 || tailStart === 0) {
718
- const lineStart = prevNl + 1; // 0 when prevNl === -1
719
- const nextNl = tail.indexOf(0x0a, matchIdx + needle.length);
720
- const lineEnd = nextNl >= 0 ? nextNl + 1 : bytesRead;
721
- const absLineStart = tailStart + lineStart;
722
- const afterLen = bytesRead - lineEnd;
723
- // Truncate first, then re-append the trailing lines. In the
724
- // common case (target is the last entry) afterLen is 0 and
725
- // this is a single ftruncate.
726
- await fh.truncate(absLineStart);
727
- if (afterLen > 0) {
728
- await fh.write(tail, lineEnd, afterLen, absLineStart);
729
- }
730
- return;
731
- }
732
- }
733
- }
734
- finally {
735
- await fh.close();
736
- }
737
- // Slow path: target was not in the last 64KB. Rare - requires many
738
- // large entries to have landed between the write and the tombstone.
739
- if (fileSize > MAX_TOMBSTONE_REWRITE_BYTES) {
740
- logForDebugging(`Skipping tombstone removal: session file too large (${formatFileSize(fileSize)})`, { level: 'warn' });
741
- return;
742
- }
743
- const content = await readFile(this.sessionFile, { encoding: 'utf-8' });
744
- const lines = content.split('\n').filter((line) => {
745
- if (!line.trim())
746
- return true;
747
- try {
748
- const entry = jsonParse(line);
749
- return entry.uuid !== targetUuid;
750
- }
751
- catch {
752
- return true; // Keep malformed lines
753
- }
754
- });
755
- await writeFile(this.sessionFile, lines.join('\n'), {
756
- encoding: 'utf8',
757
- });
758
- }
759
- catch {
760
- // Silently ignore errors - the file might not exist yet
761
- }
762
- });
763
- }
764
- /**
765
- * True when test env / cleanupPeriodDays=0 / --no-session-persistence /
766
- * CLAUDE_CODE_SKIP_PROMPT_HISTORY should suppress all transcript writes.
767
- * Shared guard for appendEntry and materializeSessionFile so both skip
768
- * consistently. The env var is set by tmuxSocket.ts so Tungsten-spawned
769
- * test sessions don't pollute the user's --resume list.
770
- */
771
- shouldSkipPersistence() {
772
- const allowTestPersistence = isEnvTruthy(process.env.TEST_ENABLE_SESSION_PERSISTENCE);
773
- return ((getNodeEnv() === 'test' && !allowTestPersistence) ||
774
- getSettings_DEPRECATED()?.cleanupPeriodDays === 0 ||
775
- isSessionPersistenceDisabled() ||
776
- isEnvTruthy(process.env.CLAUDE_CODE_SKIP_PROMPT_HISTORY));
777
- }
778
- /**
779
- * Create the session file, write cached startup metadata, and flush
780
- * buffered entries. Called on the first user/assistant message.
781
- */
782
- async materializeSessionFile() {
783
- // Guard here too — reAppendSessionMetadata writes via appendEntryToFile
784
- // (not appendEntry) so it would bypass the per-entry persistence check
785
- // and create a metadata-only file despite --no-session-persistence.
786
- if (this.shouldSkipPersistence())
787
- return;
788
- this.ensureCurrentSessionFile();
789
- // mode/agentSetting are cache-only pre-materialization; write them now.
790
- this.reAppendSessionMetadata();
791
- if (this.pendingEntries.length > 0) {
792
- const buffered = this.pendingEntries;
793
- this.pendingEntries = [];
794
- for (const entry of buffered) {
795
- await this.appendEntry(entry);
796
- }
797
- }
798
- }
799
- async insertMessageChain(messages, isSidechain = false, agentId, startingParentUuid, teamInfo) {
800
- return this.trackWrite(async () => {
801
- let parentUuid = startingParentUuid ?? null;
802
- // First user/assistant message materializes the session file.
803
- // Hook progress/attachment messages alone stay buffered.
804
- if (this.sessionFile === null &&
805
- messages.some(m => m.type === 'user' || m.type === 'assistant')) {
806
- await this.materializeSessionFile();
807
- }
808
- // Get current git branch once for this message chain
809
- let gitBranch;
810
- try {
811
- gitBranch = await getBranch();
812
- }
813
- catch {
814
- // Not in a git repo or git command failed
815
- gitBranch = undefined;
816
- }
817
- // Get slug if one exists for this session (used for plan files, etc.)
818
- const sessionId = getSessionId();
819
- const slug = getPlanSlugCache().get(sessionId);
820
- for (const message of messages) {
821
- const isCompactBoundary = isCompactBoundaryMessage(message);
822
- // For tool_result messages, use the assistant message UUID from the message
823
- // if available (set at creation time), otherwise fall back to sequential parent
824
- let effectiveParentUuid = parentUuid;
825
- if (message.type === 'user' &&
826
- 'sourceToolAssistantUUID' in message &&
827
- message.sourceToolAssistantUUID) {
828
- effectiveParentUuid = message.sourceToolAssistantUUID;
829
- }
830
- const transcriptMessage = {
831
- parentUuid: isCompactBoundary ? null : effectiveParentUuid,
832
- logicalParentUuid: isCompactBoundary ? parentUuid : undefined,
833
- isSidechain,
834
- teamName: teamInfo?.teamName,
835
- agentName: teamInfo?.agentName,
836
- promptId: message.type === 'user' ? (getPromptId() ?? undefined) : undefined,
837
- agentId,
838
- ...message,
839
- // Session-stamp fields MUST come after the spread. On --fork-session
840
- // and --resume, messages arrive as SerializedMessage (carries source
841
- // sessionId/cwd/etc. because removeExtraFields only strips parentUuid
842
- // and isSidechain). If sessionId isn't re-stamped, FRESH.jsonl ends up
843
- // with messages stamped sessionId=A but content-replacement entries
844
- // stamped sessionId=FRESH (from insertContentReplacement), and
845
- // loadFullLog's sessionId-keyed contentReplacements lookup misses →
846
- // replacement records lost → FROZEN misclassification.
847
- userType: getUserType(),
848
- entrypoint: getEntrypoint(),
849
- cwd: getCwd(),
850
- sessionId,
851
- version: VERSION,
852
- gitBranch,
853
- slug,
854
- };
855
- await this.appendEntry(transcriptMessage);
856
- if (isChainParticipant(message)) {
857
- parentUuid = message.uuid;
858
- }
859
- }
860
- // Cache this turn's user prompt for reAppendSessionMetadata —
861
- // the --resume picker shows what the user was last doing.
862
- // Overwritten every turn by design.
863
- if (!isSidechain) {
864
- const text = getFirstMeaningfulUserMessageTextContent(messages);
865
- if (text) {
866
- const flat = text.replace(/\n/g, ' ').trim();
867
- this.currentSessionLastPrompt =
868
- flat.length > 200 ? flat.slice(0, 200).trim() + '…' : flat;
869
- }
870
- }
871
- });
872
- }
873
- async insertFileHistorySnapshot(messageId, snapshot, isSnapshotUpdate) {
874
- return this.trackWrite(async () => {
875
- const fileHistoryMessage = {
876
- type: 'file-history-snapshot',
877
- messageId,
878
- snapshot,
879
- isSnapshotUpdate,
880
- };
881
- await this.appendEntry(fileHistoryMessage);
882
- });
883
- }
884
- async insertQueueOperation(queueOp) {
885
- return this.trackWrite(async () => {
886
- await this.appendEntry(queueOp);
887
- });
888
- }
889
- async insertAttributionSnapshot(snapshot) {
890
- return this.trackWrite(async () => {
891
- await this.appendEntry(snapshot);
892
- });
893
- }
894
- async insertContentReplacement(replacements, agentId) {
895
- return this.trackWrite(async () => {
896
- const entry = {
897
- type: 'content-replacement',
898
- sessionId: getSessionId(),
899
- agentId,
900
- replacements,
901
- };
902
- await this.appendEntry(entry);
903
- });
904
- }
905
- async appendEntry(entry, sessionId = getSessionId()) {
906
- if (this.shouldSkipPersistence()) {
907
- return;
908
- }
909
- const currentSessionId = getSessionId();
910
- const isCurrentSession = sessionId === currentSessionId;
911
- let sessionFile;
912
- if (isCurrentSession) {
913
- // Buffer until materializeSessionFile runs (first user/assistant message).
914
- if (this.sessionFile === null) {
915
- this.pendingEntries.push(entry);
916
- return;
917
- }
918
- sessionFile = this.sessionFile;
919
- }
920
- else {
921
- const existing = await this.getExistingSessionFile(sessionId);
922
- if (!existing) {
923
- logError(new Error(`appendEntry: session file not found for other session ${sessionId}`));
924
- return;
925
- }
926
- sessionFile = existing;
927
- }
928
- // Only load current session messages if needed
929
- if (entry.type === 'summary') {
930
- // Summaries can always be appended
931
- void this.enqueueWrite(sessionFile, entry);
932
- }
933
- else if (entry.type === 'custom-title') {
934
- // Custom titles can always be appended
935
- void this.enqueueWrite(sessionFile, entry);
936
- }
937
- else if (entry.type === 'ai-title') {
938
- // AI titles can always be appended
939
- void this.enqueueWrite(sessionFile, entry);
940
- }
941
- else if (entry.type === 'last-prompt') {
942
- void this.enqueueWrite(sessionFile, entry);
943
- }
944
- else if (entry.type === 'task-summary') {
945
- void this.enqueueWrite(sessionFile, entry);
946
- }
947
- else if (entry.type === 'tag') {
948
- // Tags can always be appended
949
- void this.enqueueWrite(sessionFile, entry);
950
- }
951
- else if (entry.type === 'agent-name') {
952
- // Agent names can always be appended
953
- void this.enqueueWrite(sessionFile, entry);
954
- }
955
- else if (entry.type === 'agent-color') {
956
- // Agent colors can always be appended
957
- void this.enqueueWrite(sessionFile, entry);
958
- }
959
- else if (entry.type === 'agent-setting') {
960
- // Agent settings can always be appended
961
- void this.enqueueWrite(sessionFile, entry);
962
- }
963
- else if (entry.type === 'pr-link') {
964
- // PR links can always be appended
965
- void this.enqueueWrite(sessionFile, entry);
966
- }
967
- else if (entry.type === 'file-history-snapshot') {
968
- // File history snapshots can always be appended
969
- void this.enqueueWrite(sessionFile, entry);
970
- }
971
- else if (entry.type === 'attribution-snapshot') {
972
- // Attribution snapshots can always be appended
973
- void this.enqueueWrite(sessionFile, entry);
974
- }
975
- else if (entry.type === 'speculation-accept') {
976
- // Speculation accept entries can always be appended
977
- void this.enqueueWrite(sessionFile, entry);
978
- }
979
- else if (entry.type === 'mode') {
980
- // Mode entries can always be appended
981
- void this.enqueueWrite(sessionFile, entry);
982
- }
983
- else if (entry.type === 'worktree-state') {
984
- void this.enqueueWrite(sessionFile, entry);
985
- }
986
- else if (entry.type === 'content-replacement') {
987
- // Content replacement records can always be appended. Subagent records
988
- // go to the sidechain file (for AgentTool resume); main-thread
989
- // records go to the session file (for /resume).
990
- const targetFile = entry.agentId
991
- ? getAgentTranscriptPath(entry.agentId)
992
- : sessionFile;
993
- void this.enqueueWrite(targetFile, entry);
994
- }
995
- else if (entry.type === 'marble-origami-commit') {
996
- // Always append. Commit order matters for restore (later commits may
997
- // reference earlier commits' summary messages), so these must be
998
- // written in the order received and read back sequentially.
999
- void this.enqueueWrite(sessionFile, entry);
1000
- }
1001
- else if (entry.type === 'marble-origami-snapshot') {
1002
- // Always append. Last-wins on restore — later entries supersede.
1003
- void this.enqueueWrite(sessionFile, entry);
1004
- }
1005
- else {
1006
- const messageSet = await getSessionMessages(sessionId);
1007
- if (entry.type === 'queue-operation') {
1008
- // Queue operations are always appended to the session file
1009
- void this.enqueueWrite(sessionFile, entry);
1010
- }
1011
- else {
1012
- // At this point, entry must be a TranscriptMessage (user/assistant/attachment/system)
1013
- // All other entry types have been handled above
1014
- const isAgentSidechain = entry.isSidechain && entry.agentId !== undefined;
1015
- const targetFile = isAgentSidechain
1016
- ? getAgentTranscriptPath(asAgentId(entry.agentId))
1017
- : sessionFile;
1018
- // For message entries, check if UUID already exists in current session.
1019
- // Skip dedup for agent sidechain LOCAL writes — they go to a separate
1020
- // file, and fork-inherited parent messages share UUIDs with the main
1021
- // session transcript. Deduping against the main session's set would
1022
- // drop them, leaving the persisted sidechain transcript incomplete
1023
- // (resume-of-fork loads a 10KB file instead of the full 85KB inherited
1024
- // context).
1025
- //
1026
- // The sidechain bypass applies ONLY to the local file write — remote
1027
- // persistence (session-ingress) uses a single Last-Uuid chain per
1028
- // sessionId, so re-POSTing a UUID it already has 409s and eventually
1029
- // exhausts retries → gracefulShutdownSync(1). See inc-4718.
1030
- const isNewUuid = !messageSet.has(entry.uuid);
1031
- if (isAgentSidechain || isNewUuid) {
1032
- // Enqueue write — appendToFile handles ENOENT by creating directories
1033
- void this.enqueueWrite(targetFile, entry);
1034
- if (!isAgentSidechain) {
1035
- // messageSet is main-file-authoritative. Sidechain entries go to a
1036
- // separate agent file — adding their UUIDs here causes recordTranscript
1037
- // to skip them on the main thread (line ~1270), so the message is never
1038
- // written to the main session file. The next main-thread message then
1039
- // chains its parentUuid to a UUID that only exists in the agent file,
1040
- // and --resume's buildConversationChain terminates at the dangling ref.
1041
- // Same constraint for remote (inc-4718 above): sidechain persisting a
1042
- // UUID the main thread hasn't written yet → 409 when main writes it.
1043
- messageSet.add(entry.uuid);
1044
- if (isTranscriptMessage(entry)) {
1045
- await this.persistToRemote(sessionId, entry);
1046
- }
1047
- }
1048
- }
1049
- }
1050
- }
1051
- }
1052
- /**
1053
- * Loads the sessionFile variable.
1054
- * Do not need to create session files until they are written to.
1055
- */
1056
- ensureCurrentSessionFile() {
1057
- if (this.sessionFile === null) {
1058
- this.sessionFile = getTranscriptPath();
1059
- }
1060
- return this.sessionFile;
1061
- }
1062
- /**
1063
- * Returns the session file path if it exists, null otherwise.
1064
- * Used for writing to sessions other than the current one.
1065
- * Caches positive results so we only stat once per session.
1066
- */
1067
- existingSessionFiles = new Map();
1068
- async getExistingSessionFile(sessionId) {
1069
- const cached = this.existingSessionFiles.get(sessionId);
1070
- if (cached)
1071
- return cached;
1072
- const targetFile = getTranscriptPathForSession(sessionId);
1073
- try {
1074
- await stat(targetFile);
1075
- this.existingSessionFiles.set(sessionId, targetFile);
1076
- return targetFile;
1077
- }
1078
- catch (e) {
1079
- if (isFsInaccessible(e))
1080
- return null;
1081
- throw e;
1082
- }
1083
- }
1084
- async persistToRemote(sessionId, entry) {
1085
- if (isShuttingDown()) {
1086
- return;
1087
- }
1088
- // CCR v2 path: write as internal worker event
1089
- if (this.internalEventWriter) {
1090
- try {
1091
- await this.internalEventWriter('transcript', entry, {
1092
- ...(isCompactBoundaryMessage(entry) && { isCompaction: true }),
1093
- ...(entry.agentId && { agentId: entry.agentId }),
1094
- });
1095
- }
1096
- catch {
1097
- logEvent('tengu_session_persistence_failed', {});
1098
- logForDebugging('Failed to write transcript as internal event');
1099
- }
1100
- return;
1101
- }
1102
- // v1 Session Ingress path
1103
- if (!isEnvTruthy(process.env.ENABLE_SESSION_PERSISTENCE) ||
1104
- !this.remoteIngressUrl) {
1105
- return;
1106
- }
1107
- const success = await sessionIngress.appendSessionLog(sessionId, entry, this.remoteIngressUrl);
1108
- if (!success) {
1109
- logEvent('tengu_session_persistence_failed', {});
1110
- gracefulShutdownSync(1, 'other');
1111
- }
1112
- }
1113
- setRemoteIngressUrl(url) {
1114
- this.remoteIngressUrl = url;
1115
- logForDebugging(`Remote persistence enabled with URL: ${url}`);
1116
- if (url) {
1117
- // If using CCR, don't delay messages by any more than 10ms.
1118
- this.FLUSH_INTERVAL_MS = REMOTE_FLUSH_INTERVAL_MS;
1119
- }
1120
- }
1121
- setInternalEventWriter(writer) {
1122
- this.internalEventWriter = writer;
1123
- logForDebugging('CCR v2 internal event writer registered for transcript persistence');
1124
- // Use fast flush interval for CCR v2
1125
- this.FLUSH_INTERVAL_MS = REMOTE_FLUSH_INTERVAL_MS;
1126
- }
1127
- setInternalEventReader(reader) {
1128
- this.internalEventReader = reader;
1129
- logForDebugging('CCR v2 internal event reader registered for session resume');
1130
- }
1131
- setInternalSubagentEventReader(reader) {
1132
- this.internalSubagentEventReader = reader;
1133
- logForDebugging('CCR v2 subagent event reader registered for session resume');
1134
- }
1135
- getInternalEventReader() {
1136
- return this.internalEventReader;
1137
- }
1138
- getInternalSubagentEventReader() {
1139
- return this.internalSubagentEventReader;
1140
- }
1141
- }
1142
- // Filter out already-recorded messages before passing to insertMessageChain.
1143
- // Without this, after compaction messagesToKeep (same UUIDs as pre-compact
1144
- // messages) are dedup-skipped by appendEntry but still advance the parentUuid
1145
- // cursor in insertMessageChain, causing new messages to chain from pre-compact
1146
- // UUIDs instead of the post-compact summary — orphaning the compact boundary.
1147
- //
1148
- // `startingParentUuidHint`: used by useLogMessages to pass the parent from
1149
- // the previous incremental slice, avoiding an O(n) scan to rediscover it.
1150
- //
1151
- // Skip-tracking: already-recorded messages are tracked as the parent ONLY if
1152
- // they form a PREFIX (appear before any new message). This handles both cases:
1153
- // - Growing-array callers (QueryEngine, queryHelpers, LocalMainSessionTask,
1154
- // trajectory): recorded messages are always a prefix → tracked → correct
1155
- // parent chain for new messages.
1156
- // - Compaction (useLogMessages): new CB/summary appear FIRST, then recorded
1157
- // messagesToKeep → not a prefix → not tracked → CB gets parentUuid=null
1158
- // (correct: truncates --continue chain at compact boundary).
1159
- export async function recordTranscript(messages, teamInfo, startingParentUuidHint, allMessages) {
1160
- const cleanedMessages = cleanMessagesForLogging(messages, allMessages);
1161
- const sessionId = getSessionId();
1162
- const messageSet = await getSessionMessages(sessionId);
1163
- const newMessages = [];
1164
- let startingParentUuid = startingParentUuidHint;
1165
- let seenNewMessage = false;
1166
- for (const m of cleanedMessages) {
1167
- if (messageSet.has(m.uuid)) {
1168
- // Only track skipped messages that form a prefix. After compaction,
1169
- // messagesToKeep appear AFTER new CB/summary, so this skips them.
1170
- if (!seenNewMessage && isChainParticipant(m)) {
1171
- startingParentUuid = m.uuid;
1172
- }
1173
- }
1174
- else {
1175
- newMessages.push(m);
1176
- seenNewMessage = true;
1177
- }
1178
- }
1179
- if (newMessages.length > 0) {
1180
- await getProject().insertMessageChain(newMessages, false, undefined, startingParentUuid, teamInfo);
1181
- }
1182
- // Return the last ACTUALLY recorded chain-participant's UUID, OR the
1183
- // prefix-tracked UUID if no new chain participants were recorded. This lets
1184
- // callers (useLogMessages) maintain the correct parent chain even when the
1185
- // slice is all-recorded (rewind, /resume scenarios where every message is
1186
- // already in messageSet). Progress is skipped — it's written to the JSONL
1187
- // but nothing chains TO it (see isChainParticipant).
1188
- const lastRecorded = newMessages.findLast(isChainParticipant);
1189
- return lastRecorded?.uuid ?? startingParentUuid ?? null;
1190
- }
1191
- export async function recordSidechainTranscript(messages, agentId, startingParentUuid) {
1192
- await getProject().insertMessageChain(cleanMessagesForLogging(messages), true, agentId, startingParentUuid);
1193
- }
1194
- export async function recordQueueOperation(queueOp) {
1195
- await getProject().insertQueueOperation(queueOp);
1196
- }
1197
- /**
1198
- * Remove a message from the transcript by UUID.
1199
- * Used when a tombstone is received for an orphaned message.
1200
- */
1201
- export async function removeTranscriptMessage(targetUuid) {
1202
- await getProject().removeMessageByUuid(targetUuid);
1203
- }
1204
- export async function recordFileHistorySnapshot(messageId, snapshot, isSnapshotUpdate) {
1205
- await getProject().insertFileHistorySnapshot(messageId, snapshot, isSnapshotUpdate);
1206
- }
1207
- export async function recordAttributionSnapshot(snapshot) {
1208
- await getProject().insertAttributionSnapshot(snapshot);
1209
- }
1210
- export async function recordContentReplacement(replacements, agentId) {
1211
- await getProject().insertContentReplacement(replacements, agentId);
1212
- }
1213
- /**
1214
- * Reset the session file pointer after switchSession/regenerateSessionId.
1215
- * The new file is created lazily on the first user/assistant message.
1216
- */
1217
- export async function resetSessionFilePointer() {
1218
- getProject().resetSessionFile();
1219
- }
1220
- /**
1221
- * Adopt the existing session file after --continue/--resume (non-fork).
1222
- * Call after switchSession + resetSessionFilePointer + restoreSessionMetadata:
1223
- * getTranscriptPath() now derives the resumed file's path from the switched
1224
- * sessionId, and the cache holds the final metadata (--name title, resumed
1225
- * mode/tag/agent).
1226
- *
1227
- * Setting sessionFile here — instead of waiting for materializeSessionFile
1228
- * on the first user message — lets the exit cleanup handler's
1229
- * reAppendSessionMetadata run (it bails when sessionFile is null). Without
1230
- * this, `-c -n foo` + quit-before-message drops the title on the floor:
1231
- * the in-memory cache is correct but never written. The resumed file
1232
- * already exists on disk (we loaded from it), so this can't create an
1233
- * orphan the way a fresh --name session would.
1234
- *
1235
- * skipTitleRefresh: restoreSessionMetadata populated the cache from the
1236
- * same disk read microseconds ago, so refreshing from the tail here is a
1237
- * no-op — unless --name was used, in which case it would clobber the fresh
1238
- * CLI title with the stale disk value. After this write, disk == cache and
1239
- * later calls (compaction, exit cleanup) absorb SDK writes normally.
1240
- */
1241
- export function adoptResumedSessionFile() {
1242
- const project = getProject();
1243
- project.sessionFile = getTranscriptPath();
1244
- project.reAppendSessionMetadata(true);
1245
- }
1246
- /**
1247
- * Append a context-collapse commit entry to the transcript. One entry per
1248
- * commit, in commit order. On resume these are collected into an ordered
1249
- * array and handed to restoreFromEntries() which rebuilds the commit log.
1250
- */
1251
- export async function recordContextCollapseCommit(commit) {
1252
- const sessionId = getSessionId();
1253
- if (!sessionId)
1254
- return;
1255
- await getProject().appendEntry({
1256
- type: 'marble-origami-commit',
1257
- sessionId,
1258
- ...commit,
1259
- });
1260
- }
1261
- /**
1262
- * Snapshot the staged queue + spawn state. Written after each ctx-agent
1263
- * spawn resolves (when staged contents may have changed). Last-wins on
1264
- * restore — the loader keeps only the most recent snapshot entry.
1265
- */
1266
- export async function recordContextCollapseSnapshot(snapshot) {
1267
- const sessionId = getSessionId();
1268
- if (!sessionId)
1269
- return;
1270
- await getProject().appendEntry({
1271
- type: 'marble-origami-snapshot',
1272
- sessionId,
1273
- ...snapshot,
1274
- });
1275
- }
1276
- export async function flushSessionStorage() {
1277
- await getProject().flush();
1278
- }
1279
- export async function hydrateRemoteSession(sessionId, ingressUrl) {
1280
- switchSession(asSessionId(sessionId));
1281
- const project = getProject();
1282
- try {
1283
- const remoteLogs = (await sessionIngress.getSessionLogs(sessionId, ingressUrl)) || [];
1284
- // Ensure the project directory and session file exist
1285
- const projectDir = getProjectDir(getOriginalCwd());
1286
- await mkdir(projectDir, { recursive: true, mode: 0o700 });
1287
- const sessionFile = getTranscriptPathForSession(sessionId);
1288
- // Replace local logs with remote logs. writeFile truncates, so no
1289
- // unlink is needed; an empty remoteLogs array produces an empty file.
1290
- const content = remoteLogs.map(e => jsonStringify(e) + '\n').join('');
1291
- await writeFile(sessionFile, content, { encoding: 'utf8', mode: 0o600 });
1292
- logForDebugging(`Hydrated ${remoteLogs.length} entries from remote`);
1293
- return remoteLogs.length > 0;
1294
- }
1295
- catch (error) {
1296
- logForDebugging(`Error hydrating session from remote: ${error}`);
1297
- logForDiagnosticsNoPII('error', 'hydrate_remote_session_fail');
1298
- return false;
1299
- }
1300
- finally {
1301
- // Set remote ingress URL after hydrating the remote session
1302
- // to ensure we've always synced with the remote session
1303
- // prior to enabling persistence
1304
- project.setRemoteIngressUrl(ingressUrl);
1305
- }
1306
- }
1307
- /**
1308
- * Hydrate session state from CCR v2 internal events.
1309
- * Fetches foreground and subagent events via the registered readers,
1310
- * extracts transcript entries from payloads, and writes them to the
1311
- * local transcript files (main + per-agent).
1312
- * The server handles compaction filtering — it returns events starting
1313
- * from the latest compaction boundary.
1314
- */
1315
- export async function hydrateFromCCRv2InternalEvents(sessionId) {
1316
- const startMs = Date.now();
1317
- switchSession(asSessionId(sessionId));
1318
- const project = getProject();
1319
- const reader = project.getInternalEventReader();
1320
- if (!reader) {
1321
- logForDebugging('No internal event reader registered for CCR v2 resume');
1322
- return false;
1323
- }
1324
- try {
1325
- // Fetch foreground events
1326
- const events = await reader();
1327
- if (!events) {
1328
- logForDebugging('Failed to read internal events for resume');
1329
- logForDiagnosticsNoPII('error', 'hydrate_ccr_v2_read_fail');
1330
- return false;
1331
- }
1332
- const projectDir = getProjectDir(getOriginalCwd());
1333
- await mkdir(projectDir, { recursive: true, mode: 0o700 });
1334
- // Write foreground transcript
1335
- const sessionFile = getTranscriptPathForSession(sessionId);
1336
- const fgContent = events.map(e => jsonStringify(e.payload) + '\n').join('');
1337
- await writeFile(sessionFile, fgContent, { encoding: 'utf8', mode: 0o600 });
1338
- logForDebugging(`Hydrated ${events.length} foreground entries from CCR v2 internal events`);
1339
- // Fetch and write subagent events
1340
- let subagentEventCount = 0;
1341
- const subagentReader = project.getInternalSubagentEventReader();
1342
- if (subagentReader) {
1343
- const subagentEvents = await subagentReader();
1344
- if (subagentEvents && subagentEvents.length > 0) {
1345
- subagentEventCount = subagentEvents.length;
1346
- // Group by agent_id
1347
- const byAgent = new Map();
1348
- for (const e of subagentEvents) {
1349
- const agentId = e.agent_id || '';
1350
- if (!agentId)
1351
- continue;
1352
- let list = byAgent.get(agentId);
1353
- if (!list) {
1354
- list = [];
1355
- byAgent.set(agentId, list);
1356
- }
1357
- list.push(e.payload);
1358
- }
1359
- // Write each agent's transcript to its own file
1360
- for (const [agentId, entries] of byAgent) {
1361
- const agentFile = getAgentTranscriptPath(asAgentId(agentId));
1362
- await mkdir(dirname(agentFile), { recursive: true, mode: 0o700 });
1363
- const agentContent = entries
1364
- .map(p => jsonStringify(p) + '\n')
1365
- .join('');
1366
- await writeFile(agentFile, agentContent, {
1367
- encoding: 'utf8',
1368
- mode: 0o600,
1369
- });
1370
- }
1371
- logForDebugging(`Hydrated ${subagentEvents.length} subagent entries across ${byAgent.size} agents`);
1372
- }
1373
- }
1374
- logForDiagnosticsNoPII('info', 'hydrate_ccr_v2_completed', {
1375
- duration_ms: Date.now() - startMs,
1376
- event_count: events.length,
1377
- subagent_event_count: subagentEventCount,
1378
- });
1379
- return events.length > 0;
1380
- }
1381
- catch (error) {
1382
- // Re-throw epoch mismatch so the worker doesn't race against gracefulShutdown
1383
- if (error instanceof Error &&
1384
- error.message === 'CCRClient: Epoch mismatch (409)') {
1385
- throw error;
1386
- }
1387
- logForDebugging(`Error hydrating session from CCR v2: ${error}`);
1388
- logForDiagnosticsNoPII('error', 'hydrate_ccr_v2_fail');
1389
- return false;
1390
- }
1391
- }
1392
- function extractFirstPrompt(transcript) {
1393
- const textContent = getFirstMeaningfulUserMessageTextContent(transcript);
1394
- if (textContent) {
1395
- let result = textContent.replace(/\n/g, ' ').trim();
1396
- // Store a reasonably long version for display-time truncation
1397
- // The actual truncation will be applied at display time based on terminal width
1398
- if (result.length > 200) {
1399
- result = result.slice(0, 200).trim() + '…';
1400
- }
1401
- return result;
1402
- }
1403
- return 'No prompt';
1404
- }
1405
- /**
1406
- * Gets the last user message that was processed (i.e., before any non-user message appears).
1407
- * Used to determine if a session has valid user interaction.
1408
- */
1409
- export function getFirstMeaningfulUserMessageTextContent(transcript) {
1410
- for (const msg of transcript) {
1411
- if (msg.type !== 'user' || msg.isMeta)
1412
- continue;
1413
- // Skip compact summary messages - they should not be treated as the first prompt
1414
- if ('isCompactSummary' in msg && msg.isCompactSummary)
1415
- continue;
1416
- const content = msg.message?.content;
1417
- if (!content)
1418
- continue;
1419
- // Collect all text values. For array content (common in VS Code where
1420
- // IDE metadata tags come before the user's actual prompt), iterate all
1421
- // text blocks so we don't miss the real prompt hidden behind
1422
- // <ide_selection>/<ide_opened_file> blocks.
1423
- const texts = [];
1424
- if (typeof content === 'string') {
1425
- texts.push(content);
1426
- }
1427
- else if (Array.isArray(content)) {
1428
- for (const block of content) {
1429
- if (block.type === 'text' && block.text) {
1430
- texts.push(block.text);
1431
- }
1432
- }
1433
- }
1434
- for (const textContent of texts) {
1435
- if (!textContent)
1436
- continue;
1437
- const commandNameTag = extractTag(textContent, COMMAND_NAME_TAG);
1438
- if (commandNameTag) {
1439
- const commandName = commandNameTag.replace(/^\//, '');
1440
- // If it's a built-in command, then it's unlikely to provide
1441
- // meaningful context (e.g. `/model sonnet`)
1442
- if (builtInCommandNames().has(commandName)) {
1443
- continue;
1444
- }
1445
- else {
1446
- // Otherwise, for custom commands, then keep it only if it has
1447
- // arguments (e.g. `/review reticulate splines`)
1448
- const commandArgs = extractTag(textContent, 'command-args')?.trim();
1449
- if (!commandArgs) {
1450
- continue;
1451
- }
1452
- // Return clean formatted command instead of raw XML
1453
- return `${commandNameTag} ${commandArgs}`;
1454
- }
1455
- }
1456
- // Format bash input with ! prefix (as user typed it). Checked before
1457
- // the generic XML skip so bash-mode sessions get a meaningful title.
1458
- const bashInput = extractTag(textContent, 'bash-input');
1459
- if (bashInput) {
1460
- return `! ${bashInput}`;
1461
- }
1462
- // Skip non-meaningful messages (local command output, hook output,
1463
- // autonomous tick prompts, task notifications, pure IDE metadata tags)
1464
- if (SKIP_FIRST_PROMPT_PATTERN.test(textContent)) {
1465
- continue;
1466
- }
1467
- return textContent;
1468
- }
1469
- }
1470
- return undefined;
1471
- }
1472
- export function removeExtraFields(transcript) {
1473
- return transcript.map(m => {
1474
- const { isSidechain, parentUuid, ...serializedMessage } = m;
1475
- return serializedMessage;
1476
- });
1477
- }
1478
- /**
1479
- * Splice the preserved segment back into the chain after compaction.
1480
- *
1481
- * Preserved messages exist in the JSONL with their ORIGINAL pre-compact
1482
- * parentUuids (recordTranscript dedup-skipped them — can't rewrite).
1483
- * The internal chain (keep[i+1]→keep[i]) is intact; only endpoints need
1484
- * patching: head→anchor, and anchor's other children→tail. Anchor is the
1485
- * last summary for suffix-preserving, boundary itself for prefix-preserving.
1486
- *
1487
- * Only the LAST seg-boundary is relinked — earlier segs were summarized
1488
- * into it. Everything physically before the absolute-last boundary (except
1489
- * preservedUuids) is deleted, which handles all multi-boundary shapes
1490
- * without special-casing.
1491
- *
1492
- * Mutates the Map in place.
1493
- */
1494
- function applyPreservedSegmentRelinks(messages) {
1495
- // Find the absolute-last boundary and the last seg-boundary (can differ:
1496
- // manual /compact after reactive compact → seg is stale).
1497
- let lastSeg;
1498
- let lastSegBoundaryIdx = -1;
1499
- let absoluteLastBoundaryIdx = -1;
1500
- const entryIndex = new Map();
1501
- let i = 0;
1502
- for (const entry of messages.values()) {
1503
- entryIndex.set(entry.uuid, i);
1504
- if (isCompactBoundaryMessage(entry)) {
1505
- absoluteLastBoundaryIdx = i;
1506
- const seg = entry.compactMetadata?.preservedSegment;
1507
- if (seg) {
1508
- lastSeg = seg;
1509
- lastSegBoundaryIdx = i;
1510
- }
1511
- }
1512
- i++;
1513
- }
1514
- // No seg anywhere → no-op. findUnresolvedToolUse etc. read the full map.
1515
- if (!lastSeg)
1516
- return;
1517
- // Seg stale (no-seg boundary came after): skip relink, still prune at
1518
- // absolute — otherwise the stale preserved chain becomes a phantom leaf.
1519
- const segIsLive = lastSegBoundaryIdx === absoluteLastBoundaryIdx;
1520
- // Validate tail→head BEFORE mutating so malformed metadata is a true
1521
- // no-op (walk stops at headUuid, doesn't need the relink to run first).
1522
- const preservedUuids = new Set();
1523
- if (segIsLive) {
1524
- const walkSeen = new Set();
1525
- let cur = messages.get(lastSeg.tailUuid);
1526
- let reachedHead = false;
1527
- while (cur && !walkSeen.has(cur.uuid)) {
1528
- walkSeen.add(cur.uuid);
1529
- preservedUuids.add(cur.uuid);
1530
- if (cur.uuid === lastSeg.headUuid) {
1531
- reachedHead = true;
1532
- break;
1533
- }
1534
- cur = cur.parentUuid ? messages.get(cur.parentUuid) : undefined;
1535
- }
1536
- if (!reachedHead) {
1537
- // tail→head walk broke — a UUID in the preserved segment isn't in the
1538
- // transcript. Returning here skips the prune below, so resume loads
1539
- // the full pre-compact history. Known cause: mid-turn-yielded
1540
- // attachment pushed to mutableMessages but never recordTranscript'd
1541
- // (SDK subprocess restarted before next turn's qe:420 flush).
1542
- logEvent('tengu_relink_walk_broken', {
1543
- tailInTranscript: messages.has(lastSeg.tailUuid),
1544
- headInTranscript: messages.has(lastSeg.headUuid),
1545
- anchorInTranscript: messages.has(lastSeg.anchorUuid),
1546
- walkSteps: walkSeen.size,
1547
- transcriptSize: messages.size,
1548
- });
1549
- return;
1550
- }
1551
- }
1552
- if (segIsLive) {
1553
- const head = messages.get(lastSeg.headUuid);
1554
- if (head) {
1555
- messages.set(lastSeg.headUuid, {
1556
- ...head,
1557
- parentUuid: lastSeg.anchorUuid,
1558
- });
1559
- }
1560
- // Tail-splice: anchor's other children → tail. No-op if already pointing
1561
- // at tail (the useLogMessages race case).
1562
- for (const [uuid, msg] of messages) {
1563
- if (msg.parentUuid === lastSeg.anchorUuid && uuid !== lastSeg.headUuid) {
1564
- messages.set(uuid, { ...msg, parentUuid: lastSeg.tailUuid });
1565
- }
1566
- }
1567
- // Zero stale usage: on-disk input_tokens reflect pre-compact context
1568
- // (~190K) — stripStaleUsage only patched in-memory copies that were
1569
- // dedup-skipped. Without this, resume → immediate autocompact spiral.
1570
- for (const uuid of preservedUuids) {
1571
- const msg = messages.get(uuid);
1572
- if (msg?.type !== 'assistant')
1573
- continue;
1574
- messages.set(uuid, {
1575
- ...msg,
1576
- message: {
1577
- ...msg.message,
1578
- usage: {
1579
- ...msg.message.usage,
1580
- input_tokens: 0,
1581
- output_tokens: 0,
1582
- cache_creation_input_tokens: 0,
1583
- cache_read_input_tokens: 0,
1584
- },
1585
- },
1586
- });
1587
- }
1588
- }
1589
- // Prune everything physically before the absolute-last boundary that
1590
- // isn't preserved. preservedUuids empty when !segIsLive → full prune.
1591
- const toDelete = [];
1592
- for (const [uuid] of messages) {
1593
- const idx = entryIndex.get(uuid);
1594
- if (idx !== undefined &&
1595
- idx < absoluteLastBoundaryIdx &&
1596
- !preservedUuids.has(uuid)) {
1597
- toDelete.push(uuid);
1598
- }
1599
- }
1600
- for (const uuid of toDelete)
1601
- messages.delete(uuid);
1602
- }
1603
- /**
1604
- * Delete messages that Snip executions removed from the in-memory array,
1605
- * and relink parentUuid across the gaps.
1606
- *
1607
- * Unlike compact_boundary which truncates a prefix, snip removes
1608
- * middle ranges. The JSONL is append-only, so removed messages stay on disk
1609
- * and the surviving messages' parentUuid chains walk through them. Without
1610
- * this filter, buildConversationChain reconstructs the full unsnipped history
1611
- * and resume immediately PTLs (adamr-20260320-165831: 397K displayed → 1.65M
1612
- * actual).
1613
- *
1614
- * Deleting alone is not enough: the surviving message AFTER a removed range
1615
- * has parentUuid pointing INTO the gap. buildConversationChain would hit
1616
- * messages.get(undefined) and stop, orphaning everything before the gap. So
1617
- * after delete we relink: for each survivor with a dangling parentUuid, walk
1618
- * backward through the removed region's own parent links to the first
1619
- * non-removed ancestor.
1620
- *
1621
- * The boundary records removedUuids at execution time so we can replay the
1622
- * exact removal on load. Older boundaries without removedUuids are skipped —
1623
- * resume loads their pre-snip history (the pre-fix behavior).
1624
- *
1625
- * Mutates the Map in place.
1626
- */
1627
- function applySnipRemovals(messages) {
1628
- const toDelete = new Set();
1629
- for (const entry of messages.values()) {
1630
- const removedUuids = entry.snipMetadata?.removedUuids;
1631
- if (!removedUuids)
1632
- continue;
1633
- for (const uuid of removedUuids)
1634
- toDelete.add(uuid);
1635
- }
1636
- if (toDelete.size === 0)
1637
- return;
1638
- // Capture each to-delete entry's own parentUuid BEFORE deleting so we can
1639
- // walk backward through contiguous removed ranges. Entries not in the Map
1640
- // (already absent, e.g. from a prior compact_boundary prune) contribute no
1641
- // link; the relink walk will stop at the gap and pick up null (chain-root
1642
- // behavior — same as if compact truncated there, which it did).
1643
- const deletedParent = new Map();
1644
- let removedCount = 0;
1645
- for (const uuid of toDelete) {
1646
- const entry = messages.get(uuid);
1647
- if (!entry)
1648
- continue;
1649
- deletedParent.set(uuid, entry.parentUuid);
1650
- messages.delete(uuid);
1651
- removedCount++;
1652
- }
1653
- // Relink survivors with dangling parentUuid. Walk backward through
1654
- // deletedParent until we hit a UUID not in toDelete (or null). Path
1655
- // compression: after resolving, seed the map with the resolved link so
1656
- // subsequent survivors sharing the same chain segment don't re-walk.
1657
- const resolve = (start) => {
1658
- const path = [];
1659
- let cur = start;
1660
- while (cur && toDelete.has(cur)) {
1661
- path.push(cur);
1662
- cur = deletedParent.get(cur);
1663
- if (cur === undefined) {
1664
- cur = null;
1665
- break;
1666
- }
1667
- }
1668
- for (const p of path)
1669
- deletedParent.set(p, cur);
1670
- return cur;
1671
- };
1672
- let relinkedCount = 0;
1673
- for (const [uuid, msg] of messages) {
1674
- if (!msg.parentUuid || !toDelete.has(msg.parentUuid))
1675
- continue;
1676
- messages.set(uuid, { ...msg, parentUuid: resolve(msg.parentUuid) });
1677
- relinkedCount++;
1678
- }
1679
- logEvent('tengu_snip_resume_filtered', {
1680
- removed_count: removedCount,
1681
- relinked_count: relinkedCount,
1682
- });
1683
- }
1684
- /**
1685
- * O(n) single-pass: find the message with the latest timestamp matching a predicate.
1686
- * Replaces the `[...values].filter(pred).sort((a,b) => Date(b)-Date(a))[0]` pattern
1687
- * which is O(n log n) + 2n Date allocations.
1688
- */
1689
- function findLatestMessage(messages, predicate) {
1690
- let latest;
1691
- let maxTime = -Infinity;
1692
- for (const m of messages) {
1693
- if (!predicate(m))
1694
- continue;
1695
- const t = Date.parse(m.timestamp);
1696
- if (t > maxTime) {
1697
- maxTime = t;
1698
- latest = m;
1699
- }
1700
- }
1701
- return latest;
1702
- }
1703
- /**
1704
- * Builds a conversation chain from a leaf message to root
1705
- * @param messages Map of all messages
1706
- * @param leafMessage The leaf message to start from
1707
- * @returns Array of messages from root to leaf
1708
- */
1709
- export function buildConversationChain(messages, leafMessage) {
1710
- const transcript = [];
1711
- const seen = new Set();
1712
- let currentMsg = leafMessage;
1713
- while (currentMsg) {
1714
- if (seen.has(currentMsg.uuid)) {
1715
- logError(new Error(`Cycle detected in parentUuid chain at message ${currentMsg.uuid}. Returning partial transcript.`));
1716
- logEvent('tengu_chain_parent_cycle', {});
1717
- break;
1718
- }
1719
- seen.add(currentMsg.uuid);
1720
- transcript.push(currentMsg);
1721
- currentMsg = currentMsg.parentUuid
1722
- ? messages.get(currentMsg.parentUuid)
1723
- : undefined;
1724
- }
1725
- transcript.reverse();
1726
- return recoverOrphanedParallelToolResults(messages, transcript, seen);
1727
- }
1728
- /**
1729
- * Post-pass for buildConversationChain: recover sibling assistant blocks and
1730
- * tool_results that the single-parent walk orphaned.
1731
- *
1732
- * Streaming (claude.ts:~2024) emits one AssistantMessage per content_block_stop
1733
- * — N parallel tool_uses → N messages, distinct uuid, same message.id. Each
1734
- * tool_result's sourceToolAssistantUUID points to its own one-block assistant,
1735
- * so insertMessageChain's override (line ~894) writes each TR's parentUuid to a
1736
- * DIFFERENT assistant. The topology is a DAG; the walk above is a linked-list
1737
- * traversal and keeps only one branch.
1738
- *
1739
- * Two loss modes observed in production (both fixed here):
1740
- * 1. Sibling assistant orphaned: walk goes prev→asstA→TR_A→next, drops asstB
1741
- * (same message.id, chained off asstA) and TR_B.
1742
- * 2. Progress-fork (legacy, pre-#23537): each tool_use asst had a progress
1743
- * child (continued the write chain) AND a TR child. Walk followed
1744
- * progress; TRs were dropped. No longer written (progress removed from
1745
- * transcript persistence), but old transcripts still have this shape.
1746
- *
1747
- * Read-side fix: the write topology is already on disk for old transcripts;
1748
- * this recovery pass handles them.
1749
- */
1750
- function recoverOrphanedParallelToolResults(messages, chain, seen) {
1751
- const chainAssistants = chain.filter((m) => m.type === 'assistant');
1752
- if (chainAssistants.length === 0)
1753
- return chain;
1754
- // Anchor = last on-chain member of each sibling group. chainAssistants is
1755
- // already in chain order, so later iterations overwrite → last wins.
1756
- const anchorByMsgId = new Map();
1757
- for (const a of chainAssistants) {
1758
- if (a.message.id)
1759
- anchorByMsgId.set(a.message.id, a);
1760
- }
1761
- // O(n) precompute: sibling groups and TR index.
1762
- // TRs indexed by parentUuid — insertMessageChain:~894 already wrote that
1763
- // as the srcUUID, and --fork-session strips srcUUID but keeps parentUuid.
1764
- const siblingsByMsgId = new Map();
1765
- const toolResultsByAsst = new Map();
1766
- for (const m of messages.values()) {
1767
- if (m.type === 'assistant' && m.message.id) {
1768
- const group = siblingsByMsgId.get(m.message.id);
1769
- if (group)
1770
- group.push(m);
1771
- else
1772
- siblingsByMsgId.set(m.message.id, [m]);
1773
- }
1774
- else if (m.type === 'user' &&
1775
- m.parentUuid &&
1776
- Array.isArray(m.message.content) &&
1777
- m.message.content.some(b => b.type === 'tool_result')) {
1778
- const group = toolResultsByAsst.get(m.parentUuid);
1779
- if (group)
1780
- group.push(m);
1781
- else
1782
- toolResultsByAsst.set(m.parentUuid, [m]);
1783
- }
1784
- }
1785
- // For each message.id group touching the chain: collect off-chain siblings,
1786
- // then off-chain TRs for ALL members. Splice right after the last on-chain
1787
- // member so the group stays contiguous for normalizeMessagesForAPI's merge
1788
- // and every TR lands after its tool_use.
1789
- const processedGroups = new Set();
1790
- const inserts = new Map();
1791
- let recoveredCount = 0;
1792
- for (const asst of chainAssistants) {
1793
- const msgId = asst.message.id;
1794
- if (!msgId || processedGroups.has(msgId))
1795
- continue;
1796
- processedGroups.add(msgId);
1797
- const group = siblingsByMsgId.get(msgId) ?? [asst];
1798
- const orphanedSiblings = group.filter(s => !seen.has(s.uuid));
1799
- const orphanedTRs = [];
1800
- for (const member of group) {
1801
- const trs = toolResultsByAsst.get(member.uuid);
1802
- if (!trs)
1803
- continue;
1804
- for (const tr of trs) {
1805
- if (!seen.has(tr.uuid))
1806
- orphanedTRs.push(tr);
1807
- }
1808
- }
1809
- if (orphanedSiblings.length === 0 && orphanedTRs.length === 0)
1810
- continue;
1811
- // Timestamp sort keeps content-block / completion order; stable-sort
1812
- // preserves JSONL write order on ties.
1813
- orphanedSiblings.sort((a, b) => a.timestamp.localeCompare(b.timestamp));
1814
- orphanedTRs.sort((a, b) => a.timestamp.localeCompare(b.timestamp));
1815
- const anchor = anchorByMsgId.get(msgId);
1816
- const recovered = [...orphanedSiblings, ...orphanedTRs];
1817
- for (const r of recovered)
1818
- seen.add(r.uuid);
1819
- recoveredCount += recovered.length;
1820
- inserts.set(anchor.uuid, recovered);
1821
- }
1822
- if (recoveredCount === 0)
1823
- return chain;
1824
- logEvent('tengu_chain_parallel_tr_recovered', {
1825
- recovered_count: recoveredCount,
1826
- });
1827
- const result = [];
1828
- for (const m of chain) {
1829
- result.push(m);
1830
- const toInsert = inserts.get(m.uuid);
1831
- if (toInsert)
1832
- result.push(...toInsert);
1833
- }
1834
- return result;
1835
- }
1836
- /**
1837
- * Find the latest turn_duration checkpoint in the reconstructed chain and
1838
- * compare its recorded messageCount against the chain's position at that
1839
- * point. Emits tengu_resume_consistency_delta for BigQuery monitoring of
1840
- * write→load round-trip drift — the class of bugs where snip/compact/
1841
- * parallel-TR operations mutate in-memory but the parentUuid walk on disk
1842
- * reconstructs a different set (adamr-20260320-165831: 397K displayed →
1843
- * 1.65M actual on resume).
1844
- *
1845
- * delta > 0: resume loaded MORE than in-session (the usual failure mode)
1846
- * delta < 0: resume loaded FEWER (chain truncation — #22453 class)
1847
- * delta = 0: round-trip consistent
1848
- *
1849
- * Called from loadConversationForResume — fires once per resume, not on
1850
- * /share or log-listing chain rebuilds.
1851
- */
1852
- export function checkResumeConsistency(chain) {
1853
- for (let i = chain.length - 1; i >= 0; i--) {
1854
- const m = chain[i];
1855
- if (m.type !== 'system' || m.subtype !== 'turn_duration')
1856
- continue;
1857
- const expected = m.messageCount;
1858
- if (expected === undefined)
1859
- return;
1860
- // `i` is the 0-based index of the checkpoint in the reconstructed chain.
1861
- // The checkpoint was appended AFTER messageCount messages, so its own
1862
- // position should be messageCount (i.e., i === expected).
1863
- const actual = i;
1864
- logEvent('tengu_resume_consistency_delta', {
1865
- expected,
1866
- actual,
1867
- delta: actual - expected,
1868
- chain_length: chain.length,
1869
- checkpoint_age_entries: chain.length - 1 - i,
1870
- });
1871
- return;
1872
- }
1873
- }
1874
- /**
1875
- * Builds a filie history snapshot chain from the conversation
1876
- */
1877
- function buildFileHistorySnapshotChain(fileHistorySnapshots, conversation) {
1878
- const snapshots = [];
1879
- // messageId → last index in snapshots[] for O(1) update lookup
1880
- const indexByMessageId = new Map();
1881
- for (const message of conversation) {
1882
- const snapshotMessage = fileHistorySnapshots.get(message.uuid);
1883
- if (!snapshotMessage) {
1884
- continue;
1885
- }
1886
- const { snapshot, isSnapshotUpdate } = snapshotMessage;
1887
- const existingIndex = isSnapshotUpdate
1888
- ? indexByMessageId.get(snapshot.messageId)
1889
- : undefined;
1890
- if (existingIndex === undefined) {
1891
- indexByMessageId.set(snapshot.messageId, snapshots.length);
1892
- snapshots.push(snapshot);
1893
- }
1894
- else {
1895
- snapshots[existingIndex] = snapshot;
1896
- }
1897
- }
1898
- return snapshots;
1899
- }
1900
- /**
1901
- * Builds an attribution snapshot chain from the conversation.
1902
- * Unlike file history snapshots, attribution snapshots are returned in full
1903
- * because they use generated UUIDs (not message UUIDs) and represent
1904
- * cumulative state that should be restored on session resume.
1905
- */
1906
- function buildAttributionSnapshotChain(attributionSnapshots, _conversation) {
1907
- // Return all attribution snapshots - they will be merged during restore
1908
- return Array.from(attributionSnapshots.values());
1909
- }
1910
- /**
1911
- * Loads a transcript from a JSON or JSONL file and converts it to LogOption format
1912
- * @param filePath Path to the transcript file (.json or .jsonl)
1913
- * @returns LogOption containing the transcript messages
1914
- * @throws Error if file doesn't exist or contains invalid data
1915
- */
1916
- export async function loadTranscriptFromFile(filePath) {
1917
- if (filePath.endsWith('.jsonl')) {
1918
- const { messages, summaries, customTitles, tags, fileHistorySnapshots, attributionSnapshots, contextCollapseCommits, contextCollapseSnapshot, leafUuids, contentReplacements, worktreeStates, } = await loadTranscriptFile(filePath);
1919
- if (messages.size === 0) {
1920
- throw new Error('No messages found in JSONL file');
1921
- }
1922
- // Find the most recent leaf message using pre-computed leaf UUIDs
1923
- const leafMessage = findLatestMessage(messages.values(), msg => leafUuids.has(msg.uuid));
1924
- if (!leafMessage) {
1925
- throw new Error('No valid conversation chain found in JSONL file');
1926
- }
1927
- // Build the conversation chain backwards from leaf to root
1928
- const transcript = buildConversationChain(messages, leafMessage);
1929
- const summary = summaries.get(leafMessage.uuid);
1930
- const customTitle = customTitles.get(leafMessage.sessionId);
1931
- const tag = tags.get(leafMessage.sessionId);
1932
- const sessionId = leafMessage.sessionId;
1933
- return {
1934
- ...convertToLogOption(transcript, 0, summary, customTitle, buildFileHistorySnapshotChain(fileHistorySnapshots, transcript), tag, filePath, buildAttributionSnapshotChain(attributionSnapshots, transcript), undefined, contentReplacements.get(sessionId) ?? []),
1935
- contextCollapseCommits: contextCollapseCommits.filter(e => e.sessionId === sessionId),
1936
- contextCollapseSnapshot: contextCollapseSnapshot?.sessionId === sessionId
1937
- ? contextCollapseSnapshot
1938
- : undefined,
1939
- worktreeSession: worktreeStates.has(sessionId)
1940
- ? worktreeStates.get(sessionId)
1941
- : undefined,
1942
- };
1943
- }
1944
- // json log files
1945
- const content = await readFile(filePath, { encoding: 'utf-8' });
1946
- let parsed;
1947
- try {
1948
- parsed = jsonParse(content);
1949
- }
1950
- catch (error) {
1951
- throw new Error(`Invalid JSON in transcript file: ${error}`);
1952
- }
1953
- let messages;
1954
- if (Array.isArray(parsed)) {
1955
- messages = parsed;
1956
- }
1957
- else if (parsed && typeof parsed === 'object' && 'messages' in parsed) {
1958
- if (!Array.isArray(parsed.messages)) {
1959
- throw new Error('Transcript messages must be an array');
1960
- }
1961
- messages = parsed.messages;
1962
- }
1963
- else {
1964
- throw new Error('Transcript must be an array of messages or an object with a messages array');
1965
- }
1966
- return convertToLogOption(messages, 0, undefined, undefined, undefined, undefined, filePath);
1967
- }
1968
- /**
1969
- * Checks if a user message has visible content (text or image, not just tool_result).
1970
- * Tool results are displayed as part of collapsed groups, not as standalone messages.
1971
- * Also excludes meta messages which are not shown to the user.
1972
- */
1973
- function hasVisibleUserContent(message) {
1974
- if (message.type !== 'user')
1975
- return false;
1976
- // Meta messages are not shown to the user
1977
- if (message.isMeta)
1978
- return false;
1979
- const content = message.message?.content;
1980
- if (!content)
1981
- return false;
1982
- // String content is always visible
1983
- if (typeof content === 'string') {
1984
- return content.trim().length > 0;
1985
- }
1986
- // Array content: check for text or image blocks (not tool_result)
1987
- if (Array.isArray(content)) {
1988
- return content.some(block => block.type === 'text' ||
1989
- block.type === 'image' ||
1990
- block.type === 'document');
1991
- }
1992
- return false;
1993
- }
1994
- /**
1995
- * Checks if an assistant message has visible text content (not just tool_use blocks).
1996
- * Tool uses are displayed as grouped/collapsed UI elements, not as standalone messages.
1997
- */
1998
- function hasVisibleAssistantContent(message) {
1999
- if (message.type !== 'assistant')
2000
- return false;
2001
- const content = message.message?.content;
2002
- if (!content || !Array.isArray(content))
2003
- return false;
2004
- // Check for text block (not just tool_use/thinking blocks)
2005
- return content.some(block => block.type === 'text' &&
2006
- typeof block.text === 'string' &&
2007
- block.text.trim().length > 0);
2008
- }
2009
- /**
2010
- * Counts visible messages that would appear as conversation turns in the UI.
2011
- * Excludes:
2012
- * - System, attachment, and progress messages
2013
- * - User messages with isMeta flag (hidden from user)
2014
- * - User messages that only contain tool_result blocks (displayed as collapsed groups)
2015
- * - Assistant messages that only contain tool_use blocks (displayed as collapsed groups)
2016
- */
2017
- function countVisibleMessages(transcript) {
2018
- let count = 0;
2019
- for (const message of transcript) {
2020
- switch (message.type) {
2021
- case 'user':
2022
- // Count user messages with visible content (text, image, not just tool_result or meta)
2023
- if (hasVisibleUserContent(message)) {
2024
- count++;
2025
- }
2026
- break;
2027
- case 'assistant':
2028
- // Count assistant messages with text content (not just tool_use)
2029
- if (hasVisibleAssistantContent(message)) {
2030
- count++;
2031
- }
2032
- break;
2033
- case 'attachment':
2034
- case 'system':
2035
- case 'progress':
2036
- // These message types are not counted as visible conversation turns
2037
- break;
2038
- }
2039
- }
2040
- return count;
2041
- }
2042
- function convertToLogOption(transcript, value = 0, summary, customTitle, fileHistorySnapshots, tag, fullPath, attributionSnapshots, agentSetting, contentReplacements) {
2043
- const lastMessage = transcript.at(-1);
2044
- const firstMessage = transcript[0];
2045
- // Get the first user message for the prompt
2046
- const firstPrompt = extractFirstPrompt(transcript);
2047
- // Create timestamps from message timestamps
2048
- const created = new Date(firstMessage.timestamp);
2049
- const modified = new Date(lastMessage.timestamp);
2050
- return {
2051
- date: lastMessage.timestamp,
2052
- messages: removeExtraFields(transcript),
2053
- fullPath,
2054
- value,
2055
- created,
2056
- modified,
2057
- firstPrompt,
2058
- messageCount: countVisibleMessages(transcript),
2059
- isSidechain: firstMessage.isSidechain,
2060
- teamName: firstMessage.teamName,
2061
- agentName: firstMessage.agentName,
2062
- agentSetting,
2063
- leafUuid: lastMessage.uuid,
2064
- summary,
2065
- customTitle,
2066
- tag,
2067
- fileHistorySnapshots: fileHistorySnapshots,
2068
- attributionSnapshots: attributionSnapshots,
2069
- contentReplacements,
2070
- gitBranch: lastMessage.gitBranch,
2071
- projectPath: firstMessage.cwd,
2072
- };
2073
- }
2074
- async function trackSessionBranchingAnalytics(logs) {
2075
- const sessionIdCounts = new Map();
2076
- let maxCount = 0;
2077
- for (const log of logs) {
2078
- const sessionId = getSessionIdFromLog(log);
2079
- if (sessionId) {
2080
- const newCount = (sessionIdCounts.get(sessionId) || 0) + 1;
2081
- sessionIdCounts.set(sessionId, newCount);
2082
- maxCount = Math.max(newCount, maxCount);
2083
- }
2084
- }
2085
- // Early exit if no duplicates detected
2086
- if (maxCount <= 1) {
2087
- return;
2088
- }
2089
- // Count sessions with branches and calculate stats using functional approach
2090
- const branchCounts = Array.from(sessionIdCounts.values()).filter(c => c > 1);
2091
- const sessionsWithBranches = branchCounts.length;
2092
- const totalBranches = branchCounts.reduce((sum, count) => sum + count, 0);
2093
- logEvent('tengu_session_forked_branches_fetched', {
2094
- total_sessions: sessionIdCounts.size,
2095
- sessions_with_branches: sessionsWithBranches,
2096
- max_branches_per_session: Math.max(...branchCounts),
2097
- avg_branches_per_session: Math.round(totalBranches / sessionsWithBranches),
2098
- total_transcript_count: logs.length,
2099
- });
2100
- }
2101
- export async function fetchLogs(limit) {
2102
- const projectDir = getProjectDir(getOriginalCwd());
2103
- const logs = await getSessionFilesLite(projectDir, limit, getOriginalCwd());
2104
- await trackSessionBranchingAnalytics(logs);
2105
- return logs;
2106
- }
2107
- /**
2108
- * Append an entry to a session file. Creates the parent dir if missing.
2109
- */
2110
- /* eslint-disable custom-rules/no-sync-fs -- sync callers (exit cleanup, materialize) */
2111
- function appendEntryToFile(fullPath, entry) {
2112
- const fs = getFsImplementation();
2113
- const line = jsonStringify(entry) + '\n';
2114
- try {
2115
- fs.appendFileSync(fullPath, line, { mode: 0o600 });
2116
- }
2117
- catch {
2118
- fs.mkdirSync(dirname(fullPath), { mode: 0o700 });
2119
- fs.appendFileSync(fullPath, line, { mode: 0o600 });
2120
- }
2121
- }
2122
- /**
2123
- * Sync tail read for reAppendSessionMetadata's external-writer check.
2124
- * fstat on the already-open fd (no extra path lookup); reads the same
2125
- * LITE_READ_BUF_SIZE window that readLiteMetadata scans. Returns empty
2126
- * string on any error so callers fall through to unconditional behavior.
2127
- */
2128
- function readFileTailSync(fullPath) {
2129
- let fd;
2130
- try {
2131
- fd = openSync(fullPath, 'r');
2132
- const st = fstatSync(fd);
2133
- const tailOffset = Math.max(0, st.size - LITE_READ_BUF_SIZE);
2134
- const buf = Buffer.allocUnsafe(Math.min(LITE_READ_BUF_SIZE, st.size - tailOffset));
2135
- const bytesRead = readSync(fd, buf, 0, buf.length, tailOffset);
2136
- return buf.toString('utf8', 0, bytesRead);
2137
- }
2138
- catch {
2139
- return '';
2140
- }
2141
- finally {
2142
- if (fd !== undefined) {
2143
- try {
2144
- closeSync(fd);
2145
- }
2146
- catch {
2147
- // closeSync can throw; swallow to preserve return '' contract
2148
- }
2149
- }
2150
- }
2151
- }
2152
- /* eslint-enable custom-rules/no-sync-fs */
2153
- export async function saveCustomTitle(sessionId, customTitle, fullPath, source = 'user') {
2154
- // Fall back to computed path if fullPath is not provided
2155
- const resolvedPath = fullPath ?? getTranscriptPathForSession(sessionId);
2156
- appendEntryToFile(resolvedPath, {
2157
- type: 'custom-title',
2158
- customTitle,
2159
- sessionId,
2160
- });
2161
- // Cache for current session only (for immediate visibility)
2162
- if (sessionId === getSessionId()) {
2163
- getProject().currentSessionTitle = customTitle;
2164
- }
2165
- logEvent('tengu_session_renamed', {
2166
- source: source,
2167
- });
2168
- }
2169
- /**
2170
- * Persist an AI-generated title to the JSONL as a distinct `ai-title` entry.
2171
- *
2172
- * Writing a separate entry type (vs. reusing `custom-title`) is load-bearing:
2173
- * - Read preference: readers prefer `customTitle` field over `aiTitle`, so
2174
- * a user rename always wins regardless of append order.
2175
- * - Resume safety: `loadTranscriptFile` only populates the `customTitles`
2176
- * Map from `custom-title` entries, so `restoreSessionMetadata` never
2177
- * caches an AI title and `reAppendSessionMetadata` never re-appends one
2178
- * at EOF — avoiding the clobber-on-resume bug where a stale AI title
2179
- * overwrites a mid-session user rename.
2180
- * - CAS semantics: VS Code's `onlyIfNoCustomTitle` check scans for the
2181
- * `customTitle` field only, so AI can overwrite its own previous AI
2182
- * title but never a user title.
2183
- * - Metrics: `tengu_session_renamed` is not fired for AI titles.
2184
- *
2185
- * Because the entry is never re-appended, it scrolls out of the 64KB tail
2186
- * window once enough messages accumulate. Readers (`readLiteMetadata`,
2187
- * `listSessionsImpl`, VS Code `fetchSessions`) fall back to scanning the
2188
- * head buffer for `aiTitle` in that case. Both head and tail reads are
2189
- * bounded (64KB each via `extractLastJsonStringField`), never a full scan.
2190
- *
2191
- * Callers with a stale-write guard (e.g., VS Code client) should prefer
2192
- * passing `persist: false` to the SDK control request and persisting
2193
- * through their own rename path after the guard passes, to avoid a race
2194
- * where the AI title lands after a mid-flight user rename.
2195
- */
2196
- export function saveAiGeneratedTitle(sessionId, aiTitle) {
2197
- appendEntryToFile(getTranscriptPathForSession(sessionId), {
2198
- type: 'ai-title',
2199
- aiTitle,
2200
- sessionId,
2201
- });
2202
- }
2203
- /**
2204
- * Append a periodic task summary for `claude ps`. Unlike ai-title this is
2205
- * not re-appended by reAppendSessionMetadata — it's a rolling snapshot of
2206
- * what the agent is doing *now*, so staleness is fine; ps reads the most
2207
- * recent one from the tail.
2208
- */
2209
- export function saveTaskSummary(sessionId, summary) {
2210
- appendEntryToFile(getTranscriptPathForSession(sessionId), {
2211
- type: 'task-summary',
2212
- summary,
2213
- sessionId,
2214
- timestamp: new Date().toISOString(),
2215
- });
2216
- }
2217
- export async function saveTag(sessionId, tag, fullPath) {
2218
- // Fall back to computed path if fullPath is not provided
2219
- const resolvedPath = fullPath ?? getTranscriptPathForSession(sessionId);
2220
- appendEntryToFile(resolvedPath, { type: 'tag', tag, sessionId });
2221
- // Cache for current session only (for immediate visibility)
2222
- if (sessionId === getSessionId()) {
2223
- getProject().currentSessionTag = tag;
2224
- }
2225
- logEvent('tengu_session_tagged', {});
2226
- }
2227
- /**
2228
- * Link a session to a GitHub pull request.
2229
- * This stores the PR number, URL, and repository for tracking and navigation.
2230
- */
2231
- export async function linkSessionToPR(sessionId, prNumber, prUrl, prRepository, fullPath) {
2232
- const resolvedPath = fullPath ?? getTranscriptPathForSession(sessionId);
2233
- appendEntryToFile(resolvedPath, {
2234
- type: 'pr-link',
2235
- sessionId,
2236
- prNumber,
2237
- prUrl,
2238
- prRepository,
2239
- timestamp: new Date().toISOString(),
2240
- });
2241
- // Cache for current session so reAppendSessionMetadata can re-write after compaction
2242
- if (sessionId === getSessionId()) {
2243
- const project = getProject();
2244
- project.currentSessionPrNumber = prNumber;
2245
- project.currentSessionPrUrl = prUrl;
2246
- project.currentSessionPrRepository = prRepository;
2247
- }
2248
- logEvent('tengu_session_linked_to_pr', { prNumber });
2249
- }
2250
- export function getCurrentSessionTag(sessionId) {
2251
- // Only returns tag for current session (the only one we cache)
2252
- if (sessionId === getSessionId()) {
2253
- return getProject().currentSessionTag;
2254
- }
2255
- return undefined;
2256
- }
2257
- export function getCurrentSessionTitle(sessionId) {
2258
- // Only returns title for current session (the only one we cache)
2259
- if (sessionId === getSessionId()) {
2260
- return getProject().currentSessionTitle;
2261
- }
2262
- return undefined;
2263
- }
2264
- export function getCurrentSessionAgentColor() {
2265
- return getProject().currentSessionAgentColor;
2266
- }
2267
- /**
2268
- * Restore session metadata into in-memory cache on resume.
2269
- * Populates the cache so metadata is available for display (e.g. the
2270
- * agent banner) and re-appended on session exit via reAppendSessionMetadata.
2271
- */
2272
- export function restoreSessionMetadata(meta) {
2273
- const project = getProject();
2274
- // ??= so --name (cacheSessionTitle) wins over the resumed
2275
- // session's title. REPL.tsx clears before calling, so /resume is unaffected.
2276
- if (meta.customTitle)
2277
- project.currentSessionTitle ??= meta.customTitle;
2278
- if (meta.tag !== undefined)
2279
- project.currentSessionTag = meta.tag || undefined;
2280
- if (meta.agentName)
2281
- project.currentSessionAgentName = meta.agentName;
2282
- if (meta.agentColor)
2283
- project.currentSessionAgentColor = meta.agentColor;
2284
- if (meta.agentSetting)
2285
- project.currentSessionAgentSetting = meta.agentSetting;
2286
- if (meta.mode)
2287
- project.currentSessionMode = meta.mode;
2288
- if (meta.worktreeSession !== undefined)
2289
- project.currentSessionWorktree = meta.worktreeSession;
2290
- if (meta.prNumber !== undefined)
2291
- project.currentSessionPrNumber = meta.prNumber;
2292
- if (meta.prUrl)
2293
- project.currentSessionPrUrl = meta.prUrl;
2294
- if (meta.prRepository)
2295
- project.currentSessionPrRepository = meta.prRepository;
2296
- }
2297
- /**
2298
- * Clear all cached session metadata (title, tag, agent name/color).
2299
- * Called when /clear creates a new session so stale metadata
2300
- * from the previous session does not leak into the new one.
2301
- */
2302
- export function clearSessionMetadata() {
2303
- const project = getProject();
2304
- project.currentSessionTitle = undefined;
2305
- project.currentSessionTag = undefined;
2306
- project.currentSessionAgentName = undefined;
2307
- project.currentSessionAgentColor = undefined;
2308
- project.currentSessionLastPrompt = undefined;
2309
- project.currentSessionAgentSetting = undefined;
2310
- project.currentSessionMode = undefined;
2311
- project.currentSessionWorktree = undefined;
2312
- project.currentSessionPrNumber = undefined;
2313
- project.currentSessionPrUrl = undefined;
2314
- project.currentSessionPrRepository = undefined;
2315
- }
2316
- /**
2317
- * Re-append cached session metadata (custom title, tag) to the end of the
2318
- * transcript file. Call this after compaction so the metadata stays within
2319
- * the 16KB tail window that readLiteMetadata reads during progressive loading.
2320
- * Without this, enough post-compaction messages can push the metadata entry
2321
- * out of the window, causing `--resume` to show the auto-generated firstPrompt
2322
- * instead of the user-set session name.
2323
- */
2324
- export function reAppendSessionMetadata() {
2325
- getProject().reAppendSessionMetadata();
2326
- }
2327
- export async function saveAgentName(sessionId, agentName, fullPath, source = 'user') {
2328
- const resolvedPath = fullPath ?? getTranscriptPathForSession(sessionId);
2329
- appendEntryToFile(resolvedPath, { type: 'agent-name', agentName, sessionId });
2330
- // Cache for current session only (for immediate visibility)
2331
- if (sessionId === getSessionId()) {
2332
- getProject().currentSessionAgentName = agentName;
2333
- void updateSessionName(agentName);
2334
- }
2335
- logEvent('tengu_agent_name_set', {
2336
- source: source,
2337
- });
2338
- }
2339
- export async function saveAgentColor(sessionId, agentColor, fullPath) {
2340
- const resolvedPath = fullPath ?? getTranscriptPathForSession(sessionId);
2341
- appendEntryToFile(resolvedPath, {
2342
- type: 'agent-color',
2343
- agentColor,
2344
- sessionId,
2345
- });
2346
- // Cache for current session only (for immediate visibility)
2347
- if (sessionId === getSessionId()) {
2348
- getProject().currentSessionAgentColor = agentColor;
2349
- }
2350
- logEvent('tengu_agent_color_set', {});
2351
- }
2352
- /**
2353
- * Cache the session agent setting. Written to disk by materializeSessionFile
2354
- * on the first user message, and re-stamped by reAppendSessionMetadata on exit.
2355
- * Cache-only here to avoid creating metadata-only session files at startup.
2356
- */
2357
- export function saveAgentSetting(agentSetting) {
2358
- getProject().currentSessionAgentSetting = agentSetting;
2359
- }
2360
- /**
2361
- * Cache a session title set at startup (--name). Written to disk by
2362
- * materializeSessionFile on the first user message. Cache-only here so no
2363
- * orphan metadata-only file is created before the session ID is finalized.
2364
- */
2365
- export function cacheSessionTitle(customTitle) {
2366
- getProject().currentSessionTitle = customTitle;
2367
- }
2368
- /**
2369
- * Cache the session mode. Written to disk by materializeSessionFile on the
2370
- * first user message, and re-stamped by reAppendSessionMetadata on exit.
2371
- * Cache-only here to avoid creating metadata-only session files at startup.
2372
- */
2373
- export function saveMode(mode) {
2374
- getProject().currentSessionMode = mode;
2375
- }
2376
- /**
2377
- * Record the session's worktree state for --resume. Written to disk by
2378
- * materializeSessionFile on the first user message and re-stamped by
2379
- * reAppendSessionMetadata on exit. Pass null when exiting a worktree
2380
- * so --resume knows not to cd back into it.
2381
- */
2382
- export function saveWorktreeState(worktreeSession) {
2383
- // Strip ephemeral fields (creationDurationMs, usedSparsePaths) that callers
2384
- // may pass via full WorktreeSession objects — TypeScript structural typing
2385
- // allows this, but we don't want them serialized to the transcript.
2386
- const stripped = worktreeSession
2387
- ? {
2388
- originalCwd: worktreeSession.originalCwd,
2389
- worktreePath: worktreeSession.worktreePath,
2390
- worktreeName: worktreeSession.worktreeName,
2391
- worktreeBranch: worktreeSession.worktreeBranch,
2392
- originalBranch: worktreeSession.originalBranch,
2393
- originalHeadCommit: worktreeSession.originalHeadCommit,
2394
- sessionId: worktreeSession.sessionId,
2395
- tmuxSessionName: worktreeSession.tmuxSessionName,
2396
- hookBased: worktreeSession.hookBased,
2397
- }
2398
- : null;
2399
- const project = getProject();
2400
- project.currentSessionWorktree = stripped;
2401
- // Write eagerly when the file already exists (mid-session enter/exit).
2402
- // For --worktree startup, sessionFile is null — materializeSessionFile
2403
- // will write it on the first message via reAppendSessionMetadata.
2404
- if (project.sessionFile) {
2405
- appendEntryToFile(project.sessionFile, {
2406
- type: 'worktree-state',
2407
- worktreeSession: stripped,
2408
- sessionId: getSessionId(),
2409
- });
2410
- }
2411
- }
2412
- /**
2413
- * Extracts the session ID from a log.
2414
- * For lite logs, uses the sessionId field directly.
2415
- * For full logs, extracts from the first message.
2416
- */
2417
- export function getSessionIdFromLog(log) {
2418
- // For lite logs, use the direct sessionId field
2419
- if (log.sessionId) {
2420
- return log.sessionId;
2421
- }
2422
- // Fall back to extracting from first message (full logs)
2423
- return log.messages[0]?.sessionId;
2424
- }
2425
- /**
2426
- * Checks if a log is a lite log that needs full loading.
2427
- * Lite logs have messages: [] and sessionId set.
2428
- */
2429
- export function isLiteLog(log) {
2430
- return log.messages.length === 0 && log.sessionId !== undefined;
2431
- }
2432
- /**
2433
- * Loads full messages for a lite log by reading its JSONL file.
2434
- * Returns a new LogOption with populated messages array.
2435
- * If the log is already full or loading fails, returns the original log.
2436
- */
2437
- export async function loadFullLog(log) {
2438
- // If already full, return as-is
2439
- if (!isLiteLog(log)) {
2440
- return log;
2441
- }
2442
- // Use the fullPath from the index entry directly
2443
- const sessionFile = log.fullPath;
2444
- if (!sessionFile) {
2445
- return log;
2446
- }
2447
- try {
2448
- const { messages, summaries, customTitles, tags, agentNames, agentColors, agentSettings, prNumbers, prUrls, prRepositories, modes, worktreeStates, fileHistorySnapshots, attributionSnapshots, contentReplacements, contextCollapseCommits, contextCollapseSnapshot, leafUuids, } = await loadTranscriptFile(sessionFile);
2449
- if (messages.size === 0) {
2450
- return log;
2451
- }
2452
- // Find the most recent user/assistant leaf message from the transcript
2453
- const mostRecentLeaf = findLatestMessage(messages.values(), msg => leafUuids.has(msg.uuid) &&
2454
- (msg.type === 'user' || msg.type === 'assistant'));
2455
- if (!mostRecentLeaf) {
2456
- return log;
2457
- }
2458
- // Build the conversation chain from this leaf
2459
- const transcript = buildConversationChain(messages, mostRecentLeaf);
2460
- // Leaf's sessionId — forked sessions copy chain[0] from the source, but
2461
- // metadata entries (custom-title etc.) are keyed by the current session.
2462
- const sessionId = mostRecentLeaf.sessionId;
2463
- return {
2464
- ...log,
2465
- messages: removeExtraFields(transcript),
2466
- firstPrompt: extractFirstPrompt(transcript),
2467
- messageCount: countVisibleMessages(transcript),
2468
- summary: mostRecentLeaf
2469
- ? summaries.get(mostRecentLeaf.uuid)
2470
- : log.summary,
2471
- customTitle: sessionId ? customTitles.get(sessionId) : log.customTitle,
2472
- tag: sessionId ? tags.get(sessionId) : log.tag,
2473
- agentName: sessionId ? agentNames.get(sessionId) : log.agentName,
2474
- agentColor: sessionId ? agentColors.get(sessionId) : log.agentColor,
2475
- agentSetting: sessionId ? agentSettings.get(sessionId) : log.agentSetting,
2476
- mode: sessionId ? modes.get(sessionId) : log.mode,
2477
- worktreeSession: sessionId && worktreeStates.has(sessionId)
2478
- ? worktreeStates.get(sessionId)
2479
- : log.worktreeSession,
2480
- prNumber: sessionId ? prNumbers.get(sessionId) : log.prNumber,
2481
- prUrl: sessionId ? prUrls.get(sessionId) : log.prUrl,
2482
- prRepository: sessionId
2483
- ? prRepositories.get(sessionId)
2484
- : log.prRepository,
2485
- gitBranch: mostRecentLeaf?.gitBranch ?? log.gitBranch,
2486
- isSidechain: transcript[0]?.isSidechain ?? log.isSidechain,
2487
- teamName: transcript[0]?.teamName ?? log.teamName,
2488
- leafUuid: mostRecentLeaf?.uuid ?? log.leafUuid,
2489
- fileHistorySnapshots: buildFileHistorySnapshotChain(fileHistorySnapshots, transcript),
2490
- attributionSnapshots: buildAttributionSnapshotChain(attributionSnapshots, transcript),
2491
- contentReplacements: sessionId
2492
- ? (contentReplacements.get(sessionId) ?? [])
2493
- : log.contentReplacements,
2494
- // Filter to the resumed session's entries. loadTranscriptFile reads
2495
- // the file sequentially so the array is already in commit order;
2496
- // filter preserves that.
2497
- contextCollapseCommits: sessionId
2498
- ? contextCollapseCommits.filter(e => e.sessionId === sessionId)
2499
- : undefined,
2500
- contextCollapseSnapshot: sessionId && contextCollapseSnapshot?.sessionId === sessionId
2501
- ? contextCollapseSnapshot
2502
- : undefined,
2503
- };
2504
- }
2505
- catch {
2506
- // If loading fails, return the original log
2507
- return log;
2508
- }
2509
- }
2510
- /**
2511
- * Searches for sessions by custom title match.
2512
- * Returns matches sorted by recency (newest first).
2513
- * Uses case-insensitive matching for better UX.
2514
- * Deduplicates by sessionId (keeps most recent per session).
2515
- * Searches across same-repo worktrees by default.
2516
- */
2517
- export async function searchSessionsByCustomTitle(query, options) {
2518
- const { limit, exact } = options || {};
2519
- // Use worktree-aware loading to search across same-repo sessions
2520
- const worktreePaths = await getWorktreePaths(getOriginalCwd());
2521
- const allStatLogs = await getStatOnlyLogsForWorktrees(worktreePaths);
2522
- // Enrich all logs to access customTitle metadata
2523
- const { logs } = await enrichLogs(allStatLogs, 0, allStatLogs.length);
2524
- const normalizedQuery = query.toLowerCase().trim();
2525
- const matchingLogs = logs.filter(log => {
2526
- const title = log.customTitle?.toLowerCase().trim();
2527
- if (!title)
2528
- return false;
2529
- return exact ? title === normalizedQuery : title.includes(normalizedQuery);
2530
- });
2531
- // Deduplicate by sessionId - multiple logs can have the same sessionId
2532
- // if they're different branches of the same conversation. Keep most recent.
2533
- const sessionIdToLog = new Map();
2534
- for (const log of matchingLogs) {
2535
- const sessionId = getSessionIdFromLog(log);
2536
- if (sessionId) {
2537
- const existing = sessionIdToLog.get(sessionId);
2538
- if (!existing || log.modified > existing.modified) {
2539
- sessionIdToLog.set(sessionId, log);
2540
- }
2541
- }
2542
- }
2543
- const deduplicated = Array.from(sessionIdToLog.values());
2544
- // Sort by recency
2545
- deduplicated.sort((a, b) => b.modified.getTime() - a.modified.getTime());
2546
- // Apply limit if specified
2547
- if (limit) {
2548
- return deduplicated.slice(0, limit);
2549
- }
2550
- return deduplicated;
2551
- }
2552
- /**
2553
- * Metadata entry types that can appear before a compact boundary but must
2554
- * still be loaded (they're session-scoped, not message-scoped).
2555
- * Kept as raw JSON string markers for cheap line filtering during streaming.
2556
- */
2557
- const METADATA_TYPE_MARKERS = [
2558
- '"type":"summary"',
2559
- '"type":"custom-title"',
2560
- '"type":"tag"',
2561
- '"type":"agent-name"',
2562
- '"type":"agent-color"',
2563
- '"type":"agent-setting"',
2564
- '"type":"mode"',
2565
- '"type":"worktree-state"',
2566
- '"type":"pr-link"',
2567
- ];
2568
- const METADATA_MARKER_BUFS = METADATA_TYPE_MARKERS.map(m => Buffer.from(m));
2569
- // Longest marker is 22 bytes; +1 for leading `{` = 23.
2570
- const METADATA_PREFIX_BOUND = 25;
2571
- // null = carry spans whole chunk. Skips concat when carry provably isn't
2572
- // a metadata line (markers sit at byte 1 after `{`).
2573
- function resolveMetadataBuf(carry, chunkBuf) {
2574
- if (carry === null || carry.length === 0)
2575
- return chunkBuf;
2576
- if (carry.length < METADATA_PREFIX_BOUND) {
2577
- return Buffer.concat([carry, chunkBuf]);
2578
- }
2579
- if (carry[0] === 0x7b /* { */) {
2580
- for (const m of METADATA_MARKER_BUFS) {
2581
- if (carry.compare(m, 0, m.length, 1, 1 + m.length) === 0) {
2582
- return Buffer.concat([carry, chunkBuf]);
2583
- }
2584
- }
2585
- }
2586
- const firstNl = chunkBuf.indexOf(0x0a);
2587
- return firstNl === -1 ? null : chunkBuf.subarray(firstNl + 1);
2588
- }
2589
- /**
2590
- * Lightweight forward scan of [0, endOffset) collecting only metadata-entry lines.
2591
- * Uses raw Buffer chunks and byte-level marker matching — no readline, no per-line
2592
- * string conversion for the ~99% of lines that are message content.
2593
- *
2594
- * Fast path: if a chunk contains zero markers (the common case — metadata entries
2595
- * are <50 per session), the entire chunk is skipped without line splitting.
2596
- */
2597
- async function scanPreBoundaryMetadata(filePath, endOffset) {
2598
- const { createReadStream } = await import('fs');
2599
- const NEWLINE = 0x0a;
2600
- const stream = createReadStream(filePath, { end: endOffset - 1 });
2601
- const metadataLines = [];
2602
- let carry = null;
2603
- for await (const chunk of stream) {
2604
- const chunkBuf = chunk;
2605
- const buf = resolveMetadataBuf(carry, chunkBuf);
2606
- if (buf === null) {
2607
- carry = null;
2608
- continue;
2609
- }
2610
- // Fast path: most chunks contain zero metadata markers. Skip line splitting.
2611
- let hasAnyMarker = false;
2612
- for (const m of METADATA_MARKER_BUFS) {
2613
- if (buf.includes(m)) {
2614
- hasAnyMarker = true;
2615
- break;
2616
- }
2617
- }
2618
- if (hasAnyMarker) {
2619
- let lineStart = 0;
2620
- let nl = buf.indexOf(NEWLINE);
2621
- while (nl !== -1) {
2622
- // Bounded marker check: only look within this line's byte range
2623
- for (const m of METADATA_MARKER_BUFS) {
2624
- const mIdx = buf.indexOf(m, lineStart);
2625
- if (mIdx !== -1 && mIdx < nl) {
2626
- metadataLines.push(buf.toString('utf-8', lineStart, nl));
2627
- break;
2628
- }
2629
- }
2630
- lineStart = nl + 1;
2631
- nl = buf.indexOf(NEWLINE, lineStart);
2632
- }
2633
- carry = buf.subarray(lineStart);
2634
- }
2635
- else {
2636
- // No markers in this chunk — just preserve the incomplete trailing line
2637
- const lastNl = buf.lastIndexOf(NEWLINE);
2638
- carry = lastNl >= 0 ? buf.subarray(lastNl + 1) : buf;
2639
- }
2640
- // Guard against quadratic carry growth for pathological huge lines
2641
- // (e.g., a 10 MB tool-output line with no newline). Real metadata entries
2642
- // are <1 KB, so if carry exceeds this we're mid-message-content — drop it.
2643
- if (carry.length > 64 * 1024)
2644
- carry = null;
2645
- }
2646
- // Final incomplete line (no trailing newline at endOffset)
2647
- if (carry !== null && carry.length > 0) {
2648
- for (const m of METADATA_MARKER_BUFS) {
2649
- if (carry.includes(m)) {
2650
- metadataLines.push(carry.toString('utf-8'));
2651
- break;
2652
- }
2653
- }
2654
- }
2655
- return metadataLines;
2656
- }
2657
- /**
2658
- * Byte-level pre-filter that excises dead fork branches before parseJSONL.
2659
- *
2660
- * Every rewind/ctrl-z leaves an orphaned chain branch in the append-only
2661
- * JSONL forever. buildConversationChain walks parentUuid from the latest leaf
2662
- * and discards everything else, but by then parseJSONL has already paid to
2663
- * JSON.parse all of it. Measured on fork-heavy sessions:
2664
- *
2665
- * 41 MB, 99% dead: parseJSONL 56.0 ms -> 3.9 ms (-93%)
2666
- * 151 MB, 92% dead: 47.3 ms -> 9.4 ms (-80%)
2667
- *
2668
- * Sessions with few dead branches (5-7%) see a small win from the overhead of
2669
- * the index pass roughly canceling the parse savings, so this is gated on
2670
- * buffer size (same threshold as SKIP_PRECOMPACT_THRESHOLD).
2671
- *
2672
- * Relies on two invariants verified across 25k+ message lines in local
2673
- * sessions (0 violations):
2674
- *
2675
- * 1. Transcript messages always serialize with parentUuid as the first key.
2676
- * JSON.stringify emits keys in insertion order and recordTranscript's
2677
- * object literal puts parentUuid first. So `{"parentUuid":` is a stable
2678
- * line prefix that distinguishes transcript messages from metadata.
2679
- *
2680
- * 2. Top-level uuid detection is handled by a suffix check + depth check
2681
- * (see inline comment in the scan loop). toolUseResult/mcpMeta serialize
2682
- * AFTER uuid with arbitrary server-controlled objects, and agent_progress
2683
- * entries serialize a nested Message in data BEFORE uuid — both can
2684
- * produce nested `"uuid":"<36>","timestamp":"` bytes, so suffix alone
2685
- * is insufficient. When multiple suffix matches exist, a brace-depth
2686
- * scan disambiguates.
2687
- *
2688
- * The append-only write discipline guarantees parents appear at earlier file
2689
- * offsets than children, so walking backward from EOF always finds them.
2690
- */
2691
- /**
2692
- * Disambiguate multiple `"uuid":"<36>","timestamp":"` matches in one line by
2693
- * finding the one at JSON nesting depth 1. String-aware brace counter:
2694
- * `{`/`}` inside string values don't count; `\"` and `\\` inside strings are
2695
- * handled. Candidates is sorted ascending (the scan loop produces them in
2696
- * byte order). Returns the first depth-1 candidate, or the last candidate if
2697
- * none are at depth 1 (shouldn't happen for well-formed JSONL — depth-1 is
2698
- * where the top-level object's fields live).
2699
- *
2700
- * Only called when ≥2 suffix matches exist (agent_progress with a nested
2701
- * Message, or mcpMeta with a coincidentally-suffixed object). Cost is
2702
- * O(max(candidates) - lineStart) — one forward byte pass, stopping at the
2703
- * first depth-1 hit.
2704
- */
2705
- function pickDepthOneUuidCandidate(buf, lineStart, candidates) {
2706
- const QUOTE = 0x22;
2707
- const BACKSLASH = 0x5c;
2708
- const OPEN_BRACE = 0x7b;
2709
- const CLOSE_BRACE = 0x7d;
2710
- let depth = 0;
2711
- let inString = false;
2712
- let escapeNext = false;
2713
- let ci = 0;
2714
- for (let i = lineStart; ci < candidates.length; i++) {
2715
- if (i === candidates[ci]) {
2716
- if (depth === 1 && !inString)
2717
- return candidates[ci];
2718
- ci++;
2719
- }
2720
- const b = buf[i];
2721
- if (escapeNext) {
2722
- escapeNext = false;
2723
- }
2724
- else if (inString) {
2725
- if (b === BACKSLASH)
2726
- escapeNext = true;
2727
- else if (b === QUOTE)
2728
- inString = false;
2729
- }
2730
- else if (b === QUOTE)
2731
- inString = true;
2732
- else if (b === OPEN_BRACE)
2733
- depth++;
2734
- else if (b === CLOSE_BRACE)
2735
- depth--;
2736
- }
2737
- return candidates.at(-1);
2738
- }
2739
- function walkChainBeforeParse(buf) {
2740
- const NEWLINE = 0x0a;
2741
- const OPEN_BRACE = 0x7b;
2742
- const QUOTE = 0x22;
2743
- const PARENT_PREFIX = Buffer.from('{"parentUuid":');
2744
- const UUID_KEY = Buffer.from('"uuid":"');
2745
- const SIDECHAIN_TRUE = Buffer.from('"isSidechain":true');
2746
- const UUID_LEN = 36;
2747
- const TS_SUFFIX = Buffer.from('","timestamp":"');
2748
- const TS_SUFFIX_LEN = TS_SUFFIX.length;
2749
- const PREFIX_LEN = PARENT_PREFIX.length;
2750
- const KEY_LEN = UUID_KEY.length;
2751
- // Stride-3 flat index of transcript messages: [lineStart, lineEnd, parentStart].
2752
- // parentStart is the byte offset of the parent uuid's first char, or -1 for null.
2753
- // Metadata lines (summary, mode, file-history-snapshot, etc.) go in metaRanges
2754
- // unfiltered - they lack the parentUuid prefix and downstream needs all of them.
2755
- const msgIdx = [];
2756
- const metaRanges = [];
2757
- const uuidToSlot = new Map();
2758
- let pos = 0;
2759
- const len = buf.length;
2760
- while (pos < len) {
2761
- const nl = buf.indexOf(NEWLINE, pos);
2762
- const lineEnd = nl === -1 ? len : nl + 1;
2763
- if (lineEnd - pos > PREFIX_LEN &&
2764
- buf[pos] === OPEN_BRACE &&
2765
- buf.compare(PARENT_PREFIX, 0, PREFIX_LEN, pos, pos + PREFIX_LEN) === 0) {
2766
- // `{"parentUuid":null,` or `{"parentUuid":"<36 chars>",`
2767
- const parentStart = buf[pos + PREFIX_LEN] === QUOTE ? pos + PREFIX_LEN + 1 : -1;
2768
- // The top-level uuid is immediately followed by `","timestamp":"` in
2769
- // user/assistant/attachment entries (the create* helpers put them
2770
- // adjacent; both always defined). But the suffix is NOT unique:
2771
- // - agent_progress entries carry a nested Message in data.message,
2772
- // serialized BEFORE top-level uuid — that inner Message has its
2773
- // own uuid,timestamp adjacent, so its bytes also satisfy the
2774
- // suffix check.
2775
- // - mcpMeta/toolUseResult come AFTER top-level uuid and hold
2776
- // server-controlled Record<string,unknown> — a server returning
2777
- // {uuid:"<36>",timestamp:"..."} would also match.
2778
- // Collect all suffix matches; a single one is unambiguous (common
2779
- // case), multiple need a brace-depth check to pick the one at
2780
- // JSON nesting depth 1. Entries with NO suffix match (some progress
2781
- // variants put timestamp BEFORE uuid → `"uuid":"<36>"}` at EOL)
2782
- // have only one `"uuid":"` and the first-match fallback is sound.
2783
- let firstAny = -1;
2784
- let suffix0 = -1;
2785
- let suffixN;
2786
- let from = pos;
2787
- for (;;) {
2788
- const next = buf.indexOf(UUID_KEY, from);
2789
- if (next < 0 || next >= lineEnd)
2790
- break;
2791
- if (firstAny < 0)
2792
- firstAny = next;
2793
- const after = next + KEY_LEN + UUID_LEN;
2794
- if (after + TS_SUFFIX_LEN <= lineEnd &&
2795
- buf.compare(TS_SUFFIX, 0, TS_SUFFIX_LEN, after, after + TS_SUFFIX_LEN) === 0) {
2796
- if (suffix0 < 0)
2797
- suffix0 = next;
2798
- else
2799
- (suffixN ??= [suffix0]).push(next);
2800
- }
2801
- from = next + KEY_LEN;
2802
- }
2803
- const uk = suffixN
2804
- ? pickDepthOneUuidCandidate(buf, pos, suffixN)
2805
- : suffix0 >= 0
2806
- ? suffix0
2807
- : firstAny;
2808
- if (uk >= 0) {
2809
- const uuidStart = uk + KEY_LEN;
2810
- // UUIDs are pure ASCII so latin1 avoids UTF-8 decode overhead.
2811
- const uuid = buf.toString('latin1', uuidStart, uuidStart + UUID_LEN);
2812
- uuidToSlot.set(uuid, msgIdx.length);
2813
- msgIdx.push(pos, lineEnd, parentStart);
2814
- }
2815
- else {
2816
- metaRanges.push(pos, lineEnd);
2817
- }
2818
- }
2819
- else {
2820
- metaRanges.push(pos, lineEnd);
2821
- }
2822
- pos = lineEnd;
2823
- }
2824
- // Leaf = last non-sidechain entry. isSidechain is the 2nd or 3rd key
2825
- // (after parentUuid, maybe logicalParentUuid) so indexOf from lineStart
2826
- // finds it within a few dozen bytes when present; when absent it spills
2827
- // into the next line, caught by the bounds check.
2828
- let leafSlot = -1;
2829
- for (let i = msgIdx.length - 3; i >= 0; i -= 3) {
2830
- const sc = buf.indexOf(SIDECHAIN_TRUE, msgIdx[i]);
2831
- if (sc === -1 || sc >= msgIdx[i + 1]) {
2832
- leafSlot = i;
2833
- break;
2834
- }
2835
- }
2836
- if (leafSlot < 0)
2837
- return buf;
2838
- // Walk parentUuid to root. Collect kept-message line starts and sum their
2839
- // byte lengths so we can decide whether the concat is worth it. A dangling
2840
- // parent (uuid not in file) is the normal termination for forked sessions
2841
- // and post-boundary chains -- same semantics as buildConversationChain.
2842
- // Correctness against index poisoning rests on the timestamp suffix check
2843
- // above: a nested `"uuid":"` match without the suffix never becomes uk.
2844
- const seen = new Set();
2845
- const chain = new Set();
2846
- let chainBytes = 0;
2847
- let slot = leafSlot;
2848
- while (slot !== undefined) {
2849
- if (seen.has(slot))
2850
- break;
2851
- seen.add(slot);
2852
- chain.add(msgIdx[slot]);
2853
- chainBytes += msgIdx[slot + 1] - msgIdx[slot];
2854
- const parentStart = msgIdx[slot + 2];
2855
- if (parentStart < 0)
2856
- break;
2857
- const parent = buf.toString('latin1', parentStart, parentStart + UUID_LEN);
2858
- slot = uuidToSlot.get(parent);
2859
- }
2860
- // parseJSONL cost scales with bytes, not entry count. A session can have
2861
- // thousands of dead entries by count but only single-digit-% of bytes if
2862
- // the dead branches are short turns and the live chain holds the fat
2863
- // assistant responses (measured: 107 MB session, 69% dead entries, 30%
2864
- // dead bytes - index+concat overhead exceeded parse savings). Gate on
2865
- // bytes: only stitch if we would drop at least half the buffer. Metadata
2866
- // is tiny so len - chainBytes approximates dead bytes closely enough.
2867
- // Near break-even the concat memcpy (copying chainBytes into a fresh
2868
- // allocation) dominates, so a conservative 50% gate stays safely on the
2869
- // winning side.
2870
- if (len - chainBytes < len >> 1)
2871
- return buf;
2872
- // Merge chain entries with metadata in original file order. Both msgIdx and
2873
- // metaRanges are already sorted by offset; interleave them into subarray
2874
- // views and concat once.
2875
- const parts = [];
2876
- let m = 0;
2877
- for (let i = 0; i < msgIdx.length; i += 3) {
2878
- const start = msgIdx[i];
2879
- while (m < metaRanges.length && metaRanges[m] < start) {
2880
- parts.push(buf.subarray(metaRanges[m], metaRanges[m + 1]));
2881
- m += 2;
2882
- }
2883
- if (chain.has(start)) {
2884
- parts.push(buf.subarray(start, msgIdx[i + 1]));
2885
- }
2886
- }
2887
- while (m < metaRanges.length) {
2888
- parts.push(buf.subarray(metaRanges[m], metaRanges[m + 1]));
2889
- m += 2;
2890
- }
2891
- return Buffer.concat(parts);
2892
- }
2893
- /**
2894
- * Loads all messages, summaries, and file history snapshots from a transcript file.
2895
- * Returns the messages, summaries, custom titles, tags, file history snapshots, and attribution snapshots.
2896
- */
2897
- export async function loadTranscriptFile(filePath, opts) {
2898
- const messages = new Map();
2899
- const summaries = new Map();
2900
- const customTitles = new Map();
2901
- const tags = new Map();
2902
- const agentNames = new Map();
2903
- const agentColors = new Map();
2904
- const agentSettings = new Map();
2905
- const prNumbers = new Map();
2906
- const prUrls = new Map();
2907
- const prRepositories = new Map();
2908
- const modes = new Map();
2909
- const worktreeStates = new Map();
2910
- const fileHistorySnapshots = new Map();
2911
- const attributionSnapshots = new Map();
2912
- const contentReplacements = new Map();
2913
- const agentContentReplacements = new Map();
2914
- // Array, not Map — commit order matters (nested collapses).
2915
- const contextCollapseCommits = [];
2916
- // Last-wins — later entries supersede.
2917
- let contextCollapseSnapshot;
2918
- try {
2919
- // For large transcripts, avoid materializing megabytes of stale content.
2920
- // Single forward chunked read: attribution-snapshot lines are skipped at
2921
- // the fd level (never buffered), compact boundaries truncate the
2922
- // accumulator in-stream. Peak allocation is the OUTPUT size, not the
2923
- // file size — a 151 MB session that is 84% stale attr-snaps allocates
2924
- // ~32 MB instead of 159+64 MB. This matters because mimalloc does not
2925
- // return those pages to the OS even after JS-level GC frees the backing
2926
- // buffers (measured: arrayBuffers=0 after Bun.gc(true) but RSS stuck at
2927
- // ~316 MB on the old scan+strip path vs ~155 MB here).
2928
- //
2929
- // Pre-boundary metadata (agent-setting, mode, pr-link, etc.) is recovered
2930
- // via a cheap byte-level forward scan of [0, boundary).
2931
- let buf = null;
2932
- let metadataLines = null;
2933
- let hasPreservedSegment = false;
2934
- if (!isEnvTruthy(process.env.CLAUDE_CODE_DISABLE_PRECOMPACT_SKIP)) {
2935
- const { size } = await stat(filePath);
2936
- if (size > SKIP_PRECOMPACT_THRESHOLD) {
2937
- const scan = await readTranscriptForLoad(filePath, size);
2938
- buf = scan.postBoundaryBuf;
2939
- hasPreservedSegment = scan.hasPreservedSegment;
2940
- // >0 means we truncated pre-boundary bytes and must recover
2941
- // session-scoped metadata from that range. A preservedSegment
2942
- // boundary does not truncate (preserved messages are physically
2943
- // pre-boundary), so offset stays 0 unless an EARLIER non-preserved
2944
- // boundary already truncated — in which case the preserved messages
2945
- // for the later boundary are post-that-earlier-boundary and were
2946
- // kept, and we still want the metadata scan.
2947
- if (scan.boundaryStartOffset > 0) {
2948
- metadataLines = await scanPreBoundaryMetadata(filePath, scan.boundaryStartOffset);
2949
- }
2950
- }
2951
- }
2952
- buf ??= await readFile(filePath);
2953
- // For large buffers (which here means readTranscriptForLoad output with
2954
- // attr-snaps already stripped at the fd level — the <5MB readFile path
2955
- // falls through the size gate below), the dominant cost is parsing dead
2956
- // fork branches that buildConversationChain would discard anyway. Skip
2957
- // when the caller needs all
2958
- // leaves (loadAllLogsFromSessionFile for /insights picks the branch with
2959
- // most user messages, not the latest), when the boundary has a
2960
- // preservedSegment (those messages keep their pre-compact parentUuid on
2961
- // disk -- applyPreservedSegmentRelinks splices them in-memory AFTER
2962
- // parse, so a pre-parse chain walk would drop them as orphans), and when
2963
- // CLAUDE_CODE_DISABLE_PRECOMPACT_SKIP is set (that kill switch means
2964
- // "load everything, skip nothing"; this is another skip-before-parse
2965
- // optimization and the scan it depends on for hasPreservedSegment did
2966
- // not run).
2967
- if (!opts?.keepAllLeaves &&
2968
- !hasPreservedSegment &&
2969
- !isEnvTruthy(process.env.CLAUDE_CODE_DISABLE_PRECOMPACT_SKIP) &&
2970
- buf.length > SKIP_PRECOMPACT_THRESHOLD) {
2971
- buf = walkChainBeforeParse(buf);
2972
- }
2973
- // First pass: process metadata-only lines collected during the boundary scan.
2974
- // These populate the session-scoped maps (agentSettings, modes, prNumbers,
2975
- // etc.) for entries written before the compact boundary. Any overlap with
2976
- // the post-boundary buffer is harmless — later values overwrite earlier ones.
2977
- if (metadataLines && metadataLines.length > 0) {
2978
- const metaEntries = parseJSONL(Buffer.from(metadataLines.join('\n')));
2979
- for (const entry of metaEntries) {
2980
- if (entry.type === 'summary' && entry.leafUuid) {
2981
- summaries.set(entry.leafUuid, entry.summary);
2982
- }
2983
- else if (entry.type === 'custom-title' && entry.sessionId) {
2984
- customTitles.set(entry.sessionId, entry.customTitle);
2985
- }
2986
- else if (entry.type === 'tag' && entry.sessionId) {
2987
- tags.set(entry.sessionId, entry.tag);
2988
- }
2989
- else if (entry.type === 'agent-name' && entry.sessionId) {
2990
- agentNames.set(entry.sessionId, entry.agentName);
2991
- }
2992
- else if (entry.type === 'agent-color' && entry.sessionId) {
2993
- agentColors.set(entry.sessionId, entry.agentColor);
2994
- }
2995
- else if (entry.type === 'agent-setting' && entry.sessionId) {
2996
- agentSettings.set(entry.sessionId, entry.agentSetting);
2997
- }
2998
- else if (entry.type === 'mode' && entry.sessionId) {
2999
- modes.set(entry.sessionId, entry.mode);
3000
- }
3001
- else if (entry.type === 'worktree-state' && entry.sessionId) {
3002
- worktreeStates.set(entry.sessionId, entry.worktreeSession);
3003
- }
3004
- else if (entry.type === 'pr-link' && entry.sessionId) {
3005
- prNumbers.set(entry.sessionId, entry.prNumber);
3006
- prUrls.set(entry.sessionId, entry.prUrl);
3007
- prRepositories.set(entry.sessionId, entry.prRepository);
3008
- }
3009
- }
3010
- }
3011
- const entries = parseJSONL(buf);
3012
- // Bridge map for legacy progress entries: progress_uuid → progress_parent_uuid.
3013
- // PR #24099 removed progress from isTranscriptMessage, so old transcripts with
3014
- // progress in the parentUuid chain would truncate at buildConversationChain
3015
- // when messages.get(progressUuid) returns undefined. Since transcripts are
3016
- // append-only (parents before children), we record each progress→parent link
3017
- // as we see it, chain-resolving through consecutive progress entries, then
3018
- // rewrite any subsequent message whose parentUuid lands in the bridge.
3019
- const progressBridge = new Map();
3020
- for (const entry of entries) {
3021
- // Legacy progress check runs before the Entry-typed else-if chain —
3022
- // progress is not in the Entry union, so checking it after TypeScript
3023
- // has narrowed `entry` intersects to `never`.
3024
- if (isLegacyProgressEntry(entry)) {
3025
- // Chain-resolve through consecutive progress entries so a later
3026
- // message pointing at the tail of a progress run bridges to the
3027
- // nearest non-progress ancestor in one lookup.
3028
- const parent = entry.parentUuid;
3029
- progressBridge.set(entry.uuid, parent && progressBridge.has(parent)
3030
- ? (progressBridge.get(parent) ?? null)
3031
- : parent);
3032
- continue;
3033
- }
3034
- if (isTranscriptMessage(entry)) {
3035
- if (entry.parentUuid && progressBridge.has(entry.parentUuid)) {
3036
- entry.parentUuid = progressBridge.get(entry.parentUuid) ?? null;
3037
- }
3038
- messages.set(entry.uuid, entry);
3039
- // Compact boundary: prior marble-origami-commit entries reference
3040
- // messages that won't be in the post-boundary chain. The >5MB
3041
- // backward-scan path discards them naturally by never reading the
3042
- // pre-boundary bytes; the <5MB path reads everything, so discard
3043
- // here. Without this, getStats().collapsedSpans in /context
3044
- // overcounts (projectView silently skips the stale commits but
3045
- // they're still in the log).
3046
- if (isCompactBoundaryMessage(entry)) {
3047
- contextCollapseCommits.length = 0;
3048
- contextCollapseSnapshot = undefined;
3049
- }
3050
- }
3051
- else if (entry.type === 'summary' && entry.leafUuid) {
3052
- summaries.set(entry.leafUuid, entry.summary);
3053
- }
3054
- else if (entry.type === 'custom-title' && entry.sessionId) {
3055
- customTitles.set(entry.sessionId, entry.customTitle);
3056
- }
3057
- else if (entry.type === 'tag' && entry.sessionId) {
3058
- tags.set(entry.sessionId, entry.tag);
3059
- }
3060
- else if (entry.type === 'agent-name' && entry.sessionId) {
3061
- agentNames.set(entry.sessionId, entry.agentName);
3062
- }
3063
- else if (entry.type === 'agent-color' && entry.sessionId) {
3064
- agentColors.set(entry.sessionId, entry.agentColor);
3065
- }
3066
- else if (entry.type === 'agent-setting' && entry.sessionId) {
3067
- agentSettings.set(entry.sessionId, entry.agentSetting);
3068
- }
3069
- else if (entry.type === 'mode' && entry.sessionId) {
3070
- modes.set(entry.sessionId, entry.mode);
3071
- }
3072
- else if (entry.type === 'worktree-state' && entry.sessionId) {
3073
- worktreeStates.set(entry.sessionId, entry.worktreeSession);
3074
- }
3075
- else if (entry.type === 'pr-link' && entry.sessionId) {
3076
- prNumbers.set(entry.sessionId, entry.prNumber);
3077
- prUrls.set(entry.sessionId, entry.prUrl);
3078
- prRepositories.set(entry.sessionId, entry.prRepository);
3079
- }
3080
- else if (entry.type === 'file-history-snapshot') {
3081
- fileHistorySnapshots.set(entry.messageId, entry);
3082
- }
3083
- else if (entry.type === 'attribution-snapshot') {
3084
- attributionSnapshots.set(entry.messageId, entry);
3085
- }
3086
- else if (entry.type === 'content-replacement') {
3087
- // Subagent decisions key by agentId (sidechain resume); main-thread
3088
- // decisions key by sessionId (/resume).
3089
- if (entry.agentId) {
3090
- const existing = agentContentReplacements.get(entry.agentId) ?? [];
3091
- agentContentReplacements.set(entry.agentId, existing);
3092
- existing.push(...entry.replacements);
3093
- }
3094
- else {
3095
- const existing = contentReplacements.get(entry.sessionId) ?? [];
3096
- contentReplacements.set(entry.sessionId, existing);
3097
- existing.push(...entry.replacements);
3098
- }
3099
- }
3100
- else if (entry.type === 'marble-origami-commit') {
3101
- contextCollapseCommits.push(entry);
3102
- }
3103
- else if (entry.type === 'marble-origami-snapshot') {
3104
- contextCollapseSnapshot = entry;
3105
- }
3106
- }
3107
- }
3108
- catch {
3109
- // File doesn't exist or can't be read
3110
- }
3111
- applyPreservedSegmentRelinks(messages);
3112
- applySnipRemovals(messages);
3113
- // Compute leaf UUIDs once at load time
3114
- // Only user/assistant messages should be considered as leaves for anchoring resume.
3115
- // Other message types (system, attachment) are metadata or auxiliary and shouldn't
3116
- // anchor a conversation chain.
3117
- //
3118
- // We use standard parent relationship for main chain detection, but also need to
3119
- // handle cases where the last message is a system/metadata message.
3120
- // For each conversation chain (identified by following parent links), the leaf
3121
- // is the most recent user/assistant message.
3122
- const allMessages = [...messages.values()];
3123
- // Standard leaf computation using parent relationships
3124
- const parentUuids = new Set(allMessages
3125
- .map(msg => msg.parentUuid)
3126
- .filter((uuid) => uuid !== null));
3127
- // Find all terminal messages (messages with no children)
3128
- const terminalMessages = allMessages.filter(msg => !parentUuids.has(msg.uuid));
3129
- const leafUuids = new Set();
3130
- let hasCycle = false;
3131
- if (getFeatureValue_CACHED_MAY_BE_STALE('tengu_pebble_leaf_prune', false)) {
3132
- // Build a set of UUIDs that have user/assistant children
3133
- // (these are mid-conversation nodes, not dead ends)
3134
- const hasUserAssistantChild = new Set();
3135
- for (const msg of allMessages) {
3136
- if (msg.parentUuid && (msg.type === 'user' || msg.type === 'assistant')) {
3137
- hasUserAssistantChild.add(msg.parentUuid);
3138
- }
3139
- }
3140
- // For each terminal message, walk back to find the nearest user/assistant ancestor.
3141
- // Skip ancestors that already have user/assistant children - those are mid-conversation
3142
- // nodes where the conversation continued (e.g., an assistant tool_use message whose
3143
- // progress child is terminal, but whose tool_result child continues the conversation).
3144
- for (const terminal of terminalMessages) {
3145
- const seen = new Set();
3146
- let current = terminal;
3147
- while (current) {
3148
- if (seen.has(current.uuid)) {
3149
- hasCycle = true;
3150
- break;
3151
- }
3152
- seen.add(current.uuid);
3153
- if (current.type === 'user' || current.type === 'assistant') {
3154
- if (!hasUserAssistantChild.has(current.uuid)) {
3155
- leafUuids.add(current.uuid);
3156
- }
3157
- break;
3158
- }
3159
- current = current.parentUuid
3160
- ? messages.get(current.parentUuid)
3161
- : undefined;
3162
- }
3163
- }
3164
- }
3165
- else {
3166
- // Original leaf computation: walk back from terminal messages to find
3167
- // the nearest user/assistant ancestor unconditionally
3168
- for (const terminal of terminalMessages) {
3169
- const seen = new Set();
3170
- let current = terminal;
3171
- while (current) {
3172
- if (seen.has(current.uuid)) {
3173
- hasCycle = true;
3174
- break;
3175
- }
3176
- seen.add(current.uuid);
3177
- if (current.type === 'user' || current.type === 'assistant') {
3178
- leafUuids.add(current.uuid);
3179
- break;
3180
- }
3181
- current = current.parentUuid
3182
- ? messages.get(current.parentUuid)
3183
- : undefined;
3184
- }
3185
- }
3186
- }
3187
- if (hasCycle) {
3188
- logEvent('tengu_transcript_parent_cycle', {});
3189
- }
3190
- return {
3191
- messages,
3192
- summaries,
3193
- customTitles,
3194
- tags,
3195
- agentNames,
3196
- agentColors,
3197
- agentSettings,
3198
- prNumbers,
3199
- prUrls,
3200
- prRepositories,
3201
- modes,
3202
- worktreeStates,
3203
- fileHistorySnapshots,
3204
- attributionSnapshots,
3205
- contentReplacements,
3206
- agentContentReplacements,
3207
- contextCollapseCommits,
3208
- contextCollapseSnapshot,
3209
- leafUuids,
3210
- };
3211
- }
3212
- /**
3213
- * Loads all messages, summaries, file history snapshots, and attribution snapshots from a specific session file.
3214
- */
3215
- async function loadSessionFile(sessionId) {
3216
- const sessionFile = join(getSessionProjectDir() ?? getProjectDir(getOriginalCwd()), `${sessionId}.jsonl`);
3217
- return loadTranscriptFile(sessionFile);
3218
- }
3219
- /**
3220
- * Gets message UUIDs for a specific session without loading all sessions.
3221
- * Memoized to avoid re-reading the same session file multiple times.
3222
- */
3223
- const getSessionMessages = memoize(async (sessionId) => {
3224
- const { messages } = await loadSessionFile(sessionId);
3225
- return new Set(messages.keys());
3226
- }, (sessionId) => sessionId);
3227
- /**
3228
- * Clear the memoized session messages cache.
3229
- * Call after compaction when old message UUIDs are no longer valid.
3230
- */
3231
- export function clearSessionMessagesCache() {
3232
- getSessionMessages.cache.clear?.();
3233
- }
3234
- /**
3235
- * Check if a message UUID exists in the session storage
3236
- */
3237
- export async function doesMessageExistInSession(sessionId, messageUuid) {
3238
- const messageSet = await getSessionMessages(sessionId);
3239
- return messageSet.has(messageUuid);
3240
- }
3241
- export async function getLastSessionLog(sessionId) {
3242
- // Single read: load all session data at once instead of reading the file twice
3243
- const { messages, summaries, customTitles, tags, agentSettings, worktreeStates, fileHistorySnapshots, attributionSnapshots, contentReplacements, contextCollapseCommits, contextCollapseSnapshot, } = await loadSessionFile(sessionId);
3244
- if (messages.size === 0)
3245
- return null;
3246
- // Prime getSessionMessages cache so recordTranscript (called after REPL
3247
- // mount on --resume) skips a second full file load. -170~227ms on large sessions.
3248
- // Guard: only prime if cache is empty. Mid-session callers (e.g. IssueFeedback)
3249
- // may call getLastSessionLog on the current session — overwriting a live cache
3250
- // with a stale disk snapshot would lose unflushed UUIDs and break dedup.
3251
- if (!getSessionMessages.cache.has(sessionId)) {
3252
- getSessionMessages.cache.set(sessionId, Promise.resolve(new Set(messages.keys())));
3253
- }
3254
- // Find the most recent non-sidechain message
3255
- const lastMessage = findLatestMessage(messages.values(), m => !m.isSidechain);
3256
- if (!lastMessage)
3257
- return null;
3258
- // Build the transcript chain from the last message
3259
- const transcript = buildConversationChain(messages, lastMessage);
3260
- const summary = summaries.get(lastMessage.uuid);
3261
- const customTitle = customTitles.get(lastMessage.sessionId);
3262
- const tag = tags.get(lastMessage.sessionId);
3263
- const agentSetting = agentSettings.get(sessionId);
3264
- return {
3265
- ...convertToLogOption(transcript, 0, summary, customTitle, buildFileHistorySnapshotChain(fileHistorySnapshots, transcript), tag, getTranscriptPathForSession(sessionId), buildAttributionSnapshotChain(attributionSnapshots, transcript), agentSetting, contentReplacements.get(sessionId) ?? []),
3266
- worktreeSession: worktreeStates.get(sessionId),
3267
- contextCollapseCommits: contextCollapseCommits.filter(e => e.sessionId === sessionId),
3268
- contextCollapseSnapshot: contextCollapseSnapshot?.sessionId === sessionId
3269
- ? contextCollapseSnapshot
3270
- : undefined,
3271
- };
3272
- }
3273
- /**
3274
- * Loads the list of message logs
3275
- * @param limit Optional limit on number of session files to load
3276
- * @returns List of message logs sorted by date
3277
- */
3278
- export async function loadMessageLogs(limit) {
3279
- const sessionLogs = await fetchLogs(limit);
3280
- // fetchLogs returns lite (stat-only) logs — enrich them to get metadata.
3281
- // enrichLogs already filters out sidechains, empty sessions, etc.
3282
- const { logs: enriched } = await enrichLogs(sessionLogs, 0, sessionLogs.length);
3283
- // enrichLogs returns fresh unshared objects — mutate in place to avoid
3284
- // re-spreading every 30-field LogOption just to renumber the index.
3285
- const sorted = sortLogs(enriched);
3286
- sorted.forEach((log, i) => {
3287
- log.value = i;
3288
- });
3289
- return sorted;
3290
- }
3291
- /**
3292
- * Loads message logs from all project directories.
3293
- * @param limit Optional limit on number of session files to load per project (used when no index exists)
3294
- * @returns List of message logs sorted by date
3295
- */
3296
- export async function loadAllProjectsMessageLogs(limit, options) {
3297
- if (options?.skipIndex) {
3298
- // Load all sessions with full message data (e.g. for /insights analysis)
3299
- return loadAllProjectsMessageLogsFull(limit);
3300
- }
3301
- const result = await loadAllProjectsMessageLogsProgressive(limit, options?.initialEnrichCount ?? INITIAL_ENRICH_COUNT);
3302
- return result.logs;
3303
- }
3304
- async function loadAllProjectsMessageLogsFull(limit) {
3305
- const projectsDir = getProjectsDir();
3306
- let dirents;
3307
- try {
3308
- dirents = await readdir(projectsDir, { withFileTypes: true });
3309
- }
3310
- catch {
3311
- return [];
3312
- }
3313
- const projectDirs = dirents
3314
- .filter(dirent => dirent.isDirectory())
3315
- .map(dirent => join(projectsDir, dirent.name));
3316
- const logsPerProject = await Promise.all(projectDirs.map(projectDir => getLogsWithoutIndex(projectDir, limit)));
3317
- const allLogs = logsPerProject.flat();
3318
- // Deduplicate — same session+leaf can appear in multiple project dirs.
3319
- // This path creates one LogOption per leaf, so use sessionId+leafUuid key.
3320
- const deduped = new Map();
3321
- for (const log of allLogs) {
3322
- const key = `${log.sessionId ?? ''}:${log.leafUuid ?? ''}`;
3323
- const existing = deduped.get(key);
3324
- if (!existing || log.modified.getTime() > existing.modified.getTime()) {
3325
- deduped.set(key, log);
3326
- }
3327
- }
3328
- // deduped values are fresh from getLogsWithoutIndex — safe to mutate
3329
- const sorted = sortLogs([...deduped.values()]);
3330
- sorted.forEach((log, i) => {
3331
- log.value = i;
3332
- });
3333
- return sorted;
3334
- }
3335
- export async function loadAllProjectsMessageLogsProgressive(limit, initialEnrichCount = INITIAL_ENRICH_COUNT) {
3336
- const projectsDir = getProjectsDir();
3337
- let dirents;
3338
- try {
3339
- dirents = await readdir(projectsDir, { withFileTypes: true });
3340
- }
3341
- catch {
3342
- return { logs: [], allStatLogs: [], nextIndex: 0 };
3343
- }
3344
- const projectDirs = dirents
3345
- .filter(dirent => dirent.isDirectory())
3346
- .map(dirent => join(projectsDir, dirent.name));
3347
- const rawLogs = [];
3348
- for (const projectDir of projectDirs) {
3349
- rawLogs.push(...(await getSessionFilesLite(projectDir, limit)));
3350
- }
3351
- // Deduplicate — same session can appear in multiple project dirs
3352
- const sorted = deduplicateLogsBySessionId(rawLogs);
3353
- const { logs, nextIndex } = await enrichLogs(sorted, 0, initialEnrichCount);
3354
- // enrichLogs returns fresh unshared objects — safe to mutate in place
3355
- logs.forEach((log, i) => {
3356
- log.value = i;
3357
- });
3358
- return { logs, allStatLogs: sorted, nextIndex };
3359
- }
3360
- export async function loadSameRepoMessageLogs(worktreePaths, limit, initialEnrichCount = INITIAL_ENRICH_COUNT) {
3361
- const result = await loadSameRepoMessageLogsProgressive(worktreePaths, limit, initialEnrichCount);
3362
- return result.logs;
3363
- }
3364
- export async function loadSameRepoMessageLogsProgressive(worktreePaths, limit, initialEnrichCount = INITIAL_ENRICH_COUNT) {
3365
- logForDebugging(`/resume: loading sessions for cwd=${getOriginalCwd()}, worktrees=[${worktreePaths.join(', ')}]`);
3366
- const allStatLogs = await getStatOnlyLogsForWorktrees(worktreePaths, limit);
3367
- logForDebugging(`/resume: found ${allStatLogs.length} session files on disk`);
3368
- const { logs, nextIndex } = await enrichLogs(allStatLogs, 0, initialEnrichCount);
3369
- // enrichLogs returns fresh unshared objects — safe to mutate in place
3370
- logs.forEach((log, i) => {
3371
- log.value = i;
3372
- });
3373
- return { logs, allStatLogs, nextIndex };
3374
- }
3375
- /**
3376
- * Gets stat-only logs for worktree paths (no file reads).
3377
- */
3378
- async function getStatOnlyLogsForWorktrees(worktreePaths, limit) {
3379
- const projectsDir = getProjectsDir();
3380
- if (worktreePaths.length <= 1) {
3381
- const cwd = getOriginalCwd();
3382
- const projectDir = getProjectDir(cwd);
3383
- return getSessionFilesLite(projectDir, undefined, cwd);
3384
- }
3385
- // On Windows, drive letter case can differ between git worktree list
3386
- // output (e.g. C:/Users/...) and how paths were stored in project
3387
- // directories (e.g. c:/Users/...). Use case-insensitive comparison.
3388
- const caseInsensitive = process.platform === 'win32';
3389
- // Sort worktree paths by sanitized prefix length (longest first) so
3390
- // more specific matches take priority over shorter ones. Without this,
3391
- // a short prefix like -code-myrepo could match -code-myrepo-worktree1
3392
- // before the longer, more specific prefix gets a chance.
3393
- const indexed = worktreePaths.map(wt => {
3394
- const sanitized = sanitizePath(wt);
3395
- return {
3396
- path: wt,
3397
- prefix: caseInsensitive ? sanitized.toLowerCase() : sanitized,
3398
- };
3399
- });
3400
- indexed.sort((a, b) => b.prefix.length - a.prefix.length);
3401
- const allLogs = [];
3402
- const seenDirs = new Set();
3403
- let allDirents;
3404
- try {
3405
- allDirents = await readdir(projectsDir, { withFileTypes: true });
3406
- }
3407
- catch (e) {
3408
- // Fall back to current project
3409
- logForDebugging(`Failed to read projects dir ${projectsDir}, falling back to current project: ${e}`);
3410
- const projectDir = getProjectDir(getOriginalCwd());
3411
- return getSessionFilesLite(projectDir, limit, getOriginalCwd());
3412
- }
3413
- for (const dirent of allDirents) {
3414
- if (!dirent.isDirectory())
3415
- continue;
3416
- const dirName = caseInsensitive ? dirent.name.toLowerCase() : dirent.name;
3417
- if (seenDirs.has(dirName))
3418
- continue;
3419
- for (const { path: wtPath, prefix } of indexed) {
3420
- if (dirName === prefix || dirName.startsWith(prefix + '-')) {
3421
- seenDirs.add(dirName);
3422
- allLogs.push(...(await getSessionFilesLite(join(projectsDir, dirent.name), undefined, wtPath)));
3423
- break;
3424
- }
3425
- }
3426
- }
3427
- // Deduplicate by sessionId — the same session can appear in multiple
3428
- // worktree project dirs. Keep the entry with the newest modified time.
3429
- return deduplicateLogsBySessionId(allLogs);
3430
- }
3431
- /**
3432
- * Retrieves the transcript for a specific agent by agentId.
3433
- * Directly loads the agent-specific transcript file.
3434
- * @param agentId The agent ID to search for
3435
- * @returns The conversation chain and budget replacement records for the agent,
3436
- * or null if not found
3437
- */
3438
- export async function getAgentTranscript(agentId) {
3439
- const agentFile = getAgentTranscriptPath(agentId);
3440
- try {
3441
- const { messages, agentContentReplacements } = await loadTranscriptFile(agentFile);
3442
- // Find messages with matching agentId
3443
- const agentMessages = Array.from(messages.values()).filter(msg => msg.agentId === agentId && msg.isSidechain);
3444
- if (agentMessages.length === 0) {
3445
- return null;
3446
- }
3447
- // Find the most recent leaf message with this agentId
3448
- const parentUuids = new Set(agentMessages.map(msg => msg.parentUuid));
3449
- const leafMessage = findLatestMessage(agentMessages, msg => !parentUuids.has(msg.uuid));
3450
- if (!leafMessage) {
3451
- return null;
3452
- }
3453
- // Build the conversation chain
3454
- const transcript = buildConversationChain(messages, leafMessage);
3455
- // Filter to only include messages with this agentId
3456
- const agentTranscript = transcript.filter(msg => msg.agentId === agentId);
3457
- return {
3458
- // Convert TranscriptMessage[] to Message[]
3459
- messages: agentTranscript.map(({ isSidechain, parentUuid, ...msg }) => msg),
3460
- contentReplacements: agentContentReplacements.get(agentId) ?? [],
3461
- };
3462
- }
3463
- catch {
3464
- return null;
3465
- }
3466
- }
3467
- /**
3468
- * Extract agent IDs from progress messages in the conversation.
3469
- * Agent/skill progress messages have type 'progress' with data.type
3470
- * 'agent_progress' or 'skill_progress' and data.agentId.
3471
- * This captures sync agents that emit progress messages during execution.
3472
- */
3473
- export function extractAgentIdsFromMessages(messages) {
3474
- const agentIds = [];
3475
- for (const message of messages) {
3476
- if (message.type === 'progress' &&
3477
- message.data &&
3478
- typeof message.data === 'object' &&
3479
- 'type' in message.data &&
3480
- (message.data.type === 'agent_progress' ||
3481
- message.data.type === 'skill_progress') &&
3482
- 'agentId' in message.data &&
3483
- typeof message.data.agentId === 'string') {
3484
- agentIds.push(message.data.agentId);
3485
- }
3486
- }
3487
- return uniq(agentIds);
3488
- }
3489
- /**
3490
- * Extract teammate transcripts directly from AppState tasks.
3491
- * In-process teammates store their messages in task.messages,
3492
- * which is more reliable than loading from disk since each teammate turn
3493
- * uses a random agentId for transcript storage.
3494
- */
3495
- export function extractTeammateTranscriptsFromTasks(tasks) {
3496
- const transcripts = {};
3497
- for (const task of Object.values(tasks)) {
3498
- if (task.type === 'in_process_teammate' &&
3499
- task.identity?.agentId &&
3500
- task.messages &&
3501
- task.messages.length > 0) {
3502
- transcripts[task.identity.agentId] = task.messages;
3503
- }
3504
- }
3505
- return transcripts;
3506
- }
3507
- /**
3508
- * Load subagent transcripts for the given agent IDs
3509
- */
3510
- export async function loadSubagentTranscripts(agentIds) {
3511
- const results = await Promise.all(agentIds.map(async (agentId) => {
3512
- try {
3513
- const result = await getAgentTranscript(asAgentId(agentId));
3514
- if (result && result.messages.length > 0) {
3515
- return { agentId, transcript: result.messages };
3516
- }
3517
- return null;
3518
- }
3519
- catch {
3520
- // Skip if transcript can't be loaded
3521
- return null;
3522
- }
3523
- }));
3524
- const transcripts = {};
3525
- for (const result of results) {
3526
- if (result) {
3527
- transcripts[result.agentId] = result.transcript;
3528
- }
3529
- }
3530
- return transcripts;
3531
- }
3532
- // Globs the session's subagents dir directly — unlike AppState.tasks, this survives task eviction.
3533
- export async function loadAllSubagentTranscriptsFromDisk() {
3534
- const subagentsDir = join(getSessionProjectDir() ?? getProjectDir(getOriginalCwd()), getSessionId(), 'subagents');
3535
- let entries;
3536
- try {
3537
- entries = await readdir(subagentsDir, { withFileTypes: true });
3538
- }
3539
- catch {
3540
- return {};
3541
- }
3542
- // Filename format is the inverse of getAgentTranscriptPath() — keep in sync.
3543
- const agentIds = entries
3544
- .filter(d => d.isFile() && d.name.startsWith('agent-') && d.name.endsWith('.jsonl'))
3545
- .map(d => d.name.slice('agent-'.length, -'.jsonl'.length));
3546
- return loadSubagentTranscripts(agentIds);
3547
- }
3548
- // Exported so useLogMessages can sync-compute the last loggable uuid
3549
- // without awaiting recordTranscript's return value (race-free hint tracking).
3550
- export function isLoggableMessage(m) {
3551
- if (m.type === 'progress')
3552
- return false;
3553
- // IMPORTANT: We deliberately filter out most attachments for non-ants because
3554
- // they have sensitive info for training that we don't want exposed to the public.
3555
- // When enabled, we allow hook_additional_context through since it contains
3556
- // user-configured hook output that is useful for session context on resume.
3557
- if (m.type === 'attachment' && getUserType() !== 'ant') {
3558
- if (m.attachment.type === 'hook_additional_context' &&
3559
- isEnvTruthy(process.env.CLAUDE_CODE_SAVE_HOOK_ADDITIONAL_CONTEXT)) {
3560
- return true;
3561
- }
3562
- return false;
3563
- }
3564
- return true;
3565
- }
3566
- function collectReplIds(messages) {
3567
- const ids = new Set();
3568
- for (const m of messages) {
3569
- if (m.type === 'assistant' && Array.isArray(m.message.content)) {
3570
- for (const b of m.message.content) {
3571
- if (b.type === 'tool_use' && b.name === REPL_TOOL_NAME) {
3572
- ids.add(b.id);
3573
- }
3574
- }
3575
- }
3576
- }
3577
- return ids;
3578
- }
3579
- /**
3580
- * For external users, make REPL invisible in the persisted transcript: strip
3581
- * REPL tool_use/tool_result pairs and promote isVirtual messages to real. On
3582
- * --resume the model then sees a coherent native-tool-call history (assistant
3583
- * called Bash, got result, called Read, got result) without the REPL wrapper.
3584
- * Ant transcripts keep the wrapper so /share training data sees REPL usage.
3585
- *
3586
- * replIds is pre-collected from the FULL session array, not the slice being
3587
- * transformed — recordTranscript receives incremental slices where the REPL
3588
- * tool_use (earlier render) and its tool_result (later render, after async
3589
- * execution) land in separate calls. A fresh per-call Set would miss the id
3590
- * and leave an orphaned tool_result on disk.
3591
- */
3592
- function transformMessagesForExternalTranscript(messages, replIds) {
3593
- return messages.flatMap(m => {
3594
- if (m.type === 'assistant' && Array.isArray(m.message.content)) {
3595
- const content = m.message.content;
3596
- const hasRepl = content.some(b => b.type === 'tool_use' && b.name === REPL_TOOL_NAME);
3597
- const filtered = hasRepl
3598
- ? content.filter(b => !(b.type === 'tool_use' && b.name === REPL_TOOL_NAME))
3599
- : content;
3600
- if (filtered.length === 0)
3601
- return [];
3602
- if (m.isVirtual) {
3603
- const { isVirtual: _omit, ...rest } = m;
3604
- return [{ ...rest, message: { ...m.message, content: filtered } }];
3605
- }
3606
- if (filtered !== content) {
3607
- return [{ ...m, message: { ...m.message, content: filtered } }];
3608
- }
3609
- return [m];
3610
- }
3611
- if (m.type === 'user' && Array.isArray(m.message.content)) {
3612
- const content = m.message.content;
3613
- const hasRepl = content.some(b => b.type === 'tool_result' && replIds.has(b.tool_use_id));
3614
- const filtered = hasRepl
3615
- ? content.filter(b => !(b.type === 'tool_result' && replIds.has(b.tool_use_id)))
3616
- : content;
3617
- if (filtered.length === 0)
3618
- return [];
3619
- if (m.isVirtual) {
3620
- const { isVirtual: _omit, ...rest } = m;
3621
- return [{ ...rest, message: { ...m.message, content: filtered } }];
3622
- }
3623
- if (filtered !== content) {
3624
- return [{ ...m, message: { ...m.message, content: filtered } }];
3625
- }
3626
- return [m];
3627
- }
3628
- // string-content user, system, attachment
3629
- if ('isVirtual' in m && m.isVirtual) {
3630
- const { isVirtual: _omit, ...rest } = m;
3631
- return [rest];
3632
- }
3633
- return [m];
3634
- });
3635
- }
3636
- export function cleanMessagesForLogging(messages, allMessages = messages) {
3637
- const filtered = messages.filter(isLoggableMessage);
3638
- return getUserType() !== 'ant'
3639
- ? transformMessagesForExternalTranscript(filtered, collectReplIds(allMessages))
3640
- : filtered;
3641
- }
3642
- /**
3643
- * Gets a log by its index
3644
- * @param index Index in the sorted list of logs (0-based)
3645
- * @returns Log data or null if not found
3646
- */
3647
- export async function getLogByIndex(index) {
3648
- const logs = await loadMessageLogs();
3649
- return logs[index] || null;
3650
- }
3651
- /**
3652
- * Looks up unresolved tool uses in the transcript by tool_use_id.
3653
- * Returns the assistant message containing the tool_use, or null if not found
3654
- * or the tool call already has a tool_result.
3655
- */
3656
- export async function findUnresolvedToolUse(toolUseId) {
3657
- try {
3658
- const transcriptPath = getTranscriptPath();
3659
- const { messages } = await loadTranscriptFile(transcriptPath);
3660
- let toolUseMessage = null;
3661
- // Find the tool use but make sure there's not also a result
3662
- for (const message of messages.values()) {
3663
- if (message.type === 'assistant') {
3664
- const content = message.message.content;
3665
- if (Array.isArray(content)) {
3666
- for (const block of content) {
3667
- if (block.type === 'tool_use' && block.id === toolUseId) {
3668
- toolUseMessage = message;
3669
- break;
3670
- }
3671
- }
3672
- }
3673
- }
3674
- else if (message.type === 'user') {
3675
- const content = message.message.content;
3676
- if (Array.isArray(content)) {
3677
- for (const block of content) {
3678
- if (block.type === 'tool_result' &&
3679
- block.tool_use_id === toolUseId) {
3680
- // Found tool result, bail out
3681
- return null;
3682
- }
3683
- }
3684
- }
3685
- }
3686
- }
3687
- return toolUseMessage;
3688
- }
3689
- catch {
3690
- return null;
3691
- }
3692
- }
3693
- /**
3694
- * Gets all session JSONL files in a project directory with their stats.
3695
- * Returns a map of sessionId → {path, mtime, ctime, size}.
3696
- * Stats are batched via Promise.all to avoid serial syscalls in the hot loop.
3697
- */
3698
- export async function getSessionFilesWithMtime(projectDir) {
3699
- const sessionFilesMap = new Map();
3700
- let dirents;
3701
- try {
3702
- dirents = await readdir(projectDir, { withFileTypes: true });
3703
- }
3704
- catch {
3705
- // Directory doesn't exist - return empty map
3706
- return sessionFilesMap;
3707
- }
3708
- const candidates = [];
3709
- for (const dirent of dirents) {
3710
- if (!dirent.isFile() || !dirent.name.endsWith('.jsonl'))
3711
- continue;
3712
- const sessionId = validateUuid(basename(dirent.name, '.jsonl'));
3713
- if (!sessionId)
3714
- continue;
3715
- candidates.push({ sessionId, filePath: join(projectDir, dirent.name) });
3716
- }
3717
- await Promise.all(candidates.map(async ({ sessionId, filePath }) => {
3718
- try {
3719
- const st = await stat(filePath);
3720
- sessionFilesMap.set(sessionId, {
3721
- path: filePath,
3722
- mtime: st.mtime.getTime(),
3723
- ctime: st.birthtime.getTime(),
3724
- size: st.size,
3725
- });
3726
- }
3727
- catch {
3728
- logForDebugging(`Failed to stat session file: ${filePath}`);
3729
- }
3730
- }));
3731
- return sessionFilesMap;
3732
- }
3733
- /**
3734
- * Number of sessions to enrich on the initial load of the resume picker.
3735
- * Each enrichment reads up to 128 KB per file (head + tail), so 50 sessions
3736
- * means ~6.4 MB of I/O — fast on any modern filesystem while giving users
3737
- * a much better initial view than the previous default of 10.
3738
- */
3739
- const INITIAL_ENRICH_COUNT = 50;
3740
- /**
3741
- * Loads all logs from a single session file with full message data.
3742
- * Builds a LogOption for each leaf message in the file.
3743
- */
3744
- export async function loadAllLogsFromSessionFile(sessionFile, projectPathOverride) {
3745
- const { messages, summaries, customTitles, tags, agentNames, agentColors, agentSettings, prNumbers, prUrls, prRepositories, modes, fileHistorySnapshots, attributionSnapshots, contentReplacements, leafUuids, } = await loadTranscriptFile(sessionFile, { keepAllLeaves: true });
3746
- if (messages.size === 0)
3747
- return [];
3748
- const leafMessages = [];
3749
- // Build parentUuid → children index once (O(n)), so trailing-message lookup is O(1) per leaf
3750
- const childrenByParent = new Map();
3751
- for (const msg of messages.values()) {
3752
- if (leafUuids.has(msg.uuid)) {
3753
- leafMessages.push(msg);
3754
- }
3755
- else if (msg.parentUuid) {
3756
- const siblings = childrenByParent.get(msg.parentUuid);
3757
- if (siblings) {
3758
- siblings.push(msg);
3759
- }
3760
- else {
3761
- childrenByParent.set(msg.parentUuid, [msg]);
3762
- }
3763
- }
3764
- }
3765
- const logs = [];
3766
- for (const leafMessage of leafMessages) {
3767
- const chain = buildConversationChain(messages, leafMessage);
3768
- if (chain.length === 0)
3769
- continue;
3770
- // Append trailing messages that are children of the leaf
3771
- const trailingMessages = childrenByParent.get(leafMessage.uuid);
3772
- if (trailingMessages) {
3773
- // ISO-8601 UTC timestamps are lexically sortable
3774
- trailingMessages.sort((a, b) => a.timestamp < b.timestamp ? -1 : a.timestamp > b.timestamp ? 1 : 0);
3775
- chain.push(...trailingMessages);
3776
- }
3777
- const firstMessage = chain[0];
3778
- const sessionId = leafMessage.sessionId;
3779
- logs.push({
3780
- date: leafMessage.timestamp,
3781
- messages: removeExtraFields(chain),
3782
- fullPath: sessionFile,
3783
- value: 0,
3784
- created: new Date(firstMessage.timestamp),
3785
- modified: new Date(leafMessage.timestamp),
3786
- firstPrompt: extractFirstPrompt(chain),
3787
- messageCount: countVisibleMessages(chain),
3788
- isSidechain: firstMessage.isSidechain ?? false,
3789
- sessionId,
3790
- leafUuid: leafMessage.uuid,
3791
- summary: summaries.get(leafMessage.uuid),
3792
- customTitle: customTitles.get(sessionId),
3793
- tag: tags.get(sessionId),
3794
- agentName: agentNames.get(sessionId),
3795
- agentColor: agentColors.get(sessionId),
3796
- agentSetting: agentSettings.get(sessionId),
3797
- mode: modes.get(sessionId),
3798
- prNumber: prNumbers.get(sessionId),
3799
- prUrl: prUrls.get(sessionId),
3800
- prRepository: prRepositories.get(sessionId),
3801
- gitBranch: leafMessage.gitBranch,
3802
- projectPath: projectPathOverride ?? firstMessage.cwd,
3803
- fileHistorySnapshots: buildFileHistorySnapshotChain(fileHistorySnapshots, chain),
3804
- attributionSnapshots: buildAttributionSnapshotChain(attributionSnapshots, chain),
3805
- contentReplacements: contentReplacements.get(sessionId) ?? [],
3806
- });
3807
- }
3808
- return logs;
3809
- }
3810
- /**
3811
- * Gets logs by loading all session files fully, bypassing the session index.
3812
- * Use this when you need full message data (e.g., for /insights analysis).
3813
-
3814
- */
3815
- async function getLogsWithoutIndex(projectDir, limit) {
3816
- const sessionFilesMap = await getSessionFilesWithMtime(projectDir);
3817
- if (sessionFilesMap.size === 0)
3818
- return [];
3819
- // If limit specified, only load N most recent files by mtime
3820
- let filesToProcess;
3821
- if (limit && sessionFilesMap.size > limit) {
3822
- filesToProcess = [...sessionFilesMap.values()]
3823
- .sort((a, b) => b.mtime - a.mtime)
3824
- .slice(0, limit);
3825
- }
3826
- else {
3827
- filesToProcess = [...sessionFilesMap.values()];
3828
- }
3829
- const logs = [];
3830
- for (const fileInfo of filesToProcess) {
3831
- try {
3832
- const fileLogOptions = await loadAllLogsFromSessionFile(fileInfo.path);
3833
- logs.push(...fileLogOptions);
3834
- }
3835
- catch {
3836
- logForDebugging(`Failed to load session file: ${fileInfo.path}`);
3837
- }
3838
- }
3839
- return logs;
3840
- }
3841
- /**
3842
- * Reads the first and last ~64KB of a JSONL file and extracts lite metadata.
3843
- *
3844
- * Head (first 64KB): isSidechain, projectPath, teamName, firstPrompt.
3845
- * Tail (last 64KB): customTitle, tag, PR link, latest gitBranch.
3846
- *
3847
- * Accepts a shared buffer to avoid per-file allocation overhead.
3848
- */
3849
- async function readLiteMetadata(filePath, fileSize, buf) {
3850
- const { head, tail } = await readHeadAndTail(filePath, fileSize, buf);
3851
- if (!head)
3852
- return { firstPrompt: '', isSidechain: false };
3853
- // Extract stable metadata from the first line via string search.
3854
- // Works even when the first line is truncated (>64KB message).
3855
- const isSidechain = head.includes('"isSidechain":true') || head.includes('"isSidechain": true');
3856
- const projectPath = extractJsonStringField(head, 'cwd');
3857
- const teamName = extractJsonStringField(head, 'teamName');
3858
- const agentSetting = extractJsonStringField(head, 'agentSetting');
3859
- // Prefer the last-prompt tail entry — captured by extractFirstPrompt at
3860
- // write time (filtered, authoritative) and shows what the user was most
3861
- // recently doing. Head scan is the fallback for sessions written before
3862
- // last-prompt entries existed. Raw string scrapes of head are last resort
3863
- // and catch array-format content blocks (VS Code <ide_selection> metadata).
3864
- const firstPrompt = extractLastJsonStringField(tail, 'lastPrompt') ||
3865
- extractFirstPromptFromChunk(head) ||
3866
- extractJsonStringFieldPrefix(head, 'content', 200) ||
3867
- extractJsonStringFieldPrefix(head, 'text', 200) ||
3868
- '';
3869
- // Extract tail metadata via string search (last occurrence wins).
3870
- // User titles (customTitle field, from custom-title entries) win over
3871
- // AI titles (aiTitle field, from ai-title entries). The distinct field
3872
- // names mean extractLastJsonStringField naturally disambiguates.
3873
- const customTitle = extractLastJsonStringField(tail, 'customTitle') ??
3874
- extractLastJsonStringField(head, 'customTitle') ??
3875
- extractLastJsonStringField(tail, 'aiTitle') ??
3876
- extractLastJsonStringField(head, 'aiTitle');
3877
- const summary = extractLastJsonStringField(tail, 'summary');
3878
- const tag = extractLastJsonStringField(tail, 'tag');
3879
- const gitBranch = extractLastJsonStringField(tail, 'gitBranch') ??
3880
- extractJsonStringField(head, 'gitBranch');
3881
- // PR link fields — prNumber is a number not a string, so try both
3882
- const prUrl = extractLastJsonStringField(tail, 'prUrl');
3883
- const prRepository = extractLastJsonStringField(tail, 'prRepository');
3884
- let prNumber;
3885
- const prNumStr = extractLastJsonStringField(tail, 'prNumber');
3886
- if (prNumStr) {
3887
- prNumber = parseInt(prNumStr, 10) || undefined;
3888
- }
3889
- if (!prNumber) {
3890
- const prNumMatch = tail.lastIndexOf('"prNumber":');
3891
- if (prNumMatch >= 0) {
3892
- const afterColon = tail.slice(prNumMatch + 11, prNumMatch + 25);
3893
- const num = parseInt(afterColon.trim(), 10);
3894
- if (num > 0)
3895
- prNumber = num;
3896
- }
3897
- }
3898
- return {
3899
- firstPrompt,
3900
- gitBranch,
3901
- isSidechain,
3902
- projectPath,
3903
- teamName,
3904
- customTitle,
3905
- summary,
3906
- tag,
3907
- agentSetting,
3908
- prNumber,
3909
- prUrl,
3910
- prRepository,
3911
- };
3912
- }
3913
- /**
3914
- * Scans a chunk of text for the first meaningful user prompt.
3915
- */
3916
- function extractFirstPromptFromChunk(chunk) {
3917
- let start = 0;
3918
- let hasTickMessages = false;
3919
- let firstCommandFallback = '';
3920
- while (start < chunk.length) {
3921
- const newlineIdx = chunk.indexOf('\n', start);
3922
- const line = newlineIdx >= 0 ? chunk.slice(start, newlineIdx) : chunk.slice(start);
3923
- start = newlineIdx >= 0 ? newlineIdx + 1 : chunk.length;
3924
- if (!line.includes('"type":"user"') && !line.includes('"type": "user"')) {
3925
- continue;
3926
- }
3927
- if (line.includes('"tool_result"'))
3928
- continue;
3929
- if (line.includes('"isMeta":true') || line.includes('"isMeta": true'))
3930
- continue;
3931
- try {
3932
- const entry = jsonParse(line);
3933
- if (entry.type !== 'user')
3934
- continue;
3935
- const message = entry.message;
3936
- if (!message)
3937
- continue;
3938
- const content = message.content;
3939
- // Collect all text values from the message content. For array content
3940
- // (common in VS Code where IDE metadata tags come before the user's
3941
- // actual prompt), iterate all text blocks so we don't miss the real
3942
- // prompt hidden behind <ide_selection>/<ide_opened_file> blocks.
3943
- const texts = [];
3944
- if (typeof content === 'string') {
3945
- texts.push(content);
3946
- }
3947
- else if (Array.isArray(content)) {
3948
- for (const block of content) {
3949
- const b = block;
3950
- if (b.type === 'text' && typeof b.text === 'string') {
3951
- texts.push(b.text);
3952
- }
3953
- }
3954
- }
3955
- for (const text of texts) {
3956
- if (!text)
3957
- continue;
3958
- let result = text.replace(/\n/g, ' ').trim();
3959
- // Skip command messages (slash commands) but remember the first one
3960
- // as a fallback title. Matches skip logic in
3961
- // getFirstMeaningfulUserMessageTextContent, but instead of discarding
3962
- // command messages entirely, we format them cleanly (e.g. "/clear")
3963
- // so the session still appears in the resume picker.
3964
- const commandNameTag = extractTag(result, COMMAND_NAME_TAG);
3965
- if (commandNameTag) {
3966
- const name = commandNameTag.replace(/^\//, '');
3967
- const commandArgs = extractTag(result, 'command-args')?.trim() || '';
3968
- if (builtInCommandNames().has(name) || !commandArgs) {
3969
- if (!firstCommandFallback) {
3970
- firstCommandFallback = commandNameTag;
3971
- }
3972
- continue;
3973
- }
3974
- // Custom command with meaningful args — use clean display
3975
- return commandArgs
3976
- ? `${commandNameTag} ${commandArgs}`
3977
- : commandNameTag;
3978
- }
3979
- // Format bash input with ! prefix before the generic XML skip
3980
- const bashInput = extractTag(result, 'bash-input');
3981
- if (bashInput)
3982
- return `! ${bashInput}`;
3983
- if (SKIP_FIRST_PROMPT_PATTERN.test(result)) {
3984
- if ((feature('PROACTIVE') || feature('KAIROS')) &&
3985
- result.startsWith(`<${TICK_TAG}>`))
3986
- hasTickMessages = true;
3987
- continue;
3988
- }
3989
- if (result.length > 200) {
3990
- result = result.slice(0, 200).trim() + '…';
3991
- }
3992
- return result;
3993
- }
3994
- }
3995
- catch {
3996
- continue;
3997
- }
3998
- }
3999
- // Session started with a slash command but had no subsequent real message —
4000
- // use the clean command name so the session still appears in the resume picker
4001
- if (firstCommandFallback)
4002
- return firstCommandFallback;
4003
- // Proactive sessions have only tick messages — give them a synthetic prompt
4004
- // so they're not filtered out by enrichLogs
4005
- if ((feature('PROACTIVE') || feature('KAIROS')) && hasTickMessages)
4006
- return 'Proactive session';
4007
- return '';
4008
- }
4009
- /**
4010
- * Like extractJsonStringField but returns the first `maxLen` characters of the
4011
- * value even when the closing quote is missing (truncated buffer). Newline
4012
- * escapes are replaced with spaces and the result is trimmed.
4013
- */
4014
- function extractJsonStringFieldPrefix(text, key, maxLen) {
4015
- const patterns = [`"${key}":"`, `"${key}": "`];
4016
- for (const pattern of patterns) {
4017
- const idx = text.indexOf(pattern);
4018
- if (idx < 0)
4019
- continue;
4020
- const valueStart = idx + pattern.length;
4021
- // Grab up to maxLen characters from the value, stopping at closing quote
4022
- let i = valueStart;
4023
- let collected = 0;
4024
- while (i < text.length && collected < maxLen) {
4025
- if (text[i] === '\\') {
4026
- i += 2; // skip escaped char
4027
- collected++;
4028
- continue;
4029
- }
4030
- if (text[i] === '"')
4031
- break;
4032
- i++;
4033
- collected++;
4034
- }
4035
- const raw = text.slice(valueStart, i);
4036
- return raw.replace(/\\n/g, ' ').replace(/\\t/g, ' ').trim();
4037
- }
4038
- return '';
4039
- }
4040
- /**
4041
- * Deduplicates logs by sessionId, keeping the entry with the newest
4042
- * modified time. Returns sorted logs with sequential value indices.
4043
- */
4044
- function deduplicateLogsBySessionId(logs) {
4045
- const deduped = new Map();
4046
- for (const log of logs) {
4047
- if (!log.sessionId)
4048
- continue;
4049
- const existing = deduped.get(log.sessionId);
4050
- if (!existing || log.modified.getTime() > existing.modified.getTime()) {
4051
- deduped.set(log.sessionId, log);
4052
- }
4053
- }
4054
- return sortLogs([...deduped.values()]).map((log, i) => ({
4055
- ...log,
4056
- value: i,
4057
- }));
4058
- }
4059
- /**
4060
- * Returns lite LogOption[] from pure filesystem metadata (stat only).
4061
- * No file reads — instant. Call `enrichLogs` to enrich
4062
- * visible sessions with firstPrompt, gitBranch, customTitle, etc.
4063
- */
4064
- export async function getSessionFilesLite(projectDir, limit, projectPath) {
4065
- const sessionFilesMap = await getSessionFilesWithMtime(projectDir);
4066
- // Sort by mtime descending and apply limit
4067
- let entries = [...sessionFilesMap.entries()].sort((a, b) => b[1].mtime - a[1].mtime);
4068
- if (limit && entries.length > limit) {
4069
- entries = entries.slice(0, limit);
4070
- }
4071
- const logs = [];
4072
- for (const [sessionId, fileInfo] of entries) {
4073
- logs.push({
4074
- date: new Date(fileInfo.mtime).toISOString(),
4075
- messages: [],
4076
- isLite: true,
4077
- fullPath: fileInfo.path,
4078
- value: 0,
4079
- created: new Date(fileInfo.ctime),
4080
- modified: new Date(fileInfo.mtime),
4081
- firstPrompt: '',
4082
- messageCount: 0,
4083
- fileSize: fileInfo.size,
4084
- isSidechain: false,
4085
- sessionId,
4086
- projectPath,
4087
- });
4088
- }
4089
- // logs are freshly pushed above — safe to mutate in place
4090
- const sorted = sortLogs(logs);
4091
- sorted.forEach((log, i) => {
4092
- log.value = i;
4093
- });
4094
- return sorted;
4095
- }
4096
- /**
4097
- * Enriches a lite log with metadata from its JSONL file.
4098
- * Returns the enriched log, or null if the log has no meaningful content
4099
- * (no firstPrompt, no customTitle — e.g., metadata-only session files).
4100
- */
4101
- async function enrichLog(log, readBuf) {
4102
- if (!log.isLite || !log.fullPath)
4103
- return log;
4104
- const meta = await readLiteMetadata(log.fullPath, log.fileSize ?? 0, readBuf);
4105
- const enriched = {
4106
- ...log,
4107
- isLite: false,
4108
- firstPrompt: meta.firstPrompt,
4109
- gitBranch: meta.gitBranch,
4110
- isSidechain: meta.isSidechain,
4111
- teamName: meta.teamName,
4112
- customTitle: meta.customTitle,
4113
- summary: meta.summary,
4114
- tag: meta.tag,
4115
- agentSetting: meta.agentSetting,
4116
- prNumber: meta.prNumber,
4117
- prUrl: meta.prUrl,
4118
- prRepository: meta.prRepository,
4119
- projectPath: meta.projectPath ?? log.projectPath,
4120
- };
4121
- // Provide a fallback title for sessions where we couldn't extract the first
4122
- // prompt (e.g., large first messages that exceed the 16KB read buffer).
4123
- // Previously these sessions were silently dropped, making them inaccessible
4124
- // via /resume after crashes or large-context sessions.
4125
- if (!enriched.firstPrompt && !enriched.customTitle) {
4126
- enriched.firstPrompt = '(session)';
4127
- }
4128
- // Filter: skip sidechains and agent sessions
4129
- if (enriched.isSidechain) {
4130
- logForDebugging(`Session ${log.sessionId} filtered from /resume: isSidechain=true`);
4131
- return null;
4132
- }
4133
- if (enriched.teamName) {
4134
- logForDebugging(`Session ${log.sessionId} filtered from /resume: teamName=${enriched.teamName}`);
4135
- return null;
4136
- }
4137
- return enriched;
4138
- }
4139
- /**
4140
- * Enriches enough lite logs from `allLogs` (starting at `startIndex`) to
4141
- * produce `count` valid results. Returns the valid enriched logs and the
4142
- * index where scanning stopped (for progressive loading to continue from).
4143
- */
4144
- export async function enrichLogs(allLogs, startIndex, count) {
4145
- const result = [];
4146
- const readBuf = Buffer.alloc(LITE_READ_BUF_SIZE);
4147
- let i = startIndex;
4148
- while (i < allLogs.length && result.length < count) {
4149
- const log = allLogs[i];
4150
- i++;
4151
- const enriched = await enrichLog(log, readBuf);
4152
- if (enriched) {
4153
- result.push(enriched);
4154
- }
4155
- }
4156
- const scanned = i - startIndex;
4157
- const filtered = scanned - result.length;
4158
- if (filtered > 0) {
4159
- logForDebugging(`/resume: enriched ${scanned} sessions, ${filtered} filtered out, ${result.length} visible (${allLogs.length - i} remaining on disk)`);
4160
- }
4161
- return { logs: result, nextIndex: i };
4162
- }