@s_s/harmonia 1.1.1 → 1.3.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +413 -205
- package/build/core/dispatch.d.ts +16 -13
- package/build/core/dispatch.js +38 -33
- package/build/core/dispatch.js.map +1 -1
- package/build/core/docs.d.ts +15 -11
- package/build/core/docs.js +24 -19
- package/build/core/docs.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/registry.d.ts +63 -6
- package/build/core/registry.js +109 -8
- package/build/core/registry.js.map +1 -1
- package/build/core/reviews.d.ts +9 -8
- package/build/core/reviews.js +22 -20
- package/build/core/reviews.js.map +1 -1
- package/build/core/state.d.ts +18 -10
- package/build/core/state.js +50 -27
- package/build/core/state.js.map +1 -1
- package/build/core/steps.d.ts +8 -7
- package/build/core/steps.js +21 -19
- package/build/core/steps.js.map +1 -1
- package/build/core/types.d.ts +32 -1
- package/build/index.js +34 -3
- package/build/index.js.map +1 -1
- package/build/setup/templates.js +79 -3
- package/build/setup/templates.js.map +1 -1
- package/build/tools/approve-doc.js +9 -2
- package/build/tools/approve-doc.js.map +1 -1
- package/build/tools/dispatch-role.js +8 -4
- package/build/tools/dispatch-role.js.map +1 -1
- package/build/tools/doc-tools.js +100 -21
- package/build/tools/doc-tools.js.map +1 -1
- package/build/tools/get-project-status.js +108 -17
- package/build/tools/get-project-status.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 +13 -0
- package/build/tools/iteration-start.js +103 -0
- package/build/tools/iteration-start.js.map +1 -0
- package/build/tools/patch-start.d.ts +14 -0
- package/build/tools/patch-start.js +97 -0
- package/build/tools/patch-start.js.map +1 -0
- package/build/tools/project-init.d.ts +5 -1
- package/build/tools/project-init.js +28 -14
- package/build/tools/project-init.js.map +1 -1
- package/build/tools/report-dispatch.js +23 -19
- package/build/tools/report-dispatch.js.map +1 -1
- package/build/tools/set-scale.js +7 -4
- package/build/tools/set-scale.js.map +1 -1
- package/build/tools/update-phase.js +11 -7
- package/build/tools/update-phase.js.map +1 -1
- package/build/tools/utils.d.ts +34 -0
- package/build/tools/utils.js +61 -0
- package/build/tools/utils.js.map +1 -0
- package/package.json +1 -1
|
@@ -0,0 +1,169 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* MCP Tools: issue_create / issue_update / issue_list
|
|
3
|
+
* Issue tracking for Harmonia projects.
|
|
4
|
+
*
|
|
5
|
+
* Issues are project-level (not per-iteration/patch). They track problems
|
|
6
|
+
* discovered during testing or user feedback, and can be linked to
|
|
7
|
+
* the patch or iteration that resolves them.
|
|
8
|
+
*/
|
|
9
|
+
import { z } from 'zod';
|
|
10
|
+
import { getProject } from '../core/registry.js';
|
|
11
|
+
import { createIssue, updateIssue, listIssues } from '../core/issues.js';
|
|
12
|
+
function formatIssue(issue) {
|
|
13
|
+
const resolvedBy = issue.resolvedBy ? ` → resolved by ${issue.resolvedBy.type}-${issue.resolvedBy.number}` : '';
|
|
14
|
+
const closed = issue.closedAt ? ` (closed: ${issue.closedAt.split('T')[0]})` : '';
|
|
15
|
+
return [
|
|
16
|
+
`[${issue.status.toUpperCase()}] ${issue.id}: ${issue.title}`,
|
|
17
|
+
` Source: ${issue.source} | Iteration: ${issue.iteration} | Created: ${issue.createdAt.split('T')[0]}${resolvedBy}${closed}`,
|
|
18
|
+
` ${issue.description}`,
|
|
19
|
+
].join('\n');
|
|
20
|
+
}
|
|
21
|
+
export function registerIssueTools(server) {
|
|
22
|
+
// ─── issue_create ───
|
|
23
|
+
server.tool('issue_create', 'Create a new issue for a project. Issues track problems found during testing or user feedback.', {
|
|
24
|
+
project_name: z.string().describe('项目名称'),
|
|
25
|
+
title: z.string().describe('Issue 标题(简短描述)'),
|
|
26
|
+
description: z.string().describe('Issue 详细描述'),
|
|
27
|
+
source: z
|
|
28
|
+
.enum(['test', 'user-feedback'])
|
|
29
|
+
.describe('Issue 来源: test(测试发现)或 user-feedback(用户反馈)'),
|
|
30
|
+
iteration: z.number().int().positive().describe('关联的迭代编号(在哪个迭代中发现的)'),
|
|
31
|
+
}, async ({ project_name, title, description, source, iteration }) => {
|
|
32
|
+
const entry = await getProject(project_name);
|
|
33
|
+
if (!entry) {
|
|
34
|
+
return {
|
|
35
|
+
content: [
|
|
36
|
+
{
|
|
37
|
+
type: 'text',
|
|
38
|
+
text: `项目 "${project_name}" 未注册。请先调用 project_init 注册项目。`,
|
|
39
|
+
},
|
|
40
|
+
],
|
|
41
|
+
isError: true,
|
|
42
|
+
};
|
|
43
|
+
}
|
|
44
|
+
const issue = await createIssue(project_name, title, description, source, iteration);
|
|
45
|
+
return {
|
|
46
|
+
content: [
|
|
47
|
+
{
|
|
48
|
+
type: 'text',
|
|
49
|
+
text: [
|
|
50
|
+
`Issue 已创建: ${issue.id}`,
|
|
51
|
+
``,
|
|
52
|
+
formatIssue(issue),
|
|
53
|
+
``,
|
|
54
|
+
`如需修复此 issue,可调用 patch_start(project_name="${project_name}", issue_id="${issue.id}") 开始补丁。`,
|
|
55
|
+
].join('\n'),
|
|
56
|
+
},
|
|
57
|
+
],
|
|
58
|
+
};
|
|
59
|
+
});
|
|
60
|
+
// ─── issue_update ───
|
|
61
|
+
server.tool('issue_update', 'Update an existing issue. Can change status and link to the resolving patch/iteration.', {
|
|
62
|
+
project_name: z.string().describe('项目名称'),
|
|
63
|
+
issue_id: z.string().describe('Issue ID (e.g. issue-1)'),
|
|
64
|
+
status: z.enum(['open', 'closed']).optional().describe('新状态'),
|
|
65
|
+
resolved_by_type: z.enum(['iteration', 'patch']).optional().describe('解决该 issue 的上下文类型'),
|
|
66
|
+
resolved_by_number: z.number().int().positive().optional().describe('解决该 issue 的上下文编号'),
|
|
67
|
+
}, async ({ project_name, issue_id, status, resolved_by_type, resolved_by_number }) => {
|
|
68
|
+
const entry = await getProject(project_name);
|
|
69
|
+
if (!entry) {
|
|
70
|
+
return {
|
|
71
|
+
content: [
|
|
72
|
+
{
|
|
73
|
+
type: 'text',
|
|
74
|
+
text: `项目 "${project_name}" 未注册。`,
|
|
75
|
+
},
|
|
76
|
+
],
|
|
77
|
+
isError: true,
|
|
78
|
+
};
|
|
79
|
+
}
|
|
80
|
+
const updates = {};
|
|
81
|
+
if (status !== undefined) {
|
|
82
|
+
updates.status = status;
|
|
83
|
+
}
|
|
84
|
+
if (resolved_by_type && resolved_by_number) {
|
|
85
|
+
updates.resolvedBy = {
|
|
86
|
+
type: resolved_by_type,
|
|
87
|
+
number: resolved_by_number,
|
|
88
|
+
};
|
|
89
|
+
}
|
|
90
|
+
try {
|
|
91
|
+
const issue = await updateIssue(project_name, issue_id, updates);
|
|
92
|
+
return {
|
|
93
|
+
content: [
|
|
94
|
+
{
|
|
95
|
+
type: 'text',
|
|
96
|
+
text: [`Issue 已更新:`, ``, formatIssue(issue)].join('\n'),
|
|
97
|
+
},
|
|
98
|
+
],
|
|
99
|
+
};
|
|
100
|
+
}
|
|
101
|
+
catch (err) {
|
|
102
|
+
return {
|
|
103
|
+
content: [
|
|
104
|
+
{
|
|
105
|
+
type: 'text',
|
|
106
|
+
text: `Error: ${err instanceof Error ? err.message : String(err)}`,
|
|
107
|
+
},
|
|
108
|
+
],
|
|
109
|
+
isError: true,
|
|
110
|
+
};
|
|
111
|
+
}
|
|
112
|
+
});
|
|
113
|
+
// ─── issue_list ───
|
|
114
|
+
server.tool('issue_list', 'List issues for a project with optional filters.', {
|
|
115
|
+
project_name: z.string().describe('项目名称'),
|
|
116
|
+
status: z.enum(['open', 'closed']).optional().describe('按状态筛选'),
|
|
117
|
+
source: z.enum(['test', 'user-feedback']).optional().describe('按来源筛选'),
|
|
118
|
+
iteration: z.number().int().positive().optional().describe('按迭代编号筛选'),
|
|
119
|
+
}, async ({ project_name, status, source, iteration }) => {
|
|
120
|
+
const entry = await getProject(project_name);
|
|
121
|
+
if (!entry) {
|
|
122
|
+
return {
|
|
123
|
+
content: [
|
|
124
|
+
{
|
|
125
|
+
type: 'text',
|
|
126
|
+
text: `项目 "${project_name}" 未注册。`,
|
|
127
|
+
},
|
|
128
|
+
],
|
|
129
|
+
isError: true,
|
|
130
|
+
};
|
|
131
|
+
}
|
|
132
|
+
const filters = {};
|
|
133
|
+
if (status)
|
|
134
|
+
filters.status = status;
|
|
135
|
+
if (source)
|
|
136
|
+
filters.source = source;
|
|
137
|
+
if (iteration !== undefined)
|
|
138
|
+
filters.iteration = iteration;
|
|
139
|
+
const issues = await listIssues(project_name, Object.keys(filters).length > 0 ? filters : undefined);
|
|
140
|
+
if (issues.length === 0) {
|
|
141
|
+
const filterDesc = Object.keys(filters).length > 0 ? '(符合筛选条件的)' : '';
|
|
142
|
+
return {
|
|
143
|
+
content: [
|
|
144
|
+
{
|
|
145
|
+
type: 'text',
|
|
146
|
+
text: `项目 "${project_name}" 暂无${filterDesc} issue。`,
|
|
147
|
+
},
|
|
148
|
+
],
|
|
149
|
+
};
|
|
150
|
+
}
|
|
151
|
+
const openCount = issues.filter((i) => i.status === 'open').length;
|
|
152
|
+
const closedCount = issues.filter((i) => i.status === 'closed').length;
|
|
153
|
+
return {
|
|
154
|
+
content: [
|
|
155
|
+
{
|
|
156
|
+
type: 'text',
|
|
157
|
+
text: [
|
|
158
|
+
`# Issues — ${project_name}`,
|
|
159
|
+
``,
|
|
160
|
+
`共 ${issues.length} 个 issue(${openCount} open, ${closedCount} closed)`,
|
|
161
|
+
``,
|
|
162
|
+
...issues.map((i) => formatIssue(i)),
|
|
163
|
+
].join('\n'),
|
|
164
|
+
},
|
|
165
|
+
],
|
|
166
|
+
};
|
|
167
|
+
});
|
|
168
|
+
}
|
|
169
|
+
//# sourceMappingURL=issue-tools.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"issue-tools.js","sourceRoot":"","sources":["../../src/tools/issue-tools.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* MCP Tool: iteration_start
|
|
3
|
+
* Start a new iteration for a registered project.
|
|
4
|
+
*
|
|
5
|
+
* Creates the iteration directory (iter-N/), initializes state.json,
|
|
6
|
+
* and updates the registry with the new iteration number.
|
|
7
|
+
*
|
|
8
|
+
* Guards:
|
|
9
|
+
* - Project must be registered (use project_init first)
|
|
10
|
+
* - If a current iteration exists, all phases must be completed (or use force)
|
|
11
|
+
*/
|
|
12
|
+
import type { McpServer } from '@modelcontextprotocol/sdk/server/mcp.js';
|
|
13
|
+
export declare function registerIterationStart(server: McpServer, builtinDir: string, customDir: string): void;
|
|
@@ -0,0 +1,103 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* MCP Tool: iteration_start
|
|
3
|
+
* Start a new iteration for a registered project.
|
|
4
|
+
*
|
|
5
|
+
* Creates the iteration directory (iter-N/), initializes state.json,
|
|
6
|
+
* and updates the registry with the new iteration number.
|
|
7
|
+
*
|
|
8
|
+
* Guards:
|
|
9
|
+
* - Project must be registered (use project_init first)
|
|
10
|
+
* - If a current iteration exists, all phases must be completed (or use force)
|
|
11
|
+
*/
|
|
12
|
+
import { z } from 'zod';
|
|
13
|
+
import { getProject, startIteration, getIterationDir, resolveContextDir } from '../core/registry.js';
|
|
14
|
+
import { loadWorkflow } from '../core/workflow.js';
|
|
15
|
+
import { initProjectState, readState } from '../core/state.js';
|
|
16
|
+
export function registerIterationStart(server, builtinDir, customDir) {
|
|
17
|
+
server.tool('iteration_start', 'Start a new iteration for a registered project. Creates iteration directory, initializes state, and updates registry. Call this after project_init to begin the first iteration, or after completing all phases to start a new iteration.', {
|
|
18
|
+
project_name: z.string().describe('项目名称'),
|
|
19
|
+
force: z.boolean().optional().describe('强制开始新迭代,即使当前迭代未完成 (default: false)'),
|
|
20
|
+
}, async ({ project_name, force }) => {
|
|
21
|
+
try {
|
|
22
|
+
// Guard: project must be registered
|
|
23
|
+
const entry = await getProject(project_name);
|
|
24
|
+
if (!entry) {
|
|
25
|
+
return {
|
|
26
|
+
content: [
|
|
27
|
+
{
|
|
28
|
+
type: 'text',
|
|
29
|
+
text: `项目 "${project_name}" 未注册。请先调用 project_init 注册项目。`,
|
|
30
|
+
},
|
|
31
|
+
],
|
|
32
|
+
isError: true,
|
|
33
|
+
};
|
|
34
|
+
}
|
|
35
|
+
// Guard: if there's a current iteration, check if all phases are completed
|
|
36
|
+
if (entry.currentIteration > 0 && !force) {
|
|
37
|
+
try {
|
|
38
|
+
// Resolve the current iteration's context dir
|
|
39
|
+
const currentIterDir = entry.activeContext
|
|
40
|
+
? resolveContextDir(project_name, `iter-${entry.currentIteration}`)?.dir
|
|
41
|
+
: undefined;
|
|
42
|
+
const currentState = await readState(project_name, entry.currentIteration, currentIterDir);
|
|
43
|
+
const incompletePhases = currentState.phases.filter((p) => p.status !== 'completed' && p.status !== 'skipped');
|
|
44
|
+
if (incompletePhases.length > 0) {
|
|
45
|
+
const phaseList = incompletePhases.map((p) => `${p.id} (${p.status})`).join(', ');
|
|
46
|
+
return {
|
|
47
|
+
content: [
|
|
48
|
+
{
|
|
49
|
+
type: 'text',
|
|
50
|
+
text: [
|
|
51
|
+
`当前迭代 (iter-${entry.currentIteration}) 尚有未完成的阶段: ${phaseList}`,
|
|
52
|
+
``,
|
|
53
|
+
`请先完成当前迭代的所有阶段,或使用 force=true 强制开始新迭代。`,
|
|
54
|
+
].join('\n'),
|
|
55
|
+
},
|
|
56
|
+
],
|
|
57
|
+
isError: true,
|
|
58
|
+
};
|
|
59
|
+
}
|
|
60
|
+
}
|
|
61
|
+
catch {
|
|
62
|
+
// State file doesn't exist — might be a corrupted iteration, allow proceeding
|
|
63
|
+
}
|
|
64
|
+
}
|
|
65
|
+
// Start new iteration (creates directory, updates registry)
|
|
66
|
+
const newIteration = await startIteration(project_name);
|
|
67
|
+
// Load workflow and initialize state
|
|
68
|
+
const wf = await loadWorkflow(builtinDir, customDir, entry.workflow);
|
|
69
|
+
const newIterDir = getIterationDir(project_name, newIteration);
|
|
70
|
+
const state = await initProjectState(project_name, entry.dir, wf, newIteration, 'iteration', newIterDir);
|
|
71
|
+
return {
|
|
72
|
+
content: [
|
|
73
|
+
{
|
|
74
|
+
type: 'text',
|
|
75
|
+
text: [
|
|
76
|
+
`迭代 ${newIteration} 已开始。`,
|
|
77
|
+
``,
|
|
78
|
+
`项目: ${project_name}`,
|
|
79
|
+
`源代码目录: ${entry.dir}`,
|
|
80
|
+
`工作流: ${wf.definition.name}`,
|
|
81
|
+
`规模: (未设定)`,
|
|
82
|
+
`当前阶段: ${state.currentPhase}`,
|
|
83
|
+
``,
|
|
84
|
+
`下一步: 与用户沟通需求,编写 PRD,PRD 审批通过后调用 project_set_scale 设定项目规模。`,
|
|
85
|
+
].join('\n'),
|
|
86
|
+
},
|
|
87
|
+
],
|
|
88
|
+
};
|
|
89
|
+
}
|
|
90
|
+
catch (err) {
|
|
91
|
+
return {
|
|
92
|
+
content: [
|
|
93
|
+
{
|
|
94
|
+
type: 'text',
|
|
95
|
+
text: `Error: ${err instanceof Error ? err.message : String(err)}`,
|
|
96
|
+
},
|
|
97
|
+
],
|
|
98
|
+
isError: true,
|
|
99
|
+
};
|
|
100
|
+
}
|
|
101
|
+
});
|
|
102
|
+
}
|
|
103
|
+
//# sourceMappingURL=iteration-start.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"iteration-start.js","sourceRoot":"","sources":["../../src/tools/iteration-start.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* MCP Tool: patch_start
|
|
3
|
+
* Start a new patch for a registered project.
|
|
4
|
+
*
|
|
5
|
+
* Creates the patch directory (patch-N/), initializes state.json with
|
|
6
|
+
* clarify/design phases skipped, scale=small, type=patch.
|
|
7
|
+
* Optionally links to an issue via issue_id.
|
|
8
|
+
*
|
|
9
|
+
* Guards:
|
|
10
|
+
* - Project must be registered (use project_init first)
|
|
11
|
+
* - At least one iteration must have been started (patches fix existing work)
|
|
12
|
+
*/
|
|
13
|
+
import type { McpServer } from '@modelcontextprotocol/sdk/server/mcp.js';
|
|
14
|
+
export declare function registerPatchStart(server: McpServer, builtinDir: string, customDir: string): void;
|
|
@@ -0,0 +1,97 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* MCP Tool: patch_start
|
|
3
|
+
* Start a new patch for a registered project.
|
|
4
|
+
*
|
|
5
|
+
* Creates the patch directory (patch-N/), initializes state.json with
|
|
6
|
+
* clarify/design phases skipped, scale=small, type=patch.
|
|
7
|
+
* Optionally links to an issue via issue_id.
|
|
8
|
+
*
|
|
9
|
+
* Guards:
|
|
10
|
+
* - Project must be registered (use project_init first)
|
|
11
|
+
* - At least one iteration must have been started (patches fix existing work)
|
|
12
|
+
*/
|
|
13
|
+
import { z } from 'zod';
|
|
14
|
+
import { getProject, startPatch, getPatchDir } from '../core/registry.js';
|
|
15
|
+
import { loadWorkflow } from '../core/workflow.js';
|
|
16
|
+
import { initProjectState } from '../core/state.js';
|
|
17
|
+
export function registerPatchStart(server, builtinDir, customDir) {
|
|
18
|
+
server.tool('patch_start', 'Start a new patch for a registered project. Patches are lightweight fix cycles — clarify and design phases are skipped, scale is fixed to small. Use this for bug fixes, small improvements, or resolving issues.', {
|
|
19
|
+
project_name: z.string().describe('项目名称'),
|
|
20
|
+
description: z.string().optional().describe('补丁描述(简要说明修复内容)'),
|
|
21
|
+
issue_id: z.string().optional().describe('关联的 issue ID(如果是修复某个 issue)'),
|
|
22
|
+
}, async ({ project_name, description, issue_id }) => {
|
|
23
|
+
try {
|
|
24
|
+
// Guard: project must be registered
|
|
25
|
+
const entry = await getProject(project_name);
|
|
26
|
+
if (!entry) {
|
|
27
|
+
return {
|
|
28
|
+
content: [
|
|
29
|
+
{
|
|
30
|
+
type: 'text',
|
|
31
|
+
text: `项目 "${project_name}" 未注册。请先调用 project_init 注册项目。`,
|
|
32
|
+
},
|
|
33
|
+
],
|
|
34
|
+
isError: true,
|
|
35
|
+
};
|
|
36
|
+
}
|
|
37
|
+
// Guard: at least one iteration must exist (patches fix existing work)
|
|
38
|
+
if (entry.totalIterations === 0) {
|
|
39
|
+
return {
|
|
40
|
+
content: [
|
|
41
|
+
{
|
|
42
|
+
type: 'text',
|
|
43
|
+
text: [
|
|
44
|
+
`项目 "${project_name}" 尚未有任何迭代。`,
|
|
45
|
+
`补丁用于修复已有工作,请先调用 iteration_start 开始第一轮迭代。`,
|
|
46
|
+
].join('\n'),
|
|
47
|
+
},
|
|
48
|
+
],
|
|
49
|
+
isError: true,
|
|
50
|
+
};
|
|
51
|
+
}
|
|
52
|
+
// Start new patch (creates directory, updates registry)
|
|
53
|
+
const newPatch = await startPatch(project_name);
|
|
54
|
+
// Load workflow and initialize state in patch mode
|
|
55
|
+
const wf = await loadWorkflow(builtinDir, customDir, entry.workflow);
|
|
56
|
+
const patchDir = getPatchDir(project_name, newPatch);
|
|
57
|
+
const state = await initProjectState(project_name, entry.dir, wf, newPatch, 'patch', patchDir);
|
|
58
|
+
const descLine = description ? `描述: ${description}` : '';
|
|
59
|
+
const issueLine = issue_id ? `关联 issue: ${issue_id}` : '';
|
|
60
|
+
return {
|
|
61
|
+
content: [
|
|
62
|
+
{
|
|
63
|
+
type: 'text',
|
|
64
|
+
text: [
|
|
65
|
+
`补丁 patch-${newPatch} 已开始。`,
|
|
66
|
+
``,
|
|
67
|
+
`项目: ${project_name}`,
|
|
68
|
+
`源代码目录: ${entry.dir}`,
|
|
69
|
+
`工作流: ${wf.definition.name}`,
|
|
70
|
+
`规模: small (固定)`,
|
|
71
|
+
`当前阶段: ${state.currentPhase}`,
|
|
72
|
+
`跳过阶段: clarify, design`,
|
|
73
|
+
descLine,
|
|
74
|
+
issueLine,
|
|
75
|
+
``,
|
|
76
|
+
`下一步: 开始开发。使用 role_dispatch 分配开发者,或直接使用 doc_write 编写文档。`,
|
|
77
|
+
]
|
|
78
|
+
.filter(Boolean)
|
|
79
|
+
.join('\n'),
|
|
80
|
+
},
|
|
81
|
+
],
|
|
82
|
+
};
|
|
83
|
+
}
|
|
84
|
+
catch (err) {
|
|
85
|
+
return {
|
|
86
|
+
content: [
|
|
87
|
+
{
|
|
88
|
+
type: 'text',
|
|
89
|
+
text: `Error: ${err instanceof Error ? err.message : String(err)}`,
|
|
90
|
+
},
|
|
91
|
+
],
|
|
92
|
+
isError: true,
|
|
93
|
+
};
|
|
94
|
+
}
|
|
95
|
+
});
|
|
96
|
+
}
|
|
97
|
+
//# sourceMappingURL=patch-start.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"patch-start.js","sourceRoot":"","sources":["../../src/tools/patch-start.ts"],"names":[],"mappings":"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"}
|
|
@@ -1,6 +1,10 @@
|
|
|
1
1
|
/**
|
|
2
2
|
* MCP Tool: project_init
|
|
3
|
-
*
|
|
3
|
+
* Register a new Harmonia project in the global registry.
|
|
4
|
+
*
|
|
5
|
+
* This tool ONLY registers the project — it does NOT create iteration directories
|
|
6
|
+
* or initialize state. After registration, call `iteration_start` to begin the
|
|
7
|
+
* first iteration.
|
|
4
8
|
*
|
|
5
9
|
* Supports an optional `workflow` parameter. When multiple workflows are
|
|
6
10
|
* available and none is specified, returns an error with the available list
|
|
@@ -1,6 +1,10 @@
|
|
|
1
1
|
/**
|
|
2
2
|
* MCP Tool: project_init
|
|
3
|
-
*
|
|
3
|
+
* Register a new Harmonia project in the global registry.
|
|
4
|
+
*
|
|
5
|
+
* This tool ONLY registers the project — it does NOT create iteration directories
|
|
6
|
+
* or initialize state. After registration, call `iteration_start` to begin the
|
|
7
|
+
* first iteration.
|
|
4
8
|
*
|
|
5
9
|
* Supports an optional `workflow` parameter. When multiple workflows are
|
|
6
10
|
* available and none is specified, returns an error with the available list
|
|
@@ -8,10 +12,9 @@
|
|
|
8
12
|
*/
|
|
9
13
|
import { z } from 'zod';
|
|
10
14
|
import { loadWorkflow, listWorkflows } from '../core/workflow.js';
|
|
11
|
-
import { initProjectState, readState } from '../core/state.js';
|
|
12
15
|
import { registerProject, getProject } from '../core/registry.js';
|
|
13
16
|
export function registerProjectInit(server, builtinDir, customDir) {
|
|
14
|
-
server.tool('project_init',
|
|
17
|
+
server.tool('project_init', 'Register a new Harmonia project. Creates the project entry in the global registry and the project source directory. Does NOT start an iteration — call iteration_start after registration to begin the first iteration.', {
|
|
15
18
|
project_name: z
|
|
16
19
|
.string()
|
|
17
20
|
.regex(/^[a-z0-9][a-z0-9-]*[a-z0-9]$/, 'project_name 只允许小写字母、数字和短横线,且不能以短横线开头或结尾')
|
|
@@ -27,15 +30,30 @@ export function registerProjectInit(server, builtinDir, customDir) {
|
|
|
27
30
|
.optional()
|
|
28
31
|
.describe('工作流名称(如 dev)。只有一个可用工作流时自动选中;多个时必须指定。'),
|
|
29
32
|
}, async ({ project_name, project_dir, workflow }) => {
|
|
30
|
-
// Check if already
|
|
33
|
+
// Check if already registered
|
|
31
34
|
const existing = await getProject(project_name);
|
|
32
35
|
if (existing) {
|
|
33
|
-
const
|
|
36
|
+
const contextInfo = existing.activeContext
|
|
37
|
+
? `活跃上下文: ${existing.activeContext}`
|
|
38
|
+
: '尚未开始迭代或补丁';
|
|
34
39
|
return {
|
|
35
40
|
content: [
|
|
36
41
|
{
|
|
37
42
|
type: 'text',
|
|
38
|
-
text:
|
|
43
|
+
text: [
|
|
44
|
+
`项目 "${project_name}" 已注册。`,
|
|
45
|
+
``,
|
|
46
|
+
`源代码目录: ${existing.dir}`,
|
|
47
|
+
`工作流: ${existing.workflow}`,
|
|
48
|
+
`迭代: ${existing.totalIterations} 轮,补丁: ${existing.totalPatches} 个`,
|
|
49
|
+
`${contextInfo}`,
|
|
50
|
+
``,
|
|
51
|
+
existing.activeContext
|
|
52
|
+
? `如需查看当前状态,请调用 project_status(project_name="${project_name}")。`
|
|
53
|
+
: `请调用 iteration_start(project_name="${project_name}") 开始第一轮迭代。`,
|
|
54
|
+
]
|
|
55
|
+
.filter(Boolean)
|
|
56
|
+
.join('\n'),
|
|
39
57
|
},
|
|
40
58
|
],
|
|
41
59
|
};
|
|
@@ -102,26 +120,22 @@ export function registerProjectInit(server, builtinDir, customDir) {
|
|
|
102
120
|
isError: true,
|
|
103
121
|
};
|
|
104
122
|
}
|
|
105
|
-
// Load workflow definition
|
|
123
|
+
// Load workflow definition (validate it loads correctly)
|
|
106
124
|
const wf = await loadWorkflow(builtinDir, customDir, workflowName);
|
|
107
|
-
// Register project (creates global data
|
|
125
|
+
// Register project (creates global data dir + project source dir)
|
|
108
126
|
await registerProject(project_name, project_dir, workflowName);
|
|
109
|
-
// Initialize project state (scale = null)
|
|
110
|
-
const state = await initProjectState(project_name, project_dir, wf);
|
|
111
127
|
return {
|
|
112
128
|
content: [
|
|
113
129
|
{
|
|
114
130
|
type: 'text',
|
|
115
131
|
text: [
|
|
116
|
-
`项目 "${project_name}"
|
|
132
|
+
`项目 "${project_name}" 注册成功。`,
|
|
117
133
|
``,
|
|
118
134
|
`源代码目录: ${project_dir}`,
|
|
119
135
|
`工作流: ${wf.definition.name} (${wf.definition.description})`,
|
|
120
|
-
`规模: (未设定)`,
|
|
121
|
-
`当前阶段: ${state.currentPhase}`,
|
|
122
136
|
`可用角色: ${Object.keys(wf.roles).join(', ')}`,
|
|
123
137
|
``,
|
|
124
|
-
`下一步:
|
|
138
|
+
`下一步: 调用 iteration_start(project_name="${project_name}") 开始第一轮迭代。`,
|
|
125
139
|
].join('\n'),
|
|
126
140
|
},
|
|
127
141
|
],
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"project-init.js","sourceRoot":"","sources":["../../src/tools/project-init.ts"],"names":[],"mappings":"AAAA
|
|
1
|
+
{"version":3,"file":"project-init.js","sourceRoot":"","sources":["../../src/tools/project-init.ts"],"names":[],"mappings":"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"}
|