@skaile/workspaces 3.16.2 → 3.18.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 (274) hide show
  1. package/CHANGELOG.md +69 -0
  2. package/dist/app-sdk/index.js +1 -1
  3. package/dist/{asset-feeds-FQT6GH24.js → asset-feeds-LT4GI576.js} +7 -7
  4. package/dist/{asset-feeds-FQT6GH24.js.map → asset-feeds-LT4GI576.js.map} +1 -1
  5. package/dist/asset-manager/catalog-deployer.js +3 -3
  6. package/dist/asset-manager/index.js +6 -6
  7. package/dist/asset-manager/installer.js +4 -4
  8. package/dist/bridge/codex-app-server.d.ts +2 -0
  9. package/dist/bridge/codex-app-server.js +5 -0
  10. package/dist/bridge/codex-app-server.js.map +1 -0
  11. package/dist/bridge/drivers/claude-sdk.js +5 -5
  12. package/dist/bridge/drivers/codex.js +1137 -4
  13. package/dist/bridge/drivers/codex.js.map +1 -1
  14. package/dist/bridge/drivers/continue.js +2 -2
  15. package/dist/bridge/drivers/echo.js +2 -2
  16. package/dist/bridge/drivers/gemini.js +3 -3
  17. package/dist/bridge/drivers/goose.js +2 -2
  18. package/dist/bridge/drivers/omp.js +1 -1
  19. package/dist/bridge/drivers/opencode.js +2 -2
  20. package/dist/bridge/drivers/qwen.js +3 -3
  21. package/dist/bridge/index.js +7 -6
  22. package/dist/bridge/src/capability-dispatch.d.ts +1 -1
  23. package/dist/bridge/src/capability-dispatch.d.ts.map +1 -1
  24. package/dist/bridge/src/codex/credentials.d.ts +12 -0
  25. package/dist/bridge/src/codex/credentials.d.ts.map +1 -0
  26. package/dist/bridge/src/codex/inputs.d.ts +8 -0
  27. package/dist/bridge/src/codex/inputs.d.ts.map +1 -0
  28. package/dist/bridge/src/codex/instance-state.d.ts +16 -0
  29. package/dist/bridge/src/codex/instance-state.d.ts.map +1 -0
  30. package/dist/bridge/src/codex/managed-driver.d.ts +71 -0
  31. package/dist/bridge/src/codex/managed-driver.d.ts.map +1 -0
  32. package/dist/bridge/src/codex/native-approvals.d.ts +22 -0
  33. package/dist/bridge/src/codex/native-approvals.d.ts.map +1 -0
  34. package/dist/bridge/src/codex/native-policy.d.ts +38 -0
  35. package/dist/bridge/src/codex/native-policy.d.ts.map +1 -0
  36. package/dist/bridge/src/codex/native-protocol.generated.d.ts +1411 -0
  37. package/dist/bridge/src/codex/native-protocol.generated.d.ts.map +1 -0
  38. package/dist/bridge/src/codex/native-state.d.ts +7 -0
  39. package/dist/bridge/src/codex/native-state.d.ts.map +1 -0
  40. package/dist/bridge/src/codex/questions.d.ts +19 -0
  41. package/dist/bridge/src/codex/questions.d.ts.map +1 -0
  42. package/dist/bridge/src/codex-app-server.d.ts +60 -0
  43. package/dist/bridge/src/codex-app-server.d.ts.map +1 -0
  44. package/dist/bridge/src/drivers/codex.d.ts +9 -1
  45. package/dist/bridge/src/drivers/codex.d.ts.map +1 -1
  46. package/dist/bridge/src/index.d.ts +1 -0
  47. package/dist/bridge/src/index.d.ts.map +1 -1
  48. package/dist/bridge/src/normalizer.d.ts.map +1 -1
  49. package/dist/bridge/src/runtime.d.ts +3 -2
  50. package/dist/bridge/src/runtime.d.ts.map +1 -1
  51. package/dist/bridge/src/types.d.ts +77 -4
  52. package/dist/bridge/src/types.d.ts.map +1 -1
  53. package/dist/{chunk-2KBA5OO2.js → chunk-23L3P7IB.js} +4 -4
  54. package/dist/{chunk-2KBA5OO2.js.map → chunk-23L3P7IB.js.map} +1 -1
  55. package/dist/{chunk-NC5YXVZF.js → chunk-2FDKUKDE.js} +3 -3
  56. package/dist/{chunk-NC5YXVZF.js.map → chunk-2FDKUKDE.js.map} +1 -1
  57. package/dist/{chunk-GRVSSAAQ.js → chunk-2IROGAS7.js} +2 -2
  58. package/dist/{chunk-GRVSSAAQ.js.map → chunk-2IROGAS7.js.map} +1 -1
  59. package/dist/{chunk-BUKPS4YL.js → chunk-4JDCKPTM.js} +2 -2
  60. package/dist/{chunk-BUKPS4YL.js.map → chunk-4JDCKPTM.js.map} +1 -1
  61. package/dist/{chunk-5KSIVLOX.js → chunk-5T7Y3AZU.js} +3 -3
  62. package/dist/{chunk-5KSIVLOX.js.map → chunk-5T7Y3AZU.js.map} +1 -1
  63. package/dist/{chunk-SWUVULBU.js → chunk-67KB2A77.js} +7 -7
  64. package/dist/{chunk-SWUVULBU.js.map → chunk-67KB2A77.js.map} +1 -1
  65. package/dist/{chunk-RRVQAE5D.js → chunk-7ZO3MUP3.js} +6 -5
  66. package/dist/chunk-7ZO3MUP3.js.map +1 -0
  67. package/dist/{chunk-EO7IJY3Q.js → chunk-AI2PZX4H.js} +3 -3
  68. package/dist/{chunk-EO7IJY3Q.js.map → chunk-AI2PZX4H.js.map} +1 -1
  69. package/dist/{chunk-CMGYUF5P.js → chunk-BJI7IGZF.js} +7 -7
  70. package/dist/{chunk-CMGYUF5P.js.map → chunk-BJI7IGZF.js.map} +1 -1
  71. package/dist/{chunk-HY6CIKFH.js → chunk-CP62G5PK.js} +8 -7
  72. package/dist/chunk-CP62G5PK.js.map +1 -0
  73. package/dist/{chunk-PBRMY64S.js → chunk-CQY7XKRV.js} +30 -9
  74. package/dist/chunk-CQY7XKRV.js.map +1 -0
  75. package/dist/{chunk-OIDFK7SG.js → chunk-DCG4UWJM.js} +3 -3
  76. package/dist/{chunk-OIDFK7SG.js.map → chunk-DCG4UWJM.js.map} +1 -1
  77. package/dist/{chunk-VT4MPCRK.js → chunk-FBD5SOIH.js} +3 -3
  78. package/dist/{chunk-VT4MPCRK.js.map → chunk-FBD5SOIH.js.map} +1 -1
  79. package/dist/{chunk-DUMD4AA2.js → chunk-FYVDBIZV.js} +6 -6
  80. package/dist/{chunk-DUMD4AA2.js.map → chunk-FYVDBIZV.js.map} +1 -1
  81. package/dist/{chunk-RTM4SFLA.js → chunk-GMKNGIIB.js} +7 -4
  82. package/dist/chunk-GMKNGIIB.js.map +1 -0
  83. package/dist/{chunk-NIQPSQFN.js → chunk-GMMACS5W.js} +4 -4
  84. package/dist/{chunk-NIQPSQFN.js.map → chunk-GMMACS5W.js.map} +1 -1
  85. package/dist/{chunk-QFYEDM63.js → chunk-GRA4BWCV.js} +5 -5
  86. package/dist/{chunk-QFYEDM63.js.map → chunk-GRA4BWCV.js.map} +1 -1
  87. package/dist/{chunk-CIPK5JMJ.js → chunk-H662SXKS.js} +4 -4
  88. package/dist/{chunk-CIPK5JMJ.js.map → chunk-H662SXKS.js.map} +1 -1
  89. package/dist/{chunk-4W2OOVN5.js → chunk-IST2V7RU.js} +3 -3
  90. package/dist/{chunk-4W2OOVN5.js.map → chunk-IST2V7RU.js.map} +1 -1
  91. package/dist/{chunk-L2UE4YJO.js → chunk-IT42ZT3T.js} +9 -9
  92. package/dist/{chunk-L2UE4YJO.js.map → chunk-IT42ZT3T.js.map} +1 -1
  93. package/dist/{chunk-FRER2PEN.js → chunk-J7VSUGGH.js} +16 -3
  94. package/dist/chunk-J7VSUGGH.js.map +1 -0
  95. package/dist/{chunk-ZNCZ7RUO.js → chunk-JVFZ5R7L.js} +3 -3
  96. package/dist/{chunk-ZNCZ7RUO.js.map → chunk-JVFZ5R7L.js.map} +1 -1
  97. package/dist/chunk-LOO5CB5M.js +12 -0
  98. package/dist/chunk-LOO5CB5M.js.map +1 -0
  99. package/dist/{chunk-AL6BU3SP.js → chunk-OJ4N4T4H.js} +12 -4
  100. package/dist/chunk-OJ4N4T4H.js.map +1 -0
  101. package/dist/chunk-QEZPFJX3.js +254 -0
  102. package/dist/chunk-QEZPFJX3.js.map +1 -0
  103. package/dist/{chunk-C4AP3XZB.js → chunk-QG2ZXU5W.js} +4 -4
  104. package/dist/{chunk-C4AP3XZB.js.map → chunk-QG2ZXU5W.js.map} +1 -1
  105. package/dist/{chunk-I3COVVFB.js → chunk-RJOGAEIY.js} +1024 -204
  106. package/dist/chunk-RJOGAEIY.js.map +1 -0
  107. package/dist/{chunk-OZ7UNMTK.js → chunk-RPVTPVGX.js} +7 -5
  108. package/dist/chunk-RPVTPVGX.js.map +1 -0
  109. package/dist/{chunk-S4UA244H.js → chunk-S635WMXH.js} +4 -4
  110. package/dist/{chunk-S4UA244H.js.map → chunk-S635WMXH.js.map} +1 -1
  111. package/dist/{chunk-BQMRUH7J.js → chunk-SFCVAEJ5.js} +4 -4
  112. package/dist/{chunk-BQMRUH7J.js.map → chunk-SFCVAEJ5.js.map} +1 -1
  113. package/dist/{chunk-EXT2LNST.js → chunk-SH7GXS7V.js} +125 -37
  114. package/dist/chunk-SH7GXS7V.js.map +1 -0
  115. package/dist/chunk-T3YLZQS4.js +336 -0
  116. package/dist/chunk-T3YLZQS4.js.map +1 -0
  117. package/dist/{chunk-X7FJ3ES3.js → chunk-X3LUB275.js} +4 -4
  118. package/dist/{chunk-X7FJ3ES3.js.map → chunk-X3LUB275.js.map} +1 -1
  119. package/dist/chunk-XKSGEYZC.js +244 -0
  120. package/dist/chunk-XKSGEYZC.js.map +1 -0
  121. package/dist/{chunk-SUPIVTLX.js → chunk-XL45U3C5.js} +3 -3
  122. package/dist/{chunk-SUPIVTLX.js.map → chunk-XL45U3C5.js.map} +1 -1
  123. package/dist/{chunk-AXEOG4B5.js → chunk-YCMHWNZA.js} +3 -3
  124. package/dist/{chunk-AXEOG4B5.js.map → chunk-YCMHWNZA.js.map} +1 -1
  125. package/dist/cli/index.js +75 -53
  126. package/dist/cli/index.js.map +1 -1
  127. package/dist/cli/src/commands/serve.d.ts.map +1 -1
  128. package/dist/client/index.js +1 -1
  129. package/dist/client/src/client.d.ts +3 -2
  130. package/dist/client/src/client.d.ts.map +1 -1
  131. package/dist/connectors/config.js +4 -4
  132. package/dist/connectors/index.js +12 -11
  133. package/dist/connectors/src/connector-prompt.d.ts +11 -0
  134. package/dist/connectors/src/connector-prompt.d.ts.map +1 -1
  135. package/dist/core/index.js +3 -3
  136. package/dist/core/runtime-assets.js +2 -2
  137. package/dist/core/src/workspace-config.d.ts.map +1 -1
  138. package/dist/core/workspace-config.js +1 -1
  139. package/dist/deploy/index.js +3 -3
  140. package/dist/{ensure-sources-4GBXK6UR.js → ensure-sources-4BQ6GMYG.js} +9 -9
  141. package/dist/{ensure-sources-4GBXK6UR.js.map → ensure-sources-4BQ6GMYG.js.map} +1 -1
  142. package/dist/factory-assets/connectors/box.js +12 -11
  143. package/dist/factory-assets/connectors/deploy.js +12 -11
  144. package/dist/factory-assets/connectors/devserver.js +12 -11
  145. package/dist/factory-assets/connectors/flow/CONNECTOR.md +4 -5
  146. package/dist/factory-assets/connectors/flow/adapter.d.ts +8 -0
  147. package/dist/factory-assets/connectors/flow/adapter.d.ts.map +1 -1
  148. package/dist/factory-assets/connectors/flow/adapter.js +12 -11
  149. package/dist/factory-assets/connectors/flow/contract/index.d.ts +1 -1
  150. package/dist/factory-assets/connectors/flow/contract/index.d.ts.map +1 -1
  151. package/dist/factory-assets/connectors/flow/contract/schema.d.ts +50 -17
  152. package/dist/factory-assets/connectors/flow/contract/schema.d.ts.map +1 -1
  153. package/dist/factory-assets/connectors/flow/contract.js +3 -3
  154. package/dist/factory-assets/connectors/flow/engine/index.d.ts +1 -0
  155. package/dist/factory-assets/connectors/flow/engine/index.d.ts.map +1 -1
  156. package/dist/factory-assets/connectors/flow/engine.js +5 -5
  157. package/dist/factory-assets/connectors/flow/run-flow.js +13 -12
  158. package/dist/factory-assets/connectors/flow/subprompt-runner.d.ts +10 -1
  159. package/dist/factory-assets/connectors/flow/subprompt-runner.d.ts.map +1 -1
  160. package/dist/factory-assets/connectors/flow.js +12 -11
  161. package/dist/factory-assets/connectors/git.js +12 -11
  162. package/dist/factory-assets/connectors/gmail.js +12 -11
  163. package/dist/factory-assets/connectors/googledrive.js +12 -11
  164. package/dist/factory-assets/connectors/local.js +12 -11
  165. package/dist/factory-assets/connectors/mattermost.js +12 -11
  166. package/dist/factory-assets/connectors/memory.js +12 -11
  167. package/dist/factory-assets/connectors/minio.js +12 -11
  168. package/dist/factory-assets/connectors/postgres.js +12 -11
  169. package/dist/factory-assets/connectors/s3.js +12 -11
  170. package/dist/factory-assets/connectors/sharepoint.js +12 -11
  171. package/dist/factory-assets/connectors/sqlite.js +12 -11
  172. package/dist/factory-assets/connectors/static-server.js +12 -11
  173. package/dist/factory-assets/connectors/tunnel.js +12 -11
  174. package/dist/factory-assets/connectors/webdav.js +12 -11
  175. package/dist/factory-assets/connectors/xstate-store.js +12 -11
  176. package/dist/factory-assets/connectors/xstate.js +12 -11
  177. package/dist/{flows-2SUFOVVO.js → flows-COBS26MK.js} +6 -6
  178. package/dist/{flows-2SUFOVVO.js.map → flows-COBS26MK.js.map} +1 -1
  179. package/dist/{helpers-26LW4IXY.js → helpers-4UJMSN6T.js} +9 -9
  180. package/dist/{helpers-26LW4IXY.js.map → helpers-4UJMSN6T.js.map} +1 -1
  181. package/dist/library/index.js +4 -4
  182. package/dist/library/install.js +3 -3
  183. package/dist/{library-publish-IYGHOPEK.js → library-publish-QHQDN4IC.js} +14 -14
  184. package/dist/{library-publish-IYGHOPEK.js.map → library-publish-QHQDN4IC.js.map} +1 -1
  185. package/dist/{open-library-HH5LST7Z.js → open-library-ZDM6DUKJ.js} +12 -12
  186. package/dist/{open-library-HH5LST7Z.js.map → open-library-ZDM6DUKJ.js.map} +1 -1
  187. package/dist/{paths-4APA2PKT.js → paths-CZPCCBYX.js} +6 -6
  188. package/dist/{paths-4APA2PKT.js.map → paths-CZPCCBYX.js.map} +1 -1
  189. package/dist/{plugin-store-JQAIKR3R.js → plugin-store-ZEIBSNTO.js} +5 -5
  190. package/dist/{plugin-store-JQAIKR3R.js.map → plugin-store-ZEIBSNTO.js.map} +1 -1
  191. package/dist/{project-U5QRUCBN.js → project-JJUAAI7N.js} +10 -10
  192. package/dist/{project-U5QRUCBN.js.map → project-JJUAAI7N.js.map} +1 -1
  193. package/dist/resolver/index.js +3 -3
  194. package/dist/runner/index.js +25 -16
  195. package/dist/runner/src/capability-registry.d.ts +4 -0
  196. package/dist/runner/src/capability-registry.d.ts.map +1 -1
  197. package/dist/runner/src/codex-init.d.ts +5 -0
  198. package/dist/runner/src/codex-init.d.ts.map +1 -0
  199. package/dist/runner/src/codex-resource-tools.d.ts +16 -0
  200. package/dist/runner/src/codex-resource-tools.d.ts.map +1 -0
  201. package/dist/runner/src/codex-tools.d.ts +12 -0
  202. package/dist/runner/src/codex-tools.d.ts.map +1 -0
  203. package/dist/runner/src/define-capability.d.ts +2 -0
  204. package/dist/runner/src/define-capability.d.ts.map +1 -1
  205. package/dist/runner/src/external-mcp.d.ts +8 -3
  206. package/dist/runner/src/external-mcp.d.ts.map +1 -1
  207. package/dist/runner/src/index.d.ts +2 -0
  208. package/dist/runner/src/index.d.ts.map +1 -1
  209. package/dist/runner/src/managed-codex-bootstrap.d.ts +54 -0
  210. package/dist/runner/src/managed-codex-bootstrap.d.ts.map +1 -0
  211. package/dist/runner/src/resources.d.ts +1 -0
  212. package/dist/runner/src/resources.d.ts.map +1 -1
  213. package/dist/runner/src/serve.d.ts +5 -0
  214. package/dist/runner/src/serve.d.ts.map +1 -1
  215. package/dist/runner/src/session-builder.d.ts +18 -1
  216. package/dist/runner/src/session-builder.d.ts.map +1 -1
  217. package/dist/sdk/asset-manager.js +6 -6
  218. package/dist/sdk/bridge.js +7 -6
  219. package/dist/sdk/client.js +1 -1
  220. package/dist/sdk/core.js +3 -3
  221. package/dist/sdk/flow.js +5 -5
  222. package/dist/sdk/index.js +26 -17
  223. package/dist/sdk/index.js.map +1 -1
  224. package/dist/sdk/resolver.js +3 -3
  225. package/dist/sdk/runner.js +25 -16
  226. package/dist/sdk/session.js +2 -2
  227. package/dist/sdk/store.js +1 -1
  228. package/dist/sdk/types.js +1 -1
  229. package/dist/session/index.js +2 -2
  230. package/dist/{setup-XKTBHRWM.js → setup-PS6ZERZ5.js} +9 -8
  231. package/dist/setup-PS6ZERZ5.js.map +1 -0
  232. package/dist/{skills-Q7PJVB3W.js → skills-LG6IQSSN.js} +5 -5
  233. package/dist/{skills-Q7PJVB3W.js.map → skills-LG6IQSSN.js.map} +1 -1
  234. package/dist/{source-6PBVTACZ.js → source-QLDIZCI3.js} +13 -13
  235. package/dist/{source-6PBVTACZ.js.map → source-QLDIZCI3.js.map} +1 -1
  236. package/dist/{source-manifest-publish-VBVNW7KL.js → source-manifest-publish-J3AVCTLX.js} +15 -15
  237. package/dist/{source-manifest-publish-VBVNW7KL.js.map → source-manifest-publish-J3AVCTLX.js.map} +1 -1
  238. package/dist/store/index.js +1 -1
  239. package/dist/store/react.js +1 -1
  240. package/dist/store/react.js.map +1 -1
  241. package/dist/store/src/react.d.ts +1 -1
  242. package/dist/store/src/react.d.ts.map +1 -1
  243. package/dist/store/src/store.d.ts +2 -1
  244. package/dist/store/src/store.d.ts.map +1 -1
  245. package/dist/tui/index.js +25 -16
  246. package/dist/tui/index.js.map +1 -1
  247. package/dist/types/index.js +1 -1
  248. package/dist/types/src/events.d.ts +14 -1
  249. package/dist/types/src/events.d.ts.map +1 -1
  250. package/dist/types/src/index.d.ts +3 -3
  251. package/dist/types/src/index.d.ts.map +1 -1
  252. package/dist/types/src/lifecycle.d.ts +43 -0
  253. package/dist/types/src/lifecycle.d.ts.map +1 -1
  254. package/dist/types/src/protocol.d.ts +18 -0
  255. package/dist/types/src/protocol.d.ts.map +1 -1
  256. package/dist/types/src/runtime.d.ts +3 -1
  257. package/dist/types/src/runtime.d.ts.map +1 -1
  258. package/dist/types/src/version.d.ts +7 -1
  259. package/dist/types/src/version.d.ts.map +1 -1
  260. package/dist/workspace-plugin/adapters/mcp.js +9 -255
  261. package/dist/workspace-plugin/adapters/mcp.js.map +1 -1
  262. package/dist/workspace-plugin/adapters/omp.js +7 -7
  263. package/dist/workspace-plugin/index.js +1 -1
  264. package/package.json +10 -1
  265. package/dist/chunk-AL6BU3SP.js.map +0 -1
  266. package/dist/chunk-EXT2LNST.js.map +0 -1
  267. package/dist/chunk-FRER2PEN.js.map +0 -1
  268. package/dist/chunk-HY6CIKFH.js.map +0 -1
  269. package/dist/chunk-I3COVVFB.js.map +0 -1
  270. package/dist/chunk-OZ7UNMTK.js.map +0 -1
  271. package/dist/chunk-PBRMY64S.js.map +0 -1
  272. package/dist/chunk-RRVQAE5D.js.map +0 -1
  273. package/dist/chunk-RTM4SFLA.js.map +0 -1
  274. package/dist/setup-XKTBHRWM.js.map +0 -1
