@shepai/cli 1.119.0-pr381.415b252 → 1.119.0-pr382.f844b0c

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 (137) 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 +8 -28
  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 +20 -117
  5. package/dist/src/presentation/web/components/layouts/app-shell/app-shell.d.ts.map +1 -1
  6. package/dist/src/presentation/web/components/layouts/app-shell/app-shell.js +8 -3
  7. package/dist/tsconfig.build.tsbuildinfo +1 -1
  8. package/package.json +1 -1
  9. package/web/.next/BUILD_ID +1 -1
  10. package/web/.next/build-manifest.json +2 -2
  11. package/web/.next/fallback-build-manifest.json +2 -2
  12. package/web/.next/prerender-manifest.json +3 -3
  13. package/web/.next/required-server-files.js +1 -1
  14. package/web/.next/required-server-files.json +1 -1
  15. package/web/.next/server/app/(dashboard)/@drawer/create/page/server-reference-manifest.json +21 -21
  16. package/web/.next/server/app/(dashboard)/@drawer/create/page.js.nft.json +1 -1
  17. package/web/.next/server/app/(dashboard)/@drawer/create/page_client-reference-manifest.js +1 -1
  18. package/web/.next/server/app/(dashboard)/@drawer/feature/[featureId]/[tab]/page/server-reference-manifest.json +27 -27
  19. package/web/.next/server/app/(dashboard)/@drawer/feature/[featureId]/[tab]/page.js.nft.json +1 -1
  20. package/web/.next/server/app/(dashboard)/@drawer/feature/[featureId]/[tab]/page_client-reference-manifest.js +1 -1
  21. package/web/.next/server/app/(dashboard)/@drawer/feature/[featureId]/page/server-reference-manifest.json +27 -27
  22. package/web/.next/server/app/(dashboard)/@drawer/feature/[featureId]/page.js.nft.json +1 -1
  23. package/web/.next/server/app/(dashboard)/@drawer/feature/[featureId]/page_client-reference-manifest.js +1 -1
  24. package/web/.next/server/app/(dashboard)/@drawer/repository/[repositoryId]/page/server-reference-manifest.json +19 -19
  25. package/web/.next/server/app/(dashboard)/@drawer/repository/[repositoryId]/page.js.nft.json +1 -1
  26. package/web/.next/server/app/(dashboard)/@drawer/repository/[repositoryId]/page_client-reference-manifest.js +1 -1
  27. package/web/.next/server/app/(dashboard)/create/page/server-reference-manifest.json +21 -21
  28. package/web/.next/server/app/(dashboard)/create/page.js.nft.json +1 -1
  29. package/web/.next/server/app/(dashboard)/create/page_client-reference-manifest.js +1 -1
  30. package/web/.next/server/app/(dashboard)/feature/[featureId]/[tab]/page/server-reference-manifest.json +27 -27
  31. package/web/.next/server/app/(dashboard)/feature/[featureId]/[tab]/page.js.nft.json +1 -1
  32. package/web/.next/server/app/(dashboard)/feature/[featureId]/[tab]/page_client-reference-manifest.js +1 -1
  33. package/web/.next/server/app/(dashboard)/feature/[featureId]/page/server-reference-manifest.json +27 -27
  34. package/web/.next/server/app/(dashboard)/feature/[featureId]/page.js.nft.json +1 -1
  35. package/web/.next/server/app/(dashboard)/feature/[featureId]/page_client-reference-manifest.js +1 -1
  36. package/web/.next/server/app/(dashboard)/page/server-reference-manifest.json +19 -19
  37. package/web/.next/server/app/(dashboard)/page.js.nft.json +1 -1
  38. package/web/.next/server/app/(dashboard)/page_client-reference-manifest.js +1 -1
  39. package/web/.next/server/app/(dashboard)/repository/[repositoryId]/page/server-reference-manifest.json +19 -19
  40. package/web/.next/server/app/(dashboard)/repository/[repositoryId]/page.js.nft.json +1 -1
  41. package/web/.next/server/app/(dashboard)/repository/[repositoryId]/page_client-reference-manifest.js +1 -1
  42. package/web/.next/server/app/_global-error.html +2 -2
  43. package/web/.next/server/app/_global-error.rsc +1 -1
  44. package/web/.next/server/app/_global-error.segments/__PAGE__.segment.rsc +1 -1
  45. package/web/.next/server/app/_global-error.segments/_full.segment.rsc +1 -1
  46. package/web/.next/server/app/_global-error.segments/_head.segment.rsc +1 -1
  47. package/web/.next/server/app/_global-error.segments/_index.segment.rsc +1 -1
  48. package/web/.next/server/app/_global-error.segments/_tree.segment.rsc +1 -1
  49. package/web/.next/server/app/_not-found/page/server-reference-manifest.json +1 -1
  50. package/web/.next/server/app/_not-found/page_client-reference-manifest.js +1 -1
  51. package/web/.next/server/app/settings/page/server-reference-manifest.json +6 -6
  52. package/web/.next/server/app/settings/page.js.nft.json +1 -1
  53. package/web/.next/server/app/settings/page_client-reference-manifest.js +1 -1
  54. package/web/.next/server/app/skills/page/server-reference-manifest.json +6 -6
  55. package/web/.next/server/app/skills/page_client-reference-manifest.js +1 -1
  56. package/web/.next/server/app/tools/page/server-reference-manifest.json +6 -6
  57. package/web/.next/server/app/tools/page_client-reference-manifest.js +1 -1
  58. package/web/.next/server/app/version/page/server-reference-manifest.json +1 -1
  59. package/web/.next/server/app/version/page_client-reference-manifest.js +1 -1
  60. package/web/.next/server/chunks/[root-of-the-server]__a402b567._.js +1 -1
  61. package/web/.next/server/chunks/ssr/744ca_web_components_common_control-center-drawer_create-drawer-client_tsx_5e26fc0a._.js +1 -1
  62. package/web/.next/server/chunks/ssr/744ca_web_components_common_control-center-drawer_create-drawer-client_tsx_5e26fc0a._.js.map +1 -1
  63. package/web/.next/server/chunks/ssr/8ba4b_server_app_(dashboard)_@drawer_repository_[repositoryId]_page_actions_ed372306.js +1 -1
  64. package/web/.next/server/chunks/ssr/8ba4b_server_app_(dashboard)_@drawer_repository_[repositoryId]_page_actions_ed372306.js.map +1 -1
  65. package/web/.next/server/chunks/ssr/8ba4b_server_app_(dashboard)_repository_[repositoryId]_page_actions_32e26434.js +1 -1
  66. package/web/.next/server/chunks/ssr/8ba4b_server_app_(dashboard)_repository_[repositoryId]_page_actions_32e26434.js.map +1 -1
  67. package/web/.next/server/chunks/ssr/[root-of-the-server]__06fef644._.js +1 -1
  68. package/web/.next/server/chunks/ssr/[root-of-the-server]__3b14e5a0._.js +1 -1
  69. package/web/.next/server/chunks/ssr/[root-of-the-server]__3b14e5a0._.js.map +1 -1
  70. package/web/.next/server/chunks/ssr/[root-of-the-server]__545792ab._.js +1 -1
  71. package/web/.next/server/chunks/ssr/[root-of-the-server]__545792ab._.js.map +1 -1
  72. package/web/.next/server/chunks/ssr/[root-of-the-server]__6b17a22d._.js +1 -1
  73. package/web/.next/server/chunks/ssr/[root-of-the-server]__6b17a22d._.js.map +1 -1
  74. package/web/.next/server/chunks/ssr/[root-of-the-server]__6bb00d90._.js +2 -2
  75. package/web/.next/server/chunks/ssr/[root-of-the-server]__6bb00d90._.js.map +1 -1
  76. package/web/.next/server/chunks/ssr/[root-of-the-server]__804c006d._.js +1 -1
  77. package/web/.next/server/chunks/ssr/[root-of-the-server]__804c006d._.js.map +1 -1
  78. package/web/.next/server/chunks/ssr/[root-of-the-server]__8b59c03e._.js +1 -1
  79. package/web/.next/server/chunks/ssr/[root-of-the-server]__8b59c03e._.js.map +1 -1
  80. package/web/.next/server/chunks/ssr/[root-of-the-server]__8c553503._.js +2 -2
  81. package/web/.next/server/chunks/ssr/[root-of-the-server]__994ad9fe._.js +1 -1
  82. package/web/.next/server/chunks/ssr/[root-of-the-server]__994ad9fe._.js.map +1 -1
  83. package/web/.next/server/chunks/ssr/[root-of-the-server]__a022445f._.js +2 -2
  84. package/web/.next/server/chunks/ssr/[root-of-the-server]__a7de2711._.js +2 -2
  85. package/web/.next/server/chunks/ssr/[root-of-the-server]__c9c1cfee._.js +1 -1
  86. package/web/.next/server/chunks/ssr/[root-of-the-server]__c9c1cfee._.js.map +1 -1
  87. package/web/.next/server/chunks/ssr/_135edb9c._.js +1 -1
  88. package/web/.next/server/chunks/ssr/_135edb9c._.js.map +1 -1
  89. package/web/.next/server/chunks/ssr/_2f6f48b8._.js +1 -1
  90. package/web/.next/server/chunks/ssr/_2f6f48b8._.js.map +1 -1
  91. package/web/.next/server/chunks/ssr/_ab069e13._.js +1 -1
  92. package/web/.next/server/chunks/ssr/_ab069e13._.js.map +1 -1
  93. package/web/.next/server/chunks/ssr/_cc77a143._.js +1 -1
  94. package/web/.next/server/chunks/ssr/_cc77a143._.js.map +1 -1
  95. package/web/.next/server/chunks/ssr/{_c016175b._.js → _d3ac41e4._.js} +2 -2
  96. package/web/.next/server/chunks/ssr/{_c016175b._.js.map → _d3ac41e4._.js.map} +1 -1
  97. package/web/.next/server/chunks/ssr/{_c6b80726._.js → _f68cd40a._.js} +2 -2
  98. package/web/.next/server/chunks/ssr/{_c6b80726._.js.map → _f68cd40a._.js.map} +1 -1
  99. package/web/.next/server/chunks/ssr/_f9f273ac._.js +3 -0
  100. package/web/.next/server/chunks/ssr/{_435cd61a._.js.map → _f9f273ac._.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_e599bb8c._.js +1 -1
  114. package/web/.next/server/chunks/ssr/src_presentation_web_components_e599bb8c._.js.map +1 -1
  115. package/web/.next/server/chunks/ssr/src_presentation_web_components_features_control-center_7ac3562e._.js +1 -1
  116. package/web/.next/server/chunks/ssr/src_presentation_web_components_features_control-center_7ac3562e._.js.map +1 -1
  117. package/web/.next/server/chunks/ssr/src_presentation_web_e8034a29._.js +2 -2
  118. package/web/.next/server/chunks/ssr/src_presentation_web_e8034a29._.js.map +1 -1
  119. package/web/.next/server/pages/500.html +2 -2
  120. package/web/.next/server/server-reference-manifest.js +1 -1
  121. package/web/.next/server/server-reference-manifest.json +33 -33
  122. package/web/.next/static/chunks/{96049ca80ceb10f0.js → 2104d54a331a01a8.js} +1 -1
  123. package/web/.next/static/chunks/{3b27bd39bf11f076.js → 22a09e8581a775da.js} +1 -1
  124. package/web/.next/static/chunks/{bb03051ee7c01e64.js → 25c3d8f72b65c176.js} +2 -2
  125. package/web/.next/static/chunks/3945855b1fb0125e.js +1 -0
  126. package/web/.next/static/chunks/{7eb1d12ff4e0a545.js → 4bf310c7837ec4c9.js} +1 -1
  127. package/web/.next/static/chunks/{418128e3931a55f3.js → 54065a2d3aa77d6a.js} +1 -1
  128. package/web/.next/static/chunks/{0f070bdb053b3579.js → 5732fcfe2e277225.js} +2 -2
  129. package/web/.next/static/chunks/{485dfa2b1ba874ef.js → 67a6eeacd4cea4b6.js} +1 -1
  130. package/web/.next/static/chunks/{619af41a8d3232e5.js → 71161130b2462279.js} +1 -1
  131. package/web/.next/static/chunks/{66c4848bc7b13df8.js → 7dee8cf92be8bf24.js} +1 -1
  132. package/web/.next/static/chunks/{139f46d14f2be0a6.js → 885da7f69d637a5f.js} +1 -1
  133. package/web/.next/server/chunks/ssr/_435cd61a._.js +0 -3
  134. package/web/.next/static/chunks/d8d23303021cea22.js +0 -1
  135. /package/web/.next/static/{VKrxBSI0iPzA7QL_Xgt6y → GvtDAY-V0NfItBFI1sJMY}/_buildManifest.js +0 -0
  136. /package/web/.next/static/{VKrxBSI0iPzA7QL_Xgt6y → GvtDAY-V0NfItBFI1sJMY}/_clientMiddlewareManifest.json +0 -0
  137. /package/web/.next/static/{VKrxBSI0iPzA7QL_Xgt6y → GvtDAY-V0NfItBFI1sJMY}/_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, _authConfig);
