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,46 @@
1
+ import { Icons } from '../ui'
2
+ import type { FileMention } from '../../types'
3
+
4
+ interface FileMentionMenuProps {
5
+ matches: FileMention[]
6
+ activeIndex: number
7
+ query: string
8
+ onSelect: (mention: FileMention) => void
9
+ onHover: (index: number) => void
10
+ }
11
+
12
+ export function FileMentionMenu({
13
+ matches,
14
+ activeIndex,
15
+ query,
16
+ onSelect,
17
+ onHover,
18
+ }: FileMentionMenuProps) {
19
+ if (matches.length === 0) return null
20
+
21
+ return (
22
+ <div className="absolute bottom-full left-0 right-0 mb-1 bg-bg-elevated border border-border rounded-lg shadow-lg max-h-[200px] overflow-y-auto z-20">
23
+ <div className="px-3 py-1.5 text-[10px] text-text-muted border-b border-border">
24
+ Files matching "{query}"
25
+ </div>
26
+ {matches.map((match, index) => (
27
+ <button
28
+ key={match.path}
29
+ onClick={() => onSelect(match)}
30
+ onMouseEnter={() => onHover(index)}
31
+ className={`w-full text-left px-3 py-2 flex items-center gap-2 transition-colors ${
32
+ index === activeIndex
33
+ ? 'bg-bg-hover'
34
+ : 'hover:bg-bg-hover/50'
35
+ }`}
36
+ >
37
+ <Icons.File className="w-3.5 h-3.5 text-accent-blue shrink-0" />
38
+ <div className="min-w-0 flex-1">
39
+ <div className="text-xs text-text-primary truncate">{match.name}</div>
40
+ <div className="text-[10px] text-text-muted truncate">{match.path}</div>
41
+ </div>
42
+ </button>
43
+ ))}
44
+ </div>
45
+ )
46
+ }
@@ -0,0 +1,61 @@
1
+ import { Button, Icons } from '../ui'
2
+
3
+ interface SessionAuthBannerProps {
4
+ visible: boolean
5
+ pending: boolean
6
+ onChatgpt: () => void
7
+ onApiKey: () => void
8
+ onRefresh?: () => void
9
+ onCancel?: () => void
10
+ }
11
+
12
+ export const SessionAuthBanner = ({
13
+ visible,
14
+ pending,
15
+ onChatgpt,
16
+ onApiKey,
17
+ onRefresh,
18
+ onCancel,
19
+ }: SessionAuthBannerProps) => {
20
+ if (!visible) {
21
+ return null
22
+ }
23
+
24
+ return (
25
+ <div className="px-4 py-3 border-b border-border bg-bg-secondary/70">
26
+ <div className="bg-bg-tertiary border border-border rounded-xl p-4 flex flex-col gap-3">
27
+ <div className="flex items-start gap-3">
28
+ <div className="w-9 h-9 rounded-lg bg-bg-primary border border-border flex items-center justify-center">
29
+ <Icons.Warning className="w-4 h-4 text-yellow-500" />
30
+ </div>
31
+ <div>
32
+ <h3 className="text-sm font-semibold text-text-primary">Authenticate to start sessions</h3>
33
+ <p className="text-xs text-text-muted mt-1">
34
+ {pending
35
+ ? 'Waiting for sign-in to complete. Return here after authorizing the account.'
36
+ : 'This account is not signed in. Connect with ChatGPT or provide an API key to enable new sessions and messaging.'}
37
+ </p>
38
+ </div>
39
+ </div>
40
+ <div className="flex flex-wrap gap-2">
41
+ <Button variant="primary" size="sm" onClick={onChatgpt}>
42
+ Sign in with ChatGPT
43
+ </Button>
44
+ <Button variant="ghost" size="sm" onClick={onApiKey}>
45
+ Use API key
46
+ </Button>
47
+ {pending && onCancel && (
48
+ <Button variant="ghost" size="sm" onClick={onCancel}>
49
+ Cancel login
50
+ </Button>
51
+ )}
52
+ {onRefresh && (
53
+ <Button variant="ghost" size="sm" onClick={onRefresh}>
54
+ Check status
55
+ </Button>
56
+ )}
57
+ </div>
58
+ </div>
59
+ </div>
60
+ )
61
+ }
@@ -0,0 +1,328 @@
1
+ import type { KeyboardEvent, RefObject, ClipboardEvent, DragEvent } from 'react'
2
+ import { useRef } from 'react'
3
+ import { SlashCommandMenu } from '../composer/slash-command-menu'
4
+ import { FileMentionMenu } from './file-mention-menu'
5
+ import { Button, IconButton, Icons, Select, type SelectOption } from '../ui'
6
+ import type { SlashCommandDefinition } from '../../utils/slash-commands'
7
+ import type { Attachment, FileMention } from '../../types'
8
+
9
+ interface SessionComposerProps {
10
+ inputValue: string
11
+ onInputChange: (value: string) => void
12
+ onKeyDown: (event: KeyboardEvent<HTMLTextAreaElement>) => void
13
+ onSend: () => void
14
+ onStop?: () => void
15
+ textareaRef: RefObject<HTMLTextAreaElement | null>
16
+ canInteract: boolean
17
+ slashMenuOpen: boolean
18
+ slashMatches: SlashCommandDefinition[]
19
+ slashIndex: number
20
+ isTaskRunning: boolean
21
+ onSlashSelect: (command: SlashCommandDefinition) => void
22
+ onSlashHover: (index: number) => void
23
+ modelOptions: SelectOption[]
24
+ effortOptions: SelectOption[]
25
+ effectiveModel: string
26
+ effectiveEffort: string
27
+ onModelChange: (value: string) => void
28
+ onEffortChange: (value: string) => void
29
+ showModelSelect: boolean
30
+ showEffortSelect: boolean
31
+ queuedCount: number
32
+ webSearchEnabled: boolean
33
+ onWebSearchToggle: () => void
34
+ attachments: Attachment[]
35
+ onAttachmentsChange: (attachments: Attachment[]) => void
36
+ fileMentions: FileMention[]
37
+ onFileMentionsChange: (mentions: FileMention[]) => void
38
+ mentionMenuOpen: boolean
39
+ mentionQuery: string
40
+ mentionMatches: FileMention[]
41
+ mentionIndex: number
42
+ onMentionSelect: (mention: FileMention) => void
43
+ onMentionHover: (index: number) => void
44
+ }
45
+
46
+ export const SessionComposer = ({
47
+ inputValue,
48
+ onInputChange,
49
+ onKeyDown,
50
+ onSend,
51
+ onStop,
52
+ textareaRef,
53
+ canInteract,
54
+ slashMenuOpen,
55
+ slashMatches,
56
+ slashIndex,
57
+ isTaskRunning,
58
+ onSlashSelect,
59
+ onSlashHover,
60
+ modelOptions,
61
+ effortOptions,
62
+ effectiveModel,
63
+ effectiveEffort,
64
+ onModelChange,
65
+ onEffortChange,
66
+ showModelSelect,
67
+ showEffortSelect,
68
+ queuedCount,
69
+ webSearchEnabled,
70
+ onWebSearchToggle,
71
+ attachments,
72
+ onAttachmentsChange,
73
+ fileMentions,
74
+ onFileMentionsChange,
75
+ mentionMenuOpen,
76
+ mentionQuery,
77
+ mentionMatches,
78
+ mentionIndex,
79
+ onMentionSelect,
80
+ onMentionHover,
81
+ }: SessionComposerProps) => {
82
+ const fileInputRef = useRef<HTMLInputElement>(null)
83
+
84
+ const handlePaste = (e: ClipboardEvent<HTMLTextAreaElement>) => {
85
+ const items = e.clipboardData?.items
86
+ if (!items) return
87
+
88
+ for (const item of items) {
89
+ if (item.type.startsWith('image/')) {
90
+ e.preventDefault()
91
+ const file = item.getAsFile()
92
+ if (file) {
93
+ const reader = new FileReader()
94
+ reader.onload = (event) => {
95
+ const dataUrl = event.target?.result as string
96
+ const newAttachment: Attachment = {
97
+ id: `img-${Date.now()}`,
98
+ type: 'image',
99
+ name: `pasted-image-${Date.now()}.png`,
100
+ url: dataUrl,
101
+ size: file.size,
102
+ }
103
+ onAttachmentsChange([...attachments, newAttachment])
104
+ }
105
+ reader.readAsDataURL(file)
106
+ }
107
+ return
108
+ }
109
+ }
110
+ }
111
+
112
+ const handleDrop = (e: DragEvent<HTMLTextAreaElement>) => {
113
+ e.preventDefault()
114
+ const files = e.dataTransfer?.files
115
+ if (!files) return
116
+
117
+ for (const file of files) {
118
+ if (file.type.startsWith('image/')) {
119
+ const reader = new FileReader()
120
+ reader.onload = (event) => {
121
+ const dataUrl = event.target?.result as string
122
+ const newAttachment: Attachment = {
123
+ id: `img-${Date.now()}`,
124
+ type: 'image',
125
+ name: file.name,
126
+ url: dataUrl,
127
+ size: file.size,
128
+ }
129
+ onAttachmentsChange([...attachments, newAttachment])
130
+ }
131
+ reader.readAsDataURL(file)
132
+ }
133
+ }
134
+ }
135
+
136
+ const handleFileInputChange = (e: React.ChangeEvent<HTMLInputElement>) => {
137
+ const files = e.target.files
138
+ if (!files) return
139
+
140
+ for (const file of files) {
141
+ if (file.type.startsWith('image/')) {
142
+ const reader = new FileReader()
143
+ reader.onload = (event) => {
144
+ const dataUrl = event.target?.result as string
145
+ const newAttachment: Attachment = {
146
+ id: `img-${Date.now()}`,
147
+ type: 'image',
148
+ name: file.name,
149
+ url: dataUrl,
150
+ size: file.size,
151
+ }
152
+ onAttachmentsChange([...attachments, newAttachment])
153
+ }
154
+ reader.readAsDataURL(file)
155
+ }
156
+ }
157
+ // Reset input
158
+ e.target.value = ''
159
+ }
160
+
161
+ const removeAttachment = (id: string) => {
162
+ onAttachmentsChange(attachments.filter(a => a.id !== id))
163
+ }
164
+
165
+ const removeMention = (path: string) => {
166
+ onFileMentionsChange(fileMentions.filter(m => m.path !== path))
167
+ }
168
+
169
+ return (
170
+ <div className="px-3 py-3 md:px-6 md:py-4 border-t border-border shrink-0 pb-safe">
171
+ <div className="max-w-4xl mx-auto">
172
+ <div className="bg-bg-tertiary border border-border rounded-xl overflow-visible focus-within:border-text-muted transition-colors relative">
173
+ {slashMenuOpen && (
174
+ <SlashCommandMenu
175
+ commands={slashMatches}
176
+ activeIndex={slashIndex}
177
+ isTaskRunning={isTaskRunning}
178
+ onSelect={onSlashSelect}
179
+ onHover={onSlashHover}
180
+ />
181
+ )}
182
+ {mentionMenuOpen && mentionMatches.length > 0 && (
183
+ <FileMentionMenu
184
+ matches={mentionMatches}
185
+ activeIndex={mentionIndex}
186
+ query={mentionQuery}
187
+ onSelect={onMentionSelect}
188
+ onHover={onMentionHover}
189
+ />
190
+ )}
191
+
192
+ {/* Attachments preview */}
193
+ {(attachments.length > 0 || fileMentions.length > 0) && (
194
+ <div className="px-4 pt-3 flex flex-wrap gap-2">
195
+ {attachments.map((attachment) => (
196
+ <div
197
+ key={attachment.id}
198
+ className="relative group flex items-center gap-2 px-2 py-1 bg-bg-elevated border border-border rounded-lg"
199
+ >
200
+ {attachment.type === 'image' && attachment.url && (
201
+ <img
202
+ src={attachment.url}
203
+ alt={attachment.name}
204
+ className="w-8 h-8 object-cover rounded"
205
+ />
206
+ )}
207
+ <span className="text-[10px] text-text-secondary max-w-[100px] truncate">
208
+ {attachment.name}
209
+ </span>
210
+ <button
211
+ onClick={() => removeAttachment(attachment.id)}
212
+ className="p-0.5 hover:bg-bg-hover rounded transition-colors"
213
+ >
214
+ <Icons.X className="w-3 h-3 text-text-muted" />
215
+ </button>
216
+ </div>
217
+ ))}
218
+ {fileMentions.map((mention) => (
219
+ <div
220
+ key={mention.path}
221
+ className="flex items-center gap-1.5 px-2 py-1 bg-accent-blue/10 border border-accent-blue/30 rounded-lg"
222
+ >
223
+ <Icons.File className="w-3 h-3 text-accent-blue" />
224
+ <span className="text-[10px] text-accent-blue max-w-[150px] truncate">
225
+ {mention.name}
226
+ </span>
227
+ <button
228
+ onClick={() => removeMention(mention.path)}
229
+ className="p-0.5 hover:bg-accent-blue/20 rounded transition-colors"
230
+ >
231
+ <Icons.X className="w-3 h-3 text-accent-blue" />
232
+ </button>
233
+ </div>
234
+ ))}
235
+ </div>
236
+ )}
237
+
238
+ <textarea
239
+ ref={textareaRef}
240
+ value={inputValue}
241
+ onChange={(event) => onInputChange(event.target.value)}
242
+ onKeyDown={onKeyDown}
243
+ onPaste={handlePaste}
244
+ onDrop={handleDrop}
245
+ onDragOver={(e) => e.preventDefault()}
246
+ placeholder="Describe a task... (@ to mention files, Enter to send)"
247
+ rows={3}
248
+ disabled={!canInteract}
249
+ className="w-full bg-transparent text-sm text-text-primary placeholder:text-text-muted outline-none resize-none px-4 py-3 leading-relaxed disabled:opacity-50"
250
+ />
251
+ <input
252
+ ref={fileInputRef}
253
+ type="file"
254
+ accept="image/*"
255
+ multiple
256
+ onChange={handleFileInputChange}
257
+ className="hidden"
258
+ />
259
+ <div className="flex items-center justify-between px-2.5 py-2 border-t border-border bg-bg-secondary/50 rounded-b-xl gap-2">
260
+ <div className="flex items-center gap-1 flex-wrap min-w-0 overflow-x-auto scrollbar-hide">
261
+ <IconButton
262
+ icon={<Icons.Paperclip className="w-4 h-4 text-text-muted" />}
263
+ size="sm"
264
+ disabled={!canInteract}
265
+ onClick={() => fileInputRef.current?.click()}
266
+ />
267
+ <IconButton icon={<Icons.Microphone className="w-4 h-4 text-text-muted" />} size="sm" disabled={!canInteract} className="hidden sm:flex" />
268
+ <IconButton
269
+ icon={<Icons.Globe className={`w-4 h-4 ${webSearchEnabled ? 'text-accent-green' : 'text-text-muted'}`} />}
270
+ size="sm"
271
+ disabled={!canInteract}
272
+ onClick={onWebSearchToggle}
273
+ />
274
+ {showModelSelect && (
275
+ <Select
276
+ options={modelOptions}
277
+ value={effectiveModel}
278
+ onChange={onModelChange}
279
+ size="sm"
280
+ disabled={!canInteract}
281
+ label="Select Model"
282
+ />
283
+ )}
284
+ {showEffortSelect && (
285
+ <Select
286
+ options={effortOptions}
287
+ value={effectiveEffort}
288
+ onChange={onEffortChange}
289
+ placeholder="Thinking"
290
+ size="sm"
291
+ disabled={!canInteract}
292
+ label="Reasoning Effort"
293
+ />
294
+ )}
295
+ </div>
296
+ <div className="flex items-center gap-2 sm:gap-3 shrink-0">
297
+ {queuedCount > 0 && (
298
+ <div className="text-[10px] text-text-muted hidden sm:block">
299
+ Queued {queuedCount}
300
+ </div>
301
+ )}
302
+ {isTaskRunning && (
303
+ <Button
304
+ variant="ghost"
305
+ size="sm"
306
+ onClick={onStop}
307
+ disabled={!canInteract || !onStop}
308
+ >
309
+ <Icons.X className="w-3.5 h-3.5" />
310
+ <span className="hidden sm:inline">Stop</span>
311
+ </Button>
312
+ )}
313
+ <Button
314
+ variant="primary"
315
+ size="sm"
316
+ onClick={onSend}
317
+ disabled={!inputValue.trim() || !canInteract}
318
+ >
319
+ <Icons.ArrowUp className="w-3.5 h-3.5" />
320
+ <span className="hidden sm:inline">Send</span>
321
+ </Button>
322
+ </div>
323
+ </div>
324
+ </div>
325
+ </div>
326
+ </div>
327
+ )
328
+ }