@@ -1,14 +1,1108 @@
1
+ import { CodexAppServerClient } from '../../chunk-XKSGEYZC.js';
2
+ import { parseCodexCredential, prepareNativePolicy, prepareCodexInstance, codexInstanceEnvironment, activateNativeApprovalPolicy, parseCodexRefreshResult, isNativeApprovalPolicyActive, allowsNativeApprovalPath } from '../../chunk-T3YLZQS4.js';
3
+ import { CodexNativeStateUnavailable } from '../../chunk-LOO5CB5M.js';
1
4
  import { fetchProviderModels } from '../../chunk-GURXUF2J.js';
2
5
  import { classifyGenericErrorMessage } from '../../chunk-GAH4YRCI.js';
3
- import { BUILTIN_DRIVER_CATALOG, AgentDriver, getBridgeLogger } from '../../chunk-FRER2PEN.js';
6
+ import { BUILTIN_DRIVER_CATALOG, AgentDriver, getBridgeLogger } from '../../chunk-J7VSUGGH.js';
4
7
  import '../../chunk-6E6PKKAD.js';
5
8
  import '../../chunk-FTG7CRFD.js';
6
9
  import '../../chunk-W4IPN3DD.js';
7
10
  import '../../chunk-NSBPE2FW.js';
8
- import { existsSync, readFileSync, mkdirSync, writeFileSync } from 'fs';
9
- import { join, dirname } from 'path';
11
+ import { join, dirname, isAbsolute, relative } from 'path';
12
+ import { existsSync, readFileSync, mkdirSync, writeFileSync, realpathSync, statSync } from 'fs';
13
+ import { randomUUID } from 'crypto';
10
14
  import * as z from 'zod';