48
+ executor = new CursorExecutorService(this.spawn);
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, AgentConfig } from '../../../../../domain/generated/output.js';
11
+ import type { AgentType, AgentFeature } 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,11 +17,10 @@ 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?;
21
20
  readonly agentType: AgentType;
22
21
  /** When true, suppresses debug logging (set per-call via options.silent) */
23
22
  private silent;
24
- constructor(spawn: SpawnFunction, authConfig?: AgentConfig | undefined);
23
+ constructor(spawn: SpawnFunction);
25
24
  /** Debug logging — writes to stdout so it appears in the worker log file */
26
25
  private log;
27
26
  supportsFeature(feature: AgentFeature): boolean;
@@ -34,35 +33,16 @@ export declare class CursorExecutorService implements IAgentExecutor {
34
33
  private buildArgs;
35
34
  private buildStreamArgs;
36
35
  /**
37
- * Resolve the cursor CLI's bundled node.exe and index.js paths on Windows.
36
+ * Spawn the agent process, handling Windows specially via PowerShell.
38
37
  *
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.
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.
58
43
  *
59
44
  * On Linux/macOS, spawn `agent` directly — no shell needed.
60
45
  */
61
- /**
62
- * Build the subprocess environment: strip CLAUDECODE, inject CURSOR_API_KEY
63
- * from authConfig when token auth is configured.
64
- */
65
- private buildEnv;
66
46
  private spawnAgent;
67
47
  private parseStreamLine;
68
48
  }
