@s_s/harmonia 1.2.0 → 1.4.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 +140 -392
- package/build/cli/setup.d.ts +4 -2
- package/build/cli/setup.js +44 -18
- package/build/cli/setup.js.map +1 -1
- package/build/core/action-registry.d.ts +36 -0
- package/build/core/action-registry.js +53 -0
- package/build/core/action-registry.js.map +1 -0
- package/build/core/artifacts.d.ts +66 -0
- package/build/core/artifacts.js +178 -0
- package/build/core/artifacts.js.map +1 -0
- package/build/core/dispatch.d.ts +18 -11
- package/build/core/dispatch.js +43 -33
- package/build/core/dispatch.js.map +1 -1
- package/build/core/issues.d.ts +37 -0
- package/build/core/issues.js +100 -0
- package/build/core/issues.js.map +1 -0
- package/build/core/overrides.d.ts +19 -26
- package/build/core/overrides.js +32 -98
- package/build/core/overrides.js.map +1 -1
- package/build/core/plugin.d.ts +86 -0
- package/build/core/plugin.js +332 -0
- package/build/core/plugin.js.map +1 -0
- package/build/core/registry.d.ts +36 -3
- package/build/core/registry.js +63 -5
- package/build/core/registry.js.map +1 -1
- package/build/core/reviews.d.ts +13 -13
- package/build/core/reviews.js +31 -32
- package/build/core/reviews.js.map +1 -1
- package/build/core/schema.d.ts +43 -15
- package/build/core/schema.js +124 -20
- package/build/core/schema.js.map +1 -1
- package/build/core/state.d.ts +29 -22
- package/build/core/state.js +49 -81
- package/build/core/state.js.map +1 -1
- package/build/core/steps.d.ts +15 -15
- package/build/core/steps.js +32 -33
- package/build/core/steps.js.map +1 -1
- package/build/core/tree-utils.d.ts +52 -0
- package/build/core/tree-utils.js +226 -0
- package/build/core/tree-utils.js.map +1 -0
- package/build/core/types.d.ts +417 -117
- package/build/core/types.js +15 -1
- package/build/core/types.js.map +1 -1
- package/build/core/workflow-engine.d.ts +68 -0
- package/build/core/workflow-engine.js +821 -0
- package/build/core/workflow-engine.js.map +1 -0
- package/build/core/workflow-validator.d.ts +22 -0
- package/build/core/workflow-validator.js +489 -0
- package/build/core/workflow-validator.js.map +1 -0
- package/build/index.js +28 -25
- package/build/index.js.map +1 -1
- package/build/setup/inject.d.ts +4 -4
- package/build/setup/inject.js +6 -6
- package/build/setup/inject.js.map +1 -1
- package/build/setup/templates.d.ts +9 -7
- package/build/setup/templates.js +68 -103
- package/build/setup/templates.js.map +1 -1
- package/build/tools/artifact-approve.d.ts +8 -0
- package/build/tools/artifact-approve.js +94 -0
- package/build/tools/artifact-approve.js.map +1 -0
- package/build/tools/artifact-schema.d.ts +12 -0
- package/build/tools/artifact-schema.js +148 -0
- package/build/tools/artifact-schema.js.map +1 -0
- package/build/tools/artifact-tools.d.ts +18 -0
- package/build/tools/artifact-tools.js +465 -0
- package/build/tools/artifact-tools.js.map +1 -0
- package/build/tools/{report-dispatch.d.ts → dispatch-report.d.ts} +7 -3
- package/build/tools/dispatch-report.js +261 -0
- package/build/tools/dispatch-report.js.map +1 -0
- package/build/tools/engine-helpers.d.ts +41 -0
- package/build/tools/engine-helpers.js +182 -0
- package/build/tools/engine-helpers.js.map +1 -0
- package/build/tools/get-project-status.d.ts +6 -4
- package/build/tools/get-project-status.js +308 -246
- package/build/tools/get-project-status.js.map +1 -1
- package/build/tools/get-role-prompt.d.ts +1 -1
- package/build/tools/get-role-prompt.js +7 -41
- package/build/tools/get-role-prompt.js.map +1 -1
- package/build/tools/issue-tools.d.ts +10 -0
- package/build/tools/issue-tools.js +169 -0
- package/build/tools/issue-tools.js.map +1 -0
- package/build/tools/iteration-start.d.ts +7 -4
- package/build/tools/iteration-start.js +51 -20
- package/build/tools/iteration-start.js.map +1 -1
- package/build/tools/loop-done.d.ts +11 -0
- package/build/tools/loop-done.js +109 -0
- package/build/tools/loop-done.js.map +1 -0
- package/build/tools/patch-start.d.ts +16 -0
- package/build/tools/patch-start.js +122 -0
- package/build/tools/patch-start.js.map +1 -0
- package/build/tools/project-init.d.ts +5 -5
- package/build/tools/project-init.js +47 -18
- package/build/tools/project-init.js.map +1 -1
- package/build/tools/role-dispatch.d.ts +55 -0
- package/build/tools/role-dispatch.js +508 -0
- package/build/tools/role-dispatch.js.map +1 -0
- package/build/tools/utils.d.ts +40 -0
- package/build/tools/utils.js +97 -0
- package/build/tools/utils.js.map +1 -0
- package/package.json +1 -1
- package/{build/hooks/claude-code.js → workflows/dev/hooks/claude.js} +34 -23
- package/{build → workflows/dev}/hooks/content.js +27 -18
- package/workflows/dev/hooks/index.js +52 -0
- package/{build → workflows/dev}/hooks/openclaw.js +31 -20
- package/{build → workflows/dev}/hooks/opencode.js +31 -20
- package/workflows/dev/roles/architect.md +68 -28
- package/workflows/dev/roles/coordinator.md +103 -0
- package/workflows/dev/roles/developer.md +5 -5
- package/workflows/dev/roles/tester.md +19 -19
- package/workflows/dev/schemas/api-contract.json +42 -0
- package/workflows/dev/schemas/api-design.json +30 -13
- package/workflows/dev/schemas/data-model.json +20 -7
- package/workflows/dev/schemas/prd.completeness-check.json +6 -5
- package/workflows/dev/schemas/prd.draft.json +13 -5
- package/workflows/dev/schemas/prd.final.json +34 -11
- package/workflows/dev/schemas/prd.json +29 -11
- package/workflows/dev/schemas/prd.requirements.json +6 -5
- package/workflows/dev/schemas/prototype.json +6 -2
- package/workflows/dev/schemas/task-breakdown.coarse.json +4 -3
- package/workflows/dev/schemas/task-breakdown.dependencies.json +5 -4
- package/workflows/dev/schemas/task-breakdown.detailed.json +8 -3
- package/workflows/dev/schemas/task-breakdown.final.json +8 -3
- package/workflows/dev/schemas/task-breakdown.json +8 -3
- package/workflows/dev/schemas/tech-design.analysis.json +6 -5
- package/workflows/dev/schemas/tech-design.draft.json +14 -5
- package/workflows/dev/schemas/tech-design.final.json +39 -13
- package/workflows/dev/schemas/tech-design.json +34 -13
- package/workflows/dev/schemas/tech-design.research.json +21 -0
- package/workflows/dev/schemas/test-plan.json +17 -7
- package/workflows/dev/schemas/test-report.json +26 -9
- package/workflows/dev/schemas/user-stories.json +7 -3
- package/workflows/dev/tools/index.js +23 -0
- package/workflows/dev/workflow.json +234 -101
- package/build/core/docs.d.ts +0 -32
- package/build/core/docs.js +0 -91
- package/build/core/docs.js.map +0 -1
- package/build/core/workflow.d.ts +0 -33
- package/build/core/workflow.js +0 -140
- package/build/core/workflow.js.map +0 -1
- package/build/hooks/claude-code.d.ts +0 -20
- package/build/hooks/claude-code.js.map +0 -1
- package/build/hooks/content.d.ts +0 -43
- package/build/hooks/content.js.map +0 -1
- package/build/hooks/install.d.ts +0 -40
- package/build/hooks/install.js +0 -63
- package/build/hooks/install.js.map +0 -1
- package/build/hooks/openclaw.d.ts +0 -24
- package/build/hooks/openclaw.js.map +0 -1
- package/build/hooks/opencode.d.ts +0 -29
- package/build/hooks/opencode.js.map +0 -1
- package/build/tools/approve-doc.d.ts +0 -6
- package/build/tools/approve-doc.js +0 -108
- package/build/tools/approve-doc.js.map +0 -1
- package/build/tools/dispatch-role.d.ts +0 -16
- package/build/tools/dispatch-role.js +0 -277
- package/build/tools/dispatch-role.js.map +0 -1
- package/build/tools/doc-tools.d.ts +0 -16
- package/build/tools/doc-tools.js +0 -389
- package/build/tools/doc-tools.js.map +0 -1
- package/build/tools/override-tools.d.ts +0 -6
- package/build/tools/override-tools.js +0 -129
- package/build/tools/override-tools.js.map +0 -1
- package/build/tools/report-dispatch.js +0 -194
- package/build/tools/report-dispatch.js.map +0 -1
- package/build/tools/set-scale.d.ts +0 -6
- package/build/tools/set-scale.js +0 -107
- package/build/tools/set-scale.js.map +0 -1
- package/build/tools/setup-project.d.ts +0 -8
- package/build/tools/setup-project.js +0 -116
- package/build/tools/setup-project.js.map +0 -1
- package/build/tools/update-phase.d.ts +0 -12
- package/build/tools/update-phase.js +0 -159
- package/build/tools/update-phase.js.map +0 -1
- package/workflows/dev/roles/pm.md +0 -99
- package/workflows/dev/schemas/deploy.json +0 -20
- package/workflows/dev/schemas/fsd.json +0 -25
- package/workflows/dev/schemas/project-plan.json +0 -20
- package/workflows/dev/schemas/retrospective.json +0 -20
- package/workflows/dev/schemas/risk-assessment.json +0 -15
- package/workflows/dev/schemas/tech-design.api-contract.json +0 -20
|
@@ -0,0 +1,508 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* MCP Tool: role_dispatch
|
|
3
|
+
*
|
|
4
|
+
* Prepare all data needed to hand off a task to a team member role.
|
|
5
|
+
* Returns: role prompt (with overrides injected), session guidance,
|
|
6
|
+
* input artifacts, task brief, and dispatch tracking info.
|
|
7
|
+
*
|
|
8
|
+
* Node-based architecture: validates against workflow node states.
|
|
9
|
+
* Accepts an optional node_id parameter to target a specific task node.
|
|
10
|
+
*
|
|
11
|
+
* Session/parallel behavior is enforced by Core:
|
|
12
|
+
* - session: none → never searches for idle sessions
|
|
13
|
+
* - session: persistent → searches for idle sessions, directs reuse
|
|
14
|
+
* - session: optional → searches for idle sessions, suggests reuse
|
|
15
|
+
* - parallel: true + running dispatch → forces new session
|
|
16
|
+
*
|
|
17
|
+
* Automatically:
|
|
18
|
+
* - Creates a dispatch record for tracking
|
|
19
|
+
* - Enforces session/parallel strategy from role frontmatter
|
|
20
|
+
* - Triggers a dispatch_requested engine event
|
|
21
|
+
* - Returns nextAction from the workflow engine
|
|
22
|
+
*
|
|
23
|
+
* This tool does NOT launch agents — it only prepares the data.
|
|
24
|
+
* The coordinator decides how to pass this to the team member.
|
|
25
|
+
*/
|
|
26
|
+
import { z } from 'zod';
|
|
27
|
+
import { readArtifact, listArtifacts, resolveArtifactDir } from '../core/artifacts.js';
|
|
28
|
+
import { getMergedOverrides, resolveRoleConfig } from '../core/overrides.js';
|
|
29
|
+
import { createDispatch, findIdleSession, hasRunningDispatch } from '../core/dispatch.js';
|
|
30
|
+
import { loadArtifactSchema, formatSchemaGuidance } from '../core/schema.js';
|
|
31
|
+
import { resolveActive, isError, buildOverrideSection } from './utils.js';
|
|
32
|
+
import { loadWorkflowForContext, processWorkflowEvent, formatNextAction, findTaskNode } from './engine-helpers.js';
|
|
33
|
+
import { collectTaskNodes, findAncestorLoopId } from '../core/tree-utils.js';
|
|
34
|
+
/**
|
|
35
|
+
* Find task nodes for a given role that are active or pending.
|
|
36
|
+
*/
|
|
37
|
+
function findDispatchableNodes(wf, state, role) {
|
|
38
|
+
const allTasks = collectTaskNodes(wf.definition.root);
|
|
39
|
+
// Include floating nodes
|
|
40
|
+
if (wf.definition.floatingNodes) {
|
|
41
|
+
allTasks.push(...wf.definition.floatingNodes);
|
|
42
|
+
}
|
|
43
|
+
return allTasks.filter((t) => {
|
|
44
|
+
if (t.role !== role)
|
|
45
|
+
return false;
|
|
46
|
+
const nodeState = state.nodes[t.id];
|
|
47
|
+
return nodeState && (nodeState.status === 'active' || nodeState.status === 'pending');
|
|
48
|
+
});
|
|
49
|
+
}
|
|
50
|
+
/**
|
|
51
|
+
* Build session guidance text.
|
|
52
|
+
*
|
|
53
|
+
* Incorporates session type behavior, parallel status, model, and agent info.
|
|
54
|
+
* This replaces the former separate "## Configuration" section — all dispatch
|
|
55
|
+
* configuration info is now part of Session Guidance.
|
|
56
|
+
*/
|
|
57
|
+
function buildSessionGuidance(params) {
|
|
58
|
+
const { idleSession, sessionType, model, agent, parallelForced } = params;
|
|
59
|
+
const lines = [];
|
|
60
|
+
// Consistent agent descriptor used across all Action lines
|
|
61
|
+
const agentDesc = agent ? `拉起 ${agent} 作为子 agent 执行任务` : '拉起子 agent 执行任务';
|
|
62
|
+
// Model/agent header
|
|
63
|
+
if (model) {
|
|
64
|
+
const agentSuffix = agent ? `,使用 ${agent}` : '';
|
|
65
|
+
lines.push(`**Model**: \`${model}\`${agentSuffix}`);
|
|
66
|
+
}
|
|
67
|
+
else if (agent) {
|
|
68
|
+
lines.push(`**Agent**: ${agent}`);
|
|
69
|
+
}
|
|
70
|
+
if (lines.length > 0)
|
|
71
|
+
lines.push('');
|
|
72
|
+
// Session guidance based on type and findings
|
|
73
|
+
if (parallelForced) {
|
|
74
|
+
// parallel=true and same role already has a running dispatch → force new session
|
|
75
|
+
lines.push(`**Session**: 该角色已有运行中的 dispatch,强制启动新会话(parallel 模式)`);
|
|
76
|
+
lines.push('');
|
|
77
|
+
lines.push(`**Action**: ${agentDesc}。`);
|
|
78
|
+
}
|
|
79
|
+
else if (idleSession) {
|
|
80
|
+
const agentId = idleSession.agentSessionId
|
|
81
|
+
? `Agent session ID: \`${idleSession.agentSessionId}\``
|
|
82
|
+
: 'Agent session ID: not recorded';
|
|
83
|
+
const label = idleSession.label ? ` (${idleSession.label})` : '';
|
|
84
|
+
lines.push(`**Reusable session found**: ${idleSession.id}${label}`);
|
|
85
|
+
lines.push(`- ${agentId}`);
|
|
86
|
+
lines.push(`- Agent type: ${idleSession.agentType ?? 'unknown'}`);
|
|
87
|
+
lines.push(`- Last active: ${idleSession.lastActiveAt}`);
|
|
88
|
+
lines.push('');
|
|
89
|
+
if (sessionType === 'persistent') {
|
|
90
|
+
lines.push(`**Action**: 复用已有会话,而非启动新 agent。`);
|
|
91
|
+
lines.push(idleSession.agentSessionId
|
|
92
|
+
? `使用 \`--resume ${idleSession.agentSessionId}\` 或 \`--session ${idleSession.agentSessionId}\` 恢复会话。`
|
|
93
|
+
: `注意: 该会话未记录 agent session ID,可能需要${agentDesc}。`);
|
|
94
|
+
}
|
|
95
|
+
else {
|
|
96
|
+
// optional — suggestion, not directive
|
|
97
|
+
lines.push(`**Suggestion**: 存在空闲会话,可复用也可启动新会话,由你决定。`);
|
|
98
|
+
if (idleSession.agentSessionId) {
|
|
99
|
+
lines.push(`如需复用: \`--resume ${idleSession.agentSessionId}\` 或 \`--session ${idleSession.agentSessionId}\``);
|
|
100
|
+
}
|
|
101
|
+
}
|
|
102
|
+
}
|
|
103
|
+
else {
|
|
104
|
+
// No idle session found (or session type is 'none')
|
|
105
|
+
if (sessionType === 'none') {
|
|
106
|
+
lines.push(`**Session**: 每次 dispatch 启动全新会话(session: none)`);
|
|
107
|
+
}
|
|
108
|
+
else {
|
|
109
|
+
lines.push(`**未找到可复用会话**`);
|
|
110
|
+
lines.push(`Session type: ${sessionType}`);
|
|
111
|
+
}
|
|
112
|
+
lines.push('');
|
|
113
|
+
lines.push(`**Action**: ${agentDesc}。`);
|
|
114
|
+
}
|
|
115
|
+
return lines.join('\n');
|
|
116
|
+
}
|
|
117
|
+
/**
|
|
118
|
+
* Get file extension from artifact definition format.
|
|
119
|
+
* - 'html' → '.html'
|
|
120
|
+
* - 'json' → '.json'
|
|
121
|
+
* - 'md' or undefined → '.md'
|
|
122
|
+
*/
|
|
123
|
+
export function getFormatExtension(format) {
|
|
124
|
+
switch (format) {
|
|
125
|
+
case 'html':
|
|
126
|
+
return '.html';
|
|
127
|
+
case 'json':
|
|
128
|
+
return '.json';
|
|
129
|
+
default:
|
|
130
|
+
return '.md';
|
|
131
|
+
}
|
|
132
|
+
}
|
|
133
|
+
/**
|
|
134
|
+
* Resolve an artifact ID to a name + path reference.
|
|
135
|
+
*
|
|
136
|
+
* - Managed artifacts: resolves to full file path via format → extension mapping
|
|
137
|
+
* - Unmanaged artifacts: resolves to the output directory
|
|
138
|
+
* - Unknown artifacts: returns not-found
|
|
139
|
+
*/
|
|
140
|
+
export function resolveInputReference(artifactId, wf, ioCtx, existingArtifacts) {
|
|
141
|
+
const artifactDef = wf.artifactDefinitions[artifactId];
|
|
142
|
+
if (!artifactDef) {
|
|
143
|
+
return {
|
|
144
|
+
id: artifactId,
|
|
145
|
+
name: artifactId,
|
|
146
|
+
path: '',
|
|
147
|
+
found: false,
|
|
148
|
+
};
|
|
149
|
+
}
|
|
150
|
+
if (artifactDef.unmanaged) {
|
|
151
|
+
// Unmanaged: resolve to directory
|
|
152
|
+
const dir = resolveArtifactDir(artifactDef.output, ioCtx);
|
|
153
|
+
return {
|
|
154
|
+
id: artifactId,
|
|
155
|
+
name: artifactDef.name,
|
|
156
|
+
path: dir,
|
|
157
|
+
found: true, // unmanaged dirs are always "available"
|
|
158
|
+
};
|
|
159
|
+
}
|
|
160
|
+
// Managed: resolve to full file path via format → extension
|
|
161
|
+
const dir = resolveArtifactDir(artifactDef.output, ioCtx);
|
|
162
|
+
const ext = getFormatExtension(artifactDef.format);
|
|
163
|
+
const filePath = `${dir}/${artifactId}${ext}`;
|
|
164
|
+
return {
|
|
165
|
+
id: artifactId,
|
|
166
|
+
name: artifactDef.name,
|
|
167
|
+
path: filePath,
|
|
168
|
+
found: existingArtifacts.has(artifactId),
|
|
169
|
+
};
|
|
170
|
+
}
|
|
171
|
+
/**
|
|
172
|
+
* Build Artifact Requirements section for the dispatch data package.
|
|
173
|
+
* Only includes schemas for artifacts associated with the dispatched role
|
|
174
|
+
* (via the role's capabilities).
|
|
175
|
+
*/
|
|
176
|
+
async function buildArtifactRequirements(wf, workflowsDir, workflowName, role) {
|
|
177
|
+
const artifactDefs = wf.artifactDefinitions;
|
|
178
|
+
// Extract artifact IDs from role capabilities
|
|
179
|
+
const roleDef = wf.roles[role];
|
|
180
|
+
const roleArtifactIds = new Set();
|
|
181
|
+
if (roleDef?.frontmatter.capabilities) {
|
|
182
|
+
for (const cap of roleDef.frontmatter.capabilities) {
|
|
183
|
+
if (cap.artifact) {
|
|
184
|
+
roleArtifactIds.add(cap.artifact);
|
|
185
|
+
}
|
|
186
|
+
}
|
|
187
|
+
}
|
|
188
|
+
// If role has no artifact capabilities, skip
|
|
189
|
+
if (roleArtifactIds.size === 0)
|
|
190
|
+
return '';
|
|
191
|
+
const sections = [];
|
|
192
|
+
for (const artifactId of roleArtifactIds) {
|
|
193
|
+
const artifactDef = artifactDefs[artifactId];
|
|
194
|
+
if (!artifactDef || artifactDef.unmanaged)
|
|
195
|
+
continue;
|
|
196
|
+
// Load main schema
|
|
197
|
+
const schema = await loadArtifactSchema(workflowsDir, workflowName, artifactId);
|
|
198
|
+
// Load step schemas if artifact has steps
|
|
199
|
+
let stepSchemas;
|
|
200
|
+
if (artifactDef.steps && artifactDef.steps.length > 0) {
|
|
201
|
+
stepSchemas = [];
|
|
202
|
+
for (const step of artifactDef.steps) {
|
|
203
|
+
const stepSchema = await loadArtifactSchema(workflowsDir, workflowName, `${artifactId}.${step.id}`);
|
|
204
|
+
stepSchemas.push({ step, schema: stepSchema });
|
|
205
|
+
}
|
|
206
|
+
}
|
|
207
|
+
// Skip if no schema at all
|
|
208
|
+
if (!schema && (!stepSchemas || stepSchemas.every((s) => !s.schema)))
|
|
209
|
+
continue;
|
|
210
|
+
sections.push(formatSchemaGuidance(artifactId, artifactDef, schema, stepSchemas));
|
|
211
|
+
}
|
|
212
|
+
if (sections.length === 0)
|
|
213
|
+
return '';
|
|
214
|
+
return ['## Artifact Requirements', '', ...sections].join('\n');
|
|
215
|
+
}
|
|
216
|
+
export function registerDispatchRole(server, workflowsDir) {
|
|
217
|
+
server.tool('role_dispatch', "Prepare all data needed to dispatch a task to a team member. Returns the role's prompt (with capability overrides), configuration, input artifacts, task brief, and a dispatch tracking ID. Automatically searches for reusable sessions and provides guidance. Does NOT launch agents — you (coordinator) decide how to pass this to the team member. After launching, call dispatch_report to register the session.", {
|
|
218
|
+
project_name: z.string().describe('Project name'),
|
|
219
|
+
role: z.string().describe('Role ID to dispatch (e.g. architect, developer, tester)'),
|
|
220
|
+
task_brief: z
|
|
221
|
+
.string()
|
|
222
|
+
.describe('Task description for the team member — what they need to do, which tasks from the breakdown, specific instructions, etc.'),
|
|
223
|
+
node_id: z
|
|
224
|
+
.string()
|
|
225
|
+
.optional()
|
|
226
|
+
.describe('Target task node ID from the workflow tree. If omitted, automatically finds an active/pending task node for the specified role.'),
|
|
227
|
+
input_artifact_ids: z
|
|
228
|
+
.array(z.string())
|
|
229
|
+
.optional()
|
|
230
|
+
.describe('Supplementary artifact IDs to include as input references (name + path) for the team member. These are merged with the node-level inputArtifacts declaration. Note: only path references are provided, not content.'),
|
|
231
|
+
}, async ({ project_name, role, task_brief, node_id, input_artifact_ids }) => {
|
|
232
|
+
try {
|
|
233
|
+
const ctx = await resolveActive(project_name);
|
|
234
|
+
if (isError(ctx))
|
|
235
|
+
return ctx;
|
|
236
|
+
// Load project state and workflow plugin
|
|
237
|
+
const { wf, state } = await loadWorkflowForContext(workflowsDir, project_name, ctx);
|
|
238
|
+
// Validate role exists
|
|
239
|
+
const roleDef = wf.roles[role];
|
|
240
|
+
if (!roleDef) {
|
|
241
|
+
const available = Object.keys(wf.roles).join(', ');
|
|
242
|
+
return {
|
|
243
|
+
content: [
|
|
244
|
+
{
|
|
245
|
+
type: 'text',
|
|
246
|
+
text: `Role "${role}" not found. Available: ${available}`,
|
|
247
|
+
},
|
|
248
|
+
],
|
|
249
|
+
isError: true,
|
|
250
|
+
};
|
|
251
|
+
}
|
|
252
|
+
// Resolve target task node
|
|
253
|
+
let targetNode;
|
|
254
|
+
if (node_id) {
|
|
255
|
+
// Explicit node_id — validate it
|
|
256
|
+
targetNode = findTaskNode(wf, node_id);
|
|
257
|
+
if (!targetNode) {
|
|
258
|
+
return {
|
|
259
|
+
content: [
|
|
260
|
+
{
|
|
261
|
+
type: 'text',
|
|
262
|
+
text: `Node "${node_id}" not found or is not a task node in the workflow.`,
|
|
263
|
+
},
|
|
264
|
+
],
|
|
265
|
+
isError: true,
|
|
266
|
+
};
|
|
267
|
+
}
|
|
268
|
+
if (targetNode.role !== role) {
|
|
269
|
+
return {
|
|
270
|
+
content: [
|
|
271
|
+
{
|
|
272
|
+
type: 'text',
|
|
273
|
+
text: `Node "${node_id}" is assigned to role "${targetNode.role}", not "${role}".`,
|
|
274
|
+
},
|
|
275
|
+
],
|
|
276
|
+
isError: true,
|
|
277
|
+
};
|
|
278
|
+
}
|
|
279
|
+
// Validate node state allows dispatch
|
|
280
|
+
const nodeState = state.nodes[node_id];
|
|
281
|
+
if (nodeState && nodeState.status !== 'active' && nodeState.status !== 'pending') {
|
|
282
|
+
return {
|
|
283
|
+
content: [
|
|
284
|
+
{
|
|
285
|
+
type: 'text',
|
|
286
|
+
text: `Node "${node_id}" is in status "${nodeState.status}" — cannot dispatch. Only active or pending nodes can be dispatched.`,
|
|
287
|
+
},
|
|
288
|
+
],
|
|
289
|
+
isError: true,
|
|
290
|
+
};
|
|
291
|
+
}
|
|
292
|
+
}
|
|
293
|
+
else {
|
|
294
|
+
// Auto-find: look for active/pending task nodes for this role
|
|
295
|
+
const candidates = findDispatchableNodes(wf, state, role);
|
|
296
|
+
if (candidates.length === 0) {
|
|
297
|
+
return {
|
|
298
|
+
content: [
|
|
299
|
+
{
|
|
300
|
+
type: 'text',
|
|
301
|
+
text: `No active or pending task nodes found for role "${role}". Check project_status to see the current workflow state.`,
|
|
302
|
+
},
|
|
303
|
+
],
|
|
304
|
+
isError: true,
|
|
305
|
+
};
|
|
306
|
+
}
|
|
307
|
+
// Prefer active over pending
|
|
308
|
+
targetNode = candidates.find((t) => state.nodes[t.id]?.status === 'active') ?? candidates[0];
|
|
309
|
+
}
|
|
310
|
+
const targetNodeId = targetNode.id;
|
|
311
|
+
// Build I/O context for artifact path resolution
|
|
312
|
+
const ioCtx = {
|
|
313
|
+
contextDir: ctx.dir,
|
|
314
|
+
projectDir: ctx.entry.dir,
|
|
315
|
+
contextLabel: ctx.activeContext,
|
|
316
|
+
};
|
|
317
|
+
// Get merged overrides
|
|
318
|
+
const overrides = await getMergedOverrides(project_name);
|
|
319
|
+
// Build the full prompt with overrides injected
|
|
320
|
+
const overrideSection = buildOverrideSection(role, overrides);
|
|
321
|
+
let fullPrompt = overrideSection ? `${roleDef.prompt}\n${overrideSection}` : roleDef.prompt;
|
|
322
|
+
// Execute beforeDispatch hooks (if defined on the target node)
|
|
323
|
+
const hookInjections = [];
|
|
324
|
+
if (targetNode.beforeDispatch) {
|
|
325
|
+
// Collect static inject text
|
|
326
|
+
if (targetNode.beforeDispatch.inject) {
|
|
327
|
+
hookInjections.push(...targetNode.beforeDispatch.inject);
|
|
328
|
+
}
|
|
329
|
+
// Execute registered actions
|
|
330
|
+
if (targetNode.beforeDispatch.actions && wf.actions) {
|
|
331
|
+
const nodeState = state.nodes[targetNodeId];
|
|
332
|
+
// Resolve loopIteration: find ancestor loop node and read its current iteration
|
|
333
|
+
let loopIteration;
|
|
334
|
+
const ancestorLoopId = findAncestorLoopId(wf.definition.root, targetNodeId);
|
|
335
|
+
if (ancestorLoopId) {
|
|
336
|
+
const loopState = state.nodes[ancestorLoopId];
|
|
337
|
+
if (loopState) {
|
|
338
|
+
loopIteration = loopState.currentIteration;
|
|
339
|
+
}
|
|
340
|
+
}
|
|
341
|
+
const actionCtx = {
|
|
342
|
+
nodeId: targetNodeId,
|
|
343
|
+
role,
|
|
344
|
+
retryCount: nodeState?.retryCount ?? 0,
|
|
345
|
+
projectName: project_name,
|
|
346
|
+
pluginConfig: wf.config,
|
|
347
|
+
workflowState: state,
|
|
348
|
+
artifacts: {
|
|
349
|
+
read: (artifactId) => readArtifact(artifactId, ioCtx, wf.artifactDefinitions[artifactId]),
|
|
350
|
+
list: () => listArtifacts(ioCtx, wf.artifactDefinitions),
|
|
351
|
+
},
|
|
352
|
+
loopIteration,
|
|
353
|
+
};
|
|
354
|
+
for (const actionName of targetNode.beforeDispatch.actions) {
|
|
355
|
+
const handler = wf.actions[actionName];
|
|
356
|
+
if (handler) {
|
|
357
|
+
try {
|
|
358
|
+
const result = await handler(actionCtx);
|
|
359
|
+
if (result.inject) {
|
|
360
|
+
hookInjections.push(...result.inject);
|
|
361
|
+
}
|
|
362
|
+
}
|
|
363
|
+
catch (err) {
|
|
364
|
+
console.warn(`[harmonia] beforeDispatch action "${actionName}" failed:`, err);
|
|
365
|
+
}
|
|
366
|
+
}
|
|
367
|
+
else {
|
|
368
|
+
console.warn(`[harmonia] beforeDispatch action "${actionName}" not registered`);
|
|
369
|
+
}
|
|
370
|
+
}
|
|
371
|
+
}
|
|
372
|
+
}
|
|
373
|
+
// Append hook injections to the role prompt
|
|
374
|
+
if (hookInjections.length > 0) {
|
|
375
|
+
fullPrompt += '\n\n' + hookInjections.join('\n\n');
|
|
376
|
+
}
|
|
377
|
+
// Resolve input artifact references (merge node declaration + coordinator parameter)
|
|
378
|
+
const nodeInputIds = targetNode.inputArtifacts ?? [];
|
|
379
|
+
const paramInputIds = input_artifact_ids ?? [];
|
|
380
|
+
const mergedInputIds = [...new Set([...nodeInputIds, ...paramInputIds])];
|
|
381
|
+
// List existing artifacts for reference resolution
|
|
382
|
+
const existingArtifacts = new Set(await listArtifacts(ioCtx, wf.artifactDefinitions));
|
|
383
|
+
// Resolve all input references
|
|
384
|
+
const inputRefs = mergedInputIds.map((id) => resolveInputReference(id, wf, ioCtx, existingArtifacts));
|
|
385
|
+
const foundRefs = inputRefs.filter((r) => r.found);
|
|
386
|
+
const missingRefs = inputRefs.filter((r) => !r.found);
|
|
387
|
+
// Resolve agent/model: override takes precedence over frontmatter
|
|
388
|
+
const roleConfig = resolveRoleConfig(role, overrides);
|
|
389
|
+
const modelDisplay = roleConfig.model ?? roleDef.frontmatter.model;
|
|
390
|
+
const agentDisplay = roleConfig.agent ?? roleDef.frontmatter.agent;
|
|
391
|
+
const sessionType = roleDef.frontmatter.session;
|
|
392
|
+
// Determine session strategy based on session type + parallel field
|
|
393
|
+
let idleSession = null;
|
|
394
|
+
let parallelForced = false;
|
|
395
|
+
if (sessionType === 'none') {
|
|
396
|
+
// session: none → never look for idle sessions
|
|
397
|
+
idleSession = null;
|
|
398
|
+
}
|
|
399
|
+
else if (roleDef.frontmatter.parallel) {
|
|
400
|
+
// parallel=true → check if same role has running dispatches
|
|
401
|
+
const hasRunning = await hasRunningDispatch(project_name, ctx.number, role, ctx.dir);
|
|
402
|
+
if (hasRunning) {
|
|
403
|
+
// Force new session — don't look for idle ones
|
|
404
|
+
parallelForced = true;
|
|
405
|
+
idleSession = null;
|
|
406
|
+
}
|
|
407
|
+
else {
|
|
408
|
+
// No running dispatch → follow normal session behavior
|
|
409
|
+
idleSession = await findIdleSession(project_name, ctx.number, role, ctx.dir);
|
|
410
|
+
}
|
|
411
|
+
}
|
|
412
|
+
else {
|
|
413
|
+
// session: persistent or optional → look for idle sessions
|
|
414
|
+
idleSession = await findIdleSession(project_name, ctx.number, role, ctx.dir);
|
|
415
|
+
}
|
|
416
|
+
// Create dispatch record
|
|
417
|
+
const dispatch = await createDispatch(project_name, ctx.number, role, task_brief, [], // expectedOutputs — determined dynamically by workflow engine
|
|
418
|
+
idleSession?.id, ctx.dir, targetNodeId);
|
|
419
|
+
// Trigger engine event: dispatch_requested
|
|
420
|
+
const engineResult = await processWorkflowEvent(workflowsDir, project_name, ctx, {
|
|
421
|
+
type: 'dispatch_requested',
|
|
422
|
+
nodeId: targetNodeId,
|
|
423
|
+
});
|
|
424
|
+
const nextActionText = formatNextAction(engineResult.nextAction);
|
|
425
|
+
// Build session guidance (now includes model/agent info — replaces ## Configuration)
|
|
426
|
+
const sessionGuidance = buildSessionGuidance({
|
|
427
|
+
idleSession,
|
|
428
|
+
sessionType,
|
|
429
|
+
model: modelDisplay,
|
|
430
|
+
agent: agentDisplay,
|
|
431
|
+
parallelForced,
|
|
432
|
+
});
|
|
433
|
+
// Build artifact requirements for expected outputs
|
|
434
|
+
const artifactRequirements = await buildArtifactRequirements(wf, workflowsDir, state.workflow, role);
|
|
435
|
+
const summary = [
|
|
436
|
+
`# Dispatch: ${role}`,
|
|
437
|
+
``,
|
|
438
|
+
`## Dispatch Tracking`,
|
|
439
|
+
`- Dispatch ID: \`${dispatch.id}\``,
|
|
440
|
+
`- Status: ${dispatch.status}`,
|
|
441
|
+
`- Target Node: ${targetNodeId}`,
|
|
442
|
+
``,
|
|
443
|
+
`## Session Guidance`,
|
|
444
|
+
sessionGuidance,
|
|
445
|
+
``,
|
|
446
|
+
`## Task Brief`,
|
|
447
|
+
task_brief,
|
|
448
|
+
``,
|
|
449
|
+
`## Project Context`,
|
|
450
|
+
`- Project: ${project_name}`,
|
|
451
|
+
`- Directory: ${state.projectDir}`,
|
|
452
|
+
`- Workflow: ${state.workflow}`,
|
|
453
|
+
];
|
|
454
|
+
// Inject unmanaged artifact output path hints
|
|
455
|
+
const unmanagedHints = [];
|
|
456
|
+
for (const cap of roleDef.frontmatter.capabilities ?? []) {
|
|
457
|
+
if (!cap.artifact)
|
|
458
|
+
continue;
|
|
459
|
+
const def = wf.artifactDefinitions[cap.artifact];
|
|
460
|
+
if (!def?.unmanaged)
|
|
461
|
+
continue;
|
|
462
|
+
const outputDir = resolveArtifactDir(def.output, ioCtx);
|
|
463
|
+
unmanagedHints.push(`- **${cap.artifact}** (${def.name}): \`${outputDir}\``);
|
|
464
|
+
}
|
|
465
|
+
if (unmanagedHints.length > 0) {
|
|
466
|
+
summary.push(``, `## Unmanaged Artifact Output Paths`, `以下 artifact 由 agent 直接输出(非 artifact_write),请将产出写入对应路径:`, ...unmanagedHints);
|
|
467
|
+
}
|
|
468
|
+
summary.push(``, `## Input References (${foundRefs.length}${missingRefs.length > 0 ? `, ${missingRefs.length} missing` : ''})`);
|
|
469
|
+
if (foundRefs.length > 0) {
|
|
470
|
+
for (const ref of foundRefs) {
|
|
471
|
+
summary.push(`- **${ref.id}** (${ref.name}): \`${ref.path}\``);
|
|
472
|
+
}
|
|
473
|
+
}
|
|
474
|
+
if (missingRefs.length > 0) {
|
|
475
|
+
summary.push(``, `### Missing`);
|
|
476
|
+
for (const ref of missingRefs) {
|
|
477
|
+
summary.push(`- **${ref.id}** (${ref.name}): 未找到`);
|
|
478
|
+
}
|
|
479
|
+
}
|
|
480
|
+
summary.push(``, `## Next Step`, `After launching the agent, call \`dispatch_report\` with dispatch_id="${dispatch.id}" and the agent's session ID.`, `When the agent finishes, call \`dispatch_report\` again with status="completed" (or "failed").`);
|
|
481
|
+
if (artifactRequirements) {
|
|
482
|
+
summary.push(``, artifactRequirements);
|
|
483
|
+
}
|
|
484
|
+
summary.push(``, `## Role Prompt`, ``, fullPrompt);
|
|
485
|
+
summary.push(nextActionText);
|
|
486
|
+
return {
|
|
487
|
+
content: [
|
|
488
|
+
{
|
|
489
|
+
type: 'text',
|
|
490
|
+
text: summary.join('\n'),
|
|
491
|
+
},
|
|
492
|
+
],
|
|
493
|
+
};
|
|
494
|
+
}
|
|
495
|
+
catch (err) {
|
|
496
|
+
return {
|
|
497
|
+
content: [
|
|
498
|
+
{
|
|
499
|
+
type: 'text',
|
|
500
|
+
text: `Error: ${err instanceof Error ? err.message : String(err)}`,
|
|
501
|
+
},
|
|
502
|
+
],
|
|
503
|
+
isError: true,
|
|
504
|
+
};
|
|
505
|
+
}
|
|
506
|
+
});
|
|
507
|
+
}
|
|
508
|
+
//# sourceMappingURL=role-dispatch.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"role-dispatch.js","sourceRoot":"","sources":["../../src/tools/role-dispatch.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,40 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Shared utility for tool handlers — resolves the active context (iteration or patch)
|
|
3
|
+
* for a project. All tools that operate on iteration/patch-level data should use this
|
|
4
|
+
* instead of directly reading entry.currentIteration.
|
|
5
|
+
*/
|
|
6
|
+
import type { ProjectEntry } from '../core/registry.js';
|
|
7
|
+
import type { OverrideConfig } from '../core/types.js';
|
|
8
|
+
export interface ResolvedContext {
|
|
9
|
+
entry: ProjectEntry;
|
|
10
|
+
/** The iteration or patch number */
|
|
11
|
+
number: number;
|
|
12
|
+
/** "iteration" or "patch" */
|
|
13
|
+
type: 'iteration' | 'patch';
|
|
14
|
+
/** Absolute path to the context directory (iter-N/ or patch-N/) */
|
|
15
|
+
dir: string;
|
|
16
|
+
/** The raw activeContext string, e.g. "iter-1" or "patch-2" */
|
|
17
|
+
activeContext: string;
|
|
18
|
+
}
|
|
19
|
+
type ToolResult = {
|
|
20
|
+
content: {
|
|
21
|
+
type: 'text';
|
|
22
|
+
text: string;
|
|
23
|
+
}[];
|
|
24
|
+
isError?: boolean;
|
|
25
|
+
};
|
|
26
|
+
/**
|
|
27
|
+
* Resolve the active context for a project. Returns either a ResolvedContext
|
|
28
|
+
* or a ToolResult error (to be returned directly from the tool handler).
|
|
29
|
+
*/
|
|
30
|
+
export declare function resolveActive(projectName: string): Promise<ResolvedContext | ToolResult>;
|
|
31
|
+
/**
|
|
32
|
+
* Type guard: check if the result is an error (ToolResult) or a resolved context.
|
|
33
|
+
*/
|
|
34
|
+
export declare function isError(result: ResolvedContext | ToolResult): result is ToolResult;
|
|
35
|
+
/**
|
|
36
|
+
* Build override instructions to inject into a role prompt.
|
|
37
|
+
* Shared by role-dispatch and get-role-prompt.
|
|
38
|
+
*/
|
|
39
|
+
export declare function buildOverrideSection(roleId: string, overrides: OverrideConfig): string;
|
|
40
|
+
export {};
|
|
@@ -0,0 +1,97 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Shared utility for tool handlers — resolves the active context (iteration or patch)
|
|
3
|
+
* for a project. All tools that operate on iteration/patch-level data should use this
|
|
4
|
+
* instead of directly reading entry.currentIteration.
|
|
5
|
+
*/
|
|
6
|
+
import { getProject, resolveContextDir } from '../core/registry.js';
|
|
7
|
+
/**
|
|
8
|
+
* Resolve the active context for a project. Returns either a ResolvedContext
|
|
9
|
+
* or a ToolResult error (to be returned directly from the tool handler).
|
|
10
|
+
*/
|
|
11
|
+
export async function resolveActive(projectName) {
|
|
12
|
+
const entry = await getProject(projectName);
|
|
13
|
+
if (!entry) {
|
|
14
|
+
return {
|
|
15
|
+
content: [
|
|
16
|
+
{
|
|
17
|
+
type: 'text',
|
|
18
|
+
text: `项目 "${projectName}" 未注册。请先调用 project_init 注册项目。`,
|
|
19
|
+
},
|
|
20
|
+
],
|
|
21
|
+
isError: true,
|
|
22
|
+
};
|
|
23
|
+
}
|
|
24
|
+
if (!entry.activeContext) {
|
|
25
|
+
return {
|
|
26
|
+
content: [
|
|
27
|
+
{
|
|
28
|
+
type: 'text',
|
|
29
|
+
text: `项目 "${projectName}" 尚未开始迭代或补丁。请先调用 iteration_start 或 patch_start。`,
|
|
30
|
+
},
|
|
31
|
+
],
|
|
32
|
+
isError: true,
|
|
33
|
+
};
|
|
34
|
+
}
|
|
35
|
+
const resolved = resolveContextDir(projectName, entry.activeContext);
|
|
36
|
+
if (!resolved) {
|
|
37
|
+
return {
|
|
38
|
+
content: [
|
|
39
|
+
{
|
|
40
|
+
type: 'text',
|
|
41
|
+
text: `项目 "${projectName}" 的 activeContext "${entry.activeContext}" 无法解析。数据可能已损坏。`,
|
|
42
|
+
},
|
|
43
|
+
],
|
|
44
|
+
isError: true,
|
|
45
|
+
};
|
|
46
|
+
}
|
|
47
|
+
return {
|
|
48
|
+
entry,
|
|
49
|
+
number: resolved.number,
|
|
50
|
+
type: resolved.type,
|
|
51
|
+
dir: resolved.dir,
|
|
52
|
+
activeContext: entry.activeContext,
|
|
53
|
+
};
|
|
54
|
+
}
|
|
55
|
+
/**
|
|
56
|
+
* Type guard: check if the result is an error (ToolResult) or a resolved context.
|
|
57
|
+
*/
|
|
58
|
+
export function isError(result) {
|
|
59
|
+
return 'content' in result && !('entry' in result);
|
|
60
|
+
}
|
|
61
|
+
/**
|
|
62
|
+
* Build override instructions to inject into a role prompt.
|
|
63
|
+
* Shared by role-dispatch and get-role-prompt.
|
|
64
|
+
*/
|
|
65
|
+
export function buildOverrideSection(roleId, overrides) {
|
|
66
|
+
const roleOverrides = overrides.roles?.[roleId]?.capabilities;
|
|
67
|
+
if (!roleOverrides || Object.keys(roleOverrides).length === 0) {
|
|
68
|
+
return '';
|
|
69
|
+
}
|
|
70
|
+
const lines = [
|
|
71
|
+
'',
|
|
72
|
+
'## Enhanced Capabilities',
|
|
73
|
+
'',
|
|
74
|
+
'The following capabilities have been configured to use external tools.',
|
|
75
|
+
'Use the specified tool instead of built-in behavior for these actions.',
|
|
76
|
+
'',
|
|
77
|
+
];
|
|
78
|
+
for (const [capId, override] of Object.entries(roleOverrides)) {
|
|
79
|
+
const o = override;
|
|
80
|
+
const toolRef = o.type === 'mcp' && o.server
|
|
81
|
+
? `\`${o.server}\` MCP server's \`${o.tool}\` tool`
|
|
82
|
+
: `\`${o.tool}\` skill tool`;
|
|
83
|
+
let instruction = `- **${capId}**: Use ${toolRef}`;
|
|
84
|
+
if (o.params && Object.keys(o.params).length > 0) {
|
|
85
|
+
const paramStr = Object.entries(o.params)
|
|
86
|
+
.map(([k, v]) => `${k}: ${JSON.stringify(v)}`)
|
|
87
|
+
.join(', ');
|
|
88
|
+
instruction += ` with fixed parameters: ${paramStr}`;
|
|
89
|
+
}
|
|
90
|
+
if (o.notes) {
|
|
91
|
+
instruction += `. Note: ${o.notes}`;
|
|
92
|
+
}
|
|
93
|
+
lines.push(instruction);
|
|
94
|
+
}
|
|
95
|
+
return lines.join('\n');
|
|
96
|
+
}
|
|
97
|
+
//# sourceMappingURL=utils.js.map
|