@shepai/cli 1.149.0 → 1.149.1-pr468.4c60284

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 (229) hide show
  1. package/apis/json-schema/AgentType.yaml +1 -0
  2. package/dist/packages/core/src/application/use-cases/features/get-branch-sync-status.use-case.d.ts.map +1 -1
  3. package/dist/packages/core/src/application/use-cases/features/get-branch-sync-status.use-case.js +4 -0
  4. package/dist/packages/core/src/domain/generated/output.d.ts +1 -0
  5. package/dist/packages/core/src/domain/generated/output.d.ts.map +1 -1
  6. package/dist/packages/core/src/domain/generated/output.js +1 -0
  7. package/dist/packages/core/src/infrastructure/di/container.d.ts.map +1 -1
  8. package/dist/packages/core/src/infrastructure/di/container.js +3 -0
  9. package/dist/packages/core/src/infrastructure/services/agents/common/agent-executor-factory.service.d.ts.map +1 -1
  10. package/dist/packages/core/src/infrastructure/services/agents/common/agent-executor-factory.service.js +22 -0
  11. package/dist/packages/core/src/infrastructure/services/agents/common/executors/codex-cli-executor.service.d.ts +55 -0
  12. package/dist/packages/core/src/infrastructure/services/agents/common/executors/codex-cli-executor.service.d.ts.map +1 -0
  13. package/dist/packages/core/src/infrastructure/services/agents/common/executors/codex-cli-executor.service.js +506 -0
  14. package/dist/src/presentation/tui/prompts/agent-select.prompt.d.ts +6 -2
  15. package/dist/src/presentation/tui/prompts/agent-select.prompt.d.ts.map +1 -1
  16. package/dist/src/presentation/tui/prompts/agent-select.prompt.js +7 -2
  17. package/dist/src/presentation/web/app/actions/get-all-agent-models.d.ts.map +1 -1
  18. package/dist/src/presentation/web/app/actions/get-all-agent-models.js +4 -2
  19. package/dist/src/presentation/web/components/common/control-center-drawer/feature-drawer-client.d.ts.map +1 -1
  20. package/dist/src/presentation/web/components/common/control-center-drawer/feature-drawer-client.js +6 -3
  21. package/dist/src/presentation/web/components/common/feature-node/agent-type-icons.d.ts +1 -1
  22. package/dist/src/presentation/web/components/common/feature-node/agent-type-icons.d.ts.map +1 -1
  23. package/dist/src/presentation/web/components/common/feature-node/agent-type-icons.js +2 -0
  24. package/dist/src/presentation/web/components/common/feature-node/agent-type-icons.stories.d.ts.map +1 -1
  25. package/dist/src/presentation/web/components/common/feature-node/agent-type-icons.stories.js +1 -0
  26. package/dist/src/presentation/web/components/features/settings/AgentModelPicker/AgentModelPicker.stories.d.ts +1 -0
  27. package/dist/src/presentation/web/components/features/settings/AgentModelPicker/AgentModelPicker.stories.d.ts.map +1 -1
  28. package/dist/src/presentation/web/components/features/settings/AgentModelPicker/AgentModelPicker.stories.js +7 -0
  29. package/dist/src/presentation/web/components/features/settings/agent-settings-section.d.ts.map +1 -1
  30. package/dist/src/presentation/web/components/features/settings/agent-settings-section.js +1 -0
  31. package/dist/src/presentation/web/components/features/settings/agent-settings-section.stories.d.ts +1 -0
  32. package/dist/src/presentation/web/components/features/settings/agent-settings-section.stories.d.ts.map +1 -1
  33. package/dist/src/presentation/web/components/features/settings/agent-settings-section.stories.js +8 -0
  34. package/dist/src/presentation/web/next.config.d.ts.map +1 -1
  35. package/dist/src/presentation/web/next.config.js +0 -3
  36. package/dist/tsconfig.build.tsbuildinfo +1 -1
  37. package/package.json +1 -1
  38. package/web/.next/BUILD_ID +1 -1
  39. package/web/.next/build-manifest.json +2 -2
  40. package/web/.next/fallback-build-manifest.json +2 -2
  41. package/web/.next/prerender-manifest.json +3 -3
  42. package/web/.next/required-server-files.js +3 -4
  43. package/web/.next/required-server-files.json +3 -4
  44. package/web/.next/server/app/(dashboard)/@drawer/adopt/page/server-reference-manifest.json +28 -28
  45. package/web/.next/server/app/(dashboard)/@drawer/adopt/page.js.nft.json +1 -1
  46. package/web/.next/server/app/(dashboard)/@drawer/adopt/page_client-reference-manifest.js +1 -1
  47. package/web/.next/server/app/(dashboard)/@drawer/create/page/server-reference-manifest.json +28 -28
  48. package/web/.next/server/app/(dashboard)/@drawer/create/page.js.nft.json +1 -1
  49. package/web/.next/server/app/(dashboard)/@drawer/create/page_client-reference-manifest.js +1 -1
  50. package/web/.next/server/app/(dashboard)/@drawer/feature/[featureId]/[tab]/page/server-reference-manifest.json +36 -36
  51. package/web/.next/server/app/(dashboard)/@drawer/feature/[featureId]/[tab]/page.js.nft.json +1 -1
  52. package/web/.next/server/app/(dashboard)/@drawer/feature/[featureId]/[tab]/page_client-reference-manifest.js +1 -1
  53. package/web/.next/server/app/(dashboard)/@drawer/feature/[featureId]/page/server-reference-manifest.json +36 -36
  54. package/web/.next/server/app/(dashboard)/@drawer/feature/[featureId]/page.js.nft.json +1 -1
  55. package/web/.next/server/app/(dashboard)/@drawer/feature/[featureId]/page_client-reference-manifest.js +1 -1
  56. package/web/.next/server/app/(dashboard)/@drawer/repository/[repositoryId]/page/server-reference-manifest.json +26 -26
  57. package/web/.next/server/app/(dashboard)/@drawer/repository/[repositoryId]/page.js.nft.json +1 -1
  58. package/web/.next/server/app/(dashboard)/@drawer/repository/[repositoryId]/page_client-reference-manifest.js +1 -1
  59. package/web/.next/server/app/(dashboard)/create/page/server-reference-manifest.json +28 -28
  60. package/web/.next/server/app/(dashboard)/create/page.js.nft.json +1 -1
  61. package/web/.next/server/app/(dashboard)/create/page_client-reference-manifest.js +1 -1
  62. package/web/.next/server/app/(dashboard)/feature/[featureId]/[tab]/page/server-reference-manifest.json +36 -36
  63. package/web/.next/server/app/(dashboard)/feature/[featureId]/[tab]/page.js.nft.json +1 -1
  64. package/web/.next/server/app/(dashboard)/feature/[featureId]/[tab]/page_client-reference-manifest.js +1 -1
  65. package/web/.next/server/app/(dashboard)/feature/[featureId]/page/server-reference-manifest.json +36 -36
  66. package/web/.next/server/app/(dashboard)/feature/[featureId]/page.js.nft.json +1 -1
  67. package/web/.next/server/app/(dashboard)/feature/[featureId]/page_client-reference-manifest.js +1 -1
  68. package/web/.next/server/app/(dashboard)/page/server-reference-manifest.json +26 -26
  69. package/web/.next/server/app/(dashboard)/page.js.nft.json +1 -1
  70. package/web/.next/server/app/(dashboard)/page_client-reference-manifest.js +1 -1
  71. package/web/.next/server/app/(dashboard)/repository/[repositoryId]/page/server-reference-manifest.json +26 -26
  72. package/web/.next/server/app/(dashboard)/repository/[repositoryId]/page.js.nft.json +1 -1
  73. package/web/.next/server/app/(dashboard)/repository/[repositoryId]/page_client-reference-manifest.js +1 -1
  74. package/web/.next/server/app/_global-error.html +2 -2
  75. package/web/.next/server/app/_global-error.rsc +1 -1
  76. package/web/.next/server/app/_global-error.segments/__PAGE__.segment.rsc +1 -1
  77. package/web/.next/server/app/_global-error.segments/_full.segment.rsc +1 -1
  78. package/web/.next/server/app/_global-error.segments/_head.segment.rsc +1 -1
  79. package/web/.next/server/app/_global-error.segments/_index.segment.rsc +1 -1
  80. package/web/.next/server/app/_global-error.segments/_tree.segment.rsc +1 -1
  81. package/web/.next/server/app/_not-found/page/server-reference-manifest.json +3 -3
  82. package/web/.next/server/app/_not-found/page_client-reference-manifest.js +1 -1
  83. package/web/.next/server/app/api/attachments/preview/route.js.nft.json +1 -1
  84. package/web/.next/server/app/api/evidence/route.js.nft.json +1 -1
  85. package/web/.next/server/app/api/graph-data/route.js.nft.json +1 -1
  86. package/web/.next/server/app/settings/page/server-reference-manifest.json +8 -8
  87. package/web/.next/server/app/settings/page.js.nft.json +1 -1
  88. package/web/.next/server/app/settings/page_client-reference-manifest.js +1 -1
  89. package/web/.next/server/app/skills/page/server-reference-manifest.json +8 -8
  90. package/web/.next/server/app/skills/page.js.nft.json +1 -1
  91. package/web/.next/server/app/skills/page_client-reference-manifest.js +1 -1
  92. package/web/.next/server/app/tools/page/server-reference-manifest.json +8 -8
  93. package/web/.next/server/app/tools/page.js.nft.json +1 -1
  94. package/web/.next/server/app/tools/page_client-reference-manifest.js +1 -1
  95. package/web/.next/server/app/version/page/server-reference-manifest.json +3 -3
  96. package/web/.next/server/app/version/page_client-reference-manifest.js +1 -1
  97. package/web/.next/server/chunks/403f9_next_dist_esm_build_templates_app-route_370c43b1.js +1 -1
  98. package/web/.next/server/chunks/403f9_next_dist_esm_build_templates_app-route_370c43b1.js.map +1 -1
  99. package/web/.next/server/chunks/403f9_next_dist_esm_build_templates_app-route_4d623b8e.js +1 -1
  100. package/web/.next/server/chunks/403f9_next_dist_esm_build_templates_app-route_4d623b8e.js.map +1 -1
  101. package/web/.next/server/chunks/[root-of-the-server]__0866d2b5._.js +1 -1
  102. package/web/.next/server/chunks/[root-of-the-server]__0866d2b5._.js.map +1 -1
  103. package/web/.next/server/chunks/[root-of-the-server]__0d33c29e._.js +1 -1
  104. package/web/.next/server/chunks/[root-of-the-server]__0d33c29e._.js.map +1 -1
  105. package/web/.next/server/chunks/[root-of-the-server]__25f23d5d._.js +1 -1
  106. package/web/.next/server/chunks/[root-of-the-server]__25f23d5d._.js.map +1 -1
  107. package/web/.next/server/chunks/[root-of-the-server]__26565141._.js +1 -1
  108. package/web/.next/server/chunks/[root-of-the-server]__26565141._.js.map +1 -1
  109. package/web/.next/server/chunks/[root-of-the-server]__2b1074db._.js +1 -1
  110. package/web/.next/server/chunks/[root-of-the-server]__2b1074db._.js.map +1 -1
  111. package/web/.next/server/chunks/[root-of-the-server]__2f61738a._.js +1 -1
  112. package/web/.next/server/chunks/[root-of-the-server]__2f61738a._.js.map +1 -1
  113. package/web/.next/server/chunks/[root-of-the-server]__332c8d91._.js +1 -1
  114. package/web/.next/server/chunks/[root-of-the-server]__332c8d91._.js.map +1 -1
  115. package/web/.next/server/chunks/[root-of-the-server]__3b72e8b0._.js +1 -1
  116. package/web/.next/server/chunks/[root-of-the-server]__3b72e8b0._.js.map +1 -1
  117. package/web/.next/server/chunks/[root-of-the-server]__9191749c._.js +1 -1
  118. package/web/.next/server/chunks/[root-of-the-server]__9191749c._.js.map +1 -1
  119. package/web/.next/server/chunks/[root-of-the-server]__9a136c79._.js +3 -3
  120. package/web/.next/server/chunks/[root-of-the-server]__9a136c79._.js.map +1 -1
  121. package/web/.next/server/chunks/[root-of-the-server]__a402b567._.js +1 -1
  122. package/web/.next/server/chunks/[root-of-the-server]__a402b567._.js.map +1 -1
  123. package/web/.next/server/chunks/[root-of-the-server]__a5879003._.js +1 -1
  124. package/web/.next/server/chunks/[root-of-the-server]__a5879003._.js.map +1 -1
  125. package/web/.next/server/chunks/[root-of-the-server]__b2f9a412._.js +1 -1
  126. package/web/.next/server/chunks/[root-of-the-server]__b2f9a412._.js.map +1 -1
  127. package/web/.next/server/chunks/[root-of-the-server]__b4102cc7._.js +1 -1
  128. package/web/.next/server/chunks/[root-of-the-server]__b4102cc7._.js.map +1 -1
  129. package/web/.next/server/chunks/[root-of-the-server]__c6e32a23._.js +1 -1
  130. package/web/.next/server/chunks/[root-of-the-server]__c6e32a23._.js.map +1 -1
  131. package/web/.next/server/chunks/[root-of-the-server]__cd67a84c._.js +1 -1
  132. package/web/.next/server/chunks/[root-of-the-server]__cd67a84c._.js.map +1 -1
  133. package/web/.next/server/chunks/[root-of-the-server]__d2c18946._.js +1 -1
  134. package/web/.next/server/chunks/[root-of-the-server]__d2c18946._.js.map +1 -1
  135. package/web/.next/server/chunks/[root-of-the-server]__d9d410a8._.js +1 -1
  136. package/web/.next/server/chunks/[root-of-the-server]__d9d410a8._.js.map +1 -1
  137. package/web/.next/server/chunks/[root-of-the-server]__e247a485._.js +1 -1
  138. package/web/.next/server/chunks/[root-of-the-server]__e247a485._.js.map +1 -1
  139. package/web/.next/server/chunks/[root-of-the-server]__fc6fd958._.js +1 -1
  140. package/web/.next/server/chunks/[root-of-the-server]__fc6fd958._.js.map +1 -1
  141. package/web/.next/server/chunks/ssr/744ca_web_components_common_control-center-drawer_create-drawer-client_tsx_5e26fc0a._.js +1 -1
  142. package/web/.next/server/chunks/ssr/744ca_web_components_common_control-center-drawer_create-drawer-client_tsx_5e26fc0a._.js.map +1 -1
  143. package/web/.next/server/chunks/ssr/[root-of-the-server]__0b150ddf._.js.map +1 -1
  144. package/web/.next/server/chunks/ssr/[root-of-the-server]__2138fa7e._.js +2 -2
  145. package/web/.next/server/chunks/ssr/[root-of-the-server]__2138fa7e._.js.map +1 -1
  146. package/web/.next/server/chunks/ssr/[root-of-the-server]__29580090._.js +1 -1
  147. package/web/.next/server/chunks/ssr/[root-of-the-server]__29580090._.js.map +1 -1
  148. package/web/.next/server/chunks/ssr/[root-of-the-server]__357d99f9._.js +1 -1
  149. package/web/.next/server/chunks/ssr/[root-of-the-server]__3ef34e4c._.js +1 -1
  150. package/web/.next/server/chunks/ssr/[root-of-the-server]__3ef34e4c._.js.map +1 -1
  151. package/web/.next/server/chunks/ssr/[root-of-the-server]__43f51aa6._.js +1 -1
  152. package/web/.next/server/chunks/ssr/[root-of-the-server]__43f51aa6._.js.map +1 -1
  153. package/web/.next/server/chunks/ssr/[root-of-the-server]__815546bd._.js +1 -1
  154. package/web/.next/server/chunks/ssr/[root-of-the-server]__815546bd._.js.map +1 -1
  155. package/web/.next/server/chunks/ssr/[root-of-the-server]__aad040c0._.js +3 -3
  156. package/web/.next/server/chunks/ssr/[root-of-the-server]__aad040c0._.js.map +1 -1
  157. package/web/.next/server/chunks/ssr/[root-of-the-server]__c094882b._.js +1 -1
  158. package/web/.next/server/chunks/ssr/[root-of-the-server]__c094882b._.js.map +1 -1
  159. package/web/.next/server/chunks/ssr/[root-of-the-server]__d48c5b11._.js +1 -1
  160. package/web/.next/server/chunks/ssr/[root-of-the-server]__d48c5b11._.js.map +1 -1
  161. package/web/.next/server/chunks/ssr/[root-of-the-server]__dac5dbf1._.js +1 -1
  162. package/web/.next/server/chunks/ssr/[root-of-the-server]__dac5dbf1._.js.map +1 -1
  163. package/web/.next/server/chunks/ssr/[root-of-the-server]__fae8b355._.js +1 -1
  164. package/web/.next/server/chunks/ssr/[root-of-the-server]__fae8b355._.js.map +1 -1
  165. package/web/.next/server/chunks/ssr/_05c23ad9._.js +1 -1
  166. package/web/.next/server/chunks/ssr/_05c23ad9._.js.map +1 -1
  167. package/web/.next/server/chunks/ssr/_0c5f56e3._.js +2 -2
  168. package/web/.next/server/chunks/ssr/_0c5f56e3._.js.map +1 -1
  169. package/web/.next/server/chunks/ssr/_16eb4fec._.js +1 -1
  170. package/web/.next/server/chunks/ssr/_16eb4fec._.js.map +1 -1
  171. package/web/.next/server/chunks/ssr/_1b719e7f._.js +1 -1
  172. package/web/.next/server/chunks/ssr/_1b719e7f._.js.map +1 -1
  173. package/web/.next/server/chunks/ssr/{_5022e2b1._.js → _3066bf50._.js} +2 -2
  174. package/web/.next/server/chunks/ssr/{_5022e2b1._.js.map → _3066bf50._.js.map} +1 -1
  175. package/web/.next/server/chunks/ssr/_37e8548b._.js +1 -1
  176. package/web/.next/server/chunks/ssr/_37e8548b._.js.map +1 -1
  177. package/web/.next/server/chunks/ssr/_4093a637._.js +1 -1
  178. package/web/.next/server/chunks/ssr/_4093a637._.js.map +1 -1
  179. package/web/.next/server/chunks/ssr/_55d763e2._.js +1 -1
  180. package/web/.next/server/chunks/ssr/_55d763e2._.js.map +1 -1
  181. package/web/.next/server/chunks/ssr/_6256a985._.js +1 -1
  182. package/web/.next/server/chunks/ssr/_6256a985._.js.map +1 -1
  183. package/web/.next/server/chunks/ssr/_64bdfc6f._.js +2 -2
  184. package/web/.next/server/chunks/ssr/_64bdfc6f._.js.map +1 -1
  185. package/web/.next/server/chunks/ssr/_8fcc39d4._.js +1 -1
  186. package/web/.next/server/chunks/ssr/_b71645b4._.js +1 -1
  187. package/web/.next/server/chunks/ssr/_b71645b4._.js.map +1 -1
  188. package/web/.next/server/chunks/ssr/_d4b20e29._.js.map +1 -1
  189. package/web/.next/server/chunks/ssr/_d8575088._.js +1 -1
  190. package/web/.next/server/chunks/ssr/_d8575088._.js.map +1 -1
  191. package/web/.next/server/chunks/ssr/{_458e9a64._.js → _e3bfffad._.js} +2 -2
  192. package/web/.next/server/chunks/ssr/{_458e9a64._.js.map → _e3bfffad._.js.map} +1 -1
  193. package/web/.next/server/chunks/ssr/b1a17_presentation_web_components_features_settings_settings-page-client_tsx_6ed9d5f8._.js +1 -1
  194. package/web/.next/server/chunks/ssr/b1a17_presentation_web_components_features_settings_settings-page-client_tsx_6ed9d5f8._.js.map +1 -1
  195. package/web/.next/server/chunks/ssr/{src_presentation_web_35159458._.js → src_presentation_web_9183c7fa._.js} +2 -2
  196. package/web/.next/server/chunks/ssr/{src_presentation_web_35159458._.js.map → src_presentation_web_9183c7fa._.js.map} +1 -1
  197. package/web/.next/server/chunks/ssr/src_presentation_web__next-internal_server_app_skills_page_actions_1b176e3c.js +1 -1
  198. package/web/.next/server/chunks/ssr/src_presentation_web__next-internal_server_app_skills_page_actions_1b176e3c.js.map +1 -1
  199. package/web/.next/server/chunks/ssr/src_presentation_web__next-internal_server_app_tools_page_actions_bd9f0dda.js +1 -1
  200. package/web/.next/server/chunks/ssr/src_presentation_web__next-internal_server_app_tools_page_actions_bd9f0dda.js.map +1 -1
  201. package/web/.next/server/chunks/ssr/src_presentation_web_app_actions_open-ide_ts_baaca5d5._.js +1 -1
  202. package/web/.next/server/chunks/ssr/src_presentation_web_components_e599bb8c._.js +1 -1
  203. package/web/.next/server/chunks/ssr/src_presentation_web_components_e599bb8c._.js.map +1 -1
  204. package/web/.next/server/chunks/ssr/src_presentation_web_components_features_control-center_7ac3562e._.js +1 -1
  205. package/web/.next/server/chunks/ssr/src_presentation_web_components_features_control-center_7ac3562e._.js.map +1 -1
  206. package/web/.next/server/pages/500.html +2 -2
  207. package/web/.next/server/server-reference-manifest.js +1 -1
  208. package/web/.next/server/server-reference-manifest.json +44 -44
  209. package/web/.next/static/chunks/{75834e430247b325.js → 0c2d51260002da28.js} +1 -1
  210. package/web/.next/static/chunks/0d1171cfea75e83e.js +1 -0
  211. package/web/.next/static/chunks/{eaca60cc3ab0bf9f.js → 12a462ee712c5f4e.js} +2 -2
  212. package/web/.next/static/chunks/{3f1b33498b472b00.js → 3a762627005e401a.js} +1 -1
  213. package/web/.next/static/chunks/{fe5d48f8ca483935.js → 42675a4533e74269.js} +1 -1
  214. package/web/.next/static/chunks/{d3df6e6434e16519.js → 58152ce0f08270cd.js} +1 -1
  215. package/web/.next/static/chunks/{b7126c0b3a97e77e.js → 663932a8e169fe21.js} +1 -1
  216. package/web/.next/static/chunks/93b1e7082b9ceb83.js +5 -0
  217. package/web/.next/static/chunks/{08baac5434d9528e.js → ae411737fa84a470.js} +7 -7
  218. package/web/.next/static/chunks/b203704d0b684bb3.js +1 -0
  219. package/web/.next/static/chunks/{79dc2e2f1c2ff519.js → bb1f383f304bd4ff.js} +1 -1
  220. package/web/.next/static/chunks/cf18f75dfe6a45ba.js +1 -0
  221. package/web/.next/static/chunks/{3e7a130816229439.js → d7bf79589d0d89d2.js} +1 -1
  222. package/web/public/icons/agents/openai.svg +3 -0
  223. package/web/.next/static/chunks/24b1c1e60fd3b7b5.js +0 -5
  224. package/web/.next/static/chunks/4ef564fb1174e497.js +0 -1
  225. package/web/.next/static/chunks/a086f8dfef2c3325.js +0 -1
  226. package/web/.next/static/chunks/a6363f73e05ccf47.js +0 -1
  227. /package/web/.next/static/{1CQHYZVn3VajyhdvnsCaw → p-__FHqacyabBuoIsJ_dd}/_buildManifest.js +0 -0
  228. /package/web/.next/static/{1CQHYZVn3VajyhdvnsCaw → p-__FHqacyabBuoIsJ_dd}/_clientMiddlewareManifest.json +0 -0
  229. /package/web/.next/static/{1CQHYZVn3VajyhdvnsCaw → p-__FHqacyabBuoIsJ_dd}/_ssgManifest.js +0 -0
