@s_s/harmonia 1.0.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 +3 -0
- package/build/core/dispatch.d.ts +38 -0
- package/build/core/dispatch.js +156 -0
- package/build/core/dispatch.js.map +1 -0
- package/build/core/docs.d.ts +19 -0
- package/build/core/docs.js +59 -0
- package/build/core/docs.js.map +1 -0
- package/build/core/overrides.d.ts +62 -0
- package/build/core/overrides.js +206 -0
- package/build/core/overrides.js.map +1 -0
- package/build/core/registry.d.ts +72 -0
- package/build/core/registry.js +121 -0
- package/build/core/registry.js.map +1 -0
- package/build/core/reviews.d.ts +26 -0
- package/build/core/reviews.js +83 -0
- package/build/core/reviews.js.map +1 -0
- package/build/core/state.d.ts +26 -0
- package/build/core/state.js +103 -0
- package/build/core/state.js.map +1 -0
- package/build/core/types.d.ts +181 -0
- package/build/core/types.js +6 -0
- package/build/core/types.js.map +1 -0
- package/build/core/workflow.d.ts +13 -0
- package/build/core/workflow.js +63 -0
- package/build/core/workflow.js.map +1 -0
- package/build/index.d.ts +15 -0
- package/build/index.js +57 -0
- package/build/index.js.map +1 -0
- package/build/setup/inject.d.ts +34 -0
- package/build/setup/inject.js +115 -0
- package/build/setup/inject.js.map +1 -0
- package/build/setup/templates.d.ts +21 -0
- package/build/setup/templates.js +177 -0
- package/build/setup/templates.js.map +1 -0
- package/build/tools/approve-doc.d.ts +6 -0
- package/build/tools/approve-doc.js +79 -0
- package/build/tools/approve-doc.js.map +1 -0
- package/build/tools/dispatch-role.d.ts +16 -0
- package/build/tools/dispatch-role.js +232 -0
- package/build/tools/dispatch-role.js.map +1 -0
- package/build/tools/doc-tools.d.ts +8 -0
- package/build/tools/doc-tools.js +102 -0
- package/build/tools/doc-tools.js.map +1 -0
- package/build/tools/get-project-status.d.ts +8 -0
- package/build/tools/get-project-status.js +230 -0
- package/build/tools/get-project-status.js.map +1 -0
- package/build/tools/get-role-prompt.d.ts +7 -0
- package/build/tools/get-role-prompt.js +95 -0
- package/build/tools/get-role-prompt.js.map +1 -0
- package/build/tools/override-tools.d.ts +6 -0
- package/build/tools/override-tools.js +129 -0
- package/build/tools/override-tools.js.map +1 -0
- package/build/tools/project-init.d.ts +6 -0
- package/build/tools/project-init.js +71 -0
- package/build/tools/project-init.js.map +1 -0
- package/build/tools/report-dispatch.d.ts +11 -0
- package/build/tools/report-dispatch.js +142 -0
- package/build/tools/report-dispatch.js.map +1 -0
- package/build/tools/setup-project.d.ts +8 -0
- package/build/tools/setup-project.js +88 -0
- package/build/tools/setup-project.js.map +1 -0
- package/build/tools/update-phase.d.ts +7 -0
- package/build/tools/update-phase.js +79 -0
- package/build/tools/update-phase.js.map +1 -0
- package/package.json +51 -0
- package/workflows/dev/roles/architect.md +66 -0
- package/workflows/dev/roles/developer.md +44 -0
- package/workflows/dev/roles/pm.md +99 -0
- package/workflows/dev/roles/tester.md +44 -0
- package/workflows/dev/workflow.json +134 -0
|
@@ -0,0 +1,95 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* MCP Tool: get_role_prompt
|
|
3
|
+
* Retrieve the prompt and configuration for a specific role,
|
|
4
|
+
* with capability overrides injected into the prompt.
|
|
5
|
+
*/
|
|
6
|
+
import { z } from 'zod';
|
|
7
|
+
import { loadWorkflow } from '../core/workflow.js';
|
|
8
|
+
import { getMergedOverrides } from '../core/overrides.js';
|
|
9
|
+
/**
|
|
10
|
+
* Generate override prompt instructions for a role based on configured overrides.
|
|
11
|
+
*/
|
|
12
|
+
function buildOverridePromptSection(roleId, overrides) {
|
|
13
|
+
const roleOverrides = overrides.roles?.[roleId]?.capabilities;
|
|
14
|
+
if (!roleOverrides || Object.keys(roleOverrides).length === 0) {
|
|
15
|
+
return '';
|
|
16
|
+
}
|
|
17
|
+
const lines = [
|
|
18
|
+
'',
|
|
19
|
+
'## Enhanced Capabilities',
|
|
20
|
+
'',
|
|
21
|
+
'The following capabilities have been configured to use external tools.',
|
|
22
|
+
'When performing these actions, use the specified tool instead of built-in behavior.',
|
|
23
|
+
'',
|
|
24
|
+
];
|
|
25
|
+
for (const [capId, override] of Object.entries(roleOverrides)) {
|
|
26
|
+
const o = override;
|
|
27
|
+
const toolRef = o.type === 'mcp' && o.server
|
|
28
|
+
? `\`${o.server}\` MCP server's \`${o.tool}\` tool`
|
|
29
|
+
: `\`${o.tool}\` skill tool`;
|
|
30
|
+
let instruction = `- **${capId}**: Use ${toolRef}`;
|
|
31
|
+
if (o.params && Object.keys(o.params).length > 0) {
|
|
32
|
+
const paramStr = Object.entries(o.params)
|
|
33
|
+
.map(([k, v]) => `${k}: ${JSON.stringify(v)}`)
|
|
34
|
+
.join(', ');
|
|
35
|
+
instruction += ` with fixed parameters: ${paramStr}`;
|
|
36
|
+
}
|
|
37
|
+
if (o.notes) {
|
|
38
|
+
instruction += `. Note: ${o.notes}`;
|
|
39
|
+
}
|
|
40
|
+
lines.push(instruction);
|
|
41
|
+
}
|
|
42
|
+
return lines.join('\n');
|
|
43
|
+
}
|
|
44
|
+
export function registerGetRolePrompt(server, workflowsDir) {
|
|
45
|
+
server.tool('get_role_prompt', "Get the system prompt and configuration for a specific role in the workflow. Includes any capability overrides configured at global or project level. Use this to understand what a role does or to set up an agent with the role's prompt.", {
|
|
46
|
+
workflow: z.string().default('dev').describe('Workflow name (default: dev)'),
|
|
47
|
+
role: z.string().describe('Role ID (e.g. pm, architect, developer, tester)'),
|
|
48
|
+
project_name: z
|
|
49
|
+
.string()
|
|
50
|
+
.optional()
|
|
51
|
+
.describe('Project name — if provided, includes project-specific capability overrides in the prompt'),
|
|
52
|
+
}, async ({ workflow: workflowName, role, project_name }) => {
|
|
53
|
+
const wf = await loadWorkflow(workflowsDir, workflowName);
|
|
54
|
+
const roleDef = wf.roles[role];
|
|
55
|
+
if (!roleDef) {
|
|
56
|
+
const available = Object.keys(wf.roles).join(', ');
|
|
57
|
+
return {
|
|
58
|
+
content: [
|
|
59
|
+
{
|
|
60
|
+
type: 'text',
|
|
61
|
+
text: `Role "${role}" not found in workflow "${workflowName}". Available roles: ${available}`,
|
|
62
|
+
},
|
|
63
|
+
],
|
|
64
|
+
isError: true,
|
|
65
|
+
};
|
|
66
|
+
}
|
|
67
|
+
// Build override section if project_name is provided
|
|
68
|
+
let overrideSection = '';
|
|
69
|
+
if (project_name) {
|
|
70
|
+
const overrides = await getMergedOverrides(project_name);
|
|
71
|
+
overrideSection = buildOverridePromptSection(role, overrides);
|
|
72
|
+
}
|
|
73
|
+
return {
|
|
74
|
+
content: [
|
|
75
|
+
{
|
|
76
|
+
type: 'text',
|
|
77
|
+
text: [
|
|
78
|
+
`# Role: ${roleDef.id}`,
|
|
79
|
+
``,
|
|
80
|
+
`## Configuration`,
|
|
81
|
+
`- Model level: ${roleDef.frontmatter.model}`,
|
|
82
|
+
`- Session: ${roleDef.frontmatter.session}`,
|
|
83
|
+
`- Parallel: ${roleDef.frontmatter.parallel}`,
|
|
84
|
+
``,
|
|
85
|
+
`## Prompt`,
|
|
86
|
+
``,
|
|
87
|
+
roleDef.prompt,
|
|
88
|
+
overrideSection,
|
|
89
|
+
].join('\n'),
|
|
90
|
+
},
|
|
91
|
+
],
|
|
92
|
+
};
|
|
93
|
+
});
|
|
94
|
+
}
|
|
95
|
+
//# sourceMappingURL=get-role-prompt.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"get-role-prompt.js","sourceRoot":"","sources":["../../src/tools/get-role-prompt.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,129 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* MCP Tools: set_override / get_overrides
|
|
3
|
+
* Manage capability overrides and review settings.
|
|
4
|
+
*/
|
|
5
|
+
import { z } from 'zod';
|
|
6
|
+
import { setCapabilityOverride, setReviewOverride, getMergedOverrides, readGlobalOverrides, readProjectOverrides, } from '../core/overrides.js';
|
|
7
|
+
export function registerOverrideTools(server) {
|
|
8
|
+
server.tool('set_capability_override', 'Configure a role capability to use an external skill or MCP tool instead of the built-in behavior. Settings are saved to the override config file.', {
|
|
9
|
+
scope: z.enum(['global', 'project']).describe('Override scope: global (all projects) or project-specific'),
|
|
10
|
+
project_name: z.string().optional().describe("Project name (required when scope is 'project')"),
|
|
11
|
+
role_id: z.string().describe('Role ID (e.g. pm, architect, developer, tester)'),
|
|
12
|
+
capability_id: z.string().describe('Capability ID (e.g. write-prd, write-tech-design)'),
|
|
13
|
+
type: z.enum(['skill', 'mcp']).describe('Tool source type'),
|
|
14
|
+
tool: z.string().describe('Tool name'),
|
|
15
|
+
server_name: z.string().optional().describe("MCP server name (required when type is 'mcp')"),
|
|
16
|
+
params: z
|
|
17
|
+
.record(z.string(), z.unknown())
|
|
18
|
+
.optional()
|
|
19
|
+
.describe('Static parameters to always pass when calling the tool'),
|
|
20
|
+
notes: z.string().optional().describe('Additional notes for prompt generation (rarely needed)'),
|
|
21
|
+
}, async ({ scope, project_name, role_id, capability_id, type, tool, server_name, params, notes }) => {
|
|
22
|
+
if (scope === 'project' && !project_name) {
|
|
23
|
+
return {
|
|
24
|
+
content: [
|
|
25
|
+
{
|
|
26
|
+
type: 'text',
|
|
27
|
+
text: "Error: project_name is required when scope is 'project'.",
|
|
28
|
+
},
|
|
29
|
+
],
|
|
30
|
+
isError: true,
|
|
31
|
+
};
|
|
32
|
+
}
|
|
33
|
+
const override = { type, tool };
|
|
34
|
+
if (server_name)
|
|
35
|
+
override.server = server_name;
|
|
36
|
+
if (params)
|
|
37
|
+
override.params = params;
|
|
38
|
+
if (notes)
|
|
39
|
+
override.notes = notes;
|
|
40
|
+
await setCapabilityOverride(scope, project_name ?? null, role_id, capability_id, override);
|
|
41
|
+
return {
|
|
42
|
+
content: [
|
|
43
|
+
{
|
|
44
|
+
type: 'text',
|
|
45
|
+
text: `Override set: ${role_id}.${capability_id} → ${type === 'mcp' ? `${server_name}/${tool}` : tool} (${scope})`,
|
|
46
|
+
},
|
|
47
|
+
],
|
|
48
|
+
};
|
|
49
|
+
});
|
|
50
|
+
server.tool('set_review_override', 'Enable or disable review requirement for a specific document type.', {
|
|
51
|
+
scope: z.enum(['global', 'project']).describe('Override scope: global or project-specific'),
|
|
52
|
+
project_name: z.string().optional().describe("Project name (required when scope is 'project')"),
|
|
53
|
+
doc_id: z.string().describe('Document ID (e.g. prd, prototype)'),
|
|
54
|
+
enabled: z.boolean().describe('true = require review, false = skip review'),
|
|
55
|
+
}, async ({ scope, project_name, doc_id, enabled }) => {
|
|
56
|
+
if (scope === 'project' && !project_name) {
|
|
57
|
+
return {
|
|
58
|
+
content: [
|
|
59
|
+
{
|
|
60
|
+
type: 'text',
|
|
61
|
+
text: "Error: project_name is required when scope is 'project'.",
|
|
62
|
+
},
|
|
63
|
+
],
|
|
64
|
+
isError: true,
|
|
65
|
+
};
|
|
66
|
+
}
|
|
67
|
+
await setReviewOverride(scope, project_name ?? null, doc_id, enabled);
|
|
68
|
+
return {
|
|
69
|
+
content: [
|
|
70
|
+
{
|
|
71
|
+
type: 'text',
|
|
72
|
+
text: `Review override set: ${doc_id} → ${enabled ? 'required' : 'skipped'} (${scope})`,
|
|
73
|
+
},
|
|
74
|
+
],
|
|
75
|
+
};
|
|
76
|
+
});
|
|
77
|
+
server.tool('get_overrides', 'Get the current override configuration. Shows the merged result (project + global) or a specific scope.', {
|
|
78
|
+
project_name: z
|
|
79
|
+
.string()
|
|
80
|
+
.optional()
|
|
81
|
+
.describe('Project name — if provided, shows merged config for this project'),
|
|
82
|
+
scope: z
|
|
83
|
+
.enum(['merged', 'global', 'project'])
|
|
84
|
+
.default('merged')
|
|
85
|
+
.describe('Which config to show: merged (default), global only, or project only'),
|
|
86
|
+
}, async ({ project_name, scope }) => {
|
|
87
|
+
let config;
|
|
88
|
+
let label;
|
|
89
|
+
if (scope === 'global') {
|
|
90
|
+
config = await readGlobalOverrides();
|
|
91
|
+
label = 'Global overrides';
|
|
92
|
+
}
|
|
93
|
+
else if (scope === 'project') {
|
|
94
|
+
if (!project_name) {
|
|
95
|
+
return {
|
|
96
|
+
content: [
|
|
97
|
+
{
|
|
98
|
+
type: 'text',
|
|
99
|
+
text: "Error: project_name is required when scope is 'project'.",
|
|
100
|
+
},
|
|
101
|
+
],
|
|
102
|
+
isError: true,
|
|
103
|
+
};
|
|
104
|
+
}
|
|
105
|
+
config = await readProjectOverrides(project_name);
|
|
106
|
+
label = `Project overrides for "${project_name}"`;
|
|
107
|
+
}
|
|
108
|
+
else {
|
|
109
|
+
if (!project_name) {
|
|
110
|
+
config = await readGlobalOverrides();
|
|
111
|
+
label = 'Global overrides (no project specified)';
|
|
112
|
+
}
|
|
113
|
+
else {
|
|
114
|
+
config = await getMergedOverrides(project_name);
|
|
115
|
+
label = `Merged overrides for "${project_name}"`;
|
|
116
|
+
}
|
|
117
|
+
}
|
|
118
|
+
const isEmpty = !config.review && (!config.roles || Object.keys(config.roles).length === 0);
|
|
119
|
+
return {
|
|
120
|
+
content: [
|
|
121
|
+
{
|
|
122
|
+
type: 'text',
|
|
123
|
+
text: isEmpty ? `${label}: (none configured)` : `${label}:\n${JSON.stringify(config, null, 2)}`,
|
|
124
|
+
},
|
|
125
|
+
],
|
|
126
|
+
};
|
|
127
|
+
});
|
|
128
|
+
}
|
|
129
|
+
//# sourceMappingURL=override-tools.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"override-tools.js","sourceRoot":"","sources":["../../src/tools/override-tools.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,6 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* MCP Tool: project_init
|
|
3
|
+
* Initialize a new Harmonia project with global registry and data directory.
|
|
4
|
+
*/
|
|
5
|
+
import type { McpServer } from '@modelcontextprotocol/sdk/server/mcp.js';
|
|
6
|
+
export declare function registerProjectInit(server: McpServer, workflowsDir: string): void;
|
|
@@ -0,0 +1,71 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* MCP Tool: project_init
|
|
3
|
+
* Initialize a new Harmonia project with global registry and data directory.
|
|
4
|
+
*/
|
|
5
|
+
import { z } from 'zod';
|
|
6
|
+
import { loadWorkflow } from '../core/workflow.js';
|
|
7
|
+
import { initProjectState, readState } from '../core/state.js';
|
|
8
|
+
import { registerProject, getProject } from '../core/registry.js';
|
|
9
|
+
export function registerProjectInit(server, workflowsDir) {
|
|
10
|
+
server.tool('project_init', "Initialize a new Harmonia project. Registers the project in the global data directory, creates data directories for documents/state, and creates the project source directory if it doesn't exist.", {
|
|
11
|
+
project_name: z.string().describe('Unique project name (used as directory name in the data directory)'),
|
|
12
|
+
project_dir: z
|
|
13
|
+
.string()
|
|
14
|
+
.describe("Absolute path to the project source directory (will be created if it doesn't exist)"),
|
|
15
|
+
workflow: z.string().default('dev').describe('Workflow name to use (default: dev)'),
|
|
16
|
+
scale: z.enum(['small', 'medium', 'large']).default('small').describe('Project scale (small/medium/large)'),
|
|
17
|
+
}, async ({ project_name, project_dir, workflow: workflowName, scale }) => {
|
|
18
|
+
// Check if already initialized
|
|
19
|
+
const existing = await getProject(project_name);
|
|
20
|
+
if (existing) {
|
|
21
|
+
const state = await readState(project_name);
|
|
22
|
+
return {
|
|
23
|
+
content: [
|
|
24
|
+
{
|
|
25
|
+
type: 'text',
|
|
26
|
+
text: `Project "${project_name}" already exists.\n\nSource directory: ${existing.dir}\n\nCurrent state:\n${JSON.stringify(state, null, 2)}`,
|
|
27
|
+
},
|
|
28
|
+
],
|
|
29
|
+
};
|
|
30
|
+
}
|
|
31
|
+
// Load workflow definition
|
|
32
|
+
const wf = await loadWorkflow(workflowsDir, workflowName);
|
|
33
|
+
// Register project (creates global data dirs + project source dir)
|
|
34
|
+
await registerProject(project_name, project_dir, workflowName);
|
|
35
|
+
// Initialize project state
|
|
36
|
+
const state = await initProjectState(project_name, project_dir, wf, scale);
|
|
37
|
+
// Build doc list based on scale
|
|
38
|
+
const requiredDocs = Object.entries(wf.definition.docs)
|
|
39
|
+
.filter(([, doc]) => {
|
|
40
|
+
const s = doc.scale[scale];
|
|
41
|
+
return s === 'full' || s === 'lite';
|
|
42
|
+
})
|
|
43
|
+
.map(([id, doc]) => `- ${doc.name} (${id})`)
|
|
44
|
+
.join('\n');
|
|
45
|
+
const optionalDocs = Object.entries(wf.definition.docs)
|
|
46
|
+
.filter(([, doc]) => doc.scale[scale] === 'optional')
|
|
47
|
+
.map(([id, doc]) => `- ${doc.name} (${id})`)
|
|
48
|
+
.join('\n');
|
|
49
|
+
return {
|
|
50
|
+
content: [
|
|
51
|
+
{
|
|
52
|
+
type: 'text',
|
|
53
|
+
text: [
|
|
54
|
+
`Project "${project_name}" initialized successfully.`,
|
|
55
|
+
``,
|
|
56
|
+
`Source directory: ${project_dir}`,
|
|
57
|
+
`Workflow: ${wf.definition.name} (${wf.definition.description})`,
|
|
58
|
+
`Scale: ${scale}`,
|
|
59
|
+
`Current phase: ${state.currentPhase}`,
|
|
60
|
+
`Available roles: ${Object.keys(wf.roles).join(', ')}`,
|
|
61
|
+
``,
|
|
62
|
+
`Required documents:`,
|
|
63
|
+
requiredDocs || '(none)',
|
|
64
|
+
optionalDocs ? `\nOptional documents:\n${optionalDocs}` : '',
|
|
65
|
+
].join('\n'),
|
|
66
|
+
},
|
|
67
|
+
],
|
|
68
|
+
};
|
|
69
|
+
});
|
|
70
|
+
}
|
|
71
|
+
//# sourceMappingURL=project-init.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"project-init.js","sourceRoot":"","sources":["../../src/tools/project-init.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* MCP Tool: report_dispatch
|
|
3
|
+
*
|
|
4
|
+
* PM calls this tool to report dispatch status changes:
|
|
5
|
+
* 1. After launching an agent: provide agent_session_id → creates/reuses session, marks dispatch running
|
|
6
|
+
* 2. After agent finishes: provide status=completed/failed → updates dispatch, session goes idle/closed
|
|
7
|
+
*
|
|
8
|
+
* This is the single tool PM needs for all dispatch lifecycle management.
|
|
9
|
+
*/
|
|
10
|
+
import type { McpServer } from '@modelcontextprotocol/sdk/server/mcp.js';
|
|
11
|
+
export declare function registerReportDispatch(server: McpServer): void;
|
|
@@ -0,0 +1,142 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* MCP Tool: report_dispatch
|
|
3
|
+
*
|
|
4
|
+
* PM calls this tool to report dispatch status changes:
|
|
5
|
+
* 1. After launching an agent: provide agent_session_id → creates/reuses session, marks dispatch running
|
|
6
|
+
* 2. After agent finishes: provide status=completed/failed → updates dispatch, session goes idle/closed
|
|
7
|
+
*
|
|
8
|
+
* This is the single tool PM needs for all dispatch lifecycle management.
|
|
9
|
+
*/
|
|
10
|
+
import { z } from 'zod';
|
|
11
|
+
import { getDispatch, updateDispatch, createSession, updateSession, findSessionByAgentId, readSessions, } from '../core/dispatch.js';
|
|
12
|
+
export function registerReportDispatch(server) {
|
|
13
|
+
server.tool('report_dispatch', 'Report dispatch status after launching or completing a team member agent. Call with agent_session_id after launching to register the session. Call with status="completed" or "failed" when the agent finishes.', {
|
|
14
|
+
project_name: z.string().describe('Project name'),
|
|
15
|
+
dispatch_id: z.string().describe('Dispatch ID returned by dispatch_role'),
|
|
16
|
+
status: z
|
|
17
|
+
.enum(['running', 'completed', 'failed', 'cancelled'])
|
|
18
|
+
.optional()
|
|
19
|
+
.describe('New dispatch status. Omit when only registering agent_session_id (defaults to "running").'),
|
|
20
|
+
agent_session_id: z
|
|
21
|
+
.string()
|
|
22
|
+
.optional()
|
|
23
|
+
.describe('The actual session ID from the host agent (e.g. OpenCode session ID). Provide on first report after launching.'),
|
|
24
|
+
agent_type: z
|
|
25
|
+
.enum(['opencode', 'openclaw', 'claude-code', 'codex'])
|
|
26
|
+
.optional()
|
|
27
|
+
.describe('Agent type used for this dispatch'),
|
|
28
|
+
label: z.string().optional().describe('Optional label for the session (e.g. "dev-auth-module")'),
|
|
29
|
+
note: z.string().optional().describe('Optional note (e.g. failure reason)'),
|
|
30
|
+
}, async ({ project_name, dispatch_id, status, agent_session_id, agent_type, label, note }) => {
|
|
31
|
+
try {
|
|
32
|
+
// Load the dispatch record
|
|
33
|
+
const dispatch = await getDispatch(project_name, dispatch_id);
|
|
34
|
+
if (!dispatch) {
|
|
35
|
+
return {
|
|
36
|
+
content: [
|
|
37
|
+
{
|
|
38
|
+
type: 'text',
|
|
39
|
+
text: `Dispatch "${dispatch_id}" not found in project "${project_name}".`,
|
|
40
|
+
},
|
|
41
|
+
],
|
|
42
|
+
isError: true,
|
|
43
|
+
};
|
|
44
|
+
}
|
|
45
|
+
const effectiveStatus = status ?? 'running';
|
|
46
|
+
const results = [];
|
|
47
|
+
// Handle session registration (when agent_session_id is provided)
|
|
48
|
+
let session = null;
|
|
49
|
+
if (agent_session_id) {
|
|
50
|
+
session = await resolveOrCreateSession(project_name, dispatch, agent_session_id, agent_type, label);
|
|
51
|
+
results.push(`Session: ${session.id} (agent: ${agent_session_id}, status: ${session.status})`);
|
|
52
|
+
}
|
|
53
|
+
// Handle status transitions
|
|
54
|
+
if (effectiveStatus === 'completed' ||
|
|
55
|
+
effectiveStatus === 'failed' ||
|
|
56
|
+
effectiveStatus === 'cancelled') {
|
|
57
|
+
// Terminal states: update dispatch and transition session
|
|
58
|
+
await updateDispatch(project_name, dispatch_id, {
|
|
59
|
+
status: effectiveStatus,
|
|
60
|
+
...(session ? { sessionId: session.id } : {}),
|
|
61
|
+
...(note ? { note } : {}),
|
|
62
|
+
});
|
|
63
|
+
// Transition session: completed → idle, failed → lost
|
|
64
|
+
const sessionId = session?.id ?? dispatch.sessionId;
|
|
65
|
+
if (sessionId) {
|
|
66
|
+
const newSessionStatus = effectiveStatus === 'completed' ? 'idle' : 'lost';
|
|
67
|
+
await updateSession(project_name, sessionId, { status: newSessionStatus });
|
|
68
|
+
results.push(`Session ${sessionId} → ${newSessionStatus}`);
|
|
69
|
+
}
|
|
70
|
+
results.push(`Dispatch ${dispatch_id} → ${effectiveStatus}`);
|
|
71
|
+
}
|
|
72
|
+
else {
|
|
73
|
+
// Running: update dispatch status + associate session
|
|
74
|
+
await updateDispatch(project_name, dispatch_id, {
|
|
75
|
+
status: 'running',
|
|
76
|
+
...(session ? { sessionId: session.id } : {}),
|
|
77
|
+
...(note ? { note } : {}),
|
|
78
|
+
});
|
|
79
|
+
// Mark session as active
|
|
80
|
+
const sessionId = session?.id ?? dispatch.sessionId;
|
|
81
|
+
if (sessionId) {
|
|
82
|
+
await updateSession(project_name, sessionId, { status: 'active' });
|
|
83
|
+
}
|
|
84
|
+
results.push(`Dispatch ${dispatch_id} → running`);
|
|
85
|
+
}
|
|
86
|
+
// Build response
|
|
87
|
+
const nextStepHint = effectiveStatus === 'running'
|
|
88
|
+
? `\nNext: When the agent finishes, call report_dispatch with dispatch_id="${dispatch_id}" and status="completed" (or "failed").`
|
|
89
|
+
: `\nNext: Call get_project_status to check overall progress and determine next steps.`;
|
|
90
|
+
return {
|
|
91
|
+
content: [
|
|
92
|
+
{
|
|
93
|
+
type: 'text',
|
|
94
|
+
text: `# Report Dispatch: ${dispatch_id}\n\n${results.join('\n')}${nextStepHint}`,
|
|
95
|
+
},
|
|
96
|
+
],
|
|
97
|
+
};
|
|
98
|
+
}
|
|
99
|
+
catch (err) {
|
|
100
|
+
return {
|
|
101
|
+
content: [
|
|
102
|
+
{
|
|
103
|
+
type: 'text',
|
|
104
|
+
text: `Error: ${err instanceof Error ? err.message : String(err)}`,
|
|
105
|
+
},
|
|
106
|
+
],
|
|
107
|
+
isError: true,
|
|
108
|
+
};
|
|
109
|
+
}
|
|
110
|
+
});
|
|
111
|
+
}
|
|
112
|
+
/**
|
|
113
|
+
* Resolve an existing session by agent session ID, or create a new one.
|
|
114
|
+
*/
|
|
115
|
+
async function resolveOrCreateSession(projectName, dispatch, agentSessionId, agentType, label) {
|
|
116
|
+
// If the dispatch already has a session, update it with the agent session ID
|
|
117
|
+
if (dispatch.sessionId) {
|
|
118
|
+
const sessions = await readSessions(projectName);
|
|
119
|
+
const existing = sessions.find((s) => s.id === dispatch.sessionId);
|
|
120
|
+
if (existing) {
|
|
121
|
+
return await updateSession(projectName, existing.id, {
|
|
122
|
+
agentSessionId,
|
|
123
|
+
...(agentType ? { agentType } : {}),
|
|
124
|
+
...(label ? { label } : {}),
|
|
125
|
+
status: 'active',
|
|
126
|
+
});
|
|
127
|
+
}
|
|
128
|
+
}
|
|
129
|
+
// Check if a session with this agent session ID already exists for this role
|
|
130
|
+
const existingByAgent = await findSessionByAgentId(projectName, dispatch.role, agentSessionId);
|
|
131
|
+
if (existingByAgent) {
|
|
132
|
+
return await updateSession(projectName, existingByAgent.id, {
|
|
133
|
+
status: 'active',
|
|
134
|
+
...(agentType ? { agentType } : {}),
|
|
135
|
+
...(label ? { label } : {}),
|
|
136
|
+
});
|
|
137
|
+
}
|
|
138
|
+
// Create a new session
|
|
139
|
+
const session = await createSession(projectName, dispatch.role, agentType, label);
|
|
140
|
+
return await updateSession(projectName, session.id, { agentSessionId });
|
|
141
|
+
}
|
|
142
|
+
//# sourceMappingURL=report-dispatch.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"report-dispatch.js","sourceRoot":"","sources":["../../src/tools/report-dispatch.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* MCP Tool: setup_project
|
|
3
|
+
*
|
|
4
|
+
* Inject Harmonia PM guidance into the host agent's config file (e.g. AGENTS.md).
|
|
5
|
+
* This makes the host agent aware of Harmonia tools and the PM workflow.
|
|
6
|
+
*/
|
|
7
|
+
import type { McpServer } from '@modelcontextprotocol/sdk/server/mcp.js';
|
|
8
|
+
export declare function registerSetupProject(server: McpServer): void;
|
|
@@ -0,0 +1,88 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* MCP Tool: setup_project
|
|
3
|
+
*
|
|
4
|
+
* Inject Harmonia PM guidance into the host agent's config file (e.g. AGENTS.md).
|
|
5
|
+
* This makes the host agent aware of Harmonia tools and the PM workflow.
|
|
6
|
+
*/
|
|
7
|
+
import { z } from 'zod';
|
|
8
|
+
import { readState } from '../core/state.js';
|
|
9
|
+
import { detectHostAgent, injectPrompt } from '../setup/inject.js';
|
|
10
|
+
export function registerSetupProject(server) {
|
|
11
|
+
server.tool('setup_project', "Inject Harmonia PM guidance into the host agent's config file (AGENTS.md / CLAUDE.md). Makes the host agent aware of all Harmonia tools and the PM workflow. Requires project_init to be called first. Idempotent — safe to call multiple times.", {
|
|
12
|
+
project_name: z.string().describe('Project name (must be initialized)'),
|
|
13
|
+
agent_type: z
|
|
14
|
+
.enum(['opencode', 'claude-code', 'codex'])
|
|
15
|
+
.optional()
|
|
16
|
+
.describe('Host agent type. If not specified, auto-detects based on project directory contents.'),
|
|
17
|
+
}, async ({ project_name, agent_type }) => {
|
|
18
|
+
try {
|
|
19
|
+
// Ensure project is initialized
|
|
20
|
+
const state = await readState(project_name);
|
|
21
|
+
// Detect or use specified agent type
|
|
22
|
+
const detectedType = agent_type ?? (await detectHostAgent(state.projectDir));
|
|
23
|
+
// Inject the prompt
|
|
24
|
+
const result = await injectPrompt(state.projectDir, detectedType, {
|
|
25
|
+
projectName: state.projectName,
|
|
26
|
+
projectDir: state.projectDir,
|
|
27
|
+
workflow: state.workflow,
|
|
28
|
+
scale: state.scale,
|
|
29
|
+
});
|
|
30
|
+
const action = result.created ? 'Created' : result.replaced ? 'Updated' : 'Appended to';
|
|
31
|
+
return {
|
|
32
|
+
content: [
|
|
33
|
+
{
|
|
34
|
+
type: 'text',
|
|
35
|
+
text: [
|
|
36
|
+
`# Setup Complete`,
|
|
37
|
+
``,
|
|
38
|
+
`${action} **${result.filePath}** with Harmonia PM guidance.`,
|
|
39
|
+
``,
|
|
40
|
+
`## Configuration`,
|
|
41
|
+
`- Agent type: ${detectedType}`,
|
|
42
|
+
`- Project: ${state.projectName}`,
|
|
43
|
+
`- Workflow: ${state.workflow}`,
|
|
44
|
+
`- Scale: ${state.scale}`,
|
|
45
|
+
``,
|
|
46
|
+
`## What was injected`,
|
|
47
|
+
`- Project Manager role definition and responsibilities`,
|
|
48
|
+
`- Full tool reference (${15} Harmonia tools)`,
|
|
49
|
+
`- Phase-by-phase workflow guide`,
|
|
50
|
+
`- Document review flow`,
|
|
51
|
+
`- Team member dispatch guide`,
|
|
52
|
+
`- Important rules for PM behavior`,
|
|
53
|
+
``,
|
|
54
|
+
`## Next Steps`,
|
|
55
|
+
`The host agent will now follow the PM workflow automatically.`,
|
|
56
|
+
`Start by calling \`get_project_status\` to see where the project stands.`,
|
|
57
|
+
].join('\n'),
|
|
58
|
+
},
|
|
59
|
+
],
|
|
60
|
+
};
|
|
61
|
+
}
|
|
62
|
+
catch (err) {
|
|
63
|
+
const message = err instanceof Error ? err.message : String(err);
|
|
64
|
+
// Check if it's a "project not found" error
|
|
65
|
+
if (message.includes('ENOENT') || message.includes('not found')) {
|
|
66
|
+
return {
|
|
67
|
+
content: [
|
|
68
|
+
{
|
|
69
|
+
type: 'text',
|
|
70
|
+
text: `Project "${project_name}" not initialized. Call project_init first, then setup_project.`,
|
|
71
|
+
},
|
|
72
|
+
],
|
|
73
|
+
isError: true,
|
|
74
|
+
};
|
|
75
|
+
}
|
|
76
|
+
return {
|
|
77
|
+
content: [
|
|
78
|
+
{
|
|
79
|
+
type: 'text',
|
|
80
|
+
text: `Error: ${message}`,
|
|
81
|
+
},
|
|
82
|
+
],
|
|
83
|
+
isError: true,
|
|
84
|
+
};
|
|
85
|
+
}
|
|
86
|
+
});
|
|
87
|
+
}
|
|
88
|
+
//# sourceMappingURL=setup-project.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"setup-project.js","sourceRoot":"","sources":["../../src/tools/setup-project.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* MCP Tool: update_phase
|
|
3
|
+
* Advance or update the status of a project phase.
|
|
4
|
+
* When completing a phase, checks that all doc-type outputs exist (output guard).
|
|
5
|
+
*/
|
|
6
|
+
import type { McpServer } from '@modelcontextprotocol/sdk/server/mcp.js';
|
|
7
|
+
export declare function registerUpdatePhase(server: McpServer, workflowsDir: string): void;
|