@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.
- package/dist/packages/core/src/infrastructure/services/agents/common/agent-executor-factory.service.js +1 -1
- package/dist/packages/core/src/infrastructure/services/agents/common/executors/cursor-executor.service.d.ts +8 -28
- package/dist/packages/core/src/infrastructure/services/agents/common/executors/cursor-executor.service.d.ts.map +1 -1
- package/dist/packages/core/src/infrastructure/services/agents/common/executors/cursor-executor.service.js +20 -117
- package/dist/src/presentation/web/components/layouts/app-shell/app-shell.d.ts.map +1 -1
- package/dist/src/presentation/web/components/layouts/app-shell/app-shell.js +8 -3
- package/dist/tsconfig.build.tsbuildinfo +1 -1
- package/package.json +1 -1
- package/web/.next/BUILD_ID +1 -1
- package/web/.next/build-manifest.json +2 -2
- package/web/.next/fallback-build-manifest.json +2 -2
- package/web/.next/prerender-manifest.json +3 -3
- package/web/.next/required-server-files.js +1 -1
- package/web/.next/required-server-files.json +1 -1
- package/web/.next/server/app/(dashboard)/@drawer/create/page/server-reference-manifest.json +21 -21
- package/web/.next/server/app/(dashboard)/@drawer/create/page.js.nft.json +1 -1
- package/web/.next/server/app/(dashboard)/@drawer/create/page_client-reference-manifest.js +1 -1
- package/web/.next/server/app/(dashboard)/@drawer/feature/[featureId]/[tab]/page/server-reference-manifest.json +27 -27
- package/web/.next/server/app/(dashboard)/@drawer/feature/[featureId]/[tab]/page.js.nft.json +1 -1
- package/web/.next/server/app/(dashboard)/@drawer/feature/[featureId]/[tab]/page_client-reference-manifest.js +1 -1
- package/web/.next/server/app/(dashboard)/@drawer/feature/[featureId]/page/server-reference-manifest.json +27 -27
- package/web/.next/server/app/(dashboard)/@drawer/feature/[featureId]/page.js.nft.json +1 -1
- package/web/.next/server/app/(dashboard)/@drawer/feature/[featureId]/page_client-reference-manifest.js +1 -1
- package/web/.next/server/app/(dashboard)/@drawer/repository/[repositoryId]/page/server-reference-manifest.json +19 -19
- package/web/.next/server/app/(dashboard)/@drawer/repository/[repositoryId]/page.js.nft.json +1 -1
- package/web/.next/server/app/(dashboard)/@drawer/repository/[repositoryId]/page_client-reference-manifest.js +1 -1
- package/web/.next/server/app/(dashboard)/create/page/server-reference-manifest.json +21 -21
- package/web/.next/server/app/(dashboard)/create/page.js.nft.json +1 -1
- package/web/.next/server/app/(dashboard)/create/page_client-reference-manifest.js +1 -1
- package/web/.next/server/app/(dashboard)/feature/[featureId]/[tab]/page/server-reference-manifest.json +27 -27
- package/web/.next/server/app/(dashboard)/feature/[featureId]/[tab]/page.js.nft.json +1 -1
- package/web/.next/server/app/(dashboard)/feature/[featureId]/[tab]/page_client-reference-manifest.js +1 -1
- package/web/.next/server/app/(dashboard)/feature/[featureId]/page/server-reference-manifest.json +27 -27
- package/web/.next/server/app/(dashboard)/feature/[featureId]/page.js.nft.json +1 -1
- package/web/.next/server/app/(dashboard)/feature/[featureId]/page_client-reference-manifest.js +1 -1
- package/web/.next/server/app/(dashboard)/page/server-reference-manifest.json +19 -19
- package/web/.next/server/app/(dashboard)/page.js.nft.json +1 -1
- package/web/.next/server/app/(dashboard)/page_client-reference-manifest.js +1 -1
- package/web/.next/server/app/(dashboard)/repository/[repositoryId]/page/server-reference-manifest.json +19 -19
- package/web/.next/server/app/(dashboard)/repository/[repositoryId]/page.js.nft.json +1 -1
- package/web/.next/server/app/(dashboard)/repository/[repositoryId]/page_client-reference-manifest.js +1 -1
- package/web/.next/server/app/_global-error.html +2 -2
- package/web/.next/server/app/_global-error.rsc +1 -1
- package/web/.next/server/app/_global-error.segments/__PAGE__.segment.rsc +1 -1
- package/web/.next/server/app/_global-error.segments/_full.segment.rsc +1 -1
- package/web/.next/server/app/_global-error.segments/_head.segment.rsc +1 -1
- package/web/.next/server/app/_global-error.segments/_index.segment.rsc +1 -1
- package/web/.next/server/app/_global-error.segments/_tree.segment.rsc +1 -1
- package/web/.next/server/app/_not-found/page/server-reference-manifest.json +1 -1
- package/web/.next/server/app/_not-found/page_client-reference-manifest.js +1 -1
- package/web/.next/server/app/settings/page/server-reference-manifest.json +6 -6
- package/web/.next/server/app/settings/page.js.nft.json +1 -1
- package/web/.next/server/app/settings/page_client-reference-manifest.js +1 -1
- package/web/.next/server/app/skills/page/server-reference-manifest.json +6 -6
- package/web/.next/server/app/skills/page_client-reference-manifest.js +1 -1
- package/web/.next/server/app/tools/page/server-reference-manifest.json +6 -6
- package/web/.next/server/app/tools/page_client-reference-manifest.js +1 -1
- package/web/.next/server/app/version/page/server-reference-manifest.json +1 -1
- package/web/.next/server/app/version/page_client-reference-manifest.js +1 -1
- package/web/.next/server/chunks/[root-of-the-server]__a402b567._.js +1 -1
- package/web/.next/server/chunks/ssr/744ca_web_components_common_control-center-drawer_create-drawer-client_tsx_5e26fc0a._.js +1 -1
- package/web/.next/server/chunks/ssr/744ca_web_components_common_control-center-drawer_create-drawer-client_tsx_5e26fc0a._.js.map +1 -1
- package/web/.next/server/chunks/ssr/8ba4b_server_app_(dashboard)_@drawer_repository_[repositoryId]_page_actions_ed372306.js +1 -1
- package/web/.next/server/chunks/ssr/8ba4b_server_app_(dashboard)_@drawer_repository_[repositoryId]_page_actions_ed372306.js.map +1 -1
- package/web/.next/server/chunks/ssr/8ba4b_server_app_(dashboard)_repository_[repositoryId]_page_actions_32e26434.js +1 -1
- package/web/.next/server/chunks/ssr/8ba4b_server_app_(dashboard)_repository_[repositoryId]_page_actions_32e26434.js.map +1 -1
- package/web/.next/server/chunks/ssr/[root-of-the-server]__06fef644._.js +1 -1
- package/web/.next/server/chunks/ssr/[root-of-the-server]__3b14e5a0._.js +1 -1
- package/web/.next/server/chunks/ssr/[root-of-the-server]__3b14e5a0._.js.map +1 -1
- package/web/.next/server/chunks/ssr/[root-of-the-server]__545792ab._.js +1 -1
- package/web/.next/server/chunks/ssr/[root-of-the-server]__545792ab._.js.map +1 -1
- package/web/.next/server/chunks/ssr/[root-of-the-server]__6b17a22d._.js +1 -1
- package/web/.next/server/chunks/ssr/[root-of-the-server]__6b17a22d._.js.map +1 -1
- package/web/.next/server/chunks/ssr/[root-of-the-server]__6bb00d90._.js +2 -2
- package/web/.next/server/chunks/ssr/[root-of-the-server]__6bb00d90._.js.map +1 -1
- package/web/.next/server/chunks/ssr/[root-of-the-server]__804c006d._.js +1 -1
- package/web/.next/server/chunks/ssr/[root-of-the-server]__804c006d._.js.map +1 -1
- package/web/.next/server/chunks/ssr/[root-of-the-server]__8b59c03e._.js +1 -1
- package/web/.next/server/chunks/ssr/[root-of-the-server]__8b59c03e._.js.map +1 -1
- package/web/.next/server/chunks/ssr/[root-of-the-server]__8c553503._.js +2 -2
- package/web/.next/server/chunks/ssr/[root-of-the-server]__994ad9fe._.js +1 -1
- package/web/.next/server/chunks/ssr/[root-of-the-server]__994ad9fe._.js.map +1 -1
- package/web/.next/server/chunks/ssr/[root-of-the-server]__a022445f._.js +2 -2
- package/web/.next/server/chunks/ssr/[root-of-the-server]__a7de2711._.js +2 -2
- package/web/.next/server/chunks/ssr/[root-of-the-server]__c9c1cfee._.js +1 -1
- package/web/.next/server/chunks/ssr/[root-of-the-server]__c9c1cfee._.js.map +1 -1
- package/web/.next/server/chunks/ssr/_135edb9c._.js +1 -1
- package/web/.next/server/chunks/ssr/_135edb9c._.js.map +1 -1
- package/web/.next/server/chunks/ssr/_2f6f48b8._.js +1 -1
- package/web/.next/server/chunks/ssr/_2f6f48b8._.js.map +1 -1
- package/web/.next/server/chunks/ssr/_ab069e13._.js +1 -1
- package/web/.next/server/chunks/ssr/_ab069e13._.js.map +1 -1
- package/web/.next/server/chunks/ssr/_cc77a143._.js +1 -1
- package/web/.next/server/chunks/ssr/_cc77a143._.js.map +1 -1
- package/web/.next/server/chunks/ssr/{_c016175b._.js → _d3ac41e4._.js} +2 -2
- package/web/.next/server/chunks/ssr/{_c016175b._.js.map → _d3ac41e4._.js.map} +1 -1
- package/web/.next/server/chunks/ssr/{_c6b80726._.js → _f68cd40a._.js} +2 -2
- package/web/.next/server/chunks/ssr/{_c6b80726._.js.map → _f68cd40a._.js.map} +1 -1
- package/web/.next/server/chunks/ssr/_f9f273ac._.js +3 -0
- package/web/.next/server/chunks/ssr/{_435cd61a._.js.map → _f9f273ac._.js.map} +1 -1
- package/web/.next/server/chunks/ssr/b1a17_presentation_web_components_features_settings_settings-page-client_tsx_6ed9d5f8._.js +1 -1
- package/web/.next/server/chunks/ssr/b1a17_presentation_web_components_features_settings_settings-page-client_tsx_6ed9d5f8._.js.map +1 -1
- package/web/.next/server/chunks/ssr/src_presentation_web_0835b28e._.js +2 -2
- package/web/.next/server/chunks/ssr/src_presentation_web_0835b28e._.js.map +1 -1
- package/web/.next/server/chunks/ssr/src_presentation_web__next-internal_server_app_(dashboard)_page_actions_e99d78dd.js +1 -1
- package/web/.next/server/chunks/ssr/src_presentation_web__next-internal_server_app_(dashboard)_page_actions_e99d78dd.js.map +1 -1
- package/web/.next/server/chunks/ssr/src_presentation_web__next-internal_server_app_skills_page_actions_1fa8042e.js +1 -1
- package/web/.next/server/chunks/ssr/src_presentation_web__next-internal_server_app_skills_page_actions_1fa8042e.js.map +1 -1
- package/web/.next/server/chunks/ssr/src_presentation_web__next-internal_server_app_tools_page_actions_24684200.js +1 -1
- package/web/.next/server/chunks/ssr/src_presentation_web__next-internal_server_app_tools_page_actions_24684200.js.map +1 -1
- package/web/.next/server/chunks/ssr/src_presentation_web_components_bf50c527._.js +1 -1
- package/web/.next/server/chunks/ssr/src_presentation_web_components_de814675._.js +1 -1
- package/web/.next/server/chunks/ssr/src_presentation_web_components_e599bb8c._.js +1 -1
- package/web/.next/server/chunks/ssr/src_presentation_web_components_e599bb8c._.js.map +1 -1
- package/web/.next/server/chunks/ssr/src_presentation_web_components_features_control-center_7ac3562e._.js +1 -1
- package/web/.next/server/chunks/ssr/src_presentation_web_components_features_control-center_7ac3562e._.js.map +1 -1
- package/web/.next/server/chunks/ssr/src_presentation_web_e8034a29._.js +2 -2
- package/web/.next/server/chunks/ssr/src_presentation_web_e8034a29._.js.map +1 -1
- package/web/.next/server/pages/500.html +2 -2
- package/web/.next/server/server-reference-manifest.js +1 -1
- package/web/.next/server/server-reference-manifest.json +33 -33
- package/web/.next/static/chunks/{96049ca80ceb10f0.js → 2104d54a331a01a8.js} +1 -1
- package/web/.next/static/chunks/{3b27bd39bf11f076.js → 22a09e8581a775da.js} +1 -1
- package/web/.next/static/chunks/{bb03051ee7c01e64.js → 25c3d8f72b65c176.js} +2 -2
- package/web/.next/static/chunks/3945855b1fb0125e.js +1 -0
- package/web/.next/static/chunks/{7eb1d12ff4e0a545.js → 4bf310c7837ec4c9.js} +1 -1
- package/web/.next/static/chunks/{418128e3931a55f3.js → 54065a2d3aa77d6a.js} +1 -1
- package/web/.next/static/chunks/{0f070bdb053b3579.js → 5732fcfe2e277225.js} +2 -2
- package/web/.next/static/chunks/{485dfa2b1ba874ef.js → 67a6eeacd4cea4b6.js} +1 -1
- package/web/.next/static/chunks/{619af41a8d3232e5.js → 71161130b2462279.js} +1 -1
- package/web/.next/static/chunks/{66c4848bc7b13df8.js → 7dee8cf92be8bf24.js} +1 -1
- package/web/.next/static/chunks/{139f46d14f2be0a6.js → 885da7f69d637a5f.js} +1 -1
- package/web/.next/server/chunks/ssr/_435cd61a._.js +0 -3
- package/web/.next/static/chunks/d8d23303021cea22.js +0 -1
- /package/web/.next/static/{VKrxBSI0iPzA7QL_Xgt6y → GvtDAY-V0NfItBFI1sJMY}/_buildManifest.js +0 -0
- /package/web/.next/static/{VKrxBSI0iPzA7QL_Xgt6y → GvtDAY-V0NfItBFI1sJMY}/_clientMiddlewareManifest.json +0 -0
- /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
|
|
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
|
|
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
|
|
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
|
-
*
|
|
36
|
+
* Spawn the agent process, handling Windows specially via PowerShell.
|
|
38
37
|
*
|
|
39
|
-
*
|
|
40
|
-
*
|
|
41
|
-
*
|
|
42
|
-
*
|
|
43
|
-
*
|
|
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,
|
|
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
|
|
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
|
|
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
|
-
|
|
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(`
|
|
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(`
|
|
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(`
|
|
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
|
-
*
|
|
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,
|
|
380
|
-
*
|
|
381
|
-
*
|
|
382
|
-
*
|
|
383
|
-
*
|
|
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
|
-
|
|
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:
|
|
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:
|
|
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;
|
|
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
|
-
/**
|
|
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 }) }) }) }));
|