@@ -0,0 +1,506 @@
1
+ /**
2
+ * Codex CLI Executor Service
3
+ *
4
+ * Infrastructure implementation of IAgentExecutor for the OpenAI Codex CLI agent.
5
+ * Executes prompts via the `codex` CLI subprocess with JSONL output format.
6
+ *
7
+ * Uses constructor dependency injection for the spawn function
8
+ * to enable testability without mocking node:child_process directly.
9
+ */
10
+ import * as fs from 'node:fs';
11
+ import * as os from 'node:os';
12
+ import * as path from 'node:path';
13
+ import { getCurrentPhase, getLogPrefix } from '../../feature-agent/log-context.js';
14
+ /** Features supported by Codex CLI */
15
+ const SUPPORTED_FEATURES = new Set(['session-resume', 'streaming', 'structured-output']);
16
+ /**
17
+ * Fatal stderr patterns indicating API-level failures even when exit code is 0.
18
+ * Codex CLI may exit 0 after encountering auth or rate-limit errors.
19
+ */
20
+ const FATAL_STDERR_PATTERNS = [
21
+ /authentication.*failed/i,
22
+ /rate.?limit/i,
23
+ /quota.*exceeded/i,
24
+ /invalid.*api.?key/i,
25
+ /RESOURCE_EXHAUSTED/i,
26
+ ];
27
+ /**
28
+ * Executor service for OpenAI Codex CLI agent.
29
+ * Uses subprocess spawning to interact with the `codex` CLI.
30
+ */
31
+ export class CodexCliExecutorService {
32
+ spawn;
33
+ authConfig;
34
+ agentType = 'codex-cli';
35
+ /** When true, suppresses debug logging (set per-call via options.silent) */
36
+ silent = false;
37
+ constructor(spawn, authConfig) {
38
+ this.spawn = spawn;
39
+ this.authConfig = authConfig;
40
+ }
41
+ /** Debug logging — writes to stdout so it appears in the worker log file */
42
+ log(message) {
43
+ if (this.silent)
44
+ return;
45
+ const ts = new Date().toISOString();
46
+ process.stdout.write(`[${ts}] ${getCurrentPhase()}${getLogPrefix()}${message}\n`);
47
+ }
48
+ supportsFeature(feature) {
49
+ return SUPPORTED_FEATURES.has(feature);
50
+ }
51
+ async execute(prompt, options) {
52
+ this.silent = options?.silent ?? false;
53
+ const isResume = !!options?.resumeSession;
54
+ let tempSchemaPath;
55
+ try {
56
+ if (options?.outputSchema) {
57
+ tempSchemaPath = path.join(os.tmpdir(), `codex-schema-${Date.now()}-${Math.random().toString(36).slice(2)}.json`);
58
+ fs.writeFileSync(tempSchemaPath, JSON.stringify(options.outputSchema));
59
+ }
60
+ const args = this.buildArgs(prompt, options, tempSchemaPath);
61
+ const spawnOpts = this.buildSpawnOptions(options);
62
+ this.log(`Spawning: codex ${args.map((a) => (a.length > 80 ? `${a.slice(0, 77)}...` : a)).join(' ')}`);
63
+ this.log(`Spawn cwd: ${spawnOpts.cwd ?? '(inherited)'}`);
64
+ const proc = this.spawn('codex', args, spawnOpts);
65
+ this.log(`Subprocess PID: ${proc.pid ?? 'undefined (spawn may have failed)'}`);
66
+ this.log(`Prompt length: ${prompt.length} chars${isResume ? ' (positional arg for resume)' : ' (piped via stdin)'}`);
67
+ // For initial executions, pipe the prompt via stdin.
68
+ // For resume, the prompt is already in the CLI args.
69
+ if (!isResume && proc.stdin) {
70
+ proc.stdin.write(prompt);
71
+ proc.stdin.end();
72
+ }
73
+ return await new Promise((resolve, reject) => {
74
+ let lineBuffer = '';
75
+ let stderr = '';
76
+ let timedOut = false;
77
+ let timeoutId;
78
+ // State accumulated from JSONL events
79
+ let resultText = '';
80
+ let sessionId;
81
+ let usage;
82
+ if (options?.timeout) {
83
+ timeoutId = setTimeout(() => {
84
+ timedOut = true;
85
+ proc.kill();
86
+ }, options.timeout);
87
+ }
88
+ const processLine = (line) => {
89
+ try {
90
+ const parsed = JSON.parse(line);
91
+ const type = parsed.type;
92
+ if (type === 'thread.started' && parsed.thread_id) {
93
+ sessionId = parsed.thread_id;
94
+ }
95
+ else if (type === 'item.completed' && parsed.item?.type === 'agent_message') {
96
+ // Accumulate response text from completed agent messages
97
+ const content = parsed.item.content;
98
+ if (Array.isArray(content)) {
99
+ for (const block of content) {
100
+ if (block.type === 'text' && block.text) {
101
+ resultText += block.text;
102
+ }
103
+ }
104
+ }
105
+ else if (typeof content === 'string') {
106
+ resultText += content;
107
+ }
108
+ }
109
+ else if (type === 'turn.completed' && parsed.usage) {
110
+ usage = this.extractUsage(parsed.usage);
111
+ }
112
+ }
113
+ catch {
114
+ // Malformed JSON line — skip gracefully
115
+ }
116
+ };
117
+ proc.stdout?.on('data', (chunk) => {
118
+ lineBuffer += chunk.toString();
119
+ const lines = lineBuffer.split('\n');
120
+ lineBuffer = lines.pop() ?? '';
121
+ for (const line of lines) {
122
+ const trimmed = line.trim();
123
+ if (trimmed)
124
+ processLine(trimmed);
125
+ }
126
+ });
127
+ proc.stderr?.on('data', (chunk) => {
128
+ const data = chunk.toString();
129
+ stderr += data;
130
+ this.log(`stderr: ${data.trimEnd()}`);
131
+ });
132
+ proc.on('error', (error) => {
133
+ this.log(`Process error event: ${error.message}`);
134
+ if (timeoutId)
135
+ clearTimeout(timeoutId);
136
+ if (error.code === 'ENOENT') {
137
+ reject(new Error('Codex CLI ("codex") not found. Please install it: npm i -g @openai/codex'));
138
+ }
139
+ else {
140
+ reject(error);
141
+ }
142
+ });
143
+ proc.on('close', (code) => {
144
+ // Flush remaining buffer
145
+ if (lineBuffer.trim())
146
+ processLine(lineBuffer.trim());
147
+ this.log(`Process closed with code ${code}, result=${resultText.length} chars`);
148
+ if (timeoutId)
149
+ clearTimeout(timeoutId);
150
+ if (timedOut) {
151
+ reject(new Error('Agent execution timed out'));
152
+ return;
153
+ }
154
+ if (code !== 0 && code !== null) {
155
+ const message = stderr.trim()
156
+ ? `Process exited with code ${code}: ${stderr.trim()}`
157
+ : `Process exited with code ${code}`;
158
+ reject(new Error(message));
159
+ return;
160
+ }
161
+ // Codex CLI may exit 0 despite fatal API errors.
162
+ // Check stderr for known fatal patterns before trusting the output.
163
+ const fatalError = this.detectFatalStderrError(stderr);
164
+ if (fatalError) {
165
+ reject(new Error(fatalError));
166
+ return;
167
+ }
168
+ if (!resultText && !sessionId) {
169
+ reject(new Error(`Empty response from Codex CLI. stderr: ${stderr.slice(0, 300)}`));
170
+ return;
171
+ }
172
+ const result = { result: resultText };
173
+ if (sessionId)
174
+ result.sessionId = sessionId;
175
+ if (usage)
176
+ result.usage = usage;
177
+ resolve(result);
178
+ });
179
+ });
180
+ }
181
+ finally {
182
+ // Clean up temp schema file
183
+ if (tempSchemaPath) {
184
+ try {
185
+ fs.unlinkSync(tempSchemaPath);
186
+ }
187
+ catch {
188
+ // Best effort cleanup
189
+ }
190
+ }
191
+ }
192
+ }
193
+ async *executeStream(prompt, options) {
194
+ this.silent = options?.silent ?? false;
195
+ const isResume = !!options?.resumeSession;
196
+ let tempSchemaPath;
197
+ try {
198
+ if (options?.outputSchema) {
199
+ tempSchemaPath = path.join(os.tmpdir(), `codex-schema-${Date.now()}-${Math.random().toString(36).slice(2)}.json`);
200
+ fs.writeFileSync(tempSchemaPath, JSON.stringify(options.outputSchema));
201
+ }
202
+ const args = this.buildArgs(prompt, options, tempSchemaPath);
203
+ const spawnOpts = this.buildSpawnOptions(options);
204
+ const proc = this.spawn('codex', args, spawnOpts);
205
+ // For initial executions, pipe the prompt via stdin.
206
+ // For resume, the prompt is already in the CLI args.
207
+ if (!isResume && proc.stdin) {
208
+ proc.stdin.write(prompt);
209
+ proc.stdin.end();
210
+ }
211
+ let lineBuffer = '';
212
+ let stderr = '';
213
+ let timedOut = false;
214
+ let timeoutId;
215
+ // State accumulated across events
216
+ let resultText = '';
217
+ const queue = [];
218
+ let resolve = null;
219
+ let spawnError = null;
220
+ function enqueue(event) {
221
+ queue.push(event);
222
+ if (resolve) {
223
+ resolve();
224
+ resolve = null;
225
+ }
226
+ }
227
+ function waitForItem() {
228
+ if (queue.length > 0)
229
+ return Promise.resolve();
230
+ return new Promise((r) => {
231
+ resolve = r;
232
+ });
233
+ }
234
+ if (options?.timeout) {
235
+ timeoutId = setTimeout(() => {
236
+ timedOut = true;
237
+ proc.kill();
238
+ enqueue({ type: 'error', content: 'Agent execution timed out', timestamp: new Date() });
239
+ enqueue(null);
240
+ }, options.timeout);
241
+ }
242
+ const processStreamLine = (line) => {
243
+ try {
244
+ const parsed = JSON.parse(line);
245
+ const type = parsed.type;
246
+ if (type === 'thread.started') {
247
+ // Internal state — no event yielded (thread_id tracked for logging)
248
+ return;
249
+ }
250
+ if (type === 'item.started' && parsed.item?.type === 'agent_message') {
251
+ enqueue({ type: 'progress', content: '', timestamp: new Date() });
252
+ return;
253
+ }
254
+ if (type === 'item.updated' && parsed.item?.type === 'agent_message') {
255
+ const delta = this.extractDeltaText(parsed);
256
+ if (delta) {
257
+ enqueue({ type: 'progress', content: delta, timestamp: new Date() });
258
+ }
259
+ return;
260
+ }
261
+ if (type === 'item.completed' && parsed.item?.type === 'agent_message') {
262
+ const text = this.extractItemText(parsed);
263
+ if (text)
264
+ resultText += text;
265
+ return;
266
+ }
267
+ if (type === 'item.started' && parsed.item?.type === 'command_execution') {
268
+ const cmd = parsed.item.command ?? parsed.item.name ?? 'command';
269
+ enqueue({ type: 'progress', content: `Running: ${cmd}`, timestamp: new Date() });
270
+ return;
271
+ }
272
+ if (type === 'item.completed' && parsed.item?.type === 'command_execution') {
273
+ const exitCode = parsed.item.exit_code ?? '';
274
+ enqueue({
275
+ type: 'progress',
276
+ content: `Command completed (exit ${exitCode})`,
277
+ timestamp: new Date(),
278
+ });
279
+ return;
280
+ }
281
+ if (type === 'item.started' && parsed.item?.type === 'file_change') {
282
+ enqueue({ type: 'progress', content: 'Modifying files', timestamp: new Date() });
283
+ return;
284
+ }
285
+ if (type === 'item.completed' && parsed.item?.type === 'file_change') {
286
+ const file = parsed.item.file ?? parsed.item.path ?? '';
287
+ enqueue({
288
+ type: 'progress',
289
+ content: file ? `Modified: ${file}` : 'File change completed',
290
+ timestamp: new Date(),
291
+ });
292
+ return;
293
+ }
294
+ if (type === 'turn.completed') {
295
+ // Yield final result event
296
+ enqueue({
297
+ type: 'result',
298
+ content: resultText,
299
+ timestamp: new Date(),
300
+ });
301
+ return;
302
+ }
303
+ if (type === 'turn.failed') {
304
+ const msg = parsed.error?.message ?? parsed.message ?? 'Turn failed';
305
+ enqueue({ type: 'error', content: msg, timestamp: new Date() });
306
+ return;
307
+ }
308
+ if (type === 'error') {
309
+ const msg = parsed.message ?? parsed.error ?? 'Unknown error';
310
+ enqueue({ type: 'error', content: msg, timestamp: new Date() });
311
+ return;
312
+ }
313
+ // Unknown event type — skip gracefully
314
+ }
315
+ catch {
316
+ // Non-JSON line — emit as raw progress
317
+ enqueue({ type: 'progress', content: line, timestamp: new Date() });
318
+ }
319
+ };
320
+ proc.stdout?.on('data', (chunk) => {
321
+ lineBuffer += chunk.toString();
322
+ const lines = lineBuffer.split('\n');
323
+ lineBuffer = lines.pop() ?? '';
324
+ for (const line of lines) {
325
+ const trimmed = line.trim();
326
+ if (!trimmed)
327
+ continue;
328
+ processStreamLine(trimmed);
329
+ }
330
+ });
331
+ proc.stderr?.on('data', (chunk) => {
332
+ stderr += chunk.toString();
333
+ });
334
+ proc.on('error', (err) => {
335
+ if (timeoutId)
336
+ clearTimeout(timeoutId);
337
+ spawnError = err;
338
+ enqueue(null);
339
+ });
340
+ proc.on('close', (code) => {
341
+ if (timeoutId)
342
+ clearTimeout(timeoutId);
343
+ if (timedOut)
344
+ return; // already handled by timeout callback
345
+ if (lineBuffer.trim()) {
346
+ processStreamLine(lineBuffer.trim());
347
+ }
348
+ if (code !== 0 && code !== null) {
349
+ const msg = stderr.trim()
350
+ ? `Process exited with code ${code}: ${stderr.trim()}`
351
+ : `Process exited with code ${code}`;
352
+ enqueue({ type: 'error', content: msg, timestamp: new Date() });
353
+ }
354
+ else {
355
+ // Check for fatal stderr patterns on exit 0
356
+ const fatalError = this.detectFatalStderrError(stderr);
357
+ if (fatalError) {
358
+ enqueue({ type: 'error', content: fatalError, timestamp: new Date() });
359
+ }
360
+ }
361
+ enqueue(null);
362
+ });
363
+ // Yield events as they arrive
364
+ while (true) {
365
+ await waitForItem();
366
+ const item = queue.shift();
367
+ if (item === null || item === undefined) {
368
+ if (spawnError !== null) {
369
+ yield {
370
+ type: 'error',
371
+ content: spawnError.message,
372
+ timestamp: new Date(),
373
+ };
374
+ }
375
+ return;
376
+ }
377
+ yield item;
378
+ }
379
+ }
380
+ finally {
381
+ // Clean up temp schema file
382
+ if (tempSchemaPath) {
383
+ try {
384
+ fs.unlinkSync(tempSchemaPath);
385
+ }
386
+ catch {
387
+ // Best effort cleanup
388
+ }
389
+ }
390
+ }
391
+ }
392
+ /**
393
+ * Build CLI arguments for codex exec.
394
+ *
395
+ * For initial execution: `codex exec - --json --sandbox danger-full-access ...`
396
+ * For resume: `codex exec resume <threadId> "prompt" --json --sandbox danger-full-access ...`
397
+ */
398
+ buildArgs(prompt, options, tempSchemaPath) {
399
+ const baseFlags = [
400
+ '--json',
401
+ '--sandbox',
402
+ 'danger-full-access',
403
+ '--skip-git-repo-check',
404
+ '--color',
405
+ 'never',
406
+ ];
407
+ if (options?.model)
408
+ baseFlags.push('--model', options.model);
409
+ if (options?.cwd)
410
+ baseFlags.push('--cd', options.cwd);
411
+ if (tempSchemaPath)
412
+ baseFlags.push('--output-schema', tempSchemaPath);
413
+ if (options?.resumeSession) {
414
+ // Resume mode: codex exec resume <threadId> "prompt" [flags]
415
+ return ['exec', 'resume', options.resumeSession, prompt, ...baseFlags];
416
+ }
417
+ // Initial execution: codex exec - [flags]
418
+ // The `-` indicates prompt is piped via stdin
419
+ return ['exec', '-', ...baseFlags];
420
+ }
421
+ buildSpawnOptions(_options) {
422
+ const spawnOpts = {};
423
+ // Explicitly pipe stdio so streams are available even when parent disconnects
424
+ spawnOpts.stdio = ['pipe', 'pipe', 'pipe'];
425
+ // On Windows: windowsHide=true to prevent blank console windows.
426
+ // Codex CLI is a native Rust binary, so shell=true is NOT needed.
427
+ if (process.platform === 'win32') {
428
+ spawnOpts.windowsHide = true;
429
+ }
430
+ // Strip CLAUDECODE env var to prevent "nested session" error when shep
431
+ // is invoked from within a Claude Code session.
432
+ const { CLAUDECODE: _, ...cleanEnv } = process.env;
433
+ // Inject CODEX_API_KEY when using token auth
434
+ if (this.authConfig?.authMethod === 'token' && this.authConfig.token) {
435
+ spawnOpts.env = { ...cleanEnv, CODEX_API_KEY: this.authConfig.token };
436
+ }
437
+ else {
438
+ spawnOpts.env = cleanEnv;
439
+ }
440
+ return spawnOpts;
441
+ }
442
+ /**
443
+ * Extract token usage from Codex CLI turn.completed usage object.
444
+ */
445
+ extractUsage(usageObj) {
446
+ if (usageObj.input_tokens === undefined && usageObj.output_tokens === undefined) {
447
+ return undefined;
448
+ }
449
+ return {
450
+ inputTokens: usageObj.input_tokens ?? 0,
451
+ outputTokens: usageObj.output_tokens ?? 0,
452
+ };
453
+ }
454
+ /**
455
+ * Extract delta text from an item.updated event.
456
+ */
457
+ extractDeltaText(parsed) {
458
+ const item = parsed.item;
459
+ if (!item)
460
+ return undefined;
461
+ const content = item.content;
462
+ if (Array.isArray(content)) {
463
+ for (const block of content) {
464
+ if (block.type === 'text' && block.text)
465
+ return block.text;
466
+ }
467
+ }
468
+ if (typeof item.delta === 'string')
469
+ return item.delta;
470
+ return undefined;
471
+ }
472
+ /**
473
+ * Extract final text from an item.completed event.
474
+ */
475
+ extractItemText(parsed) {
476
+ const item = parsed.item;
477
+ if (!item)
478
+ return undefined;
479
+ const content = item.content;
480
+ if (Array.isArray(content)) {
481
+ const parts = [];
482
+ for (const block of content) {
483
+ if (block.type === 'text' && block.text)
484
+ parts.push(block.text);
485
+ }
486
+ return parts.length > 0 ? parts.join('') : undefined;
487
+ }
488
+ if (typeof content === 'string')
489
+ return content;
490
+ return undefined;
491
+ }
492
+ /**
493
+ * Check stderr for patterns indicating fatal API errors.
494
+ * Returns an error message if fatal patterns are found, null otherwise.
495
+ */
496
+ detectFatalStderrError(stderr) {
497
+ for (const pattern of FATAL_STDERR_PATTERNS) {
498
+ if (pattern.test(stderr)) {
499
+ const lines = stderr.split('\n').filter((l) => l.trim());
500
+ const summary = lines.slice(0, 3).join(' | ').slice(0, 300);
501
+ return `Codex CLI exited 0 but fatal error detected in stderr: ${summary}`;
502
+ }
503
+ }
504
+ return null;
505
+ }
506
+ }
@@ -8,8 +8,8 @@ import { AgentType } from '../../../../packages/core/src/domain/generated/output
8
8
  /**
9
9
  * Creates the @inquirer/select configuration for selecting an AI coding agent.
10
10
  *
11
- * Only Claude Code is currently available. Other agents are shown as
12
- * disabled with a "Coming Soon" badge.
11
+ * Active agents are selectable. Agents not yet implemented are shown
12
+ * as disabled with a "Coming Soon" badge.
13
13
  */
