ashishcode 0.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (1936) hide show
  1. package/README.md +189 -0
  2. package/bun.lock +895 -0
  3. package/package.json +109 -0
  4. package/public/claude-files.png +0 -0
  5. package/public/leak-tweet.png +0 -0
  6. package/scripts/ashishcode.mjs +41 -0
  7. package/scripts/claude-local.mjs +41 -0
  8. package/src/QueryEngine.ts +1295 -0
  9. package/src/Task.ts +125 -0
  10. package/src/Tool.ts +792 -0
  11. package/src/assistant/sessionHistory.ts +87 -0
  12. package/src/bootstrap/state.ts +1758 -0
  13. package/src/bridge/bridgeApi.ts +539 -0
  14. package/src/bridge/bridgeConfig.ts +48 -0
  15. package/src/bridge/bridgeDebug.ts +135 -0
  16. package/src/bridge/bridgeEnabled.ts +203 -0
  17. package/src/bridge/bridgeMain.ts +3000 -0
  18. package/src/bridge/bridgeMessaging.ts +461 -0
  19. package/src/bridge/bridgePermissionCallbacks.ts +43 -0
  20. package/src/bridge/bridgePointer.ts +210 -0
  21. package/src/bridge/bridgeStatusUtil.ts +163 -0
  22. package/src/bridge/bridgeUI.ts +531 -0
  23. package/src/bridge/capacityWake.ts +56 -0
  24. package/src/bridge/codeSessionApi.ts +168 -0
  25. package/src/bridge/createSession.ts +384 -0
  26. package/src/bridge/debugUtils.ts +141 -0
  27. package/src/bridge/envLessBridgeConfig.ts +166 -0
  28. package/src/bridge/flushGate.ts +71 -0
  29. package/src/bridge/inboundAttachments.ts +175 -0
  30. package/src/bridge/inboundMessages.ts +80 -0
  31. package/src/bridge/initReplBridge.ts +569 -0
  32. package/src/bridge/jwtUtils.ts +256 -0
  33. package/src/bridge/pollConfig.ts +110 -0
  34. package/src/bridge/pollConfigDefaults.ts +82 -0
  35. package/src/bridge/remoteBridgeCore.ts +1008 -0
  36. package/src/bridge/replBridge.ts +2407 -0
  37. package/src/bridge/replBridgeHandle.ts +36 -0
  38. package/src/bridge/replBridgeTransport.ts +370 -0
  39. package/src/bridge/sessionIdCompat.ts +57 -0
  40. package/src/bridge/sessionRunner.ts +550 -0
  41. package/src/bridge/trustedDevice.ts +210 -0
  42. package/src/bridge/types.ts +262 -0
  43. package/src/bridge/workSecret.ts +127 -0
  44. package/src/buddy/CompanionSprite.tsx +371 -0
  45. package/src/buddy/companion.ts +133 -0
  46. package/src/buddy/prompt.ts +36 -0
  47. package/src/buddy/sprites.ts +514 -0
  48. package/src/buddy/types.ts +148 -0
  49. package/src/buddy/useBuddyNotification.tsx +98 -0
  50. package/src/cli/exit.ts +31 -0
  51. package/src/cli/handlers/agents.ts +70 -0
  52. package/src/cli/handlers/auth.ts +482 -0
  53. package/src/cli/handlers/autoMode.ts +170 -0
  54. package/src/cli/handlers/mcp.tsx +362 -0
  55. package/src/cli/handlers/plugins.ts +878 -0
  56. package/src/cli/handlers/util.tsx +110 -0
  57. package/src/cli/ndjsonSafeStringify.ts +32 -0
  58. package/src/cli/print.ts +5594 -0
  59. package/src/cli/remoteIO.ts +255 -0
  60. package/src/cli/structuredIO.ts +859 -0
  61. package/src/cli/transports/HybridTransport.ts +282 -0
  62. package/src/cli/transports/SSETransport.ts +711 -0
  63. package/src/cli/transports/SerialBatchEventUploader.ts +275 -0
  64. package/src/cli/transports/WebSocketTransport.ts +800 -0
  65. package/src/cli/transports/WorkerStateUploader.ts +131 -0
  66. package/src/cli/transports/ccrClient.ts +998 -0
  67. package/src/cli/transports/transportUtils.ts +45 -0
  68. package/src/cli/update.ts +423 -0
  69. package/src/commands/add-dir/add-dir.tsx +126 -0
  70. package/src/commands/add-dir/index.ts +11 -0
  71. package/src/commands/add-dir/validation.ts +110 -0
  72. package/src/commands/advisor.ts +109 -0
  73. package/src/commands/agents/agents.tsx +12 -0
  74. package/src/commands/agents/index.ts +10 -0
  75. package/src/commands/ant-trace/index.js +1 -0
  76. package/src/commands/autofix-pr/index.js +1 -0
  77. package/src/commands/backfill-sessions/index.js +1 -0
  78. package/src/commands/branch/branch.ts +296 -0
  79. package/src/commands/branch/index.ts +14 -0
  80. package/src/commands/break-cache/index.js +1 -0
  81. package/src/commands/bridge/bridge.tsx +509 -0
  82. package/src/commands/bridge/index.ts +26 -0
  83. package/src/commands/bridge-kick.ts +200 -0
  84. package/src/commands/brief.ts +130 -0
  85. package/src/commands/btw/btw.tsx +243 -0
  86. package/src/commands/btw/index.ts +13 -0
  87. package/src/commands/bughunter/index.js +1 -0
  88. package/src/commands/chrome/chrome.tsx +285 -0
  89. package/src/commands/chrome/index.ts +13 -0
  90. package/src/commands/clear/caches.ts +144 -0
  91. package/src/commands/clear/clear.ts +7 -0
  92. package/src/commands/clear/conversation.ts +251 -0
  93. package/src/commands/clear/index.ts +19 -0
  94. package/src/commands/color/color.ts +93 -0
  95. package/src/commands/color/index.ts +16 -0
  96. package/src/commands/commit-push-pr.ts +158 -0
  97. package/src/commands/commit.ts +92 -0
  98. package/src/commands/compact/compact.ts +287 -0
  99. package/src/commands/compact/index.ts +15 -0
  100. package/src/commands/config/config.tsx +7 -0
  101. package/src/commands/config/index.ts +11 -0
  102. package/src/commands/context/context-noninteractive.ts +325 -0
  103. package/src/commands/context/context.tsx +64 -0
  104. package/src/commands/context/index.ts +24 -0
  105. package/src/commands/copy/copy.tsx +371 -0
  106. package/src/commands/copy/index.ts +15 -0
  107. package/src/commands/cost/cost.ts +24 -0
  108. package/src/commands/cost/index.ts +23 -0
  109. package/src/commands/createMovedToPluginCommand.ts +65 -0
  110. package/src/commands/ctx_viz/index.js +1 -0
  111. package/src/commands/debug-tool-call/index.js +1 -0
  112. package/src/commands/desktop/desktop.tsx +9 -0
  113. package/src/commands/desktop/index.ts +26 -0
  114. package/src/commands/diff/diff.tsx +9 -0
  115. package/src/commands/diff/index.ts +8 -0
  116. package/src/commands/doctor/doctor.tsx +7 -0
  117. package/src/commands/doctor/index.ts +12 -0
  118. package/src/commands/effort/effort.tsx +183 -0
  119. package/src/commands/effort/index.ts +13 -0
  120. package/src/commands/env/index.js +1 -0
  121. package/src/commands/exit/exit.tsx +33 -0
  122. package/src/commands/exit/index.ts +12 -0
  123. package/src/commands/export/export.tsx +91 -0
  124. package/src/commands/export/index.ts +11 -0
  125. package/src/commands/extra-usage/extra-usage-core.ts +118 -0
  126. package/src/commands/extra-usage/extra-usage-noninteractive.ts +16 -0
  127. package/src/commands/extra-usage/extra-usage.tsx +17 -0
  128. package/src/commands/extra-usage/index.ts +31 -0
  129. package/src/commands/fast/fast.tsx +269 -0
  130. package/src/commands/fast/index.ts +26 -0
  131. package/src/commands/feedback/feedback.tsx +25 -0
  132. package/src/commands/feedback/index.ts +28 -0
  133. package/src/commands/files/files.ts +19 -0
  134. package/src/commands/files/index.ts +12 -0
  135. package/src/commands/good-claude/index.js +1 -0
  136. package/src/commands/heapdump/heapdump.ts +17 -0
  137. package/src/commands/heapdump/index.ts +12 -0
  138. package/src/commands/help/help.tsx +11 -0
  139. package/src/commands/help/index.ts +10 -0
  140. package/src/commands/hooks/hooks.tsx +13 -0
  141. package/src/commands/hooks/index.ts +11 -0
  142. package/src/commands/ide/ide.tsx +646 -0
  143. package/src/commands/ide/index.ts +11 -0
  144. package/src/commands/init-verifiers.ts +262 -0
  145. package/src/commands/init.ts +256 -0
  146. package/src/commands/insights.ts +3201 -0
  147. package/src/commands/install-github-app/ApiKeyStep.tsx +231 -0
  148. package/src/commands/install-github-app/CheckExistingSecretStep.tsx +190 -0
  149. package/src/commands/install-github-app/CheckGitHubStep.tsx +15 -0
  150. package/src/commands/install-github-app/ChooseRepoStep.tsx +211 -0
  151. package/src/commands/install-github-app/CreatingStep.tsx +65 -0
  152. package/src/commands/install-github-app/ErrorStep.tsx +85 -0
  153. package/src/commands/install-github-app/ExistingWorkflowStep.tsx +103 -0
  154. package/src/commands/install-github-app/InstallAppStep.tsx +94 -0
  155. package/src/commands/install-github-app/OAuthFlowStep.tsx +276 -0
  156. package/src/commands/install-github-app/SuccessStep.tsx +96 -0
  157. package/src/commands/install-github-app/WarningsStep.tsx +73 -0
  158. package/src/commands/install-github-app/index.ts +13 -0
  159. package/src/commands/install-github-app/install-github-app.tsx +587 -0
  160. package/src/commands/install-github-app/setupGitHubActions.ts +325 -0
  161. package/src/commands/install-slack-app/index.ts +12 -0
  162. package/src/commands/install-slack-app/install-slack-app.ts +30 -0
  163. package/src/commands/install.tsx +300 -0
  164. package/src/commands/issue/index.js +1 -0
  165. package/src/commands/keybindings/index.ts +13 -0
  166. package/src/commands/keybindings/keybindings.ts +53 -0
  167. package/src/commands/login/index.ts +14 -0
  168. package/src/commands/login/login.tsx +147 -0
  169. package/src/commands/logout/index.ts +10 -0
  170. package/src/commands/logout/logout.tsx +82 -0
  171. package/src/commands/mcp/addCommand.ts +280 -0
  172. package/src/commands/mcp/index.ts +12 -0
  173. package/src/commands/mcp/mcp.tsx +85 -0
  174. package/src/commands/mcp/xaaIdpCommand.ts +266 -0
  175. package/src/commands/memory/index.ts +10 -0
  176. package/src/commands/memory/memory.tsx +90 -0
  177. package/src/commands/mobile/index.ts +11 -0
  178. package/src/commands/mobile/mobile.tsx +274 -0
  179. package/src/commands/mock-limits/index.js +1 -0
  180. package/src/commands/model/index.ts +16 -0
  181. package/src/commands/model/model.tsx +383 -0
  182. package/src/commands/oauth-refresh/index.js +1 -0
  183. package/src/commands/onboarding/index.js +1 -0
  184. package/src/commands/output-style/index.ts +11 -0
  185. package/src/commands/output-style/output-style.tsx +7 -0
  186. package/src/commands/passes/index.ts +22 -0
  187. package/src/commands/passes/passes.tsx +24 -0
  188. package/src/commands/perf-issue/index.js +1 -0
  189. package/src/commands/permissions/index.ts +11 -0
  190. package/src/commands/permissions/permissions.tsx +10 -0
  191. package/src/commands/plan/index.ts +11 -0
  192. package/src/commands/plan/plan.tsx +122 -0
  193. package/src/commands/plugin/AddMarketplace.tsx +162 -0
  194. package/src/commands/plugin/BrowseMarketplace.tsx +802 -0
  195. package/src/commands/plugin/DiscoverPlugins.tsx +781 -0
  196. package/src/commands/plugin/ManageMarketplaces.tsx +838 -0
  197. package/src/commands/plugin/ManagePlugins.tsx +2215 -0
  198. package/src/commands/plugin/PluginErrors.tsx +124 -0
  199. package/src/commands/plugin/PluginOptionsDialog.tsx +357 -0
  200. package/src/commands/plugin/PluginOptionsFlow.tsx +135 -0
  201. package/src/commands/plugin/PluginSettings.tsx +1072 -0
  202. package/src/commands/plugin/PluginTrustWarning.tsx +32 -0
  203. package/src/commands/plugin/UnifiedInstalledCell.tsx +565 -0
  204. package/src/commands/plugin/ValidatePlugin.tsx +98 -0
  205. package/src/commands/plugin/index.tsx +11 -0
  206. package/src/commands/plugin/parseArgs.ts +103 -0
  207. package/src/commands/plugin/plugin.tsx +7 -0
  208. package/src/commands/plugin/pluginDetailsHelpers.tsx +117 -0
  209. package/src/commands/plugin/usePagination.ts +171 -0
  210. package/src/commands/pr_comments/index.ts +50 -0
  211. package/src/commands/privacy-settings/index.ts +14 -0
  212. package/src/commands/privacy-settings/privacy-settings.tsx +58 -0
  213. package/src/commands/provider/index.ts +27 -0
  214. package/src/commands/provider/provider.tsx +686 -0
  215. package/src/commands/rate-limit-options/index.ts +19 -0
  216. package/src/commands/rate-limit-options/rate-limit-options.tsx +210 -0
  217. package/src/commands/release-notes/index.ts +11 -0
  218. package/src/commands/release-notes/release-notes.ts +50 -0
  219. package/src/commands/reload-plugins/index.ts +18 -0
  220. package/src/commands/reload-plugins/reload-plugins.ts +61 -0
  221. package/src/commands/remote-env/index.ts +15 -0
  222. package/src/commands/remote-env/remote-env.tsx +7 -0
  223. package/src/commands/remote-setup/api.ts +182 -0
  224. package/src/commands/remote-setup/index.ts +20 -0
  225. package/src/commands/remote-setup/remote-setup.tsx +187 -0
  226. package/src/commands/rename/generateSessionName.ts +67 -0
  227. package/src/commands/rename/index.ts +12 -0
  228. package/src/commands/rename/rename.ts +87 -0
  229. package/src/commands/reset-limits/index.js +4 -0
  230. package/src/commands/resume/index.ts +12 -0
  231. package/src/commands/resume/resume.tsx +275 -0
  232. package/src/commands/review/UltrareviewOverageDialog.tsx +96 -0
  233. package/src/commands/review/reviewRemote.ts +316 -0
  234. package/src/commands/review/ultrareviewCommand.tsx +58 -0
  235. package/src/commands/review/ultrareviewEnabled.ts +14 -0
  236. package/src/commands/review.ts +57 -0
  237. package/src/commands/rewind/index.ts +13 -0
  238. package/src/commands/rewind/rewind.ts +13 -0
  239. package/src/commands/sandbox-toggle/index.ts +50 -0
  240. package/src/commands/sandbox-toggle/sandbox-toggle.tsx +83 -0
  241. package/src/commands/security-review.ts +243 -0
  242. package/src/commands/session/index.ts +16 -0
  243. package/src/commands/session/session.tsx +140 -0
  244. package/src/commands/share/index.js +1 -0
  245. package/src/commands/skills/index.ts +10 -0
  246. package/src/commands/skills/skills.tsx +8 -0
  247. package/src/commands/stats/index.ts +10 -0
  248. package/src/commands/stats/stats.tsx +7 -0
  249. package/src/commands/status/index.ts +12 -0
  250. package/src/commands/status/status.tsx +8 -0
  251. package/src/commands/statusline.tsx +24 -0
  252. package/src/commands/stickers/index.ts +11 -0
  253. package/src/commands/stickers/stickers.ts +16 -0
  254. package/src/commands/summary/index.js +1 -0
  255. package/src/commands/tag/index.ts +12 -0
  256. package/src/commands/tag/tag.tsx +215 -0
  257. package/src/commands/tasks/index.ts +11 -0
  258. package/src/commands/tasks/tasks.tsx +8 -0
  259. package/src/commands/teleport/index.js +1 -0
  260. package/src/commands/terminalSetup/index.ts +23 -0
  261. package/src/commands/terminalSetup/terminalSetup.tsx +531 -0
  262. package/src/commands/theme/index.ts +10 -0
  263. package/src/commands/theme/theme.tsx +57 -0
  264. package/src/commands/thinkback/index.ts +13 -0
  265. package/src/commands/thinkback/thinkback.tsx +554 -0
  266. package/src/commands/thinkback-play/index.ts +17 -0
  267. package/src/commands/thinkback-play/thinkback-play.ts +43 -0
  268. package/src/commands/ultraplan.tsx +471 -0
  269. package/src/commands/upgrade/index.ts +16 -0
  270. package/src/commands/upgrade/upgrade.tsx +38 -0
  271. package/src/commands/usage/index.ts +9 -0
  272. package/src/commands/usage/usage.tsx +7 -0
  273. package/src/commands/version.ts +24 -0
  274. package/src/commands/vim/index.ts +11 -0
  275. package/src/commands/vim/vim.ts +38 -0
  276. package/src/commands/voice/index.ts +20 -0
  277. package/src/commands/voice/voice.ts +150 -0
  278. package/src/commands.ts +756 -0
  279. package/src/components/AgentProgressLine.tsx +136 -0
  280. package/src/components/App.tsx +56 -0
  281. package/src/components/ApproveApiKey.tsx +123 -0
  282. package/src/components/AutoModeOptInDialog.tsx +142 -0
  283. package/src/components/AutoUpdater.tsx +199 -0
  284. package/src/components/AutoUpdaterWrapper.tsx +91 -0
  285. package/src/components/AwsAuthStatusBox.tsx +82 -0
  286. package/src/components/BaseTextInput.tsx +136 -0
  287. package/src/components/BashModeProgress.tsx +56 -0
  288. package/src/components/BridgeDialog.tsx +401 -0
  289. package/src/components/BypassPermissionsModeDialog.tsx +87 -0
  290. package/src/components/ChannelDowngradeDialog.tsx +102 -0
  291. package/src/components/ClaudeCodeHint/PluginHintMenu.tsx +78 -0
  292. package/src/components/ClaudeInChromeOnboarding.tsx +121 -0
  293. package/src/components/ClaudeMdExternalIncludesDialog.tsx +137 -0
  294. package/src/components/ClickableImageRef.tsx +73 -0
  295. package/src/components/CompactSummary.tsx +118 -0
  296. package/src/components/ConfigurableShortcutHint.tsx +57 -0
  297. package/src/components/ConsoleOAuthFlow.tsx +631 -0
  298. package/src/components/ContextSuggestions.tsx +47 -0
  299. package/src/components/ContextVisualization.tsx +489 -0
  300. package/src/components/CoordinatorAgentStatus.tsx +273 -0
  301. package/src/components/CostThresholdDialog.tsx +50 -0
  302. package/src/components/CtrlOToExpand.tsx +51 -0
  303. package/src/components/CustomSelect/SelectMulti.tsx +213 -0
  304. package/src/components/CustomSelect/index.ts +3 -0
  305. package/src/components/CustomSelect/option-map.ts +50 -0
  306. package/src/components/CustomSelect/select-input-option.tsx +488 -0
  307. package/src/components/CustomSelect/select-option.tsx +68 -0
  308. package/src/components/CustomSelect/select.tsx +690 -0
  309. package/src/components/CustomSelect/use-multi-select-state.ts +414 -0
  310. package/src/components/CustomSelect/use-select-input.ts +287 -0
  311. package/src/components/CustomSelect/use-select-navigation.ts +653 -0
  312. package/src/components/CustomSelect/use-select-state.ts +157 -0
  313. package/src/components/DesktopHandoff.tsx +193 -0
  314. package/src/components/DesktopUpsell/DesktopUpsellStartup.tsx +171 -0
  315. package/src/components/DevBar.tsx +49 -0
  316. package/src/components/DevChannelsDialog.tsx +105 -0
  317. package/src/components/DiagnosticsDisplay.tsx +95 -0
  318. package/src/components/EffortCallout.tsx +265 -0
  319. package/src/components/EffortIndicator.ts +42 -0
  320. package/src/components/ExitFlow.tsx +48 -0
  321. package/src/components/ExportDialog.tsx +128 -0
  322. package/src/components/FallbackToolUseErrorMessage.tsx +116 -0
  323. package/src/components/FallbackToolUseRejectedMessage.tsx +16 -0
  324. package/src/components/FastIcon.tsx +46 -0
  325. package/src/components/Feedback.tsx +593 -0
  326. package/src/components/FeedbackSurvey/FeedbackSurvey.tsx +174 -0
  327. package/src/components/FeedbackSurvey/FeedbackSurveyView.tsx +108 -0
  328. package/src/components/FeedbackSurvey/TranscriptSharePrompt.tsx +88 -0
  329. package/src/components/FeedbackSurvey/submitTranscriptShare.ts +113 -0
  330. package/src/components/FeedbackSurvey/useDebouncedDigitInput.ts +82 -0
  331. package/src/components/FeedbackSurvey/useFeedbackSurvey.tsx +296 -0
  332. package/src/components/FeedbackSurvey/useMemorySurvey.tsx +213 -0
  333. package/src/components/FeedbackSurvey/usePostCompactSurvey.tsx +206 -0
  334. package/src/components/FeedbackSurvey/useSurveyState.tsx +100 -0
  335. package/src/components/FileEditToolDiff.tsx +181 -0
  336. package/src/components/FileEditToolUpdatedMessage.tsx +124 -0
  337. package/src/components/FileEditToolUseRejectedMessage.tsx +170 -0
  338. package/src/components/FilePathLink.tsx +43 -0
  339. package/src/components/FullscreenLayout.tsx +637 -0
  340. package/src/components/GlobalSearchDialog.tsx +343 -0
  341. package/src/components/HelpV2/Commands.tsx +82 -0
  342. package/src/components/HelpV2/General.tsx +23 -0
  343. package/src/components/HelpV2/HelpV2.tsx +185 -0
  344. package/src/components/HighlightedCode/Fallback.tsx +193 -0
  345. package/src/components/HighlightedCode.tsx +190 -0
  346. package/src/components/HistorySearchDialog.tsx +118 -0
  347. package/src/components/IdeAutoConnectDialog.tsx +154 -0
  348. package/src/components/IdeOnboardingDialog.tsx +167 -0
  349. package/src/components/IdeStatusIndicator.tsx +58 -0
  350. package/src/components/IdleReturnDialog.tsx +118 -0
  351. package/src/components/InterruptedByUser.tsx +15 -0
  352. package/src/components/InvalidConfigDialog.tsx +156 -0
  353. package/src/components/InvalidSettingsDialog.tsx +89 -0
  354. package/src/components/KeybindingWarnings.tsx +55 -0
  355. package/src/components/LanguagePicker.tsx +86 -0
  356. package/src/components/LogSelector.tsx +1575 -0
  357. package/src/components/LogoV2/AnimatedAsterisk.tsx +50 -0
  358. package/src/components/LogoV2/AnimatedClawd.tsx +124 -0
  359. package/src/components/LogoV2/ChannelsNotice.tsx +266 -0
  360. package/src/components/LogoV2/Clawd.tsx +238 -0
  361. package/src/components/LogoV2/CondensedLogo.tsx +161 -0
  362. package/src/components/LogoV2/EmergencyTip.tsx +58 -0
  363. package/src/components/LogoV2/Feed.tsx +112 -0
  364. package/src/components/LogoV2/FeedColumn.tsx +59 -0
  365. package/src/components/LogoV2/GuestPassesUpsell.tsx +70 -0
  366. package/src/components/LogoV2/LogoV2.tsx +544 -0
  367. package/src/components/LogoV2/Opus1mMergeNotice.tsx +55 -0
  368. package/src/components/LogoV2/OverageCreditUpsell.tsx +166 -0
  369. package/src/components/LogoV2/VoiceModeNotice.tsx +68 -0
  370. package/src/components/LogoV2/WelcomeV2.tsx +434 -0
  371. package/src/components/LogoV2/feedConfigs.tsx +92 -0
  372. package/src/components/LspRecommendation/LspRecommendationMenu.tsx +88 -0
  373. package/src/components/MCPServerApprovalDialog.tsx +115 -0
  374. package/src/components/MCPServerDesktopImportDialog.tsx +203 -0
  375. package/src/components/MCPServerDialogCopy.tsx +15 -0
  376. package/src/components/MCPServerMultiselectDialog.tsx +133 -0
  377. package/src/components/ManagedSettingsSecurityDialog/ManagedSettingsSecurityDialog.tsx +149 -0
  378. package/src/components/ManagedSettingsSecurityDialog/utils.ts +144 -0
  379. package/src/components/Markdown.tsx +236 -0
  380. package/src/components/MarkdownTable.tsx +322 -0
  381. package/src/components/MemoryUsageIndicator.tsx +37 -0
  382. package/src/components/Message.tsx +627 -0
  383. package/src/components/MessageModel.tsx +43 -0
  384. package/src/components/MessageResponse.tsx +78 -0
  385. package/src/components/MessageRow.tsx +383 -0
  386. package/src/components/MessageSelector.tsx +831 -0
  387. package/src/components/MessageTimestamp.tsx +63 -0
  388. package/src/components/Messages.tsx +834 -0
  389. package/src/components/ModelPicker.tsx +458 -0
  390. package/src/components/NativeAutoUpdater.tsx +194 -0
  391. package/src/components/NotebookEditToolUseRejectedMessage.tsx +92 -0
  392. package/src/components/OffscreenFreeze.tsx +44 -0
  393. package/src/components/Onboarding.tsx +635 -0
  394. package/src/components/OutputStylePicker.tsx +112 -0
  395. package/src/components/PackageManagerAutoUpdater.tsx +105 -0
  396. package/src/components/Passes/Passes.tsx +184 -0
  397. package/src/components/PrBadge.tsx +97 -0
  398. package/src/components/PressEnterToContinue.tsx +15 -0
  399. package/src/components/PromptInput/HistorySearchInput.tsx +51 -0
  400. package/src/components/PromptInput/IssueFlagBanner.tsx +12 -0
  401. package/src/components/PromptInput/Notifications.tsx +332 -0
  402. package/src/components/PromptInput/PromptInput.tsx +2366 -0
  403. package/src/components/PromptInput/PromptInputFooter.tsx +191 -0
  404. package/src/components/PromptInput/PromptInputFooterLeftSide.tsx +517 -0
  405. package/src/components/PromptInput/PromptInputFooterSuggestions.tsx +293 -0
  406. package/src/components/PromptInput/PromptInputHelpMenu.tsx +358 -0
  407. package/src/components/PromptInput/PromptInputModeIndicator.tsx +93 -0
  408. package/src/components/PromptInput/PromptInputQueuedCommands.tsx +117 -0
  409. package/src/components/PromptInput/PromptInputStashNotice.tsx +25 -0
  410. package/src/components/PromptInput/SandboxPromptFooterHint.tsx +64 -0
  411. package/src/components/PromptInput/ShimmeredInput.tsx +143 -0
  412. package/src/components/PromptInput/VoiceIndicator.tsx +137 -0
  413. package/src/components/PromptInput/inputModes.ts +33 -0
  414. package/src/components/PromptInput/inputPaste.ts +90 -0
  415. package/src/components/PromptInput/useMaybeTruncateInput.ts +58 -0
  416. package/src/components/PromptInput/usePromptInputPlaceholder.ts +76 -0
  417. package/src/components/PromptInput/useShowFastIconHint.ts +31 -0
  418. package/src/components/PromptInput/useSwarmBanner.ts +155 -0
  419. package/src/components/PromptInput/utils.ts +60 -0
  420. package/src/components/ProviderPicker.tsx +111 -0
  421. package/src/components/QuickOpenDialog.tsx +244 -0
  422. package/src/components/RemoteCallout.tsx +76 -0
  423. package/src/components/RemoteEnvironmentDialog.tsx +340 -0
  424. package/src/components/ResumeTask.tsx +268 -0
  425. package/src/components/SandboxViolationExpandedView.tsx +99 -0
  426. package/src/components/ScrollKeybindingHandler.tsx +1012 -0
  427. package/src/components/SearchBox.tsx +72 -0
  428. package/src/components/SentryErrorBoundary.ts +28 -0
  429. package/src/components/SessionBackgroundHint.tsx +108 -0
  430. package/src/components/SessionPreview.tsx +194 -0
  431. package/src/components/Settings/Config.tsx +1903 -0
  432. package/src/components/Settings/Settings.tsx +137 -0
  433. package/src/components/Settings/Status.tsx +242 -0
  434. package/src/components/Settings/Usage.tsx +377 -0
  435. package/src/components/ShowInIDEPrompt.tsx +170 -0
  436. package/src/components/SkillImprovementSurvey.tsx +152 -0
  437. package/src/components/Spinner/FlashingChar.tsx +61 -0
  438. package/src/components/Spinner/GlimmerMessage.tsx +328 -0
  439. package/src/components/Spinner/ShimmerChar.tsx +36 -0
  440. package/src/components/Spinner/SpinnerAnimationRow.tsx +265 -0
  441. package/src/components/Spinner/SpinnerGlyph.tsx +80 -0
  442. package/src/components/Spinner/TeammateSpinnerLine.tsx +233 -0
  443. package/src/components/Spinner/TeammateSpinnerTree.tsx +272 -0
  444. package/src/components/Spinner/index.ts +10 -0
  445. package/src/components/Spinner/teammateSelectHint.ts +1 -0
  446. package/src/components/Spinner/useShimmerAnimation.ts +31 -0
  447. package/src/components/Spinner/useStalledAnimation.ts +75 -0
  448. package/src/components/Spinner/utils.ts +84 -0
  449. package/src/components/Spinner.tsx +562 -0
  450. package/src/components/Stats.tsx +1228 -0
  451. package/src/components/StatusLine.tsx +325 -0
  452. package/src/components/StatusNotices.tsx +55 -0
  453. package/src/components/StructuredDiff/Fallback.tsx +487 -0
  454. package/src/components/StructuredDiff/colorDiff.ts +37 -0
  455. package/src/components/StructuredDiff.tsx +190 -0
  456. package/src/components/StructuredDiffList.tsx +30 -0
  457. package/src/components/TagTabs.tsx +139 -0
  458. package/src/components/TaskListV2.tsx +378 -0
  459. package/src/components/TeammateViewHeader.tsx +82 -0
  460. package/src/components/TeleportError.tsx +189 -0
  461. package/src/components/TeleportProgress.tsx +140 -0
  462. package/src/components/TeleportRepoMismatchDialog.tsx +104 -0
  463. package/src/components/TeleportResumeWrapper.tsx +167 -0
  464. package/src/components/TeleportStash.tsx +116 -0
  465. package/src/components/TextInput.tsx +124 -0
  466. package/src/components/ThemePicker.tsx +333 -0
  467. package/src/components/ThinkingToggle.tsx +153 -0
  468. package/src/components/TokenWarning.tsx +179 -0
  469. package/src/components/ToolUseLoader.tsx +42 -0
  470. package/src/components/TrustDialog/TrustDialog.tsx +290 -0
  471. package/src/components/TrustDialog/utils.ts +245 -0
  472. package/src/components/ValidationErrorsList.tsx +148 -0
  473. package/src/components/VimTextInput.tsx +140 -0
  474. package/src/components/VirtualMessageList.tsx +1082 -0
  475. package/src/components/WorkflowMultiselectDialog.tsx +128 -0
  476. package/src/components/WorktreeExitDialog.tsx +231 -0
  477. package/src/components/agents/AgentDetail.tsx +220 -0
  478. package/src/components/agents/AgentEditor.tsx +178 -0
  479. package/src/components/agents/AgentNavigationFooter.tsx +26 -0
  480. package/src/components/agents/AgentsList.tsx +440 -0
  481. package/src/components/agents/AgentsMenu.tsx +800 -0
  482. package/src/components/agents/ColorPicker.tsx +112 -0
  483. package/src/components/agents/ModelSelector.tsx +68 -0
  484. package/src/components/agents/ToolSelector.tsx +568 -0
  485. package/src/components/agents/agentFileUtils.ts +272 -0
  486. package/src/components/agents/generateAgent.ts +197 -0
  487. package/src/components/agents/new-agent-creation/CreateAgentWizard.tsx +97 -0
  488. package/src/components/agents/new-agent-creation/wizard-steps/ColorStep.tsx +84 -0
  489. package/src/components/agents/new-agent-creation/wizard-steps/ConfirmStep.tsx +378 -0
  490. package/src/components/agents/new-agent-creation/wizard-steps/ConfirmStepWrapper.tsx +74 -0
  491. package/src/components/agents/new-agent-creation/wizard-steps/DescriptionStep.tsx +123 -0
  492. package/src/components/agents/new-agent-creation/wizard-steps/GenerateStep.tsx +143 -0
  493. package/src/components/agents/new-agent-creation/wizard-steps/LocationStep.tsx +80 -0
  494. package/src/components/agents/new-agent-creation/wizard-steps/MemoryStep.tsx +113 -0
  495. package/src/components/agents/new-agent-creation/wizard-steps/MethodStep.tsx +80 -0
  496. package/src/components/agents/new-agent-creation/wizard-steps/ModelStep.tsx +52 -0
  497. package/src/components/agents/new-agent-creation/wizard-steps/PromptStep.tsx +128 -0
  498. package/src/components/agents/new-agent-creation/wizard-steps/ToolsStep.tsx +61 -0
  499. package/src/components/agents/new-agent-creation/wizard-steps/TypeStep.tsx +103 -0
  500. package/src/components/agents/types.ts +27 -0
  501. package/src/components/agents/utils.ts +18 -0
  502. package/src/components/agents/validateAgent.ts +109 -0
  503. package/src/components/design-system/Byline.tsx +77 -0
  504. package/src/components/design-system/Dialog.tsx +138 -0
  505. package/src/components/design-system/Divider.tsx +149 -0
  506. package/src/components/design-system/FuzzyPicker.tsx +312 -0
  507. package/src/components/design-system/KeyboardShortcutHint.tsx +81 -0
  508. package/src/components/design-system/ListItem.tsx +244 -0
  509. package/src/components/design-system/LoadingState.tsx +94 -0
  510. package/src/components/design-system/Pane.tsx +77 -0
  511. package/src/components/design-system/ProgressBar.tsx +86 -0
  512. package/src/components/design-system/Ratchet.tsx +80 -0
  513. package/src/components/design-system/StatusIcon.tsx +95 -0
  514. package/src/components/design-system/Tabs.tsx +340 -0
  515. package/src/components/design-system/ThemeProvider.tsx +170 -0
  516. package/src/components/design-system/ThemedBox.tsx +156 -0
  517. package/src/components/design-system/ThemedText.tsx +124 -0
  518. package/src/components/design-system/color.ts +30 -0
  519. package/src/components/diff/DiffDetailView.tsx +281 -0
  520. package/src/components/diff/DiffDialog.tsx +383 -0
  521. package/src/components/diff/DiffFileList.tsx +292 -0
  522. package/src/components/grove/Grove.tsx +463 -0
  523. package/src/components/hooks/HooksConfigMenu.tsx +578 -0
  524. package/src/components/hooks/PromptDialog.tsx +90 -0
  525. package/src/components/hooks/SelectEventMode.tsx +127 -0
  526. package/src/components/hooks/SelectHookMode.tsx +112 -0
  527. package/src/components/hooks/SelectMatcherMode.tsx +144 -0
  528. package/src/components/hooks/ViewHookMode.tsx +199 -0
  529. package/src/components/mcp/CapabilitiesSection.tsx +61 -0
  530. package/src/components/mcp/ElicitationDialog.tsx +1169 -0
  531. package/src/components/mcp/MCPAgentServerMenu.tsx +183 -0
  532. package/src/components/mcp/MCPListPanel.tsx +504 -0
  533. package/src/components/mcp/MCPReconnect.tsx +167 -0
  534. package/src/components/mcp/MCPRemoteServerMenu.tsx +649 -0
  535. package/src/components/mcp/MCPSettings.tsx +398 -0
  536. package/src/components/mcp/MCPStdioServerMenu.tsx +177 -0
  537. package/src/components/mcp/MCPToolDetailView.tsx +212 -0
  538. package/src/components/mcp/MCPToolListView.tsx +141 -0
  539. package/src/components/mcp/McpParsingWarnings.tsx +213 -0
  540. package/src/components/mcp/index.ts +9 -0
  541. package/src/components/mcp/utils/reconnectHelpers.tsx +49 -0
  542. package/src/components/memory/MemoryFileSelector.tsx +438 -0
  543. package/src/components/memory/MemoryUpdateNotification.tsx +45 -0
  544. package/src/components/messageActions.tsx +450 -0
  545. package/src/components/messages/AdvisorMessage.tsx +158 -0
  546. package/src/components/messages/AssistantRedactedThinkingMessage.tsx +31 -0
  547. package/src/components/messages/AssistantTextMessage.tsx +270 -0
  548. package/src/components/messages/AssistantThinkingMessage.tsx +86 -0
  549. package/src/components/messages/AssistantToolUseMessage.tsx +368 -0
  550. package/src/components/messages/AttachmentMessage.tsx +536 -0
  551. package/src/components/messages/CollapsedReadSearchContent.tsx +484 -0
  552. package/src/components/messages/CompactBoundaryMessage.tsx +18 -0
  553. package/src/components/messages/GroupedToolUseContent.tsx +58 -0
  554. package/src/components/messages/HighlightedThinkingText.tsx +162 -0
  555. package/src/components/messages/HookProgressMessage.tsx +116 -0
  556. package/src/components/messages/PlanApprovalMessage.tsx +222 -0
  557. package/src/components/messages/RateLimitMessage.tsx +161 -0
  558. package/src/components/messages/ShutdownMessage.tsx +132 -0
  559. package/src/components/messages/SystemAPIErrorMessage.tsx +141 -0
  560. package/src/components/messages/SystemTextMessage.tsx +827 -0
  561. package/src/components/messages/TaskAssignmentMessage.tsx +76 -0
  562. package/src/components/messages/UserAgentNotificationMessage.tsx +83 -0
  563. package/src/components/messages/UserBashInputMessage.tsx +58 -0
  564. package/src/components/messages/UserBashOutputMessage.tsx +54 -0
  565. package/src/components/messages/UserChannelMessage.tsx +137 -0
  566. package/src/components/messages/UserCommandMessage.tsx +108 -0
  567. package/src/components/messages/UserImageMessage.tsx +59 -0
  568. package/src/components/messages/UserLocalCommandOutputMessage.tsx +167 -0
  569. package/src/components/messages/UserMemoryInputMessage.tsx +75 -0
  570. package/src/components/messages/UserPlanMessage.tsx +42 -0
  571. package/src/components/messages/UserPromptMessage.tsx +80 -0
  572. package/src/components/messages/UserResourceUpdateMessage.tsx +121 -0
  573. package/src/components/messages/UserTeammateMessage.tsx +206 -0
  574. package/src/components/messages/UserTextMessage.tsx +275 -0
  575. package/src/components/messages/UserToolResultMessage/RejectedPlanMessage.tsx +31 -0
  576. package/src/components/messages/UserToolResultMessage/RejectedToolUseMessage.tsx +16 -0
  577. package/src/components/messages/UserToolResultMessage/UserToolCanceledMessage.tsx +16 -0
  578. package/src/components/messages/UserToolResultMessage/UserToolErrorMessage.tsx +103 -0
  579. package/src/components/messages/UserToolResultMessage/UserToolRejectMessage.tsx +95 -0
  580. package/src/components/messages/UserToolResultMessage/UserToolResultMessage.tsx +106 -0
  581. package/src/components/messages/UserToolResultMessage/UserToolSuccessMessage.tsx +104 -0
  582. package/src/components/messages/UserToolResultMessage/utils.tsx +44 -0
  583. package/src/components/messages/nullRenderingAttachments.ts +70 -0
  584. package/src/components/messages/teamMemCollapsed.tsx +140 -0
  585. package/src/components/messages/teamMemSaved.ts +19 -0
  586. package/src/components/modelPickerHelpers.test.ts +74 -0
  587. package/src/components/modelPickerHelpers.ts +67 -0
  588. package/src/components/permissions/AskUserQuestionPermissionRequest/AskUserQuestionPermissionRequest.tsx +645 -0
  589. package/src/components/permissions/AskUserQuestionPermissionRequest/PreviewBox.tsx +229 -0
  590. package/src/components/permissions/AskUserQuestionPermissionRequest/PreviewQuestionView.tsx +328 -0
  591. package/src/components/permissions/AskUserQuestionPermissionRequest/QuestionNavigationBar.tsx +178 -0
  592. package/src/components/permissions/AskUserQuestionPermissionRequest/QuestionView.tsx +465 -0
  593. package/src/components/permissions/AskUserQuestionPermissionRequest/SubmitQuestionsView.tsx +144 -0
  594. package/src/components/permissions/AskUserQuestionPermissionRequest/use-multiple-choice-state.ts +179 -0
  595. package/src/components/permissions/BashPermissionRequest/BashPermissionRequest.tsx +482 -0
  596. package/src/components/permissions/BashPermissionRequest/bashToolUseOptions.tsx +147 -0
  597. package/src/components/permissions/ComputerUseApproval/ComputerUseApproval.tsx +441 -0
  598. package/src/components/permissions/EnterPlanModePermissionRequest/EnterPlanModePermissionRequest.tsx +122 -0
  599. package/src/components/permissions/ExitPlanModePermissionRequest/ExitPlanModePermissionRequest.tsx +768 -0
  600. package/src/components/permissions/FallbackPermissionRequest.tsx +333 -0
  601. package/src/components/permissions/FileEditPermissionRequest/FileEditPermissionRequest.tsx +182 -0
  602. package/src/components/permissions/FilePermissionDialog/FilePermissionDialog.tsx +204 -0
  603. package/src/components/permissions/FilePermissionDialog/ideDiffConfig.ts +42 -0
  604. package/src/components/permissions/FilePermissionDialog/permissionOptions.tsx +177 -0
  605. package/src/components/permissions/FilePermissionDialog/useFilePermissionDialog.ts +212 -0
  606. package/src/components/permissions/FilePermissionDialog/usePermissionHandler.ts +185 -0
  607. package/src/components/permissions/FileWritePermissionRequest/FileWritePermissionRequest.tsx +161 -0
  608. package/src/components/permissions/FileWritePermissionRequest/FileWriteToolDiff.tsx +89 -0
  609. package/src/components/permissions/FilesystemPermissionRequest/FilesystemPermissionRequest.tsx +115 -0
  610. package/src/components/permissions/NotebookEditPermissionRequest/NotebookEditPermissionRequest.tsx +166 -0
  611. package/src/components/permissions/NotebookEditPermissionRequest/NotebookEditToolDiff.tsx +235 -0
  612. package/src/components/permissions/PermissionDecisionDebugInfo.tsx +460 -0
  613. package/src/components/permissions/PermissionDialog.tsx +72 -0
  614. package/src/components/permissions/PermissionExplanation.tsx +272 -0
  615. package/src/components/permissions/PermissionPrompt.tsx +336 -0
  616. package/src/components/permissions/PermissionRequest.tsx +217 -0
  617. package/src/components/permissions/PermissionRequestTitle.tsx +66 -0
  618. package/src/components/permissions/PermissionRuleExplanation.tsx +121 -0
  619. package/src/components/permissions/PowerShellPermissionRequest/PowerShellPermissionRequest.tsx +235 -0
  620. package/src/components/permissions/PowerShellPermissionRequest/powershellToolUseOptions.tsx +91 -0
  621. package/src/components/permissions/SandboxPermissionRequest.tsx +163 -0
  622. package/src/components/permissions/SedEditPermissionRequest/SedEditPermissionRequest.tsx +230 -0
  623. package/src/components/permissions/SkillPermissionRequest/SkillPermissionRequest.tsx +369 -0
  624. package/src/components/permissions/WebFetchPermissionRequest/WebFetchPermissionRequest.tsx +258 -0
  625. package/src/components/permissions/WorkerBadge.tsx +49 -0
  626. package/src/components/permissions/WorkerPendingPermission.tsx +105 -0
  627. package/src/components/permissions/hooks.ts +209 -0
  628. package/src/components/permissions/rules/AddPermissionRules.tsx +180 -0
  629. package/src/components/permissions/rules/AddWorkspaceDirectory.tsx +340 -0
  630. package/src/components/permissions/rules/PermissionRuleDescription.tsx +76 -0
  631. package/src/components/permissions/rules/PermissionRuleInput.tsx +138 -0
  632. package/src/components/permissions/rules/PermissionRuleList.tsx +1179 -0
  633. package/src/components/permissions/rules/RecentDenialsTab.tsx +207 -0
  634. package/src/components/permissions/rules/RemoveWorkspaceDirectory.tsx +110 -0
  635. package/src/components/permissions/rules/WorkspaceTab.tsx +150 -0
  636. package/src/components/permissions/shellPermissionHelpers.tsx +164 -0
  637. package/src/components/permissions/useShellPermissionFeedback.ts +148 -0
  638. package/src/components/permissions/utils.ts +25 -0
  639. package/src/components/sandbox/SandboxConfigTab.tsx +45 -0
  640. package/src/components/sandbox/SandboxDependenciesTab.tsx +120 -0
  641. package/src/components/sandbox/SandboxDoctorSection.tsx +46 -0
  642. package/src/components/sandbox/SandboxOverridesTab.tsx +193 -0
  643. package/src/components/sandbox/SandboxSettings.tsx +296 -0
  644. package/src/components/shell/ExpandShellOutputContext.tsx +36 -0
  645. package/src/components/shell/OutputLine.tsx +118 -0
  646. package/src/components/shell/ShellProgressMessage.tsx +150 -0
  647. package/src/components/shell/ShellTimeDisplay.tsx +74 -0
  648. package/src/components/skills/SkillsMenu.tsx +237 -0
  649. package/src/components/tasks/AsyncAgentDetailDialog.tsx +229 -0
  650. package/src/components/tasks/BackgroundTask.tsx +345 -0
  651. package/src/components/tasks/BackgroundTaskStatus.tsx +429 -0
  652. package/src/components/tasks/BackgroundTasksDialog.tsx +652 -0
  653. package/src/components/tasks/DreamDetailDialog.tsx +251 -0
  654. package/src/components/tasks/InProcessTeammateDetailDialog.tsx +266 -0
  655. package/src/components/tasks/RemoteSessionDetailDialog.tsx +904 -0
  656. package/src/components/tasks/RemoteSessionProgress.tsx +243 -0
  657. package/src/components/tasks/ShellDetailDialog.tsx +404 -0
  658. package/src/components/tasks/ShellProgress.tsx +87 -0
  659. package/src/components/tasks/renderToolActivity.tsx +33 -0
  660. package/src/components/tasks/taskStatusUtils.tsx +107 -0
  661. package/src/components/teams/TeamStatus.tsx +80 -0
  662. package/src/components/teams/TeamsDialog.tsx +715 -0
  663. package/src/components/ui/OrderedList.tsx +71 -0
  664. package/src/components/ui/OrderedListItem.tsx +45 -0
  665. package/src/components/ui/TreeSelect.tsx +397 -0
  666. package/src/components/wizard/WizardDialogLayout.tsx +65 -0
  667. package/src/components/wizard/WizardNavigationFooter.tsx +24 -0
  668. package/src/components/wizard/WizardProvider.tsx +213 -0
  669. package/src/components/wizard/index.ts +9 -0
  670. package/src/components/wizard/useWizard.ts +13 -0
  671. package/src/constants/apiLimits.ts +94 -0
  672. package/src/constants/betas.ts +52 -0
  673. package/src/constants/common.ts +33 -0
  674. package/src/constants/cyberRiskInstruction.ts +24 -0
  675. package/src/constants/errorIds.ts +15 -0
  676. package/src/constants/figures.ts +45 -0
  677. package/src/constants/files.ts +156 -0
  678. package/src/constants/github-app.ts +144 -0
  679. package/src/constants/keys.ts +11 -0
  680. package/src/constants/messages.ts +1 -0
  681. package/src/constants/oauth.ts +234 -0
  682. package/src/constants/outputStyles.ts +216 -0
  683. package/src/constants/product.ts +76 -0
  684. package/src/constants/prompts.ts +915 -0
  685. package/src/constants/spinnerVerbs.ts +204 -0
  686. package/src/constants/system.ts +96 -0
  687. package/src/constants/systemPromptSections.ts +68 -0
  688. package/src/constants/toolLimits.ts +56 -0
  689. package/src/constants/tools.ts +112 -0
  690. package/src/constants/turnCompletionVerbs.ts +12 -0
  691. package/src/constants/xml.ts +86 -0
  692. package/src/context/QueuedMessageContext.tsx +63 -0
  693. package/src/context/fpsMetrics.tsx +30 -0
  694. package/src/context/mailbox.tsx +38 -0
  695. package/src/context/modalContext.tsx +58 -0
  696. package/src/context/notifications.tsx +240 -0
  697. package/src/context/overlayContext.tsx +151 -0
  698. package/src/context/promptOverlayContext.tsx +125 -0
  699. package/src/context/stats.tsx +220 -0
  700. package/src/context/voice.tsx +88 -0
  701. package/src/context.ts +189 -0
  702. package/src/coordinator/coordinatorMode.ts +369 -0
  703. package/src/cost-tracker.ts +323 -0
  704. package/src/costHook.ts +22 -0
  705. package/src/dialogLaunchers.tsx +133 -0
  706. package/src/entrypoints/agentSdkTypes.ts +443 -0
  707. package/src/entrypoints/cli.tsx +327 -0
  708. package/src/entrypoints/init.ts +340 -0
  709. package/src/entrypoints/mcp.ts +197 -0
  710. package/src/entrypoints/sandboxTypes.ts +156 -0
  711. package/src/entrypoints/sdk/controlSchemas.ts +663 -0
  712. package/src/entrypoints/sdk/controlTypes.ts +87 -0
  713. package/src/entrypoints/sdk/coreSchemas.ts +1889 -0
  714. package/src/entrypoints/sdk/coreTypes.generated.ts +255 -0
  715. package/src/entrypoints/sdk/coreTypes.ts +62 -0
  716. package/src/entrypoints/sdk/runtimeTypes.ts +29 -0
  717. package/src/entrypoints/sdk/settingsTypes.generated.ts +5 -0
  718. package/src/entrypoints/sdk/toolTypes.ts +5 -0
  719. package/src/history.ts +464 -0
  720. package/src/hooks/fileSuggestions.ts +811 -0
  721. package/src/hooks/notifs/useAutoModeUnavailableNotification.ts +56 -0
  722. package/src/hooks/notifs/useCanSwitchToExistingSubscription.tsx +60 -0
  723. package/src/hooks/notifs/useDeprecationWarningNotification.tsx +44 -0
  724. package/src/hooks/notifs/useFastModeNotification.tsx +162 -0
  725. package/src/hooks/notifs/useIDEStatusIndicator.tsx +186 -0
  726. package/src/hooks/notifs/useInstallMessages.tsx +26 -0
  727. package/src/hooks/notifs/useLspInitializationNotification.tsx +143 -0
  728. package/src/hooks/notifs/useMcpConnectivityStatus.tsx +88 -0
  729. package/src/hooks/notifs/useModelMigrationNotifications.tsx +52 -0
  730. package/src/hooks/notifs/useNpmDeprecationNotification.tsx +25 -0
  731. package/src/hooks/notifs/usePluginAutoupdateNotification.tsx +83 -0
  732. package/src/hooks/notifs/usePluginInstallationStatus.tsx +128 -0
  733. package/src/hooks/notifs/useRateLimitWarningNotification.tsx +114 -0
  734. package/src/hooks/notifs/useSettingsErrors.tsx +69 -0
  735. package/src/hooks/notifs/useStartupNotification.ts +41 -0
  736. package/src/hooks/notifs/useTeammateShutdownNotification.ts +78 -0
  737. package/src/hooks/renderPlaceholder.ts +51 -0
  738. package/src/hooks/toolPermission/PermissionContext.ts +388 -0
  739. package/src/hooks/toolPermission/handlers/coordinatorHandler.ts +65 -0
  740. package/src/hooks/toolPermission/handlers/interactiveHandler.ts +536 -0
  741. package/src/hooks/toolPermission/handlers/swarmWorkerHandler.ts +159 -0
  742. package/src/hooks/toolPermission/permissionLogging.ts +238 -0
  743. package/src/hooks/unifiedSuggestions.ts +202 -0
  744. package/src/hooks/useAfterFirstRender.ts +17 -0
  745. package/src/hooks/useApiKeyVerification.ts +84 -0
  746. package/src/hooks/useArrowKeyHistory.tsx +229 -0
  747. package/src/hooks/useAssistantHistory.ts +250 -0
  748. package/src/hooks/useAwaySummary.ts +125 -0
  749. package/src/hooks/useBackgroundTaskNavigation.ts +251 -0
  750. package/src/hooks/useBlink.ts +34 -0
  751. package/src/hooks/useCanUseTool.tsx +204 -0
  752. package/src/hooks/useCancelRequest.ts +276 -0
  753. package/src/hooks/useChromeExtensionNotification.tsx +50 -0
  754. package/src/hooks/useClaudeCodeHintRecommendation.tsx +129 -0
  755. package/src/hooks/useClipboardImageHint.ts +77 -0
  756. package/src/hooks/useCommandKeybindings.tsx +108 -0
  757. package/src/hooks/useCommandQueue.ts +15 -0
  758. package/src/hooks/useCopyOnSelect.ts +98 -0
  759. package/src/hooks/useDeferredHookMessages.ts +46 -0
  760. package/src/hooks/useDiffData.ts +110 -0
  761. package/src/hooks/useDiffInIDE.ts +379 -0
  762. package/src/hooks/useDirectConnect.ts +229 -0
  763. package/src/hooks/useDoublePress.ts +62 -0
  764. package/src/hooks/useDynamicConfig.ts +22 -0
  765. package/src/hooks/useElapsedTime.ts +37 -0
  766. package/src/hooks/useExitOnCtrlCD.ts +95 -0
  767. package/src/hooks/useExitOnCtrlCDWithKeybindings.ts +24 -0
  768. package/src/hooks/useFileHistorySnapshotInit.ts +25 -0
  769. package/src/hooks/useGlobalKeybindings.tsx +249 -0
  770. package/src/hooks/useHistorySearch.ts +303 -0
  771. package/src/hooks/useIDEIntegration.tsx +70 -0
  772. package/src/hooks/useIdeAtMentioned.ts +76 -0
  773. package/src/hooks/useIdeConnectionStatus.ts +33 -0
  774. package/src/hooks/useIdeLogging.ts +41 -0
  775. package/src/hooks/useIdeSelection.ts +150 -0
  776. package/src/hooks/useInboxPoller.ts +969 -0
  777. package/src/hooks/useInputBuffer.ts +132 -0
  778. package/src/hooks/useIssueFlagBanner.ts +133 -0
  779. package/src/hooks/useLogMessages.ts +119 -0
  780. package/src/hooks/useLspPluginRecommendation.tsx +194 -0
  781. package/src/hooks/useMailboxBridge.ts +21 -0
  782. package/src/hooks/useMainLoopModel.ts +34 -0
  783. package/src/hooks/useManagePlugins.ts +304 -0
  784. package/src/hooks/useMemoryUsage.ts +39 -0
  785. package/src/hooks/useMergedClients.ts +23 -0
  786. package/src/hooks/useMergedCommands.ts +15 -0
  787. package/src/hooks/useMergedTools.ts +44 -0
  788. package/src/hooks/useMinDisplayTime.ts +35 -0
  789. package/src/hooks/useNotifyAfterTimeout.ts +65 -0
  790. package/src/hooks/useOfficialMarketplaceNotification.tsx +48 -0
  791. package/src/hooks/usePasteHandler.ts +285 -0
  792. package/src/hooks/usePluginRecommendationBase.tsx +105 -0
  793. package/src/hooks/usePrStatus.ts +106 -0
  794. package/src/hooks/usePromptSuggestion.ts +177 -0
  795. package/src/hooks/usePromptsFromClaudeInChrome.tsx +71 -0
  796. package/src/hooks/useQueueProcessor.ts +68 -0
  797. package/src/hooks/useRemoteSession.ts +605 -0
  798. package/src/hooks/useReplBridge.tsx +723 -0
  799. package/src/hooks/useSSHSession.ts +241 -0
  800. package/src/hooks/useScheduledTasks.ts +139 -0
  801. package/src/hooks/useSearchInput.ts +364 -0
  802. package/src/hooks/useSessionBackgrounding.ts +158 -0
  803. package/src/hooks/useSettings.ts +17 -0
  804. package/src/hooks/useSettingsChange.ts +25 -0
  805. package/src/hooks/useSkillImprovementSurvey.ts +105 -0
  806. package/src/hooks/useSkillsChange.ts +62 -0
  807. package/src/hooks/useSwarmInitialization.ts +81 -0
  808. package/src/hooks/useSwarmPermissionPoller.ts +330 -0
  809. package/src/hooks/useTaskListWatcher.ts +221 -0
  810. package/src/hooks/useTasksV2.ts +250 -0
  811. package/src/hooks/useTeammateViewAutoExit.ts +63 -0
  812. package/src/hooks/useTeleportResume.tsx +85 -0
  813. package/src/hooks/useTerminalSize.ts +15 -0
  814. package/src/hooks/useTextInput.ts +529 -0
  815. package/src/hooks/useTimeout.ts +14 -0
  816. package/src/hooks/useTurnDiffs.ts +213 -0
  817. package/src/hooks/useTypeahead.tsx +1385 -0
  818. package/src/hooks/useUpdateNotification.ts +35 -0
  819. package/src/hooks/useVimInput.ts +316 -0
  820. package/src/hooks/useVirtualScroll.ts +721 -0
  821. package/src/hooks/useVoice.ts +1144 -0
  822. package/src/hooks/useVoiceEnabled.ts +25 -0
  823. package/src/hooks/useVoiceIntegration.tsx +677 -0
  824. package/src/ink/Ansi.tsx +292 -0
  825. package/src/ink/bidi.ts +139 -0
  826. package/src/ink/clearTerminal.ts +74 -0
  827. package/src/ink/colorize.ts +231 -0
  828. package/src/ink/components/AlternateScreen.tsx +80 -0
  829. package/src/ink/components/App.tsx +658 -0
  830. package/src/ink/components/AppContext.ts +21 -0
  831. package/src/ink/components/Box.tsx +214 -0
  832. package/src/ink/components/Button.tsx +192 -0
  833. package/src/ink/components/ClockContext.tsx +112 -0
  834. package/src/ink/components/CursorDeclarationContext.ts +32 -0
  835. package/src/ink/components/ErrorOverview.tsx +109 -0
  836. package/src/ink/components/Link.tsx +42 -0
  837. package/src/ink/components/Newline.tsx +39 -0
  838. package/src/ink/components/NoSelect.tsx +68 -0
  839. package/src/ink/components/RawAnsi.tsx +57 -0
  840. package/src/ink/components/ScrollBox.tsx +237 -0
  841. package/src/ink/components/Spacer.tsx +20 -0
  842. package/src/ink/components/StdinContext.ts +49 -0
  843. package/src/ink/components/TerminalFocusContext.tsx +52 -0
  844. package/src/ink/components/TerminalSizeContext.tsx +7 -0
  845. package/src/ink/components/Text.tsx +254 -0
  846. package/src/ink/constants.ts +2 -0
  847. package/src/ink/dom.ts +484 -0
  848. package/src/ink/events/click-event.ts +38 -0
  849. package/src/ink/events/dispatcher.ts +233 -0
  850. package/src/ink/events/emitter.ts +39 -0
  851. package/src/ink/events/event-handlers.ts +73 -0
  852. package/src/ink/events/event.ts +11 -0
  853. package/src/ink/events/focus-event.ts +21 -0
  854. package/src/ink/events/input-event.ts +205 -0
  855. package/src/ink/events/keyboard-event.ts +51 -0
  856. package/src/ink/events/terminal-event.ts +107 -0
  857. package/src/ink/events/terminal-focus-event.ts +19 -0
  858. package/src/ink/focus.ts +181 -0
  859. package/src/ink/frame.ts +124 -0
  860. package/src/ink/get-max-width.ts +27 -0
  861. package/src/ink/global.ts +2 -0
  862. package/src/ink/hit-test.ts +130 -0
  863. package/src/ink/hooks/use-animation-frame.ts +57 -0
  864. package/src/ink/hooks/use-app.ts +8 -0
  865. package/src/ink/hooks/use-declared-cursor.ts +73 -0
  866. package/src/ink/hooks/use-input.ts +92 -0
  867. package/src/ink/hooks/use-interval.ts +67 -0
  868. package/src/ink/hooks/use-search-highlight.ts +53 -0
  869. package/src/ink/hooks/use-selection.ts +104 -0
  870. package/src/ink/hooks/use-stdin.ts +8 -0
  871. package/src/ink/hooks/use-tab-status.ts +72 -0
  872. package/src/ink/hooks/use-terminal-focus.ts +16 -0
  873. package/src/ink/hooks/use-terminal-title.ts +31 -0
  874. package/src/ink/hooks/use-terminal-viewport.ts +96 -0
  875. package/src/ink/ink.tsx +1723 -0
  876. package/src/ink/instances.ts +10 -0
  877. package/src/ink/layout/engine.ts +6 -0
  878. package/src/ink/layout/geometry.ts +97 -0
  879. package/src/ink/layout/node.ts +152 -0
  880. package/src/ink/layout/yoga.ts +308 -0
  881. package/src/ink/line-width-cache.ts +24 -0
  882. package/src/ink/log-update.ts +773 -0
  883. package/src/ink/measure-element.ts +23 -0
  884. package/src/ink/measure-text.ts +47 -0
  885. package/src/ink/node-cache.ts +54 -0
  886. package/src/ink/optimizer.ts +93 -0
  887. package/src/ink/output.ts +797 -0
  888. package/src/ink/parse-keypress.ts +801 -0
  889. package/src/ink/reconciler.ts +512 -0
  890. package/src/ink/render-border.ts +231 -0
  891. package/src/ink/render-node-to-output.ts +1462 -0
  892. package/src/ink/render-to-screen.ts +231 -0
  893. package/src/ink/renderer.ts +178 -0
  894. package/src/ink/root.ts +184 -0
  895. package/src/ink/screen.ts +1486 -0
  896. package/src/ink/searchHighlight.ts +93 -0
  897. package/src/ink/selection.ts +917 -0
  898. package/src/ink/squash-text-nodes.ts +92 -0
  899. package/src/ink/stringWidth.ts +222 -0
  900. package/src/ink/styles.ts +771 -0
  901. package/src/ink/supports-hyperlinks.ts +57 -0
  902. package/src/ink/tabstops.ts +46 -0
  903. package/src/ink/terminal-focus-state.ts +47 -0
  904. package/src/ink/terminal-querier.ts +212 -0
  905. package/src/ink/terminal.ts +248 -0
  906. package/src/ink/termio/ansi.ts +75 -0
  907. package/src/ink/termio/csi.ts +319 -0
  908. package/src/ink/termio/dec.ts +60 -0
  909. package/src/ink/termio/esc.ts +67 -0
  910. package/src/ink/termio/osc.ts +493 -0
  911. package/src/ink/termio/parser.ts +394 -0
  912. package/src/ink/termio/sgr.ts +308 -0
  913. package/src/ink/termio/tokenize.ts +319 -0
  914. package/src/ink/termio/types.ts +236 -0
  915. package/src/ink/termio.ts +42 -0
  916. package/src/ink/useTerminalNotification.ts +126 -0
  917. package/src/ink/warn.ts +9 -0
  918. package/src/ink/widest-line.ts +19 -0
  919. package/src/ink/wrap-text.ts +74 -0
  920. package/src/ink/wrapAnsi.ts +20 -0
  921. package/src/ink.ts +85 -0
  922. package/src/interactiveHelpers.tsx +367 -0
  923. package/src/keybindings/KeybindingContext.tsx +243 -0
  924. package/src/keybindings/KeybindingProviderSetup.tsx +308 -0
  925. package/src/keybindings/defaultBindings.ts +340 -0
  926. package/src/keybindings/loadUserBindings.ts +472 -0
  927. package/src/keybindings/match.ts +120 -0
  928. package/src/keybindings/parser.ts +203 -0
  929. package/src/keybindings/reservedShortcuts.ts +127 -0
  930. package/src/keybindings/resolver.ts +244 -0
  931. package/src/keybindings/schema.ts +236 -0
  932. package/src/keybindings/shortcutFormat.ts +63 -0
  933. package/src/keybindings/template.ts +52 -0
  934. package/src/keybindings/useKeybinding.ts +196 -0
  935. package/src/keybindings/useShortcutDisplay.ts +59 -0
  936. package/src/keybindings/validate.ts +498 -0
  937. package/src/main.tsx +4756 -0
  938. package/src/memdir/findRelevantMemories.ts +141 -0
  939. package/src/memdir/memdir.ts +507 -0
  940. package/src/memdir/memoryAge.ts +53 -0
  941. package/src/memdir/memoryScan.ts +94 -0
  942. package/src/memdir/memoryTypes.ts +271 -0
  943. package/src/memdir/paths.ts +278 -0
  944. package/src/memdir/teamMemPaths.ts +292 -0
  945. package/src/memdir/teamMemPrompts.ts +100 -0
  946. package/src/migrations/migrateAutoUpdatesToSettings.ts +61 -0
  947. package/src/migrations/migrateBypassPermissionsAcceptedToSettings.ts +40 -0
  948. package/src/migrations/migrateEnableAllProjectMcpServersToSettings.ts +118 -0
  949. package/src/migrations/migrateFennecToOpus.ts +45 -0
  950. package/src/migrations/migrateLegacyOpusToCurrent.ts +57 -0
  951. package/src/migrations/migrateOpusToOpus1m.ts +43 -0
  952. package/src/migrations/migrateReplBridgeEnabledToRemoteControlAtStartup.ts +22 -0
  953. package/src/migrations/migrateSonnet1mToSonnet45.ts +48 -0
  954. package/src/migrations/migrateSonnet45ToSonnet46.ts +67 -0
  955. package/src/migrations/resetAutoModeOptInForDefaultOffer.ts +51 -0
  956. package/src/migrations/resetProToOpusDefault.ts +51 -0
  957. package/src/moreright/useMoreRight.tsx +26 -0
  958. package/src/native-ts/color-diff/index.ts +999 -0
  959. package/src/native-ts/file-index/index.ts +370 -0
  960. package/src/native-ts/yoga-layout/enums.ts +134 -0
  961. package/src/native-ts/yoga-layout/index.ts +2578 -0
  962. package/src/outputStyles/loadOutputStylesDir.ts +98 -0
  963. package/src/plugins/builtinPlugins.ts +159 -0
  964. package/src/plugins/bundled/index.ts +23 -0
  965. package/src/projectOnboardingState.ts +83 -0
  966. package/src/query/config.ts +48 -0
  967. package/src/query/deps.ts +40 -0
  968. package/src/query/stopHooks.ts +473 -0
  969. package/src/query/tokenBudget.ts +93 -0
  970. package/src/query.ts +1729 -0
  971. package/src/remote/RemoteSessionManager.ts +343 -0
  972. package/src/remote/SessionsWebSocket.ts +404 -0
  973. package/src/remote/remotePermissionBridge.ts +78 -0
  974. package/src/remote/sdkMessageAdapter.ts +302 -0
  975. package/src/replLauncher.tsx +22 -0
  976. package/src/schemas/hooks.ts +222 -0
  977. package/src/screens/Doctor.tsx +575 -0
  978. package/src/screens/REPL.tsx +5052 -0
  979. package/src/screens/ResumeConversation.tsx +399 -0
  980. package/src/server/createDirectConnectSession.ts +88 -0
  981. package/src/server/directConnectManager.ts +213 -0
  982. package/src/server/types.ts +57 -0
  983. package/src/services/AgentSummary/agentSummary.ts +179 -0
  984. package/src/services/MagicDocs/magicDocs.ts +254 -0
  985. package/src/services/MagicDocs/prompts.ts +127 -0
  986. package/src/services/PromptSuggestion/promptSuggestion.ts +523 -0
  987. package/src/services/PromptSuggestion/speculation.ts +991 -0
  988. package/src/services/SessionMemory/prompts.ts +324 -0
  989. package/src/services/SessionMemory/sessionMemory.ts +495 -0
  990. package/src/services/SessionMemory/sessionMemoryUtils.ts +207 -0
  991. package/src/services/analytics/config.ts +40 -0
  992. package/src/services/analytics/datadog.ts +307 -0
  993. package/src/services/analytics/firstPartyEventLogger.ts +450 -0
  994. package/src/services/analytics/firstPartyEventLoggingExporter.ts +806 -0
  995. package/src/services/analytics/growthbook.ts +1155 -0
  996. package/src/services/analytics/index.ts +173 -0
  997. package/src/services/analytics/metadata.ts +974 -0
  998. package/src/services/analytics/sink.ts +114 -0
  999. package/src/services/analytics/sinkKillswitch.ts +25 -0
  1000. package/src/services/api/adminRequests.ts +119 -0
  1001. package/src/services/api/bootstrap.ts +190 -0
  1002. package/src/services/api/claude.ts +3419 -0
  1003. package/src/services/api/client.ts +425 -0
  1004. package/src/services/api/dumpPrompts.ts +226 -0
  1005. package/src/services/api/emptyUsage.ts +22 -0
  1006. package/src/services/api/errorUtils.ts +260 -0
  1007. package/src/services/api/errors.ts +1207 -0
  1008. package/src/services/api/filesApi.ts +748 -0
  1009. package/src/services/api/firstTokenDate.ts +60 -0
  1010. package/src/services/api/grove.ts +357 -0
  1011. package/src/services/api/logging.ts +788 -0
  1012. package/src/services/api/metricsOptOut.ts +159 -0
  1013. package/src/services/api/overageCreditGrant.ts +137 -0
  1014. package/src/services/api/promptCacheBreakDetection.ts +727 -0
  1015. package/src/services/api/referral.ts +281 -0
  1016. package/src/services/api/sessionIngress.ts +514 -0
  1017. package/src/services/api/ultrareviewQuota.ts +38 -0
  1018. package/src/services/api/usage.ts +63 -0
  1019. package/src/services/api/withRetry.ts +822 -0
  1020. package/src/services/autoDream/autoDream.ts +324 -0
  1021. package/src/services/autoDream/config.ts +21 -0
  1022. package/src/services/autoDream/consolidationLock.ts +140 -0
  1023. package/src/services/autoDream/consolidationPrompt.ts +65 -0
  1024. package/src/services/awaySummary.ts +74 -0
  1025. package/src/services/claudeAiLimits.ts +515 -0
  1026. package/src/services/claudeAiLimitsHook.ts +23 -0
  1027. package/src/services/compact/apiMicrocompact.ts +153 -0
  1028. package/src/services/compact/autoCompact.ts +351 -0
  1029. package/src/services/compact/compact.ts +1705 -0
  1030. package/src/services/compact/compactWarningHook.ts +16 -0
  1031. package/src/services/compact/compactWarningState.ts +18 -0
  1032. package/src/services/compact/grouping.ts +63 -0
  1033. package/src/services/compact/microCompact.ts +530 -0
  1034. package/src/services/compact/postCompactCleanup.ts +77 -0
  1035. package/src/services/compact/prompt.ts +374 -0
  1036. package/src/services/compact/sessionMemoryCompact.ts +630 -0
  1037. package/src/services/compact/timeBasedMCConfig.ts +43 -0
  1038. package/src/services/copilot/provider.ts +1603 -0
  1039. package/src/services/diagnosticTracking.ts +397 -0
  1040. package/src/services/extractMemories/extractMemories.ts +615 -0
  1041. package/src/services/extractMemories/prompts.ts +154 -0
  1042. package/src/services/internalLogging.ts +90 -0
  1043. package/src/services/lsp/LSPClient.ts +447 -0
  1044. package/src/services/lsp/LSPDiagnosticRegistry.ts +386 -0
  1045. package/src/services/lsp/LSPServerInstance.ts +511 -0
  1046. package/src/services/lsp/LSPServerManager.ts +420 -0
  1047. package/src/services/lsp/config.ts +79 -0
  1048. package/src/services/lsp/manager.ts +289 -0
  1049. package/src/services/lsp/passiveFeedback.ts +328 -0
  1050. package/src/services/mcp/InProcessTransport.ts +63 -0
  1051. package/src/services/mcp/MCPConnectionManager.tsx +73 -0
  1052. package/src/services/mcp/SdkControlTransport.ts +136 -0
  1053. package/src/services/mcp/auth.ts +2465 -0
  1054. package/src/services/mcp/channelAllowlist.ts +76 -0
  1055. package/src/services/mcp/channelNotification.ts +316 -0
  1056. package/src/services/mcp/channelPermissions.ts +240 -0
  1057. package/src/services/mcp/claudeai.ts +164 -0
  1058. package/src/services/mcp/client.ts +3349 -0
  1059. package/src/services/mcp/config.ts +1578 -0
  1060. package/src/services/mcp/elicitationHandler.ts +313 -0
  1061. package/src/services/mcp/envExpansion.ts +38 -0
  1062. package/src/services/mcp/headersHelper.ts +138 -0
  1063. package/src/services/mcp/mcpStringUtils.ts +106 -0
  1064. package/src/services/mcp/normalization.ts +23 -0
  1065. package/src/services/mcp/oauthPort.ts +78 -0
  1066. package/src/services/mcp/officialRegistry.ts +72 -0
  1067. package/src/services/mcp/types.ts +258 -0
  1068. package/src/services/mcp/useManageMCPConnections.ts +1141 -0
  1069. package/src/services/mcp/utils.ts +575 -0
  1070. package/src/services/mcp/vscodeSdkMcp.ts +112 -0
  1071. package/src/services/mcp/xaa.ts +511 -0
  1072. package/src/services/mcp/xaaIdpLogin.ts +487 -0
  1073. package/src/services/mcpServerApproval.tsx +41 -0
  1074. package/src/services/mockRateLimits.ts +882 -0
  1075. package/src/services/notifier.ts +156 -0
  1076. package/src/services/oauth/auth-code-listener.ts +211 -0
  1077. package/src/services/oauth/client.ts +566 -0
  1078. package/src/services/oauth/crypto.ts +23 -0
  1079. package/src/services/oauth/getOauthProfile.ts +53 -0
  1080. package/src/services/oauth/index.ts +198 -0
  1081. package/src/services/openrouter/provider.ts +129 -0
  1082. package/src/services/plugins/PluginInstallationManager.ts +184 -0
  1083. package/src/services/plugins/pluginCliCommands.ts +344 -0
  1084. package/src/services/plugins/pluginOperations.ts +1088 -0
  1085. package/src/services/policyLimits/index.ts +663 -0
  1086. package/src/services/policyLimits/types.ts +27 -0
  1087. package/src/services/preventSleep.ts +165 -0
  1088. package/src/services/providerCatalog.test.ts +124 -0
  1089. package/src/services/rateLimitMessages.ts +344 -0
  1090. package/src/services/rateLimitMocking.ts +144 -0
  1091. package/src/services/remoteManagedSettings/index.ts +638 -0
  1092. package/src/services/remoteManagedSettings/securityCheck.tsx +74 -0
  1093. package/src/services/remoteManagedSettings/syncCache.ts +112 -0
  1094. package/src/services/remoteManagedSettings/syncCacheState.ts +96 -0
  1095. package/src/services/remoteManagedSettings/types.ts +31 -0
  1096. package/src/services/settingsSync/index.ts +581 -0
  1097. package/src/services/settingsSync/types.ts +67 -0
  1098. package/src/services/teamMemorySync/index.ts +1256 -0
  1099. package/src/services/teamMemorySync/secretScanner.ts +324 -0
  1100. package/src/services/teamMemorySync/teamMemSecretGuard.ts +44 -0
  1101. package/src/services/teamMemorySync/types.ts +156 -0
  1102. package/src/services/teamMemorySync/watcher.ts +387 -0
  1103. package/src/services/tips/tipHistory.ts +17 -0
  1104. package/src/services/tips/tipRegistry.ts +686 -0
  1105. package/src/services/tips/tipScheduler.ts +58 -0
  1106. package/src/services/tokenEstimation.ts +503 -0
  1107. package/src/services/toolUseSummary/toolUseSummaryGenerator.ts +112 -0
  1108. package/src/services/tools/StreamingToolExecutor.ts +530 -0
  1109. package/src/services/tools/toolExecution.ts +1745 -0
  1110. package/src/services/tools/toolHooks.ts +650 -0
  1111. package/src/services/tools/toolOrchestration.ts +188 -0
  1112. package/src/services/vcr.ts +406 -0
  1113. package/src/services/voice.ts +525 -0
  1114. package/src/services/voiceKeyterms.ts +106 -0
  1115. package/src/services/voiceStreamSTT.ts +544 -0
  1116. package/src/setup.ts +477 -0
  1117. package/src/skills/bundled/batch.ts +124 -0
  1118. package/src/skills/bundled/claudeApi.ts +196 -0
  1119. package/src/skills/bundled/claudeApiContent.ts +75 -0
  1120. package/src/skills/bundled/claudeInChrome.ts +34 -0
  1121. package/src/skills/bundled/debug.ts +103 -0
  1122. package/src/skills/bundled/index.ts +79 -0
  1123. package/src/skills/bundled/keybindings.ts +339 -0
  1124. package/src/skills/bundled/loop.ts +92 -0
  1125. package/src/skills/bundled/loremIpsum.ts +282 -0
  1126. package/src/skills/bundled/remember.ts +82 -0
  1127. package/src/skills/bundled/scheduleRemoteAgents.ts +447 -0
  1128. package/src/skills/bundled/simplify.ts +69 -0
  1129. package/src/skills/bundled/skillify.ts +197 -0
  1130. package/src/skills/bundled/stuck.ts +79 -0
  1131. package/src/skills/bundled/updateConfig.ts +475 -0
  1132. package/src/skills/bundled/verify/SKILL.md +3 -0
  1133. package/src/skills/bundled/verify/examples/cli.md +3 -0
  1134. package/src/skills/bundled/verify/examples/server.md +3 -0
  1135. package/src/skills/bundled/verify.ts +30 -0
  1136. package/src/skills/bundled/verifyContent.ts +13 -0
  1137. package/src/skills/bundledSkills.ts +220 -0
  1138. package/src/skills/loadSkillsDir.ts +1086 -0
  1139. package/src/skills/mcpSkillBuilders.ts +44 -0
  1140. package/src/state/AppState.tsx +200 -0
  1141. package/src/state/AppStateStore.ts +572 -0
  1142. package/src/state/onChangeAppState.ts +181 -0
  1143. package/src/state/selectors.ts +76 -0
  1144. package/src/state/store.ts +34 -0
  1145. package/src/state/teammateViewHelpers.ts +141 -0
  1146. package/src/tasks/DreamTask/DreamTask.ts +157 -0
  1147. package/src/tasks/InProcessTeammateTask/InProcessTeammateTask.tsx +126 -0
  1148. package/src/tasks/InProcessTeammateTask/types.ts +121 -0
  1149. package/src/tasks/LocalAgentTask/LocalAgentTask.tsx +683 -0
  1150. package/src/tasks/LocalMainSessionTask.ts +479 -0
  1151. package/src/tasks/LocalShellTask/LocalShellTask.tsx +523 -0
  1152. package/src/tasks/LocalShellTask/guards.ts +41 -0
  1153. package/src/tasks/LocalShellTask/killShellTasks.ts +76 -0
  1154. package/src/tasks/RemoteAgentTask/RemoteAgentTask.tsx +856 -0
  1155. package/src/tasks/pillLabel.ts +82 -0
  1156. package/src/tasks/stopTask.ts +100 -0
  1157. package/src/tasks/types.ts +46 -0
  1158. package/src/tasks.ts +39 -0
  1159. package/src/tools/AgentTool/AgentTool.tsx +1398 -0
  1160. package/src/tools/AgentTool/UI.tsx +872 -0
  1161. package/src/tools/AgentTool/agentColorManager.ts +66 -0
  1162. package/src/tools/AgentTool/agentDisplay.ts +104 -0
  1163. package/src/tools/AgentTool/agentMemory.ts +177 -0
  1164. package/src/tools/AgentTool/agentMemorySnapshot.ts +197 -0
  1165. package/src/tools/AgentTool/agentToolUtils.ts +686 -0
  1166. package/src/tools/AgentTool/built-in/claudeCodeGuideAgent.ts +205 -0
  1167. package/src/tools/AgentTool/built-in/exploreAgent.ts +83 -0
  1168. package/src/tools/AgentTool/built-in/generalPurposeAgent.ts +34 -0
  1169. package/src/tools/AgentTool/built-in/planAgent.ts +92 -0
  1170. package/src/tools/AgentTool/built-in/statuslineSetup.ts +144 -0
  1171. package/src/tools/AgentTool/built-in/verificationAgent.ts +152 -0
  1172. package/src/tools/AgentTool/builtInAgents.ts +72 -0
  1173. package/src/tools/AgentTool/constants.ts +12 -0
  1174. package/src/tools/AgentTool/forkSubagent.ts +210 -0
  1175. package/src/tools/AgentTool/loadAgentsDir.ts +755 -0
  1176. package/src/tools/AgentTool/prompt.ts +287 -0
  1177. package/src/tools/AgentTool/resumeAgent.ts +265 -0
  1178. package/src/tools/AgentTool/runAgent.ts +973 -0
  1179. package/src/tools/AskUserQuestionTool/AskUserQuestionTool.tsx +266 -0
  1180. package/src/tools/AskUserQuestionTool/prompt.ts +44 -0
  1181. package/src/tools/BashTool/BashTool.tsx +1144 -0
  1182. package/src/tools/BashTool/BashToolResultMessage.tsx +191 -0
  1183. package/src/tools/BashTool/UI.tsx +185 -0
  1184. package/src/tools/BashTool/bashCommandHelpers.ts +265 -0
  1185. package/src/tools/BashTool/bashPermissions.ts +2621 -0
  1186. package/src/tools/BashTool/bashSecurity.ts +2592 -0
  1187. package/src/tools/BashTool/commandSemantics.ts +140 -0
  1188. package/src/tools/BashTool/commentLabel.ts +13 -0
  1189. package/src/tools/BashTool/destructiveCommandWarning.ts +102 -0
  1190. package/src/tools/BashTool/modeValidation.ts +115 -0
  1191. package/src/tools/BashTool/pathValidation.ts +1303 -0
  1192. package/src/tools/BashTool/prompt.ts +369 -0
  1193. package/src/tools/BashTool/readOnlyValidation.ts +1990 -0
  1194. package/src/tools/BashTool/sedEditParser.ts +322 -0
  1195. package/src/tools/BashTool/sedValidation.ts +684 -0
  1196. package/src/tools/BashTool/shouldUseSandbox.ts +153 -0
  1197. package/src/tools/BashTool/toolName.ts +2 -0
  1198. package/src/tools/BashTool/utils.ts +223 -0
  1199. package/src/tools/BriefTool/BriefTool.ts +204 -0
  1200. package/src/tools/BriefTool/UI.tsx +101 -0
  1201. package/src/tools/BriefTool/attachments.ts +110 -0
  1202. package/src/tools/BriefTool/prompt.ts +22 -0
  1203. package/src/tools/BriefTool/upload.ts +174 -0
  1204. package/src/tools/ConfigTool/ConfigTool.ts +467 -0
  1205. package/src/tools/ConfigTool/UI.tsx +38 -0
  1206. package/src/tools/ConfigTool/constants.ts +1 -0
  1207. package/src/tools/ConfigTool/prompt.ts +93 -0
  1208. package/src/tools/ConfigTool/supportedSettings.ts +211 -0
  1209. package/src/tools/EnterPlanModeTool/EnterPlanModeTool.ts +126 -0
  1210. package/src/tools/EnterPlanModeTool/UI.tsx +33 -0
  1211. package/src/tools/EnterPlanModeTool/constants.ts +1 -0
  1212. package/src/tools/EnterPlanModeTool/prompt.ts +170 -0
  1213. package/src/tools/EnterWorktreeTool/EnterWorktreeTool.ts +127 -0
  1214. package/src/tools/EnterWorktreeTool/UI.tsx +20 -0
  1215. package/src/tools/EnterWorktreeTool/constants.ts +1 -0
  1216. package/src/tools/EnterWorktreeTool/prompt.ts +30 -0
  1217. package/src/tools/ExitPlanModeTool/ExitPlanModeV2Tool.ts +493 -0
  1218. package/src/tools/ExitPlanModeTool/UI.tsx +82 -0
  1219. package/src/tools/ExitPlanModeTool/constants.ts +2 -0
  1220. package/src/tools/ExitPlanModeTool/prompt.ts +29 -0
  1221. package/src/tools/ExitWorktreeTool/ExitWorktreeTool.ts +329 -0
  1222. package/src/tools/ExitWorktreeTool/UI.tsx +25 -0
  1223. package/src/tools/ExitWorktreeTool/constants.ts +1 -0
  1224. package/src/tools/ExitWorktreeTool/prompt.ts +32 -0
  1225. package/src/tools/FileEditTool/FileEditTool.ts +628 -0
  1226. package/src/tools/FileEditTool/UI.tsx +289 -0
  1227. package/src/tools/FileEditTool/constants.ts +11 -0
  1228. package/src/tools/FileEditTool/prompt.ts +28 -0
  1229. package/src/tools/FileEditTool/types.ts +85 -0
  1230. package/src/tools/FileEditTool/utils.ts +775 -0
  1231. package/src/tools/FileReadTool/FileReadTool.ts +1183 -0
  1232. package/src/tools/FileReadTool/UI.tsx +185 -0
  1233. package/src/tools/FileReadTool/imageProcessor.ts +94 -0
  1234. package/src/tools/FileReadTool/limits.ts +92 -0
  1235. package/src/tools/FileReadTool/prompt.ts +49 -0
  1236. package/src/tools/FileWriteTool/FileWriteTool.ts +437 -0
  1237. package/src/tools/FileWriteTool/UI.tsx +405 -0
  1238. package/src/tools/FileWriteTool/prompt.ts +18 -0
  1239. package/src/tools/GlobTool/GlobTool.ts +198 -0
  1240. package/src/tools/GlobTool/UI.tsx +63 -0
  1241. package/src/tools/GlobTool/prompt.ts +7 -0
  1242. package/src/tools/GrepTool/GrepTool.ts +577 -0
  1243. package/src/tools/GrepTool/UI.tsx +201 -0
  1244. package/src/tools/GrepTool/prompt.ts +18 -0
  1245. package/src/tools/LSPTool/LSPTool.ts +860 -0
  1246. package/src/tools/LSPTool/UI.tsx +228 -0
  1247. package/src/tools/LSPTool/formatters.ts +592 -0
  1248. package/src/tools/LSPTool/prompt.ts +21 -0
  1249. package/src/tools/LSPTool/schemas.ts +215 -0
  1250. package/src/tools/LSPTool/symbolContext.ts +90 -0
  1251. package/src/tools/ListMcpResourcesTool/ListMcpResourcesTool.ts +123 -0
  1252. package/src/tools/ListMcpResourcesTool/UI.tsx +29 -0
  1253. package/src/tools/ListMcpResourcesTool/prompt.ts +20 -0
  1254. package/src/tools/MCPTool/MCPTool.ts +77 -0
  1255. package/src/tools/MCPTool/UI.tsx +403 -0
  1256. package/src/tools/MCPTool/classifyForCollapse.ts +604 -0
  1257. package/src/tools/MCPTool/prompt.ts +3 -0
  1258. package/src/tools/McpAuthTool/McpAuthTool.ts +215 -0
  1259. package/src/tools/NotebookEditTool/NotebookEditTool.ts +493 -0
  1260. package/src/tools/NotebookEditTool/UI.tsx +93 -0
  1261. package/src/tools/NotebookEditTool/constants.ts +2 -0
  1262. package/src/tools/NotebookEditTool/prompt.ts +3 -0
  1263. package/src/tools/PowerShellTool/PowerShellTool.tsx +1001 -0
  1264. package/src/tools/PowerShellTool/UI.tsx +131 -0
  1265. package/src/tools/PowerShellTool/clmTypes.ts +211 -0
  1266. package/src/tools/PowerShellTool/commandSemantics.ts +142 -0
  1267. package/src/tools/PowerShellTool/commonParameters.ts +30 -0
  1268. package/src/tools/PowerShellTool/destructiveCommandWarning.ts +109 -0
  1269. package/src/tools/PowerShellTool/gitSafety.ts +176 -0
  1270. package/src/tools/PowerShellTool/modeValidation.ts +404 -0
  1271. package/src/tools/PowerShellTool/pathValidation.ts +2049 -0
  1272. package/src/tools/PowerShellTool/powershellPermissions.ts +1648 -0
  1273. package/src/tools/PowerShellTool/powershellSecurity.ts +1090 -0
  1274. package/src/tools/PowerShellTool/prompt.ts +145 -0
  1275. package/src/tools/PowerShellTool/readOnlyValidation.ts +1823 -0
  1276. package/src/tools/PowerShellTool/toolName.ts +2 -0
  1277. package/src/tools/REPLTool/constants.ts +46 -0
  1278. package/src/tools/REPLTool/primitiveTools.ts +39 -0
  1279. package/src/tools/ReadMcpResourceTool/ReadMcpResourceTool.ts +158 -0
  1280. package/src/tools/ReadMcpResourceTool/UI.tsx +37 -0
  1281. package/src/tools/ReadMcpResourceTool/prompt.ts +16 -0
  1282. package/src/tools/RemoteTriggerTool/RemoteTriggerTool.ts +161 -0
  1283. package/src/tools/RemoteTriggerTool/UI.tsx +17 -0
  1284. package/src/tools/RemoteTriggerTool/prompt.ts +15 -0
  1285. package/src/tools/ScheduleCronTool/CronCreateTool.ts +157 -0
  1286. package/src/tools/ScheduleCronTool/CronDeleteTool.ts +95 -0
  1287. package/src/tools/ScheduleCronTool/CronListTool.ts +97 -0
  1288. package/src/tools/ScheduleCronTool/UI.tsx +60 -0
  1289. package/src/tools/ScheduleCronTool/prompt.ts +135 -0
  1290. package/src/tools/SendMessageTool/SendMessageTool.ts +917 -0
  1291. package/src/tools/SendMessageTool/UI.tsx +31 -0
  1292. package/src/tools/SendMessageTool/constants.ts +1 -0
  1293. package/src/tools/SendMessageTool/prompt.ts +49 -0
  1294. package/src/tools/SkillTool/SkillTool.ts +1108 -0
  1295. package/src/tools/SkillTool/UI.tsx +128 -0
  1296. package/src/tools/SkillTool/constants.ts +1 -0
  1297. package/src/tools/SkillTool/prompt.ts +241 -0
  1298. package/src/tools/SleepTool/prompt.ts +17 -0
  1299. package/src/tools/SyntheticOutputTool/SyntheticOutputTool.ts +163 -0
  1300. package/src/tools/TaskCreateTool/TaskCreateTool.ts +138 -0
  1301. package/src/tools/TaskCreateTool/constants.ts +1 -0
  1302. package/src/tools/TaskCreateTool/prompt.ts +56 -0
  1303. package/src/tools/TaskGetTool/TaskGetTool.ts +128 -0
  1304. package/src/tools/TaskGetTool/constants.ts +1 -0
  1305. package/src/tools/TaskGetTool/prompt.ts +24 -0
  1306. package/src/tools/TaskListTool/TaskListTool.ts +116 -0
  1307. package/src/tools/TaskListTool/constants.ts +1 -0
  1308. package/src/tools/TaskListTool/prompt.ts +49 -0
  1309. package/src/tools/TaskOutputTool/TaskOutputTool.tsx +584 -0
  1310. package/src/tools/TaskOutputTool/constants.ts +1 -0
  1311. package/src/tools/TaskStopTool/TaskStopTool.ts +131 -0
  1312. package/src/tools/TaskStopTool/UI.tsx +41 -0
  1313. package/src/tools/TaskStopTool/prompt.ts +8 -0
  1314. package/src/tools/TaskUpdateTool/TaskUpdateTool.ts +406 -0
  1315. package/src/tools/TaskUpdateTool/constants.ts +1 -0
  1316. package/src/tools/TaskUpdateTool/prompt.ts +77 -0
  1317. package/src/tools/TeamCreateTool/TeamCreateTool.ts +240 -0
  1318. package/src/tools/TeamCreateTool/UI.tsx +6 -0
  1319. package/src/tools/TeamCreateTool/constants.ts +1 -0
  1320. package/src/tools/TeamCreateTool/prompt.ts +113 -0
  1321. package/src/tools/TeamDeleteTool/TeamDeleteTool.ts +139 -0
  1322. package/src/tools/TeamDeleteTool/UI.tsx +20 -0
  1323. package/src/tools/TeamDeleteTool/constants.ts +1 -0
  1324. package/src/tools/TeamDeleteTool/prompt.ts +16 -0
  1325. package/src/tools/TodoWriteTool/TodoWriteTool.ts +115 -0
  1326. package/src/tools/TodoWriteTool/constants.ts +1 -0
  1327. package/src/tools/TodoWriteTool/prompt.ts +184 -0
  1328. package/src/tools/ToolSearchTool/ToolSearchTool.ts +471 -0
  1329. package/src/tools/ToolSearchTool/constants.ts +1 -0
  1330. package/src/tools/ToolSearchTool/prompt.ts +121 -0
  1331. package/src/tools/WebFetchTool/UI.tsx +72 -0
  1332. package/src/tools/WebFetchTool/WebFetchTool.ts +318 -0
  1333. package/src/tools/WebFetchTool/preapproved.ts +166 -0
  1334. package/src/tools/WebFetchTool/prompt.ts +46 -0
  1335. package/src/tools/WebFetchTool/utils.ts +530 -0
  1336. package/src/tools/WebSearchTool/UI.tsx +101 -0
  1337. package/src/tools/WebSearchTool/WebSearchTool.ts +444 -0
  1338. package/src/tools/WebSearchTool/prompt.ts +34 -0
  1339. package/src/tools/WorkflowTool/constants.ts +2 -0
  1340. package/src/tools/shared/gitOperationTracking.ts +277 -0
  1341. package/src/tools/shared/spawnMultiAgent.ts +1026 -0
  1342. package/src/tools/testing/TestingPermissionTool.tsx +74 -0
  1343. package/src/tools/utils.ts +40 -0
  1344. package/src/tools.ts +392 -0
  1345. package/src/types/command.ts +216 -0
  1346. package/src/types/connectorText.ts +24 -0
  1347. package/src/types/generated/events_mono/claude_code/v1/claude_code_internal_event.ts +865 -0
  1348. package/src/types/generated/events_mono/common/v1/auth.ts +100 -0
  1349. package/src/types/generated/events_mono/growthbook/v1/growthbook_experiment_event.ts +223 -0
  1350. package/src/types/generated/google/protobuf/timestamp.ts +187 -0
  1351. package/src/types/hooks.ts +290 -0
  1352. package/src/types/ids.ts +44 -0
  1353. package/src/types/logs.ts +330 -0
  1354. package/src/types/permissions.ts +441 -0
  1355. package/src/types/plugin.ts +363 -0
  1356. package/src/types/textInputTypes.ts +387 -0
  1357. package/src/upstreamproxy/relay.ts +455 -0
  1358. package/src/upstreamproxy/upstreamproxy.ts +285 -0
  1359. package/src/utils/CircularBuffer.ts +84 -0
  1360. package/src/utils/Cursor.ts +1530 -0
  1361. package/src/utils/QueryGuard.ts +121 -0
  1362. package/src/utils/Shell.ts +474 -0
  1363. package/src/utils/ShellCommand.ts +465 -0
  1364. package/src/utils/abortController.ts +99 -0
  1365. package/src/utils/activityManager.ts +164 -0
  1366. package/src/utils/advisor.ts +145 -0
  1367. package/src/utils/agentContext.ts +178 -0
  1368. package/src/utils/agentId.ts +99 -0
  1369. package/src/utils/agentSwarmsEnabled.ts +44 -0
  1370. package/src/utils/agenticSessionSearch.ts +307 -0
  1371. package/src/utils/analyzeContext.ts +1382 -0
  1372. package/src/utils/ansiToPng.ts +334 -0
  1373. package/src/utils/ansiToSvg.ts +272 -0
  1374. package/src/utils/api.ts +718 -0
  1375. package/src/utils/apiPreconnect.ts +75 -0
  1376. package/src/utils/appVersion.ts +6 -0
  1377. package/src/utils/appleTerminalBackup.ts +124 -0
  1378. package/src/utils/argumentSubstitution.ts +145 -0
  1379. package/src/utils/array.ts +13 -0
  1380. package/src/utils/asciicast.ts +239 -0
  1381. package/src/utils/attachments.ts +3997 -0
  1382. package/src/utils/attribution.ts +393 -0
  1383. package/src/utils/auth.ts +2056 -0
  1384. package/src/utils/authFileDescriptor.ts +196 -0
  1385. package/src/utils/authPortable.ts +19 -0
  1386. package/src/utils/autoModeDenials.ts +26 -0
  1387. package/src/utils/autoRunIssue.tsx +122 -0
  1388. package/src/utils/autoUpdater.ts +567 -0
  1389. package/src/utils/aws.ts +74 -0
  1390. package/src/utils/awsAuthStatusManager.ts +81 -0
  1391. package/src/utils/background/remote/preconditions.ts +235 -0
  1392. package/src/utils/background/remote/remoteSession.ts +98 -0
  1393. package/src/utils/backgroundHousekeeping.ts +94 -0
  1394. package/src/utils/bash/ParsedCommand.ts +318 -0
  1395. package/src/utils/bash/ShellSnapshot.ts +582 -0
  1396. package/src/utils/bash/ast.ts +2679 -0
  1397. package/src/utils/bash/bashParser.ts +4436 -0
  1398. package/src/utils/bash/bashPipeCommand.ts +294 -0
  1399. package/src/utils/bash/commands.ts +1339 -0
  1400. package/src/utils/bash/heredoc.ts +733 -0
  1401. package/src/utils/bash/parser.ts +230 -0
  1402. package/src/utils/bash/prefix.ts +204 -0
  1403. package/src/utils/bash/registry.ts +53 -0
  1404. package/src/utils/bash/shellCompletion.ts +259 -0
  1405. package/src/utils/bash/shellPrefix.ts +28 -0
  1406. package/src/utils/bash/shellQuote.ts +304 -0
  1407. package/src/utils/bash/shellQuoting.ts +128 -0
  1408. package/src/utils/bash/specs/alias.ts +14 -0
  1409. package/src/utils/bash/specs/index.ts +18 -0
  1410. package/src/utils/bash/specs/nohup.ts +13 -0
  1411. package/src/utils/bash/specs/pyright.ts +91 -0
  1412. package/src/utils/bash/specs/sleep.ts +13 -0
  1413. package/src/utils/bash/specs/srun.ts +31 -0
  1414. package/src/utils/bash/specs/time.ts +13 -0
  1415. package/src/utils/bash/specs/timeout.ts +20 -0
  1416. package/src/utils/bash/treeSitterAnalysis.ts +506 -0
  1417. package/src/utils/betas.ts +440 -0
  1418. package/src/utils/billing.ts +78 -0
  1419. package/src/utils/binaryCheck.ts +53 -0
  1420. package/src/utils/browser.ts +68 -0
  1421. package/src/utils/bufferedWriter.ts +100 -0
  1422. package/src/utils/bundledMode.ts +22 -0
  1423. package/src/utils/caCerts.ts +115 -0
  1424. package/src/utils/caCertsConfig.ts +88 -0
  1425. package/src/utils/cachePaths.ts +38 -0
  1426. package/src/utils/classifierApprovals.ts +88 -0
  1427. package/src/utils/classifierApprovalsHook.ts +17 -0
  1428. package/src/utils/claudeCodeHints.ts +193 -0
  1429. package/src/utils/claudeDesktop.ts +152 -0
  1430. package/src/utils/claudeInChrome/browserTools.ts +19 -0
  1431. package/src/utils/claudeInChrome/chromeNativeHost.ts +527 -0
  1432. package/src/utils/claudeInChrome/common.ts +540 -0
  1433. package/src/utils/claudeInChrome/mcpServer.ts +293 -0
  1434. package/src/utils/claudeInChrome/prompt.ts +83 -0
  1435. package/src/utils/claudeInChrome/setup.ts +400 -0
  1436. package/src/utils/claudeInChrome/setupPortable.ts +233 -0
  1437. package/src/utils/claudeInChrome/toolRendering.tsx +262 -0
  1438. package/src/utils/claudemd.ts +1479 -0
  1439. package/src/utils/cleanup.ts +602 -0
  1440. package/src/utils/cleanupRegistry.ts +25 -0
  1441. package/src/utils/cliArgs.ts +60 -0
  1442. package/src/utils/cliHighlight.ts +54 -0
  1443. package/src/utils/cliSessionEnv.ts +42 -0
  1444. package/src/utils/codeIndexing.ts +206 -0
  1445. package/src/utils/collapseBackgroundBashNotifications.ts +84 -0
  1446. package/src/utils/collapseHookSummaries.ts +59 -0
  1447. package/src/utils/collapseReadSearch.ts +1109 -0
  1448. package/src/utils/collapseTeammateShutdowns.ts +55 -0
  1449. package/src/utils/combinedAbortSignal.ts +47 -0
  1450. package/src/utils/commandLifecycle.ts +21 -0
  1451. package/src/utils/commitAttribution.ts +961 -0
  1452. package/src/utils/completionCache.ts +166 -0
  1453. package/src/utils/computerUse/appNames.ts +196 -0
  1454. package/src/utils/computerUse/cleanup.ts +86 -0
  1455. package/src/utils/computerUse/common.ts +61 -0
  1456. package/src/utils/computerUse/computerUseLock.ts +215 -0
  1457. package/src/utils/computerUse/drainRunLoop.ts +79 -0
  1458. package/src/utils/computerUse/escHotkey.ts +54 -0
  1459. package/src/utils/computerUse/executor.ts +658 -0
  1460. package/src/utils/computerUse/gates.ts +72 -0
  1461. package/src/utils/computerUse/hostAdapter.ts +69 -0
  1462. package/src/utils/computerUse/inputLoader.ts +30 -0
  1463. package/src/utils/computerUse/mcpServer.ts +106 -0
  1464. package/src/utils/computerUse/setup.ts +53 -0
  1465. package/src/utils/computerUse/swiftLoader.ts +23 -0
  1466. package/src/utils/computerUse/toolRendering.tsx +125 -0
  1467. package/src/utils/computerUse/wrapper.tsx +336 -0
  1468. package/src/utils/concurrentSessions.ts +204 -0
  1469. package/src/utils/config.ts +1817 -0
  1470. package/src/utils/configConstants.ts +21 -0
  1471. package/src/utils/contentArray.ts +51 -0
  1472. package/src/utils/context.ts +221 -0
  1473. package/src/utils/contextAnalysis.ts +272 -0
  1474. package/src/utils/contextSuggestions.ts +235 -0
  1475. package/src/utils/controlMessageCompat.ts +32 -0
  1476. package/src/utils/conversationRecovery.ts +597 -0
  1477. package/src/utils/cron.ts +308 -0
  1478. package/src/utils/cronJitterConfig.ts +75 -0
  1479. package/src/utils/cronScheduler.ts +565 -0
  1480. package/src/utils/cronTasks.ts +458 -0
  1481. package/src/utils/cronTasksLock.ts +195 -0
  1482. package/src/utils/crossProjectResume.ts +75 -0
  1483. package/src/utils/crypto.ts +13 -0
  1484. package/src/utils/cwd.ts +32 -0
  1485. package/src/utils/debug.ts +268 -0
  1486. package/src/utils/debugFilter.ts +157 -0
  1487. package/src/utils/deepLink/banner.ts +123 -0
  1488. package/src/utils/deepLink/parseDeepLink.ts +170 -0
  1489. package/src/utils/deepLink/protocolHandler.ts +136 -0
  1490. package/src/utils/deepLink/registerProtocol.ts +348 -0
  1491. package/src/utils/deepLink/terminalLauncher.ts +557 -0
  1492. package/src/utils/deepLink/terminalPreference.ts +54 -0
  1493. package/src/utils/desktopDeepLink.ts +236 -0
  1494. package/src/utils/detectRepository.ts +178 -0
  1495. package/src/utils/diagLogs.ts +94 -0
  1496. package/src/utils/diff.ts +177 -0
  1497. package/src/utils/directMemberMessage.ts +69 -0
  1498. package/src/utils/displayTags.ts +51 -0
  1499. package/src/utils/doctorContextWarnings.ts +265 -0
  1500. package/src/utils/doctorDiagnostic.ts +626 -0
  1501. package/src/utils/dxt/helpers.ts +88 -0
  1502. package/src/utils/dxt/zip.ts +226 -0
  1503. package/src/utils/earlyInput.ts +221 -0
  1504. package/src/utils/editor.ts +183 -0
  1505. package/src/utils/effort.ts +329 -0
  1506. package/src/utils/embeddedTools.ts +29 -0
  1507. package/src/utils/env.ts +347 -0
  1508. package/src/utils/envDynamic.ts +151 -0
  1509. package/src/utils/envUtils.ts +183 -0
  1510. package/src/utils/envValidation.ts +38 -0
  1511. package/src/utils/errorLogSink.ts +236 -0
  1512. package/src/utils/errors.ts +238 -0
  1513. package/src/utils/exampleCommands.ts +184 -0
  1514. package/src/utils/execFileNoThrow.ts +150 -0
  1515. package/src/utils/execFileNoThrowPortable.ts +89 -0
  1516. package/src/utils/execSyncWrapper.ts +38 -0
  1517. package/src/utils/exportRenderer.tsx +98 -0
  1518. package/src/utils/extraUsage.ts +23 -0
  1519. package/src/utils/fastMode.ts +532 -0
  1520. package/src/utils/file.ts +584 -0
  1521. package/src/utils/fileHistory.ts +1115 -0
  1522. package/src/utils/fileOperationAnalytics.ts +71 -0
  1523. package/src/utils/filePersistence/filePersistence.ts +287 -0
  1524. package/src/utils/filePersistence/outputsScanner.ts +126 -0
  1525. package/src/utils/fileRead.ts +102 -0
  1526. package/src/utils/fileReadCache.ts +96 -0
  1527. package/src/utils/fileStateCache.ts +142 -0
  1528. package/src/utils/findExecutable.ts +17 -0
  1529. package/src/utils/fingerprint.ts +77 -0
  1530. package/src/utils/forkedAgent.ts +689 -0
  1531. package/src/utils/format.ts +308 -0
  1532. package/src/utils/formatBriefTimestamp.ts +81 -0
  1533. package/src/utils/fpsTracker.ts +47 -0
  1534. package/src/utils/frontmatterParser.ts +370 -0
  1535. package/src/utils/fsOperations.ts +770 -0
  1536. package/src/utils/fullscreen.ts +202 -0
  1537. package/src/utils/generatedFiles.ts +136 -0
  1538. package/src/utils/generators.ts +88 -0
  1539. package/src/utils/genericProcessUtils.ts +184 -0
  1540. package/src/utils/getWorktreePaths.ts +70 -0
  1541. package/src/utils/getWorktreePathsPortable.ts +27 -0
  1542. package/src/utils/ghPrStatus.ts +106 -0
  1543. package/src/utils/git/gitConfigParser.ts +277 -0
  1544. package/src/utils/git/gitFilesystem.ts +699 -0
  1545. package/src/utils/git/gitignore.ts +99 -0
  1546. package/src/utils/git.ts +926 -0
  1547. package/src/utils/gitDiff.ts +532 -0
  1548. package/src/utils/gitSettings.ts +18 -0
  1549. package/src/utils/github/ghAuthStatus.ts +29 -0
  1550. package/src/utils/githubRepoPathMapping.ts +162 -0
  1551. package/src/utils/glob.ts +130 -0
  1552. package/src/utils/gracefulShutdown.ts +529 -0
  1553. package/src/utils/groupToolUses.ts +182 -0
  1554. package/src/utils/handlePromptSubmit.ts +610 -0
  1555. package/src/utils/hash.ts +46 -0
  1556. package/src/utils/headlessProfiler.ts +178 -0
  1557. package/src/utils/heapDumpService.ts +304 -0
  1558. package/src/utils/heatmap.ts +198 -0
  1559. package/src/utils/highlightMatch.tsx +28 -0
  1560. package/src/utils/hooks/AsyncHookRegistry.ts +309 -0
  1561. package/src/utils/hooks/apiQueryHookHelper.ts +141 -0
  1562. package/src/utils/hooks/execAgentHook.ts +339 -0
  1563. package/src/utils/hooks/execHttpHook.ts +242 -0
  1564. package/src/utils/hooks/execPromptHook.ts +211 -0
  1565. package/src/utils/hooks/fileChangedWatcher.ts +191 -0
  1566. package/src/utils/hooks/hookEvents.ts +192 -0
  1567. package/src/utils/hooks/hookHelpers.ts +83 -0
  1568. package/src/utils/hooks/hooksConfigManager.ts +400 -0
  1569. package/src/utils/hooks/hooksConfigSnapshot.ts +133 -0
  1570. package/src/utils/hooks/hooksSettings.ts +271 -0
  1571. package/src/utils/hooks/postSamplingHooks.ts +70 -0
  1572. package/src/utils/hooks/registerFrontmatterHooks.ts +67 -0
  1573. package/src/utils/hooks/registerSkillHooks.ts +64 -0
  1574. package/src/utils/hooks/sessionHooks.ts +447 -0
  1575. package/src/utils/hooks/skillImprovement.ts +267 -0
  1576. package/src/utils/hooks/ssrfGuard.ts +294 -0
  1577. package/src/utils/hooks.ts +5022 -0
  1578. package/src/utils/horizontalScroll.ts +137 -0
  1579. package/src/utils/http.ts +137 -0
  1580. package/src/utils/hyperlink.ts +39 -0
  1581. package/src/utils/iTermBackup.ts +73 -0
  1582. package/src/utils/ide.ts +1495 -0
  1583. package/src/utils/idePathConversion.ts +90 -0
  1584. package/src/utils/idleTimeout.ts +53 -0
  1585. package/src/utils/imagePaste.ts +416 -0
  1586. package/src/utils/imageResizer.ts +880 -0
  1587. package/src/utils/imageStore.ts +167 -0
  1588. package/src/utils/imageValidation.ts +104 -0
  1589. package/src/utils/immediateCommand.ts +15 -0
  1590. package/src/utils/inProcessTeammateHelpers.ts +102 -0
  1591. package/src/utils/ink.ts +26 -0
  1592. package/src/utils/intl.ts +94 -0
  1593. package/src/utils/jetbrains.ts +191 -0
  1594. package/src/utils/json.ts +277 -0
  1595. package/src/utils/jsonRead.ts +16 -0
  1596. package/src/utils/keyboardShortcuts.ts +14 -0
  1597. package/src/utils/lazySchema.ts +8 -0
  1598. package/src/utils/listSessionsImpl.ts +454 -0
  1599. package/src/utils/localInstaller.ts +162 -0
  1600. package/src/utils/lockfile.ts +43 -0
  1601. package/src/utils/log.ts +364 -0
  1602. package/src/utils/logoV2Utils.ts +351 -0
  1603. package/src/utils/mailbox.ts +73 -0
  1604. package/src/utils/managedEnv.ts +199 -0
  1605. package/src/utils/managedEnvConstants.ts +205 -0
  1606. package/src/utils/markdown.ts +381 -0
  1607. package/src/utils/markdownConfigLoader.ts +600 -0
  1608. package/src/utils/mcp/dateTimeParser.ts +121 -0
  1609. package/src/utils/mcp/elicitationValidation.ts +336 -0
  1610. package/src/utils/mcpInstructionsDelta.ts +130 -0
  1611. package/src/utils/mcpOutputStorage.ts +189 -0
  1612. package/src/utils/mcpValidation.ts +208 -0
  1613. package/src/utils/mcpWebSocketTransport.ts +200 -0
  1614. package/src/utils/memoize.ts +269 -0
  1615. package/src/utils/memory/types.ts +12 -0
  1616. package/src/utils/memory/versions.ts +8 -0
  1617. package/src/utils/memoryFileDetection.ts +289 -0
  1618. package/src/utils/messagePredicates.ts +8 -0
  1619. package/src/utils/messageQueueManager.ts +547 -0
  1620. package/src/utils/messages/mappers.ts +290 -0
  1621. package/src/utils/messages/systemInit.ts +97 -0
  1622. package/src/utils/messages.ts +5512 -0
  1623. package/src/utils/model/agent.ts +157 -0
  1624. package/src/utils/model/aliases.ts +25 -0
  1625. package/src/utils/model/antModels.ts +64 -0
  1626. package/src/utils/model/bedrock.ts +265 -0
  1627. package/src/utils/model/check1mAccess.ts +72 -0
  1628. package/src/utils/model/configs.ts +140 -0
  1629. package/src/utils/model/contextWindowUpgradeCheck.ts +47 -0
  1630. package/src/utils/model/deprecation.ts +104 -0
  1631. package/src/utils/model/model.ts +630 -0
  1632. package/src/utils/model/modelAllowlist.ts +170 -0
  1633. package/src/utils/model/modelCapabilities.ts +118 -0
  1634. package/src/utils/model/modelOptions.ts +651 -0
  1635. package/src/utils/model/modelStrings.ts +181 -0
  1636. package/src/utils/model/modelSupportOverrides.ts +50 -0
  1637. package/src/utils/model/providers.ts +50 -0
  1638. package/src/utils/model/validateModel.ts +173 -0
  1639. package/src/utils/modelCost.ts +231 -0
  1640. package/src/utils/modelSelection.ts +43 -0
  1641. package/src/utils/modifiers.ts +36 -0
  1642. package/src/utils/mtls.ts +179 -0
  1643. package/src/utils/nativeInstaller/download.ts +523 -0
  1644. package/src/utils/nativeInstaller/index.ts +18 -0
  1645. package/src/utils/nativeInstaller/installer.ts +1709 -0
  1646. package/src/utils/nativeInstaller/packageManagers.ts +336 -0
  1647. package/src/utils/nativeInstaller/pidLock.ts +433 -0
  1648. package/src/utils/notebook.ts +224 -0
  1649. package/src/utils/objectGroupBy.ts +18 -0
  1650. package/src/utils/pasteStore.ts +104 -0
  1651. package/src/utils/path.ts +155 -0
  1652. package/src/utils/pdf.ts +300 -0
  1653. package/src/utils/pdfUtils.ts +70 -0
  1654. package/src/utils/peerAddress.ts +21 -0
  1655. package/src/utils/permissions/PermissionMode.ts +166 -0
  1656. package/src/utils/permissions/PermissionPromptToolResultSchema.ts +127 -0
  1657. package/src/utils/permissions/PermissionResult.ts +35 -0
  1658. package/src/utils/permissions/PermissionRule.ts +40 -0
  1659. package/src/utils/permissions/PermissionUpdate.ts +389 -0
  1660. package/src/utils/permissions/PermissionUpdateSchema.ts +78 -0
  1661. package/src/utils/permissions/autoModeState.ts +39 -0
  1662. package/src/utils/permissions/bashClassifier.ts +61 -0
  1663. package/src/utils/permissions/bypassPermissionsKillswitch.ts +155 -0
  1664. package/src/utils/permissions/classifierDecision.ts +98 -0
  1665. package/src/utils/permissions/classifierShared.ts +39 -0
  1666. package/src/utils/permissions/dangerousPatterns.ts +80 -0
  1667. package/src/utils/permissions/denialTracking.ts +45 -0
  1668. package/src/utils/permissions/filesystem.ts +1778 -0
  1669. package/src/utils/permissions/getNextPermissionMode.ts +101 -0
  1670. package/src/utils/permissions/pathValidation.ts +485 -0
  1671. package/src/utils/permissions/permissionExplainer.ts +250 -0
  1672. package/src/utils/permissions/permissionRuleParser.ts +198 -0
  1673. package/src/utils/permissions/permissionSetup.ts +1544 -0
  1674. package/src/utils/permissions/permissions.ts +1486 -0
  1675. package/src/utils/permissions/permissionsLoader.ts +296 -0
  1676. package/src/utils/permissions/shadowedRuleDetection.ts +234 -0
  1677. package/src/utils/permissions/shellRuleMatching.ts +228 -0
  1678. package/src/utils/permissions/yoloClassifier.ts +1495 -0
  1679. package/src/utils/planModeV2.ts +95 -0
  1680. package/src/utils/plans.ts +397 -0
  1681. package/src/utils/platform.ts +150 -0
  1682. package/src/utils/plugins/addDirPluginSettings.ts +71 -0
  1683. package/src/utils/plugins/cacheUtils.ts +196 -0
  1684. package/src/utils/plugins/dependencyResolver.ts +305 -0
  1685. package/src/utils/plugins/fetchTelemetry.ts +135 -0
  1686. package/src/utils/plugins/gitAvailability.ts +69 -0
  1687. package/src/utils/plugins/headlessPluginInstall.ts +174 -0
  1688. package/src/utils/plugins/hintRecommendation.ts +164 -0
  1689. package/src/utils/plugins/installCounts.ts +292 -0
  1690. package/src/utils/plugins/installedPluginsManager.ts +1268 -0
  1691. package/src/utils/plugins/loadPluginAgents.ts +348 -0
  1692. package/src/utils/plugins/loadPluginCommands.ts +946 -0
  1693. package/src/utils/plugins/loadPluginHooks.ts +287 -0
  1694. package/src/utils/plugins/loadPluginOutputStyles.ts +178 -0
  1695. package/src/utils/plugins/lspPluginIntegration.ts +387 -0
  1696. package/src/utils/plugins/lspRecommendation.ts +374 -0
  1697. package/src/utils/plugins/managedPlugins.ts +27 -0
  1698. package/src/utils/plugins/marketplaceHelpers.ts +592 -0
  1699. package/src/utils/plugins/marketplaceManager.ts +2643 -0
  1700. package/src/utils/plugins/mcpPluginIntegration.ts +634 -0
  1701. package/src/utils/plugins/mcpbHandler.ts +968 -0
  1702. package/src/utils/plugins/officialMarketplace.ts +25 -0
  1703. package/src/utils/plugins/officialMarketplaceGcs.ts +216 -0
  1704. package/src/utils/plugins/officialMarketplaceStartupCheck.ts +439 -0
  1705. package/src/utils/plugins/orphanedPluginFilter.ts +114 -0
  1706. package/src/utils/plugins/parseMarketplaceInput.ts +162 -0
  1707. package/src/utils/plugins/performStartupChecks.tsx +70 -0
  1708. package/src/utils/plugins/pluginAutoupdate.ts +284 -0
  1709. package/src/utils/plugins/pluginBlocklist.ts +127 -0
  1710. package/src/utils/plugins/pluginDirectories.ts +178 -0
  1711. package/src/utils/plugins/pluginFlagging.ts +208 -0
  1712. package/src/utils/plugins/pluginIdentifier.ts +123 -0
  1713. package/src/utils/plugins/pluginInstallationHelpers.ts +595 -0
  1714. package/src/utils/plugins/pluginLoader.ts +3302 -0
  1715. package/src/utils/plugins/pluginOptionsStorage.ts +400 -0
  1716. package/src/utils/plugins/pluginPolicy.ts +20 -0
  1717. package/src/utils/plugins/pluginStartupCheck.ts +341 -0
  1718. package/src/utils/plugins/pluginVersioning.ts +157 -0
  1719. package/src/utils/plugins/reconciler.ts +265 -0
  1720. package/src/utils/plugins/refresh.ts +215 -0
  1721. package/src/utils/plugins/schemas.ts +1681 -0
  1722. package/src/utils/plugins/validatePlugin.ts +903 -0
  1723. package/src/utils/plugins/walkPluginMarkdown.ts +69 -0
  1724. package/src/utils/plugins/zipCache.ts +406 -0
  1725. package/src/utils/plugins/zipCacheAdapters.ts +164 -0
  1726. package/src/utils/powershell/dangerousCmdlets.ts +185 -0
  1727. package/src/utils/powershell/parser.ts +1804 -0
  1728. package/src/utils/powershell/staticPrefix.ts +316 -0
  1729. package/src/utils/preflightChecks.tsx +151 -0
  1730. package/src/utils/privacyLevel.ts +55 -0
  1731. package/src/utils/process.ts +68 -0
  1732. package/src/utils/processUserInput/processBashCommand.tsx +140 -0
  1733. package/src/utils/processUserInput/processSlashCommand.tsx +922 -0
  1734. package/src/utils/processUserInput/processTextPrompt.ts +100 -0
  1735. package/src/utils/processUserInput/processUserInput.ts +605 -0
  1736. package/src/utils/profilerBase.ts +46 -0
  1737. package/src/utils/promptCategory.ts +49 -0
  1738. package/src/utils/promptEditor.ts +188 -0
  1739. package/src/utils/promptShellExecution.ts +183 -0
  1740. package/src/utils/providerModelCache.ts +30 -0
  1741. package/src/utils/providerSelection.ts +364 -0
  1742. package/src/utils/proxy.ts +426 -0
  1743. package/src/utils/queryContext.ts +179 -0
  1744. package/src/utils/queryHelpers.ts +552 -0
  1745. package/src/utils/queryProfiler.ts +301 -0
  1746. package/src/utils/queueProcessor.ts +95 -0
  1747. package/src/utils/readEditContext.ts +227 -0
  1748. package/src/utils/readFileInRange.ts +383 -0
  1749. package/src/utils/releaseNotes.ts +361 -0
  1750. package/src/utils/renderOptions.ts +77 -0
  1751. package/src/utils/ripgrep.ts +679 -0
  1752. package/src/utils/sandbox/sandbox-adapter.ts +985 -0
  1753. package/src/utils/sandbox/sandbox-ui-utils.ts +12 -0
  1754. package/src/utils/sanitization.ts +91 -0
  1755. package/src/utils/screenshotClipboard.ts +121 -0
  1756. package/src/utils/sdkEventQueue.ts +134 -0
  1757. package/src/utils/secureStorage/fallbackStorage.ts +70 -0
  1758. package/src/utils/secureStorage/index.ts +17 -0
  1759. package/src/utils/secureStorage/keychainPrefetch.ts +116 -0
  1760. package/src/utils/secureStorage/macOsKeychainHelpers.ts +111 -0
  1761. package/src/utils/secureStorage/macOsKeychainStorage.ts +231 -0
  1762. package/src/utils/secureStorage/plainTextStorage.ts +84 -0
  1763. package/src/utils/semanticBoolean.ts +29 -0
  1764. package/src/utils/semanticNumber.ts +36 -0
  1765. package/src/utils/semver.ts +59 -0
  1766. package/src/utils/sequential.ts +56 -0
  1767. package/src/utils/sessionActivity.ts +133 -0
  1768. package/src/utils/sessionEnvVars.ts +22 -0
  1769. package/src/utils/sessionEnvironment.ts +166 -0
  1770. package/src/utils/sessionFileAccessHooks.ts +250 -0
  1771. package/src/utils/sessionIngressAuth.ts +140 -0
  1772. package/src/utils/sessionRestore.ts +551 -0
  1773. package/src/utils/sessionStart.ts +232 -0
  1774. package/src/utils/sessionState.ts +150 -0
  1775. package/src/utils/sessionStorage.ts +5106 -0
  1776. package/src/utils/sessionStoragePortable.ts +793 -0
  1777. package/src/utils/sessionTitle.ts +129 -0
  1778. package/src/utils/sessionUrl.ts +64 -0
  1779. package/src/utils/set.ts +53 -0
  1780. package/src/utils/settings/allErrors.ts +32 -0
  1781. package/src/utils/settings/applySettingsChange.ts +92 -0
  1782. package/src/utils/settings/changeDetector.ts +488 -0
  1783. package/src/utils/settings/constants.ts +202 -0
  1784. package/src/utils/settings/internalWrites.ts +37 -0
  1785. package/src/utils/settings/managedPath.ts +34 -0
  1786. package/src/utils/settings/mdm/constants.ts +81 -0
  1787. package/src/utils/settings/mdm/rawRead.ts +130 -0
  1788. package/src/utils/settings/mdm/settings.ts +316 -0
  1789. package/src/utils/settings/permissionValidation.ts +262 -0
  1790. package/src/utils/settings/pluginOnlyPolicy.ts +60 -0
  1791. package/src/utils/settings/schemaOutput.ts +8 -0
  1792. package/src/utils/settings/settings.ts +1015 -0
  1793. package/src/utils/settings/settingsCache.ts +80 -0
  1794. package/src/utils/settings/toolValidationConfig.ts +103 -0
  1795. package/src/utils/settings/types.ts +1171 -0
  1796. package/src/utils/settings/validateEditTool.ts +45 -0
  1797. package/src/utils/settings/validation.ts +265 -0
  1798. package/src/utils/settings/validationTips.ts +164 -0
  1799. package/src/utils/shell/bashProvider.ts +255 -0
  1800. package/src/utils/shell/outputLimits.ts +14 -0
  1801. package/src/utils/shell/powershellDetection.ts +107 -0
  1802. package/src/utils/shell/powershellProvider.ts +123 -0
  1803. package/src/utils/shell/prefix.ts +367 -0
  1804. package/src/utils/shell/readOnlyCommandValidation.ts +1893 -0
  1805. package/src/utils/shell/resolveDefaultShell.ts +14 -0
  1806. package/src/utils/shell/shellProvider.ts +33 -0
  1807. package/src/utils/shell/shellToolUtils.ts +22 -0
  1808. package/src/utils/shell/specPrefix.ts +241 -0
  1809. package/src/utils/shellConfig.ts +167 -0
  1810. package/src/utils/sideQuery.ts +223 -0
  1811. package/src/utils/sideQuestion.ts +155 -0
  1812. package/src/utils/signal.ts +43 -0
  1813. package/src/utils/sinks.ts +16 -0
  1814. package/src/utils/skills/skillChangeDetector.ts +311 -0
  1815. package/src/utils/slashCommandParsing.ts +60 -0
  1816. package/src/utils/sleep.ts +84 -0
  1817. package/src/utils/sliceAnsi.ts +91 -0
  1818. package/src/utils/slowOperations.ts +286 -0
  1819. package/src/utils/standaloneAgent.ts +23 -0
  1820. package/src/utils/startupProfiler.ts +194 -0
  1821. package/src/utils/staticRender.tsx +116 -0
  1822. package/src/utils/stats.ts +1061 -0
  1823. package/src/utils/statsCache.ts +434 -0
  1824. package/src/utils/status.tsx +372 -0
  1825. package/src/utils/statusNoticeDefinitions.tsx +198 -0
  1826. package/src/utils/statusNoticeHelpers.ts +20 -0
  1827. package/src/utils/stream.ts +76 -0
  1828. package/src/utils/streamJsonStdoutGuard.ts +123 -0
  1829. package/src/utils/streamlinedTransform.ts +201 -0
  1830. package/src/utils/stringUtils.ts +235 -0
  1831. package/src/utils/subprocessEnv.ts +99 -0
  1832. package/src/utils/suggestions/commandSuggestions.ts +567 -0
  1833. package/src/utils/suggestions/directoryCompletion.ts +263 -0
  1834. package/src/utils/suggestions/shellHistoryCompletion.ts +119 -0
  1835. package/src/utils/suggestions/skillUsageTracking.ts +55 -0
  1836. package/src/utils/suggestions/slackChannelSuggestions.ts +209 -0
  1837. package/src/utils/swarm/It2SetupPrompt.tsx +380 -0
  1838. package/src/utils/swarm/backends/ITermBackend.ts +370 -0
  1839. package/src/utils/swarm/backends/InProcessBackend.ts +339 -0
  1840. package/src/utils/swarm/backends/PaneBackendExecutor.ts +354 -0
  1841. package/src/utils/swarm/backends/TmuxBackend.ts +764 -0
  1842. package/src/utils/swarm/backends/detection.ts +128 -0
  1843. package/src/utils/swarm/backends/it2Setup.ts +245 -0
  1844. package/src/utils/swarm/backends/registry.ts +464 -0
  1845. package/src/utils/swarm/backends/teammateModeSnapshot.ts +87 -0
  1846. package/src/utils/swarm/backends/types.ts +311 -0
  1847. package/src/utils/swarm/constants.ts +33 -0
  1848. package/src/utils/swarm/inProcessRunner.ts +1552 -0
  1849. package/src/utils/swarm/leaderPermissionBridge.ts +54 -0
  1850. package/src/utils/swarm/permissionSync.ts +928 -0
  1851. package/src/utils/swarm/reconnection.ts +119 -0
  1852. package/src/utils/swarm/spawnInProcess.ts +328 -0
  1853. package/src/utils/swarm/spawnUtils.ts +168 -0
  1854. package/src/utils/swarm/teamHelpers.ts +683 -0
  1855. package/src/utils/swarm/teammateInit.ts +129 -0
  1856. package/src/utils/swarm/teammateLayoutManager.ts +107 -0
  1857. package/src/utils/swarm/teammateModel.ts +10 -0
  1858. package/src/utils/swarm/teammatePromptAddendum.ts +18 -0
  1859. package/src/utils/systemDirectories.ts +74 -0
  1860. package/src/utils/systemPrompt.ts +123 -0
  1861. package/src/utils/systemPromptType.ts +14 -0
  1862. package/src/utils/systemTheme.ts +119 -0
  1863. package/src/utils/taggedId.ts +54 -0
  1864. package/src/utils/task/TaskOutput.ts +390 -0
  1865. package/src/utils/task/diskOutput.ts +451 -0
  1866. package/src/utils/task/framework.ts +308 -0
  1867. package/src/utils/task/outputFormatting.ts +38 -0
  1868. package/src/utils/task/sdkProgress.ts +36 -0
  1869. package/src/utils/tasks.ts +862 -0
  1870. package/src/utils/teamDiscovery.ts +81 -0
  1871. package/src/utils/teamMemoryOps.ts +88 -0
  1872. package/src/utils/teammate.ts +292 -0
  1873. package/src/utils/teammateContext.ts +96 -0
  1874. package/src/utils/teammateMailbox.ts +1183 -0
  1875. package/src/utils/telemetry/betaSessionTracing.ts +491 -0
  1876. package/src/utils/telemetry/bigqueryExporter.ts +252 -0
  1877. package/src/utils/telemetry/events.ts +75 -0
  1878. package/src/utils/telemetry/instrumentation.ts +826 -0
  1879. package/src/utils/telemetry/logger.ts +26 -0
  1880. package/src/utils/telemetry/perfettoTracing.ts +1120 -0
  1881. package/src/utils/telemetry/pluginTelemetry.ts +289 -0
  1882. package/src/utils/telemetry/sessionTracing.ts +927 -0
  1883. package/src/utils/telemetry/skillLoadedEvent.ts +39 -0
  1884. package/src/utils/telemetryAttributes.ts +72 -0
  1885. package/src/utils/teleport/api.ts +466 -0
  1886. package/src/utils/teleport/environmentSelection.ts +77 -0
  1887. package/src/utils/teleport/environments.ts +120 -0
  1888. package/src/utils/teleport/gitBundle.ts +292 -0
  1889. package/src/utils/teleport.tsx +1226 -0
  1890. package/src/utils/tempfile.ts +31 -0
  1891. package/src/utils/terminal.ts +131 -0
  1892. package/src/utils/terminalPanel.ts +191 -0
  1893. package/src/utils/textHighlighting.ts +166 -0
  1894. package/src/utils/theme.ts +639 -0
  1895. package/src/utils/thinking.ts +170 -0
  1896. package/src/utils/timeouts.ts +39 -0
  1897. package/src/utils/tmuxSocket.ts +427 -0
  1898. package/src/utils/todo/types.ts +18 -0
  1899. package/src/utils/tokenBudget.ts +73 -0
  1900. package/src/utils/tokens.ts +261 -0
  1901. package/src/utils/toolErrors.ts +132 -0
  1902. package/src/utils/toolPool.ts +79 -0
  1903. package/src/utils/toolResultStorage.ts +1040 -0
  1904. package/src/utils/toolSchemaCache.ts +26 -0
  1905. package/src/utils/toolSearch.ts +756 -0
  1906. package/src/utils/transcriptSearch.ts +202 -0
  1907. package/src/utils/treeify.ts +170 -0
  1908. package/src/utils/truncate.ts +179 -0
  1909. package/src/utils/ultraplan/ccrSession.ts +349 -0
  1910. package/src/utils/ultraplan/keyword.ts +127 -0
  1911. package/src/utils/ultraplan/prompt.txt +12 -0
  1912. package/src/utils/unaryLogging.ts +39 -0
  1913. package/src/utils/undercover.ts +89 -0
  1914. package/src/utils/user.ts +195 -0
  1915. package/src/utils/userAgent.ts +11 -0
  1916. package/src/utils/userPromptKeywords.ts +27 -0
  1917. package/src/utils/uuid.ts +27 -0
  1918. package/src/utils/warningHandler.ts +121 -0
  1919. package/src/utils/webSearchEnabled.ts +16 -0
  1920. package/src/utils/which.ts +82 -0
  1921. package/src/utils/windowsPaths.ts +173 -0
  1922. package/src/utils/withResolvers.ts +13 -0
  1923. package/src/utils/words.ts +800 -0
  1924. package/src/utils/workloadContext.ts +57 -0
  1925. package/src/utils/worktree.ts +1519 -0
  1926. package/src/utils/worktreeModeEnabled.ts +11 -0
  1927. package/src/utils/xdg.ts +65 -0
  1928. package/src/utils/xml.ts +16 -0
  1929. package/src/utils/yaml.ts +15 -0
  1930. package/src/utils/zodToJsonSchema.ts +23 -0
  1931. package/src/vim/motions.ts +82 -0
  1932. package/src/vim/operators.ts +556 -0
  1933. package/src/vim/textObjects.ts +186 -0
  1934. package/src/vim/transitions.ts +490 -0
  1935. package/src/vim/types.ts +199 -0
  1936. package/src/voice/voiceModeEnabled.ts +54 -0
