mcp-codex-worker 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 (462) hide show
  1. package/README.md +135 -0
  2. package/bin/mcp-codex-worker.mjs +17 -0
  3. package/dist/src/app.d.ts +29 -0
  4. package/dist/src/app.js +353 -0
  5. package/dist/src/app.js.map +1 -0
  6. package/dist/src/config/defaults.d.ts +11 -0
  7. package/dist/src/config/defaults.js +12 -0
  8. package/dist/src/config/defaults.js.map +1 -0
  9. package/dist/src/index.d.ts +2 -0
  10. package/dist/src/index.js +64 -0
  11. package/dist/src/index.js.map +1 -0
  12. package/dist/src/mcp/tool-definitions.d.ts +180 -0
  13. package/dist/src/mcp/tool-definitions.js +241 -0
  14. package/dist/src/mcp/tool-definitions.js.map +1 -0
  15. package/dist/src/services/app-server-client.d.ts +65 -0
  16. package/dist/src/services/app-server-client.js +511 -0
  17. package/dist/src/services/app-server-client.js.map +1 -0
  18. package/dist/src/services/codex-runtime.d.ts +84 -0
  19. package/dist/src/services/codex-runtime.js +371 -0
  20. package/dist/src/services/codex-runtime.js.map +1 -0
  21. package/dist/src/services/fleet-mode.d.ts +3 -0
  22. package/dist/src/services/fleet-mode.js +21 -0
  23. package/dist/src/services/fleet-mode.js.map +1 -0
  24. package/dist/src/services/model-catalog.d.ts +22 -0
  25. package/dist/src/services/model-catalog.js +51 -0
  26. package/dist/src/services/model-catalog.js.map +1 -0
  27. package/dist/src/services/profile-manager.d.ts +29 -0
  28. package/dist/src/services/profile-manager.js +82 -0
  29. package/dist/src/services/profile-manager.js.map +1 -0
  30. package/dist/src/types/codex.d.ts +50 -0
  31. package/dist/src/types/codex.js +2 -0
  32. package/dist/src/types/codex.js.map +1 -0
  33. package/package.json +53 -0
  34. package/src/app.ts +417 -0
  35. package/src/config/defaults.ts +14 -0
  36. package/src/index.ts +84 -0
  37. package/src/mcp/tool-definitions.ts +280 -0
  38. package/src/protocol/AbsolutePathBuf.ts +14 -0
  39. package/src/protocol/AgentPath.ts +5 -0
  40. package/src/protocol/ApplyPatchApprovalParams.ts +21 -0
  41. package/src/protocol/ApplyPatchApprovalResponse.ts +6 -0
  42. package/src/protocol/AuthMode.ts +8 -0
  43. package/src/protocol/ClientInfo.ts +5 -0
  44. package/src/protocol/ClientNotification.ts +5 -0
  45. package/src/protocol/ClientRequest.ts +67 -0
  46. package/src/protocol/CollaborationMode.ts +10 -0
  47. package/src/protocol/ContentItem.ts +5 -0
  48. package/src/protocol/ConversationGitInfo.ts +5 -0
  49. package/src/protocol/ConversationSummary.ts +8 -0
  50. package/src/protocol/ExecCommandApprovalParams.ts +16 -0
  51. package/src/protocol/ExecCommandApprovalResponse.ts +6 -0
  52. package/src/protocol/ExecPolicyAmendment.ts +12 -0
  53. package/src/protocol/FileChange.ts +5 -0
  54. package/src/protocol/ForcedLoginMethod.ts +5 -0
  55. package/src/protocol/FunctionCallOutputBody.ts +6 -0
  56. package/src/protocol/FunctionCallOutputContentItem.ts +10 -0
  57. package/src/protocol/FuzzyFileSearchMatchType.ts +5 -0
  58. package/src/protocol/FuzzyFileSearchParams.ts +5 -0
  59. package/src/protocol/FuzzyFileSearchResponse.ts +6 -0
  60. package/src/protocol/FuzzyFileSearchResult.ts +9 -0
  61. package/src/protocol/FuzzyFileSearchSessionCompletedNotification.ts +5 -0
  62. package/src/protocol/FuzzyFileSearchSessionUpdatedNotification.ts +6 -0
  63. package/src/protocol/GetAuthStatusParams.ts +5 -0
  64. package/src/protocol/GetAuthStatusResponse.ts +6 -0
  65. package/src/protocol/GetConversationSummaryParams.ts +6 -0
  66. package/src/protocol/GetConversationSummaryResponse.ts +6 -0
  67. package/src/protocol/GhostCommit.ts +8 -0
  68. package/src/protocol/GitDiffToRemoteParams.ts +5 -0
  69. package/src/protocol/GitDiffToRemoteResponse.ts +6 -0
  70. package/src/protocol/GitSha.ts +5 -0
  71. package/src/protocol/ImageDetail.ts +5 -0
  72. package/src/protocol/InitializeCapabilities.ts +17 -0
  73. package/src/protocol/InitializeParams.ts +7 -0
  74. package/src/protocol/InitializeResponse.ts +20 -0
  75. package/src/protocol/InputModality.ts +8 -0
  76. package/src/protocol/LocalShellAction.ts +6 -0
  77. package/src/protocol/LocalShellExecAction.ts +5 -0
  78. package/src/protocol/LocalShellStatus.ts +5 -0
  79. package/src/protocol/MessagePhase.ts +11 -0
  80. package/src/protocol/ModeKind.ts +8 -0
  81. package/src/protocol/NetworkPolicyAmendment.ts +6 -0
  82. package/src/protocol/NetworkPolicyRuleAction.ts +5 -0
  83. package/src/protocol/ParsedCommand.ts +12 -0
  84. package/src/protocol/Personality.ts +5 -0
  85. package/src/protocol/PlanType.ts +5 -0
  86. package/src/protocol/RealtimeConversationVersion.ts +5 -0
  87. package/src/protocol/ReasoningEffort.ts +8 -0
  88. package/src/protocol/ReasoningItemContent.ts +5 -0
  89. package/src/protocol/ReasoningItemReasoningSummary.ts +5 -0
  90. package/src/protocol/ReasoningSummary.ts +10 -0
  91. package/src/protocol/RequestId.ts +5 -0
  92. package/src/protocol/Resource.ts +9 -0
  93. package/src/protocol/ResourceTemplate.ts +9 -0
  94. package/src/protocol/ResponseItem.ts +18 -0
  95. package/src/protocol/ReviewDecision.ts +10 -0
  96. package/src/protocol/ServerNotification.ts +60 -0
  97. package/src/protocol/ServerRequest.ts +18 -0
  98. package/src/protocol/ServiceTier.ts +5 -0
  99. package/src/protocol/SessionSource.ts +6 -0
  100. package/src/protocol/Settings.ts +9 -0
  101. package/src/protocol/SubAgentSource.ts +7 -0
  102. package/src/protocol/ThreadId.ts +5 -0
  103. package/src/protocol/Tool.ts +9 -0
  104. package/src/protocol/Verbosity.ts +9 -0
  105. package/src/protocol/WebSearchAction.ts +5 -0
  106. package/src/protocol/WebSearchContextSize.ts +5 -0
  107. package/src/protocol/WebSearchLocation.ts +5 -0
  108. package/src/protocol/WebSearchMode.ts +5 -0
  109. package/src/protocol/WebSearchToolConfig.ts +7 -0
  110. package/src/protocol/index.ts +75 -0
  111. package/src/protocol/serde_json/JsonValue.ts +5 -0
  112. package/src/protocol/v2/Account.ts +6 -0
  113. package/src/protocol/v2/AccountLoginCompletedNotification.ts +5 -0
  114. package/src/protocol/v2/AccountRateLimitsUpdatedNotification.ts +6 -0
  115. package/src/protocol/v2/AccountUpdatedNotification.ts +7 -0
  116. package/src/protocol/v2/AdditionalFileSystemPermissions.ts +6 -0
  117. package/src/protocol/v2/AdditionalNetworkPermissions.ts +5 -0
  118. package/src/protocol/v2/AdditionalPermissionProfile.ts +7 -0
  119. package/src/protocol/v2/AgentMessageDeltaNotification.ts +5 -0
  120. package/src/protocol/v2/AnalyticsConfig.ts +6 -0
  121. package/src/protocol/v2/AppBranding.ts +8 -0
  122. package/src/protocol/v2/AppInfo.ts +19 -0
  123. package/src/protocol/v2/AppListUpdatedNotification.ts +9 -0
  124. package/src/protocol/v2/AppMetadata.ts +7 -0
  125. package/src/protocol/v2/AppReview.ts +5 -0
  126. package/src/protocol/v2/AppScreenshot.ts +5 -0
  127. package/src/protocol/v2/AppSummary.ts +8 -0
  128. package/src/protocol/v2/AppToolApproval.ts +5 -0
  129. package/src/protocol/v2/AppToolsConfig.ts +6 -0
  130. package/src/protocol/v2/ApprovalsReviewer.ts +12 -0
  131. package/src/protocol/v2/AppsConfig.ts +8 -0
  132. package/src/protocol/v2/AppsDefaultConfig.ts +5 -0
  133. package/src/protocol/v2/AppsListParams.ts +24 -0
  134. package/src/protocol/v2/AppsListResponse.ts +14 -0
  135. package/src/protocol/v2/AskForApproval.ts +5 -0
  136. package/src/protocol/v2/ByteRange.ts +5 -0
  137. package/src/protocol/v2/CancelLoginAccountParams.ts +5 -0
  138. package/src/protocol/v2/CancelLoginAccountResponse.ts +6 -0
  139. package/src/protocol/v2/CancelLoginAccountStatus.ts +5 -0
  140. package/src/protocol/v2/ChatgptAuthTokensRefreshParams.ts +16 -0
  141. package/src/protocol/v2/ChatgptAuthTokensRefreshReason.ts +5 -0
  142. package/src/protocol/v2/ChatgptAuthTokensRefreshResponse.ts +5 -0
  143. package/src/protocol/v2/CodexErrorInfo.ts +12 -0
  144. package/src/protocol/v2/CollabAgentState.ts +6 -0
  145. package/src/protocol/v2/CollabAgentStatus.ts +5 -0
  146. package/src/protocol/v2/CollabAgentTool.ts +5 -0
  147. package/src/protocol/v2/CollabAgentToolCallStatus.ts +5 -0
  148. package/src/protocol/v2/CollaborationModeMask.ts +10 -0
  149. package/src/protocol/v2/CommandAction.ts +5 -0
  150. package/src/protocol/v2/CommandExecOutputDeltaNotification.ts +30 -0
  151. package/src/protocol/v2/CommandExecOutputStream.ts +8 -0
  152. package/src/protocol/v2/CommandExecParams.ts +97 -0
  153. package/src/protocol/v2/CommandExecResizeParams.ts +18 -0
  154. package/src/protocol/v2/CommandExecResizeResponse.ts +8 -0
  155. package/src/protocol/v2/CommandExecResponse.ts +24 -0
  156. package/src/protocol/v2/CommandExecTerminalSize.ts +16 -0
  157. package/src/protocol/v2/CommandExecTerminateParams.ts +13 -0
  158. package/src/protocol/v2/CommandExecTerminateResponse.ts +8 -0
  159. package/src/protocol/v2/CommandExecWriteParams.ts +22 -0
  160. package/src/protocol/v2/CommandExecWriteResponse.ts +8 -0
  161. package/src/protocol/v2/CommandExecutionApprovalDecision.ts +7 -0
  162. package/src/protocol/v2/CommandExecutionOutputDeltaNotification.ts +5 -0
  163. package/src/protocol/v2/CommandExecutionRequestApprovalParams.ts +57 -0
  164. package/src/protocol/v2/CommandExecutionRequestApprovalResponse.ts +6 -0
  165. package/src/protocol/v2/CommandExecutionSource.ts +5 -0
  166. package/src/protocol/v2/CommandExecutionStatus.ts +5 -0
  167. package/src/protocol/v2/Config.ts +23 -0
  168. package/src/protocol/v2/ConfigBatchWriteParams.ts +14 -0
  169. package/src/protocol/v2/ConfigEdit.ts +7 -0
  170. package/src/protocol/v2/ConfigLayer.ts +7 -0
  171. package/src/protocol/v2/ConfigLayerMetadata.ts +6 -0
  172. package/src/protocol/v2/ConfigLayerSource.ts +16 -0
  173. package/src/protocol/v2/ConfigReadParams.ts +11 -0
  174. package/src/protocol/v2/ConfigReadResponse.ts +8 -0
  175. package/src/protocol/v2/ConfigRequirements.ts +9 -0
  176. package/src/protocol/v2/ConfigRequirementsReadResponse.ts +10 -0
  177. package/src/protocol/v2/ConfigValueWriteParams.ts +11 -0
  178. package/src/protocol/v2/ConfigWarningNotification.ts +22 -0
  179. package/src/protocol/v2/ConfigWriteResponse.ts +12 -0
  180. package/src/protocol/v2/ContextCompactedNotification.ts +8 -0
  181. package/src/protocol/v2/CreditsSnapshot.ts +5 -0
  182. package/src/protocol/v2/DeprecationNoticeNotification.ts +13 -0
  183. package/src/protocol/v2/DynamicToolCallOutputContentItem.ts +5 -0
  184. package/src/protocol/v2/DynamicToolCallParams.ts +6 -0
  185. package/src/protocol/v2/DynamicToolCallResponse.ts +6 -0
  186. package/src/protocol/v2/DynamicToolCallStatus.ts +5 -0
  187. package/src/protocol/v2/DynamicToolSpec.ts +6 -0
  188. package/src/protocol/v2/ErrorNotification.ts +6 -0
  189. package/src/protocol/v2/ExecPolicyAmendment.ts +5 -0
  190. package/src/protocol/v2/ExperimentalFeature.ts +37 -0
  191. package/src/protocol/v2/ExperimentalFeatureEnablementSetParams.ts +12 -0
  192. package/src/protocol/v2/ExperimentalFeatureEnablementSetResponse.ts +9 -0
  193. package/src/protocol/v2/ExperimentalFeatureListParams.ts +13 -0
  194. package/src/protocol/v2/ExperimentalFeatureListResponse.ts +11 -0
  195. package/src/protocol/v2/ExperimentalFeatureStage.ts +5 -0
  196. package/src/protocol/v2/ExternalAgentConfigDetectParams.ts +13 -0
  197. package/src/protocol/v2/ExternalAgentConfigDetectResponse.ts +6 -0
  198. package/src/protocol/v2/ExternalAgentConfigImportParams.ts +6 -0
  199. package/src/protocol/v2/ExternalAgentConfigImportResponse.ts +5 -0
  200. package/src/protocol/v2/ExternalAgentConfigMigrationItem.ts +10 -0
  201. package/src/protocol/v2/ExternalAgentConfigMigrationItemType.ts +5 -0
  202. package/src/protocol/v2/FeedbackUploadParams.ts +5 -0
  203. package/src/protocol/v2/FeedbackUploadResponse.ts +5 -0
  204. package/src/protocol/v2/FileChangeApprovalDecision.ts +5 -0
  205. package/src/protocol/v2/FileChangeOutputDeltaNotification.ts +5 -0
  206. package/src/protocol/v2/FileChangeRequestApprovalParams.ts +14 -0
  207. package/src/protocol/v2/FileChangeRequestApprovalResponse.ts +6 -0
  208. package/src/protocol/v2/FileUpdateChange.ts +6 -0
  209. package/src/protocol/v2/FsChangedNotification.ts +17 -0
  210. package/src/protocol/v2/FsCopyParams.ts +21 -0
  211. package/src/protocol/v2/FsCopyResponse.ts +8 -0
  212. package/src/protocol/v2/FsCreateDirectoryParams.ts +17 -0
  213. package/src/protocol/v2/FsCreateDirectoryResponse.ts +8 -0
  214. package/src/protocol/v2/FsGetMetadataParams.ts +13 -0
  215. package/src/protocol/v2/FsGetMetadataResponse.ts +24 -0
  216. package/src/protocol/v2/FsReadDirectoryEntry.ts +20 -0
  217. package/src/protocol/v2/FsReadDirectoryParams.ts +13 -0
  218. package/src/protocol/v2/FsReadDirectoryResponse.ts +13 -0
  219. package/src/protocol/v2/FsReadFileParams.ts +13 -0
  220. package/src/protocol/v2/FsReadFileResponse.ts +12 -0
  221. package/src/protocol/v2/FsRemoveParams.ts +21 -0
  222. package/src/protocol/v2/FsRemoveResponse.ts +8 -0
  223. package/src/protocol/v2/FsUnwatchParams.ts +12 -0
  224. package/src/protocol/v2/FsUnwatchResponse.ts +8 -0
  225. package/src/protocol/v2/FsWatchParams.ts +13 -0
  226. package/src/protocol/v2/FsWatchResponse.ts +17 -0
  227. package/src/protocol/v2/FsWriteFileParams.ts +17 -0
  228. package/src/protocol/v2/FsWriteFileResponse.ts +8 -0
  229. package/src/protocol/v2/GetAccountParams.ts +13 -0
  230. package/src/protocol/v2/GetAccountRateLimitsResponse.ts +14 -0
  231. package/src/protocol/v2/GetAccountResponse.ts +6 -0
  232. package/src/protocol/v2/GitInfo.ts +5 -0
  233. package/src/protocol/v2/GrantedPermissionProfile.ts +7 -0
  234. package/src/protocol/v2/GuardianApprovalReview.ts +12 -0
  235. package/src/protocol/v2/GuardianApprovalReviewStatus.ts +8 -0
  236. package/src/protocol/v2/GuardianRiskLevel.ts +8 -0
  237. package/src/protocol/v2/HookCompletedNotification.ts +6 -0
  238. package/src/protocol/v2/HookEventName.ts +5 -0
  239. package/src/protocol/v2/HookExecutionMode.ts +5 -0
  240. package/src/protocol/v2/HookHandlerType.ts +5 -0
  241. package/src/protocol/v2/HookOutputEntry.ts +6 -0
  242. package/src/protocol/v2/HookOutputEntryKind.ts +5 -0
  243. package/src/protocol/v2/HookPromptFragment.ts +5 -0
  244. package/src/protocol/v2/HookRunStatus.ts +5 -0
  245. package/src/protocol/v2/HookRunSummary.ts +11 -0
  246. package/src/protocol/v2/HookScope.ts +5 -0
  247. package/src/protocol/v2/HookStartedNotification.ts +6 -0
  248. package/src/protocol/v2/ItemCompletedNotification.ts +6 -0
  249. package/src/protocol/v2/ItemGuardianApprovalReviewCompletedNotification.ts +15 -0
  250. package/src/protocol/v2/ItemGuardianApprovalReviewStartedNotification.ts +15 -0
  251. package/src/protocol/v2/ItemStartedNotification.ts +6 -0
  252. package/src/protocol/v2/ListMcpServerStatusParams.ts +13 -0
  253. package/src/protocol/v2/ListMcpServerStatusResponse.ts +11 -0
  254. package/src/protocol/v2/LoginAccountParams.ts +21 -0
  255. package/src/protocol/v2/LoginAccountResponse.ts +17 -0
  256. package/src/protocol/v2/LogoutAccountResponse.ts +5 -0
  257. package/src/protocol/v2/MarketplaceInterface.ts +5 -0
  258. package/src/protocol/v2/MarketplaceLoadErrorInfo.ts +6 -0
  259. package/src/protocol/v2/McpAuthStatus.ts +5 -0
  260. package/src/protocol/v2/McpElicitationArrayType.ts +5 -0
  261. package/src/protocol/v2/McpElicitationBooleanSchema.ts +6 -0
  262. package/src/protocol/v2/McpElicitationBooleanType.ts +5 -0
  263. package/src/protocol/v2/McpElicitationConstOption.ts +5 -0
  264. package/src/protocol/v2/McpElicitationEnumSchema.ts +8 -0
  265. package/src/protocol/v2/McpElicitationLegacyTitledEnumSchema.ts +6 -0
  266. package/src/protocol/v2/McpElicitationMultiSelectEnumSchema.ts +7 -0
  267. package/src/protocol/v2/McpElicitationNumberSchema.ts +6 -0
  268. package/src/protocol/v2/McpElicitationNumberType.ts +5 -0
  269. package/src/protocol/v2/McpElicitationObjectType.ts +5 -0
  270. package/src/protocol/v2/McpElicitationPrimitiveSchema.ts +9 -0
  271. package/src/protocol/v2/McpElicitationSchema.ts +13 -0
  272. package/src/protocol/v2/McpElicitationSingleSelectEnumSchema.ts +7 -0
  273. package/src/protocol/v2/McpElicitationStringFormat.ts +5 -0
  274. package/src/protocol/v2/McpElicitationStringSchema.ts +7 -0
  275. package/src/protocol/v2/McpElicitationStringType.ts +5 -0
  276. package/src/protocol/v2/McpElicitationTitledEnumItems.ts +6 -0
  277. package/src/protocol/v2/McpElicitationTitledMultiSelectEnumSchema.ts +7 -0
  278. package/src/protocol/v2/McpElicitationTitledSingleSelectEnumSchema.ts +7 -0
  279. package/src/protocol/v2/McpElicitationUntitledEnumItems.ts +6 -0
  280. package/src/protocol/v2/McpElicitationUntitledMultiSelectEnumSchema.ts +7 -0
  281. package/src/protocol/v2/McpElicitationUntitledSingleSelectEnumSchema.ts +6 -0
  282. package/src/protocol/v2/McpServerElicitationAction.ts +5 -0
  283. package/src/protocol/v2/McpServerElicitationRequestParams.ts +16 -0
  284. package/src/protocol/v2/McpServerElicitationRequestResponse.ts +17 -0
  285. package/src/protocol/v2/McpServerOauthLoginCompletedNotification.ts +5 -0
  286. package/src/protocol/v2/McpServerOauthLoginParams.ts +5 -0
  287. package/src/protocol/v2/McpServerOauthLoginResponse.ts +5 -0
  288. package/src/protocol/v2/McpServerRefreshResponse.ts +5 -0
  289. package/src/protocol/v2/McpServerStartupState.ts +5 -0
  290. package/src/protocol/v2/McpServerStatus.ts +9 -0
  291. package/src/protocol/v2/McpServerStatusUpdatedNotification.ts +6 -0
  292. package/src/protocol/v2/McpToolCallError.ts +5 -0
  293. package/src/protocol/v2/McpToolCallProgressNotification.ts +5 -0
  294. package/src/protocol/v2/McpToolCallResult.ts +6 -0
  295. package/src/protocol/v2/McpToolCallStatus.ts +5 -0
  296. package/src/protocol/v2/MemoryCitation.ts +6 -0
  297. package/src/protocol/v2/MemoryCitationEntry.ts +5 -0
  298. package/src/protocol/v2/MergeStrategy.ts +5 -0
  299. package/src/protocol/v2/Model.ts +10 -0
  300. package/src/protocol/v2/ModelAvailabilityNux.ts +5 -0
  301. package/src/protocol/v2/ModelListParams.ts +17 -0
  302. package/src/protocol/v2/ModelListResponse.ts +11 -0
  303. package/src/protocol/v2/ModelRerouteReason.ts +5 -0
  304. package/src/protocol/v2/ModelReroutedNotification.ts +6 -0
  305. package/src/protocol/v2/ModelUpgradeInfo.ts +5 -0
  306. package/src/protocol/v2/NetworkAccess.ts +5 -0
  307. package/src/protocol/v2/NetworkApprovalContext.ts +6 -0
  308. package/src/protocol/v2/NetworkApprovalProtocol.ts +5 -0
  309. package/src/protocol/v2/NetworkDomainPermission.ts +5 -0
  310. package/src/protocol/v2/NetworkPolicyAmendment.ts +6 -0
  311. package/src/protocol/v2/NetworkPolicyRuleAction.ts +5 -0
  312. package/src/protocol/v2/NetworkRequirements.ts +32 -0
  313. package/src/protocol/v2/NetworkUnixSocketPermission.ts +5 -0
  314. package/src/protocol/v2/NonSteerableTurnKind.ts +5 -0
  315. package/src/protocol/v2/OverriddenMetadata.ts +7 -0
  316. package/src/protocol/v2/PatchApplyStatus.ts +5 -0
  317. package/src/protocol/v2/PatchChangeKind.ts +5 -0
  318. package/src/protocol/v2/PermissionGrantScope.ts +5 -0
  319. package/src/protocol/v2/PermissionsRequestApprovalParams.ts +6 -0
  320. package/src/protocol/v2/PermissionsRequestApprovalResponse.ts +7 -0
  321. package/src/protocol/v2/PlanDeltaNotification.ts +9 -0
  322. package/src/protocol/v2/PluginAuthPolicy.ts +5 -0
  323. package/src/protocol/v2/PluginDetail.ts +9 -0
  324. package/src/protocol/v2/PluginInstallParams.ts +10 -0
  325. package/src/protocol/v2/PluginInstallPolicy.ts +5 -0
  326. package/src/protocol/v2/PluginInstallResponse.ts +7 -0
  327. package/src/protocol/v2/PluginInterface.ts +11 -0
  328. package/src/protocol/v2/PluginListParams.ts +16 -0
  329. package/src/protocol/v2/PluginListResponse.ts +7 -0
  330. package/src/protocol/v2/PluginMarketplaceEntry.ts +8 -0
  331. package/src/protocol/v2/PluginReadParams.ts +6 -0
  332. package/src/protocol/v2/PluginReadResponse.ts +6 -0
  333. package/src/protocol/v2/PluginSource.ts +6 -0
  334. package/src/protocol/v2/PluginSummary.ts +9 -0
  335. package/src/protocol/v2/PluginUninstallParams.ts +9 -0
  336. package/src/protocol/v2/PluginUninstallResponse.ts +5 -0
  337. package/src/protocol/v2/ProfileV2.ts +19 -0
  338. package/src/protocol/v2/RateLimitSnapshot.ts +8 -0
  339. package/src/protocol/v2/RateLimitWindow.ts +5 -0
  340. package/src/protocol/v2/RawResponseItemCompletedNotification.ts +6 -0
  341. package/src/protocol/v2/ReadOnlyAccess.ts +6 -0
  342. package/src/protocol/v2/ReasoningEffortOption.ts +6 -0
  343. package/src/protocol/v2/ReasoningSummaryPartAddedNotification.ts +5 -0
  344. package/src/protocol/v2/ReasoningSummaryTextDeltaNotification.ts +5 -0
  345. package/src/protocol/v2/ReasoningTextDeltaNotification.ts +5 -0
  346. package/src/protocol/v2/RequestPermissionProfile.ts +7 -0
  347. package/src/protocol/v2/ResidencyRequirement.ts +5 -0
  348. package/src/protocol/v2/ReviewDelivery.ts +5 -0
  349. package/src/protocol/v2/ReviewStartParams.ts +12 -0
  350. package/src/protocol/v2/ReviewStartResponse.ts +13 -0
  351. package/src/protocol/v2/ReviewTarget.ts +9 -0
  352. package/src/protocol/v2/SandboxMode.ts +5 -0
  353. package/src/protocol/v2/SandboxPolicy.ts +8 -0
  354. package/src/protocol/v2/SandboxWorkspaceWrite.ts +5 -0
  355. package/src/protocol/v2/ServerRequestResolvedNotification.ts +6 -0
  356. package/src/protocol/v2/SessionSource.ts +6 -0
  357. package/src/protocol/v2/SkillDependencies.ts +6 -0
  358. package/src/protocol/v2/SkillErrorInfo.ts +5 -0
  359. package/src/protocol/v2/SkillInterface.ts +5 -0
  360. package/src/protocol/v2/SkillMetadata.ts +12 -0
  361. package/src/protocol/v2/SkillScope.ts +5 -0
  362. package/src/protocol/v2/SkillSummary.ts +6 -0
  363. package/src/protocol/v2/SkillToolDependency.ts +5 -0
  364. package/src/protocol/v2/SkillsChangedNotification.ts +11 -0
  365. package/src/protocol/v2/SkillsConfigWriteParams.ts +14 -0
  366. package/src/protocol/v2/SkillsConfigWriteResponse.ts +5 -0
  367. package/src/protocol/v2/SkillsListEntry.ts +7 -0
  368. package/src/protocol/v2/SkillsListExtraRootsForCwd.ts +5 -0
  369. package/src/protocol/v2/SkillsListParams.ts +18 -0
  370. package/src/protocol/v2/SkillsListResponse.ts +6 -0
  371. package/src/protocol/v2/TerminalInteractionNotification.ts +5 -0
  372. package/src/protocol/v2/TextElement.ts +14 -0
  373. package/src/protocol/v2/TextPosition.ts +13 -0
  374. package/src/protocol/v2/TextRange.ts +6 -0
  375. package/src/protocol/v2/Thread.ts +72 -0
  376. package/src/protocol/v2/ThreadActiveFlag.ts +5 -0
  377. package/src/protocol/v2/ThreadArchiveParams.ts +5 -0
  378. package/src/protocol/v2/ThreadArchiveResponse.ts +5 -0
  379. package/src/protocol/v2/ThreadArchivedNotification.ts +5 -0
  380. package/src/protocol/v2/ThreadClosedNotification.ts +5 -0
  381. package/src/protocol/v2/ThreadCompactStartParams.ts +5 -0
  382. package/src/protocol/v2/ThreadCompactStartResponse.ts +5 -0
  383. package/src/protocol/v2/ThreadForkParams.ts +34 -0
  384. package/src/protocol/v2/ThreadForkResponse.ts +15 -0
  385. package/src/protocol/v2/ThreadItem.ts +100 -0
  386. package/src/protocol/v2/ThreadListParams.ts +43 -0
  387. package/src/protocol/v2/ThreadListResponse.ts +11 -0
  388. package/src/protocol/v2/ThreadLoadedListParams.ts +13 -0
  389. package/src/protocol/v2/ThreadLoadedListResponse.ts +14 -0
  390. package/src/protocol/v2/ThreadMetadataGitInfoUpdateParams.ts +20 -0
  391. package/src/protocol/v2/ThreadMetadataUpdateParams.ts +12 -0
  392. package/src/protocol/v2/ThreadMetadataUpdateResponse.ts +6 -0
  393. package/src/protocol/v2/ThreadNameUpdatedNotification.ts +5 -0
  394. package/src/protocol/v2/ThreadReadParams.ts +9 -0
  395. package/src/protocol/v2/ThreadReadResponse.ts +6 -0
  396. package/src/protocol/v2/ThreadRealtimeAudioChunk.ts +8 -0
  397. package/src/protocol/v2/ThreadRealtimeClosedNotification.ts +8 -0
  398. package/src/protocol/v2/ThreadRealtimeErrorNotification.ts +8 -0
  399. package/src/protocol/v2/ThreadRealtimeItemAddedNotification.ts +9 -0
  400. package/src/protocol/v2/ThreadRealtimeOutputAudioDeltaNotification.ts +9 -0
  401. package/src/protocol/v2/ThreadRealtimeStartedNotification.ts +9 -0
  402. package/src/protocol/v2/ThreadRealtimeTranscriptUpdatedNotification.ts +9 -0
  403. package/src/protocol/v2/ThreadResumeParams.ts +43 -0
  404. package/src/protocol/v2/ThreadResumeResponse.ts +15 -0
  405. package/src/protocol/v2/ThreadRollbackParams.ts +12 -0
  406. package/src/protocol/v2/ThreadRollbackResponse.ts +14 -0
  407. package/src/protocol/v2/ThreadSetNameParams.ts +5 -0
  408. package/src/protocol/v2/ThreadSetNameResponse.ts +5 -0
  409. package/src/protocol/v2/ThreadShellCommandParams.ts +12 -0
  410. package/src/protocol/v2/ThreadShellCommandResponse.ts +5 -0
  411. package/src/protocol/v2/ThreadSortKey.ts +5 -0
  412. package/src/protocol/v2/ThreadSourceKind.ts +5 -0
  413. package/src/protocol/v2/ThreadStartParams.ts +23 -0
  414. package/src/protocol/v2/ThreadStartResponse.ts +15 -0
  415. package/src/protocol/v2/ThreadStartedNotification.ts +6 -0
  416. package/src/protocol/v2/ThreadStatus.ts +6 -0
  417. package/src/protocol/v2/ThreadStatusChangedNotification.ts +6 -0
  418. package/src/protocol/v2/ThreadTokenUsage.ts +6 -0
  419. package/src/protocol/v2/ThreadTokenUsageUpdatedNotification.ts +6 -0
  420. package/src/protocol/v2/ThreadUnarchiveParams.ts +5 -0
  421. package/src/protocol/v2/ThreadUnarchiveResponse.ts +6 -0
  422. package/src/protocol/v2/ThreadUnarchivedNotification.ts +5 -0
  423. package/src/protocol/v2/ThreadUnsubscribeParams.ts +5 -0
  424. package/src/protocol/v2/ThreadUnsubscribeResponse.ts +6 -0
  425. package/src/protocol/v2/ThreadUnsubscribeStatus.ts +5 -0
  426. package/src/protocol/v2/TokenUsageBreakdown.ts +5 -0
  427. package/src/protocol/v2/ToolRequestUserInputAnswer.ts +8 -0
  428. package/src/protocol/v2/ToolRequestUserInputOption.ts +8 -0
  429. package/src/protocol/v2/ToolRequestUserInputParams.ts +9 -0
  430. package/src/protocol/v2/ToolRequestUserInputQuestion.ts +9 -0
  431. package/src/protocol/v2/ToolRequestUserInputResponse.ts +9 -0
  432. package/src/protocol/v2/ToolsV2.ts +6 -0
  433. package/src/protocol/v2/Turn.ts +18 -0
  434. package/src/protocol/v2/TurnCompletedNotification.ts +6 -0
  435. package/src/protocol/v2/TurnDiffUpdatedNotification.ts +9 -0
  436. package/src/protocol/v2/TurnError.ts +6 -0
  437. package/src/protocol/v2/TurnInterruptParams.ts +5 -0
  438. package/src/protocol/v2/TurnInterruptResponse.ts +5 -0
  439. package/src/protocol/v2/TurnPlanStep.ts +6 -0
  440. package/src/protocol/v2/TurnPlanStepStatus.ts +5 -0
  441. package/src/protocol/v2/TurnPlanUpdatedNotification.ts +6 -0
  442. package/src/protocol/v2/TurnStartParams.ts +54 -0
  443. package/src/protocol/v2/TurnStartResponse.ts +6 -0
  444. package/src/protocol/v2/TurnStartedNotification.ts +6 -0
  445. package/src/protocol/v2/TurnStatus.ts +5 -0
  446. package/src/protocol/v2/TurnSteerParams.ts +11 -0
  447. package/src/protocol/v2/TurnSteerResponse.ts +5 -0
  448. package/src/protocol/v2/UserInput.ts +10 -0
  449. package/src/protocol/v2/WebSearchAction.ts +5 -0
  450. package/src/protocol/v2/WindowsSandboxSetupCompletedNotification.ts +6 -0
  451. package/src/protocol/v2/WindowsSandboxSetupMode.ts +5 -0
  452. package/src/protocol/v2/WindowsSandboxSetupStartParams.ts +7 -0
  453. package/src/protocol/v2/WindowsSandboxSetupStartResponse.ts +5 -0
  454. package/src/protocol/v2/WindowsWorldWritableWarningNotification.ts +5 -0
  455. package/src/protocol/v2/WriteStatus.ts +5 -0
  456. package/src/protocol/v2/index.ts +346 -0
  457. package/src/services/app-server-client.ts +636 -0
  458. package/src/services/codex-runtime.ts +500 -0
  459. package/src/services/fleet-mode.ts +29 -0
  460. package/src/services/model-catalog.ts +86 -0
  461. package/src/services/profile-manager.ts +113 -0
  462. package/src/types/codex.ts +57 -0
