@shepai/cli 1.122.2-pr360.dfb75fe → 1.122.2-pr381.078d7df

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 (147) 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 +211 -29
  5. package/dist/packages/core/src/infrastructure/services/agents/feature-agent/feature-agent-worker.d.ts.map +1 -1
  6. package/dist/packages/core/src/infrastructure/services/agents/feature-agent/feature-agent-worker.js +9 -0
  7. package/dist/packages/core/src/infrastructure/services/agents/feature-agent/nodes/merge/merge.node.d.ts +5 -0
  8. package/dist/packages/core/src/infrastructure/services/agents/feature-agent/nodes/merge/merge.node.d.ts.map +1 -1
  9. package/dist/packages/core/src/infrastructure/services/agents/feature-agent/nodes/merge/merge.node.js +82 -54
  10. package/dist/packages/core/src/infrastructure/services/tool-installer/tool-installer.service.d.ts.map +1 -1
  11. package/dist/packages/core/src/infrastructure/services/tool-installer/tool-installer.service.js +3 -10
  12. package/dist/packages/core/src/infrastructure/services/tool-installer/tools/claude-code.json +4 -9
  13. package/dist/src/presentation/cli/commands/install.command.js +1 -8
  14. package/dist/src/presentation/web/app/actions/check-agent-auth.d.ts +0 -2
  15. package/dist/src/presentation/web/app/actions/check-agent-auth.d.ts.map +1 -1
  16. package/dist/src/presentation/web/app/actions/check-agent-auth.js +1 -8
  17. package/dist/src/presentation/web/components/features/control-center/control-center-empty-state.js +1 -1
  18. package/dist/src/presentation/web/components/features/tools/tool-card.stories.js +1 -1
  19. package/dist/src/presentation/web/components/features/tools/tools-page-client.stories.js +1 -1
  20. package/dist/tsconfig.build.tsbuildinfo +1 -1
  21. package/package.json +1 -1
  22. package/web/.next/BUILD_ID +1 -1
  23. package/web/.next/build-manifest.json +2 -2
  24. package/web/.next/fallback-build-manifest.json +2 -2
  25. package/web/.next/prerender-manifest.json +3 -3
  26. package/web/.next/required-server-files.js +1 -1
  27. package/web/.next/required-server-files.json +1 -1
  28. package/web/.next/server/app/(dashboard)/@drawer/create/page/server-reference-manifest.json +22 -22
  29. package/web/.next/server/app/(dashboard)/@drawer/create/page.js.nft.json +1 -1
  30. package/web/.next/server/app/(dashboard)/@drawer/create/page_client-reference-manifest.js +1 -1
  31. package/web/.next/server/app/(dashboard)/@drawer/feature/[featureId]/[tab]/page/server-reference-manifest.json +28 -28
  32. package/web/.next/server/app/(dashboard)/@drawer/feature/[featureId]/[tab]/page.js.nft.json +1 -1
  33. package/web/.next/server/app/(dashboard)/@drawer/feature/[featureId]/[tab]/page_client-reference-manifest.js +1 -1
  34. package/web/.next/server/app/(dashboard)/@drawer/feature/[featureId]/page/server-reference-manifest.json +28 -28
  35. package/web/.next/server/app/(dashboard)/@drawer/feature/[featureId]/page.js.nft.json +1 -1
  36. package/web/.next/server/app/(dashboard)/@drawer/feature/[featureId]/page_client-reference-manifest.js +1 -1
  37. package/web/.next/server/app/(dashboard)/@drawer/repository/[repositoryId]/page/server-reference-manifest.json +20 -20
  38. package/web/.next/server/app/(dashboard)/@drawer/repository/[repositoryId]/page.js.nft.json +1 -1
  39. package/web/.next/server/app/(dashboard)/@drawer/repository/[repositoryId]/page_client-reference-manifest.js +1 -1
  40. package/web/.next/server/app/(dashboard)/create/page/server-reference-manifest.json +22 -22
  41. package/web/.next/server/app/(dashboard)/create/page.js.nft.json +1 -1
  42. package/web/.next/server/app/(dashboard)/create/page_client-reference-manifest.js +1 -1
  43. package/web/.next/server/app/(dashboard)/feature/[featureId]/[tab]/page/server-reference-manifest.json +28 -28
  44. package/web/.next/server/app/(dashboard)/feature/[featureId]/[tab]/page.js.nft.json +1 -1
  45. package/web/.next/server/app/(dashboard)/feature/[featureId]/[tab]/page_client-reference-manifest.js +1 -1
  46. package/web/.next/server/app/(dashboard)/feature/[featureId]/page/server-reference-manifest.json +28 -28
  47. package/web/.next/server/app/(dashboard)/feature/[featureId]/page.js.nft.json +1 -1
  48. package/web/.next/server/app/(dashboard)/feature/[featureId]/page_client-reference-manifest.js +1 -1
  49. package/web/.next/server/app/(dashboard)/page/server-reference-manifest.json +20 -20
  50. package/web/.next/server/app/(dashboard)/page.js.nft.json +1 -1
  51. package/web/.next/server/app/(dashboard)/page_client-reference-manifest.js +1 -1
  52. package/web/.next/server/app/(dashboard)/repository/[repositoryId]/page/server-reference-manifest.json +20 -20
  53. package/web/.next/server/app/(dashboard)/repository/[repositoryId]/page.js.nft.json +1 -1
  54. package/web/.next/server/app/(dashboard)/repository/[repositoryId]/page_client-reference-manifest.js +1 -1
  55. package/web/.next/server/app/_global-error.html +2 -2
  56. package/web/.next/server/app/_global-error.rsc +1 -1
  57. package/web/.next/server/app/_global-error.segments/__PAGE__.segment.rsc +1 -1
  58. package/web/.next/server/app/_global-error.segments/_full.segment.rsc +1 -1
  59. package/web/.next/server/app/_global-error.segments/_head.segment.rsc +1 -1
  60. package/web/.next/server/app/_global-error.segments/_index.segment.rsc +1 -1
  61. package/web/.next/server/app/_global-error.segments/_tree.segment.rsc +1 -1
  62. package/web/.next/server/app/_not-found/page/server-reference-manifest.json +1 -1
  63. package/web/.next/server/app/_not-found/page_client-reference-manifest.js +1 -1
  64. package/web/.next/server/app/settings/page/server-reference-manifest.json +6 -6
  65. package/web/.next/server/app/settings/page.js.nft.json +1 -1
  66. package/web/.next/server/app/settings/page_client-reference-manifest.js +1 -1
  67. package/web/.next/server/app/skills/page/server-reference-manifest.json +6 -6
  68. package/web/.next/server/app/skills/page_client-reference-manifest.js +1 -1
  69. package/web/.next/server/app/tools/page/server-reference-manifest.json +6 -6
  70. package/web/.next/server/app/tools/page_client-reference-manifest.js +1 -1
  71. package/web/.next/server/app/version/page/server-reference-manifest.json +1 -1
  72. package/web/.next/server/app/version/page_client-reference-manifest.js +1 -1
  73. package/web/.next/server/chunks/[root-of-the-server]__a402b567._.js +1 -1
  74. package/web/.next/server/chunks/ssr/744ca_web_components_common_control-center-drawer_create-drawer-client_tsx_5e26fc0a._.js +1 -1
  75. package/web/.next/server/chunks/ssr/744ca_web_components_common_control-center-drawer_create-drawer-client_tsx_5e26fc0a._.js.map +1 -1
  76. package/web/.next/server/chunks/ssr/8ba4b_server_app_(dashboard)_@drawer_repository_[repositoryId]_page_actions_f30d0343.js +1 -1
  77. package/web/.next/server/chunks/ssr/8ba4b_server_app_(dashboard)_@drawer_repository_[repositoryId]_page_actions_f30d0343.js.map +1 -1
  78. package/web/.next/server/chunks/ssr/8ba4b_server_app_(dashboard)_repository_[repositoryId]_page_actions_9f1775bb.js +1 -1
  79. package/web/.next/server/chunks/ssr/8ba4b_server_app_(dashboard)_repository_[repositoryId]_page_actions_9f1775bb.js.map +1 -1
  80. package/web/.next/server/chunks/ssr/[root-of-the-server]__06fef644._.js +1 -1
  81. package/web/.next/server/chunks/ssr/[root-of-the-server]__2698e9f4._.js +1 -1
  82. package/web/.next/server/chunks/ssr/[root-of-the-server]__2698e9f4._.js.map +1 -1
  83. package/web/.next/server/chunks/ssr/[root-of-the-server]__545792ab._.js +1 -1
  84. package/web/.next/server/chunks/ssr/[root-of-the-server]__545792ab._.js.map +1 -1
  85. package/web/.next/server/chunks/ssr/[root-of-the-server]__6b17a22d._.js +1 -1
  86. package/web/.next/server/chunks/ssr/[root-of-the-server]__6b17a22d._.js.map +1 -1
  87. package/web/.next/server/chunks/ssr/[root-of-the-server]__6bb00d90._.js +2 -2
  88. package/web/.next/server/chunks/ssr/[root-of-the-server]__6bb00d90._.js.map +1 -1
  89. package/web/.next/server/chunks/ssr/[root-of-the-server]__804c006d._.js +1 -1
  90. package/web/.next/server/chunks/ssr/[root-of-the-server]__804c006d._.js.map +1 -1
  91. package/web/.next/server/chunks/ssr/[root-of-the-server]__8c553503._.js +2 -2
  92. package/web/.next/server/chunks/ssr/[root-of-the-server]__8e3bf5d7._.js +1 -1
  93. package/web/.next/server/chunks/ssr/[root-of-the-server]__8e3bf5d7._.js.map +1 -1
  94. package/web/.next/server/chunks/ssr/[root-of-the-server]__a022445f._.js +2 -2
  95. package/web/.next/server/chunks/ssr/[root-of-the-server]__a022445f._.js.map +1 -1
  96. package/web/.next/server/chunks/ssr/[root-of-the-server]__a7de2711._.js +2 -2
  97. package/web/.next/server/chunks/ssr/[root-of-the-server]__c07f9f79._.js +1 -1
  98. package/web/.next/server/chunks/ssr/[root-of-the-server]__c07f9f79._.js.map +1 -1
  99. package/web/.next/server/chunks/ssr/[root-of-the-server]__c605a375._.js +1 -1
  100. package/web/.next/server/chunks/ssr/[root-of-the-server]__c605a375._.js.map +1 -1
  101. package/web/.next/server/chunks/ssr/_0dc2cfd3._.js +1 -1
  102. package/web/.next/server/chunks/ssr/_0dc2cfd3._.js.map +1 -1
  103. package/web/.next/server/chunks/ssr/_135edb9c._.js +1 -1
  104. package/web/.next/server/chunks/ssr/_135edb9c._.js.map +1 -1
  105. package/web/.next/server/chunks/ssr/{_1c4cecde._.js → _17418e9d._.js} +2 -2
  106. package/web/.next/server/chunks/ssr/{_1c4cecde._.js.map → _17418e9d._.js.map} +1 -1
  107. package/web/.next/server/chunks/ssr/_2f6f48b8._.js +1 -1
  108. package/web/.next/server/chunks/ssr/_2f6f48b8._.js.map +1 -1
  109. package/web/.next/server/chunks/ssr/{_004b791b._.js → _4f330b28._.js} +2 -2
  110. package/web/.next/server/chunks/ssr/{_004b791b._.js.map → _4f330b28._.js.map} +1 -1
  111. package/web/.next/server/chunks/ssr/_cc77a143._.js +1 -1
  112. package/web/.next/server/chunks/ssr/_cc77a143._.js.map +1 -1
  113. package/web/.next/server/chunks/ssr/{_0ee2702f._.js → _e87cf55c._.js} +2 -2
  114. package/web/.next/server/chunks/ssr/{_0ee2702f._.js.map → _e87cf55c._.js.map} +1 -1
  115. package/web/.next/server/chunks/ssr/b1a17_presentation_web_components_features_settings_settings-page-client_tsx_6ed9d5f8._.js +1 -1
  116. package/web/.next/server/chunks/ssr/b1a17_presentation_web_components_features_settings_settings-page-client_tsx_6ed9d5f8._.js.map +1 -1
  117. package/web/.next/server/chunks/ssr/src_presentation_web_5f039db1._.js +2 -2
  118. package/web/.next/server/chunks/ssr/src_presentation_web_5f039db1._.js.map +1 -1
  119. package/web/.next/server/chunks/ssr/src_presentation_web__next-internal_server_app_(dashboard)_page_actions_2a52b697.js +1 -1
  120. package/web/.next/server/chunks/ssr/src_presentation_web__next-internal_server_app_(dashboard)_page_actions_2a52b697.js.map +1 -1
  121. package/web/.next/server/chunks/ssr/src_presentation_web__next-internal_server_app_skills_page_actions_1fa8042e.js +1 -1
  122. package/web/.next/server/chunks/ssr/src_presentation_web__next-internal_server_app_skills_page_actions_1fa8042e.js.map +1 -1
  123. package/web/.next/server/chunks/ssr/src_presentation_web__next-internal_server_app_tools_page_actions_24684200.js +1 -1
  124. package/web/.next/server/chunks/ssr/src_presentation_web__next-internal_server_app_tools_page_actions_24684200.js.map +1 -1
  125. package/web/.next/server/chunks/ssr/src_presentation_web_c4337169._.js +2 -2
  126. package/web/.next/server/chunks/ssr/src_presentation_web_c4337169._.js.map +1 -1
  127. package/web/.next/server/chunks/ssr/src_presentation_web_ca99d62d._.js +1 -1
  128. package/web/.next/server/chunks/ssr/src_presentation_web_components_bf50c527._.js +1 -1
  129. package/web/.next/server/chunks/ssr/src_presentation_web_components_de814675._.js +1 -1
  130. package/web/.next/server/chunks/ssr/src_presentation_web_components_features_control-center_7ac3562e._.js +1 -1
  131. package/web/.next/server/chunks/ssr/src_presentation_web_components_features_control-center_7ac3562e._.js.map +1 -1
  132. package/web/.next/server/pages/500.html +2 -2
  133. package/web/.next/server/server-reference-manifest.js +1 -1
  134. package/web/.next/server/server-reference-manifest.json +34 -34
  135. package/web/.next/static/chunks/{0dd2d4fcafd8772b.js → 3f8b6dfefdcdb086.js} +1 -1
  136. package/web/.next/static/chunks/{1e6bfbd7936bba25.js → 66f3b3e9ffbdd2e0.js} +1 -1
  137. package/web/.next/static/chunks/{eb165ab35b356164.js → 6e519f34ef50afc7.js} +1 -1
  138. package/web/.next/static/chunks/{1b5419c02d253fae.js → 7189532beb0a69ea.js} +1 -1
  139. package/web/.next/static/chunks/{8e816c7f48f7653d.js → 8ace7cc9cdcc4faa.js} +2 -2
  140. package/web/.next/static/chunks/{6c4aa963056c0bc2.js → d193bfaaff210e81.js} +1 -1
  141. package/web/.next/static/chunks/{d05a044cbbedbd56.js → d6b6d7807302979b.js} +1 -1
  142. package/web/.next/static/chunks/{37634985311cc4c6.js → e359a6c4b3a3b222.js} +2 -2
  143. package/web/.next/static/chunks/{349c47b3b993ae54.js → eef9532b80f3408a.js} +1 -1
  144. package/web/.next/static/chunks/{9eb4f613f1e35899.js → f2e7c03fc48a915d.js} +1 -1
  145. /package/web/.next/static/{CMhbAJyvRj6ct2bZgc0Yp → 6DN4JYeWRmWsCZEUT6dAY}/_buildManifest.js +0 -0
  146. /package/web/.next/static/{CMhbAJyvRj6ct2bZgc0Yp → 6DN4JYeWRmWsCZEUT6dAY}/_clientMiddlewareManifest.json +0 -0
  147. /package/web/.next/static/{CMhbAJyvRj6ct2bZgc0Yp → 6DN4JYeWRmWsCZEUT6dAY}/_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;IAqOtF,aAAa,CAClB,MAAM,EAAE,MAAM,EACd,OAAO,CAAC,EAAE,qBAAqB,GAC9B,aAAa,CAAC,yBAAyB,CAAC;IAiH3C;;OAEG;IACH,OAAO,CAAC,cAAc;IAyCtB,OAAO,CAAC,SAAS;IASjB,OAAO,CAAC,eAAe;IAOvB;;;;;;;;;;;;OAYG;IACH,OAAO,CAAC,mBAAmB;IAwC3B;;;;;;;;;;OAUG;IACH;;;OAGG;IACH,OAAO,CAAC,QAAQ;IAuBhB,OAAO,CAAC,UAAU;IA+ElB,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) {
@@ -58,19 +60,56 @@ export class CursorExecutorService {
58
60
  // stream-json is unreliable on Windows where shell: true can mangle args.
59
61
  const args = this.buildArgs(prompt, options);
60
62
  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)'}`);
61
69
  return new Promise((resolve, reject) => {
62
70
  let lineBuffer = '';
63
71
  let stderr = '';
64
72
  let timedOut = false;
65
73
  let timeoutId;
74
+ let stdoutChunks = 0;
75
+ let stderrChunks = 0;
76
+ const startTime = Date.now();
66
77
  // Accumulated from JSON events or raw text fallback
67
78
  let resultText = '';
68
79
  let rawText = '';
69
80
  let sessionId;
70
81
  let metadata;
82
+ // Periodic heartbeat + zero-output watchdog.
83
+ // Cursor CLI on Windows sometimes starts but never produces any output.
84
+ // If no stdout/stderr arrives within SILENCE_TIMEOUT_MS, kill the process
85
+ // so retryExecute can retry instead of waiting 30 minutes.
86
+ const SILENCE_TIMEOUT_MS = 180_000; // 3 minutes of zero output = stuck
87
+ let lastOutputAt = Date.now();
88
+ const heartbeatId = setInterval(() => {
89
+ const elapsed = Math.round((Date.now() - startTime) / 1000);
90
+ const silenceMs = Date.now() - lastOutputAt;
91
+ this.log(`[diag] heartbeat ${elapsed}s: stdout_chunks=${stdoutChunks}, stderr_chunks=${stderrChunks}, silence=${Math.round(silenceMs / 1000)}s, pid_killed=${proc.killed}`);
92
+ // Kill if zero output for too long
93
+ if (silenceMs > SILENCE_TIMEOUT_MS && !proc.killed) {
94
+ this.log(`[diag] SILENCE WATCHDOG: no output for ${Math.round(silenceMs / 1000)}s — killing process`);
95
+ timedOut = true;
96
+ if (process.platform === 'win32' && proc.pid) {
97
+ try {
98
+ execFileSync('taskkill', ['/F', '/T', '/PID', String(proc.pid)], { stdio: 'ignore' });
99
+ }
100
+ catch {
101
+ proc.kill();
102
+ }
103
+ }
104
+ else {
105
+ proc.kill();
106
+ }
107
+ }
108
+ }, 15_000);
71
109
  if (options?.timeout) {
72
110
  timeoutId = setTimeout(() => {
73
111
  timedOut = true;
112
+ this.log(`[diag] TIMEOUT after ${options.timeout}ms — killing process tree`);
74
113
  // On Windows, proc.kill() may not kill the entire process tree
75
114
  // (PowerShell + child agent process). Use taskkill /T for tree kill.
76
115
  if (process.platform === 'win32' && proc.pid) {
@@ -78,9 +117,11 @@ export class CursorExecutorService {
78
117
  execFileSync('taskkill', ['/F', '/T', '/PID', String(proc.pid)], {
79
118
  stdio: 'ignore',
80
119
  });
120
+ this.log(`[diag] taskkill /T /PID ${proc.pid} succeeded`);
81
121
  }
82
122
  catch {
83
123
  proc.kill();
124
+ this.log(`[diag] taskkill failed, fell back to proc.kill()`);
84
125
  }
85
126
  }
86
127
  else {
@@ -107,17 +148,36 @@ export class CursorExecutorService {
107
148
  if (parsed.duration_ms !== undefined) {
108
149
  metadata = { ...metadata, duration_ms: parsed.duration_ms };
109
150
  }
151
+ if (parsed.is_error) {
152
+ this.log(`[diag] result event has is_error=true: ${JSON.stringify(parsed).slice(0, 300)}`);
153
+ }
154
+ }
155
+ else if (parsed.type === 'error') {
156
+ this.log(`[diag] cursor error event: ${JSON.stringify(parsed).slice(0, 500)}`);
157
+ }
158
+ else if (parsed.type !== 'user' &&
159
+ parsed.type !== 'system' &&
160
+ parsed.type !== 'thinking' &&
161
+ parsed.type !== 'tool_call') {
162
+ this.log(`[diag] unknown event type="${parsed.type}": ${JSON.stringify(parsed).slice(0, 300)}`);
110
163
  }
111
- // user, system, thinking events: logged but don't affect result
112
164
  }
113
165
  catch {
114
166
  // Non-JSON output — accumulate as raw text fallback
115
- if (line.length > 0)
167
+ if (line.length > 0) {
116
168
  rawText += `${line}\n`;
169
+ this.log(`[diag] non-JSON line (${line.length} chars): ${line.slice(0, 200)}`);
170
+ }
117
171
  }
118
172
  };
119
173
  proc.stdout?.on('data', (chunk) => {
120
- lineBuffer += chunk.toString();
174
+ stdoutChunks++;
175
+ lastOutputAt = Date.now();
176
+ const data = chunk.toString();
177
+ if (stdoutChunks <= 3) {
178
+ this.log(`[diag] stdout chunk #${stdoutChunks}: ${data.length} bytes, first 200: ${data.slice(0, 200).replace(/\n/g, '\\n')}`);
179
+ }
180
+ lineBuffer += data;
121
181
  const lines = lineBuffer.split('\n');
122
182
  lineBuffer = lines.pop() ?? '';
123
183
  for (const line of lines) {
@@ -127,19 +187,23 @@ export class CursorExecutorService {
127
187
  }
128
188
  });
129
189
  proc.stderr?.on('data', (chunk) => {
190
+ stderrChunks++;
191
+ lastOutputAt = Date.now();
130
192
  const data = chunk.toString();
131
193
  stderr += data;
132
- this.log(`stderr: ${data.trimEnd()}`);
194
+ this.log(`[diag] stderr chunk #${stderrChunks}: ${data.trimEnd()}`);
133
195
  // Detect fatal errors early so callers don't waste time retrying
134
196
  if (data.includes('Cannot use this model')) {
135
197
  if (timeoutId)
136
198
  clearTimeout(timeoutId);
199
+ clearInterval(heartbeatId);
137
200
  proc.kill();
138
201
  reject(new Error(data.trim()));
139
202
  }
140
203
  });
141
204
  proc.on('error', (error) => {
142
- this.log(`Process error event: ${error.message}`);
205
+ this.log(`[diag] Process ERROR event: ${error.message} (code=${error.code})`);
206
+ clearInterval(heartbeatId);
143
207
  if (timeoutId)
144
208
  clearTimeout(timeoutId);
145
209
  if (error.code === 'ENOENT') {
@@ -150,6 +214,8 @@ export class CursorExecutorService {
150
214
  }
151
215
  });
152
216
  proc.on('close', (code) => {
217
+ const elapsed = Math.round((Date.now() - startTime) / 1000);
218
+ clearInterval(heartbeatId);
153
219
  // Clean up temp file on Windows
154
220
  if (tmpFile) {
155
221
  try {
@@ -163,7 +229,7 @@ export class CursorExecutorService {
163
229
  processLine(lineBuffer.trim());
164
230
  // Use raw text as fallback when no JSON result was captured
165
231
  const finalText = resultText || rawText.trim();
166
- this.log(`Process closed with code ${code}, result=${finalText.length} chars`);
232
+ this.log(`[diag] Process CLOSE: code=${code}, elapsed=${elapsed}s, stdout_chunks=${stdoutChunks}, stderr_chunks=${stderrChunks}, result=${finalText.length} chars, raw=${rawText.length} chars`);
167
233
  if (timeoutId)
168
234
  clearTimeout(timeoutId);
169
235
  if (timedOut) {
@@ -171,9 +237,17 @@ export class CursorExecutorService {
171
237
  return;
172
238
  }
173
239
  if (code !== 0 && code !== null) {
174
- reject(new Error(stderr.trim() || `Process exited with code ${code}`));
240
+ const errMsg = stderr.trim() || `Process exited with code ${code}`;
241
+ this.log(`[diag] non-zero exit — rejecting with: ${errMsg.slice(0, 200)}`);
242
+ reject(new Error(errMsg));
175
243
  return;
176
244
  }
245
+ if (stdoutChunks === 0 && stderrChunks === 0) {
246
+ this.log(`[diag] WARNING: process exited with code 0 but produced ZERO output (stdout=0, stderr=0, elapsed=${elapsed}s)`);
247
+ }
248
+ if (!finalText && code === 0) {
249
+ this.log(`[diag] WARNING: process exited code=0 but result is empty (resultText=${resultText.length}, rawText=${rawText.length})`);
250
+ }
177
251
  const result = { result: finalText };
178
252
  if (sessionId)
179
253
  result.sessionId = sessionId;
@@ -184,20 +258,25 @@ export class CursorExecutorService {
184
258
  });
185
259
  }
186
260
  async *executeStream(prompt, options) {
261
+ this.silent = options?.silent ?? false;
187
262
  const args = this.buildStreamArgs(prompt, options);
188
263
  const { proc, tmpFile } = this.spawnAgent(prompt, args, options);
264
+ this.log(`[stream] pid=${proc.pid}, stdout=${!!proc.stdout}, stderr=${!!proc.stderr}`);
189
265
  let lineBuffer = '';
190
266
  let stderr = '';
267
+ let stdoutChunks = 0;
268
+ let stderrChunks = 0;
269
+ const startTime = Date.now();
191
270
  const queue = [];
192
271
  let resolve = null;
193
272
  let error = null;
194
- function enqueue(event) {
273
+ const enqueue = (event) => {
195
274
  queue.push(event);
196
275
  if (resolve) {
197
276
  resolve();
198
277
  resolve = null;
199
278
  }
200
- }
279
+ };
201
280
  function waitForItem() {
202
281
  if (queue.length > 0)
203
282
  return Promise.resolve();
@@ -205,8 +284,18 @@ export class CursorExecutorService {
205
284
  resolve = r;
206
285
  });
207
286
  }
287
+ // Heartbeat for stream mode too
288
+ const heartbeatId = setInterval(() => {
289
+ const elapsed = Math.round((Date.now() - startTime) / 1000);
290
+ this.log(`[stream] heartbeat ${elapsed}s: stdout_chunks=${stdoutChunks}, stderr_chunks=${stderrChunks}, pid_killed=${proc.killed}`);
291
+ }, 30_000);
208
292
  proc.stdout?.on('data', (chunk) => {
209
- lineBuffer += chunk.toString();
293
+ stdoutChunks++;
294
+ const data = chunk.toString();
295
+ if (stdoutChunks <= 3) {
296
+ this.log(`[stream] stdout chunk #${stdoutChunks}: ${data.length} bytes`);
297
+ }
298
+ lineBuffer += data;
210
299
  const lines = lineBuffer.split('\n');
211
300
  lineBuffer = lines.pop() ?? '';
212
301
  for (const line of lines) {
@@ -219,13 +308,21 @@ export class CursorExecutorService {
219
308
  }
220
309
  });
221
310
  proc.stderr?.on('data', (chunk) => {
222
- stderr += chunk.toString();
311
+ stderrChunks++;
312
+ const data = chunk.toString();
313
+ stderr += data;
314
+ this.log(`[stream] stderr chunk #${stderrChunks}: ${data.trimEnd()}`);
223
315
  });
224
316
  proc.on('error', (err) => {
317
+ this.log(`[stream] Process ERROR: ${err.message}`);
318
+ clearInterval(heartbeatId);
225
319
  error = err;
226
320
  enqueue(null);
227
321
  });
228
322
  proc.on('close', (code) => {
323
+ const elapsed = Math.round((Date.now() - startTime) / 1000);
324
+ clearInterval(heartbeatId);
325
+ this.log(`[stream] Process CLOSE: code=${code}, elapsed=${elapsed}s, stdout_chunks=${stdoutChunks}, stderr_chunks=${stderrChunks}`);
229
326
  if (tmpFile) {
230
327
  try {
231
328
  unlinkSync(tmpFile);
@@ -239,8 +336,10 @@ export class CursorExecutorService {
239
336
  if (event)
240
337
  enqueue(event);
241
338
  }
242
- if (code !== 0 && code !== null && stderr.trim()) {
243
- enqueue({ type: 'error', content: stderr.trim(), timestamp: new Date() });
339
+ if (code !== 0 && code !== null) {
340
+ const errMsg = stderr.trim() || `Process exited with code ${code}`;
341
+ this.log(`[stream] non-zero exit: ${errMsg}`);
342
+ enqueue({ type: 'error', content: errMsg, timestamp: new Date() });
244
343
  }
245
344
  enqueue(null);
246
345
  });
@@ -286,6 +385,10 @@ export class CursorExecutorService {
286
385
  }
287
386
  if (parsed.type === 'user')
288
387
  return; // Skip echoed input
388
+ // Log any unrecognized event type so nothing is silently dropped
389
+ if (!['assistant', 'tool_call', 'result', 'user', 'system', 'thinking'].includes(parsed.type)) {
390
+ this.log(`[diag] unhandled stream event type="${parsed.type}": ${line.slice(0, 200)}`);
391
+ }
289
392
  }
290
393
  catch {
291
394
  if (line.length > 0)
@@ -310,36 +413,115 @@ export class CursorExecutorService {
310
413
  return args;
311
414
  }
312
415
  /**
313
- * Spawn the agent process, handling Windows specially via PowerShell.
416
+ * Resolve the cursor CLI's bundled node.exe and index.js paths on Windows.
314
417
  *
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.
418
+ * The cursor CLI installs to `%LOCALAPPDATA%\cursor-agent\` with:
419
+ * - `agent.cmd` / `cursor-agent.ps1` (shell wrappers)
420
+ * - `versions/<YYYY.MM.DD-commit>/node.exe` + `index.js`
421
+ *
422
+ * Spawning via agent.cmd creates a problematic nesting chain:
423
+ * PowerShell → agent.cmd → PowerShell → cursor-agent.ps1 → node.exe
424
+ * This chain hangs on Windows CI runners. Direct invocation bypasses it.
425
+ *
426
+ * @returns `{ nodePath, indexPath }` or `undefined` if not found
427
+ */
428
+ resolveCursorBinary() {
429
+ const localAppData = process.env.LOCALAPPDATA;
430
+ if (!localAppData) {
431
+ this.log('[diag] resolveCursorBinary: LOCALAPPDATA not set');
432
+ return undefined;
433
+ }
434
+ const versionsDir = join(localAppData, 'cursor-agent', 'versions');
435
+ if (!existsSync(versionsDir)) {
436
+ this.log(`[diag] resolveCursorBinary: versions dir not found: ${versionsDir}`);
437
+ return undefined;
438
+ }
439
+ // Find the latest version directory (format: YYYY.MM.DD-commit)
440
+ const versionPattern = /^\d{4}\.\d{1,2}\.\d{1,2}-[a-f0-9]+$/;
441
+ const versions = readdirSync(versionsDir)
442
+ .filter((d) => versionPattern.test(d))
443
+ .sort()
444
+ .reverse();
445
+ if (versions.length === 0) {
446
+ this.log(`[diag] resolveCursorBinary: no version dirs in ${versionsDir}`);
447
+ return undefined;
448
+ }
449
+ const versionDir = join(versionsDir, versions[0]);
450
+ const nodePath = join(versionDir, 'node.exe');
451
+ const indexPath = join(versionDir, 'index.js');
452
+ if (!existsSync(nodePath) || !existsSync(indexPath)) {
453
+ this.log(`[diag] resolveCursorBinary: missing binary — node=${existsSync(nodePath)}, index=${existsSync(indexPath)}`);
454
+ return undefined;
455
+ }
456
+ this.log(`[diag] resolveCursorBinary: resolved version=${versions[0]}`);
457
+ return { nodePath, indexPath };
458
+ }
459
+ /**
460
+ * Spawn the agent process, handling Windows specially.
461
+ *
462
+ * On Windows, the cursor CLI ships as `agent.cmd` which spawns PowerShell
463
+ * which runs `cursor-agent.ps1` which runs `node.exe index.js`. This triple
464
+ * nesting (PowerShell → cmd.exe → PowerShell → node.exe) hangs on Windows
465
+ * CI runners. Solution: resolve the cursor CLI's bundled `node.exe` and
466
+ * `index.js` directly, bypassing all shell wrappers.
320
467
  *
321
468
  * On Linux/macOS, spawn `agent` directly — no shell needed.
322
469
  */
323
- spawnAgent(prompt, args, options) {
470
+ /**
471
+ * Build the subprocess environment: strip CLAUDECODE, inject CURSOR_API_KEY
472
+ * from authConfig when token auth is configured.
473
+ */
474
+ buildEnv(extra) {
324
475
  const { CLAUDECODE: _, ...cleanEnv } = process.env;
476
+ // Inject CURSOR_API_KEY from stored settings so the cursor CLI authenticates
477
+ // even when the env var isn't inherited (e.g. direct node.exe invocation on Windows).
478
+ if (this.authConfig?.authMethod === 'token' && this.authConfig.token) {
479
+ cleanEnv.CURSOR_API_KEY = this.authConfig.token;
480
+ this.log(`[diag] buildEnv: injected CURSOR_API_KEY from authConfig (${this.authConfig.token.length} chars)`);
481
+ }
482
+ else {
483
+ this.log(`[diag] buildEnv: NO token injection (authMethod=${this.authConfig?.authMethod ?? 'none'}, hasToken=${!!this.authConfig?.token}, envKey=${!!cleanEnv.CURSOR_API_KEY})`);
484
+ }
485
+ const env = extra ? { ...cleanEnv, ...extra } : cleanEnv;
486
+ this.log(`[diag] buildEnv: final CURSOR_API_KEY in env=${!!env.CURSOR_API_KEY}, len=${env.CURSOR_API_KEY?.length ?? 0}`);
487
+ return env;
488
+ }
489
+ spawnAgent(prompt, args, options) {
325
490
  const cwd = options?.cwd;
326
491
  if (IS_WINDOWS) {
327
- // Write prompt to temp file to bypass cmd.exe argument mangling
492
+ const resolved = this.resolveCursorBinary();
493
+ if (resolved) {
494
+ // Direct invocation: node.exe index.js <args>
495
+ // No shell wrappers, no nesting, no hangs.
496
+ const directArgs = [resolved.indexPath, ...args];
497
+ this.log(`Windows direct mode: ${resolved.nodePath}`);
498
+ this.log(`Args: ${directArgs.map((a) => (a.length > 80 ? `${a.slice(0, 77)}...` : a)).join(' ')}`);
499
+ const proc = this.spawn(resolved.nodePath, directArgs, {
500
+ cwd,
501
+ stdio: ['pipe', 'pipe', 'pipe'],
502
+ windowsHide: true,
503
+ env: this.buildEnv({ CURSOR_INVOKED_AS: 'agent' }),
504
+ });
505
+ this.log(`Direct PID: ${proc.pid ?? 'undefined (spawn may have failed)'}`);
506
+ if (proc.stdin)
507
+ proc.stdin.end();
508
+ return { proc, tmpFile: undefined };
509
+ }
510
+ // Fallback: if direct resolution fails, use PowerShell + temp file
511
+ this.log('[diag] Windows fallback: cursor binary not resolved, using PowerShell + temp file');
328
512
  const tmpFile = join(tmpdir(), `shep-cursor-${Date.now()}-${Math.random().toString(36).slice(2, 6)}.txt`);
329
513
  writeFileSync(tmpFile, prompt, 'utf8');
330
- // Build the agent args WITHOUT -p and the prompt (they go via temp file)
331
514
  const agentFlags = args.filter((a) => a !== '-p' && a !== prompt).join(' ');
332
515
  const safePath = tmpFile.replace(/'/g, "''");
333
516
  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>`)}`);
517
+ this.log(`[diag] PS command: ${psCmd.replace(prompt, `<${prompt.length} chars>`)}`);
336
518
  const proc = this.spawn('powershell.exe', ['-NoProfile', '-NonInteractive', '-Command', psCmd], {
337
519
  cwd,
338
520
  stdio: ['pipe', 'pipe', 'pipe'],
339
521
  windowsHide: true,
340
- env: cleanEnv,
522
+ env: this.buildEnv(),
341
523
  });
342
- this.log(`PowerShell PID: ${proc.pid ?? 'undefined (spawn may have failed)'}`);
524
+ this.log(`[diag] PowerShell PID: ${proc.pid ?? 'undefined (spawn may have failed)'}`);
343
525
  if (proc.stdin)
344
526
  proc.stdin.end();
345
527
  return { proc, tmpFile };
@@ -347,7 +529,7 @@ export class CursorExecutorService {
347
529
  // Linux/macOS: spawn agent directly, no shell needed
348
530
  const spawnOpts = {
349
531
  stdio: ['pipe', 'pipe', 'pipe'],
350
- env: cleanEnv,
532
+ env: this.buildEnv(),
351
533
  };
352
534
  if (cwd)
353
535
  spawnOpts.cwd = cwd;
@@ -1 +1 @@
1
- {"version":3,"file":"feature-agent-worker.d.ts","sourceRoot":"","sources":["../../../../../../../../packages/core/src/infrastructure/services/agents/feature-agent/feature-agent-worker.ts"],"names":[],"mappings":";AACA;;;;;;;;GAQG;AAEH,OAAO,kBAAkB,CAAC;AAe1B,OAAO,EAAiC,KAAK,SAAS,EAAE,MAAM,8BAA8B,CAAC;AAW7F,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,8BAA8B,CAAC;AAElE,MAAM,WAAW,UAAU;IACzB,SAAS,EAAE,MAAM,CAAC;IAClB,KAAK,EAAE,MAAM,CAAC;IACd,IAAI,EAAE,MAAM,CAAC;IACb,OAAO,EAAE,MAAM,CAAC;IAChB,YAAY,CAAC,EAAE,MAAM,CAAC;IACtB,aAAa,CAAC,EAAE,aAAa,CAAC;IAC9B,MAAM,CAAC,EAAE,OAAO,CAAC;IACjB,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,mBAAmB,CAAC,EAAE,OAAO,CAAC;IAC9B,IAAI,CAAC,EAAE,OAAO,CAAC;IACf,MAAM,CAAC,EAAE,OAAO,CAAC;IACjB,aAAa,CAAC,EAAE,MAAM,CAAC;IACvB,SAAS,CAAC,EAAE,SAAS,CAAC;IACtB,IAAI,CAAC,EAAE,OAAO,CAAC;IACf,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,YAAY,CAAC,EAAE,MAAM,CAAC;CACvB;AAED;;;GAGG;AACH,wBAAgB,eAAe,CAAC,IAAI,EAAE,MAAM,EAAE,GAAG,UAAU,CAwE1D;AAgCD;;;GAGG;AACH,wBAAsB,SAAS,CAAC,IAAI,EAAE,UAAU,GAAG,OAAO,CAAC,IAAI,CAAC,CA0R/D"}
1
+ {"version":3,"file":"feature-agent-worker.d.ts","sourceRoot":"","sources":["../../../../../../../../packages/core/src/infrastructure/services/agents/feature-agent/feature-agent-worker.ts"],"names":[],"mappings":";AACA;;;;;;;;GAQG;AAEH,OAAO,kBAAkB,CAAC;AAe1B,OAAO,EAAiC,KAAK,SAAS,EAAE,MAAM,8BAA8B,CAAC;AAW7F,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,8BAA8B,CAAC;AAElE,MAAM,WAAW,UAAU;IACzB,SAAS,EAAE,MAAM,CAAC;IAClB,KAAK,EAAE,MAAM,CAAC;IACd,IAAI,EAAE,MAAM,CAAC;IACb,OAAO,EAAE,MAAM,CAAC;IAChB,YAAY,CAAC,EAAE,MAAM,CAAC;IACtB,aAAa,CAAC,EAAE,aAAa,CAAC;IAC9B,MAAM,CAAC,EAAE,OAAO,CAAC;IACjB,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,mBAAmB,CAAC,EAAE,OAAO,CAAC;IAC9B,IAAI,CAAC,EAAE,OAAO,CAAC;IACf,MAAM,CAAC,EAAE,OAAO,CAAC;IACjB,aAAa,CAAC,EAAE,MAAM,CAAC;IACvB,SAAS,CAAC,EAAE,SAAS,CAAC;IACtB,IAAI,CAAC,EAAE,OAAO,CAAC;IACf,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,YAAY,CAAC,EAAE,MAAM,CAAC;CACvB;AAED;;;GAGG;AACH,wBAAgB,eAAe,CAAC,IAAI,EAAE,MAAM,EAAE,GAAG,UAAU,CAwE1D;AAgCD;;;GAGG;AACH,wBAAsB,SAAS,CAAC,IAAI,EAAE,UAAU,GAAG,OAAO,CAAC,IAAI,CAAC,CAkS/D"}
@@ -182,6 +182,15 @@ export async function runWorker(args) {
182
182
  getDefaultBranch: (cwd) => gitPrService.getDefaultBranch(cwd),
183
183
  verifyMerge: (cwd, featureBranch, baseBranch, premergeBaseSha) => gitPrService.verifyMerge(cwd, featureBranch, baseBranch, premergeBaseSha),
184
184
  revParse: (cwd, ref) => gitPrService.revParse(cwd, ref),
185
+ commitAll: async (cwd, message) => {
186
+ try {
187
+ return await gitPrService.commitAll(cwd, message);
188
+ }
189
+ catch {
190
+ // commitAll throws when there's nothing to commit — return undefined
191
+ return undefined;
192
+ }
193
+ },
185
194
  localMergeSquash: (cwd, featureBranch, baseBranch, commitMessage, hasRemote) => gitPrService.localMergeSquash(cwd, featureBranch, baseBranch, commitMessage, hasRemote),
186
195
  featureRepository,
187
196
  gitPrService,
@@ -36,6 +36,11 @@ export interface MergeNodeDeps {
36
36
  * Resolve a branch ref to its current SHA.
37
37
  */
38
38
  revParse: (cwd: string, ref: string) => Promise<string>;
39
+ /**
40
+ * Stage all changes and commit in the given directory.
41
+ * Returns the commit hash, or undefined if there was nothing to commit.
42
+ */
43
+ commitAll: (cwd: string, message: string) => Promise<string | undefined>;
39
44
  gitPrService: IGitPrService;
40
45
  cleanupFeatureWorktreeUseCase: Pick<CleanupFeatureWorktreeUseCase, 'execute'>;
41
46
  }
@@ -1 +1 @@
1
- {"version":3,"file":"merge.node.d.ts","sourceRoot":"","sources":["../../../../../../../../../../packages/core/src/infrastructure/services/agents/feature-agent/nodes/merge/merge.node.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;GAaG;AAGH,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,+DAA+D,CAAC;AACpG,OAAO,KAAK,EAAE,iBAAiB,EAAE,MAAM,gBAAgB,CAAC;AACxD,OAAO,KAAK,EAAE,kBAAkB,EAAE,MAAM,yEAAyE,CAAC;AAClH,OAAO,KAAK,EACV,WAAW,EACX,aAAa,EACd,MAAM,iEAAiE,CAAC;AAmBzE,OAAO,KAAK,EAAE,6BAA6B,EAAE,MAAM,uEAAuE,CAAC;AAE3H,MAAM,WAAW,aAAa;IAC5B,QAAQ,EAAE,cAAc,CAAC;IACzB,cAAc,EAAE,CAAC,GAAG,EAAE,MAAM,EAAE,UAAU,EAAE,MAAM,KAAK,OAAO,CAAC,WAAW,CAAC,CAAC;IAC1E,SAAS,EAAE,CAAC,GAAG,EAAE,MAAM,KAAK,OAAO,CAAC,OAAO,CAAC,CAAC;IAC7C,gBAAgB,EAAE,CAAC,GAAG,EAAE,MAAM,KAAK,OAAO,CAAC,MAAM,CAAC,CAAC;IACnD,iBAAiB,EAAE,IAAI,CAAC,kBAAkB,EAAE,UAAU,GAAG,QAAQ,CAAC,CAAC;IACnE;;OAEG;IACH,gBAAgB,EAAE,CAChB,GAAG,EAAE,MAAM,EACX,aAAa,EAAE,MAAM,EACrB,UAAU,EAAE,MAAM,EAClB,aAAa,EAAE,MAAM,EACrB,SAAS,CAAC,EAAE,OAAO,KAChB,OAAO,CAAC,IAAI,CAAC,CAAC;IACnB;;;OAGG;IACH,WAAW,EAAE,CACX,GAAG,EAAE,MAAM,EACX,aAAa,EAAE,MAAM,EACrB,UAAU,EAAE,MAAM,EAClB,eAAe,CAAC,EAAE,MAAM,KACrB,OAAO,CAAC,OAAO,CAAC,CAAC;IACtB;;OAEG;IACH,QAAQ,EAAE,CAAC,GAAG,EAAE,MAAM,EAAE,GAAG,EAAE,MAAM,KAAK,OAAO,CAAC,MAAM,CAAC,CAAC;IACxD,YAAY,EAAE,aAAa,CAAC;IAC5B,6BAA6B,EAAE,IAAI,CAAC,6BAA6B,EAAE,SAAS,CAAC,CAAC;CAC/E;AAED;;;;;GAKG;AACH,wBAAgB,eAAe,CAAC,IAAI,EAAE,aAAa,IAGnC,OAAO,iBAAiB,KAAG,OAAO,CAAC,OAAO,CAAC,iBAAiB,CAAC,CAAC,CA+T7E"}
1
+ {"version":3,"file":"merge.node.d.ts","sourceRoot":"","sources":["../../../../../../../../../../packages/core/src/infrastructure/services/agents/feature-agent/nodes/merge/merge.node.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;GAaG;AAGH,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,+DAA+D,CAAC;AACpG,OAAO,KAAK,EAAE,iBAAiB,EAAE,MAAM,gBAAgB,CAAC;AACxD,OAAO,KAAK,EAAE,kBAAkB,EAAE,MAAM,yEAAyE,CAAC;AAClH,OAAO,KAAK,EACV,WAAW,EACX,aAAa,EACd,MAAM,iEAAiE,CAAC;AAmBzE,OAAO,KAAK,EAAE,6BAA6B,EAAE,MAAM,uEAAuE,CAAC;AAE3H,MAAM,WAAW,aAAa;IAC5B,QAAQ,EAAE,cAAc,CAAC;IACzB,cAAc,EAAE,CAAC,GAAG,EAAE,MAAM,EAAE,UAAU,EAAE,MAAM,KAAK,OAAO,CAAC,WAAW,CAAC,CAAC;IAC1E,SAAS,EAAE,CAAC,GAAG,EAAE,MAAM,KAAK,OAAO,CAAC,OAAO,CAAC,CAAC;IAC7C,gBAAgB,EAAE,CAAC,GAAG,EAAE,MAAM,KAAK,OAAO,CAAC,MAAM,CAAC,CAAC;IACnD,iBAAiB,EAAE,IAAI,CAAC,kBAAkB,EAAE,UAAU,GAAG,QAAQ,CAAC,CAAC;IACnE;;OAEG;IACH,gBAAgB,EAAE,CAChB,GAAG,EAAE,MAAM,EACX,aAAa,EAAE,MAAM,EACrB,UAAU,EAAE,MAAM,EAClB,aAAa,EAAE,MAAM,EACrB,SAAS,CAAC,EAAE,OAAO,KAChB,OAAO,CAAC,IAAI,CAAC,CAAC;IACnB;;;OAGG;IACH,WAAW,EAAE,CACX,GAAG,EAAE,MAAM,EACX,aAAa,EAAE,MAAM,EACrB,UAAU,EAAE,MAAM,EAClB,eAAe,CAAC,EAAE,MAAM,KACrB,OAAO,CAAC,OAAO,CAAC,CAAC;IACtB;;OAEG;IACH,QAAQ,EAAE,CAAC,GAAG,EAAE,MAAM,EAAE,GAAG,EAAE,MAAM,KAAK,OAAO,CAAC,MAAM,CAAC,CAAC;IACxD;;;OAGG;IACH,SAAS,EAAE,CAAC,GAAG,EAAE,MAAM,EAAE,OAAO,EAAE,MAAM,KAAK,OAAO,CAAC,MAAM,GAAG,SAAS,CAAC,CAAC;IACzE,YAAY,EAAE,aAAa,CAAC;IAC5B,6BAA6B,EAAE,IAAI,CAAC,6BAA6B,EAAE,SAAS,CAAC,CAAC;CAC/E;AAED;;;;;GAKG;AACH,wBAAgB,eAAe,CAAC,IAAI,EAAE,aAAa,IAGnC,OAAO,iBAAiB,KAAG,OAAO,CAAC,OAAO,CAAC,iBAAiB,CAAC,CAAC,CA0V7E"}