@multiclawcli/core 0.1.0 → 0.3.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.
Files changed (127) hide show
  1. package/README.md +16 -0
  2. package/dist/index.js +1 -1
  3. package/package.json +10 -1
  4. package/src/agents/arch-design-reviewer.ts +1 -0
  5. package/src/agents/architect.ts +31 -1
  6. package/src/agents/backend-developer.ts +10 -1
  7. package/src/agents/code-reviewer.ts +1 -0
  8. package/src/agents/devops.ts +10 -1
  9. package/src/agents/frontend-developer.ts +10 -1
  10. package/src/agents/index.ts +2 -0
  11. package/src/agents/leader.ts +37 -0
  12. package/src/agents/product-manager.ts +1 -0
  13. package/src/agents/reviewer.ts +1 -0
  14. package/src/agents/tester.ts +10 -1
  15. package/src/agents/ui-design-reviewer.ts +1 -0
  16. package/src/agents/ui-designer.ts +10 -1
  17. package/src/index.ts +1 -1
  18. package/src/orchestrator/AgentRunner.ts +3 -1
  19. package/src/orchestrator/Orchestrator.ts +80 -4
  20. package/src/runtime/ClaudeRuntime.ts +1 -0
  21. package/src/runtime/index.ts +1 -7
  22. package/src/types/agent.ts +16 -0
  23. package/src/types/config.ts +2 -0
  24. package/src/types/event.ts +3 -3
  25. package/src/types/runtime.ts +1 -0
  26. package/dist/agents/arch-design-reviewer.d.ts +0 -4
  27. package/dist/agents/arch-design-reviewer.js +0 -39
  28. package/dist/agents/arch-design-reviewer.js.map +0 -1
  29. package/dist/agents/architect.d.ts +0 -4
  30. package/dist/agents/architect.js +0 -37
  31. package/dist/agents/architect.js.map +0 -1
  32. package/dist/agents/backend-developer.d.ts +0 -4
  33. package/dist/agents/backend-developer.js +0 -40
  34. package/dist/agents/backend-developer.js.map +0 -1
  35. package/dist/agents/code-reviewer.d.ts +0 -4
  36. package/dist/agents/code-reviewer.js +0 -48
  37. package/dist/agents/code-reviewer.js.map +0 -1
  38. package/dist/agents/devops.d.ts +0 -4
  39. package/dist/agents/devops.js +0 -45
  40. package/dist/agents/devops.js.map +0 -1
  41. package/dist/agents/frontend-developer.d.ts +0 -4
  42. package/dist/agents/frontend-developer.js +0 -42
  43. package/dist/agents/frontend-developer.js.map +0 -1
  44. package/dist/agents/index.d.ts +0 -24
  45. package/dist/agents/index.js +0 -25
  46. package/dist/agents/index.js.map +0 -1
  47. package/dist/agents/product-manager.d.ts +0 -4
  48. package/dist/agents/product-manager.js +0 -37
  49. package/dist/agents/product-manager.js.map +0 -1
  50. package/dist/agents/reviewer.d.ts +0 -4
  51. package/dist/agents/reviewer.js +0 -41
  52. package/dist/agents/reviewer.js.map +0 -1
  53. package/dist/agents/tester.d.ts +0 -4
  54. package/dist/agents/tester.js +0 -39
  55. package/dist/agents/tester.js.map +0 -1
  56. package/dist/agents/ui-design-reviewer.d.ts +0 -4
  57. package/dist/agents/ui-design-reviewer.js +0 -42
  58. package/dist/agents/ui-design-reviewer.js.map +0 -1
  59. package/dist/agents/ui-designer.d.ts +0 -4
  60. package/dist/agents/ui-designer.js +0 -47
  61. package/dist/agents/ui-designer.js.map +0 -1
  62. package/dist/config/defineConfig.d.ts +0 -2
  63. package/dist/config/defineConfig.js +0 -4
  64. package/dist/config/defineConfig.js.map +0 -1
  65. package/dist/event/EventBus.d.ts +0 -7
  66. package/dist/event/EventBus.js +0 -21
  67. package/dist/event/EventBus.js.map +0 -1
  68. package/dist/index.d.ts +0 -8
  69. package/dist/index.js.map +0 -1
  70. package/dist/orchestrator/AgentRunner.d.ts +0 -10
  71. package/dist/orchestrator/AgentRunner.js +0 -85
  72. package/dist/orchestrator/AgentRunner.js.map +0 -1
  73. package/dist/orchestrator/ContextManager.d.ts +0 -7
  74. package/dist/orchestrator/ContextManager.js +0 -14
  75. package/dist/orchestrator/ContextManager.js.map +0 -1
  76. package/dist/orchestrator/Orchestrator.d.ts +0 -12
  77. package/dist/orchestrator/Orchestrator.js +0 -87
  78. package/dist/orchestrator/Orchestrator.js.map +0 -1
  79. package/dist/orchestrator/StageBuilder.d.ts +0 -2
  80. package/dist/orchestrator/StageBuilder.js +0 -25
  81. package/dist/orchestrator/StageBuilder.js.map +0 -1
  82. package/dist/runtime/ClaudeRuntime.d.ts +0 -7
  83. package/dist/runtime/ClaudeRuntime.js +0 -46
  84. package/dist/runtime/ClaudeRuntime.js.map +0 -1
  85. package/dist/runtime/CodexRuntime.d.ts +0 -7
  86. package/dist/runtime/CodexRuntime.js +0 -55
  87. package/dist/runtime/CodexRuntime.js.map +0 -1
  88. package/dist/runtime/CursorRuntime.d.ts +0 -7
  89. package/dist/runtime/CursorRuntime.js +0 -45
  90. package/dist/runtime/CursorRuntime.js.map +0 -1
  91. package/dist/runtime/OpenCodeRuntime.d.ts +0 -7
  92. package/dist/runtime/OpenCodeRuntime.js +0 -44
  93. package/dist/runtime/OpenCodeRuntime.js.map +0 -1
  94. package/dist/runtime/RuntimeBase.d.ts +0 -6
  95. package/dist/runtime/RuntimeBase.js +0 -3
  96. package/dist/runtime/RuntimeBase.js.map +0 -1
  97. package/dist/runtime/index.d.ts +0 -15
  98. package/dist/runtime/index.js +0 -25
  99. package/dist/runtime/index.js.map +0 -1
  100. package/dist/types/agent.d.ts +0 -26
  101. package/dist/types/agent.js +0 -2
  102. package/dist/types/agent.js.map +0 -1
  103. package/dist/types/config.d.ts +0 -22
  104. package/dist/types/config.js +0 -2
  105. package/dist/types/config.js.map +0 -1
  106. package/dist/types/event.d.ts +0 -77
  107. package/dist/types/event.js +0 -2
  108. package/dist/types/event.js.map +0 -1
  109. package/dist/types/index.d.ts +0 -4
  110. package/dist/types/index.js +0 -5
  111. package/dist/types/index.js.map +0 -1
  112. package/dist/types/runtime.d.ts +0 -19
  113. package/dist/types/runtime.js +0 -2
  114. package/dist/types/runtime.js.map +0 -1
  115. package/dist/utils/prompt.d.ts +0 -1
  116. package/dist/utils/prompt.js +0 -21
  117. package/dist/utils/prompt.js.map +0 -1
  118. package/dist/utils/retry.d.ts +0 -2
  119. package/dist/utils/retry.js +0 -20
  120. package/dist/utils/retry.js.map +0 -1
  121. package/dist/utils/timeout.d.ts +0 -1
  122. package/dist/utils/timeout.js +0 -12
  123. package/dist/utils/timeout.js.map +0 -1
  124. package/src/runtime/CodexRuntime.ts +0 -52
  125. package/src/runtime/CursorRuntime.ts +0 -41
  126. package/src/runtime/OpenCodeRuntime.ts +0 -40
  127. package/tsconfig.tsbuildinfo +0 -1
