@multiclawcli/core 0.1.0 → 0.2.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 +16 -0
- package/dist/index.js +1 -1
- package/package.json +10 -1
- package/src/agents/arch-design-reviewer.ts +1 -0
- package/src/agents/architect.ts +31 -1
- package/src/agents/backend-developer.ts +10 -1
- package/src/agents/code-reviewer.ts +1 -0
- package/src/agents/devops.ts +10 -1
- package/src/agents/frontend-developer.ts +10 -1
- package/src/agents/index.ts +2 -0
- package/src/agents/leader.ts +37 -0
- package/src/agents/product-manager.ts +1 -0
- package/src/agents/reviewer.ts +1 -0
- package/src/agents/tester.ts +10 -1
- package/src/agents/ui-design-reviewer.ts +1 -0
- package/src/agents/ui-designer.ts +10 -1
- package/src/index.ts +1 -1
- package/src/orchestrator/AgentRunner.ts +3 -1
- package/src/orchestrator/Orchestrator.ts +80 -4
- package/src/runtime/ClaudeRuntime.ts +1 -0
- package/src/runtime/index.ts +1 -7
- package/src/types/agent.ts +16 -0
- package/src/types/config.ts +2 -0
- package/src/types/event.ts +3 -3
- package/src/types/runtime.ts +1 -0
- package/dist/agents/arch-design-reviewer.d.ts +0 -4
- package/dist/agents/arch-design-reviewer.js +0 -39
- package/dist/agents/arch-design-reviewer.js.map +0 -1
- package/dist/agents/architect.d.ts +0 -4
- package/dist/agents/architect.js +0 -37
- package/dist/agents/architect.js.map +0 -1
- package/dist/agents/backend-developer.d.ts +0 -4
- package/dist/agents/backend-developer.js +0 -40
- package/dist/agents/backend-developer.js.map +0 -1
- package/dist/agents/code-reviewer.d.ts +0 -4
- package/dist/agents/code-reviewer.js +0 -48
- package/dist/agents/code-reviewer.js.map +0 -1
- package/dist/agents/devops.d.ts +0 -4
- package/dist/agents/devops.js +0 -45
- package/dist/agents/devops.js.map +0 -1
- package/dist/agents/frontend-developer.d.ts +0 -4
- package/dist/agents/frontend-developer.js +0 -42
- package/dist/agents/frontend-developer.js.map +0 -1
- package/dist/agents/index.d.ts +0 -24
- package/dist/agents/index.js +0 -25
- package/dist/agents/index.js.map +0 -1
- package/dist/agents/product-manager.d.ts +0 -4
- package/dist/agents/product-manager.js +0 -37
- package/dist/agents/product-manager.js.map +0 -1
- package/dist/agents/reviewer.d.ts +0 -4
- package/dist/agents/reviewer.js +0 -41
- package/dist/agents/reviewer.js.map +0 -1
- package/dist/agents/tester.d.ts +0 -4
- package/dist/agents/tester.js +0 -39
- package/dist/agents/tester.js.map +0 -1
- package/dist/agents/ui-design-reviewer.d.ts +0 -4
- package/dist/agents/ui-design-reviewer.js +0 -42
- package/dist/agents/ui-design-reviewer.js.map +0 -1
- package/dist/agents/ui-designer.d.ts +0 -4
- package/dist/agents/ui-designer.js +0 -47
- package/dist/agents/ui-designer.js.map +0 -1
- package/dist/config/defineConfig.d.ts +0 -2
- package/dist/config/defineConfig.js +0 -4
- package/dist/config/defineConfig.js.map +0 -1
- package/dist/event/EventBus.d.ts +0 -7
- package/dist/event/EventBus.js +0 -21
- package/dist/event/EventBus.js.map +0 -1
- package/dist/index.d.ts +0 -8
- package/dist/index.js.map +0 -1
- package/dist/orchestrator/AgentRunner.d.ts +0 -10
- package/dist/orchestrator/AgentRunner.js +0 -85
- package/dist/orchestrator/AgentRunner.js.map +0 -1
- package/dist/orchestrator/ContextManager.d.ts +0 -7
- package/dist/orchestrator/ContextManager.js +0 -14
- package/dist/orchestrator/ContextManager.js.map +0 -1
- package/dist/orchestrator/Orchestrator.d.ts +0 -12
- package/dist/orchestrator/Orchestrator.js +0 -87
- package/dist/orchestrator/Orchestrator.js.map +0 -1
- package/dist/orchestrator/StageBuilder.d.ts +0 -2
- package/dist/orchestrator/StageBuilder.js +0 -25
- package/dist/orchestrator/StageBuilder.js.map +0 -1
- package/dist/runtime/ClaudeRuntime.d.ts +0 -7
- package/dist/runtime/ClaudeRuntime.js +0 -46
- package/dist/runtime/ClaudeRuntime.js.map +0 -1
- package/dist/runtime/CodexRuntime.d.ts +0 -7
- package/dist/runtime/CodexRuntime.js +0 -55
- package/dist/runtime/CodexRuntime.js.map +0 -1
- package/dist/runtime/CursorRuntime.d.ts +0 -7
- package/dist/runtime/CursorRuntime.js +0 -45
- package/dist/runtime/CursorRuntime.js.map +0 -1
- package/dist/runtime/OpenCodeRuntime.d.ts +0 -7
- package/dist/runtime/OpenCodeRuntime.js +0 -44
- package/dist/runtime/OpenCodeRuntime.js.map +0 -1
- package/dist/runtime/RuntimeBase.d.ts +0 -6
- package/dist/runtime/RuntimeBase.js +0 -3
- package/dist/runtime/RuntimeBase.js.map +0 -1
- package/dist/runtime/index.d.ts +0 -15
- package/dist/runtime/index.js +0 -25
- package/dist/runtime/index.js.map +0 -1
- package/dist/types/agent.d.ts +0 -26
- package/dist/types/agent.js +0 -2
- package/dist/types/agent.js.map +0 -1
- package/dist/types/config.d.ts +0 -22
- package/dist/types/config.js +0 -2
- package/dist/types/config.js.map +0 -1
- package/dist/types/event.d.ts +0 -77
- package/dist/types/event.js +0 -2
- package/dist/types/event.js.map +0 -1
- package/dist/types/index.d.ts +0 -4
- package/dist/types/index.js +0 -5
- package/dist/types/index.js.map +0 -1
- package/dist/types/runtime.d.ts +0 -19
- package/dist/types/runtime.js +0 -2
- package/dist/types/runtime.js.map +0 -1
- package/dist/utils/prompt.d.ts +0 -1
- package/dist/utils/prompt.js +0 -21
- package/dist/utils/prompt.js.map +0 -1
- package/dist/utils/retry.d.ts +0 -2
- package/dist/utils/retry.js +0 -20
- package/dist/utils/retry.js.map +0 -1
- package/dist/utils/timeout.d.ts +0 -1
- package/dist/utils/timeout.js +0 -12
- package/dist/utils/timeout.js.map +0 -1
- package/src/runtime/CodexRuntime.ts +0 -52
- package/src/runtime/CursorRuntime.ts +0 -41
- package/src/runtime/OpenCodeRuntime.ts +0 -40
- package/tsconfig.tsbuildinfo +0 -1
package/README.md
ADDED
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
# @multiclawcli/core
|
|
2
|
+
|
|
3
|
+
[](https://www.npmjs.com/package/@multiclawcli/core)
|
|
4
|
+
[](https://github.com/shipengqi/multiclaw)
|
|
5
|
+
|
|
6
|
+
Core runtime for [multiclaw](https://github.com/shipengqi/multiclaw) — the multi-agent orchestration CLI.
|
|
7
|
+
|
|
8
|
+
This package provides the agent runner, orchestrator, event bus, and runtime abstractions used internally by the `multiclaw` CLI. It is not intended for direct use; install [`multiclaw`](https://www.npmjs.com/package/multiclaw) instead.
|
|
9
|
+
|
|
10
|
+
## Documentation
|
|
11
|
+
|
|
12
|
+
Full documentation is available in the [main repository](https://github.com/shipengqi/multiclaw).
|
|
13
|
+
|
|
14
|
+
## License
|
|
15
|
+
|
|
16
|
+
[MIT](https://github.com/shipengqi/multiclaw/blob/main/LICENSE)
|
package/dist/index.js
CHANGED
|
@@ -2,7 +2,7 @@ export * from "./types";
|
|
|
2
2
|
export { EventBus } from "./event/EventBus";
|
|
3
3
|
export { Orchestrator } from "./orchestrator/Orchestrator";
|
|
4
4
|
export { buildStages } from "./orchestrator/StageBuilder";
|
|
5
|
-
export { runtimeRegistry, ClaudeRuntime
|
|
5
|
+
export { runtimeRegistry, ClaudeRuntime } from "./runtime";
|
|
6
6
|
export { RuntimeBase } from "./runtime/RuntimeBase";
|
|
7
7
|
export { defineConfig } from "./config/defineConfig";
|
|
8
8
|
export { agents } from "./agents";
|
package/package.json
CHANGED
|
@@ -1,9 +1,18 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@multiclawcli/core",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.2.0",
|
|
4
4
|
"type": "module",
|
|
5
5
|
"main": "dist/index.js",
|
|
6
6
|
"types": "dist/index.d.ts",
|
|
7
|
+
"repository": {
|
|
8
|
+
"type": "git",
|
|
9
|
+
"url": "https://github.com/shipengqi/multiclaw.git",
|
|
10
|
+
"directory": "packages/core"
|
|
11
|
+
},
|
|
12
|
+
"homepage": "https://github.com/shipengqi/multiclaw#readme",
|
|
13
|
+
"bugs": {
|
|
14
|
+
"url": "https://github.com/shipengqi/multiclaw/issues"
|
|
15
|
+
},
|
|
7
16
|
"publishConfig": {
|
|
8
17
|
"access": "public"
|
|
9
18
|
},
|
package/src/agents/architect.ts
CHANGED
|
@@ -9,10 +9,32 @@ Responsibilities:
|
|
|
9
9
|
- Review existing code (if any) and propose minimal-change solutions
|
|
10
10
|
- Define module boundaries, interface contracts, and directory structure
|
|
11
11
|
- Provide a clear design foundation for developers and testers
|
|
12
|
+
- Decompose the work into per-agent subtasks based on who is actually in the pipeline
|
|
12
13
|
|
|
13
14
|
Deliverables (save to the working directory):
|
|
14
15
|
- architecture.md — architecture plan (module breakdown, directory structure, technology choices, key component descriptions)
|
|
15
16
|
- api-spec.md — complete API specification (paths, methods, request/response formats, status codes, error handling)
|
|
17
|
+
- task-plan.json — structured task breakdown for all implementation agents in the pipeline (see format below)
|
|
18
|
+
|
|
19
|
+
task-plan.json format:
|
|
20
|
+
{
|
|
21
|
+
"projectName": "<project name>",
|
|
22
|
+
"requirement": "<one-line summary>",
|
|
23
|
+
"tasks": [
|
|
24
|
+
{
|
|
25
|
+
"id": "<agent id exactly as listed in pipelineAgents>",
|
|
26
|
+
"title": "<short task title>",
|
|
27
|
+
"scope": "<concrete description of what this agent should build or produce>",
|
|
28
|
+
"dependsOn": ["<other agent id>"]
|
|
29
|
+
}
|
|
30
|
+
]
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
Rules for task-plan.json:
|
|
34
|
+
- Only create tasks for implementation agents (those that produce code, designs, or infrastructure). Skip review agents (code-reviewer, arch-design-reviewer, ui-design-reviewer, reviewer) and planning agents (product-manager, architect, leader).
|
|
35
|
+
- Use the exact agent id from pipelineAgents as the task id.
|
|
36
|
+
- If an agent is not in pipelineAgents, do not create a task for it.
|
|
37
|
+
- dependsOn references other task ids, not agent names.
|
|
16
38
|
|
|
17
39
|
Principles: Execute tasks directly without asking for confirmation. If information is missing, mark the file with BLOCKED and describe what is needed. Do not change the requirement scope. Do not write business feature code. Do not refactor beyond the task scope.`
|
|
18
40
|
|
|
@@ -22,10 +44,17 @@ const TASK = `## Project
|
|
|
22
44
|
## Requirement
|
|
23
45
|
{{requirement}}
|
|
24
46
|
|
|
47
|
+
## Pipeline Agents
|
|
48
|
+
The following agents will run in this pipeline (id: name):
|
|
49
|
+
{{pipelineAgents}}
|
|
50
|
+
|
|
25
51
|
## Task
|
|
26
|
-
Analyze the requirement and create
|
|
52
|
+
Analyze the requirement and create three files in the current directory:
|
|
27
53
|
1. architecture.md — architecture plan (module breakdown, directory structure, technology choices, key component descriptions, affected scope)
|
|
28
54
|
2. api-spec.md — complete API specification (paths, methods, request parameters, response formats, status codes, error handling)
|
|
55
|
+
3. task-plan.json — task breakdown for each implementation agent listed in the pipeline above
|
|
56
|
+
|
|
57
|
+
For task-plan.json: create one task per implementation agent (skip reviewers and planners). Each task's scope should be concrete enough that the agent knows exactly what to build without ambiguity. Set dependsOn to reflect actual execution order constraints (e.g. devops depends on backend and frontend).
|
|
29
58
|
|
|
30
59
|
Create the files directly. No extra output.`
|
|
31
60
|
|
|
@@ -34,6 +63,7 @@ export function architect(overrides?: Overrides): AgentDefinition {
|
|
|
34
63
|
id: "architect",
|
|
35
64
|
name: "Architect",
|
|
36
65
|
icon: "◆",
|
|
66
|
+
models: { claude: "opus" },
|
|
37
67
|
systemPrompt: SYSTEM,
|
|
38
68
|
taskPrompt: TASK,
|
|
39
69
|
tools: ["Read", "Write"],
|
|
@@ -16,7 +16,15 @@ Deliverables (write code to the working directory, and record in implementation-
|
|
|
16
16
|
|
|
17
17
|
Principles: Write code directly without asking for confirmation. Follow the API spec strictly — do not change the contract unilaterally; escalate contract issues upstream. Do not refactor unrelated code. Run commands and report evidence.`
|
|
18
18
|
|
|
19
|
-
const TASK = `##
|
|
19
|
+
const TASK = `## Task Scope
|
|
20
|
+
{{file:task-plan.json}}
|
|
21
|
+
|
|
22
|
+
Find the entry where id == "backend-developer" and treat its scope as the primary guide for your work.
|
|
23
|
+
If task-plan.json is not found, determine your scope from the architecture design and API specification below.
|
|
24
|
+
|
|
25
|
+
---
|
|
26
|
+
|
|
27
|
+
## Architecture Design
|
|
20
28
|
{{file:architecture.md}}
|
|
21
29
|
|
|
22
30
|
## API Specification
|
|
@@ -37,6 +45,7 @@ export function backendDeveloper(overrides?: Overrides): AgentDefinition {
|
|
|
37
45
|
id: "backend-developer",
|
|
38
46
|
name: "Backend Developer",
|
|
39
47
|
icon: "⊕",
|
|
48
|
+
models: { claude: "sonnet" },
|
|
40
49
|
systemPrompt: SYSTEM,
|
|
41
50
|
taskPrompt: TASK,
|
|
42
51
|
tools: ["Read", "Write", "Bash"],
|
package/src/agents/devops.ts
CHANGED
|
@@ -21,7 +21,15 @@ Deliverables (save to the working directory):
|
|
|
21
21
|
|
|
22
22
|
Principles: Follow security best practices (non-root user, minimal base image, no secrets in image). Make CI fail fast. Document every non-obvious decision in devops-notes.md.`
|
|
23
23
|
|
|
24
|
-
const TASK = `##
|
|
24
|
+
const TASK = `## Task Scope
|
|
25
|
+
{{file:task-plan.json}}
|
|
26
|
+
|
|
27
|
+
Find the entry where id == "devops" and treat its scope as the primary guide for your work.
|
|
28
|
+
If task-plan.json is not found, determine your scope from the architecture design below.
|
|
29
|
+
|
|
30
|
+
---
|
|
31
|
+
|
|
32
|
+
## Project
|
|
25
33
|
{{projectName}}
|
|
26
34
|
|
|
27
35
|
## Architecture Design
|
|
@@ -42,6 +50,7 @@ export function devops(overrides?: Overrides): AgentDefinition {
|
|
|
42
50
|
id: "devops",
|
|
43
51
|
name: "DevOps",
|
|
44
52
|
icon: "▶",
|
|
53
|
+
models: { claude: "sonnet" },
|
|
45
54
|
systemPrompt: SYSTEM,
|
|
46
55
|
taskPrompt: TASK,
|
|
47
56
|
tools: ["Read", "Write"],
|
|
@@ -13,7 +13,15 @@ Deliverables (write code to the working directory, and record results in impleme
|
|
|
13
13
|
|
|
14
14
|
Principles: Write code directly without asking for confirmation. Do not change the API contract — escalate contract issues upstream. Do not refactor unrelated code. Run commands and report evidence.`
|
|
15
15
|
|
|
16
|
-
const TASK = `##
|
|
16
|
+
const TASK = `## Task Scope
|
|
17
|
+
{{file:task-plan.json}}
|
|
18
|
+
|
|
19
|
+
Find the entry where id == "frontend-developer" and treat its scope as the primary guide for your work.
|
|
20
|
+
If task-plan.json is not found, determine your scope from the UI design specification and architecture design below.
|
|
21
|
+
|
|
22
|
+
---
|
|
23
|
+
|
|
24
|
+
## UI Design Specification
|
|
17
25
|
{{file:ui-design.md}}
|
|
18
26
|
|
|
19
27
|
## Architecture Design
|
|
@@ -39,6 +47,7 @@ export function frontendDeveloper(overrides?: Overrides): AgentDefinition {
|
|
|
39
47
|
id: "frontend-developer",
|
|
40
48
|
name: "Frontend Developer",
|
|
41
49
|
icon: "◇",
|
|
50
|
+
models: { claude: "sonnet" },
|
|
42
51
|
systemPrompt: SYSTEM,
|
|
43
52
|
taskPrompt: TASK,
|
|
44
53
|
tools: ["Read", "Write", "Bash"],
|
package/src/agents/index.ts
CHANGED
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import { leader } from "./leader"
|
|
1
2
|
import { architect } from "./architect"
|
|
2
3
|
import { productManager } from "./product-manager"
|
|
3
4
|
import { backendDeveloper } from "./backend-developer"
|
|
@@ -11,6 +12,7 @@ import { codeReviewer } from "./code-reviewer"
|
|
|
11
12
|
import { devops } from "./devops"
|
|
12
13
|
|
|
13
14
|
export const agents = {
|
|
15
|
+
leader,
|
|
14
16
|
architect,
|
|
15
17
|
productManager,
|
|
16
18
|
backendDeveloper,
|
|
@@ -0,0 +1,37 @@
|
|
|
1
|
+
import type { AgentDefinition } from "../types/agent"
|
|
2
|
+
|
|
3
|
+
type Overrides = Partial<AgentDefinition>
|
|
4
|
+
|
|
5
|
+
const SYSTEM = `You are the project leader. Analyze the requirement and the current state of the codebase, then decide the minimum set of agents needed to complete the task.
|
|
6
|
+
|
|
7
|
+
Do not apply fixed rules — use your judgment based on the actual requirement and code. A minor bug fix may need only a developer and code-reviewer; a complex new feature may need the full pipeline. Read the code to understand the impact before deciding.
|
|
8
|
+
|
|
9
|
+
Output ONLY a single JSON object on its own line — no prose, no markdown fences:
|
|
10
|
+
{"run": ["agent-id-1", "agent-id-2"]}`
|
|
11
|
+
|
|
12
|
+
const TASK = `## Project
|
|
13
|
+
{{projectName}}
|
|
14
|
+
|
|
15
|
+
## Requirement
|
|
16
|
+
{{requirement}}
|
|
17
|
+
|
|
18
|
+
## Available Agents
|
|
19
|
+
{{availableAgents}}
|
|
20
|
+
|
|
21
|
+
## Task
|
|
22
|
+
Read the codebase to understand the current state, then decide which agents to run.
|
|
23
|
+
Output a single JSON object: {"run": ["agent-id-1", ...]}
|
|
24
|
+
Agent IDs must come from the Available Agents list above.`
|
|
25
|
+
|
|
26
|
+
export function leader(overrides?: Overrides): AgentDefinition {
|
|
27
|
+
return {
|
|
28
|
+
id: "leader",
|
|
29
|
+
name: "Leader",
|
|
30
|
+
icon: "★",
|
|
31
|
+
models: { claude: "sonnet" },
|
|
32
|
+
systemPrompt: SYSTEM,
|
|
33
|
+
taskPrompt: TASK,
|
|
34
|
+
tools: ["Read", "Bash"],
|
|
35
|
+
...overrides,
|
|
36
|
+
}
|
|
37
|
+
}
|
package/src/agents/reviewer.ts
CHANGED
package/src/agents/tester.ts
CHANGED
|
@@ -14,7 +14,15 @@ Deliverables (save to the working directory):
|
|
|
14
14
|
|
|
15
15
|
Principles: Do not PASS just because the code compiles or because a developer says it is fine. Every core feature must be verified with actual execution. When BLOCKED, state exactly what is missing.`
|
|
16
16
|
|
|
17
|
-
const TASK = `##
|
|
17
|
+
const TASK = `## Task Scope
|
|
18
|
+
{{file:task-plan.json}}
|
|
19
|
+
|
|
20
|
+
Find the entry where id == "tester" and treat its scope as the primary guide for what features to verify.
|
|
21
|
+
If task-plan.json is not found, verify all features described in the requirement below.
|
|
22
|
+
|
|
23
|
+
---
|
|
24
|
+
|
|
25
|
+
## Project
|
|
18
26
|
{{projectName}}
|
|
19
27
|
|
|
20
28
|
## Requirement
|
|
@@ -36,6 +44,7 @@ export function tester(overrides?: Overrides): AgentDefinition {
|
|
|
36
44
|
id: "tester",
|
|
37
45
|
name: "Tester",
|
|
38
46
|
icon: "⊙",
|
|
47
|
+
models: { claude: "sonnet" },
|
|
39
48
|
systemPrompt: SYSTEM,
|
|
40
49
|
taskPrompt: TASK,
|
|
41
50
|
tools: ["Read", "Write", "Bash"],
|
|
@@ -17,7 +17,15 @@ Deliverables (save to the working directory):
|
|
|
17
17
|
|
|
18
18
|
Principles: Be specific enough that a developer can implement without guessing. Every component gets a name, purpose, props/variants, and states. Flag anything that depends on backend data.`
|
|
19
19
|
|
|
20
|
-
const TASK = `##
|
|
20
|
+
const TASK = `## Task Scope
|
|
21
|
+
{{file:task-plan.json}}
|
|
22
|
+
|
|
23
|
+
Find the entry where id == "ui-designer" and treat its scope as the primary guide for your work.
|
|
24
|
+
If task-plan.json is not found, determine your scope from the architecture design and API specification below.
|
|
25
|
+
|
|
26
|
+
---
|
|
27
|
+
|
|
28
|
+
## Project
|
|
21
29
|
{{projectName}}
|
|
22
30
|
|
|
23
31
|
## Requirement
|
|
@@ -44,6 +52,7 @@ export function uiDesigner(overrides?: Overrides): AgentDefinition {
|
|
|
44
52
|
id: "ui-designer",
|
|
45
53
|
name: "UI Designer",
|
|
46
54
|
icon: "▣",
|
|
55
|
+
models: { claude: "sonnet" },
|
|
47
56
|
systemPrompt: SYSTEM,
|
|
48
57
|
taskPrompt: TASK,
|
|
49
58
|
tools: ["Read", "Write"],
|
package/src/index.ts
CHANGED
|
@@ -2,7 +2,7 @@ export * from "./types"
|
|
|
2
2
|
export { EventBus } from "./event/EventBus"
|
|
3
3
|
export { Orchestrator } from "./orchestrator/Orchestrator"
|
|
4
4
|
export { buildStages } from "./orchestrator/StageBuilder"
|
|
5
|
-
export { runtimeRegistry, ClaudeRuntime
|
|
5
|
+
export { runtimeRegistry, ClaudeRuntime } from "./runtime"
|
|
6
6
|
export { RuntimeBase } from "./runtime/RuntimeBase"
|
|
7
7
|
export { defineConfig } from "./config/defineConfig"
|
|
8
8
|
export { agents } from "./agents"
|
|
@@ -26,11 +26,12 @@ export class AgentRunner {
|
|
|
26
26
|
const retries = agent.retries ?? 0
|
|
27
27
|
const timeout = agent.timeout ?? 600_000
|
|
28
28
|
const tools = agent.tools ?? ["Read", "Write", "Bash"]
|
|
29
|
+
const model = agent.model ?? agent.models?.[agent.runtime ?? "claude"]
|
|
29
30
|
|
|
30
31
|
this.eventBus.emit({
|
|
31
32
|
type: "agent:start",
|
|
32
33
|
timestamp: new Date().toISOString(),
|
|
33
|
-
payload: { agentId: agent.id, agentName: agent.name, icon: agent.icon },
|
|
34
|
+
payload: { agentId: agent.id, agentName: agent.name, icon: agent.icon, model, taskTitle: agent.taskTitle },
|
|
34
35
|
})
|
|
35
36
|
|
|
36
37
|
let attempts = 0
|
|
@@ -49,6 +50,7 @@ export class AgentRunner {
|
|
|
49
50
|
agentId: agent.id,
|
|
50
51
|
systemPrompt: agent.systemPrompt,
|
|
51
52
|
prompt, tools, workDir, timeout, signal,
|
|
53
|
+
model,
|
|
52
54
|
onOutput: (chunk) => {
|
|
53
55
|
this.eventBus.emit({
|
|
54
56
|
type: "agent:output",
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import * as fs from "fs"
|
|
2
2
|
import * as path from "path"
|
|
3
3
|
import type { MultiClawConfig, OrchestratorResult } from "../types/config"
|
|
4
|
-
import type { AgentDefinition, AgentResult } from "../types/agent"
|
|
4
|
+
import type { AgentDefinition, AgentResult, TaskPlan } from "../types/agent"
|
|
5
5
|
import type { StageInfo } from "../types/event"
|
|
6
6
|
import { EventBus } from "../event/EventBus"
|
|
7
7
|
import { ContextManager } from "./ContextManager"
|
|
@@ -23,17 +23,27 @@ export class Orchestrator {
|
|
|
23
23
|
|
|
24
24
|
async run(): Promise<OrchestratorResult> {
|
|
25
25
|
const startTime = new Date()
|
|
26
|
-
const
|
|
26
|
+
const agents = await this.resolveAgents()
|
|
27
|
+
this.contextManager.set(
|
|
28
|
+
"pipelineAgents",
|
|
29
|
+
agents.map((a) => `${a.id}: ${a.name}`).join("\n")
|
|
30
|
+
)
|
|
31
|
+
|
|
32
|
+
let stages = buildStages(agents)
|
|
33
|
+
|
|
34
|
+
const getModel = (agent: AgentDefinition): string | undefined => {
|
|
35
|
+
return agent.model ?? agent.models?.[agent.runtime ?? "claude"]
|
|
36
|
+
}
|
|
27
37
|
|
|
28
38
|
const stageInfos: StageInfo[] = stages.map((stage, i) => ({
|
|
29
39
|
stageIndex: i,
|
|
30
|
-
agents: stage.map((a) => ({ id: a.id, name: a.name, icon: a.icon })),
|
|
40
|
+
agents: stage.map((a) => ({ id: a.id, name: a.name, icon: a.icon, model: getModel(a), taskTitle: a.taskTitle })),
|
|
31
41
|
}))
|
|
32
42
|
|
|
33
43
|
this.eventBus.emit({
|
|
34
44
|
type: "orchestration:start",
|
|
35
45
|
timestamp: new Date().toISOString(),
|
|
36
|
-
payload: { name: this.config.name,
|
|
46
|
+
payload: { name: this.config.name, requirement: this.config.context?.requirement, totalAgents: agents.length, stages: stageInfos },
|
|
37
47
|
})
|
|
38
48
|
|
|
39
49
|
const results: AgentResult[] = []
|
|
@@ -41,6 +51,7 @@ export class Orchestrator {
|
|
|
41
51
|
|
|
42
52
|
for (let i = 0; i < stages.length; i++) {
|
|
43
53
|
const stage = stages[i]
|
|
54
|
+
|
|
44
55
|
this.eventBus.emit({
|
|
45
56
|
type: "stage:start", timestamp: new Date().toISOString(),
|
|
46
57
|
payload: { stageIndex: i, agentIds: stage.map((a) => a.id) },
|
|
@@ -49,6 +60,12 @@ export class Orchestrator {
|
|
|
49
60
|
const stageResults = await this.runStage(stage)
|
|
50
61
|
results.push(...stageResults)
|
|
51
62
|
|
|
63
|
+
// After architect stage completes, apply task plan and rebuild stages
|
|
64
|
+
if (i === 0 && stage.some((a) => a.id === "architect") && stageResults.some((r) => r.status === "success")) {
|
|
65
|
+
await this.applyTaskPlan(agents)
|
|
66
|
+
stages = buildStages(agents)
|
|
67
|
+
}
|
|
68
|
+
|
|
52
69
|
for (const r of stageResults) {
|
|
53
70
|
if (r.status !== "success") {
|
|
54
71
|
allSuccess = false
|
|
@@ -89,6 +106,44 @@ export class Orchestrator {
|
|
|
89
106
|
return result
|
|
90
107
|
}
|
|
91
108
|
|
|
109
|
+
private async resolveAgents(): Promise<AgentDefinition[]> {
|
|
110
|
+
if (!this.config.leader || this.config.useLeader === false) return this.config.agents
|
|
111
|
+
|
|
112
|
+
this.contextManager.set(
|
|
113
|
+
"availableAgents",
|
|
114
|
+
this.config.agents.map((a) => `${a.id}: ${a.name}`).join("\n")
|
|
115
|
+
)
|
|
116
|
+
|
|
117
|
+
const result = await this.runner.run(this.config.leader)
|
|
118
|
+
if (result.status !== "success") return this.config.agents
|
|
119
|
+
|
|
120
|
+
const match = result.output.match(/\{[\s\S]*?"run"\s*:\s*\[[\s\S]*?\]\s*\}/)
|
|
121
|
+
if (!match) return this.config.agents
|
|
122
|
+
|
|
123
|
+
let plan: { run: string[] }
|
|
124
|
+
try { plan = JSON.parse(match[0]) } catch { return this.config.agents }
|
|
125
|
+
|
|
126
|
+
const runSet = new Set(plan.run)
|
|
127
|
+
const skippedIds = new Set(
|
|
128
|
+
this.config.agents.filter((a) => !runSet.has(a.id)).map((a) => a.id)
|
|
129
|
+
)
|
|
130
|
+
|
|
131
|
+
for (const agent of this.config.agents.filter((a) => skippedIds.has(a.id))) {
|
|
132
|
+
this.eventBus.emit({
|
|
133
|
+
type: "agent:skipped",
|
|
134
|
+
timestamp: new Date().toISOString(),
|
|
135
|
+
payload: { agentId: agent.id, agentName: agent.name, icon: agent.icon },
|
|
136
|
+
})
|
|
137
|
+
}
|
|
138
|
+
|
|
139
|
+
return this.config.agents
|
|
140
|
+
.filter((a) => runSet.has(a.id))
|
|
141
|
+
.map((a) => ({
|
|
142
|
+
...a,
|
|
143
|
+
dependsOn: a.dependsOn?.filter((dep) => !skippedIds.has(dep)),
|
|
144
|
+
}))
|
|
145
|
+
}
|
|
146
|
+
|
|
92
147
|
private async runStage(agents: AgentDefinition[]): Promise<AgentResult[]> {
|
|
93
148
|
const { maxConcurrency } = this.config
|
|
94
149
|
if (!maxConcurrency || agents.length <= maxConcurrency) {
|
|
@@ -101,4 +156,25 @@ export class Orchestrator {
|
|
|
101
156
|
}
|
|
102
157
|
return results
|
|
103
158
|
}
|
|
159
|
+
|
|
160
|
+
private async applyTaskPlan(agents: AgentDefinition[]): Promise<void> {
|
|
161
|
+
try {
|
|
162
|
+
const taskPlanPath = path.join(this.workDir, "task-plan.json")
|
|
163
|
+
if (!fs.existsSync(taskPlanPath)) return
|
|
164
|
+
|
|
165
|
+
const content = fs.readFileSync(taskPlanPath, "utf-8")
|
|
166
|
+
const taskPlan: TaskPlan = JSON.parse(content)
|
|
167
|
+
|
|
168
|
+
const taskMap = new Map(taskPlan.tasks.map((t) => [t.id, t]))
|
|
169
|
+
for (const agent of agents) {
|
|
170
|
+
const task = taskMap.get(agent.id)
|
|
171
|
+
if (task) {
|
|
172
|
+
agent.taskTitle = task.title
|
|
173
|
+
agent.dependsOn = task.dependsOn
|
|
174
|
+
}
|
|
175
|
+
}
|
|
176
|
+
} catch {
|
|
177
|
+
// Silently ignore parsing errors
|
|
178
|
+
}
|
|
179
|
+
}
|
|
104
180
|
}
|
|
@@ -16,6 +16,7 @@ export class ClaudeRuntime extends RuntimeBase {
|
|
|
16
16
|
"--allowedTools", task.tools.join(","),
|
|
17
17
|
]
|
|
18
18
|
if (task.systemPrompt) args.push("--system-prompt", task.systemPrompt)
|
|
19
|
+
if (task.model) args.push("--model", task.model)
|
|
19
20
|
|
|
20
21
|
return new Promise((resolve, reject) => {
|
|
21
22
|
const child = spawn("claude", args, { cwd: task.workDir, env: process.env })
|
package/src/runtime/index.ts
CHANGED
|
@@ -1,16 +1,10 @@
|
|
|
1
1
|
import type { AgentRuntime } from "../types/runtime"
|
|
2
2
|
import { ClaudeRuntime } from "./ClaudeRuntime"
|
|
3
|
-
import { CodexRuntime } from "./CodexRuntime"
|
|
4
|
-
import { OpenCodeRuntime } from "./OpenCodeRuntime"
|
|
5
|
-
import { CursorRuntime } from "./CursorRuntime"
|
|
6
3
|
|
|
7
4
|
class RuntimeRegistry {
|
|
8
5
|
private runtimes = new Map<string, AgentRuntime>()
|
|
9
6
|
constructor() {
|
|
10
7
|
this.register(new ClaudeRuntime())
|
|
11
|
-
this.register(new CodexRuntime())
|
|
12
|
-
this.register(new OpenCodeRuntime())
|
|
13
|
-
this.register(new CursorRuntime())
|
|
14
8
|
}
|
|
15
9
|
register(r: AgentRuntime) { this.runtimes.set(r.name, r) }
|
|
16
10
|
get(name: string): AgentRuntime {
|
|
@@ -23,4 +17,4 @@ class RuntimeRegistry {
|
|
|
23
17
|
}
|
|
24
18
|
|
|
25
19
|
export const runtimeRegistry = new RuntimeRegistry()
|
|
26
|
-
export { ClaudeRuntime
|
|
20
|
+
export { ClaudeRuntime }
|
package/src/types/agent.ts
CHANGED
|
@@ -7,8 +7,11 @@ export interface AgentDefinition {
|
|
|
7
7
|
name: string
|
|
8
8
|
icon?: string
|
|
9
9
|
runtime?: string
|
|
10
|
+
model?: string
|
|
11
|
+
models?: Partial<Record<string, string>>
|
|
10
12
|
systemPrompt: string
|
|
11
13
|
taskPrompt: string
|
|
14
|
+
taskTitle?: string
|
|
12
15
|
tools?: ToolName[]
|
|
13
16
|
dependsOn?: string[]
|
|
14
17
|
timeout?: number
|
|
@@ -30,3 +33,16 @@ export interface AgentResult {
|
|
|
30
33
|
startTime: string
|
|
31
34
|
endTime: string
|
|
32
35
|
}
|
|
36
|
+
|
|
37
|
+
export interface SubTask {
|
|
38
|
+
id: string // matches AgentDefinition.id
|
|
39
|
+
title: string
|
|
40
|
+
scope: string
|
|
41
|
+
dependsOn?: string[]
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
export interface TaskPlan {
|
|
45
|
+
projectName: string
|
|
46
|
+
requirement: string
|
|
47
|
+
tasks: SubTask[]
|
|
48
|
+
}
|
package/src/types/config.ts
CHANGED
|
@@ -3,11 +3,13 @@ import type { AgentDefinition } from "./agent"
|
|
|
3
3
|
export interface MultiClawConfig {
|
|
4
4
|
name: string
|
|
5
5
|
workDir: string
|
|
6
|
+
leader?: AgentDefinition
|
|
6
7
|
agents: AgentDefinition[]
|
|
7
8
|
context?: Record<string, string>
|
|
8
9
|
logDir?: string
|
|
9
10
|
continueOnError?: boolean
|
|
10
11
|
maxConcurrency?: number
|
|
12
|
+
useLeader?: boolean
|
|
11
13
|
dashboard?: {
|
|
12
14
|
port?: number
|
|
13
15
|
autoOpen?: boolean
|
package/src/types/event.ts
CHANGED
|
@@ -2,15 +2,15 @@ import type { AgentResult, OrchestratorResult } from "./index"
|
|
|
2
2
|
|
|
3
3
|
export interface StageInfo {
|
|
4
4
|
stageIndex: number
|
|
5
|
-
agents: Array<{ id: string; name: string; icon?: string }>
|
|
5
|
+
agents: Array<{ id: string; name: string; icon?: string; model?: string; taskTitle?: string }>
|
|
6
6
|
}
|
|
7
7
|
|
|
8
8
|
export type MultiClawEvent =
|
|
9
|
-
| { type: "orchestration:start"; timestamp: string; payload: { name: string; totalAgents: number; stages: StageInfo[] } }
|
|
9
|
+
| { type: "orchestration:start"; timestamp: string; payload: { name: string; requirement?: string; totalAgents: number; stages: StageInfo[] } }
|
|
10
10
|
| { type: "orchestration:complete"; timestamp: string; payload: OrchestratorResult }
|
|
11
11
|
| { type: "stage:start"; timestamp: string; payload: { stageIndex: number; agentIds: string[] } }
|
|
12
12
|
| { type: "stage:complete"; timestamp: string; payload: { stageIndex: number } }
|
|
13
|
-
| { type: "agent:start"; timestamp: string; payload: { agentId: string; agentName: string; icon?: string } }
|
|
13
|
+
| { type: "agent:start"; timestamp: string; payload: { agentId: string; agentName: string; icon?: string; model?: string; taskTitle?: string } }
|
|
14
14
|
| { type: "agent:output"; timestamp: string; payload: { agentId: string; chunk: string } }
|
|
15
15
|
| { type: "agent:complete"; timestamp: string; payload: AgentResult }
|
|
16
16
|
| { type: "agent:failed"; timestamp: string; payload: AgentResult }
|
package/src/types/runtime.ts
CHANGED
|
@@ -1,39 +0,0 @@
|
|
|
1
|
-
const SYSTEM = `You are an architecture design reviewer. Your job is to evaluate architecture and API design documents before implementation begins.
|
|
2
|
-
|
|
3
|
-
Responsibilities:
|
|
4
|
-
- Review architecture design for completeness, consistency, and technical soundness
|
|
5
|
-
- Review API specifications for clarity, correctness, and REST/contract conventions
|
|
6
|
-
- Identify ambiguities, missing edge cases, or risky design decisions
|
|
7
|
-
- Do not write code, do not implement — provide only design-level feedback
|
|
8
|
-
|
|
9
|
-
Deliverables (save to the working directory):
|
|
10
|
-
- arch-review.md — verdict (Approved / Changes Required), issue list (blocking / advisory) with specific locations and suggested fixes, overall assessment
|
|
11
|
-
|
|
12
|
-
Principles: Be precise — point to specific sections. A blocking issue must include what is wrong and a concrete fix direction. If the design is sound, say so directly. Do not approve with vague praise.`;
|
|
13
|
-
const TASK = `## Architecture Design
|
|
14
|
-
{{file:architecture.md}}
|
|
15
|
-
|
|
16
|
-
## API Specification
|
|
17
|
-
{{file:api-spec.md}}
|
|
18
|
-
|
|
19
|
-
## Task
|
|
20
|
-
Review the architecture design and API specification above. Output arch-review.md:
|
|
21
|
-
1. Overall verdict: Approved / Changes Required
|
|
22
|
-
2. Blocking issues (must be fixed before implementation): each with location, problem, and fix direction
|
|
23
|
-
3. Advisory issues (should fix but not blocking): each with location and suggestion
|
|
24
|
-
4. Design strengths worth noting
|
|
25
|
-
5. Final summary (1–2 sentences)
|
|
26
|
-
|
|
27
|
-
Be specific. Reference section names or endpoint paths when citing issues.`;
|
|
28
|
-
export function archDesignReviewer(overrides) {
|
|
29
|
-
return {
|
|
30
|
-
id: "arch-design-reviewer",
|
|
31
|
-
name: "Arch Design Reviewer",
|
|
32
|
-
icon: "△",
|
|
33
|
-
systemPrompt: SYSTEM,
|
|
34
|
-
taskPrompt: TASK,
|
|
35
|
-
tools: ["Read", "Write"],
|
|
36
|
-
...overrides,
|
|
37
|
-
};
|
|
38
|
-
}
|
|
39
|
-
//# sourceMappingURL=arch-design-reviewer.js.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"arch-design-reviewer.js","sourceRoot":"","sources":["../../src/agents/arch-design-reviewer.ts"],"names":[],"mappings":"AAIA,MAAM,MAAM,GAAG;;;;;;;;;;;0MAW2L,CAAA;AAE1M,MAAM,IAAI,GAAG;;;;;;;;;;;;;;2EAc8D,CAAA;AAE3E,MAAM,UAAU,kBAAkB,CAAC,SAAqB;IACtD,OAAO;QACL,EAAE,EAAE,sBAAsB;QAC1B,IAAI,EAAE,sBAAsB;QAC5B,IAAI,EAAE,GAAG;QACT,YAAY,EAAE,MAAM;QACpB,UAAU,EAAE,IAAI;QAChB,KAAK,EAAE,CAAC,MAAM,EAAE,OAAO,CAAC;QACxB,GAAG,SAAS;KACb,CAAA;AACH,CAAC"}
|