14
14
  export declare function createAgentSelectConfig(): {
15
15
  readonly message: "Select your AI coding agent";
@@ -21,6 +21,10 @@ export declare function createAgentSelectConfig(): {
21
21
  readonly name: "Gemini CLI";
22
22
  readonly value: AgentType.GeminiCli;
23
23
  readonly description: "Google Gemini CLI";
24
+ }, {
25
+ readonly name: "Codex CLI";
26
+ readonly value: AgentType.CodexCli;
27
+ readonly description: "OpenAI's Codex CLI terminal agent (GPT models)";
24
28
  }, {
25
29
  readonly name: "Cursor";
26
30
  readonly value: AgentType.Cursor;
@@ -1 +1 @@
1
- {"version":3,"file":"agent-select.prompt.d.ts","sourceRoot":"","sources":["../../../../../src/presentation/tui/prompts/agent-select.prompt.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAEH,OAAO,EAAE,SAAS,EAAE,MAAM,8BAA8B,CAAC;AAGzD;;;;;GAKG;AACH,wBAAgB,uBAAuB;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;EAqCtC"}
1
+ {"version":3,"file":"agent-select.prompt.d.ts","sourceRoot":"","sources":["../../../../../src/presentation/tui/prompts/agent-select.prompt.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAEH,OAAO,EAAE,SAAS,EAAE,MAAM,8BAA8B,CAAC;AAGzD;;;;;GAKG;AACH,wBAAgB,uBAAuB;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;EA0CtC"}
@@ -9,8 +9,8 @@ import { shepTheme } from '../themes/shep.theme.js';
9
9
  /**
10
10
  * Creates the @inquirer/select configuration for selecting an AI coding agent.
11
11
  *
12
- * Only Claude Code is currently available. Other agents are shown as
13
- * disabled with a "Coming Soon" badge.
12
+ * Active agents are selectable. Agents not yet implemented are shown
13
+ * as disabled with a "Coming Soon" badge.
14
14
  */
15
15
  export function createAgentSelectConfig() {
16
16
  return {
@@ -26,6 +26,11 @@ export function createAgentSelectConfig() {
26
26
  value: AgentType.GeminiCli,
27
27
  description: 'Google Gemini CLI',
28
28
  },
29
+ {
30
+ name: 'Codex CLI',
31
+ value: AgentType.CodexCli,
32
+ description: "OpenAI's Codex CLI terminal agent (GPT models)",
33
+ },
29
34
  {
30
35
  name: 'Cursor',
31
36
  value: AgentType.Cursor,
@@ -1 +1 @@
1
- {"version":3,"file":"get-all-agent-models.d.ts","sourceRoot":"","sources":["../../../../../../src/presentation/web/app/actions/get-all-agent-models.ts"],"names":[],"mappings":"AAMA,MAAM,WAAW,SAAS;IACxB,EAAE,EAAE,MAAM,CAAC;IACX,WAAW,EAAE,MAAM,CAAC;IACpB,WAAW,EAAE,MAAM,CAAC;CACrB;AAED,MAAM,WAAW,eAAe;IAC9B,SAAS,EAAE,MAAM,CAAC;IAClB,KAAK,EAAE,MAAM,CAAC;IACd,MAAM,EAAE,SAAS,EAAE,CAAC;CACrB;AAiBD,wBAAsB,iBAAiB,IAAI,OAAO,CAAC,eAAe,EAAE,CAAC,CA+BpE"}
1
+ {"version":3,"file":"get-all-agent-models.d.ts","sourceRoot":"","sources":["../../../../../../src/presentation/web/app/actions/get-all-agent-models.ts"],"names":[],"mappings":"AAMA,MAAM,WAAW,SAAS;IACxB,EAAE,EAAE,MAAM,CAAC;IACX,WAAW,EAAE,MAAM,CAAC;IACpB,WAAW,EAAE,MAAM,CAAC;CACrB;AAED,MAAM,WAAW,eAAe;IAC9B,SAAS,EAAE,MAAM,CAAC;IAClB,KAAK,EAAE,MAAM,CAAC;IACd,MAAM,EAAE,SAAS,EAAE,CAAC;CACrB;AAmBD,wBAAsB,iBAAiB,IAAI,OAAO,CAAC,eAAe,EAAE,CAAC,CA+BpE"}
@@ -3,6 +3,7 @@ import { resolve } from '../../lib/server-container.js';
3
3
  import { getModelMeta } from '../../lib/model-metadata.js';
4
4
  const AGENT_LABELS = {
5
5
  'claude-code': 'Claude Code',
6
+ 'codex-cli': 'Codex CLI',
6
7
  cursor: 'Cursor CLI',
7
8
  'gemini-cli': 'Gemini CLI',
8
9
  dev: 'Demo',
@@ -10,8 +11,9 @@ const AGENT_LABELS = {
10
11
  /** Sort weight — higher = further down. Demo always last. */
11
12
  const AGENT_ORDER = {
12
13
  'claude-code': 0,
13
- cursor: 1,
14
- 'gemini-cli': 2,
14
+ 'codex-cli': 1,
15
+ cursor: 2,
16
+ 'gemini-cli': 3,
15
17
  dev: 99,
16
18
  };
17
19
  export async function getAllAgentModels() {
@@ -1 +1 @@
1
- {"version":3,"file":"feature-drawer-client.d.ts","sourceRoot":"","sources":["../../../../../../../src/presentation/web/components/common/control-center-drawer/feature-drawer-client.tsx"],"names":[],"mappings":"AAuCA,OAAO,KAAK,EAAE,UAAU,EAAE,aAAa,EAAE,MAAM,eAAe,CAAC;AAK/D,MAAM,WAAW,wBAAwB;IACvC,IAAI,EAAE,UAAU,CAAC;IACjB,8FAA8F;IAC9F,MAAM,CAAC,EAAE,aAAa,CAAC;CACxB;AAED,wBAAgB,mBAAmB,CAAC,EAAE,IAAI,EAAE,WAAW,EAAE,MAAM,EAAE,EAAE,wBAAwB,2CAyoB1F"}
1
+ {"version":3,"file":"feature-drawer-client.d.ts","sourceRoot":"","sources":["../../../../../../../src/presentation/web/components/common/control-center-drawer/feature-drawer-client.tsx"],"names":[],"mappings":"AAuCA,OAAO,KAAK,EAAE,UAAU,EAAE,aAAa,EAAE,MAAM,eAAe,CAAC;AAK/D,MAAM,WAAW,wBAAwB;IACvC,IAAI,EAAE,UAAU,CAAC;IACjB,8FAA8F;IAC9F,MAAM,CAAC,EAAE,aAAa,CAAC;CACxB;AAED,wBAAgB,mBAAmB,CAAC,EAAE,IAAI,EAAE,WAAW,EAAE,MAAM,EAAE,EAAE,wBAAwB,2CA4oB1F"}
@@ -333,8 +333,11 @@ export function FeatureDrawerClient({ view: initialView, urlTab }) {
333
333
  }
334
334
  : null;
335
335
  const featureActions = useFeatureActions(featureActionsInput);
336
- // Branch sync status — only when the feature flag is on and the feature has a branch
337
- const syncFeatureId = featureFlags.gitRebaseSync && featureNode?.branch ? featureNode.featureId : null;
336
+ // Branch sync status — only when the feature flag is on, the feature has a branch,
337
+ // and the repository has a remote (no remote = no sync needed)
338
+ const syncFeatureId = featureFlags.gitRebaseSync && featureNode?.branch && featureNode?.remoteUrl
339
+ ? featureNode.featureId
340
+ : null;
338
341
  const { data: syncData, loading: syncLoading, error: syncError, refresh: refreshSync, } = useBranchSyncStatus(syncFeatureId);
339
342
  // Auto-refresh sync status after a successful rebase
340
343
  const prevRebaseLoadingRef = useRef(featureActions.rebaseLoading);
@@ -383,7 +386,7 @@ export function FeatureDrawerClient({ view: initialView, urlTab }) {
383
386
  ...(featureNode.state === 'error' && { onRetry: handleRetry }),
384
387
  ...(featureNode.state === 'pending' && { onStart: handleStart }),
385
388
  };
386
- body = (_jsx(FeatureDrawerTabs, { featureNode: enrichedNode, featureId: featureNode.featureId, initialTab: view.initialTab, urlTab: urlTab, sseEvents: events, prdData: prdData, prdSelections: prdSelections, onPrdSelect: (qId, oId) => setPrdSelections((prev) => ({ ...prev, [qId]: oId })), onPrdApprove: handlePrdApprove, onPrdReject: handlePrdReject, isPrdLoading: isLoadingPrd, techData: techData, onTechApprove: handleTechApprove, onTechReject: handleTechReject, isTechLoading: isLoadingTech, productData: isLoadingTechProduct ? null : techProductData, mergeData: mergeData, onMergeApprove: handleMergeApprove, onMergeReject: handleMergeReject, isMergeLoading: isLoadingMerge, syncStatus: featureFlags.gitRebaseSync ? syncData : undefined, syncLoading: syncLoading, syncError: syncError, onRefreshSync: featureFlags.gitRebaseSync ? refreshSync : undefined, onRebaseOnMain: featureFlags.gitRebaseSync ? featureActions.rebaseOnMain : undefined, rebaseLoading: featureActions.rebaseLoading, rebaseError: featureActions.rebaseError, isRejecting: isRejecting, chatInput: chatInput, onChatInputChange: setChatInput }));
389
+ body = (_jsx(FeatureDrawerTabs, { featureNode: enrichedNode, featureId: featureNode.featureId, initialTab: view.initialTab, urlTab: urlTab, sseEvents: events, prdData: prdData, prdSelections: prdSelections, onPrdSelect: (qId, oId) => setPrdSelections((prev) => ({ ...prev, [qId]: oId })), onPrdApprove: handlePrdApprove, onPrdReject: handlePrdReject, isPrdLoading: isLoadingPrd, techData: techData, onTechApprove: handleTechApprove, onTechReject: handleTechReject, isTechLoading: isLoadingTech, productData: isLoadingTechProduct ? null : techProductData, mergeData: mergeData, onMergeApprove: handleMergeApprove, onMergeReject: handleMergeReject, isMergeLoading: isLoadingMerge, syncStatus: syncFeatureId ? syncData : undefined, syncLoading: syncLoading, syncError: syncError, onRefreshSync: syncFeatureId ? refreshSync : undefined, onRebaseOnMain: syncFeatureId ? featureActions.rebaseOnMain : undefined, rebaseLoading: featureActions.rebaseLoading, rebaseError: featureActions.rebaseError, isRejecting: isRejecting, chatInput: chatInput, onChatInputChange: setChatInput }));
387
390
  }
388
391
  return (_jsx(BaseDrawer, { open: isOpen, onClose: attemptClose, size: "md", modal: false, header: header, "data-testid": view.type === 'feature' ? 'feature-drawer' : 'repository-drawer', children: body }));
389
392
  }
@@ -1,6 +1,6 @@
1
1
  import type { ComponentType, SVGProps } from 'react';
2
2
  /** Agent type values mirroring the TypeSpec AgentType enum. */
3
- export type AgentTypeValue = 'claude-code' | 'cursor' | 'gemini-cli' | 'aider' | 'continue' | 'dev';
3
+ export type AgentTypeValue = 'claude-code' | 'codex-cli' | 'cursor' | 'gemini-cli' | 'aider' | 'continue' | 'dev';
4
4
  type IconProps = SVGProps<SVGSVGElement> & {
5
5
  className?: string;
6
6
  };
@@ -1 +1 @@
1
- {"version":3,"file":"agent-type-icons.d.ts","sourceRoot":"","sources":["../../../../../../../src/presentation/web/components/common/feature-node/agent-type-icons.tsx"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,aAAa,EAAE,QAAQ,EAAE,MAAM,OAAO,CAAC;AAIrD,+DAA+D;AAC/D,MAAM,MAAM,cAAc,GAAG,aAAa,GAAG,QAAQ,GAAG,YAAY,GAAG,OAAO,GAAG,UAAU,GAAG,KAAK,CAAC;AAEpG,KAAK,SAAS,GAAG,QAAQ,CAAC,aAAa,CAAC,GAAG;IAAE,SAAS,CAAC,EAAE,MAAM,CAAA;CAAE,CAAC;AAmBlE,6DAA6D;AAC7D,wBAAgB,gBAAgB,CAAC,KAAK,EAAE,SAAS,2CAOhD;AA2DD,6CAA6C;AAC7C,eAAO,MAAM,eAAe,EAAE,MAAM,CAAC,cAAc,EAAE,MAAM,CAO1D,CAAC;AAEF,wEAAwE;AACxE,wBAAgB,gBAAgB,CAAC,SAAS,CAAC,EAAE,MAAM,GAAG,aAAa,CAAC,SAAS,CAAC,CAK7E"}
1
+ {"version":3,"file":"agent-type-icons.d.ts","sourceRoot":"","sources":["../../../../../../../src/presentation/web/components/common/feature-node/agent-type-icons.tsx"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,aAAa,EAAE,QAAQ,EAAE,MAAM,OAAO,CAAC;AAIrD,+DAA+D;AAC/D,MAAM,MAAM,cAAc,GACtB,aAAa,GACb,WAAW,GACX,QAAQ,GACR,YAAY,GACZ,OAAO,GACP,UAAU,GACV,KAAK,CAAC;AAEV,KAAK,SAAS,GAAG,QAAQ,CAAC,aAAa,CAAC,GAAG;IAAE,SAAS,CAAC,EAAE,MAAM,CAAA;CAAE,CAAC;AAmBlE,6DAA6D;AAC7D,wBAAgB,gBAAgB,CAAC,KAAK,EAAE,SAAS,2CAOhD;AA4DD,6CAA6C;AAC7C,eAAO,MAAM,eAAe,EAAE,MAAM,CAAC,cAAc,EAAE,MAAM,CAQ1D,CAAC;AAEF,wEAAwE;AACxE,wBAAgB,gBAAgB,CAAC,SAAS,CAAC,EAAE,MAAM,GAAG,aAAa,CAAC,SAAS,CAAC,CAK7E"}
@@ -20,6 +20,7 @@ function DevAgentIcon({ className, ...props }) {
20
20
  DevAgentIcon.displayName = 'DevAgentIcon';
21
21
  const agentTypeIconMap = {
22
22
  'claude-code': createBrandIcon('/icons/agents/claude-ai-icon.svg', 'Claude Code'),
23
+ 'codex-cli': createBrandIcon('/icons/agents/openai.svg', 'Codex CLI'),
23
24
  cursor: createBrandIcon('/icons/agents/cursor.jpeg', 'Cursor'),
24
25
  'gemini-cli': createBrandIcon('/icons/agents/gemini-cli.jpeg', 'Gemini CLI'),
25
26
  aider: createBrandIcon('/icons/agents/aider.png', 'Aider'),
@@ -29,6 +30,7 @@ const agentTypeIconMap = {
29
30
  /** Human-readable labels for agent types. */
30
31
  export const agentTypeLabels = {
31
32
  'claude-code': 'Claude Code',
33
+ 'codex-cli': 'Codex CLI',
32
34
  cursor: 'Cursor',
33
35
  'gemini-cli': 'Gemini CLI',
34
36
  aider: 'Aider',
@@ -1 +1 @@
1
- {"version":3,"file":"agent-type-icons.stories.d.ts","sourceRoot":"","sources":["../../../../../../../src/presentation/web/components/common/feature-node/agent-type-icons.stories.tsx"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,IAAI,EAAE,QAAQ,EAAE,MAAM,kBAAkB,CAAC;AAyCvD,QAAA,MAAM,IAAI,EAAE,IAIX,CAAC;AAEF,eAAe,IAAI,CAAC;AACpB,KAAK,KAAK,GAAG,QAAQ,CAAC;AAEtB,eAAO,MAAM,QAAQ,EAAE,KAEtB,CAAC;AAEF,eAAO,MAAM,UAAU,EAAE,KAExB,CAAC;AAEF,eAAO,MAAM,UAAU,EAAE,KAExB,CAAC;AAEF,eAAO,MAAM,YAAY,EAAE,KAa1B,CAAC"}
1
+ {"version":3,"file":"agent-type-icons.stories.d.ts","sourceRoot":"","sources":["../../../../../../../src/presentation/web/components/common/feature-node/agent-type-icons.stories.tsx"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,IAAI,EAAE,QAAQ,EAAE,MAAM,kBAAkB,CAAC;AA0CvD,QAAA,MAAM,IAAI,EAAE,IAIX,CAAC;AAEF,eAAe,IAAI,CAAC;AACpB,KAAK,KAAK,GAAG,QAAQ,CAAC;AAEtB,eAAO,MAAM,QAAQ,EAAE,KAEtB,CAAC;AAEF,eAAO,MAAM,UAAU,EAAE,KAExB,CAAC;AAEF,eAAO,MAAM,UAAU,EAAE,KAExB,CAAC;AAEF,eAAO,MAAM,YAAY,EAAE,KAa1B,CAAC"}
@@ -2,6 +2,7 @@ import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
2
2
  import { getAgentTypeIcon, DefaultAgentIcon } from './agent-type-icons.js';
3
3
  const allAgentTypes = [
4
4
  { type: 'claude-code', label: 'Claude Code' },
5
+ { type: 'codex-cli', label: 'Codex CLI' },
5
6
  { type: 'cursor', label: 'Cursor' },
6
7
  { type: 'gemini-cli', label: 'Gemini CLI' },
7
8
  { type: 'aider', label: 'Aider' },