@shepai/cli 1.15.1 → 1.17.0
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/README.md +168 -22
- package/dist/src/application/ports/output/agents/agent-executor-provider.interface.d.ts +5 -0
- package/dist/src/application/ports/output/agents/agent-executor-provider.interface.d.ts.map +1 -0
- package/dist/src/application/ports/output/agents/agent-executor-provider.interface.js +1 -0
- package/dist/src/application/ports/output/agents/agent-executor.interface.d.ts +2 -0
- package/dist/src/application/ports/output/agents/agent-executor.interface.d.ts.map +1 -1
- package/dist/src/application/ports/output/agents/feature-agent-process.interface.d.ts +2 -0
- package/dist/src/application/ports/output/agents/feature-agent-process.interface.d.ts.map +1 -1
- package/dist/src/application/ports/output/agents/index.d.ts +1 -0
- package/dist/src/application/ports/output/agents/index.d.ts.map +1 -1
- package/dist/src/application/ports/output/index.d.ts +1 -1
- package/dist/src/application/ports/output/index.d.ts.map +1 -1
- package/dist/src/application/use-cases/features/create-feature.use-case.d.ts +3 -3
- package/dist/src/application/use-cases/features/create-feature.use-case.d.ts.map +1 -1
- package/dist/src/application/use-cases/features/create-feature.use-case.js +10 -7
- package/dist/src/application/use-cases/features/resume-feature.use-case.d.ts.map +1 -1
- package/dist/src/application/use-cases/features/resume-feature.use-case.js +6 -1
- package/dist/src/infrastructure/di/container.d.ts.map +1 -1
- package/dist/src/infrastructure/di/container.js +9 -2
- package/dist/src/infrastructure/services/agents/common/agent-executor-factory.service.d.ts +1 -1
- package/dist/src/infrastructure/services/agents/common/agent-executor-factory.service.d.ts.map +1 -1
- package/dist/src/infrastructure/services/agents/common/agent-executor-factory.service.js +6 -2
- package/dist/src/infrastructure/services/agents/common/agent-executor-provider.service.d.ts +9 -0
- package/dist/src/infrastructure/services/agents/common/agent-executor-provider.service.d.ts.map +1 -0
- package/dist/src/infrastructure/services/agents/common/agent-executor-provider.service.js +11 -0
- package/dist/src/infrastructure/services/agents/common/agent-runner.service.d.ts +3 -3
- package/dist/src/infrastructure/services/agents/common/agent-runner.service.d.ts.map +1 -1
- package/dist/src/infrastructure/services/agents/common/agent-runner.service.js +4 -4
- package/dist/src/infrastructure/services/agents/common/agent-validator.service.d.ts +1 -9
- package/dist/src/infrastructure/services/agents/common/agent-validator.service.d.ts.map +1 -1
- package/dist/src/infrastructure/services/agents/common/agent-validator.service.js +1 -0
- package/dist/src/infrastructure/services/agents/common/executors/claude-code-executor.service.d.ts +3 -7
- package/dist/src/infrastructure/services/agents/common/executors/claude-code-executor.service.d.ts.map +1 -1
- package/dist/src/infrastructure/services/agents/common/executors/claude-code-executor.service.js +5 -0
- package/dist/src/infrastructure/services/agents/common/executors/cursor-executor.service.d.ts +38 -0
- package/dist/src/infrastructure/services/agents/common/executors/cursor-executor.service.d.ts.map +1 -0
- package/dist/src/infrastructure/services/agents/common/executors/cursor-executor.service.js +296 -0
- package/dist/src/infrastructure/services/agents/common/types.d.ts +23 -0
- package/dist/src/infrastructure/services/agents/common/types.d.ts.map +1 -0
- package/dist/src/infrastructure/services/agents/common/types.js +7 -0
- package/dist/src/infrastructure/services/agents/feature-agent/feature-agent-process.service.d.ts +2 -0
- package/dist/src/infrastructure/services/agents/feature-agent/feature-agent-process.service.d.ts.map +1 -1
- package/dist/src/infrastructure/services/agents/feature-agent/feature-agent-process.service.js +6 -0
- package/dist/src/infrastructure/services/agents/feature-agent/feature-agent-worker.d.ts +2 -0
- package/dist/src/infrastructure/services/agents/feature-agent/feature-agent-worker.d.ts.map +1 -1
- package/dist/src/infrastructure/services/agents/feature-agent/feature-agent-worker.js +32 -12
- package/dist/src/infrastructure/services/agents/feature-agent/nodes/implement.node.d.ts +8 -7
- package/dist/src/infrastructure/services/agents/feature-agent/nodes/implement.node.d.ts.map +1 -1
- package/dist/src/infrastructure/services/agents/feature-agent/nodes/implement.node.js +139 -16
- package/dist/src/infrastructure/services/agents/feature-agent/nodes/node-helpers.d.ts +6 -0
- package/dist/src/infrastructure/services/agents/feature-agent/nodes/node-helpers.d.ts.map +1 -1
- package/dist/src/infrastructure/services/agents/feature-agent/nodes/node-helpers.js +29 -5
- package/dist/src/infrastructure/services/agents/feature-agent/nodes/prompts/implement.prompt.d.ts +44 -4
- package/dist/src/infrastructure/services/agents/feature-agent/nodes/prompts/implement.prompt.d.ts.map +1 -1
- package/dist/src/infrastructure/services/agents/feature-agent/nodes/prompts/implement.prompt.js +86 -14
- package/dist/src/presentation/cli/commands/feat/ls.command.d.ts.map +1 -1
- package/dist/src/presentation/cli/commands/feat/ls.command.js +42 -7
- package/dist/src/presentation/cli/commands/feat/new.command.d.ts.map +1 -1
- package/dist/src/presentation/cli/commands/feat/new.command.js +3 -3
- package/dist/src/presentation/cli/ui/index.d.ts +1 -0
- package/dist/src/presentation/cli/ui/index.d.ts.map +1 -1
- package/dist/src/presentation/cli/ui/index.js +1 -0
- package/dist/src/presentation/cli/ui/spinner.d.ts +21 -0
- package/dist/src/presentation/cli/ui/spinner.d.ts.map +1 -0
- package/dist/src/presentation/cli/ui/spinner.js +45 -0
- package/dist/src/presentation/tui/prompts/agent-select.prompt.d.ts +1 -1
- package/dist/src/presentation/tui/prompts/agent-select.prompt.js +1 -1
- 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/cache/.previewinfo +1 -1
- package/web/.next/cache/.rscinfo +1 -1
- package/web/.next/cache/config.json +3 -3
- 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/_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.html +2 -2
- package/web/.next/server/app/_not-found.rsc +1 -1
- package/web/.next/server/app/_not-found.segments/_full.segment.rsc +1 -1
- package/web/.next/server/app/_not-found.segments/_head.segment.rsc +1 -1
- package/web/.next/server/app/_not-found.segments/_index.segment.rsc +1 -1
- package/web/.next/server/app/_not-found.segments/_not-found/__PAGE__.segment.rsc +1 -1
- package/web/.next/server/app/_not-found.segments/_not-found.segment.rsc +1 -1
- package/web/.next/server/app/_not-found.segments/_tree.segment.rsc +1 -1
- package/web/.next/server/app/index.html +2 -2
- package/web/.next/server/app/index.rsc +1 -1
- package/web/.next/server/app/index.segments/__PAGE__.segment.rsc +1 -1
- package/web/.next/server/app/index.segments/_full.segment.rsc +1 -1
- package/web/.next/server/app/index.segments/_head.segment.rsc +1 -1
- package/web/.next/server/app/index.segments/_index.segment.rsc +1 -1
- package/web/.next/server/app/index.segments/_tree.segment.rsc +1 -1
- package/web/.next/server/app/version.html +2 -2
- package/web/.next/server/app/version.rsc +1 -1
- package/web/.next/server/app/version.segments/_full.segment.rsc +1 -1
- package/web/.next/server/app/version.segments/_head.segment.rsc +1 -1
- package/web/.next/server/app/version.segments/_index.segment.rsc +1 -1
- package/web/.next/server/app/version.segments/_tree.segment.rsc +1 -1
- package/web/.next/server/app/version.segments/version/__PAGE__.segment.rsc +1 -1
- package/web/.next/server/app/version.segments/version.segment.rsc +1 -1
- package/web/.next/server/chunks/ssr/_19be0743._.js +1 -1
- package/web/.next/server/pages/404.html +2 -2
- 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 +1 -1
- package/web/.next/trace +1 -1
- package/web/.next/trace-build +1 -1
- /package/web/.next/static/{iYaq62xFNOChDTbH3WMrr → Wgd1DC_QfVhpAi62LjpwI}/_buildManifest.js +0 -0
- /package/web/.next/static/{iYaq62xFNOChDTbH3WMrr → Wgd1DC_QfVhpAi62LjpwI}/_clientMiddlewareManifest.json +0 -0
- /package/web/.next/static/{iYaq62xFNOChDTbH3WMrr → Wgd1DC_QfVhpAi62LjpwI}/_ssgManifest.js +0 -0
package/dist/src/infrastructure/services/agents/common/executors/claude-code-executor.service.d.ts
CHANGED
|
@@ -8,15 +8,9 @@
|
|
|
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 { ChildProcess } from 'node:child_process';
|
|
12
11
|
import type { AgentType, AgentFeature } from '../../../../../domain/generated/output.js';
|
|
13
12
|
import type { IAgentExecutor, AgentExecutionOptions, AgentExecutionResult, AgentExecutionStreamEvent } from '../../../../../application/ports/output/agents/agent-executor.interface.js';
|
|
14
|
-
|
|
15
|
-
* Type for the spawn dependency.
|
|
16
|
-
* Matches the signature of child_process.spawn.
|
|
17
|
-
* Injected via constructor to enable testability.
|
|
18
|
-
*/
|
|
19
|
-
export type SpawnFunction = (command: string, args: string[], options?: object) => ChildProcess;
|
|
13
|
+
import type { SpawnFunction } from '../types.js';
|
|
20
14
|
/**
|
|
21
15
|
* Executor service for Claude Code agent.
|
|
22
16
|
* Uses subprocess spawning to interact with the `claude` CLI.
|
|
@@ -24,6 +18,8 @@ export type SpawnFunction = (command: string, args: string[], options?: object)
|
|
|
24
18
|
export declare class ClaudeCodeExecutorService implements IAgentExecutor {
|
|
25
19
|
private readonly spawn;
|
|
26
20
|
readonly agentType: AgentType;
|
|
21
|
+
/** When true, suppresses debug logging (set per-call via options.silent) */
|
|
22
|
+
private silent;
|
|
27
23
|
constructor(spawn: SpawnFunction);
|
|
28
24
|
/** Debug logging — writes to stdout so it appears in the worker log file */
|
|
29
25
|
private log;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"claude-code-executor.service.d.ts","sourceRoot":"","sources":["../../../../../../../src/infrastructure/services/agents/common/executors/claude-code-executor.service.ts"],"names":[],"mappings":"AAAA;;;;;;;;;GASG;AAEH,OAAO,KAAK,EAAE,
|
|
1
|
+
{"version":3,"file":"claude-code-executor.service.d.ts","sourceRoot":"","sources":["../../../../../../../src/infrastructure/services/agents/common/executors/claude-code-executor.service.ts"],"names":[],"mappings":"AAAA;;;;;;;;;GASG;AAEH,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;AAUjD;;;GAGG;AACH,qBAAa,yBAA0B,YAAW,cAAc;IAMlD,OAAO,CAAC,QAAQ,CAAC,KAAK;IALlC,QAAQ,CAAC,SAAS,EAAE,SAAS,CAA8B;IAE3D,4EAA4E;IAC5E,OAAO,CAAC,MAAM,CAAS;gBAEM,KAAK,EAAE,aAAa;IAEjD,4EAA4E;IAC5E,OAAO,CAAC,GAAG;IAML,OAAO,CAAC,MAAM,EAAE,MAAM,EAAE,OAAO,CAAC,EAAE,qBAAqB,GAAG,OAAO,CAAC,oBAAoB,CAAC;IAmHtF,aAAa,CAClB,MAAM,EAAE,MAAM,EACd,OAAO,CAAC,EAAE,qBAAqB,GAC9B,aAAa,CAAC,yBAAyB,CAAC;IA+F3C;;;OAGG;IACH,OAAO,CAAC,cAAc;IAmCtB,eAAe,CAAC,OAAO,EAAE,YAAY,GAAG,OAAO;IAI/C,OAAO,CAAC,SAAS;IAWjB,OAAO,CAAC,eAAe;IAUvB,OAAO,CAAC,iBAAiB;IAMzB,OAAO,CAAC,eAAe;IAiCvB,OAAO,CAAC,eAAe;CAkExB"}
|
package/dist/src/infrastructure/services/agents/common/executors/claude-code-executor.service.js
CHANGED
|
@@ -22,15 +22,20 @@ const SUPPORTED_FEATURES = new Set([
|
|
|
22
22
|
export class ClaudeCodeExecutorService {
|
|
23
23
|
spawn;
|
|
24
24
|
agentType = 'claude-code';
|
|
25
|
+
/** When true, suppresses debug logging (set per-call via options.silent) */
|
|
26
|
+
silent = false;
|
|
25
27
|
constructor(spawn) {
|
|
26
28
|
this.spawn = spawn;
|
|
27
29
|
}
|
|
28
30
|
/** Debug logging — writes to stdout so it appears in the worker log file */
|
|
29
31
|
log(message) {
|
|
32
|
+
if (this.silent)
|
|
33
|
+
return;
|
|
30
34
|
const ts = new Date().toISOString();
|
|
31
35
|
process.stdout.write(`[${ts}] [claude-executor] ${message}\n`);
|
|
32
36
|
}
|
|
33
37
|
async execute(prompt, options) {
|
|
38
|
+
this.silent = options?.silent ?? false;
|
|
34
39
|
// Use stream-json so we get real-time events in the worker log
|
|
35
40
|
// instead of zero output for minutes with --output-format json
|
|
36
41
|
const args = this.buildStreamArgs(prompt, options);
|
|
@@ -0,0 +1,38 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Cursor Executor Service
|
|
3
|
+
*
|
|
4
|
+
* Infrastructure implementation of IAgentExecutor for the Cursor agent.
|
|
5
|
+
* Executes prompts via the `agent` CLI subprocess with JSON and stream-json
|
|
6
|
+
* output formats.
|
|
7
|
+
*
|
|
8
|
+
* Uses constructor dependency injection for the spawn function
|
|
9
|
+
* to enable testability without mocking node:child_process directly.
|
|
10
|
+
*/
|
|
11
|
+
import type { AgentType, AgentFeature } from '../../../../../domain/generated/output.js';
|
|
12
|
+
import type { IAgentExecutor, AgentExecutionOptions, AgentExecutionResult, AgentExecutionStreamEvent } from '../../../../../application/ports/output/agents/agent-executor.interface.js';
|
|
13
|
+
import type { SpawnFunction } from '../types.js';
|
|
14
|
+
/**
|
|
15
|
+
* Executor service for Cursor agent.
|
|
16
|
+
* Uses subprocess spawning to interact with the `agent` CLI.
|
|
17
|
+
*/
|
|
18
|
+
export declare class CursorExecutorService implements IAgentExecutor {
|
|
19
|
+
private readonly spawn;
|
|
20
|
+
readonly agentType: AgentType;
|
|
21
|
+
/** When true, suppresses debug logging (set per-call via options.silent) */
|
|
22
|
+
private silent;
|
|
23
|
+
constructor(spawn: SpawnFunction);
|
|
24
|
+
/** Debug logging — writes to stdout so it appears in the worker log file */
|
|
25
|
+
private log;
|
|
26
|
+
supportsFeature(feature: AgentFeature): boolean;
|
|
27
|
+
execute(prompt: string, options?: AgentExecutionOptions): Promise<AgentExecutionResult>;
|
|
28
|
+
executeStream(prompt: string, options?: AgentExecutionOptions): AsyncIterable<AgentExecutionStreamEvent>;
|
|
29
|
+
/**
|
|
30
|
+
* Log a stream-json line as a human-readable event in the worker log.
|
|
31
|
+
*/
|
|
32
|
+
private logStreamEvent;
|
|
33
|
+
private buildArgs;
|
|
34
|
+
private buildStreamArgs;
|
|
35
|
+
private buildSpawnOptions;
|
|
36
|
+
private parseStreamLine;
|
|
37
|
+
}
|
|
38
|
+
//# sourceMappingURL=cursor-executor.service.d.ts.map
|
package/dist/src/infrastructure/services/agents/common/executors/cursor-executor.service.d.ts.map
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"cursor-executor.service.d.ts","sourceRoot":"","sources":["../../../../../../../src/infrastructure/services/agents/common/executors/cursor-executor.service.ts"],"names":[],"mappings":"AAAA;;;;;;;;;GASG;AAEH,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;AAKjD;;;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;IAkGtF,aAAa,CAClB,MAAM,EAAE,MAAM,EACd,OAAO,CAAC,EAAE,qBAAqB,GAC9B,aAAa,CAAC,yBAAyB,CAAC;IA8E3C;;OAEG;IACH,OAAO,CAAC,cAAc;IAkCtB,OAAO,CAAC,SAAS;IASjB,OAAO,CAAC,eAAe;IAOvB,OAAO,CAAC,iBAAiB;IAMzB,OAAO,CAAC,eAAe;CAgDxB"}
|
|
@@ -0,0 +1,296 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Cursor Executor Service
|
|
3
|
+
*
|
|
4
|
+
* Infrastructure implementation of IAgentExecutor for the Cursor agent.
|
|
5
|
+
* Executes prompts via the `agent` CLI subprocess with JSON and stream-json
|
|
6
|
+
* output formats.
|
|
7
|
+
*
|
|
8
|
+
* Uses constructor dependency injection for the spawn function
|
|
9
|
+
* to enable testability without mocking node:child_process directly.
|
|
10
|
+
*/
|
|
11
|
+
/** Features supported by Cursor CLI */
|
|
12
|
+
const SUPPORTED_FEATURES = new Set(['session-resume', 'streaming']);
|
|
13
|
+
/**
|
|
14
|
+
* Executor service for Cursor agent.
|
|
15
|
+
* Uses subprocess spawning to interact with the `agent` CLI.
|
|
16
|
+
*/
|
|
17
|
+
export class CursorExecutorService {
|
|
18
|
+
spawn;
|
|
19
|
+
agentType = 'cursor';
|
|
20
|
+
/** When true, suppresses debug logging (set per-call via options.silent) */
|
|
21
|
+
silent = false;
|
|
22
|
+
constructor(spawn) {
|
|
23
|
+
this.spawn = spawn;
|
|
24
|
+
}
|
|
25
|
+
/** Debug logging — writes to stdout so it appears in the worker log file */
|
|
26
|
+
log(message) {
|
|
27
|
+
if (this.silent)
|
|
28
|
+
return;
|
|
29
|
+
const ts = new Date().toISOString();
|
|
30
|
+
process.stdout.write(`[${ts}] [cursor-executor] ${message}\n`);
|
|
31
|
+
}
|
|
32
|
+
supportsFeature(feature) {
|
|
33
|
+
return SUPPORTED_FEATURES.has(feature);
|
|
34
|
+
}
|
|
35
|
+
async execute(prompt, options) {
|
|
36
|
+
this.silent = options?.silent ?? false;
|
|
37
|
+
const args = this.buildStreamArgs(prompt, options);
|
|
38
|
+
const spawnOpts = this.buildSpawnOptions(options);
|
|
39
|
+
this.log(`Spawning: agent ${args.map((a) => (a.length > 80 ? `${a.slice(0, 77)}...` : a)).join(' ')}`);
|
|
40
|
+
this.log(`Spawn options: ${JSON.stringify(spawnOpts)}`);
|
|
41
|
+
const proc = this.spawn('agent', args, spawnOpts);
|
|
42
|
+
this.log(`Subprocess PID: ${proc.pid ?? 'undefined (spawn may have failed)'}`);
|
|
43
|
+
if (proc.stdin)
|
|
44
|
+
proc.stdin.end();
|
|
45
|
+
return new Promise((resolve, reject) => {
|
|
46
|
+
let lineBuffer = '';
|
|
47
|
+
let stderr = '';
|
|
48
|
+
let timedOut = false;
|
|
49
|
+
let timeoutId;
|
|
50
|
+
// Accumulated from assistant events
|
|
51
|
+
let resultText = '';
|
|
52
|
+
let sessionId;
|
|
53
|
+
let metadata;
|
|
54
|
+
if (options?.timeout) {
|
|
55
|
+
timeoutId = setTimeout(() => {
|
|
56
|
+
timedOut = true;
|
|
57
|
+
proc.kill();
|
|
58
|
+
}, options.timeout);
|
|
59
|
+
}
|
|
60
|
+
const processLine = (line) => {
|
|
61
|
+
this.logStreamEvent(line);
|
|
62
|
+
try {
|
|
63
|
+
const parsed = JSON.parse(line);
|
|
64
|
+
if (parsed.type === 'assistant' && Array.isArray(parsed.message?.content)) {
|
|
65
|
+
for (const block of parsed.message.content) {
|
|
66
|
+
if (block.type === 'text' && block.text)
|
|
67
|
+
resultText += block.text;
|
|
68
|
+
}
|
|
69
|
+
}
|
|
70
|
+
else if (parsed.type === 'result') {
|
|
71
|
+
if (parsed.session_id)
|
|
72
|
+
sessionId = parsed.session_id;
|
|
73
|
+
if (parsed.duration_ms !== undefined) {
|
|
74
|
+
metadata = { ...metadata, duration_ms: parsed.duration_ms };
|
|
75
|
+
}
|
|
76
|
+
}
|
|
77
|
+
// user events and tool_call events: logged but don't affect result
|
|
78
|
+
}
|
|
79
|
+
catch {
|
|
80
|
+
/* malformed JSON — already logged */
|
|
81
|
+
}
|
|
82
|
+
};
|
|
83
|
+
proc.stdout?.on('data', (chunk) => {
|
|
84
|
+
lineBuffer += chunk.toString();
|
|
85
|
+
const lines = lineBuffer.split('\n');
|
|
86
|
+
lineBuffer = lines.pop() ?? '';
|
|
87
|
+
for (const line of lines) {
|
|
88
|
+
const trimmed = line.trim();
|
|
89
|
+
if (trimmed)
|
|
90
|
+
processLine(trimmed);
|
|
91
|
+
}
|
|
92
|
+
});
|
|
93
|
+
proc.stderr?.on('data', (chunk) => {
|
|
94
|
+
const data = chunk.toString();
|
|
95
|
+
stderr += data;
|
|
96
|
+
this.log(`stderr: ${data.trimEnd()}`);
|
|
97
|
+
});
|
|
98
|
+
proc.on('error', (error) => {
|
|
99
|
+
this.log(`Process error event: ${error.message}`);
|
|
100
|
+
if (timeoutId)
|
|
101
|
+
clearTimeout(timeoutId);
|
|
102
|
+
reject(error);
|
|
103
|
+
});
|
|
104
|
+
proc.on('close', (code) => {
|
|
105
|
+
if (lineBuffer.trim())
|
|
106
|
+
processLine(lineBuffer.trim());
|
|
107
|
+
this.log(`Process closed with code ${code}, result=${resultText.length} chars`);
|
|
108
|
+
if (timeoutId)
|
|
109
|
+
clearTimeout(timeoutId);
|
|
110
|
+
if (timedOut) {
|
|
111
|
+
reject(new Error('Agent execution timed out'));
|
|
112
|
+
return;
|
|
113
|
+
}
|
|
114
|
+
if (code !== 0 && code !== null) {
|
|
115
|
+
reject(new Error(stderr.trim() || `Process exited with code ${code}`));
|
|
116
|
+
return;
|
|
117
|
+
}
|
|
118
|
+
const result = { result: resultText };
|
|
119
|
+
if (sessionId)
|
|
120
|
+
result.sessionId = sessionId;
|
|
121
|
+
if (metadata)
|
|
122
|
+
result.metadata = metadata;
|
|
123
|
+
resolve(result);
|
|
124
|
+
});
|
|
125
|
+
});
|
|
126
|
+
}
|
|
127
|
+
async *executeStream(prompt, options) {
|
|
128
|
+
const args = this.buildStreamArgs(prompt, options);
|
|
129
|
+
const spawnOpts = this.buildSpawnOptions(options);
|
|
130
|
+
const proc = this.spawn('agent', args, spawnOpts);
|
|
131
|
+
if (proc.stdin)
|
|
132
|
+
proc.stdin.end();
|
|
133
|
+
let lineBuffer = '';
|
|
134
|
+
let stderr = '';
|
|
135
|
+
const queue = [];
|
|
136
|
+
let resolve = null;
|
|
137
|
+
let error = null;
|
|
138
|
+
function enqueue(event) {
|
|
139
|
+
queue.push(event);
|
|
140
|
+
if (resolve) {
|
|
141
|
+
resolve();
|
|
142
|
+
resolve = null;
|
|
143
|
+
}
|
|
144
|
+
}
|
|
145
|
+
function waitForItem() {
|
|
146
|
+
if (queue.length > 0)
|
|
147
|
+
return Promise.resolve();
|
|
148
|
+
return new Promise((r) => {
|
|
149
|
+
resolve = r;
|
|
150
|
+
});
|
|
151
|
+
}
|
|
152
|
+
proc.stdout?.on('data', (chunk) => {
|
|
153
|
+
lineBuffer += chunk.toString();
|
|
154
|
+
const lines = lineBuffer.split('\n');
|
|
155
|
+
lineBuffer = lines.pop() ?? '';
|
|
156
|
+
for (const line of lines) {
|
|
157
|
+
const trimmed = line.trim();
|
|
158
|
+
if (!trimmed)
|
|
159
|
+
continue;
|
|
160
|
+
const event = this.parseStreamLine(trimmed);
|
|
161
|
+
if (event)
|
|
162
|
+
enqueue(event);
|
|
163
|
+
}
|
|
164
|
+
});
|
|
165
|
+
proc.stderr?.on('data', (chunk) => {
|
|
166
|
+
stderr += chunk.toString();
|
|
167
|
+
});
|
|
168
|
+
proc.on('error', (err) => {
|
|
169
|
+
error = err;
|
|
170
|
+
enqueue(null);
|
|
171
|
+
});
|
|
172
|
+
proc.on('close', (code) => {
|
|
173
|
+
if (lineBuffer.trim()) {
|
|
174
|
+
const event = this.parseStreamLine(lineBuffer.trim());
|
|
175
|
+
if (event)
|
|
176
|
+
enqueue(event);
|
|
177
|
+
}
|
|
178
|
+
if (code !== 0 && code !== null && stderr.trim()) {
|
|
179
|
+
enqueue({ type: 'error', content: stderr.trim(), timestamp: new Date() });
|
|
180
|
+
}
|
|
181
|
+
enqueue(null);
|
|
182
|
+
});
|
|
183
|
+
while (true) {
|
|
184
|
+
await waitForItem();
|
|
185
|
+
const item = queue.shift();
|
|
186
|
+
if (item === null || item === undefined) {
|
|
187
|
+
if (error !== null) {
|
|
188
|
+
yield {
|
|
189
|
+
type: 'error',
|
|
190
|
+
content: error.message,
|
|
191
|
+
timestamp: new Date(),
|
|
192
|
+
};
|
|
193
|
+
}
|
|
194
|
+
return;
|
|
195
|
+
}
|
|
196
|
+
yield item;
|
|
197
|
+
}
|
|
198
|
+
}
|
|
199
|
+
/**
|
|
200
|
+
* Log a stream-json line as a human-readable event in the worker log.
|
|
201
|
+
*/
|
|
202
|
+
logStreamEvent(line) {
|
|
203
|
+
try {
|
|
204
|
+
const parsed = JSON.parse(line);
|
|
205
|
+
if (parsed.type === 'assistant' && Array.isArray(parsed.message?.content)) {
|
|
206
|
+
for (const block of parsed.message.content) {
|
|
207
|
+
if (block.type === 'text' && block.text?.trim()) {
|
|
208
|
+
this.log(`[text] ${block.text.trim().replace(/\n/g, ' ')}`);
|
|
209
|
+
}
|
|
210
|
+
}
|
|
211
|
+
return;
|
|
212
|
+
}
|
|
213
|
+
if (parsed.type === 'tool_call') {
|
|
214
|
+
const toolName = Object.keys(parsed).find((k) => k.endsWith('ToolCall') || k.endsWith('toolCall')) ??
|
|
215
|
+
'unknown';
|
|
216
|
+
this.log(`[tool] ${parsed.subtype ?? 'call'}: ${toolName}`);
|
|
217
|
+
return;
|
|
218
|
+
}
|
|
219
|
+
if (parsed.type === 'result') {
|
|
220
|
+
this.log(`[result] session=${parsed.session_id ?? 'none'}, duration=${parsed.duration_ms ?? 'unknown'}ms`);
|
|
221
|
+
return;
|
|
222
|
+
}
|
|
223
|
+
if (parsed.type === 'user')
|
|
224
|
+
return; // Skip echoed input
|
|
225
|
+
}
|
|
226
|
+
catch {
|
|
227
|
+
if (line.length > 0)
|
|
228
|
+
this.log(`[raw] ${line}`);
|
|
229
|
+
}
|
|
230
|
+
}
|
|
231
|
+
buildArgs(prompt, options) {
|
|
232
|
+
const args = ['-p', prompt, '--output-format', 'json', '--force'];
|
|
233
|
+
if (options?.resumeSession)
|
|
234
|
+
args.push('--resume', options.resumeSession);
|
|
235
|
+
if (options?.model)
|
|
236
|
+
args.push('-m', options.model);
|
|
237
|
+
// Unsupported options silently omitted: systemPrompt, allowedTools, maxTurns, outputSchema
|
|
238
|
+
// No auth flags — binary handles its own auth
|
|
239
|
+
return args;
|
|
240
|
+
}
|
|
241
|
+
buildStreamArgs(prompt, options) {
|
|
242
|
+
const args = this.buildArgs(prompt, options);
|
|
243
|
+
const fmtIdx = args.indexOf('--output-format');
|
|
244
|
+
if (fmtIdx !== -1)
|
|
245
|
+
args[fmtIdx + 1] = 'stream-json';
|
|
246
|
+
return args;
|
|
247
|
+
}
|
|
248
|
+
buildSpawnOptions(options) {
|
|
249
|
+
const spawnOpts = {};
|
|
250
|
+
if (options?.cwd)
|
|
251
|
+
spawnOpts.cwd = options.cwd;
|
|
252
|
+
return spawnOpts;
|
|
253
|
+
}
|
|
254
|
+
parseStreamLine(line) {
|
|
255
|
+
try {
|
|
256
|
+
const parsed = JSON.parse(line);
|
|
257
|
+
if (parsed.type === 'assistant' && Array.isArray(parsed.message?.content)) {
|
|
258
|
+
const textParts = [];
|
|
259
|
+
for (const block of parsed.message.content) {
|
|
260
|
+
if (block.type === 'text' && block.text)
|
|
261
|
+
textParts.push(block.text);
|
|
262
|
+
}
|
|
263
|
+
if (textParts.length > 0) {
|
|
264
|
+
return { type: 'progress', content: textParts.join(''), timestamp: new Date() };
|
|
265
|
+
}
|
|
266
|
+
return null;
|
|
267
|
+
}
|
|
268
|
+
if (parsed.type === 'tool_call' && parsed.subtype === 'completed') {
|
|
269
|
+
const toolName = Object.keys(parsed).find((k) => k.endsWith('ToolCall') || k.endsWith('toolCall')) ??
|
|
270
|
+
'tool';
|
|
271
|
+
return { type: 'progress', content: `Tool completed: ${toolName}`, timestamp: new Date() };
|
|
272
|
+
}
|
|
273
|
+
if (parsed.type === 'tool_call' && parsed.subtype === 'started') {
|
|
274
|
+
const toolName = Object.keys(parsed).find((k) => k.endsWith('ToolCall') || k.endsWith('toolCall')) ??
|
|
275
|
+
'tool';
|
|
276
|
+
return { type: 'progress', content: `Tool started: ${toolName}`, timestamp: new Date() };
|
|
277
|
+
}
|
|
278
|
+
if (parsed.type === 'result') {
|
|
279
|
+
return { type: 'result', content: parsed.session_id ?? '', timestamp: new Date() };
|
|
280
|
+
}
|
|
281
|
+
if (parsed.type === 'user')
|
|
282
|
+
return null; // Skip echoed input
|
|
283
|
+
if (parsed.type === 'error') {
|
|
284
|
+
return {
|
|
285
|
+
type: 'error',
|
|
286
|
+
content: parsed.error ?? parsed.message ?? '',
|
|
287
|
+
timestamp: new Date(),
|
|
288
|
+
};
|
|
289
|
+
}
|
|
290
|
+
return null;
|
|
291
|
+
}
|
|
292
|
+
catch {
|
|
293
|
+
return { type: 'progress', content: line, timestamp: new Date() };
|
|
294
|
+
}
|
|
295
|
+
}
|
|
296
|
+
}
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Shared Types for Agent Infrastructure
|
|
3
|
+
*
|
|
4
|
+
* Common type definitions used across agent executor implementations
|
|
5
|
+
* and the agent validator service.
|
|
6
|
+
*/
|
|
7
|
+
import type { ChildProcess } from 'node:child_process';
|
|
8
|
+
/**
|
|
9
|
+
* Type for the spawn dependency.
|
|
10
|
+
* Matches the signature of child_process.spawn.
|
|
11
|
+
* Injected via constructor to enable testability.
|
|
12
|
+
*/
|
|
13
|
+
export type SpawnFunction = (command: string, args: string[], options?: object) => ChildProcess;
|
|
14
|
+
/**
|
|
15
|
+
* Type for the command executor dependency.
|
|
16
|
+
* Matches the promisified signature of child_process.execFile.
|
|
17
|
+
* Injected via constructor to avoid direct node module mocking in tests.
|
|
18
|
+
*/
|
|
19
|
+
export type ExecFunction = (file: string, args: string[]) => Promise<{
|
|
20
|
+
stdout: string;
|
|
21
|
+
stderr: string;
|
|
22
|
+
}>;
|
|
23
|
+
//# sourceMappingURL=types.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../../../../../../src/infrastructure/services/agents/common/types.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAEH,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,oBAAoB,CAAC;AAEvD;;;;GAIG;AACH,MAAM,MAAM,aAAa,GAAG,CAAC,OAAO,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,EAAE,EAAE,OAAO,CAAC,EAAE,MAAM,KAAK,YAAY,CAAC;AAEhG;;;;GAIG;AACH,MAAM,MAAM,YAAY,GAAG,CACzB,IAAI,EAAE,MAAM,EACZ,IAAI,EAAE,MAAM,EAAE,KACX,OAAO,CAAC;IAAE,MAAM,EAAE,MAAM,CAAC;IAAC,MAAM,EAAE,MAAM,CAAA;CAAE,CAAC,CAAC"}
|
package/dist/src/infrastructure/services/agents/feature-agent/feature-agent-process.service.d.ts
CHANGED
|
@@ -13,6 +13,8 @@ export declare class FeatureAgentProcessService implements IFeatureAgentProcessS
|
|
|
13
13
|
spawn(featureId: string, runId: string, repoPath: string, specDir: string, worktreePath?: string, options?: {
|
|
14
14
|
approvalMode?: string;
|
|
15
15
|
resume?: boolean;
|
|
16
|
+
threadId?: string;
|
|
17
|
+
resumeFromInterrupt?: boolean;
|
|
16
18
|
}): number;
|
|
17
19
|
isAlive(pid: number): boolean;
|
|
18
20
|
checkAndMarkCrashed(runId: string): Promise<void>;
|
package/dist/src/infrastructure/services/agents/feature-agent/feature-agent-process.service.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"feature-agent-process.service.d.ts","sourceRoot":"","sources":["../../../../../../src/infrastructure/services/agents/feature-agent/feature-agent-process.service.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AASH,OAAO,KAAK,EAAE,2BAA2B,EAAE,MAAM,sEAAsE,CAAC;AACxH,OAAO,KAAK,EAAE,mBAAmB,EAAE,MAAM,qEAAqE,CAAC;AAa/G,qBAAa,0BAA2B,YAAW,2BAA2B;IAChE,OAAO,CAAC,QAAQ,CAAC,aAAa;gBAAb,aAAa,EAAE,mBAAmB;IAE/D,KAAK,CACH,SAAS,EAAE,MAAM,EACjB,KAAK,EAAE,MAAM,EACb,QAAQ,EAAE,MAAM,EAChB,OAAO,EAAE,MAAM,EACf,YAAY,CAAC,EAAE,MAAM,EACrB,OAAO,CAAC,EAAE;
|
|
1
|
+
{"version":3,"file":"feature-agent-process.service.d.ts","sourceRoot":"","sources":["../../../../../../src/infrastructure/services/agents/feature-agent/feature-agent-process.service.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AASH,OAAO,KAAK,EAAE,2BAA2B,EAAE,MAAM,sEAAsE,CAAC;AACxH,OAAO,KAAK,EAAE,mBAAmB,EAAE,MAAM,qEAAqE,CAAC;AAa/G,qBAAa,0BAA2B,YAAW,2BAA2B;IAChE,OAAO,CAAC,QAAQ,CAAC,aAAa;gBAAb,aAAa,EAAE,mBAAmB;IAE/D,KAAK,CACH,SAAS,EAAE,MAAM,EACjB,KAAK,EAAE,MAAM,EACb,QAAQ,EAAE,MAAM,EAChB,OAAO,EAAE,MAAM,EACf,YAAY,CAAC,EAAE,MAAM,EACrB,OAAO,CAAC,EAAE;QACR,YAAY,CAAC,EAAE,MAAM,CAAC;QACtB,MAAM,CAAC,EAAE,OAAO,CAAC;QACjB,QAAQ,CAAC,EAAE,MAAM,CAAC;QAClB,mBAAmB,CAAC,EAAE,OAAO,CAAC;KAC/B,GACA,MAAM;IAkDT,OAAO,CAAC,GAAG,EAAE,MAAM,GAAG,OAAO;IASvB,mBAAmB,CAAC,KAAK,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC;CAexD"}
|
package/dist/src/infrastructure/services/agents/feature-agent/feature-agent-process.service.js
CHANGED
|
@@ -44,9 +44,15 @@ export class FeatureAgentProcessService {
|
|
|
44
44
|
if (options?.approvalMode) {
|
|
45
45
|
args.push('--approval-mode', options.approvalMode);
|
|
46
46
|
}
|
|
47
|
+
if (options?.threadId) {
|
|
48
|
+
args.push('--thread-id', options.threadId);
|
|
49
|
+
}
|
|
47
50
|
if (options?.resume) {
|
|
48
51
|
args.push('--resume');
|
|
49
52
|
}
|
|
53
|
+
if (options?.resumeFromInterrupt) {
|
|
54
|
+
args.push('--resume-from-interrupt');
|
|
55
|
+
}
|
|
50
56
|
// Create log file for worker output (for debugging)
|
|
51
57
|
const logsDir = join(homedir(), '.shep', 'logs');
|
|
52
58
|
mkdirSync(logsDir, { recursive: true });
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"feature-agent-worker.d.ts","sourceRoot":"","sources":["../../../../../../src/infrastructure/services/agents/feature-agent/feature-agent-worker.ts"],"names":[],"mappings":";AACA;;;;;;;;GAQG;AAEH,OAAO,kBAAkB,CAAC;AAc1B,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,YAAY,CAAC,EAAE,MAAM,CAAC;IACtB,MAAM,CAAC,EAAE,OAAO,CAAC;
|
|
1
|
+
{"version":3,"file":"feature-agent-worker.d.ts","sourceRoot":"","sources":["../../../../../../src/infrastructure/services/agents/feature-agent/feature-agent-worker.ts"],"names":[],"mappings":";AACA;;;;;;;;GAQG;AAEH,OAAO,kBAAkB,CAAC;AAc1B,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,YAAY,CAAC,EAAE,MAAM,CAAC;IACtB,MAAM,CAAC,EAAE,OAAO,CAAC;IACjB,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,mBAAmB,CAAC,EAAE,OAAO,CAAC;CAC/B;AAED;;;GAGG;AACH,wBAAgB,eAAe,CAAC,IAAI,EAAE,MAAM,EAAE,GAAG,UAAU,CAmC1D;AAgCD;;;GAGG;AACH,wBAAsB,SAAS,CAAC,IAAI,EAAE,UAAU,GAAG,OAAO,CAAC,IAAI,CAAC,CAmI/D"}
|
|
@@ -16,7 +16,7 @@ import { initializeContainer, container } from '../../../../infrastructure/di/co
|
|
|
16
16
|
import { createFeatureAgentGraph } from './feature-agent-graph.js';
|
|
17
17
|
import { createCheckpointer } from '../common/checkpointer.js';
|
|
18
18
|
import { AgentRunStatus } from '../../../../domain/generated/output.js';
|
|
19
|
-
import {
|
|
19
|
+
import { initializeSettings } from '../../../../infrastructure/services/settings.service.js';
|
|
20
20
|
import { InitializeSettingsUseCase } from '../../../../application/use-cases/settings/initialize-settings.use-case.js';
|
|
21
21
|
import { setHeartbeatContext } from './heartbeat.js';
|
|
22
22
|
/**
|
|
@@ -36,6 +36,9 @@ export function parseWorkerArgs(args) {
|
|
|
36
36
|
const approvalIdx = args.indexOf('--approval-mode');
|
|
37
37
|
const approvalMode = approvalIdx !== -1 && approvalIdx + 1 < args.length ? args[approvalIdx + 1] : undefined;
|
|
38
38
|
const resume = args.includes('--resume');
|
|
39
|
+
const resumeFromInterrupt = args.includes('--resume-from-interrupt');
|
|
40
|
+
const threadIdx = args.indexOf('--thread-id');
|
|
41
|
+
const threadId = threadIdx !== -1 && threadIdx + 1 < args.length ? args[threadIdx + 1] : undefined;
|
|
39
42
|
return {
|
|
40
43
|
featureId: getArg('feature-id'),
|
|
41
44
|
runId: getArg('run-id'),
|
|
@@ -44,6 +47,8 @@ export function parseWorkerArgs(args) {
|
|
|
44
47
|
worktreePath,
|
|
45
48
|
approvalMode,
|
|
46
49
|
resume,
|
|
50
|
+
threadId,
|
|
51
|
+
resumeFromInterrupt,
|
|
47
52
|
};
|
|
48
53
|
}
|
|
49
54
|
/** Simple worker logger — writes to stdout which is redirected to log file by the parent. */
|
|
@@ -92,14 +97,15 @@ export async function runWorker(args) {
|
|
|
92
97
|
const settings = await initSettingsUseCase.execute();
|
|
93
98
|
initializeSettings(settings);
|
|
94
99
|
const runRepository = container.resolve('IAgentRunRepository');
|
|
95
|
-
const
|
|
96
|
-
// Create executor from configured agent settings
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
//
|
|
101
|
-
const
|
|
102
|
-
|
|
100
|
+
const executorProvider = container.resolve('IAgentExecutorProvider');
|
|
101
|
+
// Create executor from configured agent settings
|
|
102
|
+
log('Creating executor from configured agent settings...');
|
|
103
|
+
const executor = executorProvider.getExecutor();
|
|
104
|
+
// Use threadId for checkpoint path so resume runs share the same checkpoint DB.
|
|
105
|
+
// Falls back to runId for backwards compatibility with existing runs.
|
|
106
|
+
const checkpointId = args.threadId ?? args.runId;
|
|
107
|
+
const checkpointPath = join(homedir(), '.shep', 'checkpoints', `${checkpointId}.db`);
|
|
108
|
+
log(`Creating checkpointer at ${checkpointPath} (thread: ${checkpointId})`);
|
|
103
109
|
const checkpointer = createCheckpointer(checkpointPath);
|
|
104
110
|
const graph = createFeatureAgentGraph(executor, checkpointer);
|
|
105
111
|
// Mark the run as running with our PID
|
|
@@ -116,12 +122,26 @@ export async function runWorker(args) {
|
|
|
116
122
|
// Set heartbeat context so node-helpers can update current node
|
|
117
123
|
setHeartbeatContext(args.runId, runRepository);
|
|
118
124
|
try {
|
|
119
|
-
const graphConfig = { configurable: { thread_id:
|
|
125
|
+
const graphConfig = { configurable: { thread_id: checkpointId } };
|
|
120
126
|
let result;
|
|
121
|
-
if (args.resume) {
|
|
122
|
-
|
|
127
|
+
if (args.resume && args.resumeFromInterrupt) {
|
|
128
|
+
// Resume from an interrupt (human-in-the-loop approval)
|
|
129
|
+
log('Resuming graph from interrupt checkpoint...');
|
|
123
130
|
result = await graph.invoke(new Command({ resume: { approved: true } }), graphConfig);
|
|
124
131
|
}
|
|
132
|
+
else if (args.resume) {
|
|
133
|
+
// Resume from error — re-invoke with initial state; LangGraph continues
|
|
134
|
+
// from the last successfully checkpointed node.
|
|
135
|
+
log('Resuming graph from error checkpoint...');
|
|
136
|
+
result = await graph.invoke({
|
|
137
|
+
featureId: args.featureId,
|
|
138
|
+
repositoryPath: args.repo,
|
|
139
|
+
worktreePath: args.worktreePath ?? args.repo,
|
|
140
|
+
specDir: args.specDir,
|
|
141
|
+
error: undefined, // Clear previous error state
|
|
142
|
+
...(args.approvalMode ? { approvalMode: args.approvalMode } : {}),
|
|
143
|
+
}, graphConfig);
|
|
144
|
+
}
|
|
125
145
|
else {
|
|
126
146
|
log('Starting graph invocation...');
|
|
127
147
|
result = await graph.invoke({
|
|
@@ -1,11 +1,12 @@
|
|
|
1
|
-
import type { IAgentExecutor } from '../../../../../application/ports/output/agents/agent-executor.interface.js';
|
|
2
|
-
import type { FeatureAgentState } from '../state.js';
|
|
3
1
|
/**
|
|
4
|
-
*
|
|
2
|
+
* Implement Node — Phase-Level Orchestrator
|
|
5
3
|
*
|
|
6
|
-
*
|
|
7
|
-
*
|
|
8
|
-
*
|
|
4
|
+
* Reads plan.yaml and tasks.yaml, then executes each phase by building
|
|
5
|
+
* a focused implementation prompt and calling the executor. Parallel
|
|
6
|
+
* phases spawn concurrent executor calls. Progress is tracked in
|
|
7
|
+
* feature.yaml between phases.
|
|
9
8
|
*/
|
|
10
|
-
|
|
9
|
+
import type { IAgentExecutor } from '../../../../../application/ports/output/agents/agent-executor.interface.js';
|
|
10
|
+
import type { FeatureAgentState } from '../state.js';
|
|
11
|
+
export declare function createImplementNode(executor: IAgentExecutor): (state: FeatureAgentState) => Promise<Partial<FeatureAgentState>>;
|
|
11
12
|
//# sourceMappingURL=implement.node.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"implement.node.d.ts","sourceRoot":"","sources":["../../../../../../../src/infrastructure/services/agents/feature-agent/nodes/implement.node.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,+DAA+D,CAAC;AACpG,OAAO,KAAK,EAAE,iBAAiB,EAAE,MAAM,aAAa,CAAC;
|
|
1
|
+
{"version":3,"file":"implement.node.d.ts","sourceRoot":"","sources":["../../../../../../../src/infrastructure/services/agents/feature-agent/nodes/implement.node.ts"],"names":[],"mappings":"AAAA;;;;;;;GAOG;AAMH,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,+DAA+D,CAAC;AACpG,OAAO,KAAK,EAAE,iBAAiB,EAAE,MAAM,aAAa,CAAC;AA4DrD,wBAAgB,mBAAmB,CAAC,QAAQ,EAAE,cAAc,IAG5C,OAAO,iBAAiB,KAAG,OAAO,CAAC,OAAO,CAAC,iBAAiB,CAAC,CAAC,CAoJ7E"}
|