@shepai/cli 1.171.0 → 1.172.0-pr528.108a424

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 (230) hide show
  1. package/apis/json-schema/AgentType.yaml +1 -0
  2. package/dist/packages/core/src/domain/generated/output.d.ts +1 -0
  3. package/dist/packages/core/src/domain/generated/output.d.ts.map +1 -1
  4. package/dist/packages/core/src/domain/generated/output.js +1 -0
  5. package/dist/packages/core/src/infrastructure/di/container.d.ts.map +1 -1
  6. package/dist/packages/core/src/infrastructure/di/container.js +3 -0
  7. package/dist/packages/core/src/infrastructure/services/agents/common/agent-executor-factory.service.d.ts.map +1 -1
  8. package/dist/packages/core/src/infrastructure/services/agents/common/agent-executor-factory.service.js +23 -0
  9. package/dist/packages/core/src/infrastructure/services/agents/common/agent-validator.service.d.ts.map +1 -1
  10. package/dist/packages/core/src/infrastructure/services/agents/common/agent-validator.service.js +1 -0
  11. package/dist/packages/core/src/infrastructure/services/agents/common/executors/copilot-cli-executor.service.d.ts +63 -0
  12. package/dist/packages/core/src/infrastructure/services/agents/common/executors/copilot-cli-executor.service.d.ts.map +1 -0
  13. package/dist/packages/core/src/infrastructure/services/agents/common/executors/copilot-cli-executor.service.js +494 -0
  14. package/dist/packages/core/src/infrastructure/services/tool-installer/tools/codex.json +32 -0
  15. package/dist/packages/core/src/infrastructure/services/tool-installer/tools/copilot.json +32 -0
  16. package/dist/src/presentation/tui/prompts/agent-select.prompt.d.ts.map +1 -1
  17. package/dist/src/presentation/tui/prompts/agent-select.prompt.js +5 -0
  18. package/dist/src/presentation/web/app/actions/check-agent-auth.d.ts.map +1 -1
  19. package/dist/src/presentation/web/app/actions/check-agent-auth.js +18 -0
  20. package/dist/src/presentation/web/app/actions/get-all-agent-models.d.ts.map +1 -1
  21. package/dist/src/presentation/web/app/actions/get-all-agent-models.js +4 -2
  22. package/dist/src/presentation/web/components/common/feature-node/agent-type-icons.d.ts +1 -1
  23. package/dist/src/presentation/web/components/common/feature-node/agent-type-icons.d.ts.map +1 -1
  24. package/dist/src/presentation/web/components/common/feature-node/agent-type-icons.js +2 -0
  25. package/dist/src/presentation/web/components/common/feature-node/agent-type-icons.stories.d.ts.map +1 -1
  26. package/dist/src/presentation/web/components/common/feature-node/agent-type-icons.stories.js +1 -0
  27. package/dist/src/presentation/web/components/common/repo-group/repo-group.js +1 -1
  28. package/dist/src/presentation/web/components/features/settings/AgentModelPicker/AgentModelPicker.stories.d.ts +1 -0
  29. package/dist/src/presentation/web/components/features/settings/AgentModelPicker/AgentModelPicker.stories.d.ts.map +1 -1
  30. package/dist/src/presentation/web/components/features/settings/AgentModelPicker/AgentModelPicker.stories.js +7 -0
  31. package/dist/src/presentation/web/components/features/settings/agent-settings-section.d.ts.map +1 -1
  32. package/dist/src/presentation/web/components/features/settings/agent-settings-section.js +11 -3
  33. package/dist/src/presentation/web/components/features/settings/agent-settings-section.stories.d.ts +1 -0
  34. package/dist/src/presentation/web/components/features/settings/agent-settings-section.stories.d.ts.map +1 -1
  35. package/dist/src/presentation/web/components/features/settings/agent-settings-section.stories.js +8 -0
  36. package/dist/translations/ar/tui.json +4 -0
  37. package/dist/translations/de/tui.json +4 -0
  38. package/dist/translations/en/tui.json +4 -0
  39. package/dist/translations/es/tui.json +4 -0
  40. package/dist/translations/fr/tui.json +4 -0
  41. package/dist/translations/he/tui.json +4 -0
  42. package/dist/translations/pt/tui.json +4 -0
  43. package/dist/translations/ru/tui.json +4 -0
  44. package/dist/tsconfig.build.tsbuildinfo +1 -1
  45. package/package.json +1 -1
  46. package/web/.next/BUILD_ID +1 -1
  47. package/web/.next/build-manifest.json +2 -2
  48. package/web/.next/fallback-build-manifest.json +2 -2
  49. package/web/.next/prerender-manifest.json +3 -3
  50. package/web/.next/required-server-files.js +3 -3
  51. package/web/.next/required-server-files.json +3 -3
  52. package/web/.next/server/app/(dashboard)/@drawer/adopt/page/server-reference-manifest.json +29 -29
  53. package/web/.next/server/app/(dashboard)/@drawer/adopt/page.js.nft.json +1 -1
  54. package/web/.next/server/app/(dashboard)/@drawer/adopt/page_client-reference-manifest.js +1 -1
  55. package/web/.next/server/app/(dashboard)/@drawer/chat/page/server-reference-manifest.json +27 -27
  56. package/web/.next/server/app/(dashboard)/@drawer/chat/page.js.nft.json +1 -1
  57. package/web/.next/server/app/(dashboard)/@drawer/chat/page_client-reference-manifest.js +1 -1
  58. package/web/.next/server/app/(dashboard)/@drawer/create/page/server-reference-manifest.json +30 -30
  59. package/web/.next/server/app/(dashboard)/@drawer/create/page.js.nft.json +1 -1
  60. package/web/.next/server/app/(dashboard)/@drawer/create/page_client-reference-manifest.js +1 -1
  61. package/web/.next/server/app/(dashboard)/@drawer/feature/[featureId]/[tab]/page/server-reference-manifest.json +38 -38
  62. package/web/.next/server/app/(dashboard)/@drawer/feature/[featureId]/[tab]/page.js.nft.json +1 -1
  63. package/web/.next/server/app/(dashboard)/@drawer/feature/[featureId]/[tab]/page_client-reference-manifest.js +1 -1
  64. package/web/.next/server/app/(dashboard)/@drawer/feature/[featureId]/page/server-reference-manifest.json +38 -38
  65. package/web/.next/server/app/(dashboard)/@drawer/feature/[featureId]/page.js.nft.json +1 -1
  66. package/web/.next/server/app/(dashboard)/@drawer/feature/[featureId]/page_client-reference-manifest.js +1 -1
  67. package/web/.next/server/app/(dashboard)/@drawer/repository/[repositoryId]/[tab]/page/server-reference-manifest.json +28 -28
  68. package/web/.next/server/app/(dashboard)/@drawer/repository/[repositoryId]/[tab]/page.js.nft.json +1 -1
  69. package/web/.next/server/app/(dashboard)/@drawer/repository/[repositoryId]/[tab]/page_client-reference-manifest.js +1 -1
  70. package/web/.next/server/app/(dashboard)/@drawer/repository/[repositoryId]/page/server-reference-manifest.json +28 -28
  71. package/web/.next/server/app/(dashboard)/@drawer/repository/[repositoryId]/page.js.nft.json +1 -1
  72. package/web/.next/server/app/(dashboard)/@drawer/repository/[repositoryId]/page_client-reference-manifest.js +1 -1
  73. package/web/.next/server/app/(dashboard)/chat/page/server-reference-manifest.json +27 -27
  74. package/web/.next/server/app/(dashboard)/chat/page.js.nft.json +1 -1
  75. package/web/.next/server/app/(dashboard)/chat/page_client-reference-manifest.js +1 -1
  76. package/web/.next/server/app/(dashboard)/create/page/server-reference-manifest.json +30 -30
  77. package/web/.next/server/app/(dashboard)/create/page.js.nft.json +1 -1
  78. package/web/.next/server/app/(dashboard)/create/page_client-reference-manifest.js +1 -1
  79. package/web/.next/server/app/(dashboard)/feature/[featureId]/[tab]/page/server-reference-manifest.json +38 -38
  80. package/web/.next/server/app/(dashboard)/feature/[featureId]/[tab]/page.js.nft.json +1 -1
  81. package/web/.next/server/app/(dashboard)/feature/[featureId]/[tab]/page_client-reference-manifest.js +1 -1
  82. package/web/.next/server/app/(dashboard)/feature/[featureId]/page/server-reference-manifest.json +38 -38
  83. package/web/.next/server/app/(dashboard)/feature/[featureId]/page.js.nft.json +1 -1
  84. package/web/.next/server/app/(dashboard)/feature/[featureId]/page_client-reference-manifest.js +1 -1
  85. package/web/.next/server/app/(dashboard)/page/server-reference-manifest.json +27 -27
  86. package/web/.next/server/app/(dashboard)/page.js.nft.json +1 -1
  87. package/web/.next/server/app/(dashboard)/page_client-reference-manifest.js +1 -1
  88. package/web/.next/server/app/(dashboard)/repository/[repositoryId]/[tab]/page/server-reference-manifest.json +28 -28
  89. package/web/.next/server/app/(dashboard)/repository/[repositoryId]/[tab]/page.js.nft.json +1 -1
  90. package/web/.next/server/app/(dashboard)/repository/[repositoryId]/[tab]/page_client-reference-manifest.js +1 -1
  91. package/web/.next/server/app/(dashboard)/repository/[repositoryId]/page/server-reference-manifest.json +28 -28
  92. package/web/.next/server/app/(dashboard)/repository/[repositoryId]/page.js.nft.json +1 -1
  93. package/web/.next/server/app/(dashboard)/repository/[repositoryId]/page_client-reference-manifest.js +1 -1
  94. package/web/.next/server/app/_global-error.html +2 -2
  95. package/web/.next/server/app/_global-error.rsc +1 -1
  96. package/web/.next/server/app/_global-error.segments/__PAGE__.segment.rsc +1 -1
  97. package/web/.next/server/app/_global-error.segments/_full.segment.rsc +1 -1
  98. package/web/.next/server/app/_global-error.segments/_head.segment.rsc +1 -1
  99. package/web/.next/server/app/_global-error.segments/_index.segment.rsc +1 -1
  100. package/web/.next/server/app/_global-error.segments/_tree.segment.rsc +1 -1
  101. package/web/.next/server/app/_not-found/page/server-reference-manifest.json +6 -6
  102. package/web/.next/server/app/_not-found/page.js.nft.json +1 -1
  103. package/web/.next/server/app/_not-found/page_client-reference-manifest.js +1 -1
  104. package/web/.next/server/app/api/attachments/preview/route.js.nft.json +1 -1
  105. package/web/.next/server/app/api/evidence/route.js.nft.json +1 -1
  106. package/web/.next/server/app/api/graph-data/route.js.nft.json +1 -1
  107. package/web/.next/server/app/api/interactive/chat/[featureId]/messages/route.js.nft.json +1 -1
  108. package/web/.next/server/app/features/page/server-reference-manifest.json +6 -6
  109. package/web/.next/server/app/features/page.js.nft.json +1 -1
  110. package/web/.next/server/app/features/page_client-reference-manifest.js +1 -1
  111. package/web/.next/server/app/settings/page/server-reference-manifest.json +9 -9
  112. package/web/.next/server/app/settings/page.js.nft.json +1 -1
  113. package/web/.next/server/app/settings/page_client-reference-manifest.js +1 -1
  114. package/web/.next/server/app/skills/page/server-reference-manifest.json +13 -13
  115. package/web/.next/server/app/skills/page.js.nft.json +1 -1
  116. package/web/.next/server/app/skills/page_client-reference-manifest.js +1 -1
  117. package/web/.next/server/app/tools/page/server-reference-manifest.json +11 -11
  118. package/web/.next/server/app/tools/page.js.nft.json +1 -1
  119. package/web/.next/server/app/tools/page_client-reference-manifest.js +1 -1
  120. package/web/.next/server/app/version/page/server-reference-manifest.json +6 -6
  121. package/web/.next/server/app/version/page.js.nft.json +1 -1
  122. package/web/.next/server/app/version/page_client-reference-manifest.js +1 -1
  123. package/web/.next/server/chunks/[root-of-the-server]__a402b567._.js +1 -1
  124. package/web/.next/server/chunks/[root-of-the-server]__c78383b1._.js +1 -1
  125. package/web/.next/server/chunks/[root-of-the-server]__c78383b1._.js.map +1 -1
  126. package/web/.next/server/chunks/[root-of-the-server]__cd67a84c._.js +1 -1
  127. package/web/.next/server/chunks/[root-of-the-server]__cd67a84c._.js.map +1 -1
  128. package/web/.next/server/chunks/ssr/744ca_web_components_common_control-center-drawer_create-drawer-client_tsx_5e26fc0a._.js +1 -1
  129. package/web/.next/server/chunks/ssr/744ca_web_components_common_control-center-drawer_create-drawer-client_tsx_5e26fc0a._.js.map +1 -1
  130. package/web/.next/server/chunks/ssr/744ca_web_components_common_control-center-drawer_feature-drawer-client_tsx_e9755fc8._.js +2 -2
  131. package/web/.next/server/chunks/ssr/744ca_web_components_common_control-center-drawer_feature-drawer-client_tsx_e9755fc8._.js.map +1 -1
  132. package/web/.next/server/chunks/ssr/[root-of-the-server]__1cd4327c._.js +1 -1
  133. package/web/.next/server/chunks/ssr/[root-of-the-server]__1cd4327c._.js.map +1 -1
  134. package/web/.next/server/chunks/ssr/[root-of-the-server]__1f389e5d._.js +1 -1
  135. package/web/.next/server/chunks/ssr/[root-of-the-server]__1f389e5d._.js.map +1 -1
  136. package/web/.next/server/chunks/ssr/[root-of-the-server]__357d99f9._.js +1 -1
  137. package/web/.next/server/chunks/ssr/[root-of-the-server]__4fb81977._.js +1 -1
  138. package/web/.next/server/chunks/ssr/[root-of-the-server]__4fb81977._.js.map +1 -1
  139. package/web/.next/server/chunks/ssr/[root-of-the-server]__6c7d3936._.js +1 -1
  140. package/web/.next/server/chunks/ssr/[root-of-the-server]__6c7d3936._.js.map +1 -1
  141. package/web/.next/server/chunks/ssr/[root-of-the-server]__7dcd0917._.js +1 -1
  142. package/web/.next/server/chunks/ssr/[root-of-the-server]__7dcd0917._.js.map +1 -1
  143. package/web/.next/server/chunks/ssr/[root-of-the-server]__92ffd5ee._.js +2 -2
  144. package/web/.next/server/chunks/ssr/[root-of-the-server]__92ffd5ee._.js.map +1 -1
  145. package/web/.next/server/chunks/ssr/[root-of-the-server]__b020c17d._.js +2 -2
  146. package/web/.next/server/chunks/ssr/[root-of-the-server]__b020c17d._.js.map +1 -1
  147. package/web/.next/server/chunks/ssr/[root-of-the-server]__b7b96453._.js +1 -1
  148. package/web/.next/server/chunks/ssr/[root-of-the-server]__b7b96453._.js.map +1 -1
  149. package/web/.next/server/chunks/ssr/[root-of-the-server]__ba7f5873._.js +1 -1
  150. package/web/.next/server/chunks/ssr/[root-of-the-server]__ba7f5873._.js.map +1 -1
  151. package/web/.next/server/chunks/ssr/[root-of-the-server]__c5e09f6f._.js +1 -1
  152. package/web/.next/server/chunks/ssr/[root-of-the-server]__c5e09f6f._.js.map +1 -1
  153. package/web/.next/server/chunks/ssr/_02e01240._.js +1 -1
  154. package/web/.next/server/chunks/ssr/_02e01240._.js.map +1 -1
  155. package/web/.next/server/chunks/ssr/_05c23ad9._.js +1 -1
  156. package/web/.next/server/chunks/ssr/_05c23ad9._.js.map +1 -1
  157. package/web/.next/server/chunks/ssr/_16eb4fec._.js +1 -1
  158. package/web/.next/server/chunks/ssr/_16eb4fec._.js.map +1 -1
  159. package/web/.next/server/chunks/ssr/_18886033._.js +1 -1
  160. package/web/.next/server/chunks/ssr/_18886033._.js.map +1 -1
  161. package/web/.next/server/chunks/ssr/_1e08a336._.js +1 -1
  162. package/web/.next/server/chunks/ssr/_22e00a14._.js +1 -1
  163. package/web/.next/server/chunks/ssr/_22e00a14._.js.map +1 -1
  164. package/web/.next/server/chunks/ssr/{_f778f3ef._.js → _324beb75._.js} +2 -2
  165. package/web/.next/server/chunks/ssr/{_f778f3ef._.js.map → _324beb75._.js.map} +1 -1
  166. package/web/.next/server/chunks/ssr/_45496654._.js +1 -1
  167. package/web/.next/server/chunks/ssr/_45496654._.js.map +1 -1
  168. package/web/.next/server/chunks/ssr/_4cbb7f95._.js +1 -1
  169. package/web/.next/server/chunks/ssr/_4cbb7f95._.js.map +1 -1
  170. package/web/.next/server/chunks/ssr/_5119a3df._.js.map +1 -1
  171. package/web/.next/server/chunks/ssr/_56b9d60f._.js +1 -1
  172. package/web/.next/server/chunks/ssr/_56b9d60f._.js.map +1 -1
  173. package/web/.next/server/chunks/ssr/{_d50cde79._.js → _5e3cb0a7._.js} +2 -2
  174. package/web/.next/server/chunks/ssr/{_d50cde79._.js.map → _5e3cb0a7._.js.map} +1 -1
  175. package/web/.next/server/chunks/ssr/_a5a5901d._.js +1 -1
  176. package/web/.next/server/chunks/ssr/_a5a5901d._.js.map +1 -1
  177. package/web/.next/server/chunks/ssr/_ad09f271._.js +1 -1
  178. package/web/.next/server/chunks/ssr/_ad09f271._.js.map +1 -1
  179. package/web/.next/server/chunks/ssr/_c3f595c6._.js +1 -1
  180. package/web/.next/server/chunks/ssr/_c3f595c6._.js.map +1 -1
  181. package/web/.next/server/chunks/ssr/{_49447b3c._.js → _c9d3f255._.js} +2 -2
  182. package/web/.next/server/chunks/ssr/{_49447b3c._.js.map → _c9d3f255._.js.map} +1 -1
  183. package/web/.next/server/chunks/ssr/_df737cce._.js +1 -1
  184. package/web/.next/server/chunks/ssr/_ea9e1556._.js +1 -1
  185. package/web/.next/server/chunks/ssr/_ea9e1556._.js.map +1 -1
  186. package/web/.next/server/chunks/ssr/_f1ba9be6._.js +2 -2
  187. package/web/.next/server/chunks/ssr/_f1ba9be6._.js.map +1 -1
  188. package/web/.next/server/chunks/ssr/_f33cd07e._.js +2 -2
  189. package/web/.next/server/chunks/ssr/_f33cd07e._.js.map +1 -1
  190. package/web/.next/server/chunks/ssr/_f8b45233._.js +1 -1
  191. package/web/.next/server/chunks/ssr/_f8b45233._.js.map +1 -1
  192. package/web/.next/server/chunks/ssr/b1a17_presentation_web_components_features_settings_settings-page-client_tsx_6ed9d5f8._.js +1 -1
  193. package/web/.next/server/chunks/ssr/b1a17_presentation_web_components_features_settings_settings-page-client_tsx_6ed9d5f8._.js.map +1 -1
  194. package/web/.next/server/chunks/ssr/f3a1f_components_common_control-center-drawer_repository-drawer-client_tsx_39a00c03._.js +1 -1
  195. package/web/.next/server/chunks/ssr/f3a1f_components_common_control-center-drawer_repository-drawer-client_tsx_39a00c03._.js.map +1 -1
  196. package/web/.next/server/chunks/ssr/src_presentation_web_app_actions_open-ide_ts_baaca5d5._.js +1 -1
  197. package/web/.next/server/chunks/ssr/src_presentation_web_app_actions_open-ide_ts_baaca5d5._.js.map +1 -1
  198. package/web/.next/server/chunks/ssr/src_presentation_web_components_895e5bfa._.js +1 -1
  199. package/web/.next/server/chunks/ssr/src_presentation_web_components_895e5bfa._.js.map +1 -1
  200. package/web/.next/server/chunks/ssr/src_presentation_web_components_features_control-center_7ac3562e._.js +1 -1
  201. package/web/.next/server/chunks/ssr/src_presentation_web_components_features_control-center_7ac3562e._.js.map +1 -1
  202. package/web/.next/server/chunks/ssr/src_presentation_web_components_features_skills_8a174cac._.js +1 -1
  203. package/web/.next/server/chunks/ssr/src_presentation_web_components_features_skills_8a174cac._.js.map +1 -1
  204. package/web/.next/server/pages/500.html +2 -2
  205. package/web/.next/server/server-reference-manifest.js +1 -1
  206. package/web/.next/server/server-reference-manifest.json +50 -50
  207. package/web/.next/static/chunks/01d34ca202152b33.js +1 -0
  208. package/web/.next/static/chunks/{4383bcae769740e7.js → 120279c82aa8aa25.js} +1 -1
  209. package/web/.next/static/chunks/2e32d8578aace93a.js +1 -0
  210. package/web/.next/static/chunks/{24dd6b3021c2d849.js → 41f5bb33ac4f3c7d.js} +1 -1
  211. package/web/.next/static/chunks/{02fe1303471793b9.js → 43cf78a6c49eb7c1.js} +2 -2
  212. package/web/.next/static/chunks/{aa077ab14015a8fd.js → 50b760a2c7ad03d3.js} +1 -1
  213. package/web/.next/static/chunks/{b93a918712cd4987.js → 6e10cf4513c1f54f.js} +1 -1
  214. package/web/.next/static/chunks/{9705f2a5695a4995.js → 8a486366e2878cbc.js} +1 -1
  215. package/web/.next/static/chunks/{5983ef48d50d2d2a.js → 947678ada7948442.js} +1 -1
  216. package/web/.next/static/chunks/{eff45ffddd85918c.js → b1b0c8ff51c0c2fc.js} +3 -3
  217. package/web/.next/static/chunks/{67a430796dea42a7.js → bd55a833b24ee17b.js} +1 -1
  218. package/web/.next/static/chunks/{6ee5d45de67d3547.js → c91571264851a71e.js} +3 -3
  219. package/web/.next/static/chunks/{3d182168cdc4c15c.js → cc832e47f53eb2c3.js} +1 -1
  220. package/web/.next/static/chunks/da504d7f1c40bce1.js +1 -0
  221. package/web/.next/static/chunks/dcf8bb4389557a76.css +1 -0
  222. package/web/.next/static/chunks/{0ce50b34df07306b.js → f8f647baf2e91a9d.js} +1 -1
  223. package/web/public/icons/agents/copilot.svg +12 -0
  224. package/web/.next/static/chunks/18d4601f068c700d.js +0 -1
  225. package/web/.next/static/chunks/a80bbfca8ee3d79b.js +0 -1
  226. package/web/.next/static/chunks/b14085e99b88e7f7.css +0 -1
  227. package/web/.next/static/chunks/bb962a996814718a.js +0 -1
  228. /package/web/.next/static/{akDn2qFk1krSwrjt4345P → S_u3qor6FkwObhA1F2xEj}/_buildManifest.js +0 -0
  229. /package/web/.next/static/{akDn2qFk1krSwrjt4345P → S_u3qor6FkwObhA1F2xEj}/_clientMiddlewareManifest.json +0 -0
  230. /package/web/.next/static/{akDn2qFk1krSwrjt4345P → S_u3qor6FkwObhA1F2xEj}/_ssgManifest.js +0 -0