11
15
 
16
+ var invalid = () => new Error("CODEX_INPUT_INVALID");
17
+ var inside = (root, path) => {
18
+ const rel = relative(root, path);
19
+ return rel !== "" && !rel.startsWith("..") && !isAbsolute(rel);
20
+ };
21
+ function codexPromptInput(input, cwd, skills) {
22
+ if (!input || typeof input.text !== "string" || input.text.length > 1024 * 1024 || input.attachments !== void 0 && !Array.isArray(input.attachments) || (input.attachments?.length ?? 0) > 32)
23
+ throw invalid();
24
+ const result = [
25
+ { type: "text", text: input.text }
26
+ ];
27
+ for (const attachment of input.attachments ?? []) {
28
+ try {
29
+ if (!attachment || typeof attachment.path !== "string") throw invalid();
30
+ const root = attachment.type === "skill" && skills ? realpathSync(skills.source) : realpathSync(cwd);
31
+ const path = realpathSync(
32
+ isAbsolute(attachment.path) ? attachment.path : join(root, attachment.path)
33
+ );
34
+ if (!inside(root, path) || !statSync(path).isFile()) throw invalid();
35
+ if (attachment.type === "image") result.push({ type: "localImage", path });
36
+ else if (attachment.type === "file" || attachment.type === "skill") {
37
+ if (!attachment.name || [...attachment.name].some((char) => char.charCodeAt(0) < 32))
38
+ throw invalid();
39
+ if (attachment.type === "skill") {
40
+ if (!skills) throw invalid();
41
+ const copied = realpathSync(join(skills.target, relative(root, path)));
42
+ if (!inside(realpathSync(skills.target), copied) || !statSync(copied).isFile())
43
+ throw invalid();
44
+ result.push({ type: "skill", name: attachment.name, path: copied });
45
+ } else result.push({ type: "mention", name: attachment.name, path });
46
+ } else throw invalid();
47
+ } catch {
48
+ throw invalid();
49
+ }
50
+ }
51
+ return result;
52
+ }
53
+
54
+ // bridge/src/codex/native-approvals.ts
55
+ function createCodexNativeApprovalHandlers(options) {
56
+ const active = (signal, threadId) => !signal.aborted && isNativeApprovalPolicyActive(options.getPolicy(), threadId);
57
+ const text = (value) => typeof value === "string" && value.length > 0 && value.length <= 8192;
58
+ const scoped = async (path, access, signal, threadId) => active(signal, threadId) && text(path) && allowsNativeApprovalPath(options.getPolicy(), path, access) && active(signal, threadId);
59
+ const permissions = async (value, signal, threadId) => {
60
+ if (value.network?.enabled || value.network != null && Object.keys(value.network).some((key) => key !== "enabled") || Object.keys(value).some((key) => !["network", "fileSystem"].includes(key)))
61
+ return false;
62
+ const fs = value.fileSystem;
63
+ if (!fs) return true;
64
+ if (fs.entries != null || fs.globScanMaxDepth != null || Object.keys(fs).some((key) => !["read", "write", "entries", "globScanMaxDepth"].includes(key)))
65
+ return false;
66
+ for (const access of ["read", "write"]) {
67
+ const paths = fs[access];
68
+ if (paths != null && (!Array.isArray(paths) || paths.length > 32)) return false;
69
+ for (const path of paths ?? [])
70
+ if (!await scoped(path, access, signal, threadId)) return false;
71
+ }
72
+ return active(signal, threadId);
73
+ };
74
+ const consent = async (identity, approval, signal) => {
75
+ if (!active(signal, identity.threadId) || approval.details.length > 64 || approval.details.some((detail) => detail.length > 8192) || approval.details.reduce((sum, detail) => sum + detail.length, 0) > 65536)
76
+ return false;
77
+ try {
78
+ return await options.questions.requestApproval(identity, approval, signal) && active(signal, identity.threadId);
79
+ } catch {
80
+ return false;
81
+ }
82
+ };
83
+ return {
84
+ "item/commandExecution/requestApproval": async (input, signal) => {
85
+ const params = structuredClone(input);
86
+ const allowed = async () => active(signal, params.threadId) && text(params.command) && (params.kind == null || params.kind === "command") && !params.environmentId && !params.networkApprovalContext && (params.availableDecisions == null || params.availableDecisions.includes("accept")) && await scoped(params.cwd, "read", signal, params.threadId) && (!params.additionalPermissions || await permissions(params.additionalPermissions, signal, params.threadId));
87
+ if (!await allowed()) return { decision: "decline" };
88
+ const details = [`Command: ${params.command}`, `Directory: ${params.cwd}`];
89
+ for (const access of ["read", "write"])
90
+ for (const path of params.additionalPermissions?.fileSystem?.[access] ?? [])
91
+ details.push(`${access}: ${path}`);
92
+ const accepted = await consent(params, { kind: "command", details }, signal);
93
+ return { decision: accepted && await allowed() ? "accept" : "decline" };
94
+ },
95
+ "item/fileChange/requestApproval": async (input, signal) => {
96
+ const params = structuredClone(input);
97
+ if (!active(signal, params.threadId)) return { decision: "decline" };
98
+ const original = options.getFileChanges(params);
99
+ if (!original?.length || original.length > 16) return { decision: "decline" };
100
+ const changes = structuredClone(original);
101
+ const snapshot = JSON.stringify(changes);
102
+ const allowed = async () => {
103
+ if (!active(signal, params.threadId) || snapshot !== JSON.stringify(options.getFileChanges(params)))
104
+ return false;
105
+ if (params.grantRoot != null && !await scoped(params.grantRoot, "write", signal, params.threadId))
106
+ return false;
107
+ for (const change of changes) {
108
+ if (!text(change.diff) || !await scoped(change.path, "write", signal, params.threadId))
109
+ return false;
110
+ if (!["add", "delete", "update"].includes(change.kind.type)) return false;
111
+ if (change.kind.type === "update" && change.kind.move_path != null && !await scoped(change.kind.move_path, "write", signal, params.threadId))
112
+ return false;
113
+ }
114
+ return active(signal, params.threadId);
115
+ };
116
+ if (!await allowed()) return { decision: "decline" };
117
+ const details = changes.flatMap((change) => [
118
+ `${change.kind.type}: ${change.path}${change.kind.type === "update" && change.kind.move_path ? ` \u2192 ${change.kind.move_path}` : ""}`,
119
+ change.diff
120
+ ]);
121
+ const accepted = await consent(params, { kind: "file", details }, signal);
122
+ return { decision: accepted && await allowed() ? "accept" : "decline" };
123
+ },
124
+ "item/permissions/requestApproval": async (input, signal) => {
125
+ const params = structuredClone(input);
126
+ const allowed = async () => active(signal, params.threadId) && !params.environmentId && await scoped(params.cwd, "read", signal, params.threadId) && await permissions(params.permissions, signal, params.threadId);
127
+ if (!await allowed()) return { permissions: {}, scope: "turn" };
128
+ const details = [`Directory: ${params.cwd}`];
129
+ for (const access of ["read", "write"])
130
+ for (const path of params.permissions.fileSystem?.[access] ?? [])
131
+ details.push(`${access}: ${path}`);
132
+ if (details.length === 1) return { permissions: {}, scope: "turn" };
133
+ const accepted = await consent(params, { kind: "permissions", details }, signal);
134
+ return {
135
+ permissions: accepted && await allowed() ? params.permissions : {},
136
+ scope: "turn"
137
+ };
138
+ }
139
+ };
140
+ }
141
+ var CodexQuestions = class {
142
+ constructor(emit) {
143
+ this.emit = emit;
144
+ }
145
+ emit;
146
+ pending;
147
+ request = async (params, signal) => this.park(params, signal);
148
+ /** Park one explicit native consent request in the same slot as ordinary questions. */
149
+ async requestApproval(identity, approval, signal) {
150
+ const result = await this.park(
151
+ {
152
+ ...identity,
153
+ isBlocking: true,
154
+ questions: [
155
+ {
156
+ id: "native-approval",
157
+ header: "Approval",
158
+ question: approval.kind === "permissions" ? "Allow these permissions for the current turn?" : "Allow this native action once?",
159
+ options: [
160
+ {
161
+ label: "Approve once",
162
+ description: approval.kind === "permissions" ? "Allow for the current turn." : "Allow only this request."
163
+ },
164
+ { label: "Deny", description: "Do not allow this request." }
165
+ ]
166
+ }
167
+ ]
168
+ },
169
+ signal,
170
+ approval
171
+ );
172
+ return result.answers["native-approval"]?.answers[0] === "Approve once";
173
+ }
174
+ async park(params, signal, approval) {
175
+ signal.throwIfAborted();
176
+ if (this.pending || !params.isBlocking || !Array.isArray(params.questions) || params.questions.length === 0 || params.questions.length > 16 || params.questions.some((q) => !q.id || !q.question || q.isSecret) || new Set(params.questions.map((q) => q.id)).size !== params.questions.length || new Set(params.questions.map((q) => q.question)).size !== params.questions.length)
177
+ throw new Error("CODEX_INPUT_UNSUPPORTED");
178
+ const id = randomUUID();
179
+ return new Promise((resolve, reject) => {
180
+ const abort = () => finish();
181
+ const finish = (result) => {
182
+ if (this.pending?.id !== id) return;
183
+ this.pending = void 0;
184
+ signal.removeEventListener("abort", abort);
185
+ if (result && !signal.aborted) resolve(result);
186
+ else reject(new Error("CODEX_INPUT_CANCELLED"));
187
+ };
188
+ this.pending = {
189
+ id,
190
+ questions: params.questions,
191
+ answers: /* @__PURE__ */ Object.create(null),
192
+ finish,
193
+ approval
194
+ };
195
+ const input = {
196
+ requestId: id,
197
+ questions: params.questions,
198
+ ...approval ? { approval } : {}
199
+ };
200
+ signal.addEventListener("abort", abort, { once: true });
201
+ if (signal.aborted) {
202
+ abort();
203
+ return;
204
+ }
205
+ this.emit({
206
+ type: "message_start",
207
+ message: {
208
+ role: "assistant",
209
+ content: [
210
+ {
211
+ type: "tool_use",
212
+ name: "AskUserQuestion",
213
+ id: params.itemId,
214
+ input
215
+ }
216
+ ]
217
+ }
218
+ });
219
+ this.emit({
220
+ type: "tool_call",
221
+ name: "AskUserQuestion",
222
+ tool: { name: "AskUserQuestion" },
223
+ toolCallId: params.itemId,
224
+ input
225
+ });
226
+ });
227
+ }
228
+ get active() {
229
+ return Boolean(this.pending);
230
+ }
231
+ answer(answer, question, requestId) {
232
+ const pending = this.pending;
233
+ if (!pending || pending.id !== requestId || typeof answer !== "string") return false;
234
+ if (pending.approval && (question !== pending.questions[0]?.question || !["Approve once", "Deny"].includes(answer)))
235
+ return false;
236
+ const q = question === void 0 ? pending.questions.find((entry) => !Object.hasOwn(pending.answers, entry.id)) : pending.questions.find((entry) => entry.question === question);
237
+ if (!q || Object.hasOwn(pending.answers, q.id)) return false;
238
+ pending.answers[q.id] = { answers: [answer] };
239
+ if (pending.questions.every((entry) => Object.hasOwn(pending.answers, entry.id)))
240
+ pending.finish({ answers: pending.answers });
241
+ return true;
242
+ }
243
+ };
244
+
245
+ // bridge/src/codex/managed-driver.ts
246
+ var record = (value) => value !== null && typeof value === "object" && !Array.isArray(value);
247
+ var failure = (code = "CODEX_RUNTIME_UNSUPPORTED") => new Error(code);
248
+ var nativeUsage = (value) => ({
249
+ ...typeof value.inputTokens === "number" ? { inputTokens: value.inputTokens } : {},
250
+ ...typeof value.outputTokens === "number" ? { outputTokens: value.outputTokens } : {},
251
+ ...typeof value.cachedInputTokens === "number" ? { cacheReadTokens: value.cachedInputTokens } : {},
252
+ ...typeof value.reasoningOutputTokens === "number" ? { reasoningTokens: value.reasoningOutputTokens } : {},
253
+ ...typeof value.totalTokens === "number" ? { totalTokens: value.totalTokens } : {}
254
+ });
255
+ var subtractUsage = (total, baseline) => {
256
+ const delta = (value, before) => value === void 0 ? void 0 : Math.max(0, value - (before ?? 0));
257
+ return {
258
+ ...delta(total.inputTokens, baseline?.inputTokens) !== void 0 ? { inputTokens: delta(total.inputTokens, baseline?.inputTokens) } : {},
259
+ ...delta(total.outputTokens, baseline?.outputTokens) !== void 0 ? { outputTokens: delta(total.outputTokens, baseline?.outputTokens) } : {},
260
+ ...delta(total.cacheReadTokens, baseline?.cacheReadTokens) !== void 0 ? {
261
+ cacheReadTokens: delta(total.cacheReadTokens, baseline?.cacheReadTokens)
262
+ } : {},
263
+ ...delta(total.reasoningTokens, baseline?.reasoningTokens) !== void 0 ? {
264
+ reasoningTokens: delta(total.reasoningTokens, baseline?.reasoningTokens)
265
+ } : {},
266
+ ...delta(total.totalTokens, baseline?.totalTokens) !== void 0 ? { totalTokens: delta(total.totalTokens, baseline?.totalTokens) } : {}
267
+ };
268
+ };
269
+ var addUsage = (left, right) => {
270
+ const result = {};
271
+ for (const key of [
272
+ "inputTokens",
273
+ "outputTokens",
274
+ "cacheReadTokens",
275
+ "reasoningTokens",
276
+ "totalTokens"
277
+ ]) {
278
+ if (left?.[key] !== void 0 || right[key] !== void 0)
279
+ result[key] = (left?.[key] ?? 0) + (right[key] ?? 0);
280
+ }
281
+ return result;
282
+ };
283
+ var limit = (value, fallback) => {
284
+ const result = value ?? fallback;
285
+ if (!Number.isSafeInteger(result) || result <= 0 || result > 18e5)
286
+ throw failure("AI_PROFILE_INVALID");
287
+ return result;
288
+ };
289
+ async function bounded(work, signal, ms) {
290
+ let timer;
291
+ let cancel = () => {
292
+ };
293
+ try {
294
+ return await Promise.race([
295
+ work,
296
+ new Promise((_, reject) => {
297
+ cancel = () => reject(failure());
298
+ if (signal.aborted) cancel();
299
+ else signal.addEventListener("abort", cancel, { once: true });
300
+ timer = setTimeout(() => reject(failure()), ms);
301
+ })
302
+ ]);
303
+ } finally {
304
+ clearTimeout(timer);
305
+ signal.removeEventListener("abort", cancel);
306
+ }
307
+ }
308
+ var ManagedCodexDriver = class extends AgentDriver {
309
+ constructor(config) {
310
+ super();
311
+ this.config = config;
312
+ }
313
+ config;
314
+ driverInfo = {
315
+ id: "codex",
316
+ name: "OpenAI Codex",
317
+ modelAgnostic: false,
318
+ supportsInBandAbort: true
319
+ };
320
+ client;
321
+ connecting;
322
+ options;
323
+ credential;
324
+ nativeApprovalPolicy;
325
+ instance;
326
+ tools;
327
+ mcpStartup = "unknown";
328
+ pendingMcpStartup;
329
+ mcpDiagnostics = {
330
+ startupBeforeTurn: "unknown",
331
+ startupAtEnd: "unknown",
332
+ toolsListBeforeTurn: 0,
333
+ toolsListTotal: 0,
334
+ toolsCallTotal: 0,
335
+ nativeMcpToolItemCount: 0
336
+ };
337
+ controller = new AbortController();
338
+ generation = 0;
339
+ killed = false;
340
+ broken = false;
341
+ cleanupUncertain = false;
342
+ unexpectedClose = false;
343
+ starting;
344
+ closing = Promise.resolve();
345
+ threadId;
346
+ lastThreadId;
347
+ resetting;
348
+ pendingPatch;
349
+ active;
350
+ threadUsageTotal;
351
+ resumeUsageTurnIds = /* @__PURE__ */ new Set();
352
+ queue = Promise.resolve();
353
+ queued = 0;
354
+ admittedTurns = 0;
355
+ loginCompleted;
356
+ startupRefreshUsed = false;
357
+ startupAuthAttempted = false;
358
+ questions = new CodexQuestions((event) => this.event(event));
359
+ get acceptsReplyAsPrompt() {
360
+ return false;
361
+ }
362
+ hasPendingQuestion() {
363
+ return this.questions.active;
364
+ }
365
+ answerQuestion(answer, question, requestId) {
366
+ return this.questions.answer(answer, question, requestId);
367
+ }
368
+ get runtimeSessionId() {
369
+ return this.threadId ?? this.lastThreadId;
370
+ }
371
+ get isRunning() {
372
+ return Boolean(this.client && this.threadId && !this.killed && !this.broken);
373
+ }
374
+ getModel() {
375
+ return this.config.model;
376
+ }
377
+ async start() {
378
+ if (this.killed || this.broken) throw failure();
379
+ if (this.threadId && this.client) return;
380
+ if (this.starting) return this.starting;
381
+ this.starting = this.initialize().catch(async (error) => {
382
+ this.broken = true;
383
+ await this.closeGeneration();
384
+ if (error instanceof CodexNativeStateUnavailable && (this.cleanupUncertain || this.unexpectedClose || this.killed || this.startupAuthAttempted))
385
+ throw failure();
386
+ const safe = error instanceof Error && /^(AI_PROFILE_INVALID|CODEX_[A-Z_]+)$/.test(error.message) ? error : failure();
387
+ throw safe;
388
+ }).finally(() => {
389
+ this.starting = void 0;
390
+ });
391
+ return this.starting;
392
+ }
393
+ async initialize() {
394
+ await this.closing;
395
+ if (this.killed) throw failure();
396
+ const options = this.config.driverOptions?.codex?.managedRuntime;
397
+ const tuning = this.config.driverOptions?.codex;
398
+ if (tuning?.authSource !== "managed" || !options || typeof options.prepareTools !== "function" || !isAbsolute(options.executable) || !this.config.model || !tuning.reasoningEffort || !tuning.approvalPolicy || tuning.approvalPolicy === "on-failure" || !tuning.sandboxMode || tuning.sandboxMode === "danger-full-access" || this.config.provider && this.config.provider !== "openai" || this.config.apiKeys?.openai || this.config.env?.OPENAI_API_KEY || options.nativeTurnBudget !== void 0 && options.nativeTurnBudget !== 1)
399
+ throw failure("AI_PROFILE_INVALID");
400
+ this.options = options;
401
+ const timeout = limit(options.requestTimeoutMs, 15e3);
402
+ limit(options.turnTimeoutMs, 3e5);
403
+ try {
404
+ this.credential = parseCodexCredential(this.credential ?? options.credential);
405
+ } catch {
406
+ throw failure("CODEX_AUTH_UNAVAILABLE");
407
+ }
408
+ if (this.credential.configId !== this.config.aiProviderConfigId)
409
+ throw failure("AI_PROFILE_INVALID");
410
+ const privatePolicy = prepareNativePolicy({
411
+ cwd: this.config.cwd,
412
+ privateRoot: options.privateRoot,
413
+ privateDirectory: options.privateDirectory,
414
+ sandboxMode: tuning.sandboxMode
415
+ });
416
+ this.instance = prepareCodexInstance(this.config, options, this.credential);
417
+ const generation = ++this.generation;
418
+ this.controller = new AbortController();
419
+ this.startupRefreshUsed = false;
420
+ this.startupAuthAttempted = false;
421
+ const handlers = {
422
+ "account/chatgptAuthTokens/refresh": async (params, signal) => {
423
+ const active = this.active;
424
+ if (!active) this.startupAuthAttempted = true;
425
+ const cancellation = AbortSignal.any([
426
+ signal,
427
+ this.controller.signal,
428
+ ...active ? [active.controller.signal] : []
429
+ ]);
430
+ try {
431
+ return await this.refresh(params, cancellation);
432
+ } catch {
433
+ if (active && this.active === active) active.failureCode = "CODEX_AUTH_UNAVAILABLE";
434
+ throw failure("CODEX_AUTH_UNAVAILABLE");
435
+ }
436
+ }
437
+ };
438
+ const authMode = this.credential.kind === "codex-subscription" ? "chatgpt" : "api";
439
+ const nativePolicy = {
440
+ cli_auth_credentials_store: "ephemeral",
441
+ forced_login_method: authMode,
442
+ model_provider: "openai",
443
+ model: this.config.model,
444
+ model_instructions_file: this.instance.instructionFile,
445
+ shell_environment_policy: {
446
+ inherit: "none",
447
+ set: { PATH: options.environment.PATH ?? "/usr/bin:/bin" }
448
+ },
449
+ mcp_servers: {}
450
+ };
451
+ const overrides = Object.entries({
452
+ cli_auth_credentials_store: "ephemeral",
453
+ forced_login_method: authMode,
454
+ model_provider: "openai",
455
+ model: this.config.model,
456
+ model_instructions_file: this.instance.instructionFile,
457
+ "shell_environment_policy.inherit": "none",
458
+ "shell_environment_policy.set.PATH": options.environment.PATH ?? "/usr/bin:/bin"
459
+ }).flatMap(([key, value]) => ["-c", `${key}=${JSON.stringify(value)}`]);
460
+ overrides.push("-c", "mcp_servers={}");
461
+ const connecting = CodexAppServerClient.connect(
462
+ {
463
+ command: options.executable,
464
+ args: [
465
+ ...options.executableArgs ?? [],
466
+ ...overrides,
467
+ ...privatePolicy.cliArgs,
468
+ "app-server",
469
+ "--stdio"
470
+ ],
471
+ cwd: this.instance.root,
472
+ env: codexInstanceEnvironment(options.environment, this.instance.home),
473
+ clientInfo: { name: "skaile-managed-codex", version: "1" },
474
+ processGroup: true,
475
+ requestTimeoutMs: timeout,
476
+ serverRequestTimeoutMs: Math.min(limit(options.interactionTimeoutMs, 3e5), 3e5),
477
+ onServerRequest: handlers,
478
+ onNotification: (method, params) => {
479
+ if (generation === this.generation) this.notification(method, params);
480
+ },
481
+ onClose: () => {
482
+ if (generation !== this.generation) return;
483
+ this.unexpectedClose = true;
484
+ this.broken = true;
485
+ this.loginCompleted?.reject(failure());
486
+ this.finishTurn("CODEX_RUNTIME_UNSUPPORTED");
487
+ void this.closeGeneration();
488
+ }
489
+ },
490
+ this.controller.signal
491
+ );
492
+ this.connecting = connecting;
493
+ try {
494
+ this.client = await connecting;
495
+ } finally {
496
+ if (this.connecting === connecting) this.connecting = void 0;
497
+ }
498
+ if (generation !== this.generation || this.killed) throw failure();
499
+ await this.authenticate(timeout);
500
+ const toolsPromise = options.prepareTools(this.controller.signal).then(async (tools) => {
501
+ if (generation !== this.generation || this.controller.signal.aborted) {
502
+ await tools.dispose().catch(() => {
503
+ });
504
+ throw failure();
505
+ }
506
+ return tools;
507
+ });
508
+ try {
509
+ this.tools = await bounded(toolsPromise, this.controller.signal, timeout);
510
+ } catch {
511
+ throw failure("CODEX_REQUIRED_TOOL_UNAVAILABLE");
512
+ }
513
+ if (!this.tools || !record(this.tools.mcpServers) || typeof this.tools.dispose !== "function" || Object.keys(this.tools.mcpServers).length === 0 && Object.keys(this.tools.onServerRequest ?? {}).length === 0)
514
+ throw failure("CODEX_REQUIRED_TOOL_UNAVAILABLE");
515
+ if (this.tools.onServerRequest?.["item/tool/requestUserInput"])
516
+ throw failure("AI_PROFILE_INVALID");
517
+ const nativeApprovals = createCodexNativeApprovalHandlers({
518
+ questions: this.questions,
519
+ getPolicy: () => tuning.approvalPolicy === "never" ? void 0 : this.nativeApprovalPolicy,
520
+ getFileChanges: ({ itemId, threadId, turnId }) => {
521
+ const active = this.active;
522
+ if (!active || active.controller.signal.aborted || threadId !== this.threadId || turnId !== active.id)
523
+ return void 0;
524
+ const snapshot = active.fileChanges.get(itemId);
525
+ return snapshot ? JSON.parse(snapshot) : void 0;
526
+ }
527
+ });
528
+ for (const [method, handler] of Object.entries({
529
+ ...this.tools.onServerRequest,
530
+ ...nativeApprovals,
531
+ "item/tool/requestUserInput": this.questions.request
532
+ })) {
533
+ if (method === "account/chatgptAuthTokens/refresh" || !handler)
534
+ throw failure("AI_PROFILE_INVALID");
535
+ handlers[method] = async (params, signal) => {
536
+ const active = this.active;
537
+ if (generation !== this.generation || !active || !record(params)) throw failure();
538
+ await active.ready;
539
+ if (generation !== this.generation || this.active !== active || params.threadId !== this.threadId || params.turnId !== active.id)
540
+ throw failure();
541
+ const cancellation = AbortSignal.any([signal, active.controller.signal]);
542
+ if (cancellation.aborted) throw failure();
543
+ const result = await handler(params, cancellation);
544
+ if (generation !== this.generation || cancellation.aborted || this.active !== active)
545
+ throw failure();
546
+ return result;
547
+ };
548
+ }
549
+ if (this.tools.instructions) this.instance.setToolInstructions(this.tools.instructions);
550
+ const threadParams = {
551
+ model: this.config.model,
552
+ modelProvider: "openai",
553
+ cwd: this.instance.cwd,
554
+ approvalPolicy: tuning.approvalPolicy,
555
+ permissions: "managed",
556
+ config: {
557
+ ...nativePolicy,
558
+ ...privatePolicy.config,
559
+ mcp_servers: this.tools.mcpServers,
560
+ model_reasoning_effort: this.config.effort ?? tuning.reasoningEffort
561
+ }
562
+ };
563
+ const resuming = Boolean(this.config.resumeSessionId);
564
+ this.threadUsageTotal = resuming ? this.threadUsageTotal ?? {} : {};
565
+ this.resumeUsageTurnIds.clear();
566
+ const response = resuming ? await this.client.request("thread/resume", {
567
+ ...threadParams,
568
+ threadId: this.config.resumeSessionId,
569
+ excludeTurns: false
570
+ }) : await this.client.request("thread/start", {
571
+ ...threadParams,
572
+ allowProviderModelFallback: false
573
+ });
574
+ if (!record(response) || response.model !== this.config.model)
575
+ throw failure("CODEX_MODEL_UNAVAILABLE");
576
+ if (!record(response.thread) || typeof response.thread.id !== "string" || resuming && response.thread.id !== this.config.resumeSessionId || resuming && !Array.isArray(response.thread.turns) || response.reasoningEffort !== (this.config.effort ?? tuning.reasoningEffort) || response.modelProvider !== "openai" || response.approvalPolicy !== tuning.approvalPolicy)
577
+ throw failure("AI_PROFILE_INVALID");
578
+ if (generation !== this.generation || this.killed) throw failure();
579
+ this.resumeUsageTurnIds = new Set(
580
+ resuming && Array.isArray(response.thread.turns) ? response.thread.turns.flatMap(
581
+ (turn) => record(turn) && typeof turn.id === "string" ? [turn.id] : []
582
+ ) : []
583
+ );
584
+ this.nativeApprovalPolicy = activateNativeApprovalPolicy(
585
+ privatePolicy,
586
+ response,
587
+ this.controller.signal
588
+ );
589
+ this.threadId = response.thread.id;
590
+ this.mcpStartup = this.pendingMcpStartup?.threadId === this.threadId ? this.pendingMcpStartup.status : "unknown";
591
+ this.pendingMcpStartup = void 0;
592
+ this.lastThreadId = this.threadId;
593
+ this.instance.bindThread(this.threadId);
594
+ }
595
+ async authenticate(timeout) {
596
+ const credential = this.credential;
597
+ if (credential.kind === "openai-api-key") {
598
+ const result = await this.client.request("account/login/start", {
599
+ type: "apiKey",
600
+ apiKey: credential.apiKey
601
+ });
602
+ if (result.type !== "apiKey") throw failure("CODEX_AUTH_UNAVAILABLE");
603
+ return;
604
+ }
605
+ const completion = new Promise((resolve, reject) => {
606
+ this.loginCompleted = { resolve, reject };
607
+ });
608
+ const wait = bounded(completion, this.controller.signal, timeout);
609
+ void wait.catch(() => {
610
+ });
611
+ try {
612
+ const result = await this.client.request("account/login/start", {
613
+ type: "chatgptAuthTokens",
614
+ accessToken: credential.accessToken,
615
+ chatgptAccountId: credential.chatgptAccountId,
616
+ chatgptPlanType: credential.chatgptPlanType ?? null
617
+ });
618
+ if (result.type !== "chatgptAuthTokens") throw failure("CODEX_AUTH_UNAVAILABLE");
619
+ await wait;
620
+ } finally {
621
+ this.loginCompleted = void 0;
622
+ }
623
+ }
624
+ async refresh(params, signal) {
625
+ const credential = this.credential;
626
+ if (!record(params) || params.reason !== "unauthorized" || !credential || credential.kind !== "codex-subscription" || params.previousAccountId != null && params.previousAccountId !== credential.chatgptAccountId || !this.options?.refreshCredential || (this.active ? this.active.refreshUsed : this.startupRefreshUsed))
627
+ throw failure("CODEX_AUTH_UNAVAILABLE");
628
+ if (this.active) this.active.refreshUsed = true;
629
+ else this.startupRefreshUsed = true;
630
+ const result = await this.options.refreshCredential(
631
+ {
632
+ kind: "codex-subscription",
633
+ configId: credential.configId,
634
+ credentialVersion: credential.credentialVersion,
635
+ reason: "retry-401"
636
+ },
637
+ signal
638
+ );
639
+ if (signal.aborted) throw failure("CODEX_AUTH_UNAVAILABLE");
640
+ let parsed;
641
+ try {
642
+ parsed = parseCodexRefreshResult(result, credential);
643
+ } catch {
644
+ throw failure("CODEX_AUTH_UNAVAILABLE");
645
+ }
646
+ if (!parsed.ok) throw failure("CODEX_AUTH_UNAVAILABLE");
647
+ this.credential = parsed.credential;
648
+ return {
649
+ accessToken: parsed.credential.accessToken,
650
+ chatgptAccountId: parsed.credential.chatgptAccountId,
651
+ chatgptPlanType: parsed.credential.chatgptPlanType ?? null
652
+ };
653
+ }
654
+ prompt(message) {
655
+ return this.promptInput({ text: message });
656
+ }
657
+ promptInput(input) {
658
+ const message = structuredClone(input);
659
+ const turnBudget = this.config.driverOptions?.codex?.managedRuntime?.nativeTurnBudget;
660
+ if (this.killed || this.broken || this.resetting || this.queued >= 32 || turnBudget !== void 0 && this.admittedTurns >= turnBudget)
661
+ return Promise.reject(failure());
662
+ if (turnBudget !== void 0) this.admittedTurns++;
663
+ this.queued++;
664
+ const task = this.queue.then(() => this.runTurn(message));
665
+ this.queue = task.catch(() => {
666
+ }).finally(() => {
667
+ this.queued--;
668
+ });
669
+ return task;
670
+ }
671
+ async runTurn(message) {
672
+ if (this.resetting) throw failure();
673
+ await this.start();
674
+ if (this.killed || this.broken || this.resetting) throw failure();
675
+ if (this.pendingPatch) {
676
+ this.config = { ...this.config, ...this.pendingPatch };
677
+ this.pendingPatch = void 0;
678
+ }
679
+ if (!this.config.model) throw failure("AI_PROFILE_INVALID");
680
+ await this.tools?.validate?.();
681
+ if (this.tools?.needsReload?.()) {
682
+ this.config = { ...this.config, resumeSessionId: this.threadId };
683
+ await this.closeGeneration();
684
+ await this.start();
685
+ }
686
+ const input = codexPromptInput(
687
+ message,
688
+ this.instance.cwd,
689
+ this.options?.skillsDirectory ? {
690
+ source: this.options.skillsDirectory,
691
+ target: join(this.instance.home, "skills")
692
+ } : void 0
693
+ );
694
+ try {
695
+ parseCodexCredential(this.credential);
696
+ } catch {
697
+ throw failure("CODEX_AUTH_UNAVAILABLE");
698
+ }
699
+ let finish;
700
+ let readyNow;
701
+ const ready = new Promise((resolve) => {
702
+ readyNow = resolve;
703
+ });
704
+ const done = new Promise((resolve) => {
705
+ finish = resolve;
706
+ });
707
+ const active = {
708
+ controller: new AbortController(),
709
+ done,
710
+ finish,
711
+ ready,
712
+ readyNow,
713
+ timer: setTimeout(
714
+ () => {
715
+ this.finishTurn("CODEX_RUNTIME_UNSUPPORTED");
716
+ this.broken = true;
717
+ void this.closeGeneration();
718
+ },
719
+ limit(this.options?.turnTimeoutMs, 3e5)
720
+ ),
721
+ events: [],
722
+ messages: /* @__PURE__ */ new Map(),
723
+ fileChanges: /* @__PURE__ */ new Map(),
724
+ toolResults: [],
725
+ toolItems: /* @__PURE__ */ new Set(),
726
+ completedToolItems: /* @__PURE__ */ new Set(),
727
+ refreshUsed: false,
728
+ usageBaseline: this.threadUsageTotal,
729
+ actualModel: this.config.model
730
+ };
731
+ this.active = active;
732
+ this.mcpDiagnostics.nativeMcpToolItemCount = 0;
733
+ this.observeMcp(true);
734
+ this.tools?.beginTurn?.(active.controller.signal);
735
+ try {
736
+ const response = await this.client.request("turn/start", {
737
+ threadId: this.threadId,
738
+ permissions: "managed",
739
+ input,
740
+ model: this.config.model,
741
+ effort: this.config.effort ?? this.config.driverOptions.codex.reasoningEffort
742
+ });
743
+ if (this.active !== active) return;
744
+ if (!record(response.turn) || typeof response.turn.id !== "string") throw failure();
745
+ active.id = response.turn.id;
746
+ active.readyNow();
747
+ for (const event of active.events.splice(0)) this.notification(event.method, event.params);
748
+ if (this.active === active && response.turn.status !== "inProgress")
749
+ this.complete(response.turn);
750
+ await done;
751
+ } catch {
752
+ this.finishTurn("CODEX_RUNTIME_UNSUPPORTED");
753
+ }
754
+ }
755
+ async abort() {
756
+ const active = this.active;
757
+ if (!active) return;
758
+ active.controller.abort();
759
+ try {
760
+ if (!active.id)
761
+ await bounded(
762
+ active.ready,
763
+ this.controller.signal,
764
+ limit(this.options?.requestTimeoutMs, 15e3)
765
+ );
766
+ if (this.active !== active) return;
767
+ await this.client.request("turn/interrupt", {
768
+ threadId: this.threadId,
769
+ turnId: active.id
770
+ });
771
+ await bounded(
772
+ active.done,
773
+ this.controller.signal,
774
+ limit(this.options?.requestTimeoutMs, 15e3)
775
+ );
776
+ } catch {
777
+ this.finishTurn("CODEX_RUNTIME_UNSUPPORTED");
778
+ this.broken = true;
779
+ await this.closeGeneration();
780
+ }
781
+ }
782
+ kill() {
783
+ if (this.killed) return;
784
+ this.killed = true;
785
+ this.finishTurn("CODEX_RUNTIME_UNSUPPORTED");
786
+ void this.closeGeneration();
787
+ }
788
+ async dispose() {
789
+ this.kill();
790
+ await this.starting?.catch(() => {
791
+ });
792
+ await this.closing;
793
+ }
794
+ async resetSession() {
795
+ if (this.killed || this.broken) throw failure();
796
+ if (this.resetting) return this.resetting;
797
+ this.resetting = Promise.resolve().then(async () => {
798
+ if (this.active) await this.abort();
799
+ await this.queue;
800
+ await this.starting;
801
+ await this.closeGeneration();
802
+ if (this.killed || this.broken) throw failure();
803
+ this.config = { ...this.config, resumeSessionId: void 0 };
804
+ this.lastThreadId = void 0;
805
+ this.threadUsageTotal = void 0;
806
+ }).finally(() => {
807
+ this.resetting = void 0;
808
+ });
809
+ return this.resetting;
810
+ }
811
+ reconfigure(patch) {
812
+ this.pendingPatch = { ...this.pendingPatch, ...patch };
813
+ }
814
+ closeGeneration() {
815
+ ++this.generation;
816
+ this.mcpStartup = "unknown";
817
+ this.pendingMcpStartup = void 0;
818
+ this.controller.abort();
819
+ this.nativeApprovalPolicy = void 0;
820
+ this.loginCompleted?.reject(failure());
821
+ this.loginCompleted = void 0;
822
+ const client = this.client;
823
+ this.client = void 0;
824
+ const connecting = this.connecting;
825
+ this.connecting = void 0;
826
+ const tools = this.tools;
827
+ this.tools = void 0;
828
+ const instance = this.instance;
829
+ this.instance = void 0;
830
+ this.threadId = void 0;
831
+ this.closing = this.closing.then(async () => {
832
+ try {
833
+ const pendingClient = await connecting?.catch(() => void 0);
834
+ await client?.dispose();
835
+ if (pendingClient && pendingClient !== client) await pendingClient.dispose();
836
+ if (client && !client.terminationConfirmed || pendingClient && !pendingClient.terminationConfirmed)
837
+ this.cleanupUncertain = true;
838
+ if (tools)
839
+ await bounded(
840
+ Promise.resolve().then(() => tools.dispose()),
841
+ new AbortController().signal,
842
+ 1e3
843
+ ).catch(() => {
844
+ this.cleanupUncertain = true;
845
+ });
846
+ } finally {
847
+ instance?.release();
848
+ }
849
+ }).catch(() => {
850
+ this.cleanupUncertain = true;
851
+ });
852
+ return this.closing;
853
+ }
854
+ notification(method, params) {
855
+ if (!record(params)) return;
856
+ if (method === "mcpServer/startupStatus/updated") {
857
+ const serverName = this.tools?.diagnostics?.serverName;
858
+ if (!serverName || params.name !== serverName || typeof params.threadId !== "string" || params.threadId.length > 512 || typeof params.status !== "string" || !["starting", "ready", "failed", "cancelled"].includes(params.status))
859
+ return;
860
+ const status = params.status;
861
+ if (this.threadId) {
862
+ if (params.threadId === this.threadId) this.mcpStartup = status;
863
+ } else this.pendingMcpStartup = { threadId: params.threadId, status };
864
+ return;
865
+ }
866
+ if (method === "account/login/completed") {
867
+ if (params.success === true && params.loginId == null) this.loginCompleted?.resolve();
868
+ else this.loginCompleted?.reject(failure("CODEX_AUTH_UNAVAILABLE"));
869
+ return;
870
+ }
871
+ const active = this.active;
872
+ if ((!active || !active.usageCursor && this.resumeUsageTurnIds.has(String(params.turnId))) && method === "thread/tokenUsage/updated" && params.threadId === (this.threadId ?? this.config.resumeSessionId) && record(params.tokenUsage) && record(params.tokenUsage.total)) {
873
+ this.threadUsageTotal = nativeUsage(params.tokenUsage.total);
874
+ if (active) active.usageBaseline = this.threadUsageTotal;
875
+ return;
876
+ }
877
+ if (!active || params.threadId !== this.threadId) return;
878
+ if (!active.id) {
879
+ if (active.events.length >= 256) {
880
+ this.broken = true;
881
+ this.finishTurn("CODEX_RUNTIME_UNSUPPORTED");
882
+ void this.closeGeneration();
883
+ } else active.events.push({ method, params });
884
+ return;
885
+ }
886
+ const turnId = record(params.turn) ? params.turn.id : params.turnId;
887
+ if (turnId !== active.id) return;
888
+ if (method === "thread/tokenUsage/updated" && record(params.tokenUsage)) {
889
+ const last = params.tokenUsage.last;
890
+ const total = params.tokenUsage.total;
891
+ const cumulativeUsage = record(total) ? nativeUsage(total) : void 0;
892
+ if (cumulativeUsage) {
893
+ active.usageBaseline ??= {};
894
+ this.resumeUsageTurnIds.clear();
895
+ const cursor = active.usageCursor ?? active.usageBaseline;
896
+ const reset = cursor?.totalTokens !== void 0 && cumulativeUsage.totalTokens !== void 0 && cumulativeUsage.totalTokens < cursor.totalTokens;
897
+ const increment = reset ? cumulativeUsage : subtractUsage(cumulativeUsage, cursor);
898
+ if (Object.values(increment).some((value) => typeof value === "number" && value > 0))
899
+ active.usage = addUsage(active.usage, increment);
900
+ active.usageCursor = cumulativeUsage;
901
+ this.threadUsageTotal = cumulativeUsage;
902
+ }
903
+ if (record(last)) {
904
+ if (typeof last.totalTokens === "number") active.contextTokens = last.totalTokens;
905
+ }
906
+ if (typeof params.tokenUsage.modelContextWindow === "number")
907
+ active.contextWindow = params.tokenUsage.modelContextWindow;
908
+ } else if (method === "model/rerouted") {
909
+ active.actualModel = typeof params.toModel === "string" ? params.toModel : active.actualModel;
910
+ active.failureCode = "CODEX_MODEL_UNAVAILABLE";
911
+ } else if (method === "turn/completed" && record(params.turn)) this.complete(params.turn);
912
+ else if (method === "error" && params.willRetry !== true)
913
+ active.failureCode = this.nativeErrorCode(params.error);
914
+ else if (method === "item/agentMessage/delta" && typeof params.itemId === "string" && typeof params.delta === "string") {
915
+ const previous = active.messages.get(params.itemId);
916
+ if (previous === void 0)
917
+ this.event({
918
+ type: "message_start",
919
+ message: { role: "assistant", content: [{ type: "text", text: "" }] }
920
+ });
921
+ const text = (previous ?? "") + params.delta;
922
+ active.messages.set(params.itemId, text);
923
+ this.event({
924
+ type: "message_update",
925
+ message: { role: "assistant", content: [{ type: "text", text }] },
926
+ _textDelta: params.delta
927
+ });
928
+ } else if ((method === "item/started" || method === "item/completed") && record(params.item) && typeof params.item.id === "string") {
929
+ this.item(
930
+ params.item,
931
+ method === "item/completed"
932
+ );
933
+ }
934
+ }
935
+ item(item, completed) {
936
+ const active = this.active;
937
+ if (item.type === "fileChange") {
938
+ active.fileChanges.delete(item.id);
939
+ if (!completed && Array.isArray(item.changes) && item.changes.length <= 16 && active.fileChanges.size < 16) {
940
+ const snapshot = JSON.stringify(item.changes);
941
+ if (snapshot.length <= 65536) active.fileChanges.set(item.id, snapshot);
942
+ }
943
+ }
944
+ if (item.type === "agentMessage") {
945
+ if (completed && typeof item.text === "string") {
946
+ const previous = active.messages.get(item.id) ?? "";
947
+ if (!active.messages.has(item.id))
948
+ this.event({
949
+ type: "message_start",
950
+ message: {
951
+ role: "assistant",
952
+ content: [{ type: "text", text: "" }]
953
+ }
954
+ });
955
+ if (item.text.startsWith(previous) && item.text.length > previous.length)
956
+ this.event({
957
+ type: "message_update",
958
+ message: {
959
+ role: "assistant",
960
+ content: [{ type: "text", text: item.text }]
961
+ },
962
+ _textDelta: item.text.slice(previous.length)
963
+ });
964
+ active.messages.set(item.id, item.text);
965
+ }
966
+ return;
967
+ }
968
+ const name = item.type === "commandExecution" ? "Bash" : item.type === "fileChange" ? "ApplyPatch" : item.type === "mcpToolCall" ? `mcp__${item.server}__${item.tool}` : void 0;
969
+ if (!name) return;
970
+ if (!active.toolItems.has(item.id)) {
971
+ if (item.type === "mcpToolCall" && item.server === this.tools?.diagnostics?.serverName)
972
+ this.mcpDiagnostics.nativeMcpToolItemCount = Math.min(
973
+ 512,
974
+ this.mcpDiagnostics.nativeMcpToolItemCount + 1
975
+ );
976
+ active.toolItems.add(item.id);
977
+ this.event({
978
+ type: "tool_call",
979
+ name,
980
+ tool: { name },
981
+ toolCallId: item.id,
982
+ input: item.type === "mcpToolCall" ? item.arguments : item.type === "commandExecution" ? { command: item.command } : item.type === "fileChange" ? { changes: item.changes } : {}
983
+ });
984
+ }
985
+ if (completed && !active.completedToolItems.has(item.id)) {
986
+ active.completedToolItems.add(item.id);
987
+ active.toolResults.push({
988
+ role: "tool",
989
+ toolName: name,
990
+ content: "",
991
+ data: item.type === "mcpToolCall" ? {
992
+ content: item.result?.content,
993
+ structuredContent: item.result?.structuredContent,
994
+ status: item.status
995
+ } : item.type === "commandExecution" ? {
996
+ output: item.aggregatedOutput,
997
+ exitCode: item.exitCode,
998
+ status: item.status
999
+ } : item.type === "fileChange" ? { changes: item.changes, status: item.status } : {},
1000
+ isError: "status" in item && item.status === "failed"
1001
+ });
1002
+ this.event({ type: "tool_execution_end", toolName: name });
1003
+ }
1004
+ }
1005
+ complete(turn) {
1006
+ if (turn.status === "completed") this.finishTurn(this.active?.failureCode);
1007
+ else if (turn.status === "interrupted") this.finishTurn("CODEX_TURN_INTERRUPTED");
1008
+ else if (turn.status === "failed")
1009
+ this.finishTurn(this.active?.failureCode ?? this.nativeErrorCode(turn.error));
1010
+ }
1011
+ nativeErrorCode(error) {
1012
+ const info = record(error) ? error.codexErrorInfo : void 0;
1013
+ if (info === "unauthorized") return "CODEX_RECONNECT_REQUIRED";
1014
+ if (info === "usageLimitExceeded" || info === "rateLimitExceeded" || info === "serverOverloaded")
1015
+ return "CODEX_RATE_LIMITED";
1016
+ if (record(info) && [
1017
+ "httpConnectionFailed",
1018
+ "responseStreamConnectionFailed",
1019
+ "responseStreamDisconnected",
1020
+ "responseTooManyFailedAttempts"
1021
+ ].some((key) => key in info))
1022
+ return "CODEX_NETWORK_UNAVAILABLE";
1023
+ return "CODEX_RUNTIME_UNSUPPORTED";
1024
+ }
1025
+ observeMcp(beforeTurn) {
1026
+ const count = (value) => typeof value === "number" && Number.isSafeInteger(value) && value >= 0 ? Math.min(512, value) : 0;
1027
+ let listed = 0;
1028
+ let called = 0;
1029
+ try {
1030
+ const counts = this.tools?.diagnostics?.requestCounts();
1031
+ listed = count(counts?.toolsListTotal);
1032
+ called = count(counts?.toolsCallTotal);
1033
+ } catch {
1034
+ }
1035
+ if (beforeTurn) {
1036
+ this.mcpDiagnostics.startupBeforeTurn = this.mcpStartup;
1037
+ this.mcpDiagnostics.toolsListBeforeTurn = listed;
1038
+ }
1039
+ this.mcpDiagnostics.startupAtEnd = this.mcpStartup;
1040
+ this.mcpDiagnostics.toolsListTotal = Math.max(this.mcpDiagnostics.toolsListBeforeTurn, listed);
1041
+ this.mcpDiagnostics.toolsCallTotal = beforeTurn ? called : Math.max(this.mcpDiagnostics.toolsCallTotal, called);
1042
+ try {
1043
+ void Promise.resolve(
1044
+ this.options?.onNativeMcpDiagnostics?.(Object.freeze({ ...this.mcpDiagnostics }))
1045
+ ).catch(() => {
1046
+ });
1047
+ } catch {
1048
+ }
1049
+ }
1050
+ finishTurn(code) {
1051
+ const active = this.active;
1052
+ if (!active) return;
1053
+ this.active = void 0;
1054
+ this.observeMcp(false);
1055
+ clearTimeout(active.timer);
1056
+ active.controller.abort();
1057
+ active.fileChanges.clear();
1058
+ active.readyNow();
1059
+ for (const text of active.messages.values())
1060
+ this.event({
1061
+ type: "message_end",
1062
+ message: { role: "assistant", content: [{ type: "text", text }] }
1063
+ });
1064
+ this.event({ type: "turn_end", toolResults: active.toolResults });
1065
+ const modelUsage = active.usage ? {
1066
+ inputTokens: active.usage.inputTokens,
1067
+ outputTokens: active.usage.outputTokens,
1068
+ cacheReadTokens: active.usage.cacheReadTokens,
1069
+ ...typeof active.contextWindow === "number" ? { contextWindow: active.contextWindow } : {}
1070
+ } : void 0;
1071
+ const usage = {
1072
+ ...active.usage ? { tokens: active.usage } : {},
1073
+ ...modelUsage ? { modelUsage: { [active.actualModel]: modelUsage } } : {},
1074
+ ...typeof active.contextTokens === "number" ? { contextTokens: active.contextTokens } : {},
1075
+ ...typeof active.contextWindow === "number" ? { contextWindow: active.contextWindow } : {}
1076
+ };
1077
+ if (code)
1078
+ this.event({
1079
+ type: "error",
1080
+ error: code,
1081
+ fatal: code !== "CODEX_TURN_INTERRUPTED",
1082
+ detail: {
1083
+ message: code,
1084
+ category: code === "CODEX_TURN_INTERRUPTED" ? "process" : code === "CODEX_RATE_LIMITED" ? "rate_limit" : code === "CODEX_NETWORK_UNAVAILABLE" ? "network" : code === "CODEX_AUTH_UNAVAILABLE" || code === "CODEX_RECONNECT_REQUIRED" ? "auth" : "config",
1085
+ retryable: false
1086
+ },
1087
+ ...usage
1088
+ });
1089
+ else
1090
+ this.event({
1091
+ type: "result",
1092
+ subtype: "success",
1093
+ summary: [...active.messages.values()].join("\n"),
1094
+ ...usage
1095
+ });
1096
+ this.event({ type: "agent_end" });
1097
+ active.finish();
1098
+ }
1099
+ event(event) {
1100
+ try {
1101
+ this.emit("agent-event", event);
1102
+ } catch {
1103
+ }
1104
+ }
1105
+ };
12
1106
  function buildCodexChildEnv(parent) {
13
1107
  const out = {};
14
1108
  const explicit = [
@@ -38,6 +1132,7 @@ var CodexDriver = class extends AgentDriver {
38
1132
  };
39
1133
  log = getBridgeLogger("codex");
40
1134
  config;
1135
+ managed;
41
1136
  thread = null;
42
1137
  running = false;
43
1138
  abortController = null;
@@ -50,11 +1145,33 @@ var CodexDriver = class extends AgentDriver {
50
1145
  constructor(config) {
51
1146
  super();
52
1147
  this.config = config;
1148
+ const codex = config.driverOptions?.codex;
1149
+ if (codex?.managedRuntime || codex?.authSource !== void 0 && codex.authSource !== "local") {
1150
+ this.managed = new ManagedCodexDriver(config);
1151
+ this.managed.on("agent-event", (event) => this.emit("agent-event", event));
1152
+ }
53
1153
  }
54
1154
  get runtimeSessionId() {
55
- return this._runtimeSessionId;
1155
+ return this.managed ? this.managed.runtimeSessionId : this._runtimeSessionId;
1156
+ }
1157
+ get acceptsReplyAsPrompt() {
1158
+ return !this.managed;
1159
+ }
1160
+ async dispose() {
1161
+ if (this.managed) return this.managed.dispose();
1162
+ this.kill();
1163
+ }
1164
+ hasPendingQuestion() {
1165
+ return this.managed?.hasPendingQuestion() ?? false;
1166
+ }
1167
+ answerQuestion(answer, question, requestId) {
1168
+ return this.managed?.answerQuestion(answer, question, requestId) ?? false;
1169
+ }
1170
+ promptInput(input) {
1171
+ return this.managed ? this.managed.promptInput(input) : super.promptInput(input);
56
1172
  }
57
1173
  async start() {
1174
+ if (this.managed) return this.managed.start();
58
1175
  if (this.thread) return;
59
1176
  let sdk;
60
1177
  try {
@@ -90,6 +1207,7 @@ var CodexDriver = class extends AgentDriver {
90
1207
  });
91
1208
  }
92
1209
  async prompt(message) {
1210
+ if (this.managed) return this.managed.prompt(message);
93
1211
  await this.start();
94
1212
  if (!this.thread) throw new Error("Codex thread not initialized");
95
1213
  if (this.running) throw new Error("Codex turn already in progress");
@@ -135,32 +1253,47 @@ var CodexDriver = class extends AgentDriver {
135
1253
  }
136
1254
  }
137
1255
  async abort() {
1256
+ if (this.managed) return this.managed.abort();
138
1257
  this.abortController?.abort();
139
1258
  }
140
1259
  get isRunning() {
1260
+ if (this.managed) return this.managed.isRunning;
141
1261
  return this.running;
142
1262
  }
143
1263
  kill() {
1264
+ if (this.managed) {
1265
+ this.managed.kill();
1266
+ return;
1267
+ }
144
1268
  this.abortController?.abort();
145
1269
  this.running = false;
146
1270
  this.abortController = null;
147
1271
  this.log.info("codex driver killed");
148
1272
  }
149
1273
  async listModels() {
1274
+ if (this.managed) return this.managed.listModels();
150
1275
  const apiKey = this.config.apiKeys?.openai || this.config.env?.OPENAI_API_KEY || process.env.OPENAI_API_KEY;
151
1276
  if (!apiKey) return [];
152
1277
  const result = await fetchProviderModels("openai", apiKey);
153
1278
  return result.ok ? result.models : [];
154
1279
  }
155
1280
  async resetSession() {
1281
+ if (this.managed) return this.managed.resetSession();
156
1282
  this.kill();
157
1283
  this.thread = null;
158
1284
  this._runtimeSessionId = void 0;
159
1285
  this._lastTokens = null;
160
1286
  }
161
1287
  getTokenUsage() {
1288
+ if (this.managed) return this.managed.getTokenUsage();
162
1289
  return this._lastTokens;
163
1290
  }
1291
+ reconfigure(patch) {
1292
+ this.managed?.reconfigure(patch);
1293
+ }
1294
+ getModel() {
1295
+ return this.managed?.getModel();
1296
+ }
164
1297
  /**
165
1298
  * Write a combined instructions file for Codex CLI's `model_instructions_file` config.
166
1299
  * Combines pre-rendered agent identity (from `skaile install`) with runtime context