@shepai/cli 1.118.0-pr380.dfa57ad → 1.118.0-pr381.402b548

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 (132) hide show
  1. package/dist/packages/core/src/infrastructure/services/agents/common/agent-executor-factory.service.js +1 -1
  2. package/dist/packages/core/src/infrastructure/services/agents/common/executors/cursor-executor.service.d.ts +28 -8
  3. package/dist/packages/core/src/infrastructure/services/agents/common/executors/cursor-executor.service.d.ts.map +1 -1
  4. package/dist/packages/core/src/infrastructure/services/agents/common/executors/cursor-executor.service.js +80 -16
  5. package/dist/src/presentation/web/components/common/control-center-drawer/feature-drawer-client.d.ts.map +1 -1
  6. package/dist/src/presentation/web/components/common/control-center-drawer/feature-drawer-client.js +0 -4
  7. package/dist/src/presentation/web/components/features/control-center/use-control-center-state.d.ts.map +1 -1
  8. package/dist/src/presentation/web/components/features/control-center/use-control-center-state.js +2 -6
  9. package/dist/tsconfig.build.tsbuildinfo +1 -1
  10. package/package.json +1 -1
  11. package/web/.next/BUILD_ID +1 -1
  12. package/web/.next/build-manifest.json +2 -2
  13. package/web/.next/fallback-build-manifest.json +2 -2
  14. package/web/.next/prerender-manifest.json +3 -3
  15. package/web/.next/required-server-files.js +1 -1
  16. package/web/.next/required-server-files.json +1 -1
  17. package/web/.next/server/app/(dashboard)/@drawer/create/page/server-reference-manifest.json +21 -21
  18. package/web/.next/server/app/(dashboard)/@drawer/create/page.js.nft.json +1 -1
  19. package/web/.next/server/app/(dashboard)/@drawer/create/page_client-reference-manifest.js +1 -1
  20. package/web/.next/server/app/(dashboard)/@drawer/feature/[featureId]/[tab]/page/server-reference-manifest.json +27 -27
  21. package/web/.next/server/app/(dashboard)/@drawer/feature/[featureId]/[tab]/page.js.nft.json +1 -1
  22. package/web/.next/server/app/(dashboard)/@drawer/feature/[featureId]/[tab]/page_client-reference-manifest.js +1 -1
  23. package/web/.next/server/app/(dashboard)/@drawer/feature/[featureId]/page/server-reference-manifest.json +27 -27
  24. package/web/.next/server/app/(dashboard)/@drawer/feature/[featureId]/page.js.nft.json +1 -1
  25. package/web/.next/server/app/(dashboard)/@drawer/feature/[featureId]/page_client-reference-manifest.js +1 -1
  26. package/web/.next/server/app/(dashboard)/@drawer/repository/[repositoryId]/page/server-reference-manifest.json +19 -19
  27. package/web/.next/server/app/(dashboard)/@drawer/repository/[repositoryId]/page.js.nft.json +1 -1
  28. package/web/.next/server/app/(dashboard)/@drawer/repository/[repositoryId]/page_client-reference-manifest.js +1 -1
  29. package/web/.next/server/app/(dashboard)/create/page/server-reference-manifest.json +21 -21
  30. package/web/.next/server/app/(dashboard)/create/page.js.nft.json +1 -1
  31. package/web/.next/server/app/(dashboard)/create/page_client-reference-manifest.js +1 -1
  32. package/web/.next/server/app/(dashboard)/feature/[featureId]/[tab]/page/server-reference-manifest.json +27 -27
  33. package/web/.next/server/app/(dashboard)/feature/[featureId]/[tab]/page.js.nft.json +1 -1
  34. package/web/.next/server/app/(dashboard)/feature/[featureId]/[tab]/page_client-reference-manifest.js +1 -1
  35. package/web/.next/server/app/(dashboard)/feature/[featureId]/page/server-reference-manifest.json +27 -27
  36. package/web/.next/server/app/(dashboard)/feature/[featureId]/page.js.nft.json +1 -1
  37. package/web/.next/server/app/(dashboard)/feature/[featureId]/page_client-reference-manifest.js +1 -1
  38. package/web/.next/server/app/(dashboard)/page/server-reference-manifest.json +19 -19
  39. package/web/.next/server/app/(dashboard)/page.js.nft.json +1 -1
  40. package/web/.next/server/app/(dashboard)/page_client-reference-manifest.js +1 -1
  41. package/web/.next/server/app/(dashboard)/repository/[repositoryId]/page/server-reference-manifest.json +19 -19
  42. package/web/.next/server/app/(dashboard)/repository/[repositoryId]/page.js.nft.json +1 -1
  43. package/web/.next/server/app/(dashboard)/repository/[repositoryId]/page_client-reference-manifest.js +1 -1
  44. package/web/.next/server/app/_global-error.html +2 -2
  45. package/web/.next/server/app/_global-error.rsc +1 -1
  46. package/web/.next/server/app/_global-error.segments/__PAGE__.segment.rsc +1 -1
  47. package/web/.next/server/app/_global-error.segments/_full.segment.rsc +1 -1
  48. package/web/.next/server/app/_global-error.segments/_head.segment.rsc +1 -1
  49. package/web/.next/server/app/_global-error.segments/_index.segment.rsc +1 -1
  50. package/web/.next/server/app/_global-error.segments/_tree.segment.rsc +1 -1
  51. package/web/.next/server/app/_not-found/page/server-reference-manifest.json +1 -1
  52. package/web/.next/server/app/_not-found/page_client-reference-manifest.js +1 -1
  53. package/web/.next/server/app/settings/page/server-reference-manifest.json +6 -6
  54. package/web/.next/server/app/settings/page.js.nft.json +1 -1
  55. package/web/.next/server/app/settings/page_client-reference-manifest.js +1 -1
  56. package/web/.next/server/app/skills/page/server-reference-manifest.json +6 -6
  57. package/web/.next/server/app/skills/page_client-reference-manifest.js +1 -1
  58. package/web/.next/server/app/tools/page/server-reference-manifest.json +6 -6
  59. package/web/.next/server/app/tools/page_client-reference-manifest.js +1 -1
  60. package/web/.next/server/app/version/page/server-reference-manifest.json +1 -1
  61. package/web/.next/server/app/version/page_client-reference-manifest.js +1 -1
  62. package/web/.next/server/chunks/[root-of-the-server]__a402b567._.js +1 -1
  63. package/web/.next/server/chunks/ssr/744ca_web_components_common_control-center-drawer_create-drawer-client_tsx_5e26fc0a._.js +1 -1
  64. package/web/.next/server/chunks/ssr/744ca_web_components_common_control-center-drawer_create-drawer-client_tsx_5e26fc0a._.js.map +1 -1
  65. package/web/.next/server/chunks/ssr/8ba4b_server_app_(dashboard)_@drawer_repository_[repositoryId]_page_actions_ed372306.js +1 -1
  66. package/web/.next/server/chunks/ssr/8ba4b_server_app_(dashboard)_@drawer_repository_[repositoryId]_page_actions_ed372306.js.map +1 -1
  67. package/web/.next/server/chunks/ssr/8ba4b_server_app_(dashboard)_repository_[repositoryId]_page_actions_32e26434.js +1 -1
  68. package/web/.next/server/chunks/ssr/8ba4b_server_app_(dashboard)_repository_[repositoryId]_page_actions_32e26434.js.map +1 -1
  69. package/web/.next/server/chunks/ssr/[root-of-the-server]__07a39ff2._.js +1 -1
  70. package/web/.next/server/chunks/ssr/[root-of-the-server]__2ff2daf6._.js +2 -2
  71. package/web/.next/server/chunks/ssr/[root-of-the-server]__3155add4._.js +1 -1
  72. package/web/.next/server/chunks/ssr/[root-of-the-server]__3155add4._.js.map +1 -1
  73. package/web/.next/server/chunks/ssr/[root-of-the-server]__6367aea0._.js +1 -1
  74. package/web/.next/server/chunks/ssr/[root-of-the-server]__6367aea0._.js.map +1 -1
  75. package/web/.next/server/chunks/ssr/[root-of-the-server]__6b17a22d._.js +1 -1
  76. package/web/.next/server/chunks/ssr/[root-of-the-server]__6b17a22d._.js.map +1 -1
  77. package/web/.next/server/chunks/ssr/[root-of-the-server]__6bb00d90._.js +2 -2
  78. package/web/.next/server/chunks/ssr/[root-of-the-server]__6bb00d90._.js.map +1 -1
  79. package/web/.next/server/chunks/ssr/[root-of-the-server]__7b707feb._.js +2 -2
  80. package/web/.next/server/chunks/ssr/[root-of-the-server]__804c006d._.js +1 -1
  81. package/web/.next/server/chunks/ssr/[root-of-the-server]__804c006d._.js.map +1 -1
  82. package/web/.next/server/chunks/ssr/[root-of-the-server]__8763fd7a._.js +2 -2
  83. package/web/.next/server/chunks/ssr/[root-of-the-server]__9c56d724._.js +1 -1
  84. package/web/.next/server/chunks/ssr/[root-of-the-server]__9c56d724._.js.map +1 -1
  85. package/web/.next/server/chunks/ssr/[root-of-the-server]__cfc116d5._.js +1 -1
  86. package/web/.next/server/chunks/ssr/[root-of-the-server]__cfc116d5._.js.map +1 -1
  87. package/web/.next/server/chunks/ssr/[root-of-the-server]__d3841d9e._.js +1 -1
  88. package/web/.next/server/chunks/ssr/[root-of-the-server]__d3841d9e._.js.map +1 -1
  89. package/web/.next/server/chunks/ssr/_135edb9c._.js +1 -1
  90. package/web/.next/server/chunks/ssr/_135edb9c._.js.map +1 -1
  91. package/web/.next/server/chunks/ssr/_2f6f48b8._.js +1 -1
  92. package/web/.next/server/chunks/ssr/_2f6f48b8._.js.map +1 -1
  93. package/web/.next/server/chunks/ssr/{_f84ed520._.js → _328ec309._.js} +2 -2
  94. package/web/.next/server/chunks/ssr/{_f84ed520._.js.map → _328ec309._.js.map} +1 -1
  95. package/web/.next/server/chunks/ssr/{_6cbd1f4e._.js → _79c13a4c._.js} +2 -2
  96. package/web/.next/server/chunks/ssr/{_6cbd1f4e._.js.map → _79c13a4c._.js.map} +1 -1
  97. package/web/.next/server/chunks/ssr/_cc77a143._.js +1 -1
  98. package/web/.next/server/chunks/ssr/_cc77a143._.js.map +1 -1
  99. package/web/.next/server/chunks/ssr/{_c55029ff._.js → _f70781c5._.js} +2 -2
  100. package/web/.next/server/chunks/ssr/{_c55029ff._.js.map → _f70781c5._.js.map} +1 -1
  101. package/web/.next/server/chunks/ssr/b1a17_presentation_web_components_features_settings_settings-page-client_tsx_6ed9d5f8._.js +1 -1
  102. package/web/.next/server/chunks/ssr/b1a17_presentation_web_components_features_settings_settings-page-client_tsx_6ed9d5f8._.js.map +1 -1
  103. package/web/.next/server/chunks/ssr/src_presentation_web_0835b28e._.js +2 -2
  104. package/web/.next/server/chunks/ssr/src_presentation_web_0835b28e._.js.map +1 -1
  105. package/web/.next/server/chunks/ssr/src_presentation_web__next-internal_server_app_(dashboard)_page_actions_e99d78dd.js +1 -1
  106. package/web/.next/server/chunks/ssr/src_presentation_web__next-internal_server_app_(dashboard)_page_actions_e99d78dd.js.map +1 -1
  107. package/web/.next/server/chunks/ssr/src_presentation_web__next-internal_server_app_skills_page_actions_1fa8042e.js +1 -1
  108. package/web/.next/server/chunks/ssr/src_presentation_web__next-internal_server_app_skills_page_actions_1fa8042e.js.map +1 -1
  109. package/web/.next/server/chunks/ssr/src_presentation_web__next-internal_server_app_tools_page_actions_24684200.js +1 -1
  110. package/web/.next/server/chunks/ssr/src_presentation_web__next-internal_server_app_tools_page_actions_24684200.js.map +1 -1
  111. package/web/.next/server/chunks/ssr/src_presentation_web_components_bf50c527._.js +1 -1
  112. package/web/.next/server/chunks/ssr/src_presentation_web_components_de814675._.js +1 -1
  113. package/web/.next/server/chunks/ssr/src_presentation_web_components_features_control-center_7ac3562e._.js +1 -1
  114. package/web/.next/server/chunks/ssr/src_presentation_web_components_features_control-center_7ac3562e._.js.map +1 -1
  115. package/web/.next/server/chunks/ssr/src_presentation_web_e8034a29._.js +2 -2
  116. package/web/.next/server/chunks/ssr/src_presentation_web_e8034a29._.js.map +1 -1
  117. package/web/.next/server/pages/500.html +2 -2
  118. package/web/.next/server/server-reference-manifest.js +1 -1
  119. package/web/.next/server/server-reference-manifest.json +33 -33
  120. package/web/.next/static/chunks/{646d3e433c9abfbd.js → 0b3964436e809492.js} +1 -1
  121. package/web/.next/static/chunks/{7d7e7ee812313120.js → 35304f98003207af.js} +1 -1
  122. package/web/.next/static/chunks/{bd6fca67f592dddf.js → 80756b33fba5cf0c.js} +1 -1
  123. package/web/.next/static/chunks/{be5124f9bf7e5c20.js → 8abac7707fa570d4.js} +2 -2
  124. package/web/.next/static/chunks/{7b6130916427c7d5.js → b5dae8fa9a8c6ac2.js} +1 -1
  125. package/web/.next/static/chunks/{441c9e090ed3421e.js → b76e77e6c165994d.js} +1 -1
  126. package/web/.next/static/chunks/{8840985592c9f6f4.js → bd9285d40fe75608.js} +2 -2
  127. package/web/.next/static/chunks/{77bea4cc562269e5.js → da81c0c951208327.js} +1 -1
  128. package/web/.next/static/chunks/{1ea3371ba4e67de9.js → dff51e1d6c46ad32.js} +1 -1
  129. package/web/.next/static/chunks/{497a6eb33eb6be8e.js → f3afa7e73e477098.js} +1 -1
  130. /package/web/.next/static/{7j2XghmmOeoShEIApfXDS → LW_LUGRZfraMxIlSZq4Q-}/_buildManifest.js +0 -0
  131. /package/web/.next/static/{7j2XghmmOeoShEIApfXDS → LW_LUGRZfraMxIlSZq4Q-}/_clientMiddlewareManifest.json +0 -0
  132. /package/web/.next/static/{7j2XghmmOeoShEIApfXDS → LW_LUGRZfraMxIlSZq4Q-}/_ssgManifest.js +0 -0