@@ -0,0 +1,494 @@
1
+ /**
2
+ * Copilot CLI Executor Service
3
+ *
4
+ * Infrastructure implementation of IAgentExecutor for the GitHub Copilot CLI agent.
5
+ * Executes prompts via the `copilot` CLI subprocess with JSONL output format.
6
+ *
7
+ * Key differences from other executors:
8
+ * - Prompt is delivered via the -p flag (not stdin piping)
9
+ * - Large prompts use temp-file indirection to avoid Windows ENAMETOOLONG spawn failures
10
+ * - Auth is GitHub OAuth only — no API key injection is possible or supported
11
+ * - --resume=<sessionId> format (with equals sign) for session resume
12
+ *
13
+ * Uses constructor dependency injection for the spawn function
14
+ * to enable testability without mocking node:child_process directly.
15
+ */
16
+ import { getCurrentPhase, getLogPrefix } from '../../feature-agent/log-context.js';
17
+ import { randomUUID } from 'node:crypto';
18
+ import { unlink, writeFile } from 'node:fs/promises';
19
+ import { join } from 'node:path';
20
+ import { tmpdir } from 'node:os';
21
+ /** Features supported by Copilot CLI */
22
+ const SUPPORTED_FEATURES = new Set(['session-resume', 'streaming']);
23
+ /**
24
+ * Base flags always passed to the copilot CLI for non-interactive headless operation.
25
+ * - --allow-all: bypass tool permission prompts (autonomous execution equivalent of --dangerously-skip-permissions)
26
+ * - --output-format json: structured JSONL event stream on stdout
27
+ * - -s: silent mode (suppress CLI progress UI on stderr, keeping it clean for error detection)
28
+ * - --no-custom-instructions: disable repo-level custom instructions for predictable behavior
29
+ * - --no-ask-user: never prompt for user input during execution
30
+ */
31
+ const BASE_FLAGS = [
32
+ '--allow-all',
33
+ '--output-format',
34
+ 'json',
35
+ '-s',
36
+ '--no-custom-instructions',
37
+ '--no-ask-user',
38
+ ];
39
+ /**
40
+ * Conservative threshold for prompt characters passed through CLI args.
41
+ * Above this, we use file indirection to avoid process spawn arg-length failures.
42
+ */
43
+ const MAX_PROMPT_ARG_CHARS = 12_000;
44
+ /** Prefix for temporary prompt files used by large prompt indirection mode. */
45
+ const PROMPT_FILE_PREFIX = 'shep-copilot-prompt-';
46
+ /**
47
+ * Legacy model aliases that appeared in older settings payloads.
48
+ * Copilot CLI expects dotted model versions (e.g. 4.5), not hyphenated (4-5).
49
+ */
50
+ const LEGACY_MODEL_ALIASES = {
51
+ 'claude-sonnet-4-5': 'claude-sonnet-4.5',
52
+ 'claude-sonnet-4-6': 'claude-sonnet-4.6',
53
+ 'claude-opus-4-5': 'claude-opus-4.5',
54
+ 'claude-opus-4-6': 'claude-opus-4.6',
55
+ 'claude-haiku-4-5': 'claude-haiku-4.5',
56
+ 'gpt-4-1': 'gpt-4.1',
57
+ 'gpt-5-2': 'gpt-5.2',
58
+ 'gpt-5-2-codex': 'gpt-5.2-codex',
59
+ 'gpt-5-3-codex': 'gpt-5.3-codex',
60
+ 'gpt-5-4': 'gpt-5.4',
61
+ 'gpt-5-4-mini': 'gpt-5.4-mini',
62
+ };
63
+ /**
64
+ * Executor service for GitHub Copilot CLI agent.
65
+ * Uses subprocess spawning to interact with the `copilot` CLI.
66
+ */
67
+ export class CopilotCliExecutorService {
68
+ spawn;
69
+ authConfig;
70
+ agentType = 'copilot-cli';
71
+ /** When true, suppresses debug logging (set per-call via options.silent) */
72
+ silent = false;
73
+ constructor(spawn, authConfig) {
74
+ this.spawn = spawn;
75
+ this.authConfig = authConfig;
76
+ }
77
+ /** Debug logging — writes to stdout so it appears in the worker log file */
78
+ log(message) {
79
+ if (this.silent)
80
+ return;
81
+ const ts = new Date().toISOString();
82
+ process.stdout.write(`[${ts}] ${getCurrentPhase()}${getLogPrefix()}${message}\n`);
83
+ }
84
+ supportsFeature(feature) {
85
+ return SUPPORTED_FEATURES.has(feature);
86
+ }
87
+ async execute(prompt, options) {
88
+ this.silent = options?.silent ?? false;
89
+ // Copilot CLI is OAuth-only. Surface a clear error if token auth is attempted.
90
+ if (this.authConfig?.authMethod === 'token') {
91
+ throw new Error('GitHub Copilot CLI does not support token-based authentication. ' +
92
+ 'Auth is managed via GitHub OAuth. Run: copilot auth login');
93
+ }
94
+ let preparedPrompt = this.prepareDirectPrompt(prompt);
95
+ if (this.shouldUsePromptFile(prompt)) {
96
+ preparedPrompt = await this.preparePromptFileIndirection(prompt);
97
+ }
98
+ const args = this.buildArgs(preparedPrompt.promptArg, options);
99
+ const spawnOpts = this.buildSpawnOptions(options);
100
+ this.log(`Spawning: copilot ${args.map((a) => (a.length > 80 ? `${a.slice(0, 77)}...` : a)).join(' ')}`);
101
+ this.log(`Spawn cwd: ${spawnOpts.cwd ?? '(inherited)'}`);
102
+ let proc;
103
+ try {
104
+ proc = this.spawn('copilot', args, spawnOpts);
105
+ }
106
+ catch (error) {
107
+ await preparedPrompt.cleanup();
108
+ throw error;
109
+ }
110
+ this.log(`Subprocess PID: ${proc.pid ?? 'undefined (spawn may have failed)'}`);
111
+ this.log(`Prompt length: ${prompt.length} chars (${preparedPrompt.usedFileIndirection ? 'delivered via temp prompt file indirection' : 'delivered via -p flag'})`);
112
+ const executionPromise = new Promise((resolve, reject) => {
113
+ let lineBuffer = '';
114
+ let stderr = '';
115
+ let timedOut = false;
116
+ let timeoutId;
117
+ // State accumulated from JSONL events
118
+ let resultText = '';
119
+ let sessionId;
120
+ let usage;
121
+ if (options?.timeout) {
122
+ timeoutId = setTimeout(() => {
123
+ timedOut = true;
124
+ proc.kill();
125
+ }, options.timeout);
126
+ }
127
+ const processLine = (line) => {
128
+ try {
129
+ const parsed = JSON.parse(line);
130
+ const type = parsed.type;
131
+ if (type === 'assistant.message' && parsed.content) {
132
+ resultText += parsed.content;
133
+ }
134
+ else if (type === 'result') {
135
+ if (parsed.sessionId)
136
+ sessionId = parsed.sessionId;
137
+ if (parsed.usage)
138
+ usage = this.extractUsage(parsed.usage);
139
+ }
140
+ }
141
+ catch {
142
+ // Malformed JSON line — skip gracefully
143
+ }
144
+ };
145
+ proc.stdout?.on('data', (chunk) => {
146
+ lineBuffer += chunk.toString();
147
+ const lines = lineBuffer.split('\n');
148
+ lineBuffer = lines.pop() ?? '';
149
+ for (const line of lines) {
150
+ const trimmed = line.trim();
151
+ if (trimmed)
152
+ processLine(trimmed);
153
+ }
154
+ });
155
+ proc.stderr?.on('data', (chunk) => {
156
+ const data = chunk.toString();
157
+ stderr += data;
158
+ this.log(`stderr: ${data.trimEnd()}`);
159
+ });
160
+ proc.on('error', (error) => {
161
+ this.log(`Process error event: ${error.message}`);
162
+ if (timeoutId)
163
+ clearTimeout(timeoutId);
164
+ if (error.code === 'ENOENT') {
165
+ reject(new Error('GitHub Copilot CLI ("copilot") not found. ' +
166
+ 'Install via: npm install -g @githubnext/github-copilot-cli, ' +
167
+ 'then authenticate with: copilot auth login'));
168
+ }
169
+ else {
170
+ reject(error);
171
+ }
172
+ });
173
+ proc.on('close', (code) => {
174
+ // Flush remaining line buffer
175
+ if (lineBuffer.trim())
176
+ processLine(lineBuffer.trim());
177
+ this.log(`Process closed with code ${code}, result=${resultText.length} chars`);
178
+ if (timeoutId)
179
+ clearTimeout(timeoutId);
180
+ if (timedOut) {
181
+ reject(new Error('Agent execution timed out'));
182
+ return;
183
+ }
184
+ if (code !== 0 && code !== null) {
185
+ // Check for auth-specific error patterns to provide actionable guidance
186
+ const authError = this.detectAuthError(stderr);
187
+ if (authError) {
188
+ reject(new Error(authError));
189
+ return;
190
+ }
191
+ const message = stderr.trim()
192
+ ? `Process exited with code ${code}: ${stderr.trim()}`
193
+ : `Process exited with code ${code}`;
194
+ reject(new Error(message));
195
+ return;
196
+ }
197
+ const result = { result: resultText };
198
+ if (sessionId)
199
+ result.sessionId = sessionId;
200
+ if (usage)
201
+ result.usage = usage;
202
+ resolve(result);
203
+ });
204
+ });
205
+ return executionPromise.finally(async () => {
206
+ await preparedPrompt.cleanup();
207
+ });
208
+ }
209
+ async *executeStream(prompt, options) {
210
+ this.silent = options?.silent ?? false;
211
+ // Copilot CLI is OAuth-only. Surface a clear error if token auth is attempted.
212
+ if (this.authConfig?.authMethod === 'token') {
213
+ yield {
214
+ type: 'error',
215
+ content: 'GitHub Copilot CLI does not support token-based authentication. ' +
216
+ 'Auth is managed via GitHub OAuth. Run: copilot auth login',
217
+ timestamp: new Date(),
218
+ };
219
+ return;
220
+ }
221
+ let preparedPrompt = this.prepareDirectPrompt(prompt);
222
+ if (this.shouldUsePromptFile(prompt)) {
223
+ preparedPrompt = await this.preparePromptFileIndirection(prompt);
224
+ }
225
+ const args = this.buildArgs(preparedPrompt.promptArg, options);
226
+ const spawnOpts = this.buildSpawnOptions(options);
227
+ let proc;
228
+ try {
229
+ proc = this.spawn('copilot', args, spawnOpts);
230
+ }
231
+ catch (error) {
232
+ await preparedPrompt.cleanup();
233
+ yield {
234
+ type: 'error',
235
+ content: error.message,
236
+ timestamp: new Date(),
237
+ };
238
+ return;
239
+ }
240
+ let lineBuffer = '';
241
+ let stderr = '';
242
+ let timedOut = false;
243
+ let timeoutId;
244
+ // Accumulated final response text (from assistant.message events)
245
+ let resultText = '';
246
+ const queue = [];
247
+ let resolveWait = null;
248
+ let spawnError = null;
249
+ function enqueue(event) {
250
+ queue.push(event);
251
+ if (resolveWait) {
252
+ resolveWait();
253
+ resolveWait = null;
254
+ }
255
+ }
256
+ function waitForItem() {
257
+ if (queue.length > 0)
258
+ return Promise.resolve();
259
+ return new Promise((r) => {
260
+ resolveWait = r;
261
+ });
262
+ }
263
+ if (options?.timeout) {
264
+ timeoutId = setTimeout(() => {
265
+ timedOut = true;
266
+ proc.kill();
267
+ enqueue({ type: 'error', content: 'Agent execution timed out', timestamp: new Date() });
268
+ enqueue(null);
269
+ }, options.timeout);
270
+ }
271
+ const processStreamLine = (line) => {
272
+ try {
273
+ const parsed = JSON.parse(line);
274
+ const type = parsed.type;
275
+ if (type === 'assistant.message_delta' && parsed.delta) {
276
+ enqueue({
277
+ type: 'progress',
278
+ content: parsed.delta,
279
+ timestamp: new Date(),
280
+ });
281
+ return;
282
+ }
283
+ if (type === 'assistant.message' && parsed.content) {
284
+ // Accumulate final text; streaming progress already yielded via deltas
285
+ resultText += parsed.content;
286
+ return;
287
+ }
288
+ if (type === 'result') {
289
+ // Final event — yield result with accumulated text
290
+ enqueue({
291
+ type: 'result',
292
+ content: resultText,
293
+ timestamp: new Date(),
294
+ });
295
+ return;
296
+ }
297
+ if (type === 'error') {
298
+ enqueue({
299
+ type: 'error',
300
+ content: parsed.message ?? parsed.content ?? 'Unknown error',
301
+ timestamp: new Date(),
302
+ });
303
+ return;
304
+ }
305
+ // Unknown event types — skip gracefully
306
+ }
307
+ catch {
308
+ // Non-JSON line — emit as raw progress
309
+ enqueue({ type: 'progress', content: line, timestamp: new Date() });
310
+ }
311
+ };
312
+ proc.stdout?.on('data', (chunk) => {
313
+ lineBuffer += chunk.toString();
314
+ const lines = lineBuffer.split('\n');
315
+ lineBuffer = lines.pop() ?? '';
316
+ for (const line of lines) {
317
+ const trimmed = line.trim();
318
+ if (!trimmed)
319
+ continue;
320
+ processStreamLine(trimmed);
321
+ }
322
+ });
323
+ proc.stderr?.on('data', (chunk) => {
324
+ stderr += chunk.toString();
325
+ });
326
+ proc.on('error', (err) => {
327
+ if (timeoutId)
328
+ clearTimeout(timeoutId);
329
+ spawnError = err;
330
+ enqueue(null);
331
+ });
332
+ proc.on('close', (code) => {
333
+ if (timeoutId)
334
+ clearTimeout(timeoutId);
335
+ if (timedOut)
336
+ return; // already handled by timeout callback
337
+ if (lineBuffer.trim()) {
338
+ processStreamLine(lineBuffer.trim());
339
+ }
340
+ if (code !== 0 && code !== null) {
341
+ const authError = this.detectAuthError(stderr);
342
+ const msg = authError ??
343
+ (stderr.trim()
344
+ ? `Process exited with code ${code}: ${stderr.trim()}`
345
+ : `Process exited with code ${code}`);
346
+ enqueue({ type: 'error', content: msg, timestamp: new Date() });
347
+ }
348
+ enqueue(null);
349
+ });
350
+ try {
351
+ while (true) {
352
+ await waitForItem();
353
+ const item = queue.shift();
354
+ if (item === null || item === undefined) {
355
+ if (spawnError !== null) {
356
+ yield {
357
+ type: 'error',
358
+ content: spawnError.message,
359
+ timestamp: new Date(),
360
+ };
361
+ }
362
+ return;
363
+ }
364
+ yield item;
365
+ }
366
+ }
367
+ finally {
368
+ await preparedPrompt.cleanup();
369
+ }
370
+ }
371
+ /**
372
+ * Build CLI args for the copilot invocation.
373
+ * Prompt is passed via -p flag (not stdin).
374
+ */
375
+ buildArgs(prompt, options) {
376
+ const args = ['-p', prompt, ...BASE_FLAGS];
377
+ if (options?.model) {
378
+ args.push('--model', this.normalizeModel(options.model));
379
+ }
380
+ if (options?.resumeSession)
381
+ args.push(`--resume=${options.resumeSession}`);
382
+ // Unsupported options — log and ignore
383
+ if (options?.allowedTools?.length) {
384
+ this.log('allowedTools option is not supported by Copilot CLI — ignoring');
385
+ }
386
+ if (options?.systemPrompt) {
387
+ this.log('systemPrompt option is not supported by Copilot CLI — ignoring');
388
+ }
389
+ if (options?.outputSchema) {
390
+ this.log('outputSchema option is not supported by Copilot CLI — ignoring');
391
+ }
392
+ return args;
393
+ }
394
+ /**
395
+ * Normalize legacy model names to the canonical Copilot CLI form.
396
+ */
397
+ normalizeModel(model) {
398
+ const alias = LEGACY_MODEL_ALIASES[model];
399
+ if (alias) {
400
+ this.log(`Normalizing legacy model alias "${model}" to "${alias}"`);
401
+ return alias;
402
+ }
403
+ // Generic fallback for legacy GPT names like gpt-5-2-codex -> gpt-5.2-codex.
404
+ const genericGptAlias = model.replace(/^gpt-(\d+)-(\d+)(.*)$/i, 'gpt-$1.$2$3');
405
+ if (genericGptAlias !== model) {
406
+ this.log(`Normalizing legacy model alias "${model}" to "${genericGptAlias}"`);
407
+ return genericGptAlias;
408
+ }
409
+ return model;
410
+ }
411
+ /**
412
+ * Prepare prompt delivery for Copilot CLI.
413
+ * Uses temporary file indirection for large prompts to avoid ENAMETOOLONG.
414
+ */
415
+ shouldUsePromptFile(prompt) {
416
+ return prompt.length > MAX_PROMPT_ARG_CHARS;
417
+ }
418
+ prepareDirectPrompt(prompt) {
419
+ return {
420
+ promptArg: prompt,
421
+ usedFileIndirection: false,
422
+ cleanup: async () => {
423
+ // No temp file created for short prompts.
424
+ },
425
+ };
426
+ }
427
+ async preparePromptFileIndirection(prompt) {
428
+ const promptFilePath = join(tmpdir(), `${PROMPT_FILE_PREFIX}${randomUUID()}.txt`);
429
+ await writeFile(promptFilePath, prompt, 'utf8');
430
+ const promptArg = 'The full original user prompt is stored in this file:\n' +
431
+ `${promptFilePath}\n` +
432
+ 'Read that file completely, then execute its instructions exactly as if its content was passed directly as the prompt. ' +
433
+ 'Do not summarize or reinterpret the instructions before executing them.';
434
+ return {
435
+ promptArg,
436
+ usedFileIndirection: true,
437
+ cleanup: async () => {
438
+ try {
439
+ await unlink(promptFilePath);
440
+ }
441
+ catch {
442
+ // Ignore cleanup failures (file may already be gone).
443
+ }
444
+ },
445
+ };
446
+ }
447
+ buildSpawnOptions(options) {
448
+ const spawnOpts = {};
449
+ if (options?.cwd)
450
+ spawnOpts.cwd = options.cwd;
451
+ // Explicitly pipe stdio so streams are available
452
+ spawnOpts.stdio = ['pipe', 'pipe', 'pipe'];
453
+ // On Windows: windowsHide=true to prevent blank console windows.
454
+ // Copilot CLI is a Node.js binary, so shell=true is NOT needed.
455
+ if (process.platform === 'win32') {
456
+ spawnOpts.windowsHide = true;
457
+ }
458
+ // Strip CLAUDECODE env var to prevent "nested session" error when shep
459
+ // is invoked from within a Claude Code session.
460
+ const { CLAUDECODE: _, ...cleanEnv } = process.env;
461
+ // Copilot CLI uses GitHub OAuth — no API key injection.
462
+ spawnOpts.env = cleanEnv;
463
+ return spawnOpts;
464
+ }
465
+ /**
466
+ * Extract token usage from the Copilot CLI result event usage object.
467
+ * Returns undefined if usage data is absent (does not throw).
468
+ */
469
+ extractUsage(usage) {
470
+ if (typeof usage.inputTokens !== 'number' || typeof usage.outputTokens !== 'number') {
471
+ return undefined;
472
+ }
473
+ return { inputTokens: usage.inputTokens, outputTokens: usage.outputTokens };
474
+ }
475
+ /**
476
+ * Detect authentication-related errors in stderr and return a user-friendly message.
477
+ * Returns null if no auth error is detected.
478
+ */
479
+ detectAuthError(stderr) {
480
+ if (!stderr)
481
+ return null;
482
+ const lowerStderr = stderr.toLowerCase();
483
+ if (lowerStderr.includes('not logged in') ||
484
+ lowerStderr.includes('authentication') ||
485
+ lowerStderr.includes('auth') ||
486
+ lowerStderr.includes('unauthorized') ||
487
+ lowerStderr.includes('login required')) {
488
+ return ('GitHub Copilot CLI authentication required. ' +
489
+ 'Run: copilot auth login\n' +
490
+ `Original error: ${stderr.trim()}`);
491
+ }
492
+ return null;
493
+ }
494
+ }
@@ -0,0 +1,32 @@
1
+ {
2
+ "name": "Codex CLI",
3
+ "summary": "AI-powered code assistant from OpenAI",
4
+ "description": "Codex CLI is an AI-powered code assistant from OpenAI that helps you write, understand, and debug code with advanced AI capabilities.",
5
+ "tags": ["cli-agent"],
6
+ "author": "OpenAI",
7
+ "website": "https://developers.openai.com/codex/cli",
8
+ "platforms": ["linux", "darwin", "win32"],
9
+ "iconUrl": "https://cdn.simpleicons.org/openai",
10
+ "binary": "codex",
11
+ "packageManager": "npm",
12
+ "commands": {
13
+ "linux": "npm i -g @openai/codex",
14
+ "darwin": "npm i -g @openai/codex",
15
+ "win32": "npm i -g @openai/codex"
16
+ },
17
+ "timeout": 300000,
18
+ "documentationUrl": "https://developers.openai.com/codex",
19
+ "verifyCommand": "codex --version",
20
+ "autoInstall": true,
21
+ "openDirectory": "cd {dir} && exec codex",
22
+ "spawnOptions": {
23
+ "shell": true,
24
+ "stdio": "inherit",
25
+ "detached": false
26
+ },
27
+ "terminalCommand": {
28
+ "linux": "x-terminal-emulator -e bash -c 'cd {dir} && exec codex'",
29
+ "darwin": "open -a Terminal.app bash -c 'cd {dir} && exec codex'",
30
+ "win32": "start pwsh.exe 'cd {dir} && codex'"
31
+ }
32
+ }
@@ -0,0 +1,32 @@
1
+ {
2
+ "name": "GitHub Copilot CLI",
3
+ "summary": "AI-powered code assistant from GitHub",
4
+ "description": "GitHub Copilot CLI is an AI-powered code assistant from GitHub that helps you write, understand, and debug code with advanced AI capabilities.",
5
+ "tags": ["cli-agent"],
6
+ "author": "GitHub",
7
+ "website": "https://github.com/features/copilot/cli",
8
+ "platforms": ["linux", "darwin", "win32"],
9
+ "iconUrl": "https://cdn.simpleicons.org/githubcopilot",
10
+ "binary": "copilot",
11
+ "packageManager": "curl",
12
+ "commands": {
13
+ "linux": "curl -fsSL https://gh.io/copilot-install | bash",
14
+ "darwin": "curl -fsSL https://gh.io/copilot-install | bash",
15
+ "win32": "npm install -g @github/copilot-cli"
16
+ },
17
+ "timeout": 300000,
18
+ "documentationUrl": "https://docs.github.com/en/copilot/how-tos/copilot-cli/use-copilot-cli-agents/overview",
19
+ "verifyCommand": "copilot --version",
20
+ "autoInstall": true,
21
+ "openDirectory": "cd {dir} && exec copilot",
22
+ "spawnOptions": {
23
+ "shell": true,
24
+ "stdio": "inherit",
25
+ "detached": false
26
+ },
27
+ "terminalCommand": {
28
+ "linux": "x-terminal-emulator -e bash -c 'cd {dir} && exec copilot'",
29
+ "darwin": "open -a Terminal.app bash -c 'cd {dir} && exec copilot'",
30
+ "win32": "start pwsh.exe 'cd {dir} && copilot'"
31
+ }
32
+ }
@@ -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;AAIzD;;;;;GAKG;AACH,wBAAgB,uBAAuB;;;;;;;;;;;;;;;;;;;;;;;EA2CtC"}
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;AAIzD;;;;;GAKG;AACH,wBAAgB,uBAAuB;;;;;;;;;;;;;;;;;;;;;;;EAgDtC"}
@@ -33,6 +33,11 @@ export function createAgentSelectConfig() {
33
33
  value: AgentType.CodexCli,
34
34
  description: t('tui:prompts.selectAgent.choices.codexCli.description'),
35
35
  },
