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