@shepai/cli 1.8.2 → 1.9.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/dist/src/application/ports/output/agent-executor-factory.interface.d.ts +45 -0
- package/dist/src/application/ports/output/agent-executor-factory.interface.d.ts.map +1 -0
- package/dist/src/application/ports/output/agent-executor-factory.interface.js +19 -0
- package/dist/src/application/ports/output/agent-executor.interface.d.ts +117 -0
- package/dist/src/application/ports/output/agent-executor.interface.d.ts.map +1 -0
- package/dist/src/application/ports/output/agent-executor.interface.js +23 -0
- package/dist/src/application/ports/output/agent-registry.interface.d.ts +91 -0
- package/dist/src/application/ports/output/agent-registry.interface.d.ts.map +1 -0
- package/dist/src/application/ports/output/agent-registry.interface.js +33 -0
- package/dist/src/application/ports/output/agent-run-repository.interface.d.ts +70 -0
- package/dist/src/application/ports/output/agent-run-repository.interface.d.ts.map +1 -0
- package/dist/src/application/ports/output/agent-run-repository.interface.js +11 -0
- package/dist/src/application/ports/output/agent-runner.interface.d.ts +82 -0
- package/dist/src/application/ports/output/agent-runner.interface.d.ts.map +1 -0
- package/dist/src/application/ports/output/agent-runner.interface.js +23 -0
- package/dist/src/application/ports/output/index.d.ts +5 -0
- package/dist/src/application/ports/output/index.d.ts.map +1 -1
- package/dist/src/application/use-cases/agents/run-agent.use-case.d.ts +52 -0
- package/dist/src/application/use-cases/agents/run-agent.use-case.d.ts.map +1 -0
- package/dist/src/application/use-cases/agents/run-agent.use-case.js +77 -0
- package/dist/src/domain/generated/output.d.ts +98 -0
- package/dist/src/domain/generated/output.d.ts.map +1 -1
- package/dist/src/domain/generated/output.js +17 -0
- package/dist/src/infrastructure/di/container.d.ts.map +1 -1
- package/dist/src/infrastructure/di/container.js +39 -0
- package/dist/src/infrastructure/persistence/sqlite/mappers/agent-run.mapper.d.ts +51 -0
- package/dist/src/infrastructure/persistence/sqlite/mappers/agent-run.mapper.d.ts.map +1 -0
- package/dist/src/infrastructure/persistence/sqlite/mappers/agent-run.mapper.js +64 -0
- package/dist/src/infrastructure/persistence/sqlite/migrations.d.ts.map +1 -1
- package/dist/src/infrastructure/persistence/sqlite/migrations.js +27 -0
- package/dist/src/infrastructure/repositories/agent-run.repository.d.ts +25 -0
- package/dist/src/infrastructure/repositories/agent-run.repository.d.ts.map +1 -0
- package/dist/src/infrastructure/repositories/agent-run.repository.js +119 -0
- package/dist/src/infrastructure/services/agents/agent-executor-factory.service.d.ts +43 -0
- package/dist/src/infrastructure/services/agents/agent-executor-factory.service.d.ts.map +1 -0
- package/dist/src/infrastructure/services/agents/agent-executor-factory.service.js +58 -0
- package/dist/src/infrastructure/services/agents/agent-registry.service.d.ts +18 -0
- package/dist/src/infrastructure/services/agents/agent-registry.service.d.ts.map +1 -0
- package/dist/src/infrastructure/services/agents/agent-registry.service.js +30 -0
- package/dist/src/infrastructure/services/agents/agent-runner.service.d.ts +27 -0
- package/dist/src/infrastructure/services/agents/agent-runner.service.d.ts.map +1 -0
- package/dist/src/infrastructure/services/agents/agent-runner.service.js +117 -0
- package/dist/src/infrastructure/services/agents/executors/claude-code-executor.service.d.ts +37 -0
- package/dist/src/infrastructure/services/agents/executors/claude-code-executor.service.d.ts.map +1 -0
- package/dist/src/infrastructure/services/agents/executors/claude-code-executor.service.js +275 -0
- package/dist/src/infrastructure/services/agents/langgraph/analyze-repository-graph.d.ts +119 -0
- package/dist/src/infrastructure/services/agents/langgraph/analyze-repository-graph.d.ts.map +1 -0
- package/dist/src/infrastructure/services/agents/langgraph/analyze-repository-graph.js +56 -0
- package/dist/src/infrastructure/services/agents/langgraph/checkpointer.d.ts +9 -0
- package/dist/src/infrastructure/services/agents/langgraph/checkpointer.d.ts.map +1 -0
- package/dist/src/infrastructure/services/agents/langgraph/checkpointer.js +10 -0
- package/dist/src/infrastructure/services/agents/langgraph/prompts/analyze-repository.prompt.d.ts +3 -0
- package/dist/src/infrastructure/services/agents/langgraph/prompts/analyze-repository.prompt.d.ts.map +1 -0
- package/dist/src/infrastructure/services/agents/langgraph/prompts/analyze-repository.prompt.js +18 -0
- package/dist/src/infrastructure/services/agents/streaming/event-channel.d.ts +39 -0
- package/dist/src/infrastructure/services/agents/streaming/event-channel.d.ts.map +1 -0
- package/dist/src/infrastructure/services/agents/streaming/event-channel.js +64 -0
- package/dist/src/infrastructure/services/agents/streaming/index.d.ts +9 -0
- package/dist/src/infrastructure/services/agents/streaming/index.d.ts.map +1 -0
- package/dist/src/infrastructure/services/agents/streaming/index.js +8 -0
- package/dist/src/infrastructure/services/agents/streaming/streaming-executor-proxy.d.ts +25 -0
- package/dist/src/infrastructure/services/agents/streaming/streaming-executor-proxy.d.ts.map +1 -0
- package/dist/src/infrastructure/services/agents/streaming/streaming-executor-proxy.js +51 -0
- package/dist/src/presentation/cli/commands/run.command.d.ts +19 -0
- package/dist/src/presentation/cli/commands/run.command.d.ts.map +1 -0
- package/dist/src/presentation/cli/commands/run.command.js +130 -0
- package/dist/src/presentation/cli/index.js +2 -0
- package/dist/src/presentation/cli/ui/messages.d.ts +1 -1
- package/dist/src/presentation/cli/ui/messages.d.ts.map +1 -1
- package/dist/src/presentation/cli/ui/messages.js +9 -3
- package/dist/src/presentation/cli/ui/symbols.d.ts +1 -1
- package/dist/tsconfig.build.tsbuildinfo +1 -1
- package/package.json +5 -2
- 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/_ccea5183._.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/{grFKAJxfDM8ro--FQzN2H → -QL3Wkz2EyCtR0S30gd0p}/_buildManifest.js +0 -0
- /package/web/.next/static/{grFKAJxfDM8ro--FQzN2H → -QL3Wkz2EyCtR0S30gd0p}/_clientMiddlewareManifest.json +0 -0
- /package/web/.next/static/{grFKAJxfDM8ro--FQzN2H → -QL3Wkz2EyCtR0S30gd0p}/_ssgManifest.js +0 -0
|
@@ -0,0 +1,43 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Agent Executor Factory Service
|
|
3
|
+
*
|
|
4
|
+
* Infrastructure implementation of the IAgentExecutorFactory port.
|
|
5
|
+
* Creates and caches agent executor instances based on agent type.
|
|
6
|
+
*
|
|
7
|
+
* Uses constructor dependency injection for the spawn function
|
|
8
|
+
* to enable testability without mocking node:child_process directly.
|
|
9
|
+
*/
|
|
10
|
+
import type { AgentType, AgentConfig } from '../../../domain/generated/output.js';
|
|
11
|
+
import type { IAgentExecutor } from '../../../application/ports/output/agent-executor.interface.js';
|
|
12
|
+
import type { IAgentExecutorFactory } from '../../../application/ports/output/agent-executor-factory.interface.js';
|
|
13
|
+
import { type SpawnFunction } from './executors/claude-code-executor.service.js';
|
|
14
|
+
/**
|
|
15
|
+
* Factory that creates and caches agent executor instances.
|
|
16
|
+
*
|
|
17
|
+
* Executor instances are cached per agent type (singleton per type)
|
|
18
|
+
* to avoid unnecessary re-creation of stateless executors.
|
|
19
|
+
*/
|
|
20
|
+
export declare class AgentExecutorFactory implements IAgentExecutorFactory {
|
|
21
|
+
private readonly spawn;
|
|
22
|
+
private readonly cache;
|
|
23
|
+
/**
|
|
24
|
+
* @param spawn - Spawn function for creating subprocesses (injectable for testing).
|
|
25
|
+
*/
|
|
26
|
+
constructor(spawn: SpawnFunction);
|
|
27
|
+
/**
|
|
28
|
+
* Create (or return cached) executor for the specified agent type.
|
|
29
|
+
*
|
|
30
|
+
* @param agentType - The type of agent to create an executor for
|
|
31
|
+
* @param _authConfig - Agent authentication and configuration
|
|
32
|
+
* @returns A configured agent executor
|
|
33
|
+
* @throws Error if the agent type is not supported
|
|
34
|
+
*/
|
|
35
|
+
createExecutor(agentType: AgentType, _authConfig: AgentConfig): IAgentExecutor;
|
|
36
|
+
/**
|
|
37
|
+
* Get the list of agent types this factory can create executors for.
|
|
38
|
+
*
|
|
39
|
+
* @returns Array of supported agent types
|
|
40
|
+
*/
|
|
41
|
+
getSupportedAgents(): AgentType[];
|
|
42
|
+
}
|
|
43
|
+
//# sourceMappingURL=agent-executor-factory.service.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"agent-executor-factory.service.d.ts","sourceRoot":"","sources":["../../../../../src/infrastructure/services/agents/agent-executor-factory.service.ts"],"names":[],"mappings":"AAAA;;;;;;;;GAQG;AAEH,OAAO,KAAK,EAAE,SAAS,EAAE,WAAW,EAAE,MAAM,qCAAqC,CAAC;AAClF,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,+DAA+D,CAAC;AACpG,OAAO,KAAK,EAAE,qBAAqB,EAAE,MAAM,uEAAuE,CAAC;AACnH,OAAO,EAEL,KAAK,aAAa,EACnB,MAAM,6CAA6C,CAAC;AAErD;;;;;GAKG;AACH,qBAAa,oBAAqB,YAAW,qBAAqB;IAMpD,OAAO,CAAC,QAAQ,CAAC,KAAK;IALlC,OAAO,CAAC,QAAQ,CAAC,KAAK,CAAqC;IAE3D;;OAEG;gBAC0B,KAAK,EAAE,aAAa;IAEjD;;;;;;;OAOG;IACH,cAAc,CAAC,SAAS,EAAE,SAAS,EAAE,WAAW,EAAE,WAAW,GAAG,cAAc;IAoB9E;;;;OAIG;IACH,kBAAkB,IAAI,SAAS,EAAE;CAGlC"}
|
|
@@ -0,0 +1,58 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Agent Executor Factory Service
|
|
3
|
+
*
|
|
4
|
+
* Infrastructure implementation of the IAgentExecutorFactory port.
|
|
5
|
+
* Creates and caches agent executor instances based on agent type.
|
|
6
|
+
*
|
|
7
|
+
* Uses constructor dependency injection for the spawn function
|
|
8
|
+
* to enable testability without mocking node:child_process directly.
|
|
9
|
+
*/
|
|
10
|
+
import { ClaudeCodeExecutorService, } from './executors/claude-code-executor.service.js';
|
|
11
|
+
/**
|
|
12
|
+
* Factory that creates and caches agent executor instances.
|
|
13
|
+
*
|
|
14
|
+
* Executor instances are cached per agent type (singleton per type)
|
|
15
|
+
* to avoid unnecessary re-creation of stateless executors.
|
|
16
|
+
*/
|
|
17
|
+
export class AgentExecutorFactory {
|
|
18
|
+
spawn;
|
|
19
|
+
cache = new Map();
|
|
20
|
+
/**
|
|
21
|
+
* @param spawn - Spawn function for creating subprocesses (injectable for testing).
|
|
22
|
+
*/
|
|
23
|
+
constructor(spawn) {
|
|
24
|
+
this.spawn = spawn;
|
|
25
|
+
}
|
|
26
|
+
/**
|
|
27
|
+
* Create (or return cached) executor for the specified agent type.
|
|
28
|
+
*
|
|
29
|
+
* @param agentType - The type of agent to create an executor for
|
|
30
|
+
* @param _authConfig - Agent authentication and configuration
|
|
31
|
+
* @returns A configured agent executor
|
|
32
|
+
* @throws Error if the agent type is not supported
|
|
33
|
+
*/
|
|
34
|
+
createExecutor(agentType, _authConfig) {
|
|
35
|
+
const key = agentType;
|
|
36
|
+
const cached = this.cache.get(key);
|
|
37
|
+
if (cached)
|
|
38
|
+
return cached;
|
|
39
|
+
let executor;
|
|
40
|
+
switch (key) {
|
|
41
|
+
case 'claude-code':
|
|
42
|
+
executor = new ClaudeCodeExecutorService(this.spawn);
|
|
43
|
+
break;
|
|
44
|
+
default:
|
|
45
|
+
throw new Error(`Unsupported agent type: ${agentType}. Supported: ${this.getSupportedAgents().join(', ')}`);
|
|
46
|
+
}
|
|
47
|
+
this.cache.set(key, executor);
|
|
48
|
+
return executor;
|
|
49
|
+
}
|
|
50
|
+
/**
|
|
51
|
+
* Get the list of agent types this factory can create executors for.
|
|
52
|
+
*
|
|
53
|
+
* @returns Array of supported agent types
|
|
54
|
+
*/
|
|
55
|
+
getSupportedAgents() {
|
|
56
|
+
return ['claude-code'];
|
|
57
|
+
}
|
|
58
|
+
}
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Agent Registry Service
|
|
3
|
+
*
|
|
4
|
+
* Infrastructure implementation of the IAgentRegistry port.
|
|
5
|
+
* Manages agent workflow definitions in an in-memory map,
|
|
6
|
+
* enabling runtime discovery and instantiation of agent workflows.
|
|
7
|
+
*
|
|
8
|
+
* Pre-registers built-in agents (analyze-repository) at construction time.
|
|
9
|
+
*/
|
|
10
|
+
import type { IAgentRegistry, AgentDefinitionWithFactory } from '../../../application/ports/output/agent-registry.interface.js';
|
|
11
|
+
export declare class AgentRegistryService implements IAgentRegistry {
|
|
12
|
+
private readonly agents;
|
|
13
|
+
constructor();
|
|
14
|
+
register(definition: AgentDefinitionWithFactory): void;
|
|
15
|
+
get(name: string): AgentDefinitionWithFactory | undefined;
|
|
16
|
+
list(): AgentDefinitionWithFactory[];
|
|
17
|
+
}
|
|
18
|
+
//# sourceMappingURL=agent-registry.service.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"agent-registry.service.d.ts","sourceRoot":"","sources":["../../../../../src/infrastructure/services/agents/agent-registry.service.ts"],"names":[],"mappings":"AAAA;;;;;;;;GAQG;AAEH,OAAO,KAAK,EACV,cAAc,EACd,0BAA0B,EAC3B,MAAM,wDAAwD,CAAC;AAGhE,qBAAa,oBAAqB,YAAW,cAAc;IACzD,OAAO,CAAC,QAAQ,CAAC,MAAM,CAAiD;;IAWxE,QAAQ,CAAC,UAAU,EAAE,0BAA0B,GAAG,IAAI;IAItD,GAAG,CAAC,IAAI,EAAE,MAAM,GAAG,0BAA0B,GAAG,SAAS;IAIzD,IAAI,IAAI,0BAA0B,EAAE;CAGrC"}
|
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Agent Registry Service
|
|
3
|
+
*
|
|
4
|
+
* Infrastructure implementation of the IAgentRegistry port.
|
|
5
|
+
* Manages agent workflow definitions in an in-memory map,
|
|
6
|
+
* enabling runtime discovery and instantiation of agent workflows.
|
|
7
|
+
*
|
|
8
|
+
* Pre-registers built-in agents (analyze-repository) at construction time.
|
|
9
|
+
*/
|
|
10
|
+
import { createAnalyzeRepositoryGraph } from './langgraph/analyze-repository-graph.js';
|
|
11
|
+
export class AgentRegistryService {
|
|
12
|
+
agents = new Map();
|
|
13
|
+
constructor() {
|
|
14
|
+
// Register built-in agents
|
|
15
|
+
this.register({
|
|
16
|
+
name: 'analyze-repository',
|
|
17
|
+
description: 'Analyze repository structure, dependencies, and architecture',
|
|
18
|
+
graphFactory: createAnalyzeRepositoryGraph,
|
|
19
|
+
});
|
|
20
|
+
}
|
|
21
|
+
register(definition) {
|
|
22
|
+
this.agents.set(definition.name, definition);
|
|
23
|
+
}
|
|
24
|
+
get(name) {
|
|
25
|
+
return this.agents.get(name);
|
|
26
|
+
}
|
|
27
|
+
list() {
|
|
28
|
+
return Array.from(this.agents.values());
|
|
29
|
+
}
|
|
30
|
+
}
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Agent Runner Service
|
|
3
|
+
*
|
|
4
|
+
* Infrastructure implementation of the IAgentRunner port.
|
|
5
|
+
* Orchestrates agent execution by resolving definitions from the registry,
|
|
6
|
+
* creating executors, compiling LangGraph workflows, and tracking runs
|
|
7
|
+
* in the repository.
|
|
8
|
+
*/
|
|
9
|
+
import type { BaseCheckpointSaver } from '@langchain/langgraph';
|
|
10
|
+
import type { IAgentRunner, AgentRunOptions } from '../../../application/ports/output/agent-runner.interface.js';
|
|
11
|
+
import type { IAgentRegistry } from '../../../application/ports/output/agent-registry.interface.js';
|
|
12
|
+
import type { IAgentExecutorFactory } from '../../../application/ports/output/agent-executor-factory.interface.js';
|
|
13
|
+
import type { IAgentRunRepository } from '../../../application/ports/output/agent-run-repository.interface.js';
|
|
14
|
+
import type { AgentRun, AgentRunEvent } from '../../../domain/generated/output.js';
|
|
15
|
+
export declare class AgentRunnerService implements IAgentRunner {
|
|
16
|
+
private readonly registry;
|
|
17
|
+
private readonly executorFactory;
|
|
18
|
+
private readonly checkpointer;
|
|
19
|
+
private readonly runRepository;
|
|
20
|
+
constructor(registry: IAgentRegistry, executorFactory: IAgentExecutorFactory, checkpointer: BaseCheckpointSaver, runRepository: IAgentRunRepository);
|
|
21
|
+
runAgent(agentName: string, prompt: string, options?: AgentRunOptions): Promise<AgentRun>;
|
|
22
|
+
runAgentStream(agentName: string, prompt: string, options?: AgentRunOptions): AsyncIterable<AgentRunEvent>;
|
|
23
|
+
private setupRun;
|
|
24
|
+
private markCompleted;
|
|
25
|
+
private markFailed;
|
|
26
|
+
}
|
|
27
|
+
//# sourceMappingURL=agent-runner.service.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"agent-runner.service.d.ts","sourceRoot":"","sources":["../../../../../src/infrastructure/services/agents/agent-runner.service.ts"],"names":[],"mappings":"AAAA;;;;;;;GAOG;AAGH,OAAO,KAAK,EAAE,mBAAmB,EAAE,MAAM,sBAAsB,CAAC;AAChE,OAAO,KAAK,EACV,YAAY,EACZ,eAAe,EAChB,MAAM,sDAAsD,CAAC;AAC9D,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,wDAAwD,CAAC;AAC7F,OAAO,KAAK,EAAE,qBAAqB,EAAE,MAAM,gEAAgE,CAAC;AAC5G,OAAO,KAAK,EAAE,mBAAmB,EAAE,MAAM,8DAA8D,CAAC;AAExG,OAAO,KAAK,EAAE,QAAQ,EAAE,aAAa,EAAE,MAAM,8BAA8B,CAAC;AAM5E,qBAAa,kBAAmB,YAAW,YAAY;IAEnD,OAAO,CAAC,QAAQ,CAAC,QAAQ;IACzB,OAAO,CAAC,QAAQ,CAAC,eAAe;IAChC,OAAO,CAAC,QAAQ,CAAC,YAAY;IAC7B,OAAO,CAAC,QAAQ,CAAC,aAAa;gBAHb,QAAQ,EAAE,cAAc,EACxB,eAAe,EAAE,qBAAqB,EACtC,YAAY,EAAE,mBAAmB,EACjC,aAAa,EAAE,mBAAmB;IAG/C,QAAQ,CAAC,SAAS,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,EAAE,OAAO,CAAC,EAAE,eAAe,GAAG,OAAO,CAAC,QAAQ,CAAC;IAmBxF,cAAc,CACnB,SAAS,EAAE,MAAM,EACjB,MAAM,EAAE,MAAM,EACd,OAAO,CAAC,EAAE,eAAe,GACxB,aAAa,CAAC,aAAa,CAAC;YAwCjB,QAAQ;YAwCR,aAAa;YAUb,UAAU;CAQzB"}
|
|
@@ -0,0 +1,117 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Agent Runner Service
|
|
3
|
+
*
|
|
4
|
+
* Infrastructure implementation of the IAgentRunner port.
|
|
5
|
+
* Orchestrates agent execution by resolving definitions from the registry,
|
|
6
|
+
* creating executors, compiling LangGraph workflows, and tracking runs
|
|
7
|
+
* in the repository.
|
|
8
|
+
*/
|
|
9
|
+
import * as crypto from 'node:crypto';
|
|
10
|
+
import { AgentRunStatus } from '../../../domain/generated/output.js';
|
|
11
|
+
import { getSettings } from '../../../infrastructure/services/settings.service.js';
|
|
12
|
+
import { EventChannel } from './streaming/event-channel.js';
|
|
13
|
+
import { StreamingExecutorProxy } from './streaming/streaming-executor-proxy.js';
|
|
14
|
+
export class AgentRunnerService {
|
|
15
|
+
registry;
|
|
16
|
+
executorFactory;
|
|
17
|
+
checkpointer;
|
|
18
|
+
runRepository;
|
|
19
|
+
constructor(registry, executorFactory, checkpointer, runRepository) {
|
|
20
|
+
this.registry = registry;
|
|
21
|
+
this.executorFactory = executorFactory;
|
|
22
|
+
this.checkpointer = checkpointer;
|
|
23
|
+
this.runRepository = runRepository;
|
|
24
|
+
}
|
|
25
|
+
async runAgent(agentName, prompt, options) {
|
|
26
|
+
const { definition, executor, runId, threadId } = await this.setupRun(agentName, prompt);
|
|
27
|
+
try {
|
|
28
|
+
const compiledGraph = definition.graphFactory(executor, this.checkpointer);
|
|
29
|
+
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
30
|
+
const result = await compiledGraph.invoke({ repositoryPath: options?.repositoryPath ?? process.cwd() }, { configurable: { thread_id: threadId } });
|
|
31
|
+
await this.markCompleted(runId, result);
|
|
32
|
+
return (await this.runRepository.findById(runId));
|
|
33
|
+
}
|
|
34
|
+
catch (error) {
|
|
35
|
+
await this.markFailed(runId, error);
|
|
36
|
+
return (await this.runRepository.findById(runId));
|
|
37
|
+
}
|
|
38
|
+
}
|
|
39
|
+
async *runAgentStream(agentName, prompt, options) {
|
|
40
|
+
const { definition, executor, runId, threadId } = await this.setupRun(agentName, prompt);
|
|
41
|
+
// Create streaming channel and proxy
|
|
42
|
+
const channel = new EventChannel();
|
|
43
|
+
const proxy = new StreamingExecutorProxy(executor, channel);
|
|
44
|
+
// Compile graph with proxy (graph doesn't know about streaming)
|
|
45
|
+
const compiledGraph = definition.graphFactory(proxy, this.checkpointer);
|
|
46
|
+
// Start graph invocation in background
|
|
47
|
+
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
48
|
+
const graphPromise = compiledGraph
|
|
49
|
+
.invoke({ repositoryPath: options?.repositoryPath ?? process.cwd() }, { configurable: { thread_id: threadId } })
|
|
50
|
+
.then(async (result) => {
|
|
51
|
+
channel.close();
|
|
52
|
+
await this.markCompleted(runId, result);
|
|
53
|
+
})
|
|
54
|
+
.catch(async (error) => {
|
|
55
|
+
channel.close();
|
|
56
|
+
await this.markFailed(runId, error);
|
|
57
|
+
});
|
|
58
|
+
// Yield events as they arrive, mapping infra → domain type
|
|
59
|
+
for await (const event of channel) {
|
|
60
|
+
yield {
|
|
61
|
+
type: event.type,
|
|
62
|
+
content: event.content,
|
|
63
|
+
timestamp: event.timestamp instanceof Date ? event.timestamp.toISOString() : event.timestamp,
|
|
64
|
+
};
|
|
65
|
+
}
|
|
66
|
+
// Ensure graph promise cleanup completes
|
|
67
|
+
await graphPromise;
|
|
68
|
+
}
|
|
69
|
+
async setupRun(agentName, prompt) {
|
|
70
|
+
const definition = this.registry.get(agentName);
|
|
71
|
+
if (!definition) {
|
|
72
|
+
throw new Error(`Agent '${agentName}' not found. Available: ${this.registry
|
|
73
|
+
.list()
|
|
74
|
+
.map((a) => a.name)
|
|
75
|
+
.join(', ')}`);
|
|
76
|
+
}
|
|
77
|
+
const settings = getSettings();
|
|
78
|
+
const agentType = settings.agent.type;
|
|
79
|
+
const executor = this.executorFactory.createExecutor(agentType, settings.agent);
|
|
80
|
+
const runId = crypto.randomUUID();
|
|
81
|
+
const threadId = crypto.randomUUID();
|
|
82
|
+
const now = new Date().toISOString();
|
|
83
|
+
const agentRun = {
|
|
84
|
+
id: runId,
|
|
85
|
+
agentType,
|
|
86
|
+
agentName,
|
|
87
|
+
status: AgentRunStatus.pending,
|
|
88
|
+
prompt,
|
|
89
|
+
threadId,
|
|
90
|
+
createdAt: now,
|
|
91
|
+
updatedAt: now,
|
|
92
|
+
};
|
|
93
|
+
await this.runRepository.create(agentRun);
|
|
94
|
+
await this.runRepository.updateStatus(runId, AgentRunStatus.running, {
|
|
95
|
+
pid: process.pid,
|
|
96
|
+
startedAt: now,
|
|
97
|
+
updatedAt: now,
|
|
98
|
+
});
|
|
99
|
+
return { definition, executor, runId, threadId };
|
|
100
|
+
}
|
|
101
|
+
async markCompleted(runId, result) {
|
|
102
|
+
const completedAt = new Date().toISOString();
|
|
103
|
+
await this.runRepository.updateStatus(runId, AgentRunStatus.completed, {
|
|
104
|
+
result: result.analysisMarkdown ?? result.result ?? JSON.stringify(result),
|
|
105
|
+
completedAt,
|
|
106
|
+
updatedAt: completedAt,
|
|
107
|
+
});
|
|
108
|
+
}
|
|
109
|
+
async markFailed(runId, error) {
|
|
110
|
+
const failedAt = new Date().toISOString();
|
|
111
|
+
await this.runRepository.updateStatus(runId, AgentRunStatus.failed, {
|
|
112
|
+
error: error instanceof Error ? error.message : String(error),
|
|
113
|
+
completedAt: failedAt,
|
|
114
|
+
updatedAt: failedAt,
|
|
115
|
+
});
|
|
116
|
+
}
|
|
117
|
+
}
|
|
@@ -0,0 +1,37 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Claude Code Executor Service
|
|
3
|
+
*
|
|
4
|
+
* Infrastructure implementation of IAgentExecutor for Claude Code agent.
|
|
5
|
+
* Executes prompts via the `claude` 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 { ChildProcess } from 'node:child_process';
|
|
12
|
+
import type { AgentType, AgentFeature } from '../../../../domain/generated/output.js';
|
|
13
|
+
import type { IAgentExecutor, AgentExecutionOptions, AgentExecutionResult, AgentExecutionStreamEvent } from '../../../../application/ports/output/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;
|
|
20
|
+
/**
|
|
21
|
+
* Executor service for Claude Code agent.
|
|
22
|
+
* Uses subprocess spawning to interact with the `claude` CLI.
|
|
23
|
+
*/
|
|
24
|
+
export declare class ClaudeCodeExecutorService implements IAgentExecutor {
|
|
25
|
+
private readonly spawn;
|
|
26
|
+
readonly agentType: AgentType;
|
|
27
|
+
constructor(spawn: SpawnFunction);
|
|
28
|
+
execute(prompt: string, options?: AgentExecutionOptions): Promise<AgentExecutionResult>;
|
|
29
|
+
executeStream(prompt: string, options?: AgentExecutionOptions): AsyncIterable<AgentExecutionStreamEvent>;
|
|
30
|
+
supportsFeature(feature: AgentFeature): boolean;
|
|
31
|
+
private buildArgs;
|
|
32
|
+
private buildStreamArgs;
|
|
33
|
+
private buildSpawnOptions;
|
|
34
|
+
private parseJsonResult;
|
|
35
|
+
private parseStreamLine;
|
|
36
|
+
}
|
|
37
|
+
//# sourceMappingURL=claude-code-executor.service.d.ts.map
|
package/dist/src/infrastructure/services/agents/executors/claude-code-executor.service.d.ts.map
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"claude-code-executor.service.d.ts","sourceRoot":"","sources":["../../../../../../src/infrastructure/services/agents/executors/claude-code-executor.service.ts"],"names":[],"mappings":"AAAA;;;;;;;;;GASG;AAEH,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,oBAAoB,CAAC;AACvD,OAAO,KAAK,EAAE,SAAS,EAAE,YAAY,EAAE,MAAM,wCAAwC,CAAC;AACtF,OAAO,KAAK,EACV,cAAc,EACd,qBAAqB,EACrB,oBAAoB,EACpB,yBAAyB,EAC1B,MAAM,kEAAkE,CAAC;AAE1E;;;;GAIG;AACH,MAAM,MAAM,aAAa,GAAG,CAAC,OAAO,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,EAAE,EAAE,OAAO,CAAC,EAAE,MAAM,KAAK,YAAY,CAAC;AAUhG;;;GAGG;AACH,qBAAa,yBAA0B,YAAW,cAAc;IAGlD,OAAO,CAAC,QAAQ,CAAC,KAAK;IAFlC,QAAQ,CAAC,SAAS,EAAE,SAAS,CAA8B;gBAE9B,KAAK,EAAE,aAAa;IAE3C,OAAO,CAAC,MAAM,EAAE,MAAM,EAAE,OAAO,CAAC,EAAE,qBAAqB,GAAG,OAAO,CAAC,oBAAoB,CAAC;IAiDtF,aAAa,CAClB,MAAM,EAAE,MAAM,EACd,OAAO,CAAC,EAAE,qBAAqB,GAC9B,aAAa,CAAC,yBAAyB,CAAC;IA+F3C,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"}
|
|
@@ -0,0 +1,275 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Claude Code Executor Service
|
|
3
|
+
*
|
|
4
|
+
* Infrastructure implementation of IAgentExecutor for Claude Code agent.
|
|
5
|
+
* Executes prompts via the `claude` 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 Claude Code CLI */
|
|
12
|
+
const SUPPORTED_FEATURES = new Set([
|
|
13
|
+
'session-resume',
|
|
14
|
+
'streaming',
|
|
15
|
+
'system-prompt',
|
|
16
|
+
'structured-output',
|
|
17
|
+
]);
|
|
18
|
+
/**
|
|
19
|
+
* Executor service for Claude Code agent.
|
|
20
|
+
* Uses subprocess spawning to interact with the `claude` CLI.
|
|
21
|
+
*/
|
|
22
|
+
export class ClaudeCodeExecutorService {
|
|
23
|
+
spawn;
|
|
24
|
+
agentType = 'claude-code';
|
|
25
|
+
constructor(spawn) {
|
|
26
|
+
this.spawn = spawn;
|
|
27
|
+
}
|
|
28
|
+
async execute(prompt, options) {
|
|
29
|
+
const args = this.buildArgs(prompt, options);
|
|
30
|
+
const spawnOpts = this.buildSpawnOptions(options);
|
|
31
|
+
const proc = this.spawn('claude', args, spawnOpts);
|
|
32
|
+
return new Promise((resolve, reject) => {
|
|
33
|
+
let stdout = '';
|
|
34
|
+
let stderr = '';
|
|
35
|
+
let timedOut = false;
|
|
36
|
+
let timeoutId;
|
|
37
|
+
if (options?.timeout) {
|
|
38
|
+
timeoutId = setTimeout(() => {
|
|
39
|
+
timedOut = true;
|
|
40
|
+
proc.kill();
|
|
41
|
+
}, options.timeout);
|
|
42
|
+
}
|
|
43
|
+
proc.stdout?.on('data', (chunk) => {
|
|
44
|
+
stdout += chunk.toString();
|
|
45
|
+
});
|
|
46
|
+
proc.stderr?.on('data', (chunk) => {
|
|
47
|
+
stderr += chunk.toString();
|
|
48
|
+
});
|
|
49
|
+
proc.on('error', (error) => {
|
|
50
|
+
if (timeoutId)
|
|
51
|
+
clearTimeout(timeoutId);
|
|
52
|
+
reject(error);
|
|
53
|
+
});
|
|
54
|
+
proc.on('close', (code) => {
|
|
55
|
+
if (timeoutId)
|
|
56
|
+
clearTimeout(timeoutId);
|
|
57
|
+
if (timedOut) {
|
|
58
|
+
reject(new Error('Agent execution timed out'));
|
|
59
|
+
return;
|
|
60
|
+
}
|
|
61
|
+
if (code !== 0 && code !== null) {
|
|
62
|
+
reject(new Error(stderr.trim() || `Process exited with code ${code}`));
|
|
63
|
+
return;
|
|
64
|
+
}
|
|
65
|
+
resolve(this.parseJsonResult(stdout));
|
|
66
|
+
});
|
|
67
|
+
});
|
|
68
|
+
}
|
|
69
|
+
async *executeStream(prompt, options) {
|
|
70
|
+
const args = this.buildStreamArgs(prompt, options);
|
|
71
|
+
const spawnOpts = this.buildSpawnOptions(options);
|
|
72
|
+
const proc = this.spawn('claude', args, spawnOpts);
|
|
73
|
+
// Close stdin immediately - we're not sending input in print mode
|
|
74
|
+
if (proc.stdin) {
|
|
75
|
+
proc.stdin.end();
|
|
76
|
+
}
|
|
77
|
+
// Buffer for incomplete lines
|
|
78
|
+
let lineBuffer = '';
|
|
79
|
+
let stderr = '';
|
|
80
|
+
// Create an async queue to bridge event-based IO to async iteration
|
|
81
|
+
const queue = [];
|
|
82
|
+
let resolve = null;
|
|
83
|
+
let error = null;
|
|
84
|
+
function enqueue(event) {
|
|
85
|
+
queue.push(event);
|
|
86
|
+
if (resolve) {
|
|
87
|
+
resolve();
|
|
88
|
+
resolve = null;
|
|
89
|
+
}
|
|
90
|
+
}
|
|
91
|
+
function waitForItem() {
|
|
92
|
+
if (queue.length > 0)
|
|
93
|
+
return Promise.resolve();
|
|
94
|
+
return new Promise((r) => {
|
|
95
|
+
resolve = r;
|
|
96
|
+
});
|
|
97
|
+
}
|
|
98
|
+
proc.stdout?.on('data', (chunk) => {
|
|
99
|
+
lineBuffer += chunk.toString();
|
|
100
|
+
const lines = lineBuffer.split('\n');
|
|
101
|
+
// Keep the last partial line in the buffer
|
|
102
|
+
lineBuffer = lines.pop() ?? '';
|
|
103
|
+
for (const line of lines) {
|
|
104
|
+
const trimmed = line.trim();
|
|
105
|
+
if (!trimmed)
|
|
106
|
+
continue;
|
|
107
|
+
const event = this.parseStreamLine(trimmed);
|
|
108
|
+
if (event) {
|
|
109
|
+
enqueue(event);
|
|
110
|
+
}
|
|
111
|
+
}
|
|
112
|
+
});
|
|
113
|
+
proc.stderr?.on('data', (chunk) => {
|
|
114
|
+
stderr += chunk.toString();
|
|
115
|
+
});
|
|
116
|
+
proc.on('error', (err) => {
|
|
117
|
+
error = err;
|
|
118
|
+
enqueue(null); // signal end
|
|
119
|
+
});
|
|
120
|
+
proc.on('close', (code) => {
|
|
121
|
+
// Process any remaining data in the buffer
|
|
122
|
+
if (lineBuffer.trim()) {
|
|
123
|
+
const event = this.parseStreamLine(lineBuffer.trim());
|
|
124
|
+
if (event)
|
|
125
|
+
enqueue(event);
|
|
126
|
+
}
|
|
127
|
+
if (code !== 0 && code !== null && stderr.trim()) {
|
|
128
|
+
enqueue({
|
|
129
|
+
type: 'error',
|
|
130
|
+
content: stderr.trim(),
|
|
131
|
+
timestamp: new Date(),
|
|
132
|
+
});
|
|
133
|
+
}
|
|
134
|
+
enqueue(null); // signal end
|
|
135
|
+
});
|
|
136
|
+
// Yield events as they arrive
|
|
137
|
+
while (true) {
|
|
138
|
+
await waitForItem();
|
|
139
|
+
const item = queue.shift();
|
|
140
|
+
if (item === null || item === undefined) {
|
|
141
|
+
if (error !== null) {
|
|
142
|
+
yield {
|
|
143
|
+
type: 'error',
|
|
144
|
+
content: error.message,
|
|
145
|
+
timestamp: new Date(),
|
|
146
|
+
};
|
|
147
|
+
}
|
|
148
|
+
return;
|
|
149
|
+
}
|
|
150
|
+
yield item;
|
|
151
|
+
}
|
|
152
|
+
}
|
|
153
|
+
supportsFeature(feature) {
|
|
154
|
+
return SUPPORTED_FEATURES.has(feature);
|
|
155
|
+
}
|
|
156
|
+
buildArgs(prompt, options) {
|
|
157
|
+
const args = ['-p', prompt, '--output-format', 'json'];
|
|
158
|
+
if (options?.resumeSession)
|
|
159
|
+
args.push('--resume', options.resumeSession);
|
|
160
|
+
if (options?.model)
|
|
161
|
+
args.push('--model', options.model);
|
|
162
|
+
if (options?.systemPrompt)
|
|
163
|
+
args.push('--append-system-prompt', options.systemPrompt);
|
|
164
|
+
if (options?.allowedTools?.length)
|
|
165
|
+
args.push('--allowedTools', options.allowedTools.join(','));
|
|
166
|
+
if (options?.outputSchema)
|
|
167
|
+
args.push('--json-schema', JSON.stringify(options.outputSchema));
|
|
168
|
+
if (options?.maxTurns)
|
|
169
|
+
args.push('--max-turns', String(options.maxTurns));
|
|
170
|
+
return args;
|
|
171
|
+
}
|
|
172
|
+
buildStreamArgs(prompt, options) {
|
|
173
|
+
const args = this.buildArgs(prompt, options);
|
|
174
|
+
const fmtIdx = args.indexOf('--output-format');
|
|
175
|
+
if (fmtIdx !== -1)
|
|
176
|
+
args[fmtIdx + 1] = 'stream-json';
|
|
177
|
+
// stream-json requires --verbose and --include-partial-messages when using -p (--print)
|
|
178
|
+
// --no-chrome ensures it runs in non-interactive mode without browser integration
|
|
179
|
+
args.push('--verbose', '--include-partial-messages', '--no-chrome');
|
|
180
|
+
return args;
|
|
181
|
+
}
|
|
182
|
+
buildSpawnOptions(options) {
|
|
183
|
+
const spawnOpts = {};
|
|
184
|
+
if (options?.cwd)
|
|
185
|
+
spawnOpts.cwd = options.cwd;
|
|
186
|
+
return spawnOpts;
|
|
187
|
+
}
|
|
188
|
+
parseJsonResult(stdout) {
|
|
189
|
+
const trimmed = stdout.trim();
|
|
190
|
+
try {
|
|
191
|
+
const parsed = JSON.parse(trimmed);
|
|
192
|
+
const result = {
|
|
193
|
+
result: parsed.result ?? trimmed,
|
|
194
|
+
};
|
|
195
|
+
if (parsed.session_id) {
|
|
196
|
+
result.sessionId = parsed.session_id;
|
|
197
|
+
}
|
|
198
|
+
if (parsed.input_tokens !== undefined && parsed.output_tokens !== undefined) {
|
|
199
|
+
result.usage = {
|
|
200
|
+
inputTokens: parsed.input_tokens,
|
|
201
|
+
outputTokens: parsed.output_tokens,
|
|
202
|
+
};
|
|
203
|
+
}
|
|
204
|
+
// Store additional metadata
|
|
205
|
+
const { result: _r, session_id: _s, input_tokens: _it, output_tokens: _ot, ...rest } = parsed;
|
|
206
|
+
if (Object.keys(rest).length > 0) {
|
|
207
|
+
result.metadata = rest;
|
|
208
|
+
}
|
|
209
|
+
return result;
|
|
210
|
+
}
|
|
211
|
+
catch {
|
|
212
|
+
// If stdout is not valid JSON, treat it as raw text result
|
|
213
|
+
return { result: trimmed };
|
|
214
|
+
}
|
|
215
|
+
}
|
|
216
|
+
parseStreamLine(line) {
|
|
217
|
+
try {
|
|
218
|
+
const parsed = JSON.parse(line);
|
|
219
|
+
// Handle Claude Code stream_json format with nested events
|
|
220
|
+
if (parsed.type === 'stream_event' && parsed.event) {
|
|
221
|
+
const { event } = parsed;
|
|
222
|
+
// Extract text deltas for progress
|
|
223
|
+
if (event.type === 'content_block_delta' && event.delta?.text) {
|
|
224
|
+
return {
|
|
225
|
+
type: 'progress',
|
|
226
|
+
content: event.delta.text,
|
|
227
|
+
timestamp: new Date(),
|
|
228
|
+
};
|
|
229
|
+
}
|
|
230
|
+
// Message complete - ignore for now (accumulated text is in progress events)
|
|
231
|
+
if (event.type === 'message_stop') {
|
|
232
|
+
return null;
|
|
233
|
+
}
|
|
234
|
+
}
|
|
235
|
+
// Ignore assistant messages - we already get all text via content_block_delta events
|
|
236
|
+
if (parsed.type === 'assistant') {
|
|
237
|
+
return null;
|
|
238
|
+
}
|
|
239
|
+
// Handle legacy format (backward compatibility)
|
|
240
|
+
if (parsed.type === 'result') {
|
|
241
|
+
return {
|
|
242
|
+
type: 'result',
|
|
243
|
+
content: parsed.result ?? '',
|
|
244
|
+
timestamp: new Date(),
|
|
245
|
+
};
|
|
246
|
+
}
|
|
247
|
+
if (parsed.type === 'error') {
|
|
248
|
+
return {
|
|
249
|
+
type: 'error',
|
|
250
|
+
content: parsed.error ?? parsed.message ?? '',
|
|
251
|
+
timestamp: new Date(),
|
|
252
|
+
};
|
|
253
|
+
}
|
|
254
|
+
// Generic progress for other event types (ensure content is a string)
|
|
255
|
+
if (parsed.content || parsed.message) {
|
|
256
|
+
const rawContent = parsed.content ?? parsed.message;
|
|
257
|
+
const content = typeof rawContent === 'string' ? rawContent : JSON.stringify(rawContent);
|
|
258
|
+
return {
|
|
259
|
+
type: 'progress',
|
|
260
|
+
content,
|
|
261
|
+
timestamp: new Date(),
|
|
262
|
+
};
|
|
263
|
+
}
|
|
264
|
+
return null;
|
|
265
|
+
}
|
|
266
|
+
catch {
|
|
267
|
+
// Non-JSON line, treat as progress text
|
|
268
|
+
return {
|
|
269
|
+
type: 'progress',
|
|
270
|
+
content: line,
|
|
271
|
+
timestamp: new Date(),
|
|
272
|
+
};
|
|
273
|
+
}
|
|
274
|
+
}
|
|
275
|
+
}
|