@adamancyzhang/claude-orchestrator 0.3.1 → 0.3.2
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 +68 -59
- package/dist/cli/commands.d.ts +2 -2
- package/dist/cli/commands.js +51 -24
- package/dist/cli/commands.js.map +1 -1
- package/dist/config.d.ts +8 -2
- package/dist/config.js +6 -2
- package/dist/config.js.map +1 -1
- package/dist/executor/runner.d.ts +19 -0
- package/dist/executor/runner.js +59 -0
- package/dist/executor/runner.js.map +1 -0
- package/dist/executor/template.d.ts +12 -0
- package/dist/executor/template.js +42 -0
- package/dist/executor/template.js.map +1 -0
- package/dist/hooks/engine.d.ts +22 -0
- package/dist/hooks/engine.js +50 -0
- package/dist/hooks/engine.js.map +1 -0
- package/dist/index.js +16 -15
- package/dist/index.js.map +1 -1
- package/dist/leader/chain-router.d.ts +22 -0
- package/dist/leader/chain-router.js +163 -0
- package/dist/leader/chain-router.js.map +1 -0
- package/dist/leader/event-bus.d.ts +1 -1
- package/dist/leader/event-bus.js +1 -1
- package/dist/leader/event-bus.js.map +1 -1
- package/dist/leader/index.d.ts +1 -2
- package/dist/leader/index.js +30 -18
- package/dist/leader/index.js.map +1 -1
- package/dist/leader/state.js +9 -0
- package/dist/leader/state.js.map +1 -1
- package/dist/leader/tui.d.ts +8 -0
- package/dist/leader/tui.js +66 -4
- package/dist/leader/tui.js.map +1 -1
- package/dist/leader/watcher.d.ts +4 -5
- package/dist/leader/watcher.js +8 -25
- package/dist/leader/watcher.js.map +1 -1
- package/dist/models/schemas.d.ts +256 -0
- package/dist/models/schemas.js +25 -0
- package/dist/models/schemas.js.map +1 -1
- package/dist/skills/claude-orchestrator/SKILL.md +124 -60
- package/dist/templates/{leader-decompose.md → worker-decompose.md} +6 -8
- package/dist/templates/worker-evaluate.md +41 -0
- package/dist/utils/exec.js +2 -0
- package/dist/utils/exec.js.map +1 -1
- package/dist/utils/logger.d.ts +10 -0
- package/dist/utils/logger.js +22 -0
- package/dist/utils/logger.js.map +1 -0
- package/dist/worker/evaluator.d.ts +13 -0
- package/dist/worker/evaluator.js +112 -0
- package/dist/worker/evaluator.js.map +1 -0
- package/dist/worker/watcher.d.ts +11 -5
- package/dist/worker/watcher.js +98 -84
- package/dist/worker/watcher.js.map +1 -1
- package/package.json +1 -1
- package/dist/leader/decision-engine.d.ts +0 -35
- package/dist/leader/decision-engine.js +0 -102
- package/dist/leader/decision-engine.js.map +0 -1
- package/dist/leader/task-generator.d.ts +0 -34
- package/dist/leader/task-generator.js +0 -93
- package/dist/leader/task-generator.js.map +0 -1
- package/dist/templates/leader-decide.md +0 -59
package/dist/worker/watcher.js
CHANGED
|
@@ -1,51 +1,38 @@
|
|
|
1
1
|
import * as fs from "node:fs";
|
|
2
|
-
import path from "node:path";
|
|
3
2
|
import * as paths from "../zk/paths.js";
|
|
4
3
|
import { MessageSchema } from "../models/schemas.js";
|
|
5
|
-
import {
|
|
6
|
-
import {
|
|
7
|
-
const LINK_TEMPLATES = ["plan", "build", "verify", "review", "accept"];
|
|
4
|
+
import { Logger } from "../utils/logger.js";
|
|
5
|
+
import { CHAIN_LINKS } from "./evaluator.js";
|
|
8
6
|
export class WorkerWatcher {
|
|
9
7
|
zk;
|
|
10
8
|
instanceId;
|
|
11
|
-
workDir;
|
|
12
|
-
command;
|
|
13
|
-
cacheDir;
|
|
14
9
|
leaderInstanceId;
|
|
10
|
+
hooks;
|
|
11
|
+
templateEngine;
|
|
12
|
+
runner;
|
|
13
|
+
evaluator;
|
|
15
14
|
inFlight = new Set();
|
|
16
|
-
templates = {};
|
|
17
15
|
instanceName = "";
|
|
18
16
|
instanceRole = "";
|
|
17
|
+
logger = new Logger("WorkerWatcher");
|
|
19
18
|
stopped = false;
|
|
20
|
-
constructor(zk, instanceId,
|
|
19
|
+
constructor(zk, instanceId, leaderInstanceId, hooks, templateEngine, runner, evaluator) {
|
|
21
20
|
this.zk = zk;
|
|
22
21
|
this.instanceId = instanceId;
|
|
23
|
-
this.workDir = workDir;
|
|
24
|
-
this.command = command;
|
|
25
|
-
this.cacheDir = cacheDir;
|
|
26
22
|
this.leaderInstanceId = leaderInstanceId;
|
|
23
|
+
this.hooks = hooks;
|
|
24
|
+
this.templateEngine = templateEngine;
|
|
25
|
+
this.runner = runner;
|
|
26
|
+
this.evaluator = evaluator;
|
|
27
27
|
}
|
|
28
28
|
async start() {
|
|
29
|
-
// Load instance metadata
|
|
30
29
|
const instData = await this.zk.getInstance(this.instanceId);
|
|
31
30
|
this.instanceName = instData?.name ?? this.instanceId.slice(0, 8);
|
|
32
31
|
this.instanceRole = instData?.role ?? "builder";
|
|
33
|
-
|
|
34
|
-
const agentsDir = path.join(this.workDir, ".claude-orchestrator", "agents");
|
|
35
|
-
for (const link of LINK_TEMPLATES) {
|
|
36
|
-
try {
|
|
37
|
-
this.templates[link] = await fs.promises.readFile(path.join(agentsDir, `worker-${link}.md`), "utf-8");
|
|
38
|
-
}
|
|
39
|
-
catch {
|
|
40
|
-
this.templates[link] = `You are a Worker.\n\n## Task\n\n{{content}}`;
|
|
41
|
-
}
|
|
42
|
-
}
|
|
32
|
+
await this.templateEngine.loadAll();
|
|
43
33
|
await this.zk.mkdirp(paths.messageDirPath(this.instanceId));
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
console.log(`Command: ${this.command}`);
|
|
47
|
-
console.log(`CACHE_DIR: ${path.join(expandHomeDir(this.cacheDir), this.leaderInstanceId)}`);
|
|
48
|
-
console.log("Press Ctrl+C to stop.\n");
|
|
34
|
+
this.logger.info(`Watching for messages on instance ${this.instanceId.slice(0, 8)}...`);
|
|
35
|
+
this.logger.info("Press Ctrl+C to stop.");
|
|
49
36
|
this.watchLoop();
|
|
50
37
|
}
|
|
51
38
|
async watchLoop() {
|
|
@@ -76,64 +63,47 @@ export class WorkerWatcher {
|
|
|
76
63
|
return;
|
|
77
64
|
this.inFlight.add(msgId);
|
|
78
65
|
const fromLabel = msg.from_name || msg.from_instance?.slice(0, 8) || "unknown";
|
|
79
|
-
const timestamp = new Date().toLocaleTimeString();
|
|
80
66
|
const link = msg.link ?? "_generic";
|
|
81
67
|
const uniqueKey = `task-${msgId}-${Date.now().toString(36)}`;
|
|
82
|
-
const
|
|
83
|
-
const resultPath =
|
|
84
|
-
const
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
.
|
|
91
|
-
.
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
.
|
|
96
|
-
.
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
68
|
+
const logPath = this.runner.logPath(uniqueKey);
|
|
69
|
+
const resultPath = this.runner.resultPath(uniqueKey);
|
|
70
|
+
const template = this.templateEngine.get(link);
|
|
71
|
+
const prompt = template
|
|
72
|
+
? this.templateEngine.render(template, {
|
|
73
|
+
name: this.instanceName,
|
|
74
|
+
preset_role: this.instanceRole,
|
|
75
|
+
task_title: msg.task_title ?? "",
|
|
76
|
+
task_description: msg.task_description ?? msg.content,
|
|
77
|
+
task_criteria: msg.task_criteria ?? "",
|
|
78
|
+
task_doc_path: msg.task_doc_path ?? "",
|
|
79
|
+
result_path: resultPath,
|
|
80
|
+
work_dir: "",
|
|
81
|
+
time: new Date().toISOString(),
|
|
82
|
+
content: msg.content,
|
|
83
|
+
})
|
|
84
|
+
: msg.content;
|
|
85
|
+
this.logger.info(`Message from ${fromLabel} (${msg.type}): ${msg.content.slice(0, 200)}`);
|
|
86
|
+
if (link !== "_generic")
|
|
87
|
+
this.logger.info(` Link: ${link}`);
|
|
88
|
+
this.logger.info("Processing...");
|
|
89
|
+
const hookCtx = {
|
|
90
|
+
instanceId: this.instanceId,
|
|
91
|
+
instanceName: this.instanceName,
|
|
92
|
+
instanceRole: this.instanceRole,
|
|
93
|
+
messageId: msgId,
|
|
94
|
+
messageType: msg.type,
|
|
95
|
+
messageContent: msg.content,
|
|
96
|
+
fromInstance: msg.from_instance,
|
|
97
|
+
fromName: msg.from_name,
|
|
98
|
+
toInstance: msg.to_instance ?? "",
|
|
99
|
+
workDir: "",
|
|
100
|
+
link: link !== "_generic" ? link : null,
|
|
101
|
+
};
|
|
102
|
+
this.hooks.fire("worker_message_start", hookCtx);
|
|
103
|
+
const result = await this.runner.run(prompt, logPath);
|
|
104
|
+
this.hooks.fire("worker_message_end", { ...hookCtx, logPath, exitCode: result.code });
|
|
106
105
|
if (link !== "_generic") {
|
|
107
|
-
|
|
108
|
-
}
|
|
109
|
-
console.log(`[${timestamp}] Processing...`);
|
|
110
|
-
await execWithTee(this.command, prompt, logPath, this.workDir);
|
|
111
|
-
// Send completion report to leader (only for linked task messages)
|
|
112
|
-
if (link !== "_generic") {
|
|
113
|
-
try {
|
|
114
|
-
const report = [
|
|
115
|
-
`Link: ${link}`,
|
|
116
|
-
`Status: completed`,
|
|
117
|
-
`Result Path: ${resultPath}`,
|
|
118
|
-
`Task completed. Leader, please review and decide next step.`,
|
|
119
|
-
].join("\n");
|
|
120
|
-
await this.zk.createMessage(this.leaderInstanceId, {
|
|
121
|
-
type: "direct",
|
|
122
|
-
from_instance: this.instanceId,
|
|
123
|
-
from_name: this.instanceName,
|
|
124
|
-
from_role: this.instanceRole,
|
|
125
|
-
to_instance: this.leaderInstanceId,
|
|
126
|
-
content: report,
|
|
127
|
-
created_at: new Date().toISOString(),
|
|
128
|
-
read: false,
|
|
129
|
-
result_path: resultPath,
|
|
130
|
-
link,
|
|
131
|
-
});
|
|
132
|
-
console.log(`[${timestamp}] Completion report sent to Leader.`);
|
|
133
|
-
}
|
|
134
|
-
catch (err) {
|
|
135
|
-
console.error(`[${timestamp}] Failed to send completion report: ${err}`);
|
|
136
|
-
}
|
|
106
|
+
await this.sendCompletionReport(link, msg, resultPath, uniqueKey);
|
|
137
107
|
}
|
|
138
108
|
try {
|
|
139
109
|
msg.read = true;
|
|
@@ -143,7 +113,51 @@ export class WorkerWatcher {
|
|
|
143
113
|
// best effort
|
|
144
114
|
}
|
|
145
115
|
this.inFlight.delete(msgId);
|
|
146
|
-
|
|
116
|
+
this.logger.info(`Done. Log: ${logPath}`);
|
|
117
|
+
}
|
|
118
|
+
async sendCompletionReport(link, msg, resultPath, uniqueKey) {
|
|
119
|
+
try {
|
|
120
|
+
let reportContent;
|
|
121
|
+
let reportLink = link;
|
|
122
|
+
if (link === "decompose") {
|
|
123
|
+
try {
|
|
124
|
+
reportContent = await fs.promises.readFile(resultPath, "utf-8");
|
|
125
|
+
reportLink = "task_defs";
|
|
126
|
+
}
|
|
127
|
+
catch {
|
|
128
|
+
reportContent = `Link: ${link}\nStatus: completed\nResult Path: ${resultPath}`;
|
|
129
|
+
}
|
|
130
|
+
}
|
|
131
|
+
else if (CHAIN_LINKS.includes(link)) {
|
|
132
|
+
const msgVars = {
|
|
133
|
+
task_title: msg.task_title ?? "",
|
|
134
|
+
task_description: msg.task_description ?? "",
|
|
135
|
+
task_criteria: msg.task_criteria ?? "",
|
|
136
|
+
task_doc_path: msg.task_doc_path ?? "",
|
|
137
|
+
content: msg.content,
|
|
138
|
+
};
|
|
139
|
+
reportContent = await this.evaluator.evaluate(link, msgVars, resultPath, uniqueKey);
|
|
140
|
+
}
|
|
141
|
+
else {
|
|
142
|
+
reportContent = `Link: ${link}\nStatus: completed\nResult Path: ${resultPath}\nTask completed.`;
|
|
143
|
+
}
|
|
144
|
+
await this.zk.createMessage(this.leaderInstanceId, {
|
|
145
|
+
type: "direct",
|
|
146
|
+
from_instance: this.instanceId,
|
|
147
|
+
from_name: this.instanceName,
|
|
148
|
+
from_role: this.instanceRole,
|
|
149
|
+
to_instance: this.instanceId,
|
|
150
|
+
content: reportContent,
|
|
151
|
+
created_at: new Date().toISOString(),
|
|
152
|
+
read: false,
|
|
153
|
+
result_path: resultPath,
|
|
154
|
+
link: reportLink,
|
|
155
|
+
});
|
|
156
|
+
this.logger.info("Completion report sent.");
|
|
157
|
+
}
|
|
158
|
+
catch (err) {
|
|
159
|
+
this.logger.error("Failed to send completion report", err);
|
|
160
|
+
}
|
|
147
161
|
}
|
|
148
162
|
stop() {
|
|
149
163
|
this.stopped = true;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"watcher.js","sourceRoot":"","sources":["../../src/worker/watcher.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,MAAM,SAAS,CAAC;
|
|
1
|
+
{"version":3,"file":"watcher.js","sourceRoot":"","sources":["../../src/worker/watcher.ts"],"names":[],"mappings":"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"}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@adamancyzhang/claude-orchestrator",
|
|
3
|
-
"version": "0.3.
|
|
3
|
+
"version": "0.3.2",
|
|
4
4
|
"description": "Multi-agent orchestration CLI backed by ZooKeeper — register, assign tasks, communicate, share context",
|
|
5
5
|
"repository": "github:adamancyzhang/claude-orchestrator-server",
|
|
6
6
|
"license": "MIT",
|
|
@@ -1,35 +0,0 @@
|
|
|
1
|
-
import { ZkClient } from "../zk/client.js";
|
|
2
|
-
import { TaskQueue } from "../modules/task-queue.js";
|
|
3
|
-
import { MessageRouter } from "../modules/message-router.js";
|
|
4
|
-
import type { Message } from "../models/schemas.js";
|
|
5
|
-
export interface DecisionContext {
|
|
6
|
-
teamStatus: object;
|
|
7
|
-
taskQueues: object;
|
|
8
|
-
chainStatus: object;
|
|
9
|
-
}
|
|
10
|
-
export interface Decision {
|
|
11
|
-
decision: "pass" | "feedback" | "reject";
|
|
12
|
-
reason: string;
|
|
13
|
-
feedbackToWorker?: string;
|
|
14
|
-
nextAction: {
|
|
15
|
-
action: "activate_next_link" | "reassign" | "close_chain" | "broadcast_help" | "none";
|
|
16
|
-
nextLink: string | null;
|
|
17
|
-
suggestedWorker: string | null;
|
|
18
|
-
messageToWorker: string | null;
|
|
19
|
-
};
|
|
20
|
-
}
|
|
21
|
-
export declare class DecisionEngine {
|
|
22
|
-
private zk;
|
|
23
|
-
private taskQueue;
|
|
24
|
-
private messageRouter;
|
|
25
|
-
private command;
|
|
26
|
-
private cacheDir;
|
|
27
|
-
private leaderInstanceId;
|
|
28
|
-
private template;
|
|
29
|
-
private templatePath;
|
|
30
|
-
constructor(zk: ZkClient, taskQueue: TaskQueue, messageRouter: MessageRouter, command: string, cacheDir: string, leaderInstanceId: string, templatePath?: string);
|
|
31
|
-
private loadTemplate;
|
|
32
|
-
evaluate(report: Message, context: DecisionContext): Promise<Decision>;
|
|
33
|
-
private executeDecision;
|
|
34
|
-
private parseOutput;
|
|
35
|
-
}
|
|
@@ -1,102 +0,0 @@
|
|
|
1
|
-
import * as fs from "node:fs";
|
|
2
|
-
import * as path from "node:path";
|
|
3
|
-
import { expandHomeDir } from "../config.js";
|
|
4
|
-
import { execAndCapture } from "../utils/exec.js";
|
|
5
|
-
const NEXT_LINKS = {
|
|
6
|
-
plan: "build",
|
|
7
|
-
build: "verify",
|
|
8
|
-
verify: "review",
|
|
9
|
-
review: "accept",
|
|
10
|
-
accept: null,
|
|
11
|
-
};
|
|
12
|
-
export class DecisionEngine {
|
|
13
|
-
zk;
|
|
14
|
-
taskQueue;
|
|
15
|
-
messageRouter;
|
|
16
|
-
command;
|
|
17
|
-
cacheDir;
|
|
18
|
-
leaderInstanceId;
|
|
19
|
-
template = null;
|
|
20
|
-
templatePath;
|
|
21
|
-
constructor(zk, taskQueue, messageRouter, command, cacheDir, leaderInstanceId, templatePath) {
|
|
22
|
-
this.zk = zk;
|
|
23
|
-
this.taskQueue = taskQueue;
|
|
24
|
-
this.messageRouter = messageRouter;
|
|
25
|
-
this.command = command;
|
|
26
|
-
this.cacheDir = cacheDir;
|
|
27
|
-
this.leaderInstanceId = leaderInstanceId;
|
|
28
|
-
this.templatePath = templatePath ?? path.join(process.cwd(), ".claude-orchestrator", "agents", "leader-decide.md");
|
|
29
|
-
}
|
|
30
|
-
async loadTemplate() {
|
|
31
|
-
if (this.template)
|
|
32
|
-
return this.template;
|
|
33
|
-
try {
|
|
34
|
-
this.template = await fs.promises.readFile(this.templatePath, "utf-8");
|
|
35
|
-
}
|
|
36
|
-
catch {
|
|
37
|
-
throw new Error(`Decide template not found at ${this.templatePath}. Run setup first.`);
|
|
38
|
-
}
|
|
39
|
-
return this.template;
|
|
40
|
-
}
|
|
41
|
-
async evaluate(report, context) {
|
|
42
|
-
const template = await this.loadTemplate();
|
|
43
|
-
const prompt = template
|
|
44
|
-
.replace("{{team_status}}", JSON.stringify(context.teamStatus, null, 2))
|
|
45
|
-
.replace("{{task_queues}}", JSON.stringify(context.taskQueues, null, 2))
|
|
46
|
-
.replace("{{chain_status}}", JSON.stringify(context.chainStatus, null, 2))
|
|
47
|
-
.replace("{{content}}", report.content);
|
|
48
|
-
const uniqueKey = `decide-${Date.now().toString(36)}`;
|
|
49
|
-
const resolvedCacheDir = expandHomeDir(path.join(this.cacheDir, this.leaderInstanceId));
|
|
50
|
-
const logPath = path.join(resolvedCacheDir, `${uniqueKey}.log`);
|
|
51
|
-
const { stdout } = await execAndCapture(this.command, prompt, logPath);
|
|
52
|
-
const decision = this.parseOutput(stdout);
|
|
53
|
-
await this.executeDecision(decision, report);
|
|
54
|
-
return decision;
|
|
55
|
-
}
|
|
56
|
-
async executeDecision(decision, report) {
|
|
57
|
-
const nextLink = decision.nextAction.nextLink;
|
|
58
|
-
const linkOrder = ["plan", "build", "verify", "review", "accept"];
|
|
59
|
-
switch (decision.nextAction.action) {
|
|
60
|
-
case "activate_next_link": {
|
|
61
|
-
if (!nextLink)
|
|
62
|
-
break;
|
|
63
|
-
const pending = await this.zk.listPendingTasks();
|
|
64
|
-
for (const [taskId, data] of pending) {
|
|
65
|
-
if (data.link === nextLink && data.chain_id === report.chain_id) {
|
|
66
|
-
// Task already exists in pending, no need to create
|
|
67
|
-
break;
|
|
68
|
-
}
|
|
69
|
-
}
|
|
70
|
-
break;
|
|
71
|
-
}
|
|
72
|
-
case "close_chain":
|
|
73
|
-
break;
|
|
74
|
-
case "reassign":
|
|
75
|
-
case "broadcast_help":
|
|
76
|
-
case "none":
|
|
77
|
-
break;
|
|
78
|
-
}
|
|
79
|
-
if (decision.decision === "feedback" && decision.feedbackToWorker && report.from_instance) {
|
|
80
|
-
await this.messageRouter.send(this.leaderInstanceId, "Leader", decision.feedbackToWorker, report.from_instance);
|
|
81
|
-
}
|
|
82
|
-
}
|
|
83
|
-
parseOutput(output) {
|
|
84
|
-
const cleaned = output
|
|
85
|
-
.replace(/```json\s*/g, "")
|
|
86
|
-
.replace(/```\s*/g, "")
|
|
87
|
-
.trim();
|
|
88
|
-
const parsed = JSON.parse(cleaned);
|
|
89
|
-
return {
|
|
90
|
-
decision: parsed.decision ?? "pass",
|
|
91
|
-
reason: parsed.reason ?? "",
|
|
92
|
-
feedbackToWorker: parsed.feedback_to_worker,
|
|
93
|
-
nextAction: {
|
|
94
|
-
action: parsed.next_action?.action ?? "none",
|
|
95
|
-
nextLink: parsed.next_action?.next_link ?? null,
|
|
96
|
-
suggestedWorker: parsed.next_action?.suggested_worker ?? null,
|
|
97
|
-
messageToWorker: parsed.next_action?.message_to_worker ?? null,
|
|
98
|
-
},
|
|
99
|
-
};
|
|
100
|
-
}
|
|
101
|
-
}
|
|
102
|
-
//# sourceMappingURL=decision-engine.js.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"decision-engine.js","sourceRoot":"","sources":["../../src/leader/decision-engine.ts"],"names":[],"mappings":"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"}
|
|
@@ -1,34 +0,0 @@
|
|
|
1
|
-
import { ZkClient } from "../zk/client.js";
|
|
2
|
-
import { TaskQueue } from "../modules/task-queue.js";
|
|
3
|
-
interface ChainTaskDef {
|
|
4
|
-
title: string;
|
|
5
|
-
description: string;
|
|
6
|
-
criteria: string;
|
|
7
|
-
priority: number;
|
|
8
|
-
}
|
|
9
|
-
interface ChainDef {
|
|
10
|
-
chain_id: string;
|
|
11
|
-
chain_title: string;
|
|
12
|
-
tasks: {
|
|
13
|
-
plan: ChainTaskDef | null;
|
|
14
|
-
build: ChainTaskDef;
|
|
15
|
-
verify: ChainTaskDef;
|
|
16
|
-
review: ChainTaskDef;
|
|
17
|
-
accept: ChainTaskDef;
|
|
18
|
-
};
|
|
19
|
-
}
|
|
20
|
-
export declare class TaskGenerator {
|
|
21
|
-
private zk;
|
|
22
|
-
private taskQueue;
|
|
23
|
-
private command;
|
|
24
|
-
private cacheDir;
|
|
25
|
-
private leaderInstanceId;
|
|
26
|
-
private template;
|
|
27
|
-
private templatePath;
|
|
28
|
-
constructor(zk: ZkClient, taskQueue: TaskQueue, command: string, cacheDir: string, leaderInstanceId: string, templatePath?: string);
|
|
29
|
-
private loadTemplate;
|
|
30
|
-
decompose(requirement: string, teamStatus: object): Promise<ChainDef[]>;
|
|
31
|
-
private pushChain;
|
|
32
|
-
private parseOutput;
|
|
33
|
-
}
|
|
34
|
-
export {};
|
|
@@ -1,93 +0,0 @@
|
|
|
1
|
-
import * as fs from "node:fs";
|
|
2
|
-
import * as path from "node:path";
|
|
3
|
-
import { expandHomeDir } from "../config.js";
|
|
4
|
-
import { execAndCapture } from "../utils/exec.js";
|
|
5
|
-
export class TaskGenerator {
|
|
6
|
-
zk;
|
|
7
|
-
taskQueue;
|
|
8
|
-
command;
|
|
9
|
-
cacheDir;
|
|
10
|
-
leaderInstanceId;
|
|
11
|
-
template = null;
|
|
12
|
-
templatePath;
|
|
13
|
-
constructor(zk, taskQueue, command, cacheDir, leaderInstanceId, templatePath) {
|
|
14
|
-
this.zk = zk;
|
|
15
|
-
this.taskQueue = taskQueue;
|
|
16
|
-
this.command = command;
|
|
17
|
-
this.cacheDir = cacheDir;
|
|
18
|
-
this.leaderInstanceId = leaderInstanceId;
|
|
19
|
-
this.templatePath = templatePath ?? path.join(process.cwd(), ".claude-orchestrator", "agents", "leader-decompose.md");
|
|
20
|
-
}
|
|
21
|
-
async loadTemplate() {
|
|
22
|
-
if (this.template)
|
|
23
|
-
return this.template;
|
|
24
|
-
try {
|
|
25
|
-
this.template = await fs.promises.readFile(this.templatePath, "utf-8");
|
|
26
|
-
}
|
|
27
|
-
catch {
|
|
28
|
-
throw new Error(`Decompose template not found at ${this.templatePath}. Run setup first.`);
|
|
29
|
-
}
|
|
30
|
-
return this.template;
|
|
31
|
-
}
|
|
32
|
-
async decompose(requirement, teamStatus) {
|
|
33
|
-
const template = await this.loadTemplate();
|
|
34
|
-
const prompt = template
|
|
35
|
-
.replace("{{team_status}}", JSON.stringify(teamStatus, null, 2))
|
|
36
|
-
.replace("{{content}}", requirement);
|
|
37
|
-
const uniqueKey = `decompose-${Date.now().toString(36)}`;
|
|
38
|
-
const resolvedCacheDir = expandHomeDir(path.join(this.cacheDir, this.leaderInstanceId));
|
|
39
|
-
const logPath = path.join(resolvedCacheDir, `${uniqueKey}.log`);
|
|
40
|
-
const { stdout } = await execAndCapture(this.command, prompt, logPath);
|
|
41
|
-
const chains = this.parseOutput(stdout);
|
|
42
|
-
for (const chain of chains) {
|
|
43
|
-
await this.pushChain(chain, resolvedCacheDir);
|
|
44
|
-
}
|
|
45
|
-
return chains;
|
|
46
|
-
}
|
|
47
|
-
async pushChain(chain, resolvedCacheDir) {
|
|
48
|
-
const taskLinks = [];
|
|
49
|
-
if (chain.tasks.plan)
|
|
50
|
-
taskLinks.push({ link: "plan", def: chain.tasks.plan });
|
|
51
|
-
taskLinks.push({ link: "build", def: chain.tasks.build });
|
|
52
|
-
taskLinks.push({ link: "verify", def: chain.tasks.verify });
|
|
53
|
-
taskLinks.push({ link: "review", def: chain.tasks.review });
|
|
54
|
-
taskLinks.push({ link: "accept", def: chain.tasks.accept });
|
|
55
|
-
for (const { link, def } of taskLinks) {
|
|
56
|
-
const task = await this.taskQueue.push(def.title, def.description, def.priority, "", undefined, undefined, null, link, chain.chain_id);
|
|
57
|
-
const docPath = path.join(resolvedCacheDir, "tasks", `${task.id}.md`);
|
|
58
|
-
await fs.promises.mkdir(path.dirname(docPath), { recursive: true });
|
|
59
|
-
await fs.promises.writeFile(docPath, `# ${def.title}\n\n` +
|
|
60
|
-
`**Link**: ${link}\n` +
|
|
61
|
-
`**Chain**: ${chain.chain_id}\n` +
|
|
62
|
-
`**Priority**: ${def.priority}\n\n` +
|
|
63
|
-
`## Description\n\n${def.description}\n\n` +
|
|
64
|
-
`## Completion Criteria\n\n${def.criteria}\n`);
|
|
65
|
-
}
|
|
66
|
-
}
|
|
67
|
-
parseOutput(output) {
|
|
68
|
-
let cleaned = output
|
|
69
|
-
.replace(/```json\s*/g, "")
|
|
70
|
-
.replace(/```\s*/g, "")
|
|
71
|
-
.trim();
|
|
72
|
-
try {
|
|
73
|
-
const parsed = JSON.parse(cleaned);
|
|
74
|
-
return Array.isArray(parsed) ? parsed : [parsed];
|
|
75
|
-
}
|
|
76
|
-
catch {
|
|
77
|
-
const results = [];
|
|
78
|
-
const matches = cleaned.match(/\{[\s\S]*?\}(?=\s*\{|\s*$)/g);
|
|
79
|
-
if (matches) {
|
|
80
|
-
for (const m of matches) {
|
|
81
|
-
try {
|
|
82
|
-
results.push(JSON.parse(m));
|
|
83
|
-
}
|
|
84
|
-
catch { /* skip */ }
|
|
85
|
-
}
|
|
86
|
-
}
|
|
87
|
-
if (results.length === 0)
|
|
88
|
-
throw new Error("Failed to parse Claude output as task chain JSON");
|
|
89
|
-
return results;
|
|
90
|
-
}
|
|
91
|
-
}
|
|
92
|
-
}
|
|
93
|
-
//# sourceMappingURL=task-generator.js.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"task-generator.js","sourceRoot":"","sources":["../../src/leader/task-generator.ts"],"names":[],"mappings":"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"}
|
|
@@ -1,59 +0,0 @@
|
|
|
1
|
-
You are the decision engine for a task coordination system. Your job is to evaluate a worker's completion report and decide the next action. You do NOT decompose new requirements — that is handled separately.
|
|
2
|
-
|
|
3
|
-
## Responsibility Chain (for context)
|
|
4
|
-
|
|
5
|
-
Plan → Build → Verify → Review → Accept. A task is only CLOSED after all five links sign off. Each link has completion criteria set when the task was created.
|
|
6
|
-
|
|
7
|
-
## Current State
|
|
8
|
-
|
|
9
|
-
### Team
|
|
10
|
-
{{team_status}}
|
|
11
|
-
|
|
12
|
-
### Task Queues
|
|
13
|
-
{{task_queues}}
|
|
14
|
-
|
|
15
|
-
### Current Chain
|
|
16
|
-
{{chain_status}}
|
|
17
|
-
|
|
18
|
-
## Worker Report
|
|
19
|
-
|
|
20
|
-
{{content}}
|
|
21
|
-
|
|
22
|
-
## Decision Rules
|
|
23
|
-
|
|
24
|
-
1. **Evaluate the report against the task's completion criteria.**
|
|
25
|
-
- Criteria met → the link PASSES
|
|
26
|
-
- Criteria partially met → FEEDBACK (tell worker what's missing)
|
|
27
|
-
- Criteria not met → REJECT (explain why, return for rework)
|
|
28
|
-
|
|
29
|
-
2. **Check chain position.**
|
|
30
|
-
- If this was Accept and it passes → the chain is CLOSED
|
|
31
|
-
- Otherwise → the next link's tasks become unblocked
|
|
32
|
-
|
|
33
|
-
3. **Consider team load when assigning the next task.**
|
|
34
|
-
- Prefer workers whose preset role matches the next link
|
|
35
|
-
- If all role-matched workers are busy, any idle worker can take it
|
|
36
|
-
- If a different link is a bottleneck, suggest cross-role assistance
|
|
37
|
-
|
|
38
|
-
4. **Priority override.**
|
|
39
|
-
- If there is an urgency=0 task in the queue, suggest handling it first
|
|
40
|
-
|
|
41
|
-
## Output Format
|
|
42
|
-
|
|
43
|
-
Output exactly one JSON decision:
|
|
44
|
-
|
|
45
|
-
```json
|
|
46
|
-
{
|
|
47
|
-
"decision": "pass" | "feedback" | "reject",
|
|
48
|
-
"reason": "<one-line explanation>",
|
|
49
|
-
"feedback_to_worker": "<only if feedback or reject: specific guidance>",
|
|
50
|
-
"next_action": {
|
|
51
|
-
"action": "activate_next_link" | "reassign" | "close_chain" | "broadcast_help" | "none",
|
|
52
|
-
"next_link": "build" | "verify" | "review" | "accept" | null,
|
|
53
|
-
"suggested_worker": "<worker name or null>",
|
|
54
|
-
"message_to_worker": "<task assignment message if activating next link>"
|
|
55
|
-
}
|
|
56
|
-
}
|
|
57
|
-
```
|
|
58
|
-
|
|
59
|
-
Output ONLY the JSON. No explanation.
|