@@ -0,0 +1,636 @@
1
+ import { EventEmitter } from 'node:events';
2
+ import { spawn, type ChildProcessWithoutNullStreams } from 'node:child_process';
3
+
4
+ import {
5
+ APP_NAME,
6
+ APP_TITLE,
7
+ OPERATION_BRIDGE_TIMEOUT_MS,
8
+ OPERATION_POLL_INTERVAL_MS,
9
+ REQUEST_TIMEOUT_MS,
10
+ } from '../config/defaults.js';
11
+ import type {
12
+ InitializeParams,
13
+ JsonLineMessage,
14
+ JsonLineNotification,
15
+ JsonLineRequest,
16
+ JsonLineResponse,
17
+ PendingServerRequest,
18
+ RequestId,
19
+ RuntimeOperation,
20
+ } from '../types/codex.js';
21
+
22
+ interface PendingRequestBinding {
23
+ resolve: (value: unknown) => void;
24
+ reject: (reason?: unknown) => void;
25
+ timeout: NodeJS.Timeout;
26
+ }
27
+
28
+ interface RequestOptions {
29
+ timeoutMs?: number | undefined;
30
+ }
31
+
32
+ interface RequestWithBridgeOptions extends RequestOptions {
33
+ threadId?: string | undefined;
34
+ bridgeTimeoutMs?: number | undefined;
35
+ }
36
+
37
+ interface WaitOptions {
38
+ timeoutMs?: number | undefined;
39
+ pollIntervalMs?: number | undefined;
40
+ }
41
+
42
+ export interface AppServerClientOptions {
43
+ command: string;
44
+ args: string[];
45
+ env: NodeJS.ProcessEnv;
46
+ codexHome: string;
47
+ appName?: string | undefined;
48
+ appVersion?: string | undefined;
49
+ }
50
+
51
+ export interface BridgedOperationResult {
52
+ status: 'completed' | 'pending_request' | 'running';
53
+ operationId: string;
54
+ requestId: RequestId;
55
+ pendingRequestIds: RequestId[];
56
+ result?: unknown;
57
+ }
58
+
59
+ const SERVER_REQUEST_METHODS = new Set([
60
+ 'item/commandExecution/requestApproval',
61
+ 'item/fileChange/requestApproval',
62
+ 'item/tool/requestUserInput',
63
+ 'mcpServer/elicitation/request',
64
+ 'item/permissions/requestApproval',
65
+ 'item/tool/call',
66
+ 'account/chatgptAuthTokens/refresh',
67
+ 'applyPatchApproval',
68
+ 'execCommandApproval',
69
+ ]);
70
+
71
+ const TURN_LIFECYCLE_METHODS = new Set([
72
+ 'turn/start',
73
+ 'turn/steer',
74
+ 'review/start',
75
+ ]);
76
+
77
+ function asObject(value: unknown): Record<string, unknown> | undefined {
78
+ if (!value || typeof value !== 'object' || Array.isArray(value)) {
79
+ return undefined;
80
+ }
81
+ return value as Record<string, unknown>;
82
+ }
83
+
84
+ function requestIdKey(id: RequestId): string {
85
+ return typeof id === 'number' ? `n:${id}` : `s:${id}`;
86
+ }
87
+
88
+ export class AppServerClient extends EventEmitter {
89
+ private readonly options: AppServerClientOptions;
90
+ private readonly pendingRequests = new Map<string, PendingRequestBinding>();
91
+ private readonly serverRequests = new Map<string, PendingServerRequest>();
92
+ private readonly operations = new Map<string, RuntimeOperation>();
93
+ private readonly operationsByRequestId = new Map<string, string>();
94
+ private readonly threadEvents = new Map<string, unknown[]>();
95
+ private process?: ChildProcessWithoutNullStreams | undefined;
96
+ private nextRequestCounter = 1;
97
+ private nextOperationCounter = 1;
98
+ private buffer = '';
99
+ private started = false;
100
+
101
+ constructor(options: AppServerClientOptions) {
102
+ super();
103
+ this.options = options;
104
+ }
105
+
106
+ async start(): Promise<void> {
107
+ if (this.started) {
108
+ return;
109
+ }
110
+
111
+ const child = spawn(this.options.command, this.options.args, {
112
+ cwd: process.cwd(),
113
+ env: {
114
+ ...this.options.env,
115
+ CODEX_HOME: this.options.codexHome,
116
+ },
117
+ stdio: 'pipe',
118
+ });
119
+
120
+ this.process = child;
121
+ this.started = true;
122
+
123
+ child.stdout.setEncoding('utf8');
124
+ child.stdout.on('data', (chunk) => this.consumeStdout(String(chunk)));
125
+ child.stderr.setEncoding('utf8');
126
+ child.stderr.on('data', (chunk) => {
127
+ this.emit('stderr', String(chunk));
128
+ });
129
+ child.on('exit', (code, signal) => {
130
+ const message = `Codex app-server exited (code=${String(code)}, signal=${String(signal)})`;
131
+ this.started = false;
132
+ this.process = undefined;
133
+ for (const binding of this.pendingRequests.values()) {
134
+ clearTimeout(binding.timeout);
135
+ binding.reject(new Error(message));
136
+ }
137
+ this.pendingRequests.clear();
138
+ this.emit('exit', { code, signal });
139
+ });
140
+
141
+ const initializeParams: InitializeParams = {
142
+ clientInfo: {
143
+ name: this.options.appName ?? APP_NAME,
144
+ title: APP_TITLE,
145
+ version: this.options.appVersion ?? '0.0.0',
146
+ },
147
+ capabilities: {
148
+ experimentalApi: false,
149
+ optOutNotificationMethods: null,
150
+ },
151
+ };
152
+
153
+ await this.request('initialize', initializeParams);
154
+ }
155
+
156
+ async stop(): Promise<void> {
157
+ if (!this.process) {
158
+ return;
159
+ }
160
+ this.process.kill('SIGTERM');
161
+ this.process = undefined;
162
+ this.started = false;
163
+ }
164
+
165
+ async request(method: string, params: unknown, options: RequestOptions = {}): Promise<unknown> {
166
+ const sent = this.sendRequest(method, params, options.timeoutMs);
167
+ return sent.promise;
168
+ }
169
+
170
+ async requestWithBridge(
171
+ method: string,
172
+ params: unknown,
173
+ options: RequestWithBridgeOptions = {},
174
+ ): Promise<BridgedOperationResult> {
175
+ const sent = this.sendRequest(method, params, options.timeoutMs);
176
+ const operationId = `op-${this.nextOperationCounter++}`;
177
+ const requestIdKeyValue = requestIdKey(sent.requestId);
178
+ const threadId = options.threadId ?? this.extractThreadIdFromParams(params);
179
+ const waitsForTurnCompletion = TURN_LIFECYCLE_METHODS.has(method);
180
+
181
+ const operation: RuntimeOperation = {
182
+ operationId,
183
+ requestId: sent.requestId,
184
+ method,
185
+ threadId,
186
+ startedAt: new Date().toISOString(),
187
+ status: 'running',
188
+ pendingRequestIds: [],
189
+ };
190
+ this.operations.set(operationId, operation);
191
+ this.operationsByRequestId.set(requestIdKeyValue, operationId);
192
+
193
+ sent.promise.then(
194
+ (result) => {
195
+ const current = this.operations.get(operationId);
196
+ if (!current) {
197
+ return;
198
+ }
199
+ current.result = result;
200
+ const turnId = this.extractTurnId(result);
201
+ if (turnId) {
202
+ current.turnId = turnId;
203
+ }
204
+ if (!waitsForTurnCompletion) {
205
+ current.status = 'completed';
206
+ current.completedAt = new Date().toISOString();
207
+ }
208
+ },
209
+ (error) => {
210
+ const current = this.operations.get(operationId);
211
+ if (!current) {
212
+ return;
213
+ }
214
+ current.status = 'failed';
215
+ current.completedAt = new Date().toISOString();
216
+ current.error = error instanceof Error ? error.message : String(error);
217
+ },
218
+ );
219
+
220
+ const bridgeTimeoutMs = options.bridgeTimeoutMs ?? OPERATION_BRIDGE_TIMEOUT_MS;
221
+ const result = await new Promise<BridgedOperationResult>((resolve, reject) => {
222
+ let settled = false;
223
+ const cleanup = () => {
224
+ this.off('server-request', onServerRequest);
225
+ this.off('notification', onNotification);
226
+ clearTimeout(timeout);
227
+ };
228
+ const resolveOnce = (value: BridgedOperationResult) => {
229
+ if (settled) {
230
+ return;
231
+ }
232
+ settled = true;
233
+ cleanup();
234
+ resolve(value);
235
+ };
236
+ const rejectOnce = (error: unknown) => {
237
+ if (settled) {
238
+ return;
239
+ }
240
+ settled = true;
241
+ cleanup();
242
+ reject(error);
243
+ };
244
+ const snapshot = (): BridgedOperationResult => {
245
+ const current = this.operations.get(operationId);
246
+ return {
247
+ status: current?.status === 'completed' ? 'completed' : 'running',
248
+ operationId,
249
+ requestId: sent.requestId,
250
+ pendingRequestIds: [...(current?.pendingRequestIds ?? [])],
251
+ ...(current?.result !== undefined ? { result: current.result } : {}),
252
+ };
253
+ };
254
+
255
+ const onServerRequest = (pending: PendingServerRequest) => {
256
+ const current = this.operations.get(operationId);
257
+ if (!current || current.status !== 'running') {
258
+ return;
259
+ }
260
+ const pendingThreadId = this.extractThreadIdFromParams(pending.params);
261
+ if (threadId && pendingThreadId && pendingThreadId !== threadId) {
262
+ return;
263
+ }
264
+ if (!current.pendingRequestIds.some((id) => requestIdKey(id) === requestIdKey(pending.id))) {
265
+ current.pendingRequestIds.push(pending.id);
266
+ }
267
+ resolveOnce({
268
+ status: 'pending_request',
269
+ operationId,
270
+ requestId: sent.requestId,
271
+ pendingRequestIds: [...current.pendingRequestIds],
272
+ });
273
+ };
274
+ const onNotification = () => {
275
+ const current = this.operations.get(operationId);
276
+ if (!current || current.status === 'running') {
277
+ return;
278
+ }
279
+ if (current.status === 'failed') {
280
+ rejectOnce(new Error(current.error ?? `Operation ${operationId} failed.`));
281
+ return;
282
+ }
283
+ resolveOnce(snapshot());
284
+ };
285
+
286
+ this.on('server-request', onServerRequest);
287
+ this.on('notification', onNotification);
288
+
289
+ sent.promise.then((response) => {
290
+ const current = this.operations.get(operationId);
291
+ if (!waitsForTurnCompletion) {
292
+ resolveOnce({
293
+ status: 'completed',
294
+ operationId,
295
+ requestId: sent.requestId,
296
+ pendingRequestIds: [...(current?.pendingRequestIds ?? [])],
297
+ result: response,
298
+ });
299
+ return;
300
+ }
301
+ if (current?.status === 'completed') {
302
+ resolveOnce(snapshot());
303
+ return;
304
+ }
305
+ if (current?.status === 'failed') {
306
+ rejectOnce(new Error(current.error ?? `Operation ${operationId} failed.`));
307
+ }
308
+ }).catch((error) => {
309
+ rejectOnce(error);
310
+ });
311
+
312
+ const timeout = setTimeout(() => {
313
+ resolveOnce(snapshot());
314
+ }, bridgeTimeoutMs);
315
+ timeout.unref();
316
+ });
317
+
318
+ return result;
319
+ }
320
+
321
+ async waitForOperation(operationId: string, options: WaitOptions = {}): Promise<RuntimeOperation> {
322
+ const timeoutMs = options.timeoutMs ?? REQUEST_TIMEOUT_MS;
323
+ const pollIntervalMs = options.pollIntervalMs ?? OPERATION_POLL_INTERVAL_MS;
324
+ const start = Date.now();
325
+
326
+ while (Date.now() - start <= timeoutMs) {
327
+ const operation = this.operations.get(operationId);
328
+ if (!operation) {
329
+ throw new Error(`Operation not found: ${operationId}`);
330
+ }
331
+ if (operation.status === 'completed' || operation.status === 'failed') {
332
+ return { ...operation, pendingRequestIds: [...operation.pendingRequestIds] };
333
+ }
334
+ await new Promise((resolve) => setTimeout(resolve, pollIntervalMs));
335
+ }
336
+
337
+ throw new Error(`Timed out waiting for operation ${operationId}`);
338
+ }
339
+
340
+ getOperation(operationId: string): RuntimeOperation | undefined {
341
+ const operation = this.operations.get(operationId);
342
+ if (!operation) {
343
+ return undefined;
344
+ }
345
+ return { ...operation, pendingRequestIds: [...operation.pendingRequestIds] };
346
+ }
347
+
348
+ listOperations(): RuntimeOperation[] {
349
+ return [...this.operations.values()].map((operation) => ({
350
+ ...operation,
351
+ pendingRequestIds: [...operation.pendingRequestIds],
352
+ }));
353
+ }
354
+
355
+ listServerRequests(includeResolved = false): PendingServerRequest[] {
356
+ return [...this.serverRequests.values()]
357
+ .filter((request) => includeResolved || request.status === 'pending')
358
+ .map((request) => ({ ...request }));
359
+ }
360
+
361
+ getServerRequest(id: RequestId): PendingServerRequest | undefined {
362
+ const request = this.serverRequests.get(requestIdKey(id));
363
+ return request ? { ...request } : undefined;
364
+ }
365
+
366
+ async respondToServerRequest(id: RequestId, payload: unknown): Promise<void> {
367
+ const requestKey = requestIdKey(id);
368
+ const request = this.serverRequests.get(requestKey);
369
+ if (!request) {
370
+ throw new Error(`Pending server request not found: ${String(id)}`);
371
+ }
372
+ if (!this.process || !this.started) {
373
+ throw new Error('Codex app-server is not running');
374
+ }
375
+
376
+ this.writeLine({
377
+ id,
378
+ result: payload,
379
+ });
380
+
381
+ request.response = payload;
382
+ request.status = 'resolved';
383
+ request.resolvedAt = new Date().toISOString();
384
+ }
385
+
386
+ getThreadEvents(threadId: string): unknown[] {
387
+ return [...(this.threadEvents.get(threadId) ?? [])];
388
+ }
389
+
390
+ private sendRequest(method: string, params: unknown, timeoutMs = REQUEST_TIMEOUT_MS): {
391
+ requestId: RequestId;
392
+ promise: Promise<unknown>;
393
+ } {
394
+ if (!this.process || !this.started) {
395
+ throw new Error('Codex app-server is not running');
396
+ }
397
+
398
+ const requestId: RequestId = `client-${this.nextRequestCounter++}`;
399
+ const key = requestIdKey(requestId);
400
+ const promise = new Promise<unknown>((resolve, reject) => {
401
+ const timeout = setTimeout(() => {
402
+ this.pendingRequests.delete(key);
403
+ reject(new Error(`Timed out waiting for ${method} response`));
404
+ }, timeoutMs);
405
+ timeout.unref();
406
+ this.pendingRequests.set(key, {
407
+ resolve,
408
+ reject,
409
+ timeout,
410
+ });
411
+ });
412
+
413
+ const message: JsonLineRequest = { method, id: requestId, params };
414
+ this.writeLine(message);
415
+ return { requestId, promise };
416
+ }
417
+
418
+ private consumeStdout(chunk: string): void {
419
+ this.buffer += chunk;
420
+ while (true) {
421
+ const lineBreak = this.buffer.indexOf('\n');
422
+ if (lineBreak === -1) {
423
+ return;
424
+ }
425
+
426
+ const line = this.buffer.slice(0, lineBreak).trim();
427
+ this.buffer = this.buffer.slice(lineBreak + 1);
428
+ if (!line) {
429
+ continue;
430
+ }
431
+
432
+ let message: JsonLineMessage;
433
+ try {
434
+ message = JSON.parse(line) as JsonLineMessage;
435
+ } catch (error) {
436
+ this.emit('parse-error', error);
437
+ continue;
438
+ }
439
+
440
+ this.handleMessage(message);
441
+ }
442
+ }
443
+
444
+ private handleMessage(message: JsonLineMessage): void {
445
+ const asResponse = asObject(message);
446
+ if (!asResponse) {
447
+ return;
448
+ }
449
+
450
+ const hasMethod = typeof asResponse.method === 'string';
451
+ const hasId = typeof asResponse.id === 'string' || typeof asResponse.id === 'number';
452
+
453
+ if (hasMethod && hasId) {
454
+ const request = message as JsonLineRequest;
455
+ const key = requestIdKey(request.id);
456
+ if (this.pendingRequests.has(key)) {
457
+ this.resolveClientRequest(request.id, request as unknown as JsonLineResponse);
458
+ return;
459
+ }
460
+ this.storeServerRequest(request);
461
+ return;
462
+ }
463
+
464
+ if (hasId) {
465
+ this.resolveClientRequest((message as JsonLineResponse).id, message as JsonLineResponse);
466
+ return;
467
+ }
468
+
469
+ if (hasMethod) {
470
+ this.handleNotification(message as JsonLineNotification);
471
+ }
472
+ }
473
+
474
+ private resolveClientRequest(id: RequestId, response: JsonLineResponse): void {
475
+ const key = requestIdKey(id);
476
+ const binding = this.pendingRequests.get(key);
477
+ if (!binding) {
478
+ return;
479
+ }
480
+
481
+ clearTimeout(binding.timeout);
482
+ this.pendingRequests.delete(key);
483
+ if ('error' in response && response.error !== undefined) {
484
+ binding.reject(
485
+ new Error(
486
+ typeof response.error === 'string'
487
+ ? response.error
488
+ : JSON.stringify(response.error),
489
+ ),
490
+ );
491
+ return;
492
+ }
493
+ binding.resolve(response.result);
494
+ }
495
+
496
+ private storeServerRequest(request: JsonLineRequest): void {
497
+ if (!SERVER_REQUEST_METHODS.has(request.method)) {
498
+ return;
499
+ }
500
+ const key = requestIdKey(request.id);
501
+ const pending: PendingServerRequest = {
502
+ id: request.id,
503
+ method: request.method,
504
+ params: request.params,
505
+ createdAt: new Date().toISOString(),
506
+ status: 'pending',
507
+ };
508
+ this.serverRequests.set(key, pending);
509
+ this.emit('server-request', pending);
510
+ }
511
+
512
+ private handleNotification(notification: JsonLineNotification): void {
513
+ if (notification.method === 'serverRequest/resolved') {
514
+ const params = asObject(notification.params);
515
+ const requestId = params?.requestId;
516
+ if (typeof requestId === 'string' || typeof requestId === 'number') {
517
+ const request = this.serverRequests.get(requestIdKey(requestId));
518
+ if (request) {
519
+ request.status = 'resolved';
520
+ request.resolvedAt = new Date().toISOString();
521
+ }
522
+ }
523
+ }
524
+
525
+ this.updateOperationsFromNotification(notification);
526
+
527
+ const threadId = this.extractThreadIdFromParams(notification.params);
528
+ if (threadId) {
529
+ const events = this.threadEvents.get(threadId) ?? [];
530
+ events.push({
531
+ receivedAt: new Date().toISOString(),
532
+ method: notification.method,
533
+ params: notification.params,
534
+ });
535
+ this.threadEvents.set(threadId, events.slice(-200));
536
+ }
537
+
538
+ this.emit('notification', notification);
539
+ }
540
+
541
+ private updateOperationsFromNotification(notification: JsonLineNotification): void {
542
+ const threadId = this.extractThreadIdFromParams(notification.params);
543
+ if (!threadId) {
544
+ return;
545
+ }
546
+
547
+ if (notification.method === 'turn/completed') {
548
+ const params = asObject(notification.params);
549
+ const turn = asObject(params?.turn);
550
+ const turnId = typeof turn?.id === 'string' ? turn.id : undefined;
551
+ const turnStatus = typeof turn?.status === 'string' ? turn.status : undefined;
552
+ for (const operation of this.operations.values()) {
553
+ if (operation.status !== 'running' || operation.threadId !== threadId || !TURN_LIFECYCLE_METHODS.has(operation.method)) {
554
+ continue;
555
+ }
556
+ if (turnId) {
557
+ operation.turnId = operation.turnId ?? turnId;
558
+ if (operation.turnId !== turnId) {
559
+ continue;
560
+ }
561
+ }
562
+ if (turnStatus === 'completed' || turnStatus === 'interrupted') {
563
+ operation.status = 'completed';
564
+ operation.completedAt = new Date().toISOString();
565
+ operation.result = { turn };
566
+ } else {
567
+ operation.status = 'failed';
568
+ operation.completedAt = new Date().toISOString();
569
+ operation.error = this.extractTurnError(turn) ?? `Turn finished with status ${turnStatus ?? 'unknown'}.`;
570
+ operation.result = { turn };
571
+ }
572
+ }
573
+ return;
574
+ }
575
+
576
+ if (notification.method === 'error') {
577
+ const params = asObject(notification.params);
578
+ const message = typeof params?.message === 'string' ? params.message : 'Codex reported an error.';
579
+ for (const operation of this.operations.values()) {
580
+ if (operation.status === 'running' && operation.threadId === threadId && TURN_LIFECYCLE_METHODS.has(operation.method)) {
581
+ operation.status = 'failed';
582
+ operation.completedAt = new Date().toISOString();
583
+ operation.error = message;
584
+ }
585
+ }
586
+ }
587
+ }
588
+
589
+ private extractThreadIdFromParams(params: unknown): string | undefined {
590
+ const object = asObject(params);
591
+ const threadId = object?.threadId;
592
+ if (typeof threadId === 'string') {
593
+ return threadId;
594
+ }
595
+ const thread = asObject(object?.thread);
596
+ const threadIdFromThread = thread?.id;
597
+ if (typeof threadIdFromThread === 'string') {
598
+ return threadIdFromThread;
599
+ }
600
+ return undefined;
601
+ }
602
+
603
+ private extractTurnId(payload: unknown): string | undefined {
604
+ const object = asObject(payload);
605
+ const turn = asObject(object?.turn);
606
+ if (typeof turn?.id === 'string') {
607
+ return turn.id;
608
+ }
609
+ if (typeof object?.turnId === 'string') {
610
+ return object.turnId;
611
+ }
612
+ return undefined;
613
+ }
614
+
615
+ private extractTurnError(turn: Record<string, unknown> | undefined): string | undefined {
616
+ if (!turn) {
617
+ return undefined;
618
+ }
619
+ const error = turn.error;
620
+ if (typeof error === 'string') {
621
+ return error;
622
+ }
623
+ const object = asObject(error);
624
+ if (typeof object?.message === 'string') {
625
+ return object.message;
626
+ }
627
+ return undefined;
628
+ }
629
+
630
+ private writeLine(message: JsonLineMessage | { id: RequestId; result: unknown }): void {
631
+ if (!this.process || !this.started) {
632
+ throw new Error('Codex app-server is not running');
633
+ }
634
+ this.process.stdin.write(`${JSON.stringify(message)}\n`);
635
+ }
636
+ }