better-codex 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 (405) hide show
  1. package/README.md +26 -0
  2. package/apps/backend/README.md +46 -0
  3. package/apps/backend/bun.lock +64 -0
  4. package/apps/backend/package.json +18 -0
  5. package/apps/backend/scripts/generate-protocol.ts +32 -0
  6. package/apps/backend/src/analytics/service.ts +219 -0
  7. package/apps/backend/src/analytics/store.ts +284 -0
  8. package/apps/backend/src/config.ts +98 -0
  9. package/apps/backend/src/core/app-server.ts +131 -0
  10. package/apps/backend/src/core/jsonrpc.ts +166 -0
  11. package/apps/backend/src/protocol/AbsolutePathBuf.ts +14 -0
  12. package/apps/backend/src/protocol/AddConversationListenerParams.ts +6 -0
  13. package/apps/backend/src/protocol/AddConversationSubscriptionResponse.ts +5 -0
  14. package/apps/backend/src/protocol/AgentMessageContent.ts +5 -0
  15. package/apps/backend/src/protocol/AgentMessageContentDeltaEvent.ts +5 -0
  16. package/apps/backend/src/protocol/AgentMessageDeltaEvent.ts +5 -0
  17. package/apps/backend/src/protocol/AgentMessageEvent.ts +5 -0
  18. package/apps/backend/src/protocol/AgentMessageItem.ts +6 -0
  19. package/apps/backend/src/protocol/AgentReasoningDeltaEvent.ts +5 -0
  20. package/apps/backend/src/protocol/AgentReasoningEvent.ts +5 -0
  21. package/apps/backend/src/protocol/AgentReasoningRawContentDeltaEvent.ts +5 -0
  22. package/apps/backend/src/protocol/AgentReasoningRawContentEvent.ts +5 -0
  23. package/apps/backend/src/protocol/AgentReasoningSectionBreakEvent.ts +5 -0
  24. package/apps/backend/src/protocol/Annotations.ts +9 -0
  25. package/apps/backend/src/protocol/ApplyPatchApprovalParams.ts +21 -0
  26. package/apps/backend/src/protocol/ApplyPatchApprovalRequestEvent.ts +23 -0
  27. package/apps/backend/src/protocol/ApplyPatchApprovalResponse.ts +6 -0
  28. package/apps/backend/src/protocol/ArchiveConversationParams.ts +6 -0
  29. package/apps/backend/src/protocol/ArchiveConversationResponse.ts +5 -0
  30. package/apps/backend/src/protocol/AskForApproval.ts +9 -0
  31. package/apps/backend/src/protocol/AudioContent.ts +9 -0
  32. package/apps/backend/src/protocol/AuthMode.ts +5 -0
  33. package/apps/backend/src/protocol/AuthStatusChangeNotification.ts +9 -0
  34. package/apps/backend/src/protocol/BackgroundEventEvent.ts +5 -0
  35. package/apps/backend/src/protocol/BlobResourceContents.ts +5 -0
  36. package/apps/backend/src/protocol/CallToolResult.ts +10 -0
  37. package/apps/backend/src/protocol/CancelLoginChatGptParams.ts +5 -0
  38. package/apps/backend/src/protocol/CancelLoginChatGptResponse.ts +5 -0
  39. package/apps/backend/src/protocol/ClientInfo.ts +5 -0
  40. package/apps/backend/src/protocol/ClientNotification.ts +5 -0
  41. package/apps/backend/src/protocol/ClientRequest.ts +46 -0
  42. package/apps/backend/src/protocol/CodexErrorInfo.ts +8 -0
  43. package/apps/backend/src/protocol/ContentBlock.ts +10 -0
  44. package/apps/backend/src/protocol/ContentItem.ts +5 -0
  45. package/apps/backend/src/protocol/ContextCompactedEvent.ts +5 -0
  46. package/apps/backend/src/protocol/ConversationGitInfo.ts +5 -0
  47. package/apps/backend/src/protocol/ConversationId.ts +5 -0
  48. package/apps/backend/src/protocol/ConversationSummary.ts +8 -0
  49. package/apps/backend/src/protocol/CreditsSnapshot.ts +5 -0
  50. package/apps/backend/src/protocol/CustomPrompt.ts +5 -0
  51. package/apps/backend/src/protocol/DeprecationNoticeEvent.ts +13 -0
  52. package/apps/backend/src/protocol/ElicitationRequestEvent.ts +6 -0
  53. package/apps/backend/src/protocol/EmbeddedResource.ts +13 -0
  54. package/apps/backend/src/protocol/EmbeddedResourceResource.ts +7 -0
  55. package/apps/backend/src/protocol/ErrorEvent.ts +6 -0
  56. package/apps/backend/src/protocol/EventMsg.ts +60 -0
  57. package/apps/backend/src/protocol/ExecApprovalRequestEvent.ts +32 -0
  58. package/apps/backend/src/protocol/ExecCommandApprovalParams.ts +12 -0
  59. package/apps/backend/src/protocol/ExecCommandApprovalResponse.ts +6 -0
  60. package/apps/backend/src/protocol/ExecCommandBeginEvent.ts +35 -0
  61. package/apps/backend/src/protocol/ExecCommandEndEvent.ts +59 -0
  62. package/apps/backend/src/protocol/ExecCommandOutputDeltaEvent.ts +18 -0
  63. package/apps/backend/src/protocol/ExecCommandSource.ts +5 -0
  64. package/apps/backend/src/protocol/ExecOneOffCommandParams.ts +6 -0
  65. package/apps/backend/src/protocol/ExecOneOffCommandResponse.ts +5 -0
  66. package/apps/backend/src/protocol/ExecOutputStream.ts +5 -0
  67. package/apps/backend/src/protocol/ExecPolicyAmendment.ts +12 -0
  68. package/apps/backend/src/protocol/ExitedReviewModeEvent.ts +6 -0
  69. package/apps/backend/src/protocol/FileChange.ts +5 -0
  70. package/apps/backend/src/protocol/ForcedLoginMethod.ts +5 -0
  71. package/apps/backend/src/protocol/FunctionCallOutputContentItem.ts +9 -0
  72. package/apps/backend/src/protocol/FunctionCallOutputPayload.ts +15 -0
  73. package/apps/backend/src/protocol/FuzzyFileSearchParams.ts +5 -0
  74. package/apps/backend/src/protocol/FuzzyFileSearchResponse.ts +6 -0
  75. package/apps/backend/src/protocol/FuzzyFileSearchResult.ts +8 -0
  76. package/apps/backend/src/protocol/GetAuthStatusParams.ts +5 -0
  77. package/apps/backend/src/protocol/GetAuthStatusResponse.ts +6 -0
  78. package/apps/backend/src/protocol/GetConversationSummaryParams.ts +6 -0
  79. package/apps/backend/src/protocol/GetConversationSummaryResponse.ts +6 -0
  80. package/apps/backend/src/protocol/GetHistoryEntryResponseEvent.ts +10 -0
  81. package/apps/backend/src/protocol/GetUserAgentResponse.ts +5 -0
  82. package/apps/backend/src/protocol/GetUserSavedConfigResponse.ts +6 -0
  83. package/apps/backend/src/protocol/GhostCommit.ts +8 -0
  84. package/apps/backend/src/protocol/GitDiffToRemoteParams.ts +5 -0
  85. package/apps/backend/src/protocol/GitDiffToRemoteResponse.ts +6 -0
  86. package/apps/backend/src/protocol/GitSha.ts +5 -0
  87. package/apps/backend/src/protocol/HistoryEntry.ts +5 -0
  88. package/apps/backend/src/protocol/ImageContent.ts +9 -0
  89. package/apps/backend/src/protocol/InitializeParams.ts +6 -0
  90. package/apps/backend/src/protocol/InitializeResponse.ts +5 -0
  91. package/apps/backend/src/protocol/InputItem.ts +5 -0
  92. package/apps/backend/src/protocol/InterruptConversationParams.ts +6 -0
  93. package/apps/backend/src/protocol/InterruptConversationResponse.ts +6 -0
  94. package/apps/backend/src/protocol/ItemCompletedEvent.ts +7 -0
  95. package/apps/backend/src/protocol/ItemStartedEvent.ts +7 -0
  96. package/apps/backend/src/protocol/ListConversationsParams.ts +5 -0
  97. package/apps/backend/src/protocol/ListConversationsResponse.ts +6 -0
  98. package/apps/backend/src/protocol/ListCustomPromptsResponseEvent.ts +9 -0
  99. package/apps/backend/src/protocol/ListSkillsResponseEvent.ts +9 -0
  100. package/apps/backend/src/protocol/LocalShellAction.ts +6 -0
  101. package/apps/backend/src/protocol/LocalShellExecAction.ts +5 -0
  102. package/apps/backend/src/protocol/LocalShellStatus.ts +5 -0
  103. package/apps/backend/src/protocol/LoginApiKeyParams.ts +5 -0
  104. package/apps/backend/src/protocol/LoginApiKeyResponse.ts +5 -0
  105. package/apps/backend/src/protocol/LoginChatGptCompleteNotification.ts +8 -0
  106. package/apps/backend/src/protocol/LoginChatGptResponse.ts +5 -0
  107. package/apps/backend/src/protocol/LogoutChatGptResponse.ts +5 -0
  108. package/apps/backend/src/protocol/McpAuthStatus.ts +5 -0
  109. package/apps/backend/src/protocol/McpInvocation.ts +18 -0
  110. package/apps/backend/src/protocol/McpListToolsResponseEvent.ts +25 -0
  111. package/apps/backend/src/protocol/McpStartupCompleteEvent.ts +6 -0
  112. package/apps/backend/src/protocol/McpStartupFailure.ts +5 -0
  113. package/apps/backend/src/protocol/McpStartupStatus.ts +5 -0
  114. package/apps/backend/src/protocol/McpStartupUpdateEvent.ts +14 -0
  115. package/apps/backend/src/protocol/McpToolCallBeginEvent.ts +10 -0
  116. package/apps/backend/src/protocol/McpToolCallEndEvent.ts +15 -0
  117. package/apps/backend/src/protocol/NetworkAccess.ts +8 -0
  118. package/apps/backend/src/protocol/NewConversationParams.ts +8 -0
  119. package/apps/backend/src/protocol/NewConversationResponse.ts +7 -0
  120. package/apps/backend/src/protocol/ParsedCommand.ts +12 -0
  121. package/apps/backend/src/protocol/PatchApplyBeginEvent.ts +23 -0
  122. package/apps/backend/src/protocol/PatchApplyEndEvent.ts +31 -0
  123. package/apps/backend/src/protocol/PlanItemArg.ts +6 -0
  124. package/apps/backend/src/protocol/PlanType.ts +5 -0
  125. package/apps/backend/src/protocol/Profile.ts +9 -0
  126. package/apps/backend/src/protocol/README.md +11 -0
  127. package/apps/backend/src/protocol/RateLimitSnapshot.ts +8 -0
  128. package/apps/backend/src/protocol/RateLimitWindow.ts +17 -0
  129. package/apps/backend/src/protocol/RawResponseItemEvent.ts +6 -0
  130. package/apps/backend/src/protocol/ReasoningContentDeltaEvent.ts +5 -0
  131. package/apps/backend/src/protocol/ReasoningEffort.ts +8 -0
  132. package/apps/backend/src/protocol/ReasoningItem.ts +5 -0
  133. package/apps/backend/src/protocol/ReasoningItemContent.ts +5 -0
  134. package/apps/backend/src/protocol/ReasoningItemReasoningSummary.ts +5 -0
  135. package/apps/backend/src/protocol/ReasoningRawContentDeltaEvent.ts +5 -0
  136. package/apps/backend/src/protocol/ReasoningSummary.ts +10 -0
  137. package/apps/backend/src/protocol/RemoveConversationListenerParams.ts +5 -0
  138. package/apps/backend/src/protocol/RemoveConversationSubscriptionResponse.ts +5 -0
  139. package/apps/backend/src/protocol/RequestId.ts +5 -0
  140. package/apps/backend/src/protocol/Resource.ts +9 -0
  141. package/apps/backend/src/protocol/ResourceLink.ts +11 -0
  142. package/apps/backend/src/protocol/ResourceTemplate.ts +9 -0
  143. package/apps/backend/src/protocol/ResponseItem.ts +17 -0
  144. package/apps/backend/src/protocol/ResumeConversationParams.ts +8 -0
  145. package/apps/backend/src/protocol/ResumeConversationResponse.ts +7 -0
  146. package/apps/backend/src/protocol/ReviewCodeLocation.ts +9 -0
  147. package/apps/backend/src/protocol/ReviewDecision.ts +9 -0
  148. package/apps/backend/src/protocol/ReviewFinding.ts +9 -0
  149. package/apps/backend/src/protocol/ReviewLineRange.ts +8 -0
  150. package/apps/backend/src/protocol/ReviewOutputEvent.ts +9 -0
  151. package/apps/backend/src/protocol/ReviewRequest.ts +9 -0
  152. package/apps/backend/src/protocol/ReviewTarget.ts +9 -0
  153. package/apps/backend/src/protocol/Role.ts +8 -0
  154. package/apps/backend/src/protocol/SandboxMode.ts +5 -0
  155. package/apps/backend/src/protocol/SandboxPolicy.ts +35 -0
  156. package/apps/backend/src/protocol/SandboxSettings.ts +6 -0
  157. package/apps/backend/src/protocol/SendUserMessageParams.ts +7 -0
  158. package/apps/backend/src/protocol/SendUserMessageResponse.ts +5 -0
  159. package/apps/backend/src/protocol/SendUserTurnParams.ts +11 -0
  160. package/apps/backend/src/protocol/SendUserTurnResponse.ts +5 -0
  161. package/apps/backend/src/protocol/ServerNotification.ts +36 -0
  162. package/apps/backend/src/protocol/ServerRequest.ts +13 -0
  163. package/apps/backend/src/protocol/SessionConfiguredEvent.ts +48 -0
  164. package/apps/backend/src/protocol/SessionConfiguredNotification.ts +8 -0
  165. package/apps/backend/src/protocol/SessionSource.ts +6 -0
  166. package/apps/backend/src/protocol/SetDefaultModelParams.ts +6 -0
  167. package/apps/backend/src/protocol/SetDefaultModelResponse.ts +5 -0
  168. package/apps/backend/src/protocol/SkillErrorInfo.ts +5 -0
  169. package/apps/backend/src/protocol/SkillMetadata.ts +6 -0
  170. package/apps/backend/src/protocol/SkillScope.ts +5 -0
  171. package/apps/backend/src/protocol/SkillsListEntry.ts +7 -0
  172. package/apps/backend/src/protocol/StepStatus.ts +5 -0
  173. package/apps/backend/src/protocol/StreamErrorEvent.ts +6 -0
  174. package/apps/backend/src/protocol/SubAgentSource.ts +5 -0
  175. package/apps/backend/src/protocol/TaskCompleteEvent.ts +5 -0
  176. package/apps/backend/src/protocol/TaskStartedEvent.ts +5 -0
  177. package/apps/backend/src/protocol/TerminalInteractionEvent.ts +17 -0
  178. package/apps/backend/src/protocol/TextContent.ts +9 -0
  179. package/apps/backend/src/protocol/TextResourceContents.ts +5 -0
  180. package/apps/backend/src/protocol/TokenCountEvent.ts +7 -0
  181. package/apps/backend/src/protocol/TokenUsage.ts +5 -0
  182. package/apps/backend/src/protocol/TokenUsageInfo.ts +6 -0
  183. package/apps/backend/src/protocol/Tool.ts +11 -0
  184. package/apps/backend/src/protocol/ToolAnnotations.ts +15 -0
  185. package/apps/backend/src/protocol/ToolInputSchema.ts +9 -0
  186. package/apps/backend/src/protocol/ToolOutputSchema.ts +10 -0
  187. package/apps/backend/src/protocol/Tools.ts +5 -0
  188. package/apps/backend/src/protocol/TurnAbortReason.ts +5 -0
  189. package/apps/backend/src/protocol/TurnAbortedEvent.ts +6 -0
  190. package/apps/backend/src/protocol/TurnDiffEvent.ts +5 -0
  191. package/apps/backend/src/protocol/TurnItem.ts +9 -0
  192. package/apps/backend/src/protocol/UndoCompletedEvent.ts +5 -0
  193. package/apps/backend/src/protocol/UndoStartedEvent.ts +5 -0
  194. package/apps/backend/src/protocol/UpdatePlanArgs.ts +6 -0
  195. package/apps/backend/src/protocol/UserInfoResponse.ts +5 -0
  196. package/apps/backend/src/protocol/UserInput.ts +8 -0
  197. package/apps/backend/src/protocol/UserMessageEvent.ts +5 -0
  198. package/apps/backend/src/protocol/UserMessageItem.ts +6 -0
  199. package/apps/backend/src/protocol/UserSavedConfig.ts +14 -0
  200. package/apps/backend/src/protocol/Verbosity.ts +9 -0
  201. package/apps/backend/src/protocol/ViewImageToolCallEvent.ts +13 -0
  202. package/apps/backend/src/protocol/WarningEvent.ts +5 -0
  203. package/apps/backend/src/protocol/WebSearchAction.ts +5 -0
  204. package/apps/backend/src/protocol/WebSearchBeginEvent.ts +5 -0
  205. package/apps/backend/src/protocol/WebSearchEndEvent.ts +5 -0
  206. package/apps/backend/src/protocol/WebSearchItem.ts +5 -0
  207. package/apps/backend/src/protocol/index.ts +198 -0
  208. package/apps/backend/src/protocol/serde_json/JsonValue.ts +5 -0
  209. package/apps/backend/src/protocol/v2/Account.ts +6 -0
  210. package/apps/backend/src/protocol/v2/AccountLoginCompletedNotification.ts +5 -0
  211. package/apps/backend/src/protocol/v2/AccountRateLimitsUpdatedNotification.ts +6 -0
  212. package/apps/backend/src/protocol/v2/AccountUpdatedNotification.ts +6 -0
  213. package/apps/backend/src/protocol/v2/AgentMessageDeltaNotification.ts +5 -0
  214. package/apps/backend/src/protocol/v2/ApprovalDecision.ts +6 -0
  215. package/apps/backend/src/protocol/v2/AskForApproval.ts +5 -0
  216. package/apps/backend/src/protocol/v2/CancelLoginAccountParams.ts +5 -0
  217. package/apps/backend/src/protocol/v2/CancelLoginAccountResponse.ts +6 -0
  218. package/apps/backend/src/protocol/v2/CancelLoginAccountStatus.ts +5 -0
  219. package/apps/backend/src/protocol/v2/CodexErrorInfo.ts +11 -0
  220. package/apps/backend/src/protocol/v2/CommandAction.ts +5 -0
  221. package/apps/backend/src/protocol/v2/CommandExecParams.ts +6 -0
  222. package/apps/backend/src/protocol/v2/CommandExecResponse.ts +5 -0
  223. package/apps/backend/src/protocol/v2/CommandExecutionOutputDeltaNotification.ts +5 -0
  224. package/apps/backend/src/protocol/v2/CommandExecutionRequestApprovalParams.ts +14 -0
  225. package/apps/backend/src/protocol/v2/CommandExecutionRequestApprovalResponse.ts +6 -0
  226. package/apps/backend/src/protocol/v2/CommandExecutionStatus.ts +5 -0
  227. package/apps/backend/src/protocol/v2/Config.ts +15 -0
  228. package/apps/backend/src/protocol/v2/ConfigBatchWriteParams.ts +10 -0
  229. package/apps/backend/src/protocol/v2/ConfigEdit.ts +7 -0
  230. package/apps/backend/src/protocol/v2/ConfigLayer.ts +7 -0
  231. package/apps/backend/src/protocol/v2/ConfigLayerMetadata.ts +6 -0
  232. package/apps/backend/src/protocol/v2/ConfigLayerSource.ts +6 -0
  233. package/apps/backend/src/protocol/v2/ConfigReadParams.ts +5 -0
  234. package/apps/backend/src/protocol/v2/ConfigReadResponse.ts +8 -0
  235. package/apps/backend/src/protocol/v2/ConfigValueWriteParams.ts +11 -0
  236. package/apps/backend/src/protocol/v2/ConfigWriteResponse.ts +12 -0
  237. package/apps/backend/src/protocol/v2/ContextCompactedNotification.ts +5 -0
  238. package/apps/backend/src/protocol/v2/CreditsSnapshot.ts +5 -0
  239. package/apps/backend/src/protocol/v2/DeprecationNoticeNotification.ts +13 -0
  240. package/apps/backend/src/protocol/v2/ErrorNotification.ts +6 -0
  241. package/apps/backend/src/protocol/v2/ExecPolicyAmendment.ts +5 -0
  242. package/apps/backend/src/protocol/v2/FeedbackUploadParams.ts +5 -0
  243. package/apps/backend/src/protocol/v2/FeedbackUploadResponse.ts +5 -0
  244. package/apps/backend/src/protocol/v2/FileChangeOutputDeltaNotification.ts +5 -0
  245. package/apps/backend/src/protocol/v2/FileChangeRequestApprovalParams.ts +14 -0
  246. package/apps/backend/src/protocol/v2/FileChangeRequestApprovalResponse.ts +6 -0
  247. package/apps/backend/src/protocol/v2/FileUpdateChange.ts +6 -0
  248. package/apps/backend/src/protocol/v2/GetAccountParams.ts +5 -0
  249. package/apps/backend/src/protocol/v2/GetAccountRateLimitsResponse.ts +6 -0
  250. package/apps/backend/src/protocol/v2/GetAccountResponse.ts +6 -0
  251. package/apps/backend/src/protocol/v2/GitInfo.ts +5 -0
  252. package/apps/backend/src/protocol/v2/ItemCompletedNotification.ts +6 -0
  253. package/apps/backend/src/protocol/v2/ItemStartedNotification.ts +6 -0
  254. package/apps/backend/src/protocol/v2/ListMcpServerStatusParams.ts +13 -0
  255. package/apps/backend/src/protocol/v2/ListMcpServerStatusResponse.ts +11 -0
  256. package/apps/backend/src/protocol/v2/LoginAccountParams.ts +5 -0
  257. package/apps/backend/src/protocol/v2/LoginAccountResponse.ts +9 -0
  258. package/apps/backend/src/protocol/v2/LogoutAccountResponse.ts +5 -0
  259. package/apps/backend/src/protocol/v2/McpAuthStatus.ts +5 -0
  260. package/apps/backend/src/protocol/v2/McpServerOauthLoginCompletedNotification.ts +5 -0
  261. package/apps/backend/src/protocol/v2/McpServerOauthLoginParams.ts +5 -0
  262. package/apps/backend/src/protocol/v2/McpServerOauthLoginResponse.ts +5 -0
  263. package/apps/backend/src/protocol/v2/McpServerStatus.ts +9 -0
  264. package/apps/backend/src/protocol/v2/McpToolCallError.ts +5 -0
  265. package/apps/backend/src/protocol/v2/McpToolCallProgressNotification.ts +5 -0
  266. package/apps/backend/src/protocol/v2/McpToolCallResult.ts +7 -0
  267. package/apps/backend/src/protocol/v2/McpToolCallStatus.ts +5 -0
  268. package/apps/backend/src/protocol/v2/MergeStrategy.ts +5 -0
  269. package/apps/backend/src/protocol/v2/Model.ts +7 -0
  270. package/apps/backend/src/protocol/v2/ModelListParams.ts +13 -0
  271. package/apps/backend/src/protocol/v2/ModelListResponse.ts +11 -0
  272. package/apps/backend/src/protocol/v2/NetworkAccess.ts +5 -0
  273. package/apps/backend/src/protocol/v2/OverriddenMetadata.ts +7 -0
  274. package/apps/backend/src/protocol/v2/PatchApplyStatus.ts +5 -0
  275. package/apps/backend/src/protocol/v2/PatchChangeKind.ts +5 -0
  276. package/apps/backend/src/protocol/v2/ProfileV2.ts +10 -0
  277. package/apps/backend/src/protocol/v2/RateLimitSnapshot.ts +8 -0
  278. package/apps/backend/src/protocol/v2/RateLimitWindow.ts +5 -0
  279. package/apps/backend/src/protocol/v2/RawResponseItemCompletedNotification.ts +6 -0
  280. package/apps/backend/src/protocol/v2/ReasoningEffortOption.ts +6 -0
  281. package/apps/backend/src/protocol/v2/ReasoningSummaryPartAddedNotification.ts +5 -0
  282. package/apps/backend/src/protocol/v2/ReasoningSummaryTextDeltaNotification.ts +5 -0
  283. package/apps/backend/src/protocol/v2/ReasoningTextDeltaNotification.ts +5 -0
  284. package/apps/backend/src/protocol/v2/ReviewDelivery.ts +5 -0
  285. package/apps/backend/src/protocol/v2/ReviewStartParams.ts +12 -0
  286. package/apps/backend/src/protocol/v2/ReviewStartResponse.ts +13 -0
  287. package/apps/backend/src/protocol/v2/ReviewTarget.ts +9 -0
  288. package/apps/backend/src/protocol/v2/SandboxMode.ts +5 -0
  289. package/apps/backend/src/protocol/v2/SandboxPolicy.ts +7 -0
  290. package/apps/backend/src/protocol/v2/SandboxWorkspaceWrite.ts +5 -0
  291. package/apps/backend/src/protocol/v2/SessionSource.ts +5 -0
  292. package/apps/backend/src/protocol/v2/SkillErrorInfo.ts +5 -0
  293. package/apps/backend/src/protocol/v2/SkillMetadata.ts +6 -0
  294. package/apps/backend/src/protocol/v2/SkillScope.ts +5 -0
  295. package/apps/backend/src/protocol/v2/SkillsListEntry.ts +7 -0
  296. package/apps/backend/src/protocol/v2/SkillsListParams.ts +13 -0
  297. package/apps/backend/src/protocol/v2/SkillsListResponse.ts +6 -0
  298. package/apps/backend/src/protocol/v2/TerminalInteractionNotification.ts +5 -0
  299. package/apps/backend/src/protocol/v2/Thread.ts +46 -0
  300. package/apps/backend/src/protocol/v2/ThreadArchiveParams.ts +5 -0
  301. package/apps/backend/src/protocol/v2/ThreadArchiveResponse.ts +5 -0
  302. package/apps/backend/src/protocol/v2/ThreadItem.ts +48 -0
  303. package/apps/backend/src/protocol/v2/ThreadListParams.ts +18 -0
  304. package/apps/backend/src/protocol/v2/ThreadListResponse.ts +11 -0
  305. package/apps/backend/src/protocol/v2/ThreadResumeParams.ts +35 -0
  306. package/apps/backend/src/protocol/v2/ThreadResumeResponse.ts +9 -0
  307. package/apps/backend/src/protocol/v2/ThreadStartParams.ts +15 -0
  308. package/apps/backend/src/protocol/v2/ThreadStartResponse.ts +9 -0
  309. package/apps/backend/src/protocol/v2/ThreadStartedNotification.ts +6 -0
  310. package/apps/backend/src/protocol/v2/ThreadTokenUsage.ts +6 -0
  311. package/apps/backend/src/protocol/v2/ThreadTokenUsageUpdatedNotification.ts +6 -0
  312. package/apps/backend/src/protocol/v2/TokenUsageBreakdown.ts +5 -0
  313. package/apps/backend/src/protocol/v2/ToolsV2.ts +5 -0
  314. package/apps/backend/src/protocol/v2/Turn.ts +18 -0
  315. package/apps/backend/src/protocol/v2/TurnCompletedNotification.ts +6 -0
  316. package/apps/backend/src/protocol/v2/TurnDiffUpdatedNotification.ts +9 -0
  317. package/apps/backend/src/protocol/v2/TurnError.ts +6 -0
  318. package/apps/backend/src/protocol/v2/TurnInterruptParams.ts +5 -0
  319. package/apps/backend/src/protocol/v2/TurnInterruptResponse.ts +5 -0
  320. package/apps/backend/src/protocol/v2/TurnPlanStep.ts +6 -0
  321. package/apps/backend/src/protocol/v2/TurnPlanStepStatus.ts +5 -0
  322. package/apps/backend/src/protocol/v2/TurnPlanUpdatedNotification.ts +6 -0
  323. package/apps/backend/src/protocol/v2/TurnStartParams.ts +34 -0
  324. package/apps/backend/src/protocol/v2/TurnStartResponse.ts +6 -0
  325. package/apps/backend/src/protocol/v2/TurnStartedNotification.ts +6 -0
  326. package/apps/backend/src/protocol/v2/TurnStatus.ts +5 -0
  327. package/apps/backend/src/protocol/v2/UserInput.ts +5 -0
  328. package/apps/backend/src/protocol/v2/WindowsWorldWritableWarningNotification.ts +5 -0
  329. package/apps/backend/src/protocol/v2/WriteStatus.ts +5 -0
  330. package/apps/backend/src/protocol/v2/index.ts +123 -0
  331. package/apps/backend/src/reviews/service.ts +27 -0
  332. package/apps/backend/src/reviews/store.ts +124 -0
  333. package/apps/backend/src/server.ts +531 -0
  334. package/apps/backend/src/services/profile-store.ts +114 -0
  335. package/apps/backend/src/services/supervisor.ts +102 -0
  336. package/apps/backend/src/thread-index/service.ts +75 -0
  337. package/apps/backend/src/thread-index/store.ts +195 -0
  338. package/apps/backend/src/ws/messages.ts +73 -0
  339. package/apps/backend/tsconfig.json +20 -0
  340. package/apps/web/README.md +24 -0
  341. package/apps/web/bun.lock +1062 -0
  342. package/apps/web/eslint.config.js +23 -0
  343. package/apps/web/index.html +16 -0
  344. package/apps/web/package.json +38 -0
  345. package/apps/web/src/app.tsx +83 -0
  346. package/apps/web/src/components/composer/slash-command-menu.tsx +47 -0
  347. package/apps/web/src/components/index.ts +2 -0
  348. package/apps/web/src/components/layout/account-usage-panel.tsx +167 -0
  349. package/apps/web/src/components/layout/analytics-view.tsx +296 -0
  350. package/apps/web/src/components/layout/index.ts +7 -0
  351. package/apps/web/src/components/layout/mobile-header.tsx +56 -0
  352. package/apps/web/src/components/layout/reviews-view.tsx +848 -0
  353. package/apps/web/src/components/layout/session-view.tsx +1374 -0
  354. package/apps/web/src/components/layout/settings-dialog.tsx +322 -0
  355. package/apps/web/src/components/layout/side-bar.tsx +417 -0
  356. package/apps/web/src/components/layout/thread-list.tsx +488 -0
  357. package/apps/web/src/components/layout/virtualized-message-list.tsx +748 -0
  358. package/apps/web/src/components/loading/startup-ascii.ts +652 -0
  359. package/apps/web/src/components/loading/startup-loader.tsx +37 -0
  360. package/apps/web/src/components/session-view/file-mention-menu.tsx +46 -0
  361. package/apps/web/src/components/session-view/session-auth-banner.tsx +61 -0
  362. package/apps/web/src/components/session-view/session-composer.tsx +328 -0
  363. package/apps/web/src/components/session-view/session-dialogs.tsx +280 -0
  364. package/apps/web/src/components/session-view/session-empty.tsx +47 -0
  365. package/apps/web/src/components/session-view/session-header.tsx +49 -0
  366. package/apps/web/src/components/ui/avatar.tsx +19 -0
  367. package/apps/web/src/components/ui/badge.tsx +21 -0
  368. package/apps/web/src/components/ui/button.tsx +47 -0
  369. package/apps/web/src/components/ui/collapsible-content.tsx +114 -0
  370. package/apps/web/src/components/ui/contribution-graph.tsx +182 -0
  371. package/apps/web/src/components/ui/dialog-box.tsx +203 -0
  372. package/apps/web/src/components/ui/icon-button.tsx +32 -0
  373. package/apps/web/src/components/ui/icons.tsx +187 -0
  374. package/apps/web/src/components/ui/index.tsx +15 -0
  375. package/apps/web/src/components/ui/input.tsx +43 -0
  376. package/apps/web/src/components/ui/markdown-stream.tsx +21 -0
  377. package/apps/web/src/components/ui/mobile-drawer.tsx +124 -0
  378. package/apps/web/src/components/ui/section-header.tsx +13 -0
  379. package/apps/web/src/components/ui/select.tsx +217 -0
  380. package/apps/web/src/components/ui/shimmer.tsx +138 -0
  381. package/apps/web/src/components/ui/status-dot.tsx +24 -0
  382. package/apps/web/src/config.ts +5 -0
  383. package/apps/web/src/hooks/index.ts +3 -0
  384. package/apps/web/src/hooks/use-analytics.ts +122 -0
  385. package/apps/web/src/hooks/use-hub-connection.ts +587 -0
  386. package/apps/web/src/hooks/use-mobile.ts +76 -0
  387. package/apps/web/src/hooks/use-thread-history.ts +210 -0
  388. package/apps/web/src/index.css +269 -0
  389. package/apps/web/src/main.tsx +10 -0
  390. package/apps/web/src/services/hub-client.ts +358 -0
  391. package/apps/web/src/store/index.ts +528 -0
  392. package/apps/web/src/types/index.ts +119 -0
  393. package/apps/web/src/utils/account-refresh.ts +168 -0
  394. package/apps/web/src/utils/approval-policy.ts +53 -0
  395. package/apps/web/src/utils/init-prompt.ts +41 -0
  396. package/apps/web/src/utils/item-format.ts +170 -0
  397. package/apps/web/src/utils/prompt-expander.ts +62 -0
  398. package/apps/web/src/utils/reasoning-summary.ts +48 -0
  399. package/apps/web/src/utils/slash-commands.ts +98 -0
  400. package/apps/web/tsconfig.app.json +28 -0
  401. package/apps/web/tsconfig.json +7 -0
  402. package/apps/web/tsconfig.node.json +26 -0
  403. package/apps/web/vite.config.ts +8 -0
  404. package/bin/better-codex.cjs +199 -0
  405. package/package.json +20 -0
