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,168 @@
1
+ import type { Account, AccountStatus, AccountUsage, ModelInfo } from '../types'
2
+ import { hubClient } from '../services/hub-client'
3
+
4
+ export type AccountReadResult = {
5
+ account?: {
6
+ type: string
7
+ email?: string
8
+ planType?: string
9
+ } | null
10
+ requiresOpenaiAuth?: boolean
11
+ }
12
+
13
+ type RateLimitWindowRaw = {
14
+ used_percent?: number
15
+ usedPercent?: number
16
+ window_minutes?: number | null
17
+ windowDurationMins?: number | null
18
+ resets_at?: number | null
19
+ resetsAt?: number | null
20
+ }
21
+
22
+ type CreditsSnapshotRaw = {
23
+ has_credits?: boolean
24
+ hasCredits?: boolean
25
+ unlimited?: boolean
26
+ balance?: string | null
27
+ }
28
+
29
+ export type RateLimitResult = {
30
+ rateLimits?: {
31
+ primary?: RateLimitWindowRaw | null
32
+ secondary?: RateLimitWindowRaw | null
33
+ credits?: CreditsSnapshotRaw | null
34
+ plan_type?: string | null
35
+ planType?: string | null
36
+ } | null
37
+ }
38
+
39
+ type ModelListResult = {
40
+ data?: ModelInfo[]
41
+ nextCursor?: string | null
42
+ }
43
+
44
+ const readNumber = (...values: Array<number | null | undefined>) => {
45
+ for (const value of values) {
46
+ if (typeof value === 'number') {
47
+ return value
48
+ }
49
+ }
50
+ return 0
51
+ }
52
+
53
+ const readNumberOrNull = (...values: Array<number | null | undefined>) => {
54
+ for (const value of values) {
55
+ if (typeof value === 'number') {
56
+ return value
57
+ }
58
+ }
59
+ return null
60
+ }
61
+
62
+ export const parseUsage = (result: RateLimitResult): AccountUsage | undefined => {
63
+ const limits = result.rateLimits
64
+ if (!limits) return undefined
65
+ return {
66
+ primary: limits.primary ? {
67
+ usedPercent: readNumber(limits.primary.usedPercent, limits.primary.used_percent),
68
+ windowMinutes: readNumberOrNull(
69
+ limits.primary.windowDurationMins,
70
+ limits.primary.window_minutes
71
+ ),
72
+ resetsAt: readNumberOrNull(limits.primary.resetsAt, limits.primary.resets_at),
73
+ } : null,
74
+ secondary: limits.secondary ? {
75
+ usedPercent: readNumber(limits.secondary.usedPercent, limits.secondary.used_percent),
76
+ windowMinutes: readNumberOrNull(
77
+ limits.secondary.windowDurationMins,
78
+ limits.secondary.window_minutes
79
+ ),
80
+ resetsAt: readNumberOrNull(limits.secondary.resetsAt, limits.secondary.resets_at),
81
+ } : null,
82
+ credits: limits.credits ? {
83
+ hasCredits: limits.credits.hasCredits ?? limits.credits.has_credits ?? false,
84
+ unlimited: limits.credits.unlimited ?? false,
85
+ balance: limits.credits.balance ?? null,
86
+ } : null,
87
+ planType: limits.planType ?? limits.plan_type ?? null,
88
+ }
89
+ }
90
+
91
+ export const accountStatusFromRead = (result: AccountReadResult): AccountStatus => {
92
+ if (!result.account) {
93
+ return result.requiresOpenaiAuth ? 'offline' : 'online'
94
+ }
95
+ return 'online'
96
+ }
97
+
98
+ export const fetchAllModels = async (profileId: string): Promise<ModelInfo[]> => {
99
+ const models: ModelInfo[] = []
100
+ let cursor: string | null = null
101
+ for (let page = 0; page < 10; page += 1) {
102
+ let result: ModelListResult | null = null
103
+ try {
104
+ result = (await hubClient.request(profileId, 'model/list', {
105
+ limit: 100,
106
+ cursor,
107
+ })) as ModelListResult
108
+ } catch {
109
+ return models
110
+ }
111
+ if (!result?.data?.length) {
112
+ break
113
+ }
114
+ models.push(...result.data)
115
+ if (!result.nextCursor || result.nextCursor === cursor) {
116
+ break
117
+ }
118
+ cursor = result.nextCursor
119
+ }
120
+ return models
121
+ }
122
+
123
+ export const refreshAccountSnapshot = async (
124
+ profileId: string,
125
+ updateAccount: (id: string, updater: (account: Account) => Account) => void,
126
+ setModelsForAccount: (id: string, models: ModelInfo[]) => void
127
+ ): Promise<void> => {
128
+ let accountResult: AccountReadResult | null = null
129
+ try {
130
+ accountResult = (await hubClient.request(profileId, 'account/read', {
131
+ refreshToken: false,
132
+ })) as AccountReadResult
133
+ } catch {
134
+ accountResult = null
135
+ }
136
+ if (accountResult) {
137
+ updateAccount(profileId, (prev) => ({
138
+ ...prev,
139
+ status: accountStatusFromRead(accountResult),
140
+ email: accountResult.account?.email ?? prev.email,
141
+ plan: accountResult.account?.planType ?? prev.plan,
142
+ }))
143
+ }
144
+
145
+ try {
146
+ const limits = (await hubClient.request(profileId, 'account/rateLimits/read')) as RateLimitResult
147
+ if (limits) {
148
+ const usage = parseUsage(limits)
149
+ const rate = usage?.primary?.usedPercent
150
+ updateAccount(profileId, (prev) => ({
151
+ ...prev,
152
+ rateLimit: typeof rate === 'number' ? Math.round(rate) : prev.rateLimit,
153
+ usage: usage ?? prev.usage,
154
+ }))
155
+ }
156
+ } catch {
157
+ // Ignore rate limit errors for unauthenticated accounts.
158
+ }
159
+
160
+ try {
161
+ const models = await fetchAllModels(profileId)
162
+ if (models.length) {
163
+ setModelsForAccount(profileId, models)
164
+ }
165
+ } catch {
166
+ // Ignore model errors for unauthenticated accounts.
167
+ }
168
+ }
@@ -0,0 +1,53 @@
1
+ import type { ApprovalPolicy } from '../types'
2
+
3
+ const APPROVAL_POLICY_ALIASES: Record<string, ApprovalPolicy> = {
4
+ untrusted: 'untrusted',
5
+ unlessTrusted: 'untrusted',
6
+ 'unless-trusted': 'untrusted',
7
+ 'unless_trusted': 'untrusted',
8
+ 'on-request': 'on-request',
9
+ onRequest: 'on-request',
10
+ on_request: 'on-request',
11
+ 'on-failure': 'on-failure',
12
+ onFailure: 'on-failure',
13
+ on_failure: 'on-failure',
14
+ never: 'never',
15
+ }
16
+
17
+ export const normalizeApprovalPolicy = (value?: string | null): ApprovalPolicy | null => {
18
+ if (!value) {
19
+ return null
20
+ }
21
+ const normalized = APPROVAL_POLICY_ALIASES[value]
22
+ if (normalized) {
23
+ return normalized
24
+ }
25
+ const lower = value.toLowerCase()
26
+ return APPROVAL_POLICY_ALIASES[lower] ?? null
27
+ }
28
+
29
+ export const approvalPolicyLabel = (value: ApprovalPolicy): string => {
30
+ switch (value) {
31
+ case 'untrusted':
32
+ return 'Untrusted'
33
+ case 'on-failure':
34
+ return 'On failure'
35
+ case 'on-request':
36
+ return 'On request'
37
+ case 'never':
38
+ return 'Never'
39
+ }
40
+ }
41
+
42
+ export const approvalPolicyDescription = (value: ApprovalPolicy): string => {
43
+ switch (value) {
44
+ case 'untrusted':
45
+ return 'Always ask before running commands or edits.'
46
+ case 'on-failure':
47
+ return 'Run in sandbox; ask if it fails.'
48
+ case 'on-request':
49
+ return 'Ask before risky commands; auto-run safe reads.'
50
+ case 'never':
51
+ return 'Run without approvals.'
52
+ }
53
+ }
@@ -0,0 +1,41 @@
1
+ export const INIT_PROMPT = `Generate a file named AGENTS.md that serves as a contributor guide for this repository.
2
+ Your goal is to produce a clear, concise, and well-structured document with descriptive headings and actionable explanations for each section.
3
+ Follow the outline below, but adapt as needed -- add sections if relevant, and omit those that do not apply to this project.
4
+
5
+ Document Requirements
6
+
7
+ - Title the document "Repository Guidelines".
8
+ - Use Markdown headings (#, ##, etc.) for structure.
9
+ - Keep the document concise. 200-400 words is optimal.
10
+ - Keep explanations short, direct, and specific to this repository.
11
+ - Provide examples where helpful (commands, directory paths, naming patterns).
12
+ - Maintain a professional, instructional tone.
13
+
14
+ Recommended Sections
15
+
16
+ Project Structure & Module Organization
17
+
18
+ - Outline the project structure, including where the source code, tests, and assets are located.
19
+
20
+ Build, Test, and Development Commands
21
+
22
+ - List key commands for building, testing, and running locally (e.g., npm test, make build).
23
+ - Briefly explain what each command does.
24
+
25
+ Coding Style & Naming Conventions
26
+
27
+ - Specify indentation rules, language-specific style preferences, and naming patterns.
28
+ - Include any formatting or linting tools used.
29
+
30
+ Testing Guidelines
31
+
32
+ - Identify testing frameworks and coverage requirements.
33
+ - State test naming conventions and how to run tests.
34
+
35
+ Commit & Pull Request Guidelines
36
+
37
+ - Summarize commit message conventions found in the project's Git history.
38
+ - Outline pull request requirements (descriptions, linked issues, screenshots, etc.).
39
+
40
+ (Optional) Add other sections if relevant, such as Security & Configuration Tips, Architecture Overview, or Agent-Specific Instructions.
41
+ `
@@ -0,0 +1,170 @@
1
+ import type { Message, MessageKind } from '../types'
2
+
3
+ type ThreadItem = {
4
+ type: string
5
+ id: string
6
+ [key: string]: unknown
7
+ }
8
+
9
+ type CommandAction =
10
+ | { type: 'read'; command: string; name: string; path: string }
11
+ | { type: 'listFiles'; command: string; path?: string | null }
12
+ | { type: 'search'; command: string; query?: string | null; path?: string | null }
13
+ | { type: 'unknown'; command: string }
14
+
15
+ const clampText = (value: string, max = 1400) => {
16
+ if (value.length <= max) {
17
+ return value
18
+ }
19
+ return `${value.slice(0, max)}\n…`
20
+ }
21
+
22
+ const safeStringify = (value: unknown) => {
23
+ try {
24
+ return JSON.stringify(value, null, 2)
25
+ } catch {
26
+ return String(value)
27
+ }
28
+ }
29
+
30
+ const formatFileChanges = (changes: Array<{ path?: unknown; kind?: unknown; diff?: string; movePath?: unknown }>) => {
31
+ const summary = changes
32
+ .map((change) => {
33
+ const path =
34
+ typeof change.path === 'string'
35
+ ? change.path
36
+ : change.path
37
+ ? safeStringify(change.path)
38
+ : 'unknown'
39
+ const kind = typeof change.kind === 'string' ? change.kind : 'update'
40
+ const movePath =
41
+ typeof change.movePath === 'string'
42
+ ? ` -> ${change.movePath}`
43
+ : change.movePath
44
+ ? ` -> ${safeStringify(change.movePath)}`
45
+ : ''
46
+ return `${kind}: ${path}${movePath}`
47
+ })
48
+ .join('\n')
49
+
50
+ const diffPreview = changes
51
+ .map((change) => change.diff ?? '')
52
+ .filter(Boolean)
53
+ .join('\n\n')
54
+
55
+ const content = [summary, diffPreview].filter(Boolean).join('\n\n')
56
+ return clampText(content)
57
+ }
58
+
59
+ const formatCommandActions = (actions: CommandAction[], commandFallback: string) => {
60
+ if (!actions.length) {
61
+ return {
62
+ kind: 'command' as MessageKind,
63
+ title: 'Command',
64
+ content: commandFallback,
65
+ }
66
+ }
67
+
68
+ const primary = actions.find((action) => action.type !== 'unknown') ?? actions[0]
69
+ switch (primary.type) {
70
+ case 'read': {
71
+ const detail = primary.path ? `${primary.name} · ${primary.path}` : primary.name
72
+ return {
73
+ kind: 'tool' as MessageKind,
74
+ title: 'Read',
75
+ content: detail || commandFallback,
76
+ }
77
+ }
78
+ case 'search': {
79
+ const detail = [primary.query, primary.path].filter(Boolean).join(' · ')
80
+ return {
81
+ kind: 'tool' as MessageKind,
82
+ title: 'Search',
83
+ content: detail || commandFallback,
84
+ }
85
+ }
86
+ case 'listFiles': {
87
+ return {
88
+ kind: 'tool' as MessageKind,
89
+ title: 'List',
90
+ content: primary.path || commandFallback,
91
+ }
92
+ }
93
+ default:
94
+ return {
95
+ kind: 'command' as MessageKind,
96
+ title: 'Command',
97
+ content: commandFallback,
98
+ }
99
+ }
100
+ }
101
+
102
+ export const formatThreadItem = (item: ThreadItem): { kind: MessageKind; content: string; title?: string } | null => {
103
+ switch (item.type) {
104
+ case 'reasoning': {
105
+ const summary = Array.isArray(item.summary) ? item.summary.join('\n') : ''
106
+ const content = summary
107
+ return { kind: 'reasoning', content: clampText(content), title: 'Reasoning' }
108
+ }
109
+ case 'commandExecution': {
110
+ const command = typeof item.command === 'string' ? item.command : 'Command'
111
+ const output = typeof item.aggregatedOutput === 'string' ? item.aggregatedOutput : ''
112
+ const status = typeof item.status === 'string' ? item.status : 'inProgress'
113
+ const actions = Array.isArray(item.commandActions) ? (item.commandActions as CommandAction[]) : []
114
+ const actionSummary = formatCommandActions(actions, command)
115
+ const content = output ? `${actionSummary.content}\n\n${output}` : actionSummary.content
116
+ return { kind: actionSummary.kind, content: clampText(content), title: `${actionSummary.title} · ${status}` }
117
+ }
118
+ case 'fileChange': {
119
+ const changes = Array.isArray(item.changes) ? item.changes : []
120
+ const content = formatFileChanges(changes as Array<{ path?: string; kind?: string; diff?: string; movePath?: string }>)
121
+ const status = typeof item.status === 'string' ? item.status : 'inProgress'
122
+ return { kind: 'file', content, title: `Files · ${status}` }
123
+ }
124
+ case 'mcpToolCall': {
125
+ const server = typeof item.server === 'string' ? item.server : 'mcp'
126
+ const tool = typeof item.tool === 'string' ? item.tool : 'tool'
127
+ const args = item.arguments ? safeStringify(item.arguments) : ''
128
+ const result = item.result ? safeStringify(item.result) : ''
129
+ const error = item.error ? safeStringify(item.error) : ''
130
+ const content = [args, result, error].filter(Boolean).join('\n\n')
131
+ return { kind: 'tool', content: clampText(content || `${server}.${tool}`), title: `${server}.${tool}` }
132
+ }
133
+ case 'webSearch': {
134
+ const query = typeof item.query === 'string' ? item.query : 'Search'
135
+ return { kind: 'tool', content: clampText(query), title: 'Web Search' }
136
+ }
137
+ case 'imageView': {
138
+ const path = typeof item.path === 'string' ? item.path : 'Image'
139
+ return { kind: 'tool', content: clampText(path), title: 'Image View' }
140
+ }
141
+ case 'enteredReviewMode': {
142
+ const review = typeof item.review === 'string' ? item.review : 'Review'
143
+ return { kind: 'tool', content: clampText(review), title: 'Review Started' }
144
+ }
145
+ case 'exitedReviewMode': {
146
+ const review = typeof item.review === 'string' ? item.review : 'Review'
147
+ return { kind: 'tool', content: clampText(review, 2400), title: 'Review' }
148
+ }
149
+ case 'compacted': {
150
+ return { kind: 'tool', content: 'Conversation compacted to save context.', title: 'Compaction' }
151
+ }
152
+ default:
153
+ return null
154
+ }
155
+ }
156
+
157
+ export const buildSystemMessage = (item: ThreadItem): Message | null => {
158
+ const formatted = formatThreadItem(item)
159
+ if (!formatted) {
160
+ return null
161
+ }
162
+ return {
163
+ id: item.id,
164
+ role: 'assistant',
165
+ kind: formatted.kind,
166
+ title: formatted.title,
167
+ content: formatted.content,
168
+ timestamp: '',
169
+ }
170
+ }
@@ -0,0 +1,62 @@
1
+ type ParsedArgs = {
2
+ positional: string[]
3
+ named: Record<string, string>
4
+ }
5
+
6
+ const tokenizeArgs = (input: string): string[] => {
7
+ if (!input.trim()) {
8
+ return []
9
+ }
10
+ const tokens: string[] = []
11
+ const regex = /"([^"]*)"|'([^']*)'|([^\s]+)/g
12
+ let match: RegExpExecArray | null
13
+ while ((match = regex.exec(input)) !== null) {
14
+ tokens.push(match[1] ?? match[2] ?? match[3] ?? '')
15
+ }
16
+ return tokens
17
+ }
18
+
19
+ const parseArgs = (input: string): ParsedArgs => {
20
+ const tokens = tokenizeArgs(input)
21
+ const positional: string[] = []
22
+ const named: Record<string, string> = {}
23
+
24
+ tokens.forEach((token) => {
25
+ const eqIndex = token.indexOf('=')
26
+ if (eqIndex > 0) {
27
+ const key = token.slice(0, eqIndex)
28
+ const value = token.slice(eqIndex + 1)
29
+ named[key] = value
30
+ } else {
31
+ positional.push(token)
32
+ }
33
+ })
34
+
35
+ return { positional, named }
36
+ }
37
+
38
+ export const stripPromptFrontmatter = (input: string): string => {
39
+ const trimmed = input.trimStart()
40
+ if (!trimmed.startsWith('---')) {
41
+ return input
42
+ }
43
+ const end = trimmed.indexOf('\n---', 3)
44
+ if (end === -1) {
45
+ return input
46
+ }
47
+ const after = trimmed.slice(end + 4)
48
+ return after.startsWith('\n') ? after.slice(1) : after
49
+ }
50
+
51
+ export const expandPromptTemplate = (template: string, args: string): string => {
52
+ const { positional, named } = parseArgs(args)
53
+ const placeholder = '__CODEX_DOLLAR__'
54
+ let output = template.replace(/\$\$/g, placeholder)
55
+
56
+ output = output.replace(/\$ARGUMENTS/g, positional.join(' '))
57
+ output = output.replace(/\$(\d)/g, (_, digit) => positional[Number(digit) - 1] ?? '')
58
+ output = output.replace(/\$([A-Z][A-Z0-9_]*)/g, (_, key) => named[key] ?? '')
59
+
60
+ output = output.replace(new RegExp(placeholder, 'g'), '$')
61
+ return output
62
+ }
@@ -0,0 +1,48 @@
1
+ import type { ReasoningSummary } from '../types'
2
+
3
+ const SUMMARY_ALIASES: Record<string, ReasoningSummary> = {
4
+ auto: 'auto',
5
+ concise: 'concise',
6
+ detailed: 'detailed',
7
+ none: 'none',
8
+ off: 'none',
9
+ disable: 'none',
10
+ }
11
+
12
+ export const normalizeReasoningSummary = (value?: string | null): ReasoningSummary | null => {
13
+ if (!value) {
14
+ return null
15
+ }
16
+ const normalized = SUMMARY_ALIASES[value]
17
+ if (normalized) {
18
+ return normalized
19
+ }
20
+ const lower = value.toLowerCase()
21
+ return SUMMARY_ALIASES[lower] ?? null
22
+ }
23
+
24
+ export const reasoningSummaryLabel = (value: ReasoningSummary): string => {
25
+ switch (value) {
26
+ case 'auto':
27
+ return 'Auto'
28
+ case 'concise':
29
+ return 'Concise'
30
+ case 'detailed':
31
+ return 'Detailed'
32
+ case 'none':
33
+ return 'None'
34
+ }
35
+ }
36
+
37
+ export const reasoningSummaryDescription = (value: ReasoningSummary): string => {
38
+ switch (value) {
39
+ case 'auto':
40
+ return 'Let the model choose the best summary length.'
41
+ case 'concise':
42
+ return 'Short, readable reasoning summaries.'
43
+ case 'detailed':
44
+ return 'Longer reasoning summaries with extra detail.'
45
+ case 'none':
46
+ return 'Disable reasoning summaries.'
47
+ }
48
+ }
@@ -0,0 +1,98 @@
1
+ export type SlashCommandId =
2
+ | 'model'
3
+ | 'summary'
4
+ | 'cwd'
5
+ | 'approvals'
6
+ | 'skills'
7
+ | 'review'
8
+ | 'new'
9
+ | 'resume'
10
+ | 'init'
11
+ | 'compact'
12
+ | 'diff'
13
+ | 'mention'
14
+ | 'status'
15
+ | 'mcp'
16
+ | 'experimental'
17
+ | 'logout'
18
+ | 'quit'
19
+ | 'exit'
20
+ | 'feedback'
21
+ | `prompts:${string}`
22
+
23
+ export type SlashCommandDefinition = {
24
+ id: SlashCommandId
25
+ description: string
26
+ availableDuringTask: boolean
27
+ }
28
+
29
+ export const SLASH_COMMANDS: SlashCommandDefinition[] = [
30
+ { id: 'model', description: 'choose what model and reasoning effort to use', availableDuringTask: false },
31
+ { id: 'summary', description: 'set reasoning summary length', availableDuringTask: false },
32
+ { id: 'cwd', description: 'set working directory for the thread', availableDuringTask: false },
33
+ { id: 'approvals', description: 'choose what Codex can do without approval', availableDuringTask: false },
34
+ { id: 'skills', description: 'browse and insert skills', availableDuringTask: true },
35
+ { id: 'review', description: 'review my current changes and find issues', availableDuringTask: false },
36
+ { id: 'new', description: 'start a new chat during a conversation', availableDuringTask: false },
37
+ { id: 'resume', description: 'resume a saved chat', availableDuringTask: false },
38
+ { id: 'init', description: 'create an AGENTS.md file with instructions for Codex', availableDuringTask: false },
39
+ { id: 'compact', description: 'summarize conversation to prevent hitting the context limit', availableDuringTask: false },
40
+ { id: 'diff', description: 'show git diff (including untracked files)', availableDuringTask: true },
41
+ { id: 'mention', description: 'mention a file', availableDuringTask: true },
42
+ { id: 'status', description: 'show current session configuration and token usage', availableDuringTask: true },
43
+ { id: 'mcp', description: 'list configured MCP tools', availableDuringTask: true },
44
+ { id: 'experimental', description: 'open experimental menu', availableDuringTask: true },
45
+ { id: 'logout', description: 'log out of Codex', availableDuringTask: false },
46
+ { id: 'quit', description: 'exit Codex', availableDuringTask: true },
47
+ { id: 'exit', description: 'exit Codex', availableDuringTask: true },
48
+ { id: 'feedback', description: 'send logs to maintainers', availableDuringTask: true },
49
+ ]
50
+
51
+ export const filterSlashCommands = (query: string, extra: SlashCommandDefinition[] = []) => {
52
+ const allCommands = [...SLASH_COMMANDS, ...extra]
53
+ if (!query) {
54
+ return allCommands
55
+ }
56
+ const lowered = query.toLowerCase()
57
+ return allCommands.filter((command) => command.id.startsWith(lowered))
58
+ }
59
+
60
+ export const findSlashCommand = (name: string, extra: SlashCommandDefinition[] = []) =>
61
+ [...SLASH_COMMANDS, ...extra].find((command) => command.id === name)
62
+
63
+ export const getSlashQuery = (text: string): string | null => {
64
+ const firstLine = text.split('\n')[0] ?? ''
65
+ if (!firstLine.startsWith('/')) {
66
+ return null
67
+ }
68
+ if (firstLine.startsWith('/ ') || firstLine.startsWith('/\t')) {
69
+ return null
70
+ }
71
+ const raw = firstLine.slice(1)
72
+ const token = raw.split(/\s/)[0]
73
+ return token
74
+ }
75
+
76
+ export const parseSlashInput = (text: string): { name: string; rest: string } | null => {
77
+ const firstLine = text.split('\n')[0] ?? ''
78
+ if (!firstLine.startsWith('/')) {
79
+ return null
80
+ }
81
+ if (firstLine.startsWith('/ ') || firstLine.startsWith('/\t')) {
82
+ return null
83
+ }
84
+ const raw = firstLine.slice(1)
85
+ if (!raw) {
86
+ return { name: '', rest: '' }
87
+ }
88
+ const match = raw.match(/^([^\s]+)\s*(.*)$/)
89
+ if (!match) {
90
+ return null
91
+ }
92
+ const name = match[1]
93
+ const rest = match[2] ?? ''
94
+ if (!name || name.includes('/')) {
95
+ return null
96
+ }
97
+ return { name, rest: rest.trim() }
98
+ }
@@ -0,0 +1,28 @@
1
+ {
2
+ "compilerOptions": {
3
+ "tsBuildInfoFile": "./node_modules/.tmp/tsconfig.app.tsbuildinfo",
4
+ "target": "ES2022",
5
+ "useDefineForClassFields": true,
6
+ "lib": ["ES2022", "DOM", "DOM.Iterable"],
7
+ "module": "ESNext",
8
+ "types": ["vite/client"],
9
+ "skipLibCheck": true,
10
+
11
+ /* Bundler mode */
12
+ "moduleResolution": "bundler",
13
+ "allowImportingTsExtensions": true,
14
+ "verbatimModuleSyntax": true,
15
+ "moduleDetection": "force",
16
+ "noEmit": true,
17
+ "jsx": "react-jsx",
18
+
19
+ /* Linting */
20
+ "strict": true,
21
+ "noUnusedLocals": true,
22
+ "noUnusedParameters": true,
23
+ "erasableSyntaxOnly": true,
24
+ "noFallthroughCasesInSwitch": true,
25
+ "noUncheckedSideEffectImports": true
26
+ },
27
+ "include": ["src"]
28
+ }
@@ -0,0 +1,7 @@
1
+ {
2
+ "files": [],
3
+ "references": [
4
+ { "path": "./tsconfig.app.json" },
5
+ { "path": "./tsconfig.node.json" }
6
+ ]
7
+ }