36
+ {
37
+ name: t('tui:prompts.selectAgent.choices.copilotCli.name'),
38
+ value: AgentType.CopilotCli,
39
+ description: t('tui:prompts.selectAgent.choices.copilotCli.description'),
40
+ },
36
41
  {
37
42
  name: t('tui:prompts.selectAgent.choices.cursor.name'),
38
43
  value: AgentType.Cursor,
@@ -1 +1 @@
1
- {"version":3,"file":"check-agent-auth.d.ts","sourceRoot":"","sources":["../../../../../../src/presentation/web/app/actions/check-agent-auth.ts"],"names":[],"mappings":"AAWA,MAAM,WAAW,eAAe;IAC9B,SAAS,EAAE,MAAM,CAAC;IAClB,+CAA+C;IAC/C,SAAS,EAAE,OAAO,CAAC;IACnB,8CAA8C;IAC9C,aAAa,EAAE,OAAO,CAAC;IACvB,yCAAyC;IACzC,KAAK,EAAE,MAAM,CAAC;IACd,gDAAgD;IAChD,UAAU,EAAE,MAAM,GAAG,IAAI,CAAC;IAC1B,0FAA0F;IAC1F,cAAc,EAAE,MAAM,GAAG,IAAI,CAAC;IAC9B,wDAAwD;IACxD,WAAW,EAAE,MAAM,GAAG,IAAI,CAAC;CAC5B;AA6FD;;;GAGG;AACH,wBAAsB,cAAc,IAAI,OAAO,CAAC,eAAe,CAAC,CAwF/D"}
1
+ {"version":3,"file":"check-agent-auth.d.ts","sourceRoot":"","sources":["../../../../../../src/presentation/web/app/actions/check-agent-auth.ts"],"names":[],"mappings":"AAWA,MAAM,WAAW,eAAe;IAC9B,SAAS,EAAE,MAAM,CAAC;IAClB,+CAA+C;IAC/C,SAAS,EAAE,OAAO,CAAC;IACnB,8CAA8C;IAC9C,aAAa,EAAE,OAAO,CAAC;IACvB,yCAAyC;IACzC,KAAK,EAAE,MAAM,CAAC;IACd,gDAAgD;IAChD,UAAU,EAAE,MAAM,GAAG,IAAI,CAAC;IAC1B,0FAA0F;IAC1F,cAAc,EAAE,MAAM,GAAG,IAAI,CAAC;IAC9B,wDAAwD;IACxD,WAAW,EAAE,MAAM,GAAG,IAAI,CAAC;CAC5B;AA6GD;;;GAGG;AACH,wBAAsB,cAAc,IAAI,OAAO,CAAC,eAAe,CAAC,CAwF/D"}
@@ -11,6 +11,7 @@ const AGENT_LABELS = {
11
11
  cursor: 'Cursor Agent',
12
12
  'gemini-cli': 'Gemini CLI',
13
13
  aider: 'Aider',
14
+ copilot: 'Copilot CLI',
14
15
  continue: 'Continue',
15
16
  dev: 'Demo',
16
17
  };
@@ -18,11 +19,13 @@ const AGENT_TOOL_MAP = {
18
19
  'claude-code': 'claude-code',
19
20
  cursor: 'cursor-cli',
20
21
  'gemini-cli': 'gemini-cli',
22
+ copilot: 'copilot-cli',
21
23
  };
22
24
  const AGENT_BINARY_MAP = {
23
25
  'claude-code': 'claude',
24
26
  cursor: 'cursor-agent',
25
27
  'gemini-cli': 'gemini',
28
+ copilot: 'copilot',
26
29
  };
27
30
  /**
28
31
  * Tier 1: Instant credential/env check (~5ms, no subprocess).
@@ -60,6 +63,17 @@ function tier1AuthCheck(agentType) {
60
63
  const accountsPath = join(home, '.gemini', 'google_accounts.json');
61
64
  return existsSync(accountsPath);
62
65
  }
66
+ case 'copilot-cli': {
67
+ if (process.env['GITHUB_TOKEN'])
68
+ return true;
69
+ if (process.env['GH_TOKEN'])
70
+ return true;
71
+ if (process.env['GITHUB_AUTH_TOKEN'])
72
+ return true;
73
+ // GitHub CLI stores creds after `gh auth login` — check common locations
74
+ const ghDir = IS_WINDOWS ? join(home, '.copilot') : join(home, '.config', 'gh');
75
+ return existsSync(ghDir);
76
+ }
63
77
  default:
64
78
  // dev, aider, continue — assume no auth needed
65
79
  return true;
@@ -82,6 +96,10 @@ function tier2AuthVerify(agentType, binaryName) {
82
96
  cmd = binaryName;
83
97
  args = ['status'];
84
98
  break;
99
+ case 'copilot-cli':
100
+ cmd = 'gh';
101
+ args = ['auth', 'status'];
102
+ break;
85
103
  default:
86
104
  // No tier 2 command available — trust tier 1
87
105
  resolve(true);
@@ -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;AAmBD,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;AAqBD,wBAAsB,iBAAiB,IAAI,OAAO,CAAC,eAAe,EAAE,CAAC,CA+BpE"}
@@ -4,6 +4,7 @@ import { getModelMeta } from '../../lib/model-metadata.js';
4
4
  const AGENT_LABELS = {
5
5
  'claude-code': 'Claude Code',
6
6
  'codex-cli': 'Codex CLI',
7
+ 'copilot-cli': 'Copilot CLI',
7
8
  cursor: 'Cursor CLI',
8
9
  'gemini-cli': 'Gemini CLI',
9
10
  dev: 'Demo',
@@ -12,8 +13,9 @@ const AGENT_LABELS = {
12
13
  const AGENT_ORDER = {
13
14
  'claude-code': 0,
14
15
  'codex-cli': 1,
15
- cursor: 2,
16
- 'gemini-cli': 3,
16
+ 'copilot-cli': 2,
17
+ cursor: 3,
18
+ 'gemini-cli': 4,
17
19
  dev: 99,
18
20
  };
19
21
  export async function getAllAgentModels() {
@@ -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' | 'codex-cli' | 'cursor' | 'gemini-cli' | 'aider' | 'continue' | 'dev';
3
+ export type AgentTypeValue = 'claude-code' | 'codex-cli' | 'copilot-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,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"}
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,aAAa,GACb,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;AA6DD,6CAA6C;AAC7C,eAAO,MAAM,eAAe,EAAE,MAAM,CAAC,cAAc,EAAE,MAAM,CAS1D,CAAC;AAEF,wEAAwE;AACxE,wBAAgB,gBAAgB,CAAC,SAAS,CAAC,EAAE,MAAM,GAAG,aAAa,CAAC,SAAS,CAAC,CAK7E"}