@@ -0,0 +1,280 @@
1
+ import type { ApprovalPolicy, ReasoningEffort, ReasoningSummary } from '../../types'
2
+ import { AlertDialog, Button, CopyDialog, Dialog, PromptDialog, Select, type SelectOption } from '../ui'
3
+
4
+ interface SessionDialogsProps {
5
+ showModelDialog: boolean
6
+ onCloseModelDialog: () => void
7
+ modelOptions: SelectOption[]
8
+ pendingModelId: string
9
+ setPendingModelId: (value: string) => void
10
+ pendingEffortOptions: SelectOption[]
11
+ pendingEffort: ReasoningEffort | ''
12
+ setPendingEffort: (value: ReasoningEffort | '') => void
13
+ summaryOptions: SelectOption[]
14
+ pendingSummary: ReasoningSummary | ''
15
+ setPendingSummary: (value: ReasoningSummary | '') => void
16
+ pendingCwd: string
17
+ setPendingCwd: (value: string) => void
18
+ onApplyModel: () => void
19
+ showApprovalsDialog: boolean
20
+ onCloseApprovalsDialog: () => void
21
+ approvalOptions: Array<{ value: ApprovalPolicy; label: string; description: string }>
22
+ pendingApproval: ApprovalPolicy
23
+ setPendingApproval: (value: ApprovalPolicy) => void
24
+ onApplyApproval: () => void
25
+ showSkillsDialog: boolean
26
+ onCloseSkillsDialog: () => void
27
+ skillsLoading: boolean
28
+ skillsError: string | null
29
+ skillsList: Array<{ name: string; description: string; path: string }>
30
+ onSelectSkill: (name: string) => void
31
+ showResumeDialog: boolean
32
+ onCloseResumeDialog: () => void
33
+ resumeCandidates: Array<{ id: string; title: string; preview: string }>
34
+ onResumeThread: (threadId: string) => void
35
+ showFeedbackDialog: boolean
36
+ onCloseFeedbackDialog: () => void
37
+ feedbackCategory: string
38
+ setFeedbackCategory: (value: string) => void
39
+ feedbackReason: string
40
+ setFeedbackReason: (value: string) => void
41
+ feedbackIncludeLogs: boolean
42
+ setFeedbackIncludeLogs: (value: boolean) => void
43
+ onSendFeedback: () => void
44
+ showApiKeyPrompt: boolean
45
+ onCloseApiKeyPrompt: () => void
46
+ onApiKeySubmit: (value: string) => void
47
+ copyDialog: { open: boolean; url: string }
48
+ setCopyDialog: (state: { open: boolean; url: string }) => void
49
+ alertDialog: { open: boolean; title: string; message: string; variant: 'info' | 'warning' | 'error' }
50
+ setAlertDialog: (state: { open: boolean; title: string; message: string; variant: 'info' | 'warning' | 'error' }) => void
51
+ }
52
+
53
+ export const SessionDialogs = ({
54
+ showModelDialog,
55
+ onCloseModelDialog,
56
+ modelOptions,
57
+ pendingModelId,
58
+ setPendingModelId,
59
+ pendingEffortOptions,
60
+ pendingEffort,
61
+ setPendingEffort,
62
+ summaryOptions,
63
+ pendingSummary,
64
+ setPendingSummary,
65
+ pendingCwd,
66
+ setPendingCwd,
67
+ onApplyModel,
68
+ showApprovalsDialog,
69
+ onCloseApprovalsDialog,
70
+ approvalOptions,
71
+ pendingApproval,
72
+ setPendingApproval,
73
+ onApplyApproval,
74
+ showSkillsDialog,
75
+ onCloseSkillsDialog,
76
+ skillsLoading,
77
+ skillsError,
78
+ skillsList,
79
+ onSelectSkill,
80
+ showResumeDialog,
81
+ onCloseResumeDialog,
82
+ resumeCandidates,
83
+ onResumeThread,
84
+ showFeedbackDialog,
85
+ onCloseFeedbackDialog,
86
+ feedbackCategory,
87
+ setFeedbackCategory,
88
+ feedbackReason,
89
+ setFeedbackReason,
90
+ feedbackIncludeLogs,
91
+ setFeedbackIncludeLogs,
92
+ onSendFeedback,
93
+ showApiKeyPrompt,
94
+ onCloseApiKeyPrompt,
95
+ onApiKeySubmit,
96
+ copyDialog,
97
+ setCopyDialog,
98
+ alertDialog,
99
+ setAlertDialog,
100
+ }: SessionDialogsProps) => {
101
+ return (
102
+ <>
103
+ <Dialog open={showModelDialog} onClose={onCloseModelDialog} title="Model & Reasoning">
104
+ <div className="space-y-3">
105
+ <Select
106
+ options={modelOptions}
107
+ value={pendingModelId}
108
+ onChange={(value) => setPendingModelId(value)}
109
+ placeholder="Select model"
110
+ />
111
+ {pendingEffortOptions.length > 0 && (
112
+ <Select
113
+ options={pendingEffortOptions}
114
+ value={pendingEffort || ''}
115
+ onChange={(value) => setPendingEffort(value as ReasoningEffort)}
116
+ placeholder="Effort"
117
+ />
118
+ )}
119
+ <Select
120
+ options={summaryOptions}
121
+ value={pendingSummary || ''}
122
+ onChange={(value) => setPendingSummary(value as ReasoningSummary)}
123
+ placeholder="Summary"
124
+ />
125
+ <div className="space-y-1">
126
+ <div className="text-[10px] uppercase tracking-[0.2em] text-text-muted">
127
+ Working directory
128
+ </div>
129
+ <input
130
+ value={pendingCwd}
131
+ onChange={(event) => setPendingCwd(event.target.value)}
132
+ placeholder="/path/to/repo"
133
+ className="w-full bg-bg-tertiary border border-border rounded-lg px-3 py-2 text-xs text-text-primary placeholder:text-text-muted outline-none focus:border-text-muted transition-colors"
134
+ />
135
+ </div>
136
+ </div>
137
+ <div className="flex justify-end gap-2 mt-4">
138
+ <Button variant="ghost" size="sm" onClick={onCloseModelDialog}>
139
+ Cancel
140
+ </Button>
141
+ <Button variant="primary" size="sm" onClick={onApplyModel}>
142
+ Apply
143
+ </Button>
144
+ </div>
145
+ </Dialog>
146
+
147
+ <Dialog open={showApprovalsDialog} onClose={onCloseApprovalsDialog} title="Approvals">
148
+ <div className="space-y-2">
149
+ {approvalOptions.map((option) => (
150
+ <button
151
+ key={option.value}
152
+ type="button"
153
+ onClick={() => setPendingApproval(option.value)}
154
+ className={`w-full text-left px-3 py-2 rounded-lg border transition-colors ${
155
+ pendingApproval === option.value
156
+ ? 'border-text-muted bg-bg-elevated text-text-primary'
157
+ : 'border-border bg-bg-tertiary text-text-secondary hover:bg-bg-hover'
158
+ }`}
159
+ >
160
+ <div className="text-xs font-semibold">{option.label}</div>
161
+ <div className="text-[10px] text-text-muted mt-0.5">{option.description}</div>
162
+ </button>
163
+ ))}
164
+ </div>
165
+ <div className="flex justify-end gap-2 mt-4">
166
+ <Button variant="ghost" size="sm" onClick={onCloseApprovalsDialog}>
167
+ Cancel
168
+ </Button>
169
+ <Button variant="primary" size="sm" onClick={onApplyApproval}>
170
+ Apply
171
+ </Button>
172
+ </div>
173
+ </Dialog>
174
+
175
+ <Dialog open={showSkillsDialog} onClose={onCloseSkillsDialog} title="Skills">
176
+ <div className="space-y-2 max-h-[240px] overflow-y-auto">
177
+ {skillsLoading && <div className="text-xs text-text-muted">Loading skills...</div>}
178
+ {skillsError && <div className="text-xs text-accent-red">{skillsError}</div>}
179
+ {!skillsLoading && !skillsError && skillsList.length === 0 && (
180
+ <div className="text-xs text-text-muted">No skills found.</div>
181
+ )}
182
+ {!skillsLoading && !skillsError && skillsList.map((skill) => (
183
+ <button
184
+ key={skill.path}
185
+ type="button"
186
+ onClick={() => onSelectSkill(skill.name)}
187
+ className="w-full text-left px-3 py-2 rounded-lg border border-border bg-bg-tertiary text-text-secondary hover:bg-bg-hover transition-colors"
188
+ >
189
+ <div className="text-xs font-semibold text-text-primary">{skill.name}</div>
190
+ <div className="text-[10px] text-text-muted mt-0.5">{skill.description}</div>
191
+ </button>
192
+ ))}
193
+ </div>
194
+ </Dialog>
195
+
196
+ <Dialog open={showResumeDialog} onClose={onCloseResumeDialog} title="Resume Session">
197
+ <div className="space-y-2 max-h-[240px] overflow-y-auto">
198
+ {resumeCandidates.length === 0 && (
199
+ <div className="text-xs text-text-muted">No sessions available.</div>
200
+ )}
201
+ {resumeCandidates.map((thread) => (
202
+ <button
203
+ key={thread.id}
204
+ type="button"
205
+ onClick={() => onResumeThread(thread.id)}
206
+ className="w-full text-left px-3 py-2 rounded-lg border border-border bg-bg-tertiary text-text-secondary hover:bg-bg-hover transition-colors"
207
+ >
208
+ <div className="text-xs font-semibold text-text-primary truncate">{thread.title}</div>
209
+ <div className="text-[10px] text-text-muted mt-0.5 truncate">{thread.preview}</div>
210
+ </button>
211
+ ))}
212
+ </div>
213
+ </Dialog>
214
+
215
+ <Dialog open={showFeedbackDialog} onClose={onCloseFeedbackDialog} title="Send Feedback">
216
+ <div className="space-y-3">
217
+ <Select
218
+ options={[
219
+ { value: 'bug', label: 'Bug' },
220
+ { value: 'feature', label: 'Feature request' },
221
+ { value: 'ux', label: 'UX' },
222
+ { value: 'other', label: 'Other' },
223
+ ]}
224
+ value={feedbackCategory}
225
+ onChange={(value) => setFeedbackCategory(value)}
226
+ />
227
+ <textarea
228
+ value={feedbackReason}
229
+ onChange={(event) => setFeedbackReason(event.target.value)}
230
+ rows={3}
231
+ placeholder="Describe the issue or suggestion..."
232
+ className="w-full bg-bg-tertiary border border-border rounded-lg px-3 py-2 text-sm text-text-primary placeholder:text-text-muted outline-none focus:border-text-muted transition-colors"
233
+ />
234
+ <label className="flex items-center gap-2 text-xs text-text-muted">
235
+ <input
236
+ type="checkbox"
237
+ checked={feedbackIncludeLogs}
238
+ onChange={(event) => setFeedbackIncludeLogs(event.target.checked)}
239
+ className="accent-accent-green"
240
+ />
241
+ Include logs
242
+ </label>
243
+ </div>
244
+ <div className="flex justify-end gap-2 mt-4">
245
+ <Button variant="ghost" size="sm" onClick={onCloseFeedbackDialog}>
246
+ Cancel
247
+ </Button>
248
+ <Button variant="primary" size="sm" onClick={onSendFeedback}>
249
+ Send
250
+ </Button>
251
+ </div>
252
+ </Dialog>
253
+
254
+ <PromptDialog
255
+ open={showApiKeyPrompt}
256
+ onClose={onCloseApiKeyPrompt}
257
+ onSubmit={onApiKeySubmit}
258
+ title="Use API Key"
259
+ placeholder="Paste OpenAI API key..."
260
+ submitLabel="Connect"
261
+ />
262
+
263
+ <CopyDialog
264
+ open={copyDialog.open}
265
+ onClose={() => setCopyDialog({ open: false, url: '' })}
266
+ title="Sign In"
267
+ message="Open this URL in your browser to sign in to your OpenAI account:"
268
+ copyText={copyDialog.url}
269
+ />
270
+
271
+ <AlertDialog
272
+ open={alertDialog.open}
273
+ onClose={() => setAlertDialog({ ...alertDialog, open: false })}
274
+ title={alertDialog.title}
275
+ message={alertDialog.message}
276
+ variant={alertDialog.variant}
277
+ />
278
+ </>
279
+ )
280
+ }
@@ -0,0 +1,47 @@
1
+ import { useEffect, useState } from 'react'
2
+ import { Button, Icons } from '../ui'
3
+ import { STARTUP_FRAMES, STARTUP_FRAME_TICK_MS } from '../loading/startup-ascii'
4
+ import { useAppStore } from '../../store'
5
+
6
+ interface SessionEmptyProps {
7
+ onNewSession?: () => void
8
+ }
9
+
10
+ export const SessionEmpty = ({ onNewSession }: SessionEmptyProps) => {
11
+ const [frameIndex, setFrameIndex] = useState(0)
12
+ const { setMobileThreadListOpen } = useAppStore()
13
+
14
+ useEffect(() => {
15
+ const intervalId = window.setInterval(() => {
16
+ setFrameIndex((current) => (current + 1) % STARTUP_FRAMES.length)
17
+ }, STARTUP_FRAME_TICK_MS)
18
+ return () => window.clearInterval(intervalId)
19
+ }, [])
20
+
21
+ return (
22
+ <main className="flex-1 flex flex-col items-center justify-center px-4 md:px-6 bg-bg-primary">
23
+ <pre className="whitespace-pre font-mono text-[9px] sm:text-[11px] leading-tight text-text-secondary mb-5 overflow-hidden max-w-full">
24
+ {STARTUP_FRAMES[frameIndex]}
25
+ </pre>
26
+ <h2 className="text-base sm:text-lg font-semibold text-text-primary mb-2 text-center">Select a session</h2>
27
+ <p className="text-xs text-text-muted text-center max-w-xs mb-5 leading-relaxed">
28
+ Choose a session from the list to view the conversation, or start a new one to begin coding.
29
+ </p>
30
+ <div className="flex flex-col sm:flex-row gap-2">
31
+ <Button
32
+ variant="ghost"
33
+ size="lg"
34
+ onClick={() => setMobileThreadListOpen(true)}
35
+ className="md:hidden"
36
+ >
37
+ <Icons.List className="w-4 h-4" />
38
+ View Sessions
39
+ </Button>
40
+ <Button variant="primary" size="lg" onClick={onNewSession}>
41
+ <Icons.Plus className="w-4 h-4" />
42
+ New Session
43
+ </Button>
44
+ </div>
45
+ </main>
46
+ )
47
+ }
@@ -0,0 +1,49 @@
1
+ import { IconButton, Icons } from '../ui'
2
+
3
+ interface SessionHeaderProps {
4
+ title: string
5
+ accountName?: string
6
+ model?: string
7
+ status?: string
8
+ canInteract: boolean
9
+ onArchive: () => void
10
+ }
11
+
12
+ export const SessionHeader = ({
13
+ title,
14
+ accountName,
15
+ model,
16
+ status,
17
+ canInteract,
18
+ onArchive,
19
+ }: SessionHeaderProps) => {
20
+ const isActive = status === 'active'
21
+
22
+ return (
23
+ <header className="hidden md:flex px-4 py-3 border-b border-border items-center justify-between shrink-0 gap-4">
24
+ <div className="min-w-0 flex-1 overflow-hidden">
25
+ <h2 className="text-sm font-semibold text-text-primary truncate">{title}</h2>
26
+ <div className="flex items-center gap-2 mt-0.5 text-[10px] text-text-muted">
27
+ <span className="truncate max-w-[100px]">{accountName || 'Unknown account'}</span>
28
+ <span>·</span>
29
+ <span>{model || 'unknown'}</span>
30
+ <span>·</span>
31
+ <span className={`flex items-center gap-1 ${isActive ? 'text-accent-green' : ''}`}>
32
+ {isActive && <span className="w-1.5 h-1.5 rounded-full bg-accent-green animate-pulse" />}
33
+ {status || 'idle'}
34
+ </span>
35
+ </div>
36
+ </div>
37
+ <div className="flex items-center gap-2 shrink-0">
38
+ <IconButton icon={<Icons.Copy className="w-4 h-4 text-text-muted" />} size="sm" />
39
+ <IconButton
40
+ icon={<Icons.Archive className="w-4 h-4 text-text-muted" />}
41
+ size="sm"
42
+ disabled={!canInteract}
43
+ onClick={onArchive}
44
+ />
45
+ <IconButton icon={<Icons.MoreVertical className="w-4 h-4 text-text-muted" />} size="sm" />
46
+ </div>
47
+ </header>
48
+ )
49
+ }
@@ -0,0 +1,19 @@
1
+ interface AvatarProps {
2
+ name: string
3
+ size?: 'sm' | 'md' | 'lg'
4
+ className?: string
5
+ }
6
+
7
+ export function Avatar({ name, size = 'md', className = '' }: AvatarProps) {
8
+ const sizeStyles = {
9
+ sm: 'w-6 h-6 text-xs',
10
+ md: 'w-8 h-8 text-sm',
11
+ lg: 'w-10 h-10 text-base',
12
+ }
13
+
14
+ return (
15
+ <div className={`rounded-full bg-bg-tertiary flex items-center justify-center font-medium text-text-primary ${sizeStyles[size]} ${className}`}>
16
+ {name[0].toUpperCase()}
17
+ </div>
18
+ )
19
+ }
@@ -0,0 +1,21 @@
1
+ import type { ReactNode } from 'react'
2
+
3
+ interface BadgeProps {
4
+ children: ReactNode
5
+ variant?: 'default' | 'success' | 'warning' | 'error'
6
+ }
7
+
8
+ export function Badge({ children, variant = 'default' }: BadgeProps) {
9
+ const variantStyles = {
10
+ default: 'bg-bg-elevated text-text-secondary border-border',
11
+ success: 'bg-accent-green/15 text-accent-green border-accent-green/20',
12
+ warning: 'bg-yellow-500/15 text-yellow-500 border-yellow-500/20',
13
+ error: 'bg-accent-red/15 text-accent-red border-accent-red/20',
14
+ }
15
+
16
+ return (
17
+ <span className={`inline-flex items-center px-2 py-0.5 rounded text-xs font-medium border ${variantStyles[variant]}`}>
18
+ {children}
19
+ </span>
20
+ )
21
+ }
@@ -0,0 +1,47 @@
1
+ import type { ReactNode } from 'react'
2
+
3
+ interface ButtonProps {
4
+ children: ReactNode
5
+ onClick?: () => void
6
+ variant?: 'primary' | 'secondary' | 'ghost' | 'danger'
7
+ size?: 'sm' | 'md' | 'lg'
8
+ className?: string
9
+ disabled?: boolean
10
+ fullWidth?: boolean
11
+ }
12
+
13
+ export function Button({
14
+ children,
15
+ onClick,
16
+ variant = 'secondary',
17
+ size = 'md',
18
+ className = '',
19
+ disabled = false,
20
+ fullWidth = false,
21
+ }: ButtonProps) {
22
+ const baseStyles =
23
+ 'inline-flex items-center justify-center gap-2 font-medium transition-colors rounded-lg disabled:opacity-50 disabled:cursor-not-allowed'
24
+
25
+ const variantStyles = {
26
+ primary: 'bg-accent-green text-black hover:bg-accent-green/90',
27
+ secondary: 'bg-bg-elevated border border-border text-text-secondary hover:bg-bg-hover',
28
+ ghost: 'text-text-muted hover:text-text-secondary hover:bg-bg-hover',
29
+ danger: 'bg-accent-red text-white hover:bg-accent-red/90',
30
+ }
31
+
32
+ const sizeStyles = {
33
+ sm: 'px-2.5 py-1 text-xs',
34
+ md: 'px-3 py-1.5 text-sm',
35
+ lg: 'px-4 py-2 text-sm',
36
+ }
37
+
38
+ return (
39
+ <button
40
+ onClick={onClick}
41
+ disabled={disabled}
42
+ className={`${baseStyles} ${variantStyles[variant]} ${sizeStyles[size]} ${fullWidth ? 'w-full' : ''} ${className}`}
43
+ >
44
+ {children}
45
+ </button>
46
+ )
47
+ }
@@ -0,0 +1,114 @@
1
+ import { useState, useRef, useEffect } from 'react'
2
+ import { Icons } from './icons'
3
+
4
+ interface CollapsibleContentProps {
5
+ children: React.ReactNode
6
+ maxHeight?: number
7
+ className?: string
8
+ showLineCount?: boolean
9
+ }
10
+
11
+ export function CollapsibleContent({
12
+ children,
13
+ maxHeight = 200,
14
+ className = '',
15
+ showLineCount = true,
16
+ }: CollapsibleContentProps) {
17
+ const [isExpanded, setIsExpanded] = useState(false)
18
+ const [needsCollapse, setNeedsCollapse] = useState(false)
19
+ const [lineCount, setLineCount] = useState(0)
20
+ const contentRef = useRef<HTMLDivElement>(null)
21
+
22
+ useEffect(() => {
23
+ if (contentRef.current) {
24
+ const height = contentRef.current.scrollHeight
25
+ setNeedsCollapse(height > maxHeight)
26
+
27
+ const text = contentRef.current.textContent || ''
28
+ const lines = text.split('\n').length
29
+ setLineCount(lines)
30
+ }
31
+ }, [children, maxHeight])
32
+
33
+ if (!needsCollapse) {
34
+ return <div className={className}>{children}</div>
35
+ }
36
+
37
+ return (
38
+ <div className={className}>
39
+ <div
40
+ ref={contentRef}
41
+ className="relative overflow-hidden transition-[max-height] duration-300 ease-in-out"
42
+ style={{ maxHeight: isExpanded ? 'none' : maxHeight }}
43
+ >
44
+ {children}
45
+ {!isExpanded && (
46
+ <div className="absolute bottom-0 left-0 right-0 h-12 bg-gradient-to-t from-bg-tertiary to-transparent pointer-events-none" />
47
+ )}
48
+ </div>
49
+ <button
50
+ onClick={() => setIsExpanded(!isExpanded)}
51
+ className="flex items-center gap-1.5 mt-2 text-xs text-text-muted hover:text-text-primary transition-colors group"
52
+ >
53
+ <Icons.ChevronDown
54
+ className={`w-3 h-3 transition-transform duration-200 ${isExpanded ? 'rotate-180' : ''}`}
55
+ />
56
+ <span>
57
+ {isExpanded ? 'Collapse' : 'Expand'}
58
+ {showLineCount && lineCount > 0 && (
59
+ <span className="text-text-muted/60 ml-1">({lineCount} lines)</span>
60
+ )}
61
+ </span>
62
+ </button>
63
+ </div>
64
+ )
65
+ }
66
+
67
+ interface CollapsibleCodeBlockProps {
68
+ code: string
69
+ language?: string
70
+ maxLines?: number
71
+ className?: string
72
+ }
73
+
74
+ export function CollapsibleCodeBlock({
75
+ code,
76
+ language,
77
+ maxLines = 15,
78
+ className = '',
79
+ }: CollapsibleCodeBlockProps) {
80
+ const [isExpanded, setIsExpanded] = useState(false)
81
+ const lines = code.split('\n')
82
+ const needsCollapse = lines.length > maxLines
83
+ const visibleCode = needsCollapse && !isExpanded
84
+ ? lines.slice(0, maxLines).join('\n')
85
+ : code
86
+
87
+ return (
88
+ <div className={className}>
89
+ <div className="relative">
90
+ <pre className="text-xs font-mono whitespace-pre-wrap leading-relaxed break-words overflow-wrap-anywhere">
91
+ <code className={language ? `language-${language}` : ''}>
92
+ {visibleCode}
93
+ </code>
94
+ </pre>
95
+ {needsCollapse && !isExpanded && (
96
+ <div className="absolute bottom-0 left-0 right-0 h-8 bg-gradient-to-t from-bg-primary to-transparent pointer-events-none" />
97
+ )}
98
+ </div>
99
+ {needsCollapse && (
100
+ <button
101
+ onClick={() => setIsExpanded(!isExpanded)}
102
+ className="flex items-center gap-1.5 mt-2 text-xs text-text-muted hover:text-text-primary transition-colors"
103
+ >
104
+ <Icons.ChevronDown
105
+ className={`w-3 h-3 transition-transform duration-200 ${isExpanded ? 'rotate-180' : ''}`}
106
+ />
107
+ <span>
108
+ {isExpanded ? 'Show less' : `Show ${lines.length - maxLines} more lines`}
109
+ </span>
110
+ </button>
111
+ )}
112
+ </div>
113
+ )
114
+ }