package/README.md ADDED
@@ -0,0 +1,16 @@
1
+ # @multiclawcli/core
2
+
3
+ [![npm](https://img.shields.io/npm/v/@multiclawcli/core)](https://www.npmjs.com/package/@multiclawcli/core)
4
+ [![GitHub](https://img.shields.io/badge/GitHub-shipengqi%2Fmulticlaw-blue?logo=github)](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, CodexRuntime, OpenCodeRuntime, CursorRuntime } from "./runtime";
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.1.0",
3
+ "version": "0.3.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
  },
@@ -36,6 +36,7 @@ export function archDesignReviewer(overrides?: Overrides): AgentDefinition {
36
36
  id: "arch-design-reviewer",
37
37
  name: "Arch Design Reviewer",
38
38
  icon: "△",
39
+ models: { claude: "haiku" },
39
40
  systemPrompt: SYSTEM,
40
41
  taskPrompt: TASK,
41
42
  tools: ["Read", "Write"],
@@ -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 two files in the current directory:
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 = `## Architecture Design
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"],
@@ -45,6 +45,7 @@ export function codeReviewer(overrides?: Overrides): AgentDefinition {
45
45
  id: "code-reviewer",
46
46
  name: "Code Reviewer",
47
47
  icon: "⊗",
48
+ models: { claude: "haiku" },
48
49
  systemPrompt: SYSTEM,
49
50
  taskPrompt: TASK,
50
51
  tools: ["Read", "Write"],
@@ -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 = `## Project
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 = `## UI Design Specification
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"],
@@ -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
+ }
@@ -34,6 +34,7 @@ export function productManager(overrides?: Overrides): AgentDefinition {
34
34
  id: "product-manager",
35
35
  name: "Product Manager",
36
36
  icon: "≡",
37
+ models: { claude: "sonnet" },
37
38
  systemPrompt: SYSTEM,
38
39
  taskPrompt: TASK,
39
40
  tools: ["Write"],
@@ -38,6 +38,7 @@ export function reviewer(overrides?: Overrides): AgentDefinition {
38
38
  id: "reviewer",
39
39
  name: "Reviewer",
40
40
  icon: "◉",
41
+ models: { claude: "haiku" },
41
42
  systemPrompt: SYSTEM,
42
43
  taskPrompt: TASK,
43
44
  tools: ["Read", "Write"],
@@ -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 = `## Project
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"],
@@ -39,6 +39,7 @@ export function uiDesignReviewer(overrides?: Overrides): AgentDefinition {
39
39
  id: "ui-design-reviewer",
40
40
  name: "UI Design Reviewer",
41
41
  icon: "◎",
42
+ models: { claude: "haiku" },
42
43
  systemPrompt: SYSTEM,
43
44
  taskPrompt: TASK,
44
45
  tools: ["Read", "Write"],
@@ -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 = `## Project
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, CodexRuntime, OpenCodeRuntime, CursorRuntime } from "./runtime"
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 stages = buildStages(this.config.agents)
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, totalAgents: this.config.agents.length, stages: stageInfos },
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 })
@@ -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, CodexRuntime, OpenCodeRuntime, CursorRuntime }
20
+ export { ClaudeRuntime }
@@ -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
+ }
@@ -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
@@ -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 }
@@ -7,6 +7,7 @@ export interface AgentTask {
7
7
  timeout: number
8
8
  signal?: AbortSignal
9
9
  onOutput?: (chunk: string) => void
10
+ model?: string
10
11
  }
11
12
 
12
13
  export interface AgentOutput {
@@ -1,4 +0,0 @@
1
- import type { AgentDefinition } from "../types/agent";
2
- type Overrides = Partial<AgentDefinition>;
3
- export declare function archDesignReviewer(overrides?: Overrides): AgentDefinition;
4
- export {};
@@ -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"}
@@ -1,4 +0,0 @@
1
- import type { AgentDefinition } from "../types/agent";
2
- type Overrides = Partial<AgentDefinition>;
3
- export declare function architect(overrides?: Overrides): AgentDefinition;
4
- export {};