@@ -0,0 +1,3201 @@
1
+ import { getAppVersion } from '../utils/appVersion.js'
2
+ import { execFileSync } from 'child_process'
3
+ import { diffLines } from 'diff'
4
+ import { constants as fsConstants } from 'fs'
5
+ import {
6
+ copyFile,
7
+ mkdir,
8
+ mkdtemp,
9
+ readdir,
10
+ readFile,
11
+ rm,
12
+ unlink,
13
+ writeFile,
14
+ } from 'fs/promises'
15
+ import { tmpdir } from 'os'
16
+ import { extname, join } from 'path'
17
+ import type { Command } from '../commands.js'
18
+ import { queryWithModel } from '../services/api/claude.js'
19
+ import {
20
+ AGENT_TOOL_NAME,
21
+ LEGACY_AGENT_TOOL_NAME,
22
+ } from '../tools/AgentTool/constants.js'
23
+ import type { LogOption } from '../types/logs.js'
24
+ import { getClaudeConfigHomeDir } from '../utils/envUtils.js'
25
+ import { toError } from '../utils/errors.js'
26
+ import { execFileNoThrow } from '../utils/execFileNoThrow.js'
27
+ import { logError } from '../utils/log.js'
28
+ import { extractTextContent } from '../utils/messages.js'
29
+ import { getDefaultOpusModel } from '../utils/model/model.js'
30
+ import {
31
+ getProjectsDir,
32
+ getSessionFilesWithMtime,
33
+ getSessionIdFromLog,
34
+ loadAllLogsFromSessionFile,
35
+ } from '../utils/sessionStorage.js'
36
+ import { jsonParse, jsonStringify } from '../utils/slowOperations.js'
37
+ import { countCharInString } from '../utils/stringUtils.js'
38
+ import { asSystemPrompt } from '../utils/systemPromptType.js'
39
+ import { escapeXmlAttr as escapeHtml } from '../utils/xml.js'
40
+
41
+ // Model for facet extraction and summarization (Opus - best quality)
42
+ function getAnalysisModel(): string {
43
+ return getDefaultOpusModel()
44
+ }
45
+
46
+ // Model for narrative insights (Opus - best quality)
47
+ function getInsightsModel(): string {
48
+ return getDefaultOpusModel()
49
+ }
50
+
51
+ // ============================================================================
52
+ // Homespace Data Collection
53
+ // ============================================================================
54
+
55
+ type RemoteHostInfo = {
56
+ name: string
57
+ sessionCount: number
58
+ }
59
+
60
+ /* eslint-disable custom-rules/no-process-env-top-level */
61
+ const getRunningRemoteHosts: () => Promise<string[]> =
62
+ process.env.USER_TYPE === 'ant'
63
+ ? async () => {
64
+ const { stdout, code } = await execFileNoThrow(
65
+ 'coder',
66
+ ['list', '-o', 'json'],
67
+ { timeout: 30000 },
68
+ )
69
+ if (code !== 0) return []
70
+ try {
71
+ const workspaces = jsonParse(stdout) as Array<{
72
+ name: string
73
+ latest_build?: { status?: string }
74
+ }>
75
+ return workspaces
76
+ .filter(w => w.latest_build?.status === 'running')
77
+ .map(w => w.name)
78
+ } catch {
79
+ return []
80
+ }
81
+ }
82
+ : async () => []
83
+
84
+ const getRemoteHostSessionCount: (hs: string) => Promise<number> =
85
+ process.env.USER_TYPE === 'ant'
86
+ ? async (homespace: string) => {
87
+ const { stdout, code } = await execFileNoThrow(
88
+ 'ssh',
89
+ [
90
+ `${homespace}.coder`,
91
+ 'find /root/.claude/projects -name "*.jsonl" 2>/dev/null | wc -l',
92
+ ],
93
+ { timeout: 30000 },
94
+ )
95
+ if (code !== 0) return 0
96
+ return parseInt(stdout.trim(), 10) || 0
97
+ }
98
+ : async () => 0
99
+
100
+ const collectFromRemoteHost: (
101
+ hs: string,
102
+ destDir: string,
103
+ ) => Promise<{ copied: number; skipped: number }> =
104
+ process.env.USER_TYPE === 'ant'
105
+ ? async (homespace: string, destDir: string) => {
106
+ const result = { copied: 0, skipped: 0 }
107
+
108
+ // Create temp directory
109
+ const tempDir = await mkdtemp(join(tmpdir(), 'claude-hs-'))
110
+
111
+ try {
112
+ // SCP the projects folder
113
+ const scpResult = await execFileNoThrow(
114
+ 'scp',
115
+ ['-rq', `${homespace}.coder:/root/.claude/projects/`, tempDir],
116
+ { timeout: 300000 },
117
+ )
118
+ if (scpResult.code !== 0) {
119
+ // SCP failed
120
+ return result
121
+ }
122
+
123
+ const projectsDir = join(tempDir, 'projects')
124
+ let projectDirents: Awaited<ReturnType<typeof readdir>>
125
+ try {
126
+ projectDirents = await readdir(projectsDir, { withFileTypes: true })
127
+ } catch {
128
+ return result
129
+ }
130
+
131
+ // Merge into destination (parallel per project directory)
132
+ await Promise.all(
133
+ projectDirents.map(async dirent => {
134
+ const projectName = dirent.name
135
+ const projectPath = join(projectsDir, projectName)
136
+
137
+ // Skip if not a directory
138
+ if (!dirent.isDirectory()) return
139
+
140
+ const destProjectName = `${projectName}__${homespace}`
141
+ const destProjectPath = join(destDir, destProjectName)
142
+
143
+ try {
144
+ await mkdir(destProjectPath, { recursive: true })
145
+ } catch {
146
+ // Directory may already exist
147
+ }
148
+
149
+ // Copy session files (skip existing)
150
+ let files: Awaited<ReturnType<typeof readdir>>
151
+ try {
152
+ files = await readdir(projectPath, { withFileTypes: true })
153
+ } catch {
154
+ return
155
+ }
156
+ await Promise.all(
157
+ files.map(async fileDirent => {
158
+ const fileName = fileDirent.name
159
+ if (!fileName.endsWith('.jsonl')) return
160
+
161
+ const srcFile = join(projectPath, fileName)
162
+ const destFile = join(destProjectPath, fileName)
163
+
164
+ try {
165
+ await copyFile(srcFile, destFile, fsConstants.COPYFILE_EXCL)
166
+ result.copied++
167
+ } catch {
168
+ // EEXIST from COPYFILE_EXCL means dest already exists
169
+ result.skipped++
170
+ }
171
+ }),
172
+ )
173
+ }),
174
+ )
175
+ } finally {
176
+ try {
177
+ await rm(tempDir, { recursive: true, force: true })
178
+ } catch {
179
+ // Ignore cleanup errors
180
+ }
181
+ }
182
+
183
+ return result
184
+ }
185
+ : async () => ({ copied: 0, skipped: 0 })
186
+
187
+ const collectAllRemoteHostData: (destDir: string) => Promise<{
188
+ hosts: RemoteHostInfo[]
189
+ totalCopied: number
190
+ totalSkipped: number
191
+ }> =
192
+ process.env.USER_TYPE === 'ant'
193
+ ? async (destDir: string) => {
194
+ const rHosts = await getRunningRemoteHosts()
195
+ const result: RemoteHostInfo[] = []
196
+ let totalCopied = 0
197
+ let totalSkipped = 0
198
+
199
+ // Collect from all hosts in parallel (SCP per host can take seconds)
200
+ const hostResults = await Promise.all(
201
+ rHosts.map(async hs => {
202
+ const sessionCount = await getRemoteHostSessionCount(hs)
203
+ if (sessionCount > 0) {
204
+ const { copied, skipped } = await collectFromRemoteHost(
205
+ hs,
206
+ destDir,
207
+ )
208
+ return { name: hs, sessionCount, copied, skipped }
209
+ }
210
+ return { name: hs, sessionCount, copied: 0, skipped: 0 }
211
+ }),
212
+ )
213
+
214
+ for (const hr of hostResults) {
215
+ result.push({ name: hr.name, sessionCount: hr.sessionCount })
216
+ totalCopied += hr.copied
217
+ totalSkipped += hr.skipped
218
+ }
219
+
220
+ return { hosts: result, totalCopied, totalSkipped }
221
+ }
222
+ : async () => ({ hosts: [], totalCopied: 0, totalSkipped: 0 })
223
+ /* eslint-enable custom-rules/no-process-env-top-level */
224
+
225
+ // ============================================================================
226
+ // Types
227
+ // ============================================================================
228
+
229
+ type SessionMeta = {
230
+ session_id: string
231
+ project_path: string
232
+ start_time: string
233
+ duration_minutes: number
234
+ user_message_count: number
235
+ assistant_message_count: number
236
+ tool_counts: Record<string, number>
237
+ languages: Record<string, number>
238
+ git_commits: number
239
+ git_pushes: number
240
+ input_tokens: number
241
+ output_tokens: number
242
+ first_prompt: string
243
+ summary?: string
244
+ // New stats
245
+ user_interruptions: number
246
+ user_response_times: number[]
247
+ tool_errors: number
248
+ tool_error_categories: Record<string, number>
249
+ uses_task_agent: boolean
250
+ uses_mcp: boolean
251
+ uses_web_search: boolean
252
+ uses_web_fetch: boolean
253
+ // Additional stats
254
+ lines_added: number
255
+ lines_removed: number
256
+ files_modified: number
257
+ message_hours: number[]
258
+ user_message_timestamps: string[] // ISO timestamps for multi-clauding detection
259
+ }
260
+
261
+ type SessionFacets = {
262
+ session_id: string
263
+ underlying_goal: string
264
+ goal_categories: Record<string, number>
265
+ outcome: string
266
+ user_satisfaction_counts: Record<string, number>
267
+ claude_helpfulness: string
268
+ session_type: string
269
+ friction_counts: Record<string, number>
270
+ friction_detail: string
271
+ primary_success: string
272
+ brief_summary: string
273
+ user_instructions_to_claude?: string[]
274
+ }
275
+
276
+ type AggregatedData = {
277
+ total_sessions: number
278
+ total_sessions_scanned?: number
279
+ sessions_with_facets: number
280
+ date_range: { start: string; end: string }
281
+ total_messages: number
282
+ total_duration_hours: number
283
+ total_input_tokens: number
284
+ total_output_tokens: number
285
+ tool_counts: Record<string, number>
286
+ languages: Record<string, number>
287
+ git_commits: number
288
+ git_pushes: number
289
+ projects: Record<string, number>
290
+ goal_categories: Record<string, number>
291
+ outcomes: Record<string, number>
292
+ satisfaction: Record<string, number>
293
+ helpfulness: Record<string, number>
294
+ session_types: Record<string, number>
295
+ friction: Record<string, number>
296
+ success: Record<string, number>
297
+ session_summaries: Array<{
298
+ id: string
299
+ date: string
300
+ summary: string
301
+ goal?: string
302
+ }>
303
+ // New aggregated stats
304
+ total_interruptions: number
305
+ total_tool_errors: number
306
+ tool_error_categories: Record<string, number>
307
+ user_response_times: number[]
308
+ median_response_time: number
309
+ avg_response_time: number
310
+ sessions_using_task_agent: number
311
+ sessions_using_mcp: number
312
+ sessions_using_web_search: number
313
+ sessions_using_web_fetch: number
314
+ // Additional stats from Python reference
315
+ total_lines_added: number
316
+ total_lines_removed: number
317
+ total_files_modified: number
318
+ days_active: number
319
+ messages_per_day: number
320
+ message_hours: number[] // Hour of day for each user message (for time of day chart)
321
+ // Multi-clauding stats (matching Python reference)
322
+ multi_clauding: {
323
+ overlap_events: number
324
+ sessions_involved: number
325
+ user_messages_during: number
326
+ }
327
+ }
328
+
329
+ // ============================================================================
330
+ // Constants
331
+ // ============================================================================
332
+
333
+ const EXTENSION_TO_LANGUAGE: Record<string, string> = {
334
+ '.ts': 'TypeScript',
335
+ '.tsx': 'TypeScript',
336
+ '.js': 'JavaScript',
337
+ '.jsx': 'JavaScript',
338
+ '.py': 'Python',
339
+ '.rb': 'Ruby',
340
+ '.go': 'Go',
341
+ '.rs': 'Rust',
342
+ '.java': 'Java',
343
+ '.md': 'Markdown',
344
+ '.json': 'JSON',
345
+ '.yaml': 'YAML',
346
+ '.yml': 'YAML',
347
+ '.sh': 'Shell',
348
+ '.css': 'CSS',
349
+ '.html': 'HTML',
350
+ }
351
+
352
+ // Label map for cleaning up category names (matching Python reference)
353
+ const LABEL_MAP: Record<string, string> = {
354
+ // Goal categories
355
+ debug_investigate: 'Debug/Investigate',
356
+ implement_feature: 'Implement Feature',
357
+ fix_bug: 'Fix Bug',
358
+ write_script_tool: 'Write Script/Tool',
359
+ refactor_code: 'Refactor Code',
360
+ configure_system: 'Configure System',
361
+ create_pr_commit: 'Create PR/Commit',
362
+ analyze_data: 'Analyze Data',
363
+ understand_codebase: 'Understand Codebase',
364
+ write_tests: 'Write Tests',
365
+ write_docs: 'Write Docs',
366
+ deploy_infra: 'Deploy/Infra',
367
+ warmup_minimal: 'Cache Warmup',
368
+ // Success factors
369
+ fast_accurate_search: 'Fast/Accurate Search',
370
+ correct_code_edits: 'Correct Code Edits',
371
+ good_explanations: 'Good Explanations',
372
+ proactive_help: 'Proactive Help',
373
+ multi_file_changes: 'Multi-file Changes',
374
+ handled_complexity: 'Multi-file Changes',
375
+ good_debugging: 'Good Debugging',
376
+ // Friction types
377
+ misunderstood_request: 'Misunderstood Request',
378
+ wrong_approach: 'Wrong Approach',
379
+ buggy_code: 'Buggy Code',
380
+ user_rejected_action: 'User Rejected Action',
381
+ claude_got_blocked: 'Claude Got Blocked',
382
+ user_stopped_early: 'User Stopped Early',
383
+ wrong_file_or_location: 'Wrong File/Location',
384
+ excessive_changes: 'Excessive Changes',
385
+ slow_or_verbose: 'Slow/Verbose',
386
+ tool_failed: 'Tool Failed',
387
+ user_unclear: 'User Unclear',
388
+ external_issue: 'External Issue',
389
+ // Satisfaction labels
390
+ frustrated: 'Frustrated',
391
+ dissatisfied: 'Dissatisfied',
392
+ likely_satisfied: 'Likely Satisfied',
393
+ satisfied: 'Satisfied',
394
+ happy: 'Happy',
395
+ unsure: 'Unsure',
396
+ neutral: 'Neutral',
397
+ delighted: 'Delighted',
398
+ // Session types
399
+ single_task: 'Single Task',
400
+ multi_task: 'Multi Task',
401
+ iterative_refinement: 'Iterative Refinement',
402
+ exploration: 'Exploration',
403
+ quick_question: 'Quick Question',
404
+ // Outcomes
405
+ fully_achieved: 'Fully Achieved',
406
+ mostly_achieved: 'Mostly Achieved',
407
+ partially_achieved: 'Partially Achieved',
408
+ not_achieved: 'Not Achieved',
409
+ unclear_from_transcript: 'Unclear',
410
+ // Helpfulness
411
+ unhelpful: 'Unhelpful',
412
+ slightly_helpful: 'Slightly Helpful',
413
+ moderately_helpful: 'Moderately Helpful',
414
+ very_helpful: 'Very Helpful',
415
+ essential: 'Essential',
416
+ }
417
+
418
+ // Lazy getters: getClaudeConfigHomeDir() is memoized and reads process.env.
419
+ // Calling it at module scope would populate the memoize cache before
420
+ // entrypoints can set CLAUDE_CONFIG_DIR, breaking all 150+ other callers.
421
+ function getDataDir(): string {
422
+ return join(getClaudeConfigHomeDir(), 'usage-data')
423
+ }
424
+ function getFacetsDir(): string {
425
+ return join(getDataDir(), 'facets')
426
+ }
427
+ function getSessionMetaDir(): string {
428
+ return join(getDataDir(), 'session-meta')
429
+ }
430
+
431
+ const FACET_EXTRACTION_PROMPT = `Analyze this Claude Code session and extract structured facets.
432
+
433
+ CRITICAL GUIDELINES:
434
+
435
+ 1. **goal_categories**: Count ONLY what the USER explicitly asked for.
436
+ - DO NOT count Claude's autonomous codebase exploration
437
+ - DO NOT count work Claude decided to do on its own
438
+ - ONLY count when user says "can you...", "please...", "I need...", "let's..."
439
+
440
+ 2. **user_satisfaction_counts**: Base ONLY on explicit user signals.
441
+ - "Yay!", "great!", "perfect!" → happy
442
+ - "thanks", "looks good", "that works" → satisfied
443
+ - "ok, now let's..." (continuing without complaint) → likely_satisfied
444
+ - "that's not right", "try again" → dissatisfied
445
+ - "this is broken", "I give up" → frustrated
446
+
447
+ 3. **friction_counts**: Be specific about what went wrong.
448
+ - misunderstood_request: Claude interpreted incorrectly
449
+ - wrong_approach: Right goal, wrong solution method
450
+ - buggy_code: Code didn't work correctly
451
+ - user_rejected_action: User said no/stop to a tool call
452
+ - excessive_changes: Over-engineered or changed too much
453
+
454
+ 4. If very short or just warmup, use warmup_minimal for goal_category
455
+
456
+ SESSION:
457
+ `
458
+
459
+ // ============================================================================
460
+ // Helper Functions
461
+ // ============================================================================
462
+
463
+ function getLanguageFromPath(filePath: string): string | null {
464
+ const ext = extname(filePath).toLowerCase()
465
+ return EXTENSION_TO_LANGUAGE[ext] || null
466
+ }
467
+
468
+ function extractToolStats(log: LogOption): {
469
+ toolCounts: Record<string, number>
470
+ languages: Record<string, number>
471
+ gitCommits: number
472
+ gitPushes: number
473
+ inputTokens: number
474
+ outputTokens: number
475
+ // New stats
476
+ userInterruptions: number
477
+ userResponseTimes: number[]
478
+ toolErrors: number
479
+ toolErrorCategories: Record<string, number>
480
+ usesTaskAgent: boolean
481
+ usesMcp: boolean
482
+ usesWebSearch: boolean
483
+ usesWebFetch: boolean
484
+ // Additional stats
485
+ linesAdded: number
486
+ linesRemoved: number
487
+ filesModified: Set<string>
488
+ messageHours: number[]
489
+ userMessageTimestamps: string[] // ISO timestamps for multi-clauding detection
490
+ } {
491
+ const toolCounts: Record<string, number> = {}
492
+ const languages: Record<string, number> = {}
493
+ let gitCommits = 0
494
+ let gitPushes = 0
495
+ let inputTokens = 0
496
+ let outputTokens = 0
497
+
498
+ // New stats
499
+ let userInterruptions = 0
500
+ const userResponseTimes: number[] = []
501
+ let toolErrors = 0
502
+ const toolErrorCategories: Record<string, number> = {}
503
+ let usesTaskAgent = false
504
+
505
+ // Additional stats
506
+ let linesAdded = 0
507
+ let linesRemoved = 0
508
+ const filesModified = new Set<string>()
509
+ const messageHours: number[] = []
510
+ const userMessageTimestamps: string[] = [] // For multi-clauding detection
511
+ let usesMcp = false
512
+ let usesWebSearch = false
513
+ let usesWebFetch = false
514
+ let lastAssistantTimestamp: string | null = null
515
+
516
+ for (const msg of log.messages) {
517
+ // Get message timestamp for response time calculation
518
+ const msgTimestamp = (msg as { timestamp?: string }).timestamp
519
+
520
+ if (msg.type === 'assistant' && msg.message) {
521
+ // Track timestamp for response time calculation
522
+ if (msgTimestamp) {
523
+ lastAssistantTimestamp = msgTimestamp
524
+ }
525
+
526
+ const usage = (
527
+ msg.message as {
528
+ usage?: { input_tokens?: number; output_tokens?: number }
529
+ }
530
+ ).usage
531
+ if (usage) {
532
+ inputTokens += usage.input_tokens || 0
533
+ outputTokens += usage.output_tokens || 0
534
+ }
535
+
536
+ const content = msg.message.content
537
+ if (Array.isArray(content)) {
538
+ for (const block of content) {
539
+ if (block.type === 'tool_use' && 'name' in block) {
540
+ const toolName = block.name as string
541
+ toolCounts[toolName] = (toolCounts[toolName] || 0) + 1
542
+
543
+ // Check for special tool usage
544
+ if (
545
+ toolName === AGENT_TOOL_NAME ||
546
+ toolName === LEGACY_AGENT_TOOL_NAME
547
+ )
548
+ usesTaskAgent = true
549
+ if (toolName.startsWith('mcp__')) usesMcp = true
550
+ if (toolName === 'WebSearch') usesWebSearch = true
551
+ if (toolName === 'WebFetch') usesWebFetch = true
552
+
553
+ const input = (block as { input?: Record<string, unknown> }).input
554
+
555
+ if (input) {
556
+ const filePath = (input.file_path as string) || ''
557
+ if (filePath) {
558
+ const lang = getLanguageFromPath(filePath)
559
+ if (lang) {
560
+ languages[lang] = (languages[lang] || 0) + 1
561
+ }
562
+ // Track files modified by Edit/Write tools
563
+ if (toolName === 'Edit' || toolName === 'Write') {
564
+ filesModified.add(filePath)
565
+ }
566
+ }
567
+
568
+ if (toolName === 'Edit') {
569
+ const oldString = (input.old_string as string) || ''
570
+ const newString = (input.new_string as string) || ''
571
+ for (const change of diffLines(oldString, newString)) {
572
+ if (change.added) linesAdded += change.count || 0
573
+ if (change.removed) linesRemoved += change.count || 0
574
+ }
575
+ }
576
+
577
+ // Track lines from Write tool (all added)
578
+ if (toolName === 'Write') {
579
+ const writeContent = (input.content as string) || ''
580
+ if (writeContent) {
581
+ linesAdded += countCharInString(writeContent, '\n') + 1
582
+ }
583
+ }
584
+
585
+ const command = (input.command as string) || ''
586
+ if (command.includes('git commit')) gitCommits++
587
+ if (command.includes('git push')) gitPushes++
588
+ }
589
+ }
590
+ }
591
+ }
592
+ }
593
+
594
+ // Check user messages
595
+ if (msg.type === 'user' && msg.message) {
596
+ const content = msg.message.content
597
+
598
+ // Check if this is an actual human message (has text) vs just tool_result
599
+ // matching Python reference logic
600
+ let isHumanMessage = false
601
+ if (typeof content === 'string' && content.trim()) {
602
+ isHumanMessage = true
603
+ } else if (Array.isArray(content)) {
604
+ for (const block of content) {
605
+ if (block.type === 'text' && 'text' in block) {
606
+ isHumanMessage = true
607
+ break
608
+ }
609
+ }
610
+ }
611
+
612
+ // Only track message hours and response times for actual human messages
613
+ if (isHumanMessage) {
614
+ // Track message hour for time-of-day analysis and timestamp for multi-clauding
615
+ if (msgTimestamp) {
616
+ try {
617
+ const msgDate = new Date(msgTimestamp)
618
+ const hour = msgDate.getHours() // Local hour 0-23
619
+ messageHours.push(hour)
620
+ // Collect timestamp for multi-clauding detection (matching Python)
621
+ userMessageTimestamps.push(msgTimestamp)
622
+ } catch {
623
+ // Skip invalid timestamps
624
+ }
625
+ }
626
+
627
+ // Calculate response time (time from last assistant message to this user message)
628
+ // Only count gaps > 2 seconds (real user think time, not tool results)
629
+ if (lastAssistantTimestamp && msgTimestamp) {
630
+ const assistantTime = new Date(lastAssistantTimestamp).getTime()
631
+ const userTime = new Date(msgTimestamp).getTime()
632
+ const responseTimeSec = (userTime - assistantTime) / 1000
633
+ // Only count reasonable response times (2s-1 hour) matching Python
634
+ if (responseTimeSec > 2 && responseTimeSec < 3600) {
635
+ userResponseTimes.push(responseTimeSec)
636
+ }
637
+ }
638
+ }
639
+
640
+ // Process tool results (for error tracking)
641
+ if (Array.isArray(content)) {
642
+ for (const block of content) {
643
+ if (block.type === 'tool_result' && 'content' in block) {
644
+ const isError = (block as { is_error?: boolean }).is_error
645
+
646
+ // Count and categorize tool errors (matching Python reference logic)
647
+ if (isError) {
648
+ toolErrors++
649
+ const resultContent = (block as { content?: string }).content
650
+ let category = 'Other'
651
+ if (typeof resultContent === 'string') {
652
+ const lowerContent = resultContent.toLowerCase()
653
+ if (lowerContent.includes('exit code')) {
654
+ category = 'Command Failed'
655
+ } else if (
656
+ lowerContent.includes('rejected') ||
657
+ lowerContent.includes("doesn't want")
658
+ ) {
659
+ category = 'User Rejected'
660
+ } else if (
661
+ lowerContent.includes('string to replace not found') ||
662
+ lowerContent.includes('no changes')
663
+ ) {
664
+ category = 'Edit Failed'
665
+ } else if (lowerContent.includes('modified since read')) {
666
+ category = 'File Changed'
667
+ } else if (
668
+ lowerContent.includes('exceeds maximum') ||
669
+ lowerContent.includes('too large')
670
+ ) {
671
+ category = 'File Too Large'
672
+ } else if (
673
+ lowerContent.includes('file not found') ||
674
+ lowerContent.includes('does not exist')
675
+ ) {
676
+ category = 'File Not Found'
677
+ }
678
+ }
679
+ toolErrorCategories[category] =
680
+ (toolErrorCategories[category] || 0) + 1
681
+ }
682
+ }
683
+ }
684
+ }
685
+
686
+ // Check for interruptions (matching Python reference)
687
+ if (typeof content === 'string') {
688
+ if (content.includes('[Request interrupted by user')) {
689
+ userInterruptions++
690
+ }
691
+ } else if (Array.isArray(content)) {
692
+ for (const block of content) {
693
+ if (
694
+ block.type === 'text' &&
695
+ 'text' in block &&
696
+ (block.text as string).includes('[Request interrupted by user')
697
+ ) {
698
+ userInterruptions++
699
+ break
700
+ }
701
+ }
702
+ }
703
+ }
704
+ }
705
+
706
+ return {
707
+ toolCounts,
708
+ languages,
709
+ gitCommits,
710
+ gitPushes,
711
+ inputTokens,
712
+ outputTokens,
713
+ // New stats
714
+ userInterruptions,
715
+ userResponseTimes,
716
+ toolErrors,
717
+ toolErrorCategories,
718
+ usesTaskAgent,
719
+ usesMcp,
720
+ usesWebSearch,
721
+ usesWebFetch,
722
+ // Additional stats
723
+ linesAdded,
724
+ linesRemoved,
725
+ filesModified,
726
+ messageHours,
727
+ userMessageTimestamps,
728
+ }
729
+ }
730
+
731
+ function hasValidDates(log: LogOption): boolean {
732
+ return (
733
+ !Number.isNaN(log.created.getTime()) &&
734
+ !Number.isNaN(log.modified.getTime())
735
+ )
736
+ }
737
+
738
+ function logToSessionMeta(log: LogOption): SessionMeta {
739
+ const stats = extractToolStats(log)
740
+ const sessionId = getSessionIdFromLog(log) || 'unknown'
741
+ const startTime = log.created.toISOString()
742
+ const durationMinutes = Math.round(
743
+ (log.modified.getTime() - log.created.getTime()) / 1000 / 60,
744
+ )
745
+
746
+ let userMessageCount = 0
747
+ let assistantMessageCount = 0
748
+ for (const msg of log.messages) {
749
+ if (msg.type === 'assistant') assistantMessageCount++
750
+ // Only count user messages that have actual text content (human messages)
751
+ // not just tool_result messages (matching Python reference)
752
+ if (msg.type === 'user' && msg.message) {
753
+ const content = msg.message.content
754
+ let isHumanMessage = false
755
+ if (typeof content === 'string' && content.trim()) {
756
+ isHumanMessage = true
757
+ } else if (Array.isArray(content)) {
758
+ for (const block of content) {
759
+ if (block.type === 'text' && 'text' in block) {
760
+ isHumanMessage = true
761
+ break
762
+ }
763
+ }
764
+ }
765
+ if (isHumanMessage) {
766
+ userMessageCount++
767
+ }
768
+ }
769
+ }
770
+
771
+ return {
772
+ session_id: sessionId,
773
+ project_path: log.projectPath || '',
774
+ start_time: startTime,
775
+ duration_minutes: durationMinutes,
776
+ user_message_count: userMessageCount,
777
+ assistant_message_count: assistantMessageCount,
778
+ tool_counts: stats.toolCounts,
779
+ languages: stats.languages,
780
+ git_commits: stats.gitCommits,
781
+ git_pushes: stats.gitPushes,
782
+ input_tokens: stats.inputTokens,
783
+ output_tokens: stats.outputTokens,
784
+ first_prompt: log.firstPrompt || '',
785
+ summary: log.summary,
786
+ // New stats
787
+ user_interruptions: stats.userInterruptions,
788
+ user_response_times: stats.userResponseTimes,
789
+ tool_errors: stats.toolErrors,
790
+ tool_error_categories: stats.toolErrorCategories,
791
+ uses_task_agent: stats.usesTaskAgent,
792
+ uses_mcp: stats.usesMcp,
793
+ uses_web_search: stats.usesWebSearch,
794
+ uses_web_fetch: stats.usesWebFetch,
795
+ // Additional stats
796
+ lines_added: stats.linesAdded,
797
+ lines_removed: stats.linesRemoved,
798
+ files_modified: stats.filesModified.size,
799
+ message_hours: stats.messageHours,
800
+ user_message_timestamps: stats.userMessageTimestamps,
801
+ }
802
+ }
803
+
804
+ /**
805
+ * Deduplicate conversation branches within the same session.
806
+ *
807
+ * When a session file has multiple leaf messages (from retries or branching),
808
+ * loadAllLogsFromSessionFile produces one LogOption per leaf. Each branch
809
+ * shares the same root message, so its duration overlaps with sibling
810
+ * branches. This keeps only the branch with the most user messages
811
+ * (tie-break by longest duration) per session_id.
812
+ */
813
+ export function deduplicateSessionBranches(
814
+ entries: Array<{ log: LogOption; meta: SessionMeta }>,
815
+ ): Array<{ log: LogOption; meta: SessionMeta }> {
816
+ const bestBySession = new Map<string, { log: LogOption; meta: SessionMeta }>()
817
+ for (const entry of entries) {
818
+ const id = entry.meta.session_id
819
+ const existing = bestBySession.get(id)
820
+ if (
821
+ !existing ||
822
+ entry.meta.user_message_count > existing.meta.user_message_count ||
823
+ (entry.meta.user_message_count === existing.meta.user_message_count &&
824
+ entry.meta.duration_minutes > existing.meta.duration_minutes)
825
+ ) {
826
+ bestBySession.set(id, entry)
827
+ }
828
+ }
829
+ return [...bestBySession.values()]
830
+ }
831
+
832
+ function formatTranscriptForFacets(log: LogOption): string {
833
+ const lines: string[] = []
834
+ const meta = logToSessionMeta(log)
835
+
836
+ lines.push(`Session: ${meta.session_id.slice(0, 8)}`)
837
+ lines.push(`Date: ${meta.start_time}`)
838
+ lines.push(`Project: ${meta.project_path}`)
839
+ lines.push(`Duration: ${meta.duration_minutes} min`)
840
+ lines.push('')
841
+
842
+ for (const msg of log.messages) {
843
+ if (msg.type === 'user' && msg.message) {
844
+ const content = msg.message.content
845
+ if (typeof content === 'string') {
846
+ lines.push(`[User]: ${content.slice(0, 500)}`)
847
+ } else if (Array.isArray(content)) {
848
+ for (const block of content) {
849
+ if (block.type === 'text' && 'text' in block) {
850
+ lines.push(`[User]: ${(block.text as string).slice(0, 500)}`)
851
+ }
852
+ }
853
+ }
854
+ } else if (msg.type === 'assistant' && msg.message) {
855
+ const content = msg.message.content
856
+ if (Array.isArray(content)) {
857
+ for (const block of content) {
858
+ if (block.type === 'text' && 'text' in block) {
859
+ lines.push(`[Assistant]: ${(block.text as string).slice(0, 300)}`)
860
+ } else if (block.type === 'tool_use' && 'name' in block) {
861
+ lines.push(`[Tool: ${block.name}]`)
862
+ }
863
+ }
864
+ }
865
+ }
866
+ }
867
+
868
+ return lines.join('\n')
869
+ }
870
+
871
+ const SUMMARIZE_CHUNK_PROMPT = `Summarize this portion of a Claude Code session transcript. Focus on:
872
+ 1. What the user asked for
873
+ 2. What Claude did (tools used, files modified)
874
+ 3. Any friction or issues
875
+ 4. The outcome
876
+
877
+ Keep it concise - 3-5 sentences. Preserve specific details like file names, error messages, and user feedback.
878
+
879
+ TRANSCRIPT CHUNK:
880
+ `
881
+
882
+ async function summarizeTranscriptChunk(chunk: string): Promise<string> {
883
+ try {
884
+ const result = await queryWithModel({
885
+ systemPrompt: asSystemPrompt([]),
886
+ userPrompt: SUMMARIZE_CHUNK_PROMPT + chunk,
887
+ signal: new AbortController().signal,
888
+ options: {
889
+ model: getAnalysisModel(),
890
+ querySource: 'insights',
891
+ agents: [],
892
+ isNonInteractiveSession: true,
893
+ hasAppendSystemPrompt: false,
894
+ mcpTools: [],
895
+ maxOutputTokensOverride: 500,
896
+ },
897
+ })
898
+
899
+ const text = extractTextContent(result.message.content)
900
+ return text || chunk.slice(0, 2000)
901
+ } catch {
902
+ // On error, just return truncated chunk
903
+ return chunk.slice(0, 2000)
904
+ }
905
+ }
906
+
907
+ async function formatTranscriptWithSummarization(
908
+ log: LogOption,
909
+ ): Promise<string> {
910
+ const fullTranscript = formatTranscriptForFacets(log)
911
+
912
+ // If under 30k chars, use as-is
913
+ if (fullTranscript.length <= 30000) {
914
+ return fullTranscript
915
+ }
916
+
917
+ // For long transcripts, split into chunks and summarize in parallel
918
+ const CHUNK_SIZE = 25000
919
+ const chunks: string[] = []
920
+
921
+ for (let i = 0; i < fullTranscript.length; i += CHUNK_SIZE) {
922
+ chunks.push(fullTranscript.slice(i, i + CHUNK_SIZE))
923
+ }
924
+
925
+ // Summarize all chunks in parallel
926
+ const summaries = await Promise.all(chunks.map(summarizeTranscriptChunk))
927
+
928
+ // Combine summaries with session header
929
+ const meta = logToSessionMeta(log)
930
+ const header = [
931
+ `Session: ${meta.session_id.slice(0, 8)}`,
932
+ `Date: ${meta.start_time}`,
933
+ `Project: ${meta.project_path}`,
934
+ `Duration: ${meta.duration_minutes} min`,
935
+ `[Long session - ${chunks.length} parts summarized]`,
936
+ '',
937
+ ].join('\n')
938
+
939
+ return header + summaries.join('\n\n---\n\n')
940
+ }
941
+
942
+ async function loadCachedFacets(
943
+ sessionId: string,
944
+ ): Promise<SessionFacets | null> {
945
+ const facetPath = join(getFacetsDir(), `${sessionId}.json`)
946
+ try {
947
+ const content = await readFile(facetPath, { encoding: 'utf-8' })
948
+ const parsed: unknown = jsonParse(content)
949
+ if (!isValidSessionFacets(parsed)) {
950
+ // Delete corrupted cache file so it gets re-extracted next run
951
+ try {
952
+ await unlink(facetPath)
953
+ } catch {
954
+ // Ignore deletion errors
955
+ }
956
+ return null
957
+ }
958
+ return parsed
959
+ } catch {
960
+ return null
961
+ }
962
+ }
963
+
964
+ async function saveFacets(facets: SessionFacets): Promise<void> {
965
+ try {
966
+ await mkdir(getFacetsDir(), { recursive: true })
967
+ } catch {
968
+ // Directory may already exist
969
+ }
970
+ const facetPath = join(getFacetsDir(), `${facets.session_id}.json`)
971
+ await writeFile(facetPath, jsonStringify(facets, null, 2), {
972
+ encoding: 'utf-8',
973
+ mode: 0o600,
974
+ })
975
+ }
976
+
977
+ async function loadCachedSessionMeta(
978
+ sessionId: string,
979
+ ): Promise<SessionMeta | null> {
980
+ const metaPath = join(getSessionMetaDir(), `${sessionId}.json`)
981
+ try {
982
+ const content = await readFile(metaPath, { encoding: 'utf-8' })
983
+ return jsonParse(content)
984
+ } catch {
985
+ return null
986
+ }
987
+ }
988
+
989
+ async function saveSessionMeta(meta: SessionMeta): Promise<void> {
990
+ try {
991
+ await mkdir(getSessionMetaDir(), { recursive: true })
992
+ } catch {
993
+ // Directory may already exist
994
+ }
995
+ const metaPath = join(getSessionMetaDir(), `${meta.session_id}.json`)
996
+ await writeFile(metaPath, jsonStringify(meta, null, 2), {
997
+ encoding: 'utf-8',
998
+ mode: 0o600,
999
+ })
1000
+ }
1001
+
1002
+ async function extractFacetsFromAPI(
1003
+ log: LogOption,
1004
+ sessionId: string,
1005
+ ): Promise<SessionFacets | null> {
1006
+ try {
1007
+ // Use summarization for long transcripts
1008
+ const transcript = await formatTranscriptWithSummarization(log)
1009
+
1010
+ // Build prompt asking for JSON directly (no tool use)
1011
+ const jsonPrompt = `${FACET_EXTRACTION_PROMPT}${transcript}
1012
+
1013
+ RESPOND WITH ONLY A VALID JSON OBJECT matching this schema:
1014
+ {
1015
+ "underlying_goal": "What the user fundamentally wanted to achieve",
1016
+ "goal_categories": {"category_name": count, ...},
1017
+ "outcome": "fully_achieved|mostly_achieved|partially_achieved|not_achieved|unclear_from_transcript",
1018
+ "user_satisfaction_counts": {"level": count, ...},
1019
+ "claude_helpfulness": "unhelpful|slightly_helpful|moderately_helpful|very_helpful|essential",
1020
+ "session_type": "single_task|multi_task|iterative_refinement|exploration|quick_question",
1021
+ "friction_counts": {"friction_type": count, ...},
1022
+ "friction_detail": "One sentence describing friction or empty",
1023
+ "primary_success": "none|fast_accurate_search|correct_code_edits|good_explanations|proactive_help|multi_file_changes|good_debugging",
1024
+ "brief_summary": "One sentence: what user wanted and whether they got it"
1025
+ }`
1026
+
1027
+ const result = await queryWithModel({
1028
+ systemPrompt: asSystemPrompt([]),
1029
+ userPrompt: jsonPrompt,
1030
+ signal: new AbortController().signal,
1031
+ options: {
1032
+ model: getAnalysisModel(),
1033
+ querySource: 'insights',
1034
+ agents: [],
1035
+ isNonInteractiveSession: true,
1036
+ hasAppendSystemPrompt: false,
1037
+ mcpTools: [],
1038
+ maxOutputTokensOverride: 4096,
1039
+ },
1040
+ })
1041
+
1042
+ const text = extractTextContent(result.message.content)
1043
+
1044
+ // Parse JSON from response
1045
+ const jsonMatch = text.match(/\{[\s\S]*\}/)
1046
+ if (!jsonMatch) return null
1047
+
1048
+ const parsed: unknown = jsonParse(jsonMatch[0])
1049
+ if (!isValidSessionFacets(parsed)) return null
1050
+ const facets: SessionFacets = { ...parsed, session_id: sessionId }
1051
+ return facets
1052
+ } catch (err) {
1053
+ logError(new Error(`Facet extraction failed: ${toError(err).message}`))
1054
+ return null
1055
+ }
1056
+ }
1057
+
1058
+ /**
1059
+ * Detects multi-clauding (using multiple Claude sessions concurrently).
1060
+ * Uses a sliding window to find the pattern: session1 -> session2 -> session1
1061
+ * within a 30-minute window.
1062
+ */
1063
+ export function detectMultiClauding(
1064
+ sessions: Array<{
1065
+ session_id: string
1066
+ user_message_timestamps: string[]
1067
+ }>,
1068
+ ): {
1069
+ overlap_events: number
1070
+ sessions_involved: number
1071
+ user_messages_during: number
1072
+ } {
1073
+ const OVERLAP_WINDOW_MS = 30 * 60000
1074
+ const allSessionMessages: Array<{ ts: number; sessionId: string }> = []
1075
+
1076
+ for (const session of sessions) {
1077
+ for (const timestamp of session.user_message_timestamps) {
1078
+ try {
1079
+ const ts = new Date(timestamp).getTime()
1080
+ allSessionMessages.push({ ts, sessionId: session.session_id })
1081
+ } catch {
1082
+ // Skip invalid timestamps
1083
+ }
1084
+ }
1085
+ }
1086
+
1087
+ allSessionMessages.sort((a, b) => a.ts - b.ts)
1088
+
1089
+ const multiClaudeSessionPairs = new Set<string>()
1090
+ const messagesDuringMulticlaude = new Set<string>()
1091
+
1092
+ // Sliding window: sessionLastIndex tracks the most recent index for each session
1093
+ let windowStart = 0
1094
+ const sessionLastIndex = new Map<string, number>()
1095
+
1096
+ for (let i = 0; i < allSessionMessages.length; i++) {
1097
+ const msg = allSessionMessages[i]!
1098
+
1099
+ // Shrink window from the left
1100
+ while (
1101
+ windowStart < i &&
1102
+ msg.ts - allSessionMessages[windowStart]!.ts > OVERLAP_WINDOW_MS
1103
+ ) {
1104
+ const expiring = allSessionMessages[windowStart]!
1105
+ if (sessionLastIndex.get(expiring.sessionId) === windowStart) {
1106
+ sessionLastIndex.delete(expiring.sessionId)
1107
+ }
1108
+ windowStart++
1109
+ }
1110
+
1111
+ // Check if this session appeared earlier in the window (pattern: s1 -> s2 -> s1)
1112
+ const prevIndex = sessionLastIndex.get(msg.sessionId)
1113
+ if (prevIndex !== undefined) {
1114
+ for (let j = prevIndex + 1; j < i; j++) {
1115
+ const between = allSessionMessages[j]!
1116
+ if (between.sessionId !== msg.sessionId) {
1117
+ const pair = [msg.sessionId, between.sessionId].sort().join(':')
1118
+ multiClaudeSessionPairs.add(pair)
1119
+ messagesDuringMulticlaude.add(
1120
+ `${allSessionMessages[prevIndex]!.ts}:${msg.sessionId}`,
1121
+ )
1122
+ messagesDuringMulticlaude.add(`${between.ts}:${between.sessionId}`)
1123
+ messagesDuringMulticlaude.add(`${msg.ts}:${msg.sessionId}`)
1124
+ break
1125
+ }
1126
+ }
1127
+ }
1128
+
1129
+ sessionLastIndex.set(msg.sessionId, i)
1130
+ }
1131
+
1132
+ const sessionsWithOverlaps = new Set<string>()
1133
+ for (const pair of multiClaudeSessionPairs) {
1134
+ const [s1, s2] = pair.split(':')
1135
+ if (s1) sessionsWithOverlaps.add(s1)
1136
+ if (s2) sessionsWithOverlaps.add(s2)
1137
+ }
1138
+
1139
+ return {
1140
+ overlap_events: multiClaudeSessionPairs.size,
1141
+ sessions_involved: sessionsWithOverlaps.size,
1142
+ user_messages_during: messagesDuringMulticlaude.size,
1143
+ }
1144
+ }
1145
+
1146
+ function aggregateData(
1147
+ sessions: SessionMeta[],
1148
+ facets: Map<string, SessionFacets>,
1149
+ ): AggregatedData {
1150
+ const result: AggregatedData = {
1151
+ total_sessions: sessions.length,
1152
+ sessions_with_facets: facets.size,
1153
+ date_range: { start: '', end: '' },
1154
+ total_messages: 0,
1155
+ total_duration_hours: 0,
1156
+ total_input_tokens: 0,
1157
+ total_output_tokens: 0,
1158
+ tool_counts: {},
1159
+ languages: {},
1160
+ git_commits: 0,
1161
+ git_pushes: 0,
1162
+ projects: {},
1163
+ goal_categories: {},
1164
+ outcomes: {},
1165
+ satisfaction: {},
1166
+ helpfulness: {},
1167
+ session_types: {},
1168
+ friction: {},
1169
+ success: {},
1170
+ session_summaries: [],
1171
+ // New stats
1172
+ total_interruptions: 0,
1173
+ total_tool_errors: 0,
1174
+ tool_error_categories: {},
1175
+ user_response_times: [],
1176
+ median_response_time: 0,
1177
+ avg_response_time: 0,
1178
+ sessions_using_task_agent: 0,
1179
+ sessions_using_mcp: 0,
1180
+ sessions_using_web_search: 0,
1181
+ sessions_using_web_fetch: 0,
1182
+ // Additional stats
1183
+ total_lines_added: 0,
1184
+ total_lines_removed: 0,
1185
+ total_files_modified: 0,
1186
+ days_active: 0,
1187
+ messages_per_day: 0,
1188
+ message_hours: [],
1189
+ // Multi-clauding stats (matching Python reference)
1190
+ multi_clauding: {
1191
+ overlap_events: 0,
1192
+ sessions_involved: 0,
1193
+ user_messages_during: 0,
1194
+ },
1195
+ }
1196
+
1197
+ const dates: string[] = []
1198
+ const allResponseTimes: number[] = []
1199
+ const allMessageHours: number[] = []
1200
+
1201
+ for (const session of sessions) {
1202
+ dates.push(session.start_time)
1203
+ result.total_messages += session.user_message_count
1204
+ result.total_duration_hours += session.duration_minutes / 60
1205
+ result.total_input_tokens += session.input_tokens
1206
+ result.total_output_tokens += session.output_tokens
1207
+ result.git_commits += session.git_commits
1208
+ result.git_pushes += session.git_pushes
1209
+
1210
+ // New stats aggregation
1211
+ result.total_interruptions += session.user_interruptions
1212
+ result.total_tool_errors += session.tool_errors
1213
+ for (const [cat, count] of Object.entries(session.tool_error_categories)) {
1214
+ result.tool_error_categories[cat] =
1215
+ (result.tool_error_categories[cat] || 0) + count
1216
+ }
1217
+ allResponseTimes.push(...session.user_response_times)
1218
+ if (session.uses_task_agent) result.sessions_using_task_agent++
1219
+ if (session.uses_mcp) result.sessions_using_mcp++
1220
+ if (session.uses_web_search) result.sessions_using_web_search++
1221
+ if (session.uses_web_fetch) result.sessions_using_web_fetch++
1222
+
1223
+ // Additional stats aggregation
1224
+ result.total_lines_added += session.lines_added
1225
+ result.total_lines_removed += session.lines_removed
1226
+ result.total_files_modified += session.files_modified
1227
+ allMessageHours.push(...session.message_hours)
1228
+
1229
+ for (const [tool, count] of Object.entries(session.tool_counts)) {
1230
+ result.tool_counts[tool] = (result.tool_counts[tool] || 0) + count
1231
+ }
1232
+
1233
+ for (const [lang, count] of Object.entries(session.languages)) {
1234
+ result.languages[lang] = (result.languages[lang] || 0) + count
1235
+ }
1236
+
1237
+ if (session.project_path) {
1238
+ result.projects[session.project_path] =
1239
+ (result.projects[session.project_path] || 0) + 1
1240
+ }
1241
+
1242
+ const sessionFacets = facets.get(session.session_id)
1243
+ if (sessionFacets) {
1244
+ // Goal categories
1245
+ for (const [cat, count] of safeEntries(sessionFacets.goal_categories)) {
1246
+ if (count > 0) {
1247
+ result.goal_categories[cat] =
1248
+ (result.goal_categories[cat] || 0) + count
1249
+ }
1250
+ }
1251
+
1252
+ // Outcomes
1253
+ result.outcomes[sessionFacets.outcome] =
1254
+ (result.outcomes[sessionFacets.outcome] || 0) + 1
1255
+
1256
+ // Satisfaction counts
1257
+ for (const [level, count] of safeEntries(
1258
+ sessionFacets.user_satisfaction_counts,
1259
+ )) {
1260
+ if (count > 0) {
1261
+ result.satisfaction[level] = (result.satisfaction[level] || 0) + count
1262
+ }
1263
+ }
1264
+
1265
+ // Helpfulness
1266
+ result.helpfulness[sessionFacets.claude_helpfulness] =
1267
+ (result.helpfulness[sessionFacets.claude_helpfulness] || 0) + 1
1268
+
1269
+ // Session types
1270
+ result.session_types[sessionFacets.session_type] =
1271
+ (result.session_types[sessionFacets.session_type] || 0) + 1
1272
+
1273
+ // Friction counts
1274
+ for (const [type, count] of safeEntries(sessionFacets.friction_counts)) {
1275
+ if (count > 0) {
1276
+ result.friction[type] = (result.friction[type] || 0) + count
1277
+ }
1278
+ }
1279
+
1280
+ // Success factors
1281
+ if (sessionFacets.primary_success !== 'none') {
1282
+ result.success[sessionFacets.primary_success] =
1283
+ (result.success[sessionFacets.primary_success] || 0) + 1
1284
+ }
1285
+ }
1286
+
1287
+ if (result.session_summaries.length < 50) {
1288
+ result.session_summaries.push({
1289
+ id: session.session_id.slice(0, 8),
1290
+ date: session.start_time.split('T')[0] || '',
1291
+ summary: session.summary || session.first_prompt.slice(0, 100),
1292
+ goal: sessionFacets?.underlying_goal,
1293
+ })
1294
+ }
1295
+ }
1296
+
1297
+ dates.sort()
1298
+ result.date_range.start = dates[0]?.split('T')[0] || ''
1299
+ result.date_range.end = dates[dates.length - 1]?.split('T')[0] || ''
1300
+
1301
+ // Calculate response time stats
1302
+ result.user_response_times = allResponseTimes
1303
+ if (allResponseTimes.length > 0) {
1304
+ const sorted = [...allResponseTimes].sort((a, b) => a - b)
1305
+ result.median_response_time = sorted[Math.floor(sorted.length / 2)] || 0
1306
+ result.avg_response_time =
1307
+ allResponseTimes.reduce((a, b) => a + b, 0) / allResponseTimes.length
1308
+ }
1309
+
1310
+ // Calculate days active and messages per day
1311
+ const uniqueDays = new Set(dates.map(d => d.split('T')[0]))
1312
+ result.days_active = uniqueDays.size
1313
+ result.messages_per_day =
1314
+ result.days_active > 0
1315
+ ? Math.round((result.total_messages / result.days_active) * 10) / 10
1316
+ : 0
1317
+
1318
+ // Store message hours for time-of-day chart
1319
+ result.message_hours = allMessageHours
1320
+
1321
+ result.multi_clauding = detectMultiClauding(sessions)
1322
+
1323
+ return result
1324
+ }
1325
+
1326
+ // ============================================================================
1327
+ // Parallel Insights Generation (6 sections)
1328
+ // ============================================================================
1329
+
1330
+ type InsightSection = {
1331
+ name: string
1332
+ prompt: string
1333
+ maxTokens: number
1334
+ }
1335
+
1336
+ // Sections that run in parallel first
1337
+ const INSIGHT_SECTIONS: InsightSection[] = [
1338
+ {
1339
+ name: 'project_areas',
1340
+ prompt: `Analyze this Claude Code usage data and identify project areas.
1341
+
1342
+ RESPOND WITH ONLY A VALID JSON OBJECT:
1343
+ {
1344
+ "areas": [
1345
+ {"name": "Area name", "session_count": N, "description": "2-3 sentences about what was worked on and how Claude Code was used."}
1346
+ ]
1347
+ }
1348
+
1349
+ Include 4-5 areas. Skip internal CC operations.`,
1350
+ maxTokens: 8192,
1351
+ },
1352
+ {
1353
+ name: 'interaction_style',
1354
+ prompt: `Analyze this Claude Code usage data and describe the user's interaction style.
1355
+
1356
+ RESPOND WITH ONLY A VALID JSON OBJECT:
1357
+ {
1358
+ "narrative": "2-3 paragraphs analyzing HOW the user interacts with Claude Code. Use second person 'you'. Describe patterns: iterate quickly vs detailed upfront specs? Interrupt often or let Claude run? Include specific examples. Use **bold** for key insights.",
1359
+ "key_pattern": "One sentence summary of most distinctive interaction style"
1360
+ }`,
1361
+ maxTokens: 8192,
1362
+ },
1363
+ {
1364
+ name: 'what_works',
1365
+ prompt: `Analyze this Claude Code usage data and identify what's working well for this user. Use second person ("you").
1366
+
1367
+ RESPOND WITH ONLY A VALID JSON OBJECT:
1368
+ {
1369
+ "intro": "1 sentence of context",
1370
+ "impressive_workflows": [
1371
+ {"title": "Short title (3-6 words)", "description": "2-3 sentences describing the impressive workflow or approach. Use 'you' not 'the user'."}
1372
+ ]
1373
+ }
1374
+
1375
+ Include 3 impressive workflows.`,
1376
+ maxTokens: 8192,
1377
+ },
1378
+ {
1379
+ name: 'friction_analysis',
1380
+ prompt: `Analyze this Claude Code usage data and identify friction points for this user. Use second person ("you").
1381
+
1382
+ RESPOND WITH ONLY A VALID JSON OBJECT:
1383
+ {
1384
+ "intro": "1 sentence summarizing friction patterns",
1385
+ "categories": [
1386
+ {"category": "Concrete category name", "description": "1-2 sentences explaining this category and what could be done differently. Use 'you' not 'the user'.", "examples": ["Specific example with consequence", "Another example"]}
1387
+ ]
1388
+ }
1389
+
1390
+ Include 3 friction categories with 2 examples each.`,
1391
+ maxTokens: 8192,
1392
+ },
1393
+ {
1394
+ name: 'suggestions',
1395
+ prompt: `Analyze this Claude Code usage data and suggest improvements.
1396
+
1397
+ ## CC FEATURES REFERENCE (pick from these for features_to_try):
1398
+ 1. **MCP Servers**: Connect Claude to external tools, databases, and APIs via Model Context Protocol.
1399
+ - How to use: Run \`claude mcp add <server-name> -- <command>\`
1400
+ - Good for: database queries, Slack integration, GitHub issue lookup, connecting to internal APIs
1401
+
1402
+ 2. **Custom Skills**: Reusable prompts you define as markdown files that run with a single /command.
1403
+ - How to use: Create \`.claude/skills/commit/SKILL.md\` with instructions. Then type \`/commit\` to run it.
1404
+ - Good for: repetitive workflows - /commit, /review, /test, /deploy, /pr, or complex multi-step workflows
1405
+
1406
+ 3. **Hooks**: Shell commands that auto-run at specific lifecycle events.
1407
+ - How to use: Add to \`.claude/settings.json\` under "hooks" key.
1408
+ - Good for: auto-formatting code, running type checks, enforcing conventions
1409
+
1410
+ 4. **Headless Mode**: Run Claude non-interactively from scripts and CI/CD.
1411
+ - How to use: \`claude -p "fix lint errors" --allowedTools "Edit,Read,Bash"\`
1412
+ - Good for: CI/CD integration, batch code fixes, automated reviews
1413
+
1414
+ 5. **Task Agents**: Claude spawns focused sub-agents for complex exploration or parallel work.
1415
+ - How to use: Claude auto-invokes when helpful, or ask "use an agent to explore X"
1416
+ - Good for: codebase exploration, understanding complex systems
1417
+
1418
+ RESPOND WITH ONLY A VALID JSON OBJECT:
1419
+ {
1420
+ "claude_md_additions": [
1421
+ {"addition": "A specific line or block to add to CLAUDE.md based on workflow patterns. E.g., 'Always run tests after modifying auth-related files'", "why": "1 sentence explaining why this would help based on actual sessions", "prompt_scaffold": "Instructions for where to add this in CLAUDE.md. E.g., 'Add under ## Testing section'"}
1422
+ ],
1423
+ "features_to_try": [
1424
+ {"feature": "Feature name from CC FEATURES REFERENCE above", "one_liner": "What it does", "why_for_you": "Why this would help YOU based on your sessions", "example_code": "Actual command or config to copy"}
1425
+ ],
1426
+ "usage_patterns": [
1427
+ {"title": "Short title", "suggestion": "1-2 sentence summary", "detail": "3-4 sentences explaining how this applies to YOUR work", "copyable_prompt": "A specific prompt to copy and try"}
1428
+ ]
1429
+ }
1430
+
1431
+ IMPORTANT for claude_md_additions: PRIORITIZE instructions that appear MULTIPLE TIMES in the user data. If user told Claude the same thing in 2+ sessions (e.g., 'always run tests', 'use TypeScript'), that's a PRIME candidate - they shouldn't have to repeat themselves.
1432
+
1433
+ IMPORTANT for features_to_try: Pick 2-3 from the CC FEATURES REFERENCE above. Include 2-3 items for each category.`,
1434
+ maxTokens: 8192,
1435
+ },
1436
+ {
1437
+ name: 'on_the_horizon',
1438
+ prompt: `Analyze this Claude Code usage data and identify future opportunities.
1439
+
1440
+ RESPOND WITH ONLY A VALID JSON OBJECT:
1441
+ {
1442
+ "intro": "1 sentence about evolving AI-assisted development",
1443
+ "opportunities": [
1444
+ {"title": "Short title (4-8 words)", "whats_possible": "2-3 ambitious sentences about autonomous workflows", "how_to_try": "1-2 sentences mentioning relevant tooling", "copyable_prompt": "Detailed prompt to try"}
1445
+ ]
1446
+ }
1447
+
1448
+ Include 3 opportunities. Think BIG - autonomous workflows, parallel agents, iterating against tests.`,
1449
+ maxTokens: 8192,
1450
+ },
1451
+ ...(process.env.USER_TYPE === 'ant'
1452
+ ? [
1453
+ {
1454
+ name: 'cc_team_improvements',
1455
+ prompt: `Analyze this Claude Code usage data and suggest product improvements for the CC team.
1456
+
1457
+ RESPOND WITH ONLY A VALID JSON OBJECT:
1458
+ {
1459
+ "improvements": [
1460
+ {"title": "Product/tooling improvement", "detail": "3-4 sentences describing the improvement", "evidence": "3-4 sentences with specific session examples"}
1461
+ ]
1462
+ }
1463
+
1464
+ Include 2-3 improvements based on friction patterns observed.`,
1465
+ maxTokens: 8192,
1466
+ },
1467
+ {
1468
+ name: 'model_behavior_improvements',
1469
+ prompt: `Analyze this Claude Code usage data and suggest model behavior improvements.
1470
+
1471
+ RESPOND WITH ONLY A VALID JSON OBJECT:
1472
+ {
1473
+ "improvements": [
1474
+ {"title": "Model behavior change", "detail": "3-4 sentences describing what the model should do differently", "evidence": "3-4 sentences with specific examples"}
1475
+ ]
1476
+ }
1477
+
1478
+ Include 2-3 improvements based on friction patterns observed.`,
1479
+ maxTokens: 8192,
1480
+ },
1481
+ ]
1482
+ : []),
1483
+ {
1484
+ name: 'fun_ending',
1485
+ prompt: `Analyze this Claude Code usage data and find a memorable moment.
1486
+
1487
+ RESPOND WITH ONLY A VALID JSON OBJECT:
1488
+ {
1489
+ "headline": "A memorable QUALITATIVE moment from the transcripts - not a statistic. Something human, funny, or surprising.",
1490
+ "detail": "Brief context about when/where this happened"
1491
+ }
1492
+
1493
+ Find something genuinely interesting or amusing from the session summaries.`,
1494
+ maxTokens: 8192,
1495
+ },
1496
+ ]
1497
+
1498
+ type InsightResults = {
1499
+ at_a_glance?: {
1500
+ whats_working?: string
1501
+ whats_hindering?: string
1502
+ quick_wins?: string
1503
+ ambitious_workflows?: string
1504
+ }
1505
+ project_areas?: {
1506
+ areas?: Array<{ name: string; session_count: number; description: string }>
1507
+ }
1508
+ interaction_style?: {
1509
+ narrative?: string
1510
+ key_pattern?: string
1511
+ }
1512
+ what_works?: {
1513
+ intro?: string
1514
+ impressive_workflows?: Array<{ title: string; description: string }>
1515
+ }
1516
+ friction_analysis?: {
1517
+ intro?: string
1518
+ categories?: Array<{
1519
+ category: string
1520
+ description: string
1521
+ examples?: string[]
1522
+ }>
1523
+ }
1524
+ suggestions?: {
1525
+ claude_md_additions?: Array<{
1526
+ addition: string
1527
+ why: string
1528
+ where?: string
1529
+ prompt_scaffold?: string
1530
+ }>
1531
+ features_to_try?: Array<{
1532
+ feature: string
1533
+ one_liner: string
1534
+ why_for_you: string
1535
+ example_code?: string
1536
+ }>
1537
+ usage_patterns?: Array<{
1538
+ title: string
1539
+ suggestion: string
1540
+ detail?: string
1541
+ copyable_prompt?: string
1542
+ }>
1543
+ }
1544
+ on_the_horizon?: {
1545
+ intro?: string
1546
+ opportunities?: Array<{
1547
+ title: string
1548
+ whats_possible: string
1549
+ how_to_try?: string
1550
+ copyable_prompt?: string
1551
+ }>
1552
+ }
1553
+ cc_team_improvements?: {
1554
+ improvements?: Array<{
1555
+ title: string
1556
+ detail: string
1557
+ evidence?: string
1558
+ }>
1559
+ }
1560
+ model_behavior_improvements?: {
1561
+ improvements?: Array<{
1562
+ title: string
1563
+ detail: string
1564
+ evidence?: string
1565
+ }>
1566
+ }
1567
+ fun_ending?: {
1568
+ headline?: string
1569
+ detail?: string
1570
+ }
1571
+ }
1572
+
1573
+ async function generateSectionInsight(
1574
+ section: InsightSection,
1575
+ dataContext: string,
1576
+ ): Promise<{ name: string; result: unknown }> {
1577
+ try {
1578
+ const result = await queryWithModel({
1579
+ systemPrompt: asSystemPrompt([]),
1580
+ userPrompt: section.prompt + '\n\nDATA:\n' + dataContext,
1581
+ signal: new AbortController().signal,
1582
+ options: {
1583
+ model: getInsightsModel(),
1584
+ querySource: 'insights',
1585
+ agents: [],
1586
+ isNonInteractiveSession: true,
1587
+ hasAppendSystemPrompt: false,
1588
+ mcpTools: [],
1589
+ maxOutputTokensOverride: section.maxTokens,
1590
+ },
1591
+ })
1592
+
1593
+ const text = extractTextContent(result.message.content)
1594
+
1595
+ if (text) {
1596
+ // Parse JSON from response
1597
+ const jsonMatch = text.match(/\{[\s\S]*\}/)
1598
+ if (jsonMatch) {
1599
+ try {
1600
+ return { name: section.name, result: jsonParse(jsonMatch[0]) }
1601
+ } catch {
1602
+ return { name: section.name, result: null }
1603
+ }
1604
+ }
1605
+ }
1606
+ return { name: section.name, result: null }
1607
+ } catch (err) {
1608
+ logError(new Error(`${section.name} failed: ${toError(err).message}`))
1609
+ return { name: section.name, result: null }
1610
+ }
1611
+ }
1612
+
1613
+ async function generateParallelInsights(
1614
+ data: AggregatedData,
1615
+ facets: Map<string, SessionFacets>,
1616
+ ): Promise<InsightResults> {
1617
+ // Build data context string
1618
+ const facetSummaries = Array.from(facets.values())
1619
+ .slice(0, 50)
1620
+ .map(f => `- ${f.brief_summary} (${f.outcome}, ${f.claude_helpfulness})`)
1621
+ .join('\n')
1622
+
1623
+ const frictionDetails = Array.from(facets.values())
1624
+ .filter(f => f.friction_detail)
1625
+ .slice(0, 20)
1626
+ .map(f => `- ${f.friction_detail}`)
1627
+ .join('\n')
1628
+
1629
+ const userInstructions = Array.from(facets.values())
1630
+ .flatMap(f => f.user_instructions_to_claude || [])
1631
+ .slice(0, 15)
1632
+ .map(i => `- ${i}`)
1633
+ .join('\n')
1634
+
1635
+ const dataContext = jsonStringify(
1636
+ {
1637
+ sessions: data.total_sessions,
1638
+ analyzed: data.sessions_with_facets,
1639
+ date_range: data.date_range,
1640
+ messages: data.total_messages,
1641
+ hours: Math.round(data.total_duration_hours),
1642
+ commits: data.git_commits,
1643
+ top_tools: Object.entries(data.tool_counts)
1644
+ .sort((a, b) => b[1] - a[1])
1645
+ .slice(0, 8),
1646
+ top_goals: Object.entries(data.goal_categories)
1647
+ .sort((a, b) => b[1] - a[1])
1648
+ .slice(0, 8),
1649
+ outcomes: data.outcomes,
1650
+ satisfaction: data.satisfaction,
1651
+ friction: data.friction,
1652
+ success: data.success,
1653
+ languages: data.languages,
1654
+ },
1655
+ null,
1656
+ 2,
1657
+ )
1658
+
1659
+ const fullContext =
1660
+ dataContext +
1661
+ '\n\nSESSION SUMMARIES:\n' +
1662
+ facetSummaries +
1663
+ '\n\nFRICTION DETAILS:\n' +
1664
+ frictionDetails +
1665
+ '\n\nUSER INSTRUCTIONS TO CLAUDE:\n' +
1666
+ (userInstructions || 'None captured')
1667
+
1668
+ // Run sections in parallel first (excluding at_a_glance)
1669
+ const results = await Promise.all(
1670
+ INSIGHT_SECTIONS.map(section =>
1671
+ generateSectionInsight(section, fullContext),
1672
+ ),
1673
+ )
1674
+
1675
+ // Combine results
1676
+ const insights: InsightResults = {}
1677
+ for (const { name, result } of results) {
1678
+ if (result) {
1679
+ ;(insights as Record<string, unknown>)[name] = result
1680
+ }
1681
+ }
1682
+
1683
+ // Build rich context from generated sections for At a Glance
1684
+ const projectAreasText =
1685
+ (
1686
+ insights.project_areas as {
1687
+ areas?: Array<{ name: string; description: string }>
1688
+ }
1689
+ )?.areas
1690
+ ?.map(a => `- ${a.name}: ${a.description}`)
1691
+ .join('\n') || ''
1692
+
1693
+ const bigWinsText =
1694
+ (
1695
+ insights.what_works as {
1696
+ impressive_workflows?: Array<{ title: string; description: string }>
1697
+ }
1698
+ )?.impressive_workflows
1699
+ ?.map(w => `- ${w.title}: ${w.description}`)
1700
+ .join('\n') || ''
1701
+
1702
+ const frictionText =
1703
+ (
1704
+ insights.friction_analysis as {
1705
+ categories?: Array<{ category: string; description: string }>
1706
+ }
1707
+ )?.categories
1708
+ ?.map(c => `- ${c.category}: ${c.description}`)
1709
+ .join('\n') || ''
1710
+
1711
+ const featuresText =
1712
+ (
1713
+ insights.suggestions as {
1714
+ features_to_try?: Array<{ feature: string; one_liner: string }>
1715
+ }
1716
+ )?.features_to_try
1717
+ ?.map(f => `- ${f.feature}: ${f.one_liner}`)
1718
+ .join('\n') || ''
1719
+
1720
+ const patternsText =
1721
+ (
1722
+ insights.suggestions as {
1723
+ usage_patterns?: Array<{ title: string; suggestion: string }>
1724
+ }
1725
+ )?.usage_patterns
1726
+ ?.map(p => `- ${p.title}: ${p.suggestion}`)
1727
+ .join('\n') || ''
1728
+
1729
+ const horizonText =
1730
+ (
1731
+ insights.on_the_horizon as {
1732
+ opportunities?: Array<{ title: string; whats_possible: string }>
1733
+ }
1734
+ )?.opportunities
1735
+ ?.map(o => `- ${o.title}: ${o.whats_possible}`)
1736
+ .join('\n') || ''
1737
+
1738
+ // Now generate "At a Glance" with access to other sections' outputs
1739
+ const atAGlancePrompt = `You're writing an "At a Glance" summary for a Claude Code usage insights report for Claude Code users. The goal is to help them understand their usage and improve how they can use Claude better, especially as models improve.
1740
+
1741
+ Use this 4-part structure:
1742
+
1743
+ 1. **What's working** - What is the user's unique style of interacting with Claude and what are some impactful things they've done? You can include one or two details, but keep it high level since things might not be fresh in the user's memory. Don't be fluffy or overly complimentary. Also, don't focus on the tool calls they use.
1744
+
1745
+ 2. **What's hindering you** - Split into (a) Claude's fault (misunderstandings, wrong approaches, bugs) and (b) user-side friction (not providing enough context, environment issues -- ideally more general than just one project). Be honest but constructive.
1746
+
1747
+ 3. **Quick wins to try** - Specific Claude Code features they could try from the examples below, or a workflow technique if you think it's really compelling. (Avoid stuff like "Ask Claude to confirm before taking actions" or "Type out more context up front" which are less compelling.)
1748
+
1749
+ 4. **Ambitious workflows for better models** - As we move to much more capable models over the next 3-6 months, what should they prepare for? What workflows that seem impossible now will become possible? Draw from the appropriate section below.
1750
+
1751
+ Keep each section to 2-3 not-too-long sentences. Don't overwhelm the user. Don't mention specific numerical stats or underlined_categories from the session data below. Use a coaching tone.
1752
+
1753
+ RESPOND WITH ONLY A VALID JSON OBJECT:
1754
+ {
1755
+ "whats_working": "(refer to instructions above)",
1756
+ "whats_hindering": "(refer to instructions above)",
1757
+ "quick_wins": "(refer to instructions above)",
1758
+ "ambitious_workflows": "(refer to instructions above)"
1759
+ }
1760
+
1761
+ SESSION DATA:
1762
+ ${fullContext}
1763
+
1764
+ ## Project Areas (what user works on)
1765
+ ${projectAreasText}
1766
+
1767
+ ## Big Wins (impressive accomplishments)
1768
+ ${bigWinsText}
1769
+
1770
+ ## Friction Categories (where things go wrong)
1771
+ ${frictionText}
1772
+
1773
+ ## Features to Try
1774
+ ${featuresText}
1775
+
1776
+ ## Usage Patterns to Adopt
1777
+ ${patternsText}
1778
+
1779
+ ## On the Horizon (ambitious workflows for better models)
1780
+ ${horizonText}`
1781
+
1782
+ const atAGlanceSection: InsightSection = {
1783
+ name: 'at_a_glance',
1784
+ prompt: atAGlancePrompt,
1785
+ maxTokens: 8192,
1786
+ }
1787
+
1788
+ const atAGlanceResult = await generateSectionInsight(atAGlanceSection, '')
1789
+ if (atAGlanceResult.result) {
1790
+ insights.at_a_glance = atAGlanceResult.result as {
1791
+ whats_working?: string
1792
+ whats_hindering?: string
1793
+ quick_wins?: string
1794
+ ambitious_workflows?: string
1795
+ }
1796
+ }
1797
+
1798
+ return insights
1799
+ }
1800
+
1801
+ // Escape HTML but render **bold** as <strong>
1802
+ function escapeHtmlWithBold(text: string): string {
1803
+ const escaped = escapeHtml(text)
1804
+ return escaped.replace(/\*\*(.+?)\*\*/g, '<strong>$1</strong>')
1805
+ }
1806
+
1807
+ // Fixed orderings for specific charts (matching Python reference)
1808
+ const SATISFACTION_ORDER = [
1809
+ 'frustrated',
1810
+ 'dissatisfied',
1811
+ 'likely_satisfied',
1812
+ 'satisfied',
1813
+ 'happy',
1814
+ 'unsure',
1815
+ ]
1816
+
1817
+ const OUTCOME_ORDER = [
1818
+ 'not_achieved',
1819
+ 'partially_achieved',
1820
+ 'mostly_achieved',
1821
+ 'fully_achieved',
1822
+ 'unclear_from_transcript',
1823
+ ]
1824
+
1825
+ function generateBarChart(
1826
+ data: Record<string, number>,
1827
+ color: string,
1828
+ maxItems = 6,
1829
+ fixedOrder?: string[],
1830
+ ): string {
1831
+ let entries: [string, number][]
1832
+
1833
+ if (fixedOrder) {
1834
+ // Use fixed order, only including items that exist in data
1835
+ entries = fixedOrder
1836
+ .filter(key => key in data && (data[key] ?? 0) > 0)
1837
+ .map(key => [key, data[key] ?? 0] as [string, number])
1838
+ } else {
1839
+ // Sort by count descending
1840
+ entries = Object.entries(data)
1841
+ .sort((a, b) => b[1] - a[1])
1842
+ .slice(0, maxItems)
1843
+ }
1844
+
1845
+ if (entries.length === 0) return '<p class="empty">No data</p>'
1846
+
1847
+ const maxVal = Math.max(...entries.map(e => e[1]))
1848
+ return entries
1849
+ .map(([label, count]) => {
1850
+ const pct = (count / maxVal) * 100
1851
+ // Use LABEL_MAP if available, otherwise clean up underscores and title case
1852
+ const cleanLabel =
1853
+ LABEL_MAP[label] ||
1854
+ label.replace(/_/g, ' ').replace(/\b\w/g, c => c.toUpperCase())
1855
+ return `<div class="bar-row">
1856
+ <div class="bar-label">${escapeHtml(cleanLabel)}</div>
1857
+ <div class="bar-track"><div class="bar-fill" style="width:${pct}%;background:${color}"></div></div>
1858
+ <div class="bar-value">${count}</div>
1859
+ </div>`
1860
+ })
1861
+ .join('\n')
1862
+ }
1863
+
1864
+ function generateResponseTimeHistogram(times: number[]): string {
1865
+ if (times.length === 0) return '<p class="empty">No response time data</p>'
1866
+
1867
+ // Create buckets (matching Python reference)
1868
+ const buckets: Record<string, number> = {
1869
+ '2-10s': 0,
1870
+ '10-30s': 0,
1871
+ '30s-1m': 0,
1872
+ '1-2m': 0,
1873
+ '2-5m': 0,
1874
+ '5-15m': 0,
1875
+ '>15m': 0,
1876
+ }
1877
+
1878
+ for (const t of times) {
1879
+ if (t < 10) buckets['2-10s'] = (buckets['2-10s'] ?? 0) + 1
1880
+ else if (t < 30) buckets['10-30s'] = (buckets['10-30s'] ?? 0) + 1
1881
+ else if (t < 60) buckets['30s-1m'] = (buckets['30s-1m'] ?? 0) + 1
1882
+ else if (t < 120) buckets['1-2m'] = (buckets['1-2m'] ?? 0) + 1
1883
+ else if (t < 300) buckets['2-5m'] = (buckets['2-5m'] ?? 0) + 1
1884
+ else if (t < 900) buckets['5-15m'] = (buckets['5-15m'] ?? 0) + 1
1885
+ else buckets['>15m'] = (buckets['>15m'] ?? 0) + 1
1886
+ }
1887
+
1888
+ const maxVal = Math.max(...Object.values(buckets))
1889
+ if (maxVal === 0) return '<p class="empty">No response time data</p>'
1890
+
1891
+ return Object.entries(buckets)
1892
+ .map(([label, count]) => {
1893
+ const pct = (count / maxVal) * 100
1894
+ return `<div class="bar-row">
1895
+ <div class="bar-label">${label}</div>
1896
+ <div class="bar-track"><div class="bar-fill" style="width:${pct}%;background:#6366f1"></div></div>
1897
+ <div class="bar-value">${count}</div>
1898
+ </div>`
1899
+ })
1900
+ .join('\n')
1901
+ }
1902
+
1903
+ function generateTimeOfDayChart(messageHours: number[]): string {
1904
+ if (messageHours.length === 0) return '<p class="empty">No time data</p>'
1905
+
1906
+ // Group into time periods
1907
+ const periods = [
1908
+ { label: 'Morning (6-12)', range: [6, 7, 8, 9, 10, 11] },
1909
+ { label: 'Afternoon (12-18)', range: [12, 13, 14, 15, 16, 17] },
1910
+ { label: 'Evening (18-24)', range: [18, 19, 20, 21, 22, 23] },
1911
+ { label: 'Night (0-6)', range: [0, 1, 2, 3, 4, 5] },
1912
+ ]
1913
+
1914
+ const hourCounts: Record<number, number> = {}
1915
+ for (const h of messageHours) {
1916
+ hourCounts[h] = (hourCounts[h] || 0) + 1
1917
+ }
1918
+
1919
+ const periodCounts = periods.map(p => ({
1920
+ label: p.label,
1921
+ count: p.range.reduce((sum, h) => sum + (hourCounts[h] || 0), 0),
1922
+ }))
1923
+
1924
+ const maxVal = Math.max(...periodCounts.map(p => p.count)) || 1
1925
+
1926
+ const barsHtml = periodCounts
1927
+ .map(
1928
+ p => `
1929
+ <div class="bar-row">
1930
+ <div class="bar-label">${p.label}</div>
1931
+ <div class="bar-track"><div class="bar-fill" style="width:${(p.count / maxVal) * 100}%;background:#8b5cf6"></div></div>
1932
+ <div class="bar-value">${p.count}</div>
1933
+ </div>`,
1934
+ )
1935
+ .join('\n')
1936
+
1937
+ return `<div id="hour-histogram">${barsHtml}</div>`
1938
+ }
1939
+
1940
+ function getHourCountsJson(messageHours: number[]): string {
1941
+ const hourCounts: Record<number, number> = {}
1942
+ for (const h of messageHours) {
1943
+ hourCounts[h] = (hourCounts[h] || 0) + 1
1944
+ }
1945
+ return jsonStringify(hourCounts)
1946
+ }
1947
+
1948
+ function generateHtmlReport(
1949
+ data: AggregatedData,
1950
+ insights: InsightResults,
1951
+ ): string {
1952
+ const markdownToHtml = (md: string): string => {
1953
+ if (!md) return ''
1954
+ return md
1955
+ .split('\n\n')
1956
+ .map(p => {
1957
+ let html = escapeHtml(p)
1958
+ html = html.replace(/\*\*(.+?)\*\*/g, '<strong>$1</strong>')
1959
+ html = html.replace(/^- /gm, '• ')
1960
+ html = html.replace(/\n/g, '<br>')
1961
+ return `<p>${html}</p>`
1962
+ })
1963
+ .join('\n')
1964
+ }
1965
+
1966
+ // Build At a Glance section (new 4-part format with links to sections)
1967
+ const atAGlance = insights.at_a_glance
1968
+ const atAGlanceHtml = atAGlance
1969
+ ? `
1970
+ <div class="at-a-glance">
1971
+ <div class="glance-title">At a Glance</div>
1972
+ <div class="glance-sections">
1973
+ ${atAGlance.whats_working ? `<div class="glance-section"><strong>What's working:</strong> ${escapeHtmlWithBold(atAGlance.whats_working)} <a href="#section-wins" class="see-more">Impressive Things You Did →</a></div>` : ''}
1974
+ ${atAGlance.whats_hindering ? `<div class="glance-section"><strong>What's hindering you:</strong> ${escapeHtmlWithBold(atAGlance.whats_hindering)} <a href="#section-friction" class="see-more">Where Things Go Wrong →</a></div>` : ''}
1975
+ ${atAGlance.quick_wins ? `<div class="glance-section"><strong>Quick wins to try:</strong> ${escapeHtmlWithBold(atAGlance.quick_wins)} <a href="#section-features" class="see-more">Features to Try →</a></div>` : ''}
1976
+ ${atAGlance.ambitious_workflows ? `<div class="glance-section"><strong>Ambitious workflows:</strong> ${escapeHtmlWithBold(atAGlance.ambitious_workflows)} <a href="#section-horizon" class="see-more">On the Horizon →</a></div>` : ''}
1977
+ </div>
1978
+ </div>
1979
+ `
1980
+ : ''
1981
+
1982
+ // Build project areas section
1983
+ const projectAreas = insights.project_areas?.areas || []
1984
+ const projectAreasHtml =
1985
+ projectAreas.length > 0
1986
+ ? `
1987
+ <h2 id="section-work">What You Work On</h2>
1988
+ <div class="project-areas">
1989
+ ${projectAreas
1990
+ .map(
1991
+ area => `
1992
+ <div class="project-area">
1993
+ <div class="area-header">
1994
+ <span class="area-name">${escapeHtml(area.name)}</span>
1995
+ <span class="area-count">~${area.session_count} sessions</span>
1996
+ </div>
1997
+ <div class="area-desc">${escapeHtml(area.description)}</div>
1998
+ </div>
1999
+ `,
2000
+ )
2001
+ .join('')}
2002
+ </div>
2003
+ `
2004
+ : ''
2005
+
2006
+ // Build interaction style section
2007
+ const interactionStyle = insights.interaction_style
2008
+ const interactionHtml = interactionStyle?.narrative
2009
+ ? `
2010
+ <h2 id="section-usage">How You Use Claude Code</h2>
2011
+ <div class="narrative">
2012
+ ${markdownToHtml(interactionStyle.narrative)}
2013
+ ${interactionStyle.key_pattern ? `<div class="key-insight"><strong>Key pattern:</strong> ${escapeHtml(interactionStyle.key_pattern)}</div>` : ''}
2014
+ </div>
2015
+ `
2016
+ : ''
2017
+
2018
+ // Build what works section
2019
+ const whatWorks = insights.what_works
2020
+ const whatWorksHtml =
2021
+ whatWorks?.impressive_workflows && whatWorks.impressive_workflows.length > 0
2022
+ ? `
2023
+ <h2 id="section-wins">Impressive Things You Did</h2>
2024
+ ${whatWorks.intro ? `<p class="section-intro">${escapeHtml(whatWorks.intro)}</p>` : ''}
2025
+ <div class="big-wins">
2026
+ ${whatWorks.impressive_workflows
2027
+ .map(
2028
+ wf => `
2029
+ <div class="big-win">
2030
+ <div class="big-win-title">${escapeHtml(wf.title || '')}</div>
2031
+ <div class="big-win-desc">${escapeHtml(wf.description || '')}</div>
2032
+ </div>
2033
+ `,
2034
+ )
2035
+ .join('')}
2036
+ </div>
2037
+ `
2038
+ : ''
2039
+
2040
+ // Build friction section
2041
+ const frictionAnalysis = insights.friction_analysis
2042
+ const frictionHtml =
2043
+ frictionAnalysis?.categories && frictionAnalysis.categories.length > 0
2044
+ ? `
2045
+ <h2 id="section-friction">Where Things Go Wrong</h2>
2046
+ ${frictionAnalysis.intro ? `<p class="section-intro">${escapeHtml(frictionAnalysis.intro)}</p>` : ''}
2047
+ <div class="friction-categories">
2048
+ ${frictionAnalysis.categories
2049
+ .map(
2050
+ cat => `
2051
+ <div class="friction-category">
2052
+ <div class="friction-title">${escapeHtml(cat.category || '')}</div>
2053
+ <div class="friction-desc">${escapeHtml(cat.description || '')}</div>
2054
+ ${cat.examples ? `<ul class="friction-examples">${cat.examples.map(ex => `<li>${escapeHtml(ex)}</li>`).join('')}</ul>` : ''}
2055
+ </div>
2056
+ `,
2057
+ )
2058
+ .join('')}
2059
+ </div>
2060
+ `
2061
+ : ''
2062
+
2063
+ // Build suggestions section
2064
+ const suggestions = insights.suggestions
2065
+ const suggestionsHtml = suggestions
2066
+ ? `
2067
+ ${
2068
+ suggestions.claude_md_additions &&
2069
+ suggestions.claude_md_additions.length > 0
2070
+ ? `
2071
+ <h2 id="section-features">Existing CC Features to Try</h2>
2072
+ <div class="claude-md-section">
2073
+ <h3>Suggested CLAUDE.md Additions</h3>
2074
+ <p style="font-size: 12px; color: #64748b; margin-bottom: 12px;">Just copy this into Claude Code to add it to your CLAUDE.md.</p>
2075
+ <div class="claude-md-actions">
2076
+ <button class="copy-all-btn" onclick="copyAllCheckedClaudeMd()">Copy All Checked</button>
2077
+ </div>
2078
+ ${suggestions.claude_md_additions
2079
+ .map(
2080
+ (add, i) => `
2081
+ <div class="claude-md-item">
2082
+ <input type="checkbox" id="cmd-${i}" class="cmd-checkbox" checked data-text="${escapeHtml(add.prompt_scaffold || add.where || 'Add to CLAUDE.md')}\\n\\n${escapeHtml(add.addition)}">
2083
+ <label for="cmd-${i}">
2084
+ <code class="cmd-code">${escapeHtml(add.addition)}</code>
2085
+ <button class="copy-btn" onclick="copyCmdItem(${i})">Copy</button>
2086
+ </label>
2087
+ <div class="cmd-why">${escapeHtml(add.why)}</div>
2088
+ </div>
2089
+ `,
2090
+ )
2091
+ .join('')}
2092
+ </div>
2093
+ `
2094
+ : ''
2095
+ }
2096
+ ${
2097
+ suggestions.features_to_try && suggestions.features_to_try.length > 0
2098
+ ? `
2099
+ <p style="font-size: 13px; color: #64748b; margin-bottom: 12px;">Just copy this into Claude Code and it'll set it up for you.</p>
2100
+ <div class="features-section">
2101
+ ${suggestions.features_to_try
2102
+ .map(
2103
+ feat => `
2104
+ <div class="feature-card">
2105
+ <div class="feature-title">${escapeHtml(feat.feature || '')}</div>
2106
+ <div class="feature-oneliner">${escapeHtml(feat.one_liner || '')}</div>
2107
+ <div class="feature-why"><strong>Why for you:</strong> ${escapeHtml(feat.why_for_you || '')}</div>
2108
+ ${
2109
+ feat.example_code
2110
+ ? `
2111
+ <div class="feature-examples">
2112
+ <div class="feature-example">
2113
+ <div class="example-code-row">
2114
+ <code class="example-code">${escapeHtml(feat.example_code)}</code>
2115
+ <button class="copy-btn" onclick="copyText(this)">Copy</button>
2116
+ </div>
2117
+ </div>
2118
+ </div>
2119
+ `
2120
+ : ''
2121
+ }
2122
+ </div>
2123
+ `,
2124
+ )
2125
+ .join('')}
2126
+ </div>
2127
+ `
2128
+ : ''
2129
+ }
2130
+ ${
2131
+ suggestions.usage_patterns && suggestions.usage_patterns.length > 0
2132
+ ? `
2133
+ <h2 id="section-patterns">New Ways to Use Claude Code</h2>
2134
+ <p style="font-size: 13px; color: #64748b; margin-bottom: 12px;">Just copy this into Claude Code and it'll walk you through it.</p>
2135
+ <div class="patterns-section">
2136
+ ${suggestions.usage_patterns
2137
+ .map(
2138
+ pat => `
2139
+ <div class="pattern-card">
2140
+ <div class="pattern-title">${escapeHtml(pat.title || '')}</div>
2141
+ <div class="pattern-summary">${escapeHtml(pat.suggestion || '')}</div>
2142
+ ${pat.detail ? `<div class="pattern-detail">${escapeHtml(pat.detail)}</div>` : ''}
2143
+ ${
2144
+ pat.copyable_prompt
2145
+ ? `
2146
+ <div class="copyable-prompt-section">
2147
+ <div class="prompt-label">Paste into Claude Code:</div>
2148
+ <div class="copyable-prompt-row">
2149
+ <code class="copyable-prompt">${escapeHtml(pat.copyable_prompt)}</code>
2150
+ <button class="copy-btn" onclick="copyText(this)">Copy</button>
2151
+ </div>
2152
+ </div>
2153
+ `
2154
+ : ''
2155
+ }
2156
+ </div>
2157
+ `,
2158
+ )
2159
+ .join('')}
2160
+ </div>
2161
+ `
2162
+ : ''
2163
+ }
2164
+ `
2165
+ : ''
2166
+
2167
+ // Build On the Horizon section
2168
+ const horizonData = insights.on_the_horizon
2169
+ const horizonHtml =
2170
+ horizonData?.opportunities && horizonData.opportunities.length > 0
2171
+ ? `
2172
+ <h2 id="section-horizon">On the Horizon</h2>
2173
+ ${horizonData.intro ? `<p class="section-intro">${escapeHtml(horizonData.intro)}</p>` : ''}
2174
+ <div class="horizon-section">
2175
+ ${horizonData.opportunities
2176
+ .map(
2177
+ opp => `
2178
+ <div class="horizon-card">
2179
+ <div class="horizon-title">${escapeHtml(opp.title || '')}</div>
2180
+ <div class="horizon-possible">${escapeHtml(opp.whats_possible || '')}</div>
2181
+ ${opp.how_to_try ? `<div class="horizon-tip"><strong>Getting started:</strong> ${escapeHtml(opp.how_to_try)}</div>` : ''}
2182
+ ${opp.copyable_prompt ? `<div class="pattern-prompt"><div class="prompt-label">Paste into Claude Code:</div><code>${escapeHtml(opp.copyable_prompt)}</code><button class="copy-btn" onclick="copyText(this)">Copy</button></div>` : ''}
2183
+ </div>
2184
+ `,
2185
+ )
2186
+ .join('')}
2187
+ </div>
2188
+ `
2189
+ : ''
2190
+
2191
+ // Build Team Feedback section (collapsible, ant-only)
2192
+ const ccImprovements =
2193
+ process.env.USER_TYPE === 'ant'
2194
+ ? insights.cc_team_improvements?.improvements || []
2195
+ : []
2196
+ const modelImprovements =
2197
+ process.env.USER_TYPE === 'ant'
2198
+ ? insights.model_behavior_improvements?.improvements || []
2199
+ : []
2200
+ const teamFeedbackHtml =
2201
+ ccImprovements.length > 0 || modelImprovements.length > 0
2202
+ ? `
2203
+ <h2 id="section-feedback" class="feedback-header">Closing the Loop: Feedback for Other Teams</h2>
2204
+ <p class="feedback-intro">Suggestions for the CC product and model teams based on your usage patterns. Click to expand.</p>
2205
+ ${
2206
+ ccImprovements.length > 0
2207
+ ? `
2208
+ <div class="collapsible-section">
2209
+ <div class="collapsible-header" onclick="toggleCollapsible(this)">
2210
+ <span class="collapsible-arrow">▶</span>
2211
+ <h3>Product Improvements for CC Team</h3>
2212
+ </div>
2213
+ <div class="collapsible-content">
2214
+ <div class="suggestions-section">
2215
+ ${ccImprovements
2216
+ .map(
2217
+ imp => `
2218
+ <div class="feedback-card team-card">
2219
+ <div class="feedback-title">${escapeHtml(imp.title || '')}</div>
2220
+ <div class="feedback-detail">${escapeHtml(imp.detail || '')}</div>
2221
+ ${imp.evidence ? `<div class="feedback-evidence"><em>Evidence:</em> ${escapeHtml(imp.evidence)}</div>` : ''}
2222
+ </div>
2223
+ `,
2224
+ )
2225
+ .join('')}
2226
+ </div>
2227
+ </div>
2228
+ </div>
2229
+ `
2230
+ : ''
2231
+ }
2232
+ ${
2233
+ modelImprovements.length > 0
2234
+ ? `
2235
+ <div class="collapsible-section">
2236
+ <div class="collapsible-header" onclick="toggleCollapsible(this)">
2237
+ <span class="collapsible-arrow">▶</span>
2238
+ <h3>Model Behavior Improvements</h3>
2239
+ </div>
2240
+ <div class="collapsible-content">
2241
+ <div class="suggestions-section">
2242
+ ${modelImprovements
2243
+ .map(
2244
+ imp => `
2245
+ <div class="feedback-card model-card">
2246
+ <div class="feedback-title">${escapeHtml(imp.title || '')}</div>
2247
+ <div class="feedback-detail">${escapeHtml(imp.detail || '')}</div>
2248
+ ${imp.evidence ? `<div class="feedback-evidence"><em>Evidence:</em> ${escapeHtml(imp.evidence)}</div>` : ''}
2249
+ </div>
2250
+ `,
2251
+ )
2252
+ .join('')}
2253
+ </div>
2254
+ </div>
2255
+ </div>
2256
+ `
2257
+ : ''
2258
+ }
2259
+ `
2260
+ : ''
2261
+
2262
+ // Build Fun Ending section
2263
+ const funEnding = insights.fun_ending
2264
+ const funEndingHtml = funEnding?.headline
2265
+ ? `
2266
+ <div class="fun-ending">
2267
+ <div class="fun-headline">"${escapeHtml(funEnding.headline)}"</div>
2268
+ ${funEnding.detail ? `<div class="fun-detail">${escapeHtml(funEnding.detail)}</div>` : ''}
2269
+ </div>
2270
+ `
2271
+ : ''
2272
+
2273
+ const css = `
2274
+ * { box-sizing: border-box; margin: 0; padding: 0; }
2275
+ body { font-family: 'Inter', -apple-system, BlinkMacSystemFont, sans-serif; background: #f8fafc; color: #334155; line-height: 1.65; padding: 48px 24px; }
2276
+ .container { max-width: 800px; margin: 0 auto; }
2277
+ h1 { font-size: 32px; font-weight: 700; color: #0f172a; margin-bottom: 8px; }
2278
+ h2 { font-size: 20px; font-weight: 600; color: #0f172a; margin-top: 48px; margin-bottom: 16px; }
2279
+ .subtitle { color: #64748b; font-size: 15px; margin-bottom: 32px; }
2280
+ .nav-toc { display: flex; flex-wrap: wrap; gap: 8px; margin: 24px 0 32px 0; padding: 16px; background: white; border-radius: 8px; border: 1px solid #e2e8f0; }
2281
+ .nav-toc a { font-size: 12px; color: #64748b; text-decoration: none; padding: 6px 12px; border-radius: 6px; background: #f1f5f9; transition: all 0.15s; }
2282
+ .nav-toc a:hover { background: #e2e8f0; color: #334155; }
2283
+ .stats-row { display: flex; gap: 24px; margin-bottom: 40px; padding: 20px 0; border-top: 1px solid #e2e8f0; border-bottom: 1px solid #e2e8f0; flex-wrap: wrap; }
2284
+ .stat { text-align: center; }
2285
+ .stat-value { font-size: 24px; font-weight: 700; color: #0f172a; }
2286
+ .stat-label { font-size: 11px; color: #64748b; text-transform: uppercase; }
2287
+ .at-a-glance { background: linear-gradient(135deg, #fef3c7 0%, #fde68a 100%); border: 1px solid #f59e0b; border-radius: 12px; padding: 20px 24px; margin-bottom: 32px; }
2288
+ .glance-title { font-size: 16px; font-weight: 700; color: #92400e; margin-bottom: 16px; }
2289
+ .glance-sections { display: flex; flex-direction: column; gap: 12px; }
2290
+ .glance-section { font-size: 14px; color: #78350f; line-height: 1.6; }
2291
+ .glance-section strong { color: #92400e; }
2292
+ .see-more { color: #b45309; text-decoration: none; font-size: 13px; white-space: nowrap; }
2293
+ .see-more:hover { text-decoration: underline; }
2294
+ .project-areas { display: flex; flex-direction: column; gap: 12px; margin-bottom: 32px; }
2295
+ .project-area { background: white; border: 1px solid #e2e8f0; border-radius: 8px; padding: 16px; }
2296
+ .area-header { display: flex; justify-content: space-between; align-items: center; margin-bottom: 8px; }
2297
+ .area-name { font-weight: 600; font-size: 15px; color: #0f172a; }
2298
+ .area-count { font-size: 12px; color: #64748b; background: #f1f5f9; padding: 2px 8px; border-radius: 4px; }
2299
+ .area-desc { font-size: 14px; color: #475569; line-height: 1.5; }
2300
+ .narrative { background: white; border: 1px solid #e2e8f0; border-radius: 8px; padding: 20px; margin-bottom: 24px; }
2301
+ .narrative p { margin-bottom: 12px; font-size: 14px; color: #475569; line-height: 1.7; }
2302
+ .key-insight { background: #f0fdf4; border: 1px solid #bbf7d0; border-radius: 8px; padding: 12px 16px; margin-top: 12px; font-size: 14px; color: #166534; }
2303
+ .section-intro { font-size: 14px; color: #64748b; margin-bottom: 16px; }
2304
+ .big-wins { display: flex; flex-direction: column; gap: 12px; margin-bottom: 24px; }
2305
+ .big-win { background: #f0fdf4; border: 1px solid #bbf7d0; border-radius: 8px; padding: 16px; }
2306
+ .big-win-title { font-weight: 600; font-size: 15px; color: #166534; margin-bottom: 8px; }
2307
+ .big-win-desc { font-size: 14px; color: #15803d; line-height: 1.5; }
2308
+ .friction-categories { display: flex; flex-direction: column; gap: 16px; margin-bottom: 24px; }
2309
+ .friction-category { background: #fef2f2; border: 1px solid #fca5a5; border-radius: 8px; padding: 16px; }
2310
+ .friction-title { font-weight: 600; font-size: 15px; color: #991b1b; margin-bottom: 6px; }
2311
+ .friction-desc { font-size: 13px; color: #7f1d1d; margin-bottom: 10px; }
2312
+ .friction-examples { margin: 0 0 0 20px; font-size: 13px; color: #334155; }
2313
+ .friction-examples li { margin-bottom: 4px; }
2314
+ .claude-md-section { background: #eff6ff; border: 1px solid #bfdbfe; border-radius: 8px; padding: 16px; margin-bottom: 20px; }
2315
+ .claude-md-section h3 { font-size: 14px; font-weight: 600; color: #1e40af; margin: 0 0 12px 0; }
2316
+ .claude-md-actions { margin-bottom: 12px; padding-bottom: 12px; border-bottom: 1px solid #dbeafe; }
2317
+ .copy-all-btn { background: #2563eb; color: white; border: none; border-radius: 4px; padding: 6px 12px; font-size: 12px; cursor: pointer; font-weight: 500; transition: all 0.2s; }
2318
+ .copy-all-btn:hover { background: #1d4ed8; }
2319
+ .copy-all-btn.copied { background: #16a34a; }
2320
+ .claude-md-item { display: flex; flex-wrap: wrap; align-items: flex-start; gap: 8px; padding: 10px 0; border-bottom: 1px solid #dbeafe; }
2321
+ .claude-md-item:last-child { border-bottom: none; }
2322
+ .cmd-checkbox { margin-top: 2px; }
2323
+ .cmd-code { background: white; padding: 8px 12px; border-radius: 4px; font-size: 12px; color: #1e40af; border: 1px solid #bfdbfe; font-family: monospace; display: block; white-space: pre-wrap; word-break: break-word; flex: 1; }
2324
+ .cmd-why { font-size: 12px; color: #64748b; width: 100%; padding-left: 24px; margin-top: 4px; }
2325
+ .features-section, .patterns-section { display: flex; flex-direction: column; gap: 12px; margin: 16px 0; }
2326
+ .feature-card { background: #f0fdf4; border: 1px solid #86efac; border-radius: 8px; padding: 16px; }
2327
+ .pattern-card { background: #f0f9ff; border: 1px solid #7dd3fc; border-radius: 8px; padding: 16px; }
2328
+ .feature-title, .pattern-title { font-weight: 600; font-size: 15px; color: #0f172a; margin-bottom: 6px; }
2329
+ .feature-oneliner { font-size: 14px; color: #475569; margin-bottom: 8px; }
2330
+ .pattern-summary { font-size: 14px; color: #475569; margin-bottom: 8px; }
2331
+ .feature-why, .pattern-detail { font-size: 13px; color: #334155; line-height: 1.5; }
2332
+ .feature-examples { margin-top: 12px; }
2333
+ .feature-example { padding: 8px 0; border-top: 1px solid #d1fae5; }
2334
+ .feature-example:first-child { border-top: none; }
2335
+ .example-desc { font-size: 13px; color: #334155; margin-bottom: 6px; }
2336
+ .example-code-row { display: flex; align-items: flex-start; gap: 8px; }
2337
+ .example-code { flex: 1; background: #f1f5f9; padding: 8px 12px; border-radius: 4px; font-family: monospace; font-size: 12px; color: #334155; overflow-x: auto; white-space: pre-wrap; }
2338
+ .copyable-prompt-section { margin-top: 12px; padding-top: 12px; border-top: 1px solid #e2e8f0; }
2339
+ .copyable-prompt-row { display: flex; align-items: flex-start; gap: 8px; }
2340
+ .copyable-prompt { flex: 1; background: #f8fafc; padding: 10px 12px; border-radius: 4px; font-family: monospace; font-size: 12px; color: #334155; border: 1px solid #e2e8f0; white-space: pre-wrap; line-height: 1.5; }
2341
+ .feature-code { background: #f8fafc; padding: 12px; border-radius: 6px; margin-top: 12px; border: 1px solid #e2e8f0; display: flex; align-items: flex-start; gap: 8px; }
2342
+ .feature-code code { flex: 1; font-family: monospace; font-size: 12px; color: #334155; white-space: pre-wrap; }
2343
+ .pattern-prompt { background: #f8fafc; padding: 12px; border-radius: 6px; margin-top: 12px; border: 1px solid #e2e8f0; }
2344
+ .pattern-prompt code { font-family: monospace; font-size: 12px; color: #334155; display: block; white-space: pre-wrap; margin-bottom: 8px; }
2345
+ .prompt-label { font-size: 11px; font-weight: 600; text-transform: uppercase; color: #64748b; margin-bottom: 6px; }
2346
+ .copy-btn { background: #e2e8f0; border: none; border-radius: 4px; padding: 4px 8px; font-size: 11px; cursor: pointer; color: #475569; flex-shrink: 0; }
2347
+ .copy-btn:hover { background: #cbd5e1; }
2348
+ .charts-row { display: grid; grid-template-columns: 1fr 1fr; gap: 24px; margin: 24px 0; }
2349
+ .chart-card { background: white; border: 1px solid #e2e8f0; border-radius: 8px; padding: 16px; }
2350
+ .chart-title { font-size: 12px; font-weight: 600; color: #64748b; text-transform: uppercase; margin-bottom: 12px; }
2351
+ .bar-row { display: flex; align-items: center; margin-bottom: 6px; }
2352
+ .bar-label { width: 100px; font-size: 11px; color: #475569; flex-shrink: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
2353
+ .bar-track { flex: 1; height: 6px; background: #f1f5f9; border-radius: 3px; margin: 0 8px; }
2354
+ .bar-fill { height: 100%; border-radius: 3px; }
2355
+ .bar-value { width: 28px; font-size: 11px; font-weight: 500; color: #64748b; text-align: right; }
2356
+ .empty { color: #94a3b8; font-size: 13px; }
2357
+ .horizon-section { display: flex; flex-direction: column; gap: 16px; }
2358
+ .horizon-card { background: linear-gradient(135deg, #faf5ff 0%, #f5f3ff 100%); border: 1px solid #c4b5fd; border-radius: 8px; padding: 16px; }
2359
+ .horizon-title { font-weight: 600; font-size: 15px; color: #5b21b6; margin-bottom: 8px; }
2360
+ .horizon-possible { font-size: 14px; color: #334155; margin-bottom: 10px; line-height: 1.5; }
2361
+ .horizon-tip { font-size: 13px; color: #6b21a8; background: rgba(255,255,255,0.6); padding: 8px 12px; border-radius: 4px; }
2362
+ .feedback-header { margin-top: 48px; color: #64748b; font-size: 16px; }
2363
+ .feedback-intro { font-size: 13px; color: #94a3b8; margin-bottom: 16px; }
2364
+ .feedback-section { margin-top: 16px; }
2365
+ .feedback-section h3 { font-size: 14px; font-weight: 600; color: #475569; margin-bottom: 12px; }
2366
+ .feedback-card { background: white; border: 1px solid #e2e8f0; border-radius: 8px; padding: 16px; margin-bottom: 12px; }
2367
+ .feedback-card.team-card { background: #eff6ff; border-color: #bfdbfe; }
2368
+ .feedback-card.model-card { background: #faf5ff; border-color: #e9d5ff; }
2369
+ .feedback-title { font-weight: 600; font-size: 14px; color: #0f172a; margin-bottom: 6px; }
2370
+ .feedback-detail { font-size: 13px; color: #475569; line-height: 1.5; }
2371
+ .feedback-evidence { font-size: 12px; color: #64748b; margin-top: 8px; }
2372
+ .fun-ending { background: linear-gradient(135deg, #fef3c7 0%, #fde68a 100%); border: 1px solid #fbbf24; border-radius: 12px; padding: 24px; margin-top: 40px; text-align: center; }
2373
+ .fun-headline { font-size: 18px; font-weight: 600; color: #78350f; margin-bottom: 8px; }
2374
+ .fun-detail { font-size: 14px; color: #92400e; }
2375
+ .collapsible-section { margin-top: 16px; }
2376
+ .collapsible-header { display: flex; align-items: center; gap: 8px; cursor: pointer; padding: 12px 0; border-bottom: 1px solid #e2e8f0; }
2377
+ .collapsible-header h3 { margin: 0; font-size: 14px; font-weight: 600; color: #475569; }
2378
+ .collapsible-arrow { font-size: 12px; color: #94a3b8; transition: transform 0.2s; }
2379
+ .collapsible-content { display: none; padding-top: 16px; }
2380
+ .collapsible-content.open { display: block; }
2381
+ .collapsible-header.open .collapsible-arrow { transform: rotate(90deg); }
2382
+ @media (max-width: 640px) { .charts-row { grid-template-columns: 1fr; } .stats-row { justify-content: center; } }
2383
+ `
2384
+
2385
+ const hourCountsJson = getHourCountsJson(data.message_hours)
2386
+
2387
+ const js = `
2388
+ function toggleCollapsible(header) {
2389
+ header.classList.toggle('open');
2390
+ const content = header.nextElementSibling;
2391
+ content.classList.toggle('open');
2392
+ }
2393
+ function copyText(btn) {
2394
+ const code = btn.previousElementSibling;
2395
+ navigator.clipboard.writeText(code.textContent).then(() => {
2396
+ btn.textContent = 'Copied!';
2397
+ setTimeout(() => { btn.textContent = 'Copy'; }, 2000);
2398
+ });
2399
+ }
2400
+ function copyCmdItem(idx) {
2401
+ const checkbox = document.getElementById('cmd-' + idx);
2402
+ if (checkbox) {
2403
+ const text = checkbox.dataset.text;
2404
+ navigator.clipboard.writeText(text).then(() => {
2405
+ const btn = checkbox.nextElementSibling.querySelector('.copy-btn');
2406
+ if (btn) { btn.textContent = 'Copied!'; setTimeout(() => { btn.textContent = 'Copy'; }, 2000); }
2407
+ });
2408
+ }
2409
+ }
2410
+ function copyAllCheckedClaudeMd() {
2411
+ const checkboxes = document.querySelectorAll('.cmd-checkbox:checked');
2412
+ const texts = [];
2413
+ checkboxes.forEach(cb => {
2414
+ if (cb.dataset.text) { texts.push(cb.dataset.text); }
2415
+ });
2416
+ const combined = texts.join('\\n');
2417
+ const btn = document.querySelector('.copy-all-btn');
2418
+ if (btn) {
2419
+ navigator.clipboard.writeText(combined).then(() => {
2420
+ btn.textContent = 'Copied ' + texts.length + ' items!';
2421
+ btn.classList.add('copied');
2422
+ setTimeout(() => { btn.textContent = 'Copy All Checked'; btn.classList.remove('copied'); }, 2000);
2423
+ });
2424
+ }
2425
+ }
2426
+ // Timezone selector for time of day chart (data is from our own analytics, not user input)
2427
+ const rawHourCounts = ${hourCountsJson};
2428
+ function updateHourHistogram(offsetFromPT) {
2429
+ const periods = [
2430
+ { label: "Morning (6-12)", range: [6,7,8,9,10,11] },
2431
+ { label: "Afternoon (12-18)", range: [12,13,14,15,16,17] },
2432
+ { label: "Evening (18-24)", range: [18,19,20,21,22,23] },
2433
+ { label: "Night (0-6)", range: [0,1,2,3,4,5] }
2434
+ ];
2435
+ const adjustedCounts = {};
2436
+ for (const [hour, count] of Object.entries(rawHourCounts)) {
2437
+ const newHour = (parseInt(hour) + offsetFromPT + 24) % 24;
2438
+ adjustedCounts[newHour] = (adjustedCounts[newHour] || 0) + count;
2439
+ }
2440
+ const periodCounts = periods.map(p => ({
2441
+ label: p.label,
2442
+ count: p.range.reduce((sum, h) => sum + (adjustedCounts[h] || 0), 0)
2443
+ }));
2444
+ const maxCount = Math.max(...periodCounts.map(p => p.count)) || 1;
2445
+ const container = document.getElementById('hour-histogram');
2446
+ container.textContent = '';
2447
+ periodCounts.forEach(p => {
2448
+ const row = document.createElement('div');
2449
+ row.className = 'bar-row';
2450
+ const label = document.createElement('div');
2451
+ label.className = 'bar-label';
2452
+ label.textContent = p.label;
2453
+ const track = document.createElement('div');
2454
+ track.className = 'bar-track';
2455
+ const fill = document.createElement('div');
2456
+ fill.className = 'bar-fill';
2457
+ fill.style.width = (p.count / maxCount) * 100 + '%';
2458
+ fill.style.background = '#8b5cf6';
2459
+ track.appendChild(fill);
2460
+ const value = document.createElement('div');
2461
+ value.className = 'bar-value';
2462
+ value.textContent = p.count;
2463
+ row.appendChild(label);
2464
+ row.appendChild(track);
2465
+ row.appendChild(value);
2466
+ container.appendChild(row);
2467
+ });
2468
+ }
2469
+ document.getElementById('timezone-select').addEventListener('change', function() {
2470
+ const customInput = document.getElementById('custom-offset');
2471
+ if (this.value === 'custom') {
2472
+ customInput.style.display = 'inline-block';
2473
+ customInput.focus();
2474
+ } else {
2475
+ customInput.style.display = 'none';
2476
+ updateHourHistogram(parseInt(this.value));
2477
+ }
2478
+ });
2479
+ document.getElementById('custom-offset').addEventListener('change', function() {
2480
+ const offset = parseInt(this.value) + 8;
2481
+ updateHourHistogram(offset);
2482
+ });
2483
+ `
2484
+
2485
+ return `<!DOCTYPE html>
2486
+ <html>
2487
+ <head>
2488
+ <meta charset="utf-8">
2489
+ <title>Claude Code Insights</title>
2490
+ <link href="https://fonts.googleapis.com/css2?family=Inter:wght@400;500;600;700&display=swap" rel="stylesheet">
2491
+ <style>${css}</style>
2492
+ </head>
2493
+ <body>
2494
+ <div class="container">
2495
+ <h1>Claude Code Insights</h1>
2496
+ <p class="subtitle">${data.total_messages.toLocaleString()} messages across ${data.total_sessions} sessions${data.total_sessions_scanned && data.total_sessions_scanned > data.total_sessions ? ` (${data.total_sessions_scanned.toLocaleString()} total)` : ''} | ${data.date_range.start} to ${data.date_range.end}</p>
2497
+
2498
+ ${atAGlanceHtml}
2499
+
2500
+ <nav class="nav-toc">
2501
+ <a href="#section-work">What You Work On</a>
2502
+ <a href="#section-usage">How You Use CC</a>
2503
+ <a href="#section-wins">Impressive Things</a>
2504
+ <a href="#section-friction">Where Things Go Wrong</a>
2505
+ <a href="#section-features">Features to Try</a>
2506
+ <a href="#section-patterns">New Usage Patterns</a>
2507
+ <a href="#section-horizon">On the Horizon</a>
2508
+ <a href="#section-feedback">Team Feedback</a>
2509
+ </nav>
2510
+
2511
+ <div class="stats-row">
2512
+ <div class="stat"><div class="stat-value">${data.total_messages.toLocaleString()}</div><div class="stat-label">Messages</div></div>
2513
+ <div class="stat"><div class="stat-value">+${data.total_lines_added.toLocaleString()}/-${data.total_lines_removed.toLocaleString()}</div><div class="stat-label">Lines</div></div>
2514
+ <div class="stat"><div class="stat-value">${data.total_files_modified}</div><div class="stat-label">Files</div></div>
2515
+ <div class="stat"><div class="stat-value">${data.days_active}</div><div class="stat-label">Days</div></div>
2516
+ <div class="stat"><div class="stat-value">${data.messages_per_day}</div><div class="stat-label">Msgs/Day</div></div>
2517
+ </div>
2518
+
2519
+ ${projectAreasHtml}
2520
+
2521
+ <div class="charts-row">
2522
+ <div class="chart-card">
2523
+ <div class="chart-title">What You Wanted</div>
2524
+ ${generateBarChart(data.goal_categories, '#2563eb')}
2525
+ </div>
2526
+ <div class="chart-card">
2527
+ <div class="chart-title">Top Tools Used</div>
2528
+ ${generateBarChart(data.tool_counts, '#0891b2')}
2529
+ </div>
2530
+ </div>
2531
+
2532
+ <div class="charts-row">
2533
+ <div class="chart-card">
2534
+ <div class="chart-title">Languages</div>
2535
+ ${generateBarChart(data.languages, '#10b981')}
2536
+ </div>
2537
+ <div class="chart-card">
2538
+ <div class="chart-title">Session Types</div>
2539
+ ${generateBarChart(data.session_types || {}, '#8b5cf6')}
2540
+ </div>
2541
+ </div>
2542
+
2543
+ ${interactionHtml}
2544
+
2545
+ <!-- Response Time Distribution -->
2546
+ <div class="chart-card" style="margin: 24px 0;">
2547
+ <div class="chart-title">User Response Time Distribution</div>
2548
+ ${generateResponseTimeHistogram(data.user_response_times)}
2549
+ <div style="font-size: 12px; color: #64748b; margin-top: 8px;">
2550
+ Median: ${data.median_response_time.toFixed(1)}s &bull; Average: ${data.avg_response_time.toFixed(1)}s
2551
+ </div>
2552
+ </div>
2553
+
2554
+ <!-- Multi-clauding Section (matching Python reference) -->
2555
+ <div class="chart-card" style="margin: 24px 0;">
2556
+ <div class="chart-title">Multi-Clauding (Parallel Sessions)</div>
2557
+ ${
2558
+ data.multi_clauding.overlap_events === 0
2559
+ ? `
2560
+ <p style="font-size: 14px; color: #64748b; padding: 8px 0;">
2561
+ No parallel session usage detected. You typically work with one Claude Code session at a time.
2562
+ </p>
2563
+ `
2564
+ : `
2565
+ <div style="display: flex; gap: 24px; margin: 12px 0;">
2566
+ <div style="text-align: center;">
2567
+ <div style="font-size: 24px; font-weight: 700; color: #7c3aed;">${data.multi_clauding.overlap_events}</div>
2568
+ <div style="font-size: 11px; color: #64748b; text-transform: uppercase;">Overlap Events</div>
2569
+ </div>
2570
+ <div style="text-align: center;">
2571
+ <div style="font-size: 24px; font-weight: 700; color: #7c3aed;">${data.multi_clauding.sessions_involved}</div>
2572
+ <div style="font-size: 11px; color: #64748b; text-transform: uppercase;">Sessions Involved</div>
2573
+ </div>
2574
+ <div style="text-align: center;">
2575
+ <div style="font-size: 24px; font-weight: 700; color: #7c3aed;">${data.total_messages > 0 ? Math.round((100 * data.multi_clauding.user_messages_during) / data.total_messages) : 0}%</div>
2576
+ <div style="font-size: 11px; color: #64748b; text-transform: uppercase;">Of Messages</div>
2577
+ </div>
2578
+ </div>
2579
+ <p style="font-size: 13px; color: #475569; margin-top: 12px;">
2580
+ You run multiple Claude Code sessions simultaneously. Multi-clauding is detected when sessions
2581
+ overlap in time, suggesting parallel workflows.
2582
+ </p>
2583
+ `
2584
+ }
2585
+ </div>
2586
+
2587
+ <!-- Time of Day & Tool Errors -->
2588
+ <div class="charts-row">
2589
+ <div class="chart-card">
2590
+ <div class="chart-title" style="display: flex; align-items: center; gap: 12px;">
2591
+ User Messages by Time of Day
2592
+ <select id="timezone-select" style="font-size: 12px; padding: 4px 8px; border-radius: 4px; border: 1px solid #e2e8f0;">
2593
+ <option value="0">PT (UTC-8)</option>
2594
+ <option value="3">ET (UTC-5)</option>
2595
+ <option value="8">London (UTC)</option>
2596
+ <option value="9">CET (UTC+1)</option>
2597
+ <option value="17">Tokyo (UTC+9)</option>
2598
+ <option value="custom">Custom offset...</option>
2599
+ </select>
2600
+ <input type="number" id="custom-offset" placeholder="UTC offset" style="display: none; width: 80px; font-size: 12px; padding: 4px; border-radius: 4px; border: 1px solid #e2e8f0;">
2601
+ </div>
2602
+ ${generateTimeOfDayChart(data.message_hours)}
2603
+ </div>
2604
+ <div class="chart-card">
2605
+ <div class="chart-title">Tool Errors Encountered</div>
2606
+ ${Object.keys(data.tool_error_categories).length > 0 ? generateBarChart(data.tool_error_categories, '#dc2626') : '<p class="empty">No tool errors</p>'}
2607
+ </div>
2608
+ </div>
2609
+
2610
+ ${whatWorksHtml}
2611
+
2612
+ <div class="charts-row">
2613
+ <div class="chart-card">
2614
+ <div class="chart-title">What Helped Most (Claude's Capabilities)</div>
2615
+ ${generateBarChart(data.success, '#16a34a')}
2616
+ </div>
2617
+ <div class="chart-card">
2618
+ <div class="chart-title">Outcomes</div>
2619
+ ${generateBarChart(data.outcomes, '#8b5cf6', 6, OUTCOME_ORDER)}
2620
+ </div>
2621
+ </div>
2622
+
2623
+ ${frictionHtml}
2624
+
2625
+ <div class="charts-row">
2626
+ <div class="chart-card">
2627
+ <div class="chart-title">Primary Friction Types</div>
2628
+ ${generateBarChart(data.friction, '#dc2626')}
2629
+ </div>
2630
+ <div class="chart-card">
2631
+ <div class="chart-title">Inferred Satisfaction (model-estimated)</div>
2632
+ ${generateBarChart(data.satisfaction, '#eab308', 6, SATISFACTION_ORDER)}
2633
+ </div>
2634
+ </div>
2635
+
2636
+ ${suggestionsHtml}
2637
+
2638
+ ${horizonHtml}
2639
+
2640
+ ${funEndingHtml}
2641
+
2642
+ ${teamFeedbackHtml}
2643
+ </div>
2644
+ <script>${js}</script>
2645
+ </body>
2646
+ </html>`
2647
+ }
2648
+
2649
+ // ============================================================================
2650
+ // Export Types & Functions
2651
+ // ============================================================================
2652
+
2653
+ /**
2654
+ * Structured export format for claudescope consumption
2655
+ */
2656
+ export type InsightsExport = {
2657
+ metadata: {
2658
+ username: string
2659
+ generated_at: string
2660
+ claude_code_version: string
2661
+ date_range: { start: string; end: string }
2662
+ session_count: number
2663
+ remote_hosts_collected?: string[]
2664
+ }
2665
+ aggregated_data: AggregatedData
2666
+ insights: InsightResults
2667
+ facets_summary?: {
2668
+ total: number
2669
+ goal_categories: Record<string, number>
2670
+ outcomes: Record<string, number>
2671
+ satisfaction: Record<string, number>
2672
+ friction: Record<string, number>
2673
+ }
2674
+ }
2675
+
2676
+ /**
2677
+ * Build export data from already-computed values.
2678
+ * Used by background upload to S3.
2679
+ */
2680
+ export function buildExportData(
2681
+ data: AggregatedData,
2682
+ insights: InsightResults,
2683
+ facets: Map<string, SessionFacets>,
2684
+ remoteStats?: { hosts: RemoteHostInfo[]; totalCopied: number },
2685
+ ): InsightsExport {
2686
+ const version = getAppVersion()
2687
+
2688
+ const remote_hosts_collected = remoteStats?.hosts
2689
+ .filter(h => h.sessionCount > 0)
2690
+ .map(h => h.name)
2691
+
2692
+ const facets_summary = {
2693
+ total: facets.size,
2694
+ goal_categories: {} as Record<string, number>,
2695
+ outcomes: {} as Record<string, number>,
2696
+ satisfaction: {} as Record<string, number>,
2697
+ friction: {} as Record<string, number>,
2698
+ }
2699
+ for (const f of facets.values()) {
2700
+ for (const [cat, count] of safeEntries(f.goal_categories)) {
2701
+ if (count > 0) {
2702
+ facets_summary.goal_categories[cat] =
2703
+ (facets_summary.goal_categories[cat] || 0) + count
2704
+ }
2705
+ }
2706
+ facets_summary.outcomes[f.outcome] =
2707
+ (facets_summary.outcomes[f.outcome] || 0) + 1
2708
+ for (const [level, count] of safeEntries(f.user_satisfaction_counts)) {
2709
+ if (count > 0) {
2710
+ facets_summary.satisfaction[level] =
2711
+ (facets_summary.satisfaction[level] || 0) + count
2712
+ }
2713
+ }
2714
+ for (const [type, count] of safeEntries(f.friction_counts)) {
2715
+ if (count > 0) {
2716
+ facets_summary.friction[type] =
2717
+ (facets_summary.friction[type] || 0) + count
2718
+ }
2719
+ }
2720
+ }
2721
+
2722
+ return {
2723
+ metadata: {
2724
+ username: process.env.SAFEUSER || process.env.USER || 'unknown',
2725
+ generated_at: new Date().toISOString(),
2726
+ claude_code_version: version,
2727
+ date_range: data.date_range,
2728
+ session_count: data.total_sessions,
2729
+ ...(remote_hosts_collected &&
2730
+ remote_hosts_collected.length > 0 && {
2731
+ remote_hosts_collected,
2732
+ }),
2733
+ },
2734
+ aggregated_data: data,
2735
+ insights,
2736
+ facets_summary,
2737
+ }
2738
+ }
2739
+
2740
+ // ============================================================================
2741
+ // Lite Session Scanning
2742
+ // ============================================================================
2743
+
2744
+ type LiteSessionInfo = {
2745
+ sessionId: string
2746
+ path: string
2747
+ mtime: number
2748
+ size: number
2749
+ }
2750
+
2751
+ /**
2752
+ * Scans all project directories using filesystem metadata only (no JSONL parsing).
2753
+ * Returns a list of session file info sorted by mtime descending.
2754
+ * Yields to the event loop between project directories to keep the UI responsive.
2755
+ */
2756
+ async function scanAllSessions(): Promise<LiteSessionInfo[]> {
2757
+ const projectsDir = getProjectsDir()
2758
+
2759
+ let dirents: Awaited<ReturnType<typeof readdir>>
2760
+ try {
2761
+ dirents = await readdir(projectsDir, { withFileTypes: true })
2762
+ } catch {
2763
+ return []
2764
+ }
2765
+
2766
+ const projectDirs = dirents
2767
+ .filter(dirent => dirent.isDirectory())
2768
+ .map(dirent => join(projectsDir, dirent.name))
2769
+
2770
+ const allSessions: LiteSessionInfo[] = []
2771
+
2772
+ for (let i = 0; i < projectDirs.length; i++) {
2773
+ const sessionFiles = await getSessionFilesWithMtime(projectDirs[i]!)
2774
+ for (const [sessionId, fileInfo] of sessionFiles) {
2775
+ allSessions.push({
2776
+ sessionId,
2777
+ path: fileInfo.path,
2778
+ mtime: fileInfo.mtime,
2779
+ size: fileInfo.size,
2780
+ })
2781
+ }
2782
+ // Yield to event loop every 10 project directories
2783
+ if (i % 10 === 9) {
2784
+ await new Promise<void>(resolve => setImmediate(resolve))
2785
+ }
2786
+ }
2787
+
2788
+ // Sort by mtime descending (most recent first)
2789
+ allSessions.sort((a, b) => b.mtime - a.mtime)
2790
+ return allSessions
2791
+ }
2792
+
2793
+ // ============================================================================
2794
+ // Main Function
2795
+ // ============================================================================
2796
+
2797
+ export async function generateUsageReport(options?: {
2798
+ collectRemote?: boolean
2799
+ }): Promise<{
2800
+ insights: InsightResults
2801
+ htmlPath: string
2802
+ data: AggregatedData
2803
+ remoteStats?: { hosts: RemoteHostInfo[]; totalCopied: number }
2804
+ facets: Map<string, SessionFacets>
2805
+ }> {
2806
+ let remoteStats: { hosts: RemoteHostInfo[]; totalCopied: number } | undefined
2807
+
2808
+ // Optionally collect data from remote hosts first (ant-only)
2809
+ if (process.env.USER_TYPE === 'ant' && options?.collectRemote) {
2810
+ const destDir = join(getClaudeConfigHomeDir(), 'projects')
2811
+ const { hosts, totalCopied } = await collectAllRemoteHostData(destDir)
2812
+ remoteStats = { hosts, totalCopied }
2813
+ }
2814
+
2815
+ // Phase 1: Lite scan — filesystem metadata only (no JSONL parsing)
2816
+ const allScannedSessions = await scanAllSessions()
2817
+ const totalSessionsScanned = allScannedSessions.length
2818
+
2819
+ // Phase 2: Load SessionMeta — use cache where available, parse only uncached
2820
+ // Read cached metas in parallel batches to avoid blocking the event loop
2821
+ const META_BATCH_SIZE = 50
2822
+ const MAX_SESSIONS_TO_LOAD = 200
2823
+ let allMetas: SessionMeta[] = []
2824
+ const uncachedSessions: LiteSessionInfo[] = []
2825
+
2826
+ for (let i = 0; i < allScannedSessions.length; i += META_BATCH_SIZE) {
2827
+ const batch = allScannedSessions.slice(i, i + META_BATCH_SIZE)
2828
+ const results = await Promise.all(
2829
+ batch.map(async sessionInfo => ({
2830
+ sessionInfo,
2831
+ cached: await loadCachedSessionMeta(sessionInfo.sessionId),
2832
+ })),
2833
+ )
2834
+ for (const { sessionInfo, cached } of results) {
2835
+ if (cached) {
2836
+ allMetas.push(cached)
2837
+ } else if (uncachedSessions.length < MAX_SESSIONS_TO_LOAD) {
2838
+ uncachedSessions.push(sessionInfo)
2839
+ }
2840
+ }
2841
+ }
2842
+
2843
+ // Load full message data only for uncached sessions and compute SessionMeta
2844
+ const logsForFacets = new Map<string, LogOption>()
2845
+
2846
+ // Filter out /insights meta-sessions (facet extraction API calls get logged as sessions)
2847
+ const isMetaSession = (log: LogOption): boolean => {
2848
+ for (const msg of log.messages.slice(0, 5)) {
2849
+ if (msg.type === 'user' && msg.message) {
2850
+ const content = msg.message.content
2851
+ if (typeof content === 'string') {
2852
+ if (
2853
+ content.includes('RESPOND WITH ONLY A VALID JSON OBJECT') ||
2854
+ content.includes('record_facets')
2855
+ ) {
2856
+ return true
2857
+ }
2858
+ }
2859
+ }
2860
+ }
2861
+ return false
2862
+ }
2863
+
2864
+ // Load uncached sessions in batches to yield to event loop between batches
2865
+ const LOAD_BATCH_SIZE = 10
2866
+ for (let i = 0; i < uncachedSessions.length; i += LOAD_BATCH_SIZE) {
2867
+ const batch = uncachedSessions.slice(i, i + LOAD_BATCH_SIZE)
2868
+ const batchResults = await Promise.all(
2869
+ batch.map(async sessionInfo => {
2870
+ try {
2871
+ return await loadAllLogsFromSessionFile(sessionInfo.path)
2872
+ } catch {
2873
+ return []
2874
+ }
2875
+ }),
2876
+ )
2877
+ // Collect metas synchronously, then save them in parallel (independent writes)
2878
+ const metasToSave: SessionMeta[] = []
2879
+ for (const logs of batchResults) {
2880
+ for (const log of logs) {
2881
+ if (isMetaSession(log) || !hasValidDates(log)) continue
2882
+ const meta = logToSessionMeta(log)
2883
+ allMetas.push(meta)
2884
+ metasToSave.push(meta)
2885
+ // Keep the log around for potential facet extraction
2886
+ logsForFacets.set(meta.session_id, log)
2887
+ }
2888
+ }
2889
+ await Promise.all(metasToSave.map(meta => saveSessionMeta(meta)))
2890
+ }
2891
+
2892
+ // Deduplicate session branches (keep the one with most user messages per session_id)
2893
+ // This prevents inflated totals when a session has multiple conversation branches
2894
+ const bestBySession = new Map<string, SessionMeta>()
2895
+ for (const meta of allMetas) {
2896
+ const existing = bestBySession.get(meta.session_id)
2897
+ if (
2898
+ !existing ||
2899
+ meta.user_message_count > existing.user_message_count ||
2900
+ (meta.user_message_count === existing.user_message_count &&
2901
+ meta.duration_minutes > existing.duration_minutes)
2902
+ ) {
2903
+ bestBySession.set(meta.session_id, meta)
2904
+ }
2905
+ }
2906
+ // Replace allMetas with deduplicated list and remove unused logs from logsForFacets
2907
+ const keptSessionIds = new Set(bestBySession.keys())
2908
+ allMetas = [...bestBySession.values()]
2909
+ for (const sessionId of logsForFacets.keys()) {
2910
+ if (!keptSessionIds.has(sessionId)) {
2911
+ logsForFacets.delete(sessionId)
2912
+ }
2913
+ }
2914
+
2915
+ // Sort all metas by start_time descending (most recent first)
2916
+ allMetas.sort((a, b) => b.start_time.localeCompare(a.start_time))
2917
+
2918
+ // Pre-filter obviously minimal sessions to save API calls
2919
+ // (matching Python's substantive filtering concept)
2920
+ const isSubstantiveSession = (meta: SessionMeta): boolean => {
2921
+ // Skip sessions with very few user messages
2922
+ if (meta.user_message_count < 2) return false
2923
+ // Skip very short sessions (< 1 minute)
2924
+ if (meta.duration_minutes < 1) return false
2925
+ return true
2926
+ }
2927
+
2928
+ const substantiveMetas = allMetas.filter(isSubstantiveSession)
2929
+
2930
+ // Phase 3: Facet extraction — only for sessions without cached facets
2931
+ const facets = new Map<string, SessionFacets>()
2932
+ const toExtract: Array<{ log: LogOption; sessionId: string }> = []
2933
+ const MAX_FACET_EXTRACTIONS = 50
2934
+
2935
+ // Load cached facets for all substantive sessions in parallel
2936
+ const cachedFacetResults = await Promise.all(
2937
+ substantiveMetas.map(async meta => ({
2938
+ sessionId: meta.session_id,
2939
+ cached: await loadCachedFacets(meta.session_id),
2940
+ })),
2941
+ )
2942
+ for (const { sessionId, cached } of cachedFacetResults) {
2943
+ if (cached) {
2944
+ facets.set(sessionId, cached)
2945
+ } else {
2946
+ const log = logsForFacets.get(sessionId)
2947
+ if (log && toExtract.length < MAX_FACET_EXTRACTIONS) {
2948
+ toExtract.push({ log, sessionId })
2949
+ }
2950
+ }
2951
+ }
2952
+
2953
+ // Extract facets for sessions that need them (50 concurrent)
2954
+ const CONCURRENCY = 50
2955
+ for (let i = 0; i < toExtract.length; i += CONCURRENCY) {
2956
+ const batch = toExtract.slice(i, i + CONCURRENCY)
2957
+ const results = await Promise.all(
2958
+ batch.map(async ({ log, sessionId }) => {
2959
+ const newFacets = await extractFacetsFromAPI(log, sessionId)
2960
+ return { sessionId, newFacets }
2961
+ }),
2962
+ )
2963
+ // Collect facets synchronously, save in parallel (independent writes)
2964
+ const facetsToSave: SessionFacets[] = []
2965
+ for (const { sessionId, newFacets } of results) {
2966
+ if (newFacets) {
2967
+ facets.set(sessionId, newFacets)
2968
+ facetsToSave.push(newFacets)
2969
+ }
2970
+ }
2971
+ await Promise.all(facetsToSave.map(f => saveFacets(f)))
2972
+ }
2973
+
2974
+ // Filter out warmup/minimal sessions (matching Python's is_minimal)
2975
+ // A session is minimal if warmup_minimal is the ONLY goal category
2976
+ const isMinimalSession = (sessionId: string): boolean => {
2977
+ const sessionFacets = facets.get(sessionId)
2978
+ if (!sessionFacets) return false
2979
+ const cats = sessionFacets.goal_categories
2980
+ const catKeys = safeKeys(cats).filter(k => (cats[k] ?? 0) > 0)
2981
+ return catKeys.length === 1 && catKeys[0] === 'warmup_minimal'
2982
+ }
2983
+
2984
+ const substantiveSessions = substantiveMetas.filter(
2985
+ s => !isMinimalSession(s.session_id),
2986
+ )
2987
+
2988
+ const substantiveFacets = new Map<string, SessionFacets>()
2989
+ for (const [sessionId, f] of facets) {
2990
+ if (!isMinimalSession(sessionId)) {
2991
+ substantiveFacets.set(sessionId, f)
2992
+ }
2993
+ }
2994
+
2995
+ const aggregated = aggregateData(substantiveSessions, substantiveFacets)
2996
+ aggregated.total_sessions_scanned = totalSessionsScanned
2997
+
2998
+ // Generate parallel insights from Claude (6 sections)
2999
+ const insights = await generateParallelInsights(aggregated, facets)
3000
+
3001
+ // Generate HTML report
3002
+ const htmlReport = generateHtmlReport(aggregated, insights)
3003
+
3004
+ // Save reports
3005
+ try {
3006
+ await mkdir(getDataDir(), { recursive: true })
3007
+ } catch {
3008
+ // Directory may already exist
3009
+ }
3010
+
3011
+ const htmlPath = join(getDataDir(), 'report.html')
3012
+ await writeFile(htmlPath, htmlReport, {
3013
+ encoding: 'utf-8',
3014
+ mode: 0o600,
3015
+ })
3016
+
3017
+ return {
3018
+ insights,
3019
+ htmlPath,
3020
+ data: aggregated,
3021
+ remoteStats,
3022
+ facets: substantiveFacets,
3023
+ }
3024
+ }
3025
+
3026
+ function safeEntries<V>(
3027
+ obj: Record<string, V> | undefined | null,
3028
+ ): [string, V][] {
3029
+ return obj ? Object.entries(obj) : []
3030
+ }
3031
+
3032
+ function safeKeys(obj: Record<string, unknown> | undefined | null): string[] {
3033
+ return obj ? Object.keys(obj) : []
3034
+ }
3035
+
3036
+ // ============================================================================
3037
+ // Command Definition
3038
+ // ============================================================================
3039
+
3040
+ const usageReport: Command = {
3041
+ type: 'prompt',
3042
+ name: 'insights',
3043
+ description: 'Generate a report analyzing your Claude Code sessions',
3044
+ contentLength: 0, // Dynamic content
3045
+ progressMessage: 'analyzing your sessions',
3046
+ source: 'builtin',
3047
+ async getPromptForCommand(args) {
3048
+ let collectRemote = false
3049
+ let remoteHosts: string[] = []
3050
+ let hasRemoteHosts = false
3051
+
3052
+ if (process.env.USER_TYPE === 'ant') {
3053
+ // Parse --homespaces flag
3054
+ collectRemote = args?.includes('--homespaces') ?? false
3055
+
3056
+ // Check for available remote hosts
3057
+ remoteHosts = await getRunningRemoteHosts()
3058
+ hasRemoteHosts = remoteHosts.length > 0
3059
+
3060
+ // Show collection message if collecting
3061
+ if (collectRemote && hasRemoteHosts) {
3062
+ // biome-ignore lint/suspicious/noConsole: intentional
3063
+ console.error(
3064
+ `Collecting sessions from ${remoteHosts.length} homespace(s): ${remoteHosts.join(', ')}...`,
3065
+ )
3066
+ }
3067
+ }
3068
+
3069
+ const { insights, htmlPath, data, remoteStats } = await generateUsageReport(
3070
+ { collectRemote },
3071
+ )
3072
+
3073
+ let reportUrl = `file://${htmlPath}`
3074
+ let uploadHint = ''
3075
+
3076
+ if (process.env.USER_TYPE === 'ant') {
3077
+ // Try to upload to S3
3078
+ const timestamp = new Date()
3079
+ .toISOString()
3080
+ .replace(/[-:]/g, '')
3081
+ .replace('T', '_')
3082
+ .slice(0, 15)
3083
+ const username = process.env.SAFEUSER || process.env.USER || 'unknown'
3084
+ const filename = `${username}_insights_${timestamp}.html`
3085
+ const s3Path = `s3://anthropic-serve/atamkin/cc-user-reports/${filename}`
3086
+ const s3Url = `https://s3-frontend.infra.ant.dev/anthropic-serve/atamkin/cc-user-reports/${filename}`
3087
+
3088
+ reportUrl = s3Url
3089
+ try {
3090
+ execFileSync('ff', ['cp', htmlPath, s3Path], {
3091
+ timeout: 60000,
3092
+ stdio: 'pipe', // Suppress output
3093
+ })
3094
+ } catch {
3095
+ // Upload failed - fall back to local file and show upload command
3096
+ reportUrl = `file://${htmlPath}`
3097
+ uploadHint = `\nAutomatic upload failed. Are you on the boron namespace? Try \`use-bo\` and ensure you've run \`sso\`.
3098
+ To share, run: ff cp ${htmlPath} ${s3Path}
3099
+ Then access at: ${s3Url}`
3100
+ }
3101
+ }
3102
+
3103
+ // Build header with stats
3104
+ const sessionLabel =
3105
+ data.total_sessions_scanned &&
3106
+ data.total_sessions_scanned > data.total_sessions
3107
+ ? `${data.total_sessions_scanned.toLocaleString()} sessions total · ${data.total_sessions} analyzed`
3108
+ : `${data.total_sessions} sessions`
3109
+ const stats = [
3110
+ sessionLabel,
3111
+ `${data.total_messages.toLocaleString()} messages`,
3112
+ `${Math.round(data.total_duration_hours)}h`,
3113
+ `${data.git_commits} commits`,
3114
+ ].join(' · ')
3115
+
3116
+ // Build remote host info (ant-only)
3117
+ let remoteInfo = ''
3118
+ if (process.env.USER_TYPE === 'ant') {
3119
+ if (remoteStats && remoteStats.totalCopied > 0) {
3120
+ const hsNames = remoteStats.hosts
3121
+ .filter(h => h.sessionCount > 0)
3122
+ .map(h => h.name)
3123
+ .join(', ')
3124
+ remoteInfo = `\n_Collected ${remoteStats.totalCopied} new sessions from: ${hsNames}_\n`
3125
+ } else if (!collectRemote && hasRemoteHosts) {
3126
+ // Suggest using --homespaces if they have remote hosts but didn't use the flag
3127
+ remoteInfo = `\n_Tip: Run \`/insights --homespaces\` to include sessions from your ${remoteHosts.length} running homespace(s)_\n`
3128
+ }
3129
+ }
3130
+
3131
+ // Build markdown summary from insights
3132
+ const atAGlance = insights.at_a_glance
3133
+ const summaryText = atAGlance
3134
+ ? `## At a Glance
3135
+
3136
+ ${atAGlance.whats_working ? `**What's working:** ${atAGlance.whats_working} See _Impressive Things You Did_.` : ''}
3137
+
3138
+ ${atAGlance.whats_hindering ? `**What's hindering you:** ${atAGlance.whats_hindering} See _Where Things Go Wrong_.` : ''}
3139
+
3140
+ ${atAGlance.quick_wins ? `**Quick wins to try:** ${atAGlance.quick_wins} See _Features to Try_.` : ''}
3141
+
3142
+ ${atAGlance.ambitious_workflows ? `**Ambitious workflows:** ${atAGlance.ambitious_workflows} See _On the Horizon_.` : ''}`
3143
+ : '_No insights generated_'
3144
+
3145
+ const header = `# Claude Code Insights
3146
+
3147
+ ${stats}
3148
+ ${data.date_range.start} to ${data.date_range.end}
3149
+ ${remoteInfo}
3150
+ `
3151
+
3152
+ const userSummary = `${header}${summaryText}
3153
+
3154
+ Your full shareable insights report is ready: ${reportUrl}${uploadHint}`
3155
+
3156
+ // Return prompt for Claude to respond to
3157
+ return [
3158
+ {
3159
+ type: 'text',
3160
+ text: `The user just ran /insights to generate a usage report analyzing their Claude Code sessions.
3161
+
3162
+ Here is the full insights data:
3163
+ ${jsonStringify(insights, null, 2)}
3164
+
3165
+ Report URL: ${reportUrl}
3166
+ HTML file: ${htmlPath}
3167
+ Facets directory: ${getFacetsDir()}
3168
+
3169
+ Here is what the user sees:
3170
+ ${userSummary}
3171
+
3172
+ Now output the following message exactly:
3173
+
3174
+ <message>
3175
+ Your shareable insights report is ready:
3176
+ ${reportUrl}${uploadHint}
3177
+
3178
+ Want to dig into any section or try one of the suggestions?
3179
+ </message>`,
3180
+ },
3181
+ ]
3182
+ },
3183
+ }
3184
+
3185
+ function isValidSessionFacets(obj: unknown): obj is SessionFacets {
3186
+ if (!obj || typeof obj !== 'object') return false
3187
+ const o = obj as Record<string, unknown>
3188
+ return (
3189
+ typeof o.underlying_goal === 'string' &&
3190
+ typeof o.outcome === 'string' &&
3191
+ typeof o.brief_summary === 'string' &&
3192
+ o.goal_categories !== null &&
3193
+ typeof o.goal_categories === 'object' &&
3194
+ o.user_satisfaction_counts !== null &&
3195
+ typeof o.user_satisfaction_counts === 'object' &&
3196
+ o.friction_counts !== null &&
3197
+ typeof o.friction_counts === 'object'
3198
+ )
3199
+ }
3200
+
3201
+ export default usageReport