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,528 @@
1
+ import { create } from 'zustand'
2
+ import type { Account, Thread, Message, ApprovalRequest, TabType, ModelInfo, ReasoningEffort, ReasoningSummary, ApprovalPolicy, QueuedMessage, ReviewSession } from '../types'
3
+
4
+ interface AppState {
5
+ accounts: Account[]
6
+ selectedAccountId: string | null
7
+ connectionStatus: 'idle' | 'connecting' | 'connected' | 'error'
8
+ accountLoginIds: Record<string, string>
9
+
10
+ threads: Thread[]
11
+ selectedThreadId: string | null
12
+ modelsByAccount: Record<string, ModelInfo[]>
13
+ threadModels: Record<string, string>
14
+ threadEfforts: Record<string, ReasoningEffort>
15
+ threadSummaries: Record<string, ReasoningSummary>
16
+ threadCwds: Record<string, string>
17
+ threadApprovals: Record<string, ApprovalPolicy>
18
+ threadWebSearch: Record<string, boolean>
19
+ threadTurnIds: Record<string, string>
20
+ threadTurnStartedAt: Record<string, number>
21
+ threadLastTurnDuration: Record<string, number>
22
+ threadTokenUsage: Record<string, unknown>
23
+
24
+ messages: Record<string, Message[]>
25
+ queuedMessages: Record<string, QueuedMessage[]>
26
+
27
+ approvals: ApprovalRequest[]
28
+ reviewSessions: ReviewSession[]
29
+
30
+ activeTab: TabType
31
+ isSidebarCollapsed: boolean
32
+ showAnalytics: boolean
33
+ showReviews: boolean
34
+
35
+ isMobileSidebarOpen: boolean
36
+ isMobileThreadListOpen: boolean
37
+
38
+ setSelectedAccountId: (id: string | null) => void
39
+ setAccounts: (accounts: Account[]) => void
40
+ addAccount: (account: Account) => void
41
+ removeAccount: (id: string) => void
42
+ updateAccountStatus: (id: string, status: Account['status']) => void
43
+ updateAccount: (id: string, updater: (account: Account) => Account) => void
44
+ setAccountLoginId: (id: string, loginId: string | null) => void
45
+
46
+ setSelectedThreadId: (id: string | null) => void
47
+ setThreadsForAccount: (accountId: string, threads: Thread[]) => void
48
+ addThread: (thread: Thread) => void
49
+ removeThread: (id: string) => void
50
+ updateThread: (id: string, updates: Partial<Thread>) => void
51
+ setModelsForAccount: (accountId: string, models: ModelInfo[]) => void
52
+ setThreadModel: (threadId: string, modelId: string) => void
53
+ setThreadEffort: (threadId: string, effort: ReasoningEffort) => void
54
+ setThreadSummary: (threadId: string, summary: ReasoningSummary) => void
55
+ setThreadCwd: (threadId: string, cwd: string) => void
56
+ setThreadApproval: (threadId: string, approval: ApprovalPolicy) => void
57
+ setThreadWebSearch: (threadId: string, enabled: boolean) => void
58
+ setThreadTurnId: (threadId: string, turnId: string | null) => void
59
+ setThreadTurnStartedAt: (threadId: string, startedAt: number | null) => void
60
+ setThreadLastTurnDuration: (threadId: string, duration: number | null) => void
61
+ setThreadTokenUsage: (threadId: string, usage: unknown) => void
62
+
63
+ addMessage: (threadId: string, message: Message) => void
64
+ appendAgentDelta: (threadId: string, messageId: string, delta: string) => void
65
+ appendMessageDelta: (threadId: string, messageId: string, delta: string) => void
66
+ upsertMessage: (threadId: string, message: Message) => void
67
+ ensureAssistantMessage: (threadId: string, messageId: string) => void
68
+ setMessagesForThread: (threadId: string, messages: Message[]) => void
69
+ clearMessages: (threadId: string) => void
70
+ enqueueMessage: (threadId: string, message: QueuedMessage) => void
71
+ shiftQueuedMessage: (threadId: string) => QueuedMessage | null
72
+ clearQueuedMessages: (threadId: string) => void
73
+
74
+ addApproval: (approval: ApprovalRequest) => void
75
+ resolveApproval: (id: string, status: 'approved' | 'denied') => void
76
+ upsertReviewSession: (session: ReviewSession) => void
77
+ updateReviewSession: (id: string, updates: Partial<ReviewSession>) => void
78
+
79
+ setActiveTab: (tab: TabType) => void
80
+ toggleSidebar: () => void
81
+ setShowAnalytics: (show: boolean) => void
82
+ setShowReviews: (show: boolean) => void
83
+ setConnectionStatus: (status: AppState['connectionStatus']) => void
84
+
85
+ setMobileSidebarOpen: (open: boolean) => void
86
+ setMobileThreadListOpen: (open: boolean) => void
87
+ closeMobileDrawers: () => void
88
+ }
89
+
90
+ export const useAppStore = create<AppState>((set) => ({
91
+ accounts: [],
92
+ selectedAccountId: null,
93
+ connectionStatus: 'idle',
94
+ accountLoginIds: {},
95
+ threads: [],
96
+ selectedThreadId: null,
97
+ modelsByAccount: {},
98
+ threadModels: {},
99
+ threadEfforts: {},
100
+ threadSummaries: {},
101
+ threadCwds: {},
102
+ threadApprovals: {},
103
+ threadWebSearch: {},
104
+ threadTurnIds: {},
105
+ threadTurnStartedAt: {},
106
+ threadLastTurnDuration: {},
107
+ threadTokenUsage: {},
108
+ messages: {},
109
+ queuedMessages: {},
110
+ approvals: [],
111
+ reviewSessions: [],
112
+ activeTab: 'sessions',
113
+ isSidebarCollapsed: false,
114
+ showAnalytics: false,
115
+ showReviews: false,
116
+ isMobileSidebarOpen: false,
117
+ isMobileThreadListOpen: false,
118
+
119
+ setSelectedAccountId: (id) => set({ selectedAccountId: id }),
120
+ setAccounts: (accounts) => set({ accounts }),
121
+ addAccount: (account) => set((state) => ({ accounts: [...state.accounts, account] })),
122
+ removeAccount: (id) => set((state) => {
123
+ const remainingThreads = state.threads.filter((thread) => thread.accountId !== id)
124
+ const remainingThreadIds = new Set(remainingThreads.map((thread) => thread.id))
125
+ const messages = Object.fromEntries(
126
+ Object.entries(state.messages).filter(([threadId]) => remainingThreadIds.has(threadId))
127
+ )
128
+ const queuedMessages = Object.fromEntries(
129
+ Object.entries(state.queuedMessages).filter(([threadId]) => remainingThreadIds.has(threadId))
130
+ )
131
+ const threadModels = Object.fromEntries(
132
+ Object.entries(state.threadModels).filter(([threadId]) => remainingThreadIds.has(threadId))
133
+ )
134
+ const threadEfforts = Object.fromEntries(
135
+ Object.entries(state.threadEfforts).filter(([threadId]) => remainingThreadIds.has(threadId))
136
+ )
137
+ const threadSummaries = Object.fromEntries(
138
+ Object.entries(state.threadSummaries).filter(([threadId]) => remainingThreadIds.has(threadId))
139
+ )
140
+ const threadCwds = Object.fromEntries(
141
+ Object.entries(state.threadCwds).filter(([threadId]) => remainingThreadIds.has(threadId))
142
+ )
143
+ const threadApprovals = Object.fromEntries(
144
+ Object.entries(state.threadApprovals).filter(([threadId]) => remainingThreadIds.has(threadId))
145
+ )
146
+ const threadTokenUsage = Object.fromEntries(
147
+ Object.entries(state.threadTokenUsage).filter(([threadId]) => remainingThreadIds.has(threadId))
148
+ )
149
+ const modelsByAccount = { ...state.modelsByAccount }
150
+ delete modelsByAccount[id]
151
+ const accountLoginIds = { ...state.accountLoginIds }
152
+ delete accountLoginIds[id]
153
+
154
+ return {
155
+ accounts: state.accounts.filter((account) => account.id !== id),
156
+ selectedAccountId: state.selectedAccountId === id ? null : state.selectedAccountId,
157
+ selectedThreadId:
158
+ state.selectedThreadId && remainingThreadIds.has(state.selectedThreadId)
159
+ ? state.selectedThreadId
160
+ : null,
161
+ threads: remainingThreads,
162
+ messages,
163
+ queuedMessages,
164
+ threadModels,
165
+ threadEfforts,
166
+ threadSummaries,
167
+ threadCwds,
168
+ threadApprovals,
169
+ threadTokenUsage,
170
+ modelsByAccount,
171
+ accountLoginIds,
172
+ reviewSessions: state.reviewSessions.filter((session) => session.profileId !== id),
173
+ approvals: state.approvals.filter((approval) => approval.profileId !== id),
174
+ }
175
+ }),
176
+ updateAccountStatus: (id, status) => set((state) => ({
177
+ accounts: state.accounts.map((a) => a.id === id ? { ...a, status } : a),
178
+ })),
179
+ updateAccount: (id, updater) => set((state) => ({
180
+ accounts: state.accounts.map((a) => (a.id === id ? updater(a) : a)),
181
+ })),
182
+ setAccountLoginId: (id, loginId) => set((state) => {
183
+ if (!loginId) {
184
+ const { [id]: _, ...rest } = state.accountLoginIds
185
+ return { accountLoginIds: rest }
186
+ }
187
+ return {
188
+ accountLoginIds: {
189
+ ...state.accountLoginIds,
190
+ [id]: loginId,
191
+ },
192
+ }
193
+ }),
194
+
195
+ setSelectedThreadId: (id) => set({ selectedThreadId: id }),
196
+ setThreadsForAccount: (accountId, threads) => set((state) => ({
197
+ threads: [
198
+ ...state.threads.filter((thread) => thread.accountId !== accountId),
199
+ ...threads,
200
+ ],
201
+ })),
202
+ addThread: (thread) => set((state) => ({
203
+ threads: [thread, ...state.threads.filter((t) => t.id !== thread.id)],
204
+ })),
205
+ removeThread: (id) => set((state) => ({
206
+ threads: state.threads.filter((t) => t.id !== id),
207
+ selectedThreadId: state.selectedThreadId === id ? null : state.selectedThreadId,
208
+ queuedMessages: Object.fromEntries(
209
+ Object.entries(state.queuedMessages).filter(([threadId]) => threadId !== id)
210
+ ),
211
+ threadSummaries: Object.fromEntries(
212
+ Object.entries(state.threadSummaries).filter(([threadId]) => threadId !== id)
213
+ ),
214
+ threadCwds: Object.fromEntries(
215
+ Object.entries(state.threadCwds).filter(([threadId]) => threadId !== id)
216
+ ),
217
+ threadTokenUsage: Object.fromEntries(
218
+ Object.entries(state.threadTokenUsage).filter(([threadId]) => threadId !== id)
219
+ ),
220
+ })),
221
+ updateThread: (id, updates) => set((state) => {
222
+ const exists = state.threads.some((t) => t.id === id)
223
+ if (!exists) {
224
+ return {
225
+ threads: [
226
+ {
227
+ id,
228
+ accountId: updates.accountId ?? '',
229
+ title: updates.title ?? 'Untitled session',
230
+ preview: updates.preview ?? '',
231
+ model: updates.model ?? 'unknown',
232
+ createdAt: updates.createdAt ?? '',
233
+ status: updates.status ?? 'idle',
234
+ messageCount: updates.messageCount ?? 0,
235
+ },
236
+ ...state.threads,
237
+ ],
238
+ }
239
+ }
240
+ return {
241
+ threads: state.threads.map((t) => t.id === id ? { ...t, ...updates } : t),
242
+ }
243
+ }),
244
+ setModelsForAccount: (accountId, models) => set((state) => ({
245
+ modelsByAccount: {
246
+ ...state.modelsByAccount,
247
+ [accountId]: models,
248
+ },
249
+ })),
250
+ setThreadModel: (threadId, modelId) => set((state) => ({
251
+ threadModels: {
252
+ ...state.threadModels,
253
+ [threadId]: modelId,
254
+ },
255
+ })),
256
+ setThreadEffort: (threadId, effort) => set((state) => ({
257
+ threadEfforts: {
258
+ ...state.threadEfforts,
259
+ [threadId]: effort,
260
+ },
261
+ })),
262
+ setThreadSummary: (threadId, summary) => set((state) => ({
263
+ threadSummaries: {
264
+ ...state.threadSummaries,
265
+ [threadId]: summary,
266
+ },
267
+ })),
268
+ setThreadCwd: (threadId, cwd) => set((state) => ({
269
+ threadCwds: {
270
+ ...state.threadCwds,
271
+ [threadId]: cwd,
272
+ },
273
+ })),
274
+ setThreadApproval: (threadId, approval) => set((state) => ({
275
+ threadApprovals: {
276
+ ...state.threadApprovals,
277
+ [threadId]: approval,
278
+ },
279
+ })),
280
+ setThreadWebSearch: (threadId, enabled) => set((state) => ({
281
+ threadWebSearch: {
282
+ ...state.threadWebSearch,
283
+ [threadId]: enabled,
284
+ },
285
+ })),
286
+ setThreadTurnId: (threadId, turnId) => set((state) => {
287
+ if (turnId === null) {
288
+ const { [threadId]: _, ...rest } = state.threadTurnIds
289
+ return { threadTurnIds: rest }
290
+ }
291
+ return {
292
+ threadTurnIds: {
293
+ ...state.threadTurnIds,
294
+ [threadId]: turnId,
295
+ },
296
+ }
297
+ }),
298
+ setThreadTurnStartedAt: (threadId, startedAt) => set((state) => {
299
+ if (startedAt === null) {
300
+ const { [threadId]: _, ...rest } = state.threadTurnStartedAt
301
+ return { threadTurnStartedAt: rest }
302
+ }
303
+ return {
304
+ threadTurnStartedAt: {
305
+ ...state.threadTurnStartedAt,
306
+ [threadId]: startedAt,
307
+ },
308
+ }
309
+ }),
310
+ setThreadLastTurnDuration: (threadId, duration) => set((state) => {
311
+ if (duration === null) {
312
+ const { [threadId]: _, ...rest } = state.threadLastTurnDuration
313
+ return { threadLastTurnDuration: rest }
314
+ }
315
+ return {
316
+ threadLastTurnDuration: {
317
+ ...state.threadLastTurnDuration,
318
+ [threadId]: duration,
319
+ },
320
+ }
321
+ }),
322
+ setThreadTokenUsage: (threadId, usage) => set((state) => ({
323
+ threadTokenUsage: {
324
+ ...state.threadTokenUsage,
325
+ [threadId]: usage,
326
+ },
327
+ })),
328
+
329
+ addMessage: (threadId, message) => set((state) => ({
330
+ messages: {
331
+ ...state.messages,
332
+ [threadId]: [...(state.messages[threadId] || []), message],
333
+ },
334
+ threads: state.threads.map((thread) =>
335
+ thread.id === threadId
336
+ ? { ...thread, messageCount: thread.messageCount + 1 }
337
+ : thread
338
+ ),
339
+ })),
340
+ appendAgentDelta: (threadId, messageId, delta) => set((state) => {
341
+ const existing = state.messages[threadId] || []
342
+ const index = existing.findIndex((msg) => msg.id === messageId)
343
+ if (index === -1) {
344
+ return {
345
+ messages: {
346
+ ...state.messages,
347
+ [threadId]: [
348
+ ...existing,
349
+ {
350
+ id: messageId,
351
+ role: 'assistant',
352
+ content: delta,
353
+ kind: 'chat',
354
+ timestamp: new Date().toLocaleTimeString([], { hour: '2-digit', minute: '2-digit' }),
355
+ },
356
+ ],
357
+ },
358
+ }
359
+ }
360
+ const updated = [...existing]
361
+ updated[index] = {
362
+ ...updated[index],
363
+ content: `${updated[index].content}${delta}`,
364
+ }
365
+ return {
366
+ messages: {
367
+ ...state.messages,
368
+ [threadId]: updated,
369
+ },
370
+ }
371
+ }),
372
+ appendMessageDelta: (threadId, messageId, delta) => set((state) => {
373
+ const existing = state.messages[threadId] || []
374
+ const index = existing.findIndex((msg) => msg.id === messageId)
375
+ if (index === -1) {
376
+ return {
377
+ messages: {
378
+ ...state.messages,
379
+ [threadId]: [
380
+ ...existing,
381
+ {
382
+ id: messageId,
383
+ role: 'assistant',
384
+ content: delta,
385
+ kind: 'chat',
386
+ timestamp: new Date().toLocaleTimeString([], { hour: '2-digit', minute: '2-digit' }),
387
+ },
388
+ ],
389
+ },
390
+ }
391
+ }
392
+ const updated = [...existing]
393
+ updated[index] = {
394
+ ...updated[index],
395
+ content: `${updated[index].content}${delta}`,
396
+ }
397
+ return {
398
+ messages: {
399
+ ...state.messages,
400
+ [threadId]: updated,
401
+ },
402
+ }
403
+ }),
404
+ upsertMessage: (threadId, message) => set((state) => {
405
+ const existing = state.messages[threadId] || []
406
+ const index = existing.findIndex((msg) => msg.id === message.id)
407
+ if (index === -1) {
408
+ return {
409
+ messages: {
410
+ ...state.messages,
411
+ [threadId]: [...existing, message],
412
+ },
413
+ threads: state.threads.map((thread) =>
414
+ thread.id === threadId
415
+ ? { ...thread, messageCount: thread.messageCount + 1 }
416
+ : thread
417
+ ),
418
+ }
419
+ }
420
+ const updated = [...existing]
421
+ updated[index] = { ...updated[index], ...message }
422
+ return {
423
+ messages: {
424
+ ...state.messages,
425
+ [threadId]: updated,
426
+ },
427
+ }
428
+ }),
429
+ ensureAssistantMessage: (threadId, messageId) => set((state) => {
430
+ const existing = state.messages[threadId] || []
431
+ if (existing.some((msg) => msg.id === messageId)) {
432
+ return state
433
+ }
434
+ return {
435
+ messages: {
436
+ ...state.messages,
437
+ [threadId]: [
438
+ ...existing,
439
+ {
440
+ id: messageId,
441
+ role: 'assistant',
442
+ content: '',
443
+ kind: 'chat',
444
+ timestamp: new Date().toLocaleTimeString([], { hour: '2-digit', minute: '2-digit' }),
445
+ },
446
+ ],
447
+ },
448
+ }
449
+ }),
450
+ setMessagesForThread: (threadId, messages) => set((state) => ({
451
+ messages: {
452
+ ...state.messages,
453
+ [threadId]: messages,
454
+ },
455
+ threads: state.threads.map((thread) =>
456
+ thread.id === threadId
457
+ ? { ...thread, messageCount: messages.length }
458
+ : thread
459
+ ),
460
+ })),
461
+ clearMessages: (threadId) => set((state) => ({
462
+ messages: { ...state.messages, [threadId]: [] },
463
+ })),
464
+ enqueueMessage: (threadId, message) => set((state) => ({
465
+ queuedMessages: {
466
+ ...state.queuedMessages,
467
+ [threadId]: [...(state.queuedMessages[threadId] || []), message],
468
+ },
469
+ })),
470
+ shiftQueuedMessage: (threadId) => {
471
+ let next: QueuedMessage | null = null
472
+ set((state) => {
473
+ const queue = state.queuedMessages[threadId] || []
474
+ if (!queue.length) {
475
+ return state
476
+ }
477
+ next = queue[0]
478
+ const remaining = queue.slice(1)
479
+ const queuedMessages = { ...state.queuedMessages }
480
+ if (remaining.length) {
481
+ queuedMessages[threadId] = remaining
482
+ } else {
483
+ delete queuedMessages[threadId]
484
+ }
485
+ return { queuedMessages }
486
+ })
487
+ return next
488
+ },
489
+ clearQueuedMessages: (threadId) => set((state) => {
490
+ if (!state.queuedMessages[threadId]) {
491
+ return state
492
+ }
493
+ const queuedMessages = { ...state.queuedMessages }
494
+ delete queuedMessages[threadId]
495
+ return { queuedMessages }
496
+ }),
497
+
498
+ addApproval: (approval) => set((state) => ({ approvals: [...state.approvals, approval] })),
499
+ resolveApproval: (id, status) => set((state) => ({
500
+ approvals: state.approvals.map((a) => a.id === id ? { ...a, status } : a),
501
+ })),
502
+ upsertReviewSession: (session) => set((state) => {
503
+ const existing = state.reviewSessions.find((item) => item.id === session.id)
504
+ if (!existing) {
505
+ return { reviewSessions: [session, ...state.reviewSessions] }
506
+ }
507
+ return {
508
+ reviewSessions: state.reviewSessions.map((item) =>
509
+ item.id === session.id ? { ...item, ...session } : item
510
+ ),
511
+ }
512
+ }),
513
+ updateReviewSession: (id, updates) => set((state) => ({
514
+ reviewSessions: state.reviewSessions.map((item) =>
515
+ item.id === id ? { ...item, ...updates } : item
516
+ ),
517
+ })),
518
+
519
+ setActiveTab: (tab) => set({ activeTab: tab }),
520
+ toggleSidebar: () => set((state) => ({ isSidebarCollapsed: !state.isSidebarCollapsed })),
521
+ setShowAnalytics: (show) => set({ showAnalytics: show, showReviews: false }),
522
+ setShowReviews: (show) => set({ showReviews: show, showAnalytics: false }),
523
+ setConnectionStatus: (status) => set({ connectionStatus: status }),
524
+
525
+ setMobileSidebarOpen: (open) => set({ isMobileSidebarOpen: open }),
526
+ setMobileThreadListOpen: (open) => set({ isMobileThreadListOpen: open }),
527
+ closeMobileDrawers: () => set({ isMobileSidebarOpen: false, isMobileThreadListOpen: false }),
528
+ }))
@@ -0,0 +1,119 @@
1
+ export type AccountStatus = 'online' | 'degraded' | 'offline'
2
+ export type ThreadStatus = 'active' | 'idle' | 'archived'
3
+ export type MessageRole = 'user' | 'assistant'
4
+ export type MessageKind = 'chat' | 'reasoning' | 'command' | 'file' | 'tool'
5
+ export type TabType = 'sessions' | 'reviews' | 'archive'
6
+ export type ReasoningEffort = 'none' | 'minimal' | 'low' | 'medium' | 'high' | 'xhigh'
7
+ export type ReasoningSummary = 'auto' | 'concise' | 'detailed' | 'none'
8
+ export type ApprovalPolicy = 'untrusted' | 'on-failure' | 'on-request' | 'never'
9
+ export type ReviewStatus = 'pending' | 'running' | 'completed' | 'failed'
10
+
11
+ export interface Attachment {
12
+ id: string
13
+ type: 'image' | 'file'
14
+ name: string
15
+ path?: string
16
+ url?: string
17
+ size?: number
18
+ }
19
+
20
+ export interface FileMention {
21
+ path: string
22
+ name: string
23
+ }
24
+
25
+ export interface RateLimitWindow {
26
+ usedPercent: number
27
+ windowMinutes: number | null
28
+ resetsAt: number | null
29
+ }
30
+
31
+ export interface CreditsSnapshot {
32
+ hasCredits: boolean
33
+ unlimited: boolean
34
+ balance: string | null
35
+ }
36
+
37
+ export interface AccountUsage {
38
+ primary: RateLimitWindow | null
39
+ secondary: RateLimitWindow | null
40
+ credits: CreditsSnapshot | null
41
+ planType: string | null
42
+ }
43
+
44
+ export interface Account {
45
+ id: string
46
+ name: string
47
+ email: string
48
+ plan: string
49
+ status: AccountStatus
50
+ rateLimit: number
51
+ usage?: AccountUsage
52
+ }
53
+
54
+ export interface Thread {
55
+ id: string
56
+ accountId: string
57
+ title: string
58
+ preview: string
59
+ model: string
60
+ createdAt: string
61
+ status: ThreadStatus
62
+ messageCount: number
63
+ }
64
+
65
+ export interface Message {
66
+ id: string
67
+ role: MessageRole
68
+ content: string
69
+ kind?: MessageKind
70
+ title?: string
71
+ timestamp: string
72
+ }
73
+
74
+ export interface QueuedMessage {
75
+ id: string
76
+ text: string
77
+ model?: string
78
+ effort?: ReasoningEffort | null
79
+ summary?: ReasoningSummary | null
80
+ cwd?: string | null
81
+ approvalPolicy?: ApprovalPolicy | null
82
+ createdAt: number
83
+ }
84
+
85
+ export interface ModelInfo {
86
+ id: string
87
+ model: string
88
+ displayName: string
89
+ description: string
90
+ supportedReasoningEfforts: Array<{
91
+ reasoningEffort: ReasoningEffort
92
+ description: string
93
+ }>
94
+ defaultReasoningEffort: ReasoningEffort
95
+ isDefault: boolean
96
+ }
97
+
98
+ export interface ApprovalRequest {
99
+ id: string
100
+ requestId: number
101
+ profileId: string
102
+ threadId: string
103
+ type: 'command' | 'file' | 'network'
104
+ payload: string
105
+ status: 'pending' | 'approved' | 'denied'
106
+ }
107
+
108
+ export interface ReviewSession {
109
+ id: string
110
+ threadId: string
111
+ profileId: string
112
+ model?: string
113
+ cwd?: string
114
+ status: ReviewStatus
115
+ startedAt: number
116
+ completedAt?: number
117
+ label?: string
118
+ review?: string
119
+ }