@@ -45,7 +45,7 @@ export class AgentExecutorFactory {
45
45
  executor = new ClaudeCodeExecutorService(this.spawn);
46
46
  break;
47
47
  case 'cursor':
48
- executor = new CursorExecutorService(this.spawn);
48
+ executor = new CursorExecutorService(this.spawn, _authConfig);
49
49
  break;
50
50
  case 'dev':
51
51
  executor = new DevAgentExecutorService();
@@ -8,7 +8,7 @@
8
8
  * Uses constructor dependency injection for the spawn function
9
9
  * to enable testability without mocking node:child_process directly.
10
10
  */
11
- import type { AgentType, AgentFeature } from '../../../../../domain/generated/output.js';
11
+ import type { AgentType, AgentFeature, AgentConfig } from '../../../../../domain/generated/output.js';
12
12
  import type { IAgentExecutor, AgentExecutionOptions, AgentExecutionResult, AgentExecutionStreamEvent } from '../../../../../application/ports/output/agents/agent-executor.interface.js';
13
13
  import type { SpawnFunction } from '../types.js';
14
14
  /**
@@ -17,10 +17,11 @@ import type { SpawnFunction } from '../types.js';
17
17
  */
18
18
  export declare class CursorExecutorService implements IAgentExecutor {
19
19
  private readonly spawn;
20
+ private readonly authConfig?;
20
21
  readonly agentType: AgentType;
21
22
  /** When true, suppresses debug logging (set per-call via options.silent) */
22
23
  private silent;
23
- constructor(spawn: SpawnFunction);
24
+ constructor(spawn: SpawnFunction, authConfig?: AgentConfig | undefined);
24
25
  /** Debug logging — writes to stdout so it appears in the worker log file */
25
26
  private log;
26
27
  supportsFeature(feature: AgentFeature): boolean;
@@ -33,16 +34,35 @@ export declare class CursorExecutorService implements IAgentExecutor {
33
34
  private buildArgs;
34
35
  private buildStreamArgs;
35
36
  /**
36
- * Spawn the agent process, handling Windows specially via PowerShell.
37
+ * Resolve the cursor CLI's bundled node.exe and index.js paths on Windows.
37
38
  *
38
- * On Windows, cursor CLI ships as `agent.cmd` which requires `shell: true`,
39
- * but cmd.exe mangles long `-p` arguments (8191-char limit + special chars).
40
- * Solution: write prompt to a temp file, invoke agent via PowerShell which
41
- * reads the file and passes the content as `-p`. PowerShell handles long
42
- * strings natively (32K limit) and doesn't mangle arguments.
39
+ * The cursor CLI installs to `%LOCALAPPDATA%\cursor-agent\` with:
40
+ * - `agent.cmd` / `cursor-agent.ps1` (shell wrappers)
41
+ * - `versions/<YYYY.MM.DD-commit>/node.exe` + `index.js`
42
+ *
43
+ * Spawning via agent.cmd creates a problematic nesting chain:
44
+ * PowerShell → agent.cmd → PowerShell → cursor-agent.ps1 → node.exe
45
+ * This chain hangs on Windows CI runners. Direct invocation bypasses it.
46
+ *
47
+ * @returns `{ nodePath, indexPath }` or `undefined` if not found
48
+ */
49
+ private resolveCursorBinary;
50
+ /**
51
+ * Spawn the agent process, handling Windows specially.
52
+ *
53
+ * On Windows, the cursor CLI ships as `agent.cmd` which spawns PowerShell
54
+ * which runs `cursor-agent.ps1` which runs `node.exe index.js`. This triple
55
+ * nesting (PowerShell → cmd.exe → PowerShell → node.exe) hangs on Windows
56
+ * CI runners. Solution: resolve the cursor CLI's bundled `node.exe` and
57
+ * `index.js` directly, bypassing all shell wrappers.
43
58
  *
44
59
  * On Linux/macOS, spawn `agent` directly — no shell needed.
45
60
  */
61
+ /**
62
+ * Build the subprocess environment: strip CLAUDECODE, inject CURSOR_API_KEY
63
+ * from authConfig when token auth is configured.
64
+ */
65
+ private buildEnv;
46
66
  private spawnAgent;
47
67
  private parseStreamLine;
48
68
  }
@@ -1 +1 @@
1
- {"version":3,"file":"cursor-executor.service.d.ts","sourceRoot":"","sources":["../../../../../../../../../packages/core/src/infrastructure/services/agents/common/executors/cursor-executor.service.ts"],"names":[],"mappings":"AAAA;;;;;;;;;GASG;AAMH,OAAO,KAAK,EAAE,SAAS,EAAE,YAAY,EAAE,MAAM,2CAA2C,CAAC;AACzF,OAAO,KAAK,EACV,cAAc,EACd,qBAAqB,EACrB,oBAAoB,EACpB,yBAAyB,EAC1B,MAAM,4EAA4E,CAAC;AACpF,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,aAAa,CAAC;AAuBjD;;;GAGG;AACH,qBAAa,qBAAsB,YAAW,cAAc;IAM9C,OAAO,CAAC,QAAQ,CAAC,KAAK;IALlC,QAAQ,CAAC,SAAS,EAAE,SAAS,CAAyB;IAEtD,4EAA4E;IAC5E,OAAO,CAAC,MAAM,CAAS;gBAEM,KAAK,EAAE,aAAa;IAEjD,4EAA4E;IAC5E,OAAO,CAAC,GAAG;IAMX,eAAe,CAAC,OAAO,EAAE,YAAY,GAAG,OAAO;IAIzC,OAAO,CAAC,MAAM,EAAE,MAAM,EAAE,OAAO,CAAC,EAAE,qBAAqB,GAAG,OAAO,CAAC,oBAAoB,CAAC;IAoItF,aAAa,CAClB,MAAM,EAAE,MAAM,EACd,OAAO,CAAC,EAAE,qBAAqB,GAC9B,aAAa,CAAC,yBAAyB,CAAC;IAkF3C;;OAEG;IACH,OAAO,CAAC,cAAc;IAkCtB,OAAO,CAAC,SAAS;IASjB,OAAO,CAAC,eAAe;IAOvB;;;;;;;;;;OAUG;IACH,OAAO,CAAC,UAAU;IA2DlB,OAAO,CAAC,eAAe;CAgDxB"}
1
+ {"version":3,"file":"cursor-executor.service.d.ts","sourceRoot":"","sources":["../../../../../../../../../packages/core/src/infrastructure/services/agents/common/executors/cursor-executor.service.ts"],"names":[],"mappings":"AAAA;;;;;;;;;GASG;AAMH,OAAO,KAAK,EACV,SAAS,EACT,YAAY,EACZ,WAAW,EACZ,MAAM,2CAA2C,CAAC;AACnD,OAAO,KAAK,EACV,cAAc,EACd,qBAAqB,EACrB,oBAAoB,EACpB,yBAAyB,EAC1B,MAAM,4EAA4E,CAAC;AACpF,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,aAAa,CAAC;AAuBjD;;;GAGG;AACH,qBAAa,qBAAsB,YAAW,cAAc;IAOxD,OAAO,CAAC,QAAQ,CAAC,KAAK;IACtB,OAAO,CAAC,QAAQ,CAAC,UAAU,CAAC;IAP9B,QAAQ,CAAC,SAAS,EAAE,SAAS,CAAyB;IAEtD,4EAA4E;IAC5E,OAAO,CAAC,MAAM,CAAS;gBAGJ,KAAK,EAAE,aAAa,EACpB,UAAU,CAAC,EAAE,WAAW,YAAA;IAG3C,4EAA4E;IAC5E,OAAO,CAAC,GAAG;IAMX,eAAe,CAAC,OAAO,EAAE,YAAY,GAAG,OAAO;IAIzC,OAAO,CAAC,MAAM,EAAE,MAAM,EAAE,OAAO,CAAC,EAAE,qBAAqB,GAAG,OAAO,CAAC,oBAAoB,CAAC;IAoItF,aAAa,CAClB,MAAM,EAAE,MAAM,EACd,OAAO,CAAC,EAAE,qBAAqB,GAC9B,aAAa,CAAC,yBAAyB,CAAC;IAkF3C;;OAEG;IACH,OAAO,CAAC,cAAc;IAkCtB,OAAO,CAAC,SAAS;IASjB,OAAO,CAAC,eAAe;IAOvB;;;;;;;;;;;;OAYG;IACH,OAAO,CAAC,mBAAmB;IAyB3B;;;;;;;;;;OAUG;IACH;;;OAGG;IACH,OAAO,CAAC,QAAQ;IAYhB,OAAO,CAAC,UAAU;IA6ElB,OAAO,CAAC,eAAe;CAgDxB"}
@@ -8,7 +8,7 @@
8
8
  * Uses constructor dependency injection for the spawn function
9
9
  * to enable testability without mocking node:child_process directly.
10
10
  */
11
- import { writeFileSync, unlinkSync } from 'node:fs';
11
+ import { writeFileSync, unlinkSync, readdirSync, existsSync } from 'node:fs';
12
12
  import { execFileSync } from 'node:child_process';
13
13
  import { tmpdir } from 'node:os';
14
14
  import { join } from 'node:path';
@@ -36,11 +36,13 @@ const SUPPORTED_FEATURES = new Set(['session-resume', 'streaming']);
36
36
  */
37
37
  export class CursorExecutorService {
38
38
  spawn;
39
+ authConfig;
39
40
  agentType = 'cursor';
40
41
  /** When true, suppresses debug logging (set per-call via options.silent) */
41
42
  silent = false;
42
- constructor(spawn) {
43
+ constructor(spawn, authConfig) {
43
44
  this.spawn = spawn;
45
+ this.authConfig = authConfig;
44
46
  }
45
47
  /** Debug logging — writes to stdout so it appears in the worker log file */
46
48
  log(message) {
@@ -310,36 +312,98 @@ export class CursorExecutorService {
310
312
  return args;
311
313
  }
312
314
  /**
313
- * Spawn the agent process, handling Windows specially via PowerShell.
315
+ * Resolve the cursor CLI's bundled node.exe and index.js paths on Windows.
314
316
  *
315
- * On Windows, cursor CLI ships as `agent.cmd` which requires `shell: true`,
316
- * but cmd.exe mangles long `-p` arguments (8191-char limit + special chars).
317
- * Solution: write prompt to a temp file, invoke agent via PowerShell which
318
- * reads the file and passes the content as `-p`. PowerShell handles long
319
- * strings natively (32K limit) and doesn't mangle arguments.
317
+ * The cursor CLI installs to `%LOCALAPPDATA%\cursor-agent\` with:
318
+ * - `agent.cmd` / `cursor-agent.ps1` (shell wrappers)
319
+ * - `versions/<YYYY.MM.DD-commit>/node.exe` + `index.js`
320
+ *
321
+ * Spawning via agent.cmd creates a problematic nesting chain:
322
+ * PowerShell → agent.cmd → PowerShell → cursor-agent.ps1 → node.exe
323
+ * This chain hangs on Windows CI runners. Direct invocation bypasses it.
324
+ *
325
+ * @returns `{ nodePath, indexPath }` or `undefined` if not found
326
+ */
327
+ resolveCursorBinary() {
328
+ const localAppData = process.env.LOCALAPPDATA;
329
+ if (!localAppData)
330
+ return undefined;
331
+ const versionsDir = join(localAppData, 'cursor-agent', 'versions');
332
+ if (!existsSync(versionsDir))
333
+ return undefined;
334
+ // Find the latest version directory (format: YYYY.MM.DD-commit)
335
+ const versionPattern = /^\d{4}\.\d{1,2}\.\d{1,2}-[a-f0-9]+$/;
336
+ const versions = readdirSync(versionsDir)
337
+ .filter((d) => versionPattern.test(d))
338
+ .sort()
339
+ .reverse();
340
+ if (versions.length === 0)
341
+ return undefined;
342
+ const versionDir = join(versionsDir, versions[0]);
343
+ const nodePath = join(versionDir, 'node.exe');
344
+ const indexPath = join(versionDir, 'index.js');
345
+ if (!existsSync(nodePath) || !existsSync(indexPath))
346
+ return undefined;
347
+ return { nodePath, indexPath };
348
+ }
349
+ /**
350
+ * Spawn the agent process, handling Windows specially.
351
+ *
352
+ * On Windows, the cursor CLI ships as `agent.cmd` which spawns PowerShell
353
+ * which runs `cursor-agent.ps1` which runs `node.exe index.js`. This triple
354
+ * nesting (PowerShell → cmd.exe → PowerShell → node.exe) hangs on Windows
355
+ * CI runners. Solution: resolve the cursor CLI's bundled `node.exe` and
356
+ * `index.js` directly, bypassing all shell wrappers.
320
357
  *
321
358
  * On Linux/macOS, spawn `agent` directly — no shell needed.
322
359
  */
323
- spawnAgent(prompt, args, options) {
360
+ /**
361
+ * Build the subprocess environment: strip CLAUDECODE, inject CURSOR_API_KEY
362
+ * from authConfig when token auth is configured.
363
+ */
364
+ buildEnv(extra) {
324
365
  const { CLAUDECODE: _, ...cleanEnv } = process.env;
366
+ // Inject CURSOR_API_KEY from stored settings so the cursor CLI authenticates
367
+ // even when the env var isn't inherited (e.g. direct node.exe invocation on Windows).
368
+ if (this.authConfig?.authMethod === 'token' && this.authConfig.token) {
369
+ cleanEnv.CURSOR_API_KEY = this.authConfig.token;
370
+ }
371
+ return extra ? { ...cleanEnv, ...extra } : cleanEnv;
372
+ }
373
+ spawnAgent(prompt, args, options) {
325
374
  const cwd = options?.cwd;
326
375
  if (IS_WINDOWS) {
327
- // Write prompt to temp file to bypass cmd.exe argument mangling
376
+ const resolved = this.resolveCursorBinary();
377
+ if (resolved) {
378
+ // Direct invocation: node.exe index.js <args>
379
+ // No shell wrappers, no nesting, no hangs.
380
+ const directArgs = [resolved.indexPath, ...args];
381
+ this.log(`Windows direct mode: ${resolved.nodePath}`);
382
+ this.log(`Args: ${directArgs.map((a) => (a.length > 80 ? `${a.slice(0, 77)}...` : a)).join(' ')}`);
383
+ const proc = this.spawn(resolved.nodePath, directArgs, {
384
+ cwd,
385
+ stdio: ['pipe', 'pipe', 'pipe'],
386
+ windowsHide: true,
387
+ env: this.buildEnv({ CURSOR_INVOKED_AS: 'agent' }),
388
+ });
389
+ this.log(`Direct PID: ${proc.pid ?? 'undefined (spawn may have failed)'}`);
390
+ if (proc.stdin)
391
+ proc.stdin.end();
392
+ return { proc, tmpFile: undefined };
393
+ }
394
+ // Fallback: if direct resolution fails, use PowerShell + temp file
395
+ this.log('Windows fallback: cursor binary not resolved, using PowerShell');
328
396
  const tmpFile = join(tmpdir(), `shep-cursor-${Date.now()}-${Math.random().toString(36).slice(2, 6)}.txt`);
329
397
  writeFileSync(tmpFile, prompt, 'utf8');
330
- // Build the agent args WITHOUT -p and the prompt (they go via temp file)
331
398
  const agentFlags = args.filter((a) => a !== '-p' && a !== prompt).join(' ');
332
399
  const safePath = tmpFile.replace(/'/g, "''");
333
400
  const psCmd = `$p = Get-Content -Raw '${safePath}'; & agent ${agentFlags} -p $p`;
334
- this.log(`Windows PowerShell mode: wrote ${prompt.length} chars to ${tmpFile}`);
335
- this.log(`PS command: ${psCmd.replace(prompt, `<${prompt.length} chars>`)}`);
336
401
  const proc = this.spawn('powershell.exe', ['-NoProfile', '-NonInteractive', '-Command', psCmd], {
337
402
  cwd,
338
403
  stdio: ['pipe', 'pipe', 'pipe'],
339
404
  windowsHide: true,
340
- env: cleanEnv,
405
+ env: this.buildEnv(),
341
406
  });
342
- this.log(`PowerShell PID: ${proc.pid ?? 'undefined (spawn may have failed)'}`);
343
407
  if (proc.stdin)
344
408
  proc.stdin.end();
345
409
  return { proc, tmpFile };
@@ -347,7 +411,7 @@ export class CursorExecutorService {
347
411
  // Linux/macOS: spawn agent directly, no shell needed
348
412
  const spawnOpts = {
349
413
  stdio: ['pipe', 'pipe', 'pipe'],
350
- env: cleanEnv,
414
+ env: this.buildEnv(),
351
415
  };
352
416
  if (cwd)
353
417
  spawnOpts.cwd = cwd;
@@ -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;AAI/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,2CAqkB1F"}
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;AAI/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,2CA+jB1F"}
@@ -194,10 +194,6 @@ export function FeatureDrawerClient({ view: initialView, urlTab }) {
194
194
  if (result.iterationWarning) {
195
195
  toast.warning(`Iteration ${result.iteration} — consider approving or adjusting feedback to avoid excessive iterations`);
196
196
  }
197
- // Optimistically update canvas node before SSE arrives (~500ms delay)
198
- window.dispatchEvent(new CustomEvent('shep:feature-approved', {
199
- detail: { featureId: featureNode.featureId },
200
- }));
201
197
  onClose();
202
198
  onDone?.();
203
199
  }
@@ -1 +1 @@
1
- {"version":3,"file":"use-control-center-state.d.ts","sourceRoot":"","sources":["../../../../../../../src/presentation/web/components/features/control-center/use-control-center-state.ts"],"names":[],"mappings":"AAKA,OAAO,KAAK,EAAE,UAAU,EAAE,IAAI,EAAE,UAAU,EAAE,MAAM,eAAe,CAAC;AAClE,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,kCAAkC,CAAC;AACxE,OAAO,KAAK,EAAE,kBAAkB,EAAE,MAAM,qCAAqC,CAAC;AAC9E,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,uCAAuC,CAAC;AAC5E,OAAO,EAGL,KAAK,eAAe,EACrB,MAAM,yBAAyB,CAAC;AAejC,OAAO,EAAiB,KAAK,cAAc,EAAE,MAAM,yBAAyB,CAAC;AAM7E,MAAM,WAAW,kBAAkB;IACjC,KAAK,EAAE,cAAc,EAAE,CAAC;IACxB,KAAK,EAAE,IAAI,EAAE,CAAC;IACd,aAAa,EAAE,CAAC,OAAO,EAAE,UAAU,CAAC,cAAc,CAAC,EAAE,KAAK,IAAI,CAAC;IAC/D,aAAa,EAAE,CAAC,UAAU,EAAE,UAAU,KAAK,IAAI,CAAC;IAChD,mBAAmB,EAAE,CAAC,IAAI,EAAE,MAAM,KAAK;QAAE,QAAQ,EAAE,OAAO,CAAC;QAAC,QAAQ,EAAE,MAAM,CAAA;KAAE,CAAC;IAC/E,YAAY,EAAE,CAAC,SAAS,EAAE,eAAe,KAAK,IAAI,CAAC;IACnD,mBAAmB,EAAE,CAAC,SAAS,EAAE,MAAM,EAAE,OAAO,CAAC,EAAE,OAAO,EAAE,aAAa,CAAC,EAAE,OAAO,KAAK,IAAI,CAAC;IAC7F,kBAAkB,EAAE,CAAC,SAAS,EAAE,MAAM,KAAK,IAAI,CAAC;IAChD,kBAAkB,EAAE,CAAC,SAAS,EAAE,MAAM,KAAK,IAAI,CAAC;IAChD,sBAAsB,EAAE,CAAC,YAAY,EAAE,MAAM,KAAK,OAAO,CAAC,IAAI,CAAC,CAAC;IAChE,iBAAiB,EAAE,CACjB,YAAY,EAAE,MAAM,GAAG,IAAI,EAC3B,YAAY,CAAC,EAAE,OAAO,CAAC,eAAe,CAAC,EACvC,QAAQ,CAAC,EAAE,MAAM,KACd,MAAM,CAAC;IACZ,wDAAwD;IACxD,wBAAwB,EAAE,CAAC,aAAa,EAAE,MAAM,KAAK,MAAM,GAAG,SAAS,CAAC;IACxE,gDAAgD;IAChD,iBAAiB,EAAE,CAAC,MAAM,EAAE,MAAM,KAAK,kBAAkB,GAAG,SAAS,CAAC;IACtE,0EAA0E;IAC1E,YAAY,EAAE,CAAC,SAAS,EAAE,cAAc,KAAK,IAAI,CAAC;CACnD;AAQD,wBAAgB,qBAAqB,CACnC,YAAY,EAAE,cAAc,EAAE,EAC9B,YAAY,EAAE,IAAI,EAAE,GACnB,kBAAkB,CAwfpB"}
1
+ {"version":3,"file":"use-control-center-state.d.ts","sourceRoot":"","sources":["../../../../../../../src/presentation/web/components/features/control-center/use-control-center-state.ts"],"names":[],"mappings":"AAKA,OAAO,KAAK,EAAE,UAAU,EAAE,IAAI,EAAE,UAAU,EAAE,MAAM,eAAe,CAAC;AAClE,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,kCAAkC,CAAC;AACxE,OAAO,KAAK,EAAE,kBAAkB,EAAE,MAAM,qCAAqC,CAAC;AAC9E,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,uCAAuC,CAAC;AAC5E,OAAO,EAGL,KAAK,eAAe,EACrB,MAAM,yBAAyB,CAAC;AAejC,OAAO,EAAiB,KAAK,cAAc,EAAE,MAAM,yBAAyB,CAAC;AAM7E,MAAM,WAAW,kBAAkB;IACjC,KAAK,EAAE,cAAc,EAAE,CAAC;IACxB,KAAK,EAAE,IAAI,EAAE,CAAC;IACd,aAAa,EAAE,CAAC,OAAO,EAAE,UAAU,CAAC,cAAc,CAAC,EAAE,KAAK,IAAI,CAAC;IAC/D,aAAa,EAAE,CAAC,UAAU,EAAE,UAAU,KAAK,IAAI,CAAC;IAChD,mBAAmB,EAAE,CAAC,IAAI,EAAE,MAAM,KAAK;QAAE,QAAQ,EAAE,OAAO,CAAC;QAAC,QAAQ,EAAE,MAAM,CAAA;KAAE,CAAC;IAC/E,YAAY,EAAE,CAAC,SAAS,EAAE,eAAe,KAAK,IAAI,CAAC;IACnD,mBAAmB,EAAE,CAAC,SAAS,EAAE,MAAM,EAAE,OAAO,CAAC,EAAE,OAAO,EAAE,aAAa,CAAC,EAAE,OAAO,KAAK,IAAI,CAAC;IAC7F,kBAAkB,EAAE,CAAC,SAAS,EAAE,MAAM,KAAK,IAAI,CAAC;IAChD,kBAAkB,EAAE,CAAC,SAAS,EAAE,MAAM,KAAK,IAAI,CAAC;IAChD,sBAAsB,EAAE,CAAC,YAAY,EAAE,MAAM,KAAK,OAAO,CAAC,IAAI,CAAC,CAAC;IAChE,iBAAiB,EAAE,CACjB,YAAY,EAAE,MAAM,GAAG,IAAI,EAC3B,YAAY,CAAC,EAAE,OAAO,CAAC,eAAe,CAAC,EACvC,QAAQ,CAAC,EAAE,MAAM,KACd,MAAM,CAAC;IACZ,wDAAwD;IACxD,wBAAwB,EAAE,CAAC,aAAa,EAAE,MAAM,KAAK,MAAM,GAAG,SAAS,CAAC;IACxE,gDAAgD;IAChD,iBAAiB,EAAE,CAAC,MAAM,EAAE,MAAM,KAAK,kBAAkB,GAAG,SAAS,CAAC;IACtE,0EAA0E;IAC1E,YAAY,EAAE,CAAC,SAAS,EAAE,cAAc,KAAK,IAAI,CAAC;CACnD;AAQD,wBAAgB,qBAAqB,CACnC,YAAY,EAAE,cAAc,EAAE,EAC9B,YAAY,EAAE,IAAI,EAAE,GACnB,kBAAkB,CAofpB"}
@@ -114,19 +114,15 @@ export function useControlCenterState(initialNodes, initialEdges) {
114
114
  }
115
115
  }
116
116
  }, [events, updateFeature]);
117
- // Listen for optimistic approval/rejection events from the drawer (fires before SSE arrives).
118
- // Uses beginMutation + endMutation to prevent stale poll/reconcile data from overwriting
119
- // the optimistic 'running' state during the transition window (avoids brief "Something went wrong" flash).
117
+ // Listen for optimistic approval events from the drawer (fires before SSE arrives)
120
118
  useEffect(() => {
121
119
  const handler = (e) => {
122
120
  const { featureId } = e.detail;
123
- beginMutation();
124
121
  updateFeature(`feat-${featureId}`, { state: 'running' });
125
- endMutation();
126
122
  };
127
123
  window.addEventListener('shep:feature-approved', handler);
128
124
  return () => window.removeEventListener('shep:feature-approved', handler);
129
- }, [updateFeature, beginMutation, endMutation]);
125
+ }, [updateFeature]);
130
126
  // Separate effect: fetch metadata (name + description) when SSE reports it changed
131
127
  const metadataFetchedRef = useRef(new Set());
132
128
  const processedMetadataCountRef = useRef(0);