@@ -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,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;IA2KtF,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;IAuBhB,OAAO,CAAC,UAAU;IA6ElB,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,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"}
@@ -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, readdirSync, existsSync } from 'node:fs';
11
+ import { writeFileSync, unlinkSync } 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,13 +36,11 @@ const SUPPORTED_FEATURES = new Set(['session-resume', 'streaming']);
36
36
  */
37
37
  export class CursorExecutorService {
38
38
  spawn;
39
- authConfig;
40
39
  agentType = 'cursor';
41
40
  /** When true, suppresses debug logging (set per-call via options.silent) */
42
41
  silent = false;
43
- constructor(spawn, authConfig) {
42
+ constructor(spawn) {
44
43
  this.spawn = spawn;
45
- this.authConfig = authConfig;
46
44
  }
47
45
  /** Debug logging — writes to stdout so it appears in the worker log file */
48
46
  log(message) {
@@ -60,34 +58,19 @@ export class CursorExecutorService {
60
58
  // stream-json is unreliable on Windows where shell: true can mangle args.
61
59
  const args = this.buildArgs(prompt, options);
62
60
  const { proc, tmpFile } = this.spawnAgent(prompt, args, options);
63
- // Diagnostic: verify streams are connected and process is alive
64
- this.log(`[diag] proc.pid=${proc.pid}, killed=${proc.killed}`);
65
- this.log(`[diag] stdout=${!!proc.stdout}, stderr=${!!proc.stderr}, stdin=${!!proc.stdin}`);
66
- this.log(`[diag] CURSOR_API_KEY set=${!!process.env.CURSOR_API_KEY}, len=${process.env.CURSOR_API_KEY?.length ?? 0}`);
67
- this.log(`[diag] authConfig.token set=${!!this.authConfig?.token}, method=${this.authConfig?.authMethod ?? 'none'}`);
68
- this.log(`[diag] platform=${process.platform}, cwd=${options?.cwd ?? '(inherited)'}`);
69
61
  return new Promise((resolve, reject) => {
70
62
  let lineBuffer = '';
71
63
  let stderr = '';
72
64
  let timedOut = false;
73
65
  let timeoutId;
74
- let stdoutChunks = 0;
75
- let stderrChunks = 0;
76
- const startTime = Date.now();
77
66
  // Accumulated from JSON events or raw text fallback
78
67
  let resultText = '';
79
68
  let rawText = '';
80
69
  let sessionId;
81
70
  let metadata;
82
- // Periodic heartbeat to prove the executor is alive and waiting
83
- const heartbeatId = setInterval(() => {
84
- const elapsed = Math.round((Date.now() - startTime) / 1000);
85
- this.log(`[diag] heartbeat ${elapsed}s: stdout_chunks=${stdoutChunks}, stderr_chunks=${stderrChunks}, pid_killed=${proc.killed}`);
86
- }, 15_000);
87
71
  if (options?.timeout) {
88
72
  timeoutId = setTimeout(() => {
89
73
  timedOut = true;
90
- this.log(`[diag] TIMEOUT after ${options.timeout}ms — killing process tree`);
91
74
  // On Windows, proc.kill() may not kill the entire process tree
92
75
  // (PowerShell + child agent process). Use taskkill /T for tree kill.
93
76
  if (process.platform === 'win32' && proc.pid) {
@@ -95,11 +78,9 @@ export class CursorExecutorService {
95
78
  execFileSync('taskkill', ['/F', '/T', '/PID', String(proc.pid)], {
96
79
  stdio: 'ignore',
97
80
  });
98
- this.log(`[diag] taskkill /T /PID ${proc.pid} succeeded`);
99
81
  }
100
82
  catch {
101
83
  proc.kill();
102
- this.log(`[diag] taskkill failed, fell back to proc.kill()`);
103
84
  }
104
85
  }
105
86
  else {
@@ -136,12 +117,7 @@ export class CursorExecutorService {
136
117
  }
137
118
  };
138
119
  proc.stdout?.on('data', (chunk) => {
139
- stdoutChunks++;
140
- const data = chunk.toString();
141
- if (stdoutChunks <= 3) {
142
- this.log(`[diag] stdout chunk #${stdoutChunks}: ${data.length} bytes, first 200: ${data.slice(0, 200).replace(/\n/g, '\\n')}`);
143
- }
144
- lineBuffer += data;
120
+ lineBuffer += chunk.toString();
145
121
  const lines = lineBuffer.split('\n');
146
122
  lineBuffer = lines.pop() ?? '';
147
123
  for (const line of lines) {
@@ -151,22 +127,19 @@ export class CursorExecutorService {
151
127
  }
152
128
  });
153
129
  proc.stderr?.on('data', (chunk) => {
154
- stderrChunks++;
155
130
  const data = chunk.toString();
156
131
  stderr += data;
157
- this.log(`[diag] stderr chunk #${stderrChunks}: ${data.trimEnd()}`);
132
+ this.log(`stderr: ${data.trimEnd()}`);
158
133
  // Detect fatal errors early so callers don't waste time retrying
159
134
  if (data.includes('Cannot use this model')) {
160
135
  if (timeoutId)
161
136
  clearTimeout(timeoutId);
162
- clearInterval(heartbeatId);
163
137
  proc.kill();
164
138
  reject(new Error(data.trim()));
165
139
  }
166
140
  });
167
141
  proc.on('error', (error) => {
168
- this.log(`[diag] Process ERROR event: ${error.message} (code=${error.code})`);
169
- clearInterval(heartbeatId);
142
+ this.log(`Process error event: ${error.message}`);
170
143
  if (timeoutId)
171
144
  clearTimeout(timeoutId);
172
145
  if (error.code === 'ENOENT') {
@@ -177,8 +150,6 @@ export class CursorExecutorService {
177
150
  }
178
151
  });
179
152
  proc.on('close', (code) => {
180
- const elapsed = Math.round((Date.now() - startTime) / 1000);
181
- clearInterval(heartbeatId);
182
153
  // Clean up temp file on Windows
183
154
  if (tmpFile) {
184
155
  try {
@@ -192,7 +163,7 @@ export class CursorExecutorService {
192
163
  processLine(lineBuffer.trim());
193
164
  // Use raw text as fallback when no JSON result was captured
194
165
  const finalText = resultText || rawText.trim();
195
- this.log(`[diag] Process CLOSE: code=${code}, elapsed=${elapsed}s, stdout_chunks=${stdoutChunks}, stderr_chunks=${stderrChunks}, result=${finalText.length} chars, raw=${rawText.length} chars`);
166
+ this.log(`Process closed with code ${code}, result=${finalText.length} chars`);
196
167
  if (timeoutId)
197
168
  clearTimeout(timeoutId);
198
169
  if (timedOut) {
@@ -339,104 +310,36 @@ export class CursorExecutorService {
339
310
  return args;
340
311
  }
341
312
  /**
342
- * Resolve the cursor CLI's bundled node.exe and index.js paths on Windows.
343
- *
344
- * The cursor CLI installs to `%LOCALAPPDATA%\cursor-agent\` with:
345
- * - `agent.cmd` / `cursor-agent.ps1` (shell wrappers)
346
- * - `versions/<YYYY.MM.DD-commit>/node.exe` + `index.js`
347
- *
348
- * Spawning via agent.cmd creates a problematic nesting chain:
349
- * PowerShell → agent.cmd → PowerShell → cursor-agent.ps1 → node.exe
350
- * This chain hangs on Windows CI runners. Direct invocation bypasses it.
351
- *
352
- * @returns `{ nodePath, indexPath }` or `undefined` if not found
353
- */
354
- resolveCursorBinary() {
355
- const localAppData = process.env.LOCALAPPDATA;
356
- if (!localAppData)
357
- return undefined;
358
- const versionsDir = join(localAppData, 'cursor-agent', 'versions');
359
- if (!existsSync(versionsDir))
360
- return undefined;
361
- // Find the latest version directory (format: YYYY.MM.DD-commit)
362
- const versionPattern = /^\d{4}\.\d{1,2}\.\d{1,2}-[a-f0-9]+$/;
363
- const versions = readdirSync(versionsDir)
364
- .filter((d) => versionPattern.test(d))
365
- .sort()
366
- .reverse();
367
- if (versions.length === 0)
368
- return undefined;
369
- const versionDir = join(versionsDir, versions[0]);
370
- const nodePath = join(versionDir, 'node.exe');
371
- const indexPath = join(versionDir, 'index.js');
372
- if (!existsSync(nodePath) || !existsSync(indexPath))
373
- return undefined;
374
- return { nodePath, indexPath };
375
- }
376
- /**
377
- * Spawn the agent process, handling Windows specially.
313
+ * Spawn the agent process, handling Windows specially via PowerShell.
378
314
  *
379
- * On Windows, the cursor CLI ships as `agent.cmd` which spawns PowerShell
380
- * which runs `cursor-agent.ps1` which runs `node.exe index.js`. This triple
381
- * nesting (PowerShell cmd.exe PowerShell node.exe) hangs on Windows
382
- * CI runners. Solution: resolve the cursor CLI's bundled `node.exe` and
383
- * `index.js` directly, bypassing all shell wrappers.
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.
384
320
  *
385
321
  * On Linux/macOS, spawn `agent` directly — no shell needed.
386
322
  */
387
- /**
388
- * Build the subprocess environment: strip CLAUDECODE, inject CURSOR_API_KEY
389
- * from authConfig when token auth is configured.
390
- */
391
- buildEnv(extra) {
392
- const { CLAUDECODE: _, ...cleanEnv } = process.env;
393
- // Inject CURSOR_API_KEY from stored settings so the cursor CLI authenticates
394
- // even when the env var isn't inherited (e.g. direct node.exe invocation on Windows).
395
- if (this.authConfig?.authMethod === 'token' && this.authConfig.token) {
396
- cleanEnv.CURSOR_API_KEY = this.authConfig.token;
397
- this.log(`[diag] buildEnv: injected CURSOR_API_KEY from authConfig (${this.authConfig.token.length} chars)`);
398
- }
399
- else {
400
- this.log(`[diag] buildEnv: NO token injection (authMethod=${this.authConfig?.authMethod ?? 'none'}, hasToken=${!!this.authConfig?.token}, envKey=${!!cleanEnv.CURSOR_API_KEY})`);
401
- }
402
- const env = extra ? { ...cleanEnv, ...extra } : cleanEnv;
403
- this.log(`[diag] buildEnv: final CURSOR_API_KEY in env=${!!env.CURSOR_API_KEY}, len=${env.CURSOR_API_KEY?.length ?? 0}`);
404
- return env;
405
- }
406
323
  spawnAgent(prompt, args, options) {
324
+ const { CLAUDECODE: _, ...cleanEnv } = process.env;
407
325
  const cwd = options?.cwd;
408
326
  if (IS_WINDOWS) {
409
- const resolved = this.resolveCursorBinary();
410
- if (resolved) {
411
- // Direct invocation: node.exe index.js <args>
412
- // No shell wrappers, no nesting, no hangs.
413
- const directArgs = [resolved.indexPath, ...args];
414
- this.log(`Windows direct mode: ${resolved.nodePath}`);
415
- this.log(`Args: ${directArgs.map((a) => (a.length > 80 ? `${a.slice(0, 77)}...` : a)).join(' ')}`);
416
- const proc = this.spawn(resolved.nodePath, directArgs, {
417
- cwd,
418
- stdio: ['pipe', 'pipe', 'pipe'],
419
- windowsHide: true,
420
- env: this.buildEnv({ CURSOR_INVOKED_AS: 'agent' }),
421
- });
422
- this.log(`Direct PID: ${proc.pid ?? 'undefined (spawn may have failed)'}`);
423
- if (proc.stdin)
424
- proc.stdin.end();
425
- return { proc, tmpFile: undefined };
426
- }
427
- // Fallback: if direct resolution fails, use PowerShell + temp file
428
- this.log('Windows fallback: cursor binary not resolved, using PowerShell');
327
+ // Write prompt to temp file to bypass cmd.exe argument mangling
429
328
  const tmpFile = join(tmpdir(), `shep-cursor-${Date.now()}-${Math.random().toString(36).slice(2, 6)}.txt`);
430
329
  writeFileSync(tmpFile, prompt, 'utf8');
330
+ // Build the agent args WITHOUT -p and the prompt (they go via temp file)
431
331
  const agentFlags = args.filter((a) => a !== '-p' && a !== prompt).join(' ');
432
332
  const safePath = tmpFile.replace(/'/g, "''");
433
333
  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>`)}`);
434
336
  const proc = this.spawn('powershell.exe', ['-NoProfile', '-NonInteractive', '-Command', psCmd], {
435
337
  cwd,
436
338
  stdio: ['pipe', 'pipe', 'pipe'],
437
339
  windowsHide: true,
438
- env: this.buildEnv(),
340
+ env: cleanEnv,
439
341
  });
342
+ this.log(`PowerShell PID: ${proc.pid ?? 'undefined (spawn may have failed)'}`);
440
343
  if (proc.stdin)
441
344
  proc.stdin.end();
442
345
  return { proc, tmpFile };
@@ -444,7 +347,7 @@ export class CursorExecutorService {
444
347
  // Linux/macOS: spawn agent directly, no shell needed
445
348
  const spawnOpts = {
446
349
  stdio: ['pipe', 'pipe', 'pipe'],
447
- env: this.buildEnv(),
350
+ env: cleanEnv,
448
351
  };
449
352
  if (cwd)
450
353
  spawnOpts.cwd = cwd;
@@ -1 +1 @@
1
- {"version":3,"file":"app-shell.d.ts","sourceRoot":"","sources":["../../../../../../../src/presentation/web/components/layouts/app-shell/app-shell.tsx"],"names":[],"mappings":"AAEA,OAAO,EAAkC,KAAK,SAAS,EAAE,MAAM,OAAO,CAAC;AAsBvE,UAAU,aAAa;IACrB,QAAQ,EAAE,SAAS,CAAC;CACrB;AAiFD,wBAAgB,QAAQ,CAAC,EAAE,QAAQ,EAAE,EAAE,aAAa,2CAUnD"}
1
+ {"version":3,"file":"app-shell.d.ts","sourceRoot":"","sources":["../../../../../../../src/presentation/web/components/layouts/app-shell/app-shell.tsx"],"names":[],"mappings":"AAEA,OAAO,EAAkC,KAAK,SAAS,EAAE,MAAM,OAAO,CAAC;AAsBvE,UAAU,aAAa;IACrB,QAAQ,EAAE,SAAS,CAAC;CACrB;AA0FD,wBAAgB,QAAQ,CAAC,EAAE,QAAQ,EAAE,EAAE,aAAa,2CAUnD"}
@@ -1,7 +1,7 @@
1
1
  'use client';
2
2
  import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
3
3
  import { useCallback, useMemo, useState } from 'react';
4
- import { useRouter } from 'next/navigation';
4
+ import { useRouter, usePathname } from 'next/navigation';
5
5
  import { Plus, FolderPlus } from 'lucide-react';
6
6
  import { SidebarProvider, SidebarInset } from '../../ui/sidebar.js';
7
7
  import { AppSidebar } from '../../layouts/app-sidebar/index.js';
@@ -14,9 +14,14 @@ import { DrawerCloseGuardProvider, useDrawerCloseGuard } from '../../../hooks/dr
14
14
  import { SidebarFeaturesProvider, useSidebarFeaturesContext, } from '../../../hooks/sidebar-features-context.js';
15
15
  import { useNotifications } from '../../../hooks/use-notifications.js';
16
16
  import { useFeatureFlags } from '../../../hooks/feature-flags-context.js';
17
- /** Inner shell that consumes the agent-events context for notifications. */
17
+ /** Control center route prefixes where the FAB should be visible. */
18
+ const CONTROL_CENTER_PREFIXES = ['/', '/create', '/feature', '/repository'];
19
+ function isControlCenterRoute(pathname) {
20
+ return CONTROL_CENTER_PREFIXES.some((prefix) => pathname === prefix || (prefix !== '/' && pathname.startsWith(`${prefix}/`)));
21
+ }
18
22
  function AppShellInner({ children }) {
19
23
  const router = useRouter();
24
+ const pathname = usePathname();
20
25
  const { guardedNavigate } = useDrawerCloseGuard();
21
26
  const featureFlags = useFeatureFlags();
22
27
  // Subscribe to agent lifecycle events and dispatch toast/browser notifications
@@ -58,7 +63,7 @@ function AppShellInner({ children }) {
58
63
  loading: addingRepo,
59
64
  },
60
65
  ], [handleNewFeature, handleAddRepository, addingRepo]);
61
- return (_jsxs(SidebarProvider, { defaultOpen: false, children: [_jsx(AppSidebar, { features: features, featureFlags: featureFlags, onFeatureClick: handleFeatureClick }), _jsx(SidebarInset, { children: _jsxs("div", { className: "relative h-full", children: [_jsxs("div", { className: "absolute top-3 right-3 z-50 flex gap-1", "data-test-id": "canvas-actions-toolbar", children: [_jsx(SoundToggle, {}), _jsx(ThemeToggle, {})] }), _jsx("main", { className: "h-full", children: children }), _jsx(FloatingActionButton, { actions: fabActions })] }) })] }));
66
+ return (_jsxs(SidebarProvider, { defaultOpen: false, children: [_jsx(AppSidebar, { features: features, featureFlags: featureFlags, onFeatureClick: handleFeatureClick }), _jsx(SidebarInset, { children: _jsxs("div", { className: "relative h-full", children: [_jsxs("div", { className: "absolute top-3 right-3 z-50 flex gap-1", "data-test-id": "canvas-actions-toolbar", children: [_jsx(SoundToggle, {}), _jsx(ThemeToggle, {})] }), _jsx("main", { className: "h-full", children: children }), isControlCenterRoute(pathname) && _jsx(FloatingActionButton, { actions: fabActions })] }) })] }));
62
67
  }
63
68
  export function AppShell({ children }) {
64
69
  return (_jsx(AgentEventsProvider, { children: _jsx(DrawerCloseGuardProvider, { children: _jsx(SidebarFeaturesProvider, { children: _jsx(AppShellInner, { children: children }) }) }) }));