superplanners-mcp 0.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (46) hide show
  1. package/README.md +160 -0
  2. package/dist/file-manager.d.ts +99 -0
  3. package/dist/file-manager.d.ts.map +1 -0
  4. package/dist/file-manager.js +364 -0
  5. package/dist/file-manager.js.map +1 -0
  6. package/dist/index.d.ts +3 -0
  7. package/dist/index.d.ts.map +1 -0
  8. package/dist/index.js +65 -0
  9. package/dist/index.js.map +1 -0
  10. package/dist/renderer.d.ts +10 -0
  11. package/dist/renderer.d.ts.map +1 -0
  12. package/dist/renderer.js +170 -0
  13. package/dist/renderer.js.map +1 -0
  14. package/dist/server.d.ts +6 -0
  15. package/dist/server.d.ts.map +1 -0
  16. package/dist/server.js +438 -0
  17. package/dist/server.js.map +1 -0
  18. package/dist/task-engine/dependency-resolver.d.ts +43 -0
  19. package/dist/task-engine/dependency-resolver.d.ts.map +1 -0
  20. package/dist/task-engine/dependency-resolver.js +94 -0
  21. package/dist/task-engine/dependency-resolver.js.map +1 -0
  22. package/dist/task-engine/index.d.ts +6 -0
  23. package/dist/task-engine/index.d.ts.map +1 -0
  24. package/dist/task-engine/index.js +6 -0
  25. package/dist/task-engine/index.js.map +1 -0
  26. package/dist/task-engine/next-task-selector.d.ts +18 -0
  27. package/dist/task-engine/next-task-selector.d.ts.map +1 -0
  28. package/dist/task-engine/next-task-selector.js +99 -0
  29. package/dist/task-engine/next-task-selector.js.map +1 -0
  30. package/dist/task-engine/parser.d.ts +20 -0
  31. package/dist/task-engine/parser.d.ts.map +1 -0
  32. package/dist/task-engine/parser.js +77 -0
  33. package/dist/task-engine/parser.js.map +1 -0
  34. package/dist/task-engine/progress-calculator.d.ts +15 -0
  35. package/dist/task-engine/progress-calculator.d.ts.map +1 -0
  36. package/dist/task-engine/progress-calculator.js +58 -0
  37. package/dist/task-engine/progress-calculator.js.map +1 -0
  38. package/dist/task-engine/status-reducer.d.ts +18 -0
  39. package/dist/task-engine/status-reducer.d.ts.map +1 -0
  40. package/dist/task-engine/status-reducer.js +88 -0
  41. package/dist/task-engine/status-reducer.js.map +1 -0
  42. package/dist/types.d.ts +999 -0
  43. package/dist/types.d.ts.map +1 -0
  44. package/dist/types.js +228 -0
  45. package/dist/types.js.map +1 -0
  46. package/package.json +51 -0
package/dist/server.js ADDED
@@ -0,0 +1,438 @@
1
+ import { FileManager } from './file-manager.js';
2
+ import { PlanInputSchema, StatusInputSchema, UpdateInputSchema, ResetInputSchema } from './types.js';
3
+ import { updateTaskStatusWithValidation } from './task-engine/status-reducer.js';
4
+ import { calculateTaskSummary, calculateProgress, formatProgressString, } from './task-engine/progress-calculator.js';
5
+ import { selectNextTask } from './task-engine/next-task-selector.js';
6
+ // 工具定义
7
+ export const TOOLS = [
8
+ {
9
+ name: 'superplanners_plan',
10
+ description: '根据需求创建结构化任务计划',
11
+ inputSchema: {
12
+ type: 'object',
13
+ properties: {
14
+ requirement: {
15
+ type: 'string',
16
+ description: '需求描述,用于分解成任务',
17
+ },
18
+ project_name: {
19
+ type: 'string',
20
+ description: '项目名称,默认从需求推断',
21
+ },
22
+ },
23
+ required: ['requirement'],
24
+ },
25
+ },
26
+ {
27
+ name: 'superplanners_status',
28
+ description: '查看任务状态和整体进度',
29
+ inputSchema: {
30
+ type: 'object',
31
+ properties: {
32
+ project_id: {
33
+ type: 'string',
34
+ description: '项目ID,不填则显示全部项目',
35
+ },
36
+ },
37
+ },
38
+ },
39
+ {
40
+ name: 'superplanners_update',
41
+ description: '更新任务状态',
42
+ inputSchema: {
43
+ type: 'object',
44
+ properties: {
45
+ project_id: {
46
+ type: 'string',
47
+ description: '项目ID',
48
+ },
49
+ task_id: {
50
+ type: 'string',
51
+ description: '任务ID',
52
+ },
53
+ status: {
54
+ type: 'string',
55
+ enum: ['pending', 'in_progress', 'completed', 'blocked', 'skipped'],
56
+ description: '新状态',
57
+ },
58
+ notes: {
59
+ type: 'string',
60
+ description: '备注',
61
+ },
62
+ },
63
+ required: ['project_id', 'task_id', 'status'],
64
+ },
65
+ },
66
+ {
67
+ name: 'superplanners_reset',
68
+ description: '归档清理或恢复历史任务',
69
+ inputSchema: {
70
+ type: 'object',
71
+ properties: {
72
+ action: {
73
+ type: 'string',
74
+ enum: ['cleanup', 'list', 'restore'],
75
+ description: '操作类型',
76
+ },
77
+ project_id: {
78
+ type: 'string',
79
+ description: 'cleanup 时可选的项目ID',
80
+ },
81
+ archive_id: {
82
+ type: 'string',
83
+ description: 'restore 时必填的归档ID',
84
+ },
85
+ },
86
+ required: ['action'],
87
+ },
88
+ },
89
+ ];
90
+ // 创建工具处理器
91
+ export function createToolHandlers(baseDir) {
92
+ const fm = new FileManager(baseDir);
93
+ return {
94
+ superplanners_plan: async (args) => handlePlan(fm, args),
95
+ superplanners_status: async (args) => handleStatus(fm, args),
96
+ superplanners_update: async (args) => handleUpdate(fm, args),
97
+ superplanners_reset: async (args) => handleReset(fm, args),
98
+ };
99
+ }
100
+ /**
101
+ * 生成 project_id (slug 格式)
102
+ */
103
+ function generateProjectId(name) {
104
+ // 简单的中文转拼音首字母 + 去除特殊字符
105
+ const slug = name
106
+ .toLowerCase()
107
+ .replace(/[\s_]+/g, '-')
108
+ .replace(/[^\w\u4e00-\u9fa5-]/g, '')
109
+ .replace(/^-+|-+$/g, '');
110
+ // 如果是纯中文,生成随机 ID
111
+ if (/^[\u4e00-\u9fa5-]+$/.test(slug)) {
112
+ const timestamp = Date.now().toString(36);
113
+ return `project-${timestamp}`;
114
+ }
115
+ return slug || `project-${Date.now().toString(36)}`;
116
+ }
117
+ /**
118
+ * 根据需求生成默认任务(简化版本)
119
+ * 在实际应用中,这里应该调用 AI 进行任务分解
120
+ */
121
+ function generateDefaultTasks(requirement) {
122
+ // 这是一个简化的实现,实际应该由 Claude 分解
123
+ return [
124
+ {
125
+ id: '1',
126
+ title: '需求分析',
127
+ description: `分析需求: ${requirement}`,
128
+ status: 'pending',
129
+ priority: 'high',
130
+ estimate: '2h',
131
+ },
132
+ {
133
+ id: '2',
134
+ title: '技术设计',
135
+ status: 'pending',
136
+ priority: 'high',
137
+ estimate: '4h',
138
+ dependencies: ['1'],
139
+ },
140
+ {
141
+ id: '3',
142
+ title: '开发实现',
143
+ status: 'pending',
144
+ priority: 'high',
145
+ estimate: '8h',
146
+ dependencies: ['2'],
147
+ },
148
+ {
149
+ id: '4',
150
+ title: '测试验证',
151
+ status: 'pending',
152
+ priority: 'medium',
153
+ estimate: '4h',
154
+ dependencies: ['3'],
155
+ },
156
+ ];
157
+ }
158
+ async function handlePlan(fm, args) {
159
+ const input = PlanInputSchema.safeParse(args);
160
+ if (!input.success) {
161
+ return { success: false, error: `参数错误: ${input.error.message}` };
162
+ }
163
+ const { requirement, project_name } = input.data;
164
+ const name = project_name || '新项目';
165
+ const projectId = generateProjectId(name);
166
+ // 检查项目是否已存在
167
+ if (await fm.projectExists(projectId)) {
168
+ return { success: false, error: `项目 ${projectId} 已存在` };
169
+ }
170
+ const now = new Date().toISOString();
171
+ const tasks = generateDefaultTasks(requirement);
172
+ // 创建项目数据
173
+ const projectData = {
174
+ meta: {
175
+ project: name,
176
+ project_id: projectId,
177
+ created: now,
178
+ updated: now,
179
+ version: 1,
180
+ description: requirement,
181
+ },
182
+ tasks,
183
+ };
184
+ // 写入项目
185
+ const writeResult = await fm.writeProjectData(projectId, projectData);
186
+ if (!writeResult.success) {
187
+ return { success: false, error: writeResult.error };
188
+ }
189
+ // 更新或创建 task-plan.yaml
190
+ let taskPlan;
191
+ const taskPlanResult = await fm.readTaskPlan();
192
+ if (taskPlanResult.success && taskPlanResult.data) {
193
+ taskPlan = {
194
+ ...taskPlanResult.data,
195
+ projects: [
196
+ ...taskPlanResult.data.projects,
197
+ {
198
+ project_id: projectId,
199
+ project: name,
200
+ status: 'active',
201
+ updated: now,
202
+ path: `${projectId}/tasks.yaml`,
203
+ },
204
+ ],
205
+ };
206
+ }
207
+ else {
208
+ taskPlan = {
209
+ meta: {
210
+ name: 'SuperPlanners',
211
+ version: '1.0.0',
212
+ updated: now,
213
+ },
214
+ projects: [
215
+ {
216
+ project_id: projectId,
217
+ project: name,
218
+ status: 'active',
219
+ updated: now,
220
+ path: `${projectId}/tasks.yaml`,
221
+ },
222
+ ],
223
+ };
224
+ }
225
+ await fm.writeTaskPlan(taskPlan);
226
+ // 计算摘要
227
+ const summary = calculateTaskSummary(tasks);
228
+ const totalEstimate = tasks
229
+ .map((t) => t.estimate || '0h')
230
+ .join(' + ');
231
+ const nextTask = selectNextTask(tasks);
232
+ return {
233
+ success: true,
234
+ project_id: projectId,
235
+ project_name: name,
236
+ summary: {
237
+ total_tasks: summary.total,
238
+ total_estimate: totalEstimate,
239
+ },
240
+ files: {
241
+ index_yaml: 'tasks/task-plan.yaml',
242
+ index_md: 'tasks/task-plan.md',
243
+ project_yaml: `tasks/${projectId}/tasks.yaml`,
244
+ project_md: `tasks/${projectId}/tasks.md`,
245
+ },
246
+ next_task: nextTask,
247
+ };
248
+ }
249
+ async function handleStatus(fm, args) {
250
+ const input = StatusInputSchema.safeParse(args);
251
+ if (!input.success) {
252
+ return { success: false, error: `参数错误: ${input.error.message}` };
253
+ }
254
+ const { project_id } = input.data;
255
+ // 项目视图
256
+ if (project_id) {
257
+ const result = await fm.readProjectData(project_id);
258
+ if (!result.success) {
259
+ return { success: false, error: result.error };
260
+ }
261
+ const { meta, tasks } = result.data;
262
+ const summary = calculateTaskSummary(tasks);
263
+ const progress = calculateProgress(tasks);
264
+ const nextTask = selectNextTask(tasks);
265
+ // 找到当前进行中的任务
266
+ const currentTask = tasks.find((t) => t.status === 'in_progress');
267
+ return {
268
+ success: true,
269
+ project: {
270
+ id: meta.project_id,
271
+ name: meta.project,
272
+ description: meta.description,
273
+ updated: meta.updated,
274
+ },
275
+ summary,
276
+ progress,
277
+ current_task: currentTask
278
+ ? { id: currentTask.id, title: currentTask.title }
279
+ : null,
280
+ tasks,
281
+ };
282
+ }
283
+ // 全局视图
284
+ const taskPlanResult = await fm.readTaskPlan();
285
+ if (!taskPlanResult.success) {
286
+ return { success: false, error: taskPlanResult.error };
287
+ }
288
+ // 如果没有 task-plan.yaml,返回空列表
289
+ if (!taskPlanResult.data) {
290
+ return {
291
+ success: true,
292
+ total_projects: 0,
293
+ projects: [],
294
+ };
295
+ }
296
+ const projects = [];
297
+ for (const entry of taskPlanResult.data.projects) {
298
+ const projectResult = await fm.readProjectData(entry.project_id);
299
+ let progress = '?/?';
300
+ if (projectResult.success) {
301
+ progress = formatProgressString(projectResult.data.tasks);
302
+ }
303
+ projects.push({
304
+ id: entry.project_id,
305
+ name: entry.project,
306
+ status: entry.status,
307
+ progress,
308
+ updated: entry.updated,
309
+ });
310
+ }
311
+ return {
312
+ success: true,
313
+ total_projects: projects.length,
314
+ projects,
315
+ };
316
+ }
317
+ async function handleUpdate(fm, args) {
318
+ const input = UpdateInputSchema.safeParse(args);
319
+ if (!input.success) {
320
+ return { success: false, error: `参数错误: ${input.error.message}` };
321
+ }
322
+ const { project_id, task_id, status, notes } = input.data;
323
+ // 读取项目数据
324
+ const readResult = await fm.readProjectData(project_id);
325
+ if (!readResult.success) {
326
+ return { success: false, error: readResult.error };
327
+ }
328
+ const projectData = readResult.data;
329
+ // 执行状态更新(带校验)
330
+ const updateResult = updateTaskStatusWithValidation(projectData.tasks, task_id, status, notes);
331
+ if (!updateResult.success) {
332
+ return { success: false, error: updateResult.error };
333
+ }
334
+ // 更新数据
335
+ const updatedData = {
336
+ ...projectData,
337
+ tasks: updateResult.tasks,
338
+ };
339
+ // 写回文件
340
+ const writeResult = await fm.writeProjectData(project_id, updatedData);
341
+ if (!writeResult.success) {
342
+ return { success: false, error: writeResult.error };
343
+ }
344
+ // 计算返回值
345
+ const summary = calculateTaskSummary(updateResult.tasks);
346
+ const progress = calculateProgress(updateResult.tasks);
347
+ const nextTask = selectNextTask(updateResult.tasks);
348
+ return {
349
+ success: true,
350
+ updated: {
351
+ task_id,
352
+ status,
353
+ notes,
354
+ },
355
+ summary,
356
+ progress,
357
+ next_task: nextTask,
358
+ };
359
+ }
360
+ async function handleReset(fm, args) {
361
+ const input = ResetInputSchema.safeParse(args);
362
+ if (!input.success) {
363
+ return { success: false, error: `参数错误: ${input.error.message}` };
364
+ }
365
+ const { action, project_id, archive_id } = input.data;
366
+ switch (action) {
367
+ case 'cleanup': {
368
+ if (project_id) {
369
+ // 归档指定项目
370
+ const result = await fm.archiveProject(project_id);
371
+ if (!result.success) {
372
+ return { success: false, error: result.error };
373
+ }
374
+ return {
375
+ success: true,
376
+ action: 'cleanup',
377
+ archived_count: 1,
378
+ archived: [result.data.archiveId],
379
+ };
380
+ }
381
+ else {
382
+ // 归档所有已完成项目
383
+ const projects = await fm.listProjects();
384
+ const archived = [];
385
+ for (const pid of projects) {
386
+ const readResult = await fm.readProjectData(pid);
387
+ if (!readResult.success)
388
+ continue;
389
+ // 检查是否所有任务都完成
390
+ const allCompleted = readResult.data.tasks.every((t) => t.status === 'completed' || t.status === 'skipped');
391
+ if (allCompleted) {
392
+ const archiveResult = await fm.archiveProject(pid);
393
+ if (archiveResult.success) {
394
+ archived.push(archiveResult.data.archiveId);
395
+ }
396
+ }
397
+ }
398
+ return {
399
+ success: true,
400
+ action: 'cleanup',
401
+ archived_count: archived.length,
402
+ archived,
403
+ };
404
+ }
405
+ }
406
+ case 'list': {
407
+ const archives = await fm.listArchives();
408
+ return {
409
+ success: true,
410
+ action: 'list',
411
+ total: archives.length,
412
+ archives: archives.map((a) => ({
413
+ archive_id: a.archiveId,
414
+ project_id: a.projectId,
415
+ archived_at: a.archivedAt,
416
+ })),
417
+ };
418
+ }
419
+ case 'restore': {
420
+ if (!archive_id) {
421
+ return { success: false, error: 'restore 操作需要提供 archive_id' };
422
+ }
423
+ const result = await fm.restoreArchive(archive_id);
424
+ if (!result.success) {
425
+ return { success: false, error: result.error };
426
+ }
427
+ return {
428
+ success: true,
429
+ action: 'restore',
430
+ restored_project_id: result.data.projectId,
431
+ from_archive: archive_id,
432
+ };
433
+ }
434
+ default:
435
+ return { success: false, error: `未知操作: ${action}` };
436
+ }
437
+ }
438
+ //# sourceMappingURL=server.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"server.js","sourceRoot":"","sources":["../src/server.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,43 @@
1
+ import type { Task } from '../types.js';
2
+ export type DependencyGraph = Map<string, string[]>;
3
+ export type CircularCheckResult = {
4
+ hasCircle: false;
5
+ } | {
6
+ hasCircle: true;
7
+ cycle: string[];
8
+ };
9
+ /**
10
+ * 构建依赖图
11
+ * @param tasks 任务列表
12
+ * @returns 依赖图(Map)
13
+ */
14
+ export declare function buildDependencyGraph(tasks: Task[]): DependencyGraph;
15
+ /**
16
+ * 检测循环依赖
17
+ * 使用 DFS 算法检测有向图中的环
18
+ * @param tasks 任务列表
19
+ * @returns 检测结果,包含是否有环及环的路径
20
+ */
21
+ export declare function detectCircularDependency(tasks: Task[]): CircularCheckResult;
22
+ /**
23
+ * 获取任务的直接依赖列表
24
+ * @param tasks 任务列表
25
+ * @param taskId 任务ID
26
+ * @returns 依赖的任务ID列表
27
+ */
28
+ export declare function getTaskDependencies(tasks: Task[], taskId: string): string[];
29
+ /**
30
+ * 检查任务的所有依赖是否已完成
31
+ * @param tasks 任务列表
32
+ * @param taskId 任务ID
33
+ * @returns 如果所有依赖都已完成则返回 true
34
+ */
35
+ export declare function areDependenciesMet(tasks: Task[], taskId: string): boolean;
36
+ /**
37
+ * 获取未完成的依赖列表
38
+ * @param tasks 任务列表
39
+ * @param taskId 任务ID
40
+ * @returns 未完成的依赖任务ID列表
41
+ */
42
+ export declare function getUnmetDependencies(tasks: Task[], taskId: string): string[];
43
+ //# sourceMappingURL=dependency-resolver.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"dependency-resolver.d.ts","sourceRoot":"","sources":["../../src/task-engine/dependency-resolver.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,IAAI,EAAE,MAAM,aAAa,CAAC;AAGxC,MAAM,MAAM,eAAe,GAAG,GAAG,CAAC,MAAM,EAAE,MAAM,EAAE,CAAC,CAAC;AAGpD,MAAM,MAAM,mBAAmB,GAC3B;IAAE,SAAS,EAAE,KAAK,CAAA;CAAE,GACpB;IAAE,SAAS,EAAE,IAAI,CAAC;IAAC,KAAK,EAAE,MAAM,EAAE,CAAA;CAAE,CAAC;AAEzC;;;;GAIG;AACH,wBAAgB,oBAAoB,CAAC,KAAK,EAAE,IAAI,EAAE,GAAG,eAAe,CAQnE;AAED;;;;;GAKG;AACH,wBAAgB,wBAAwB,CAAC,KAAK,EAAE,IAAI,EAAE,GAAG,mBAAmB,CAsC3E;AAED;;;;;GAKG;AACH,wBAAgB,mBAAmB,CAAC,KAAK,EAAE,IAAI,EAAE,EAAE,MAAM,EAAE,MAAM,GAAG,MAAM,EAAE,CAG3E;AAED;;;;;GAKG;AACH,wBAAgB,kBAAkB,CAAC,KAAK,EAAE,IAAI,EAAE,EAAE,MAAM,EAAE,MAAM,GAAG,OAAO,CAWzE;AAED;;;;;GAKG;AACH,wBAAgB,oBAAoB,CAAC,KAAK,EAAE,IAAI,EAAE,EAAE,MAAM,EAAE,MAAM,GAAG,MAAM,EAAE,CAO5E"}
@@ -0,0 +1,94 @@
1
+ /**
2
+ * 构建依赖图
3
+ * @param tasks 任务列表
4
+ * @returns 依赖图(Map)
5
+ */
6
+ export function buildDependencyGraph(tasks) {
7
+ const graph = new Map();
8
+ for (const task of tasks) {
9
+ graph.set(task.id, task.dependencies ?? []);
10
+ }
11
+ return graph;
12
+ }
13
+ /**
14
+ * 检测循环依赖
15
+ * 使用 DFS 算法检测有向图中的环
16
+ * @param tasks 任务列表
17
+ * @returns 检测结果,包含是否有环及环的路径
18
+ */
19
+ export function detectCircularDependency(tasks) {
20
+ const graph = buildDependencyGraph(tasks);
21
+ const visited = new Set();
22
+ const recStack = new Set();
23
+ const path = [];
24
+ function dfs(nodeId) {
25
+ visited.add(nodeId);
26
+ recStack.add(nodeId);
27
+ path.push(nodeId);
28
+ const dependencies = graph.get(nodeId) ?? [];
29
+ for (const dep of dependencies) {
30
+ if (!visited.has(dep)) {
31
+ const cycle = dfs(dep);
32
+ if (cycle)
33
+ return cycle;
34
+ }
35
+ else if (recStack.has(dep)) {
36
+ // 发现环:从环的起点到当前节点,再加上起点形成闭环
37
+ const cycleStart = path.indexOf(dep);
38
+ return path.slice(cycleStart).concat(dep);
39
+ }
40
+ }
41
+ path.pop();
42
+ recStack.delete(nodeId);
43
+ return null;
44
+ }
45
+ for (const task of tasks) {
46
+ if (!visited.has(task.id)) {
47
+ const cycle = dfs(task.id);
48
+ if (cycle) {
49
+ return { hasCircle: true, cycle };
50
+ }
51
+ }
52
+ }
53
+ return { hasCircle: false };
54
+ }
55
+ /**
56
+ * 获取任务的直接依赖列表
57
+ * @param tasks 任务列表
58
+ * @param taskId 任务ID
59
+ * @returns 依赖的任务ID列表
60
+ */
61
+ export function getTaskDependencies(tasks, taskId) {
62
+ const task = tasks.find((t) => t.id === taskId);
63
+ return task?.dependencies ?? [];
64
+ }
65
+ /**
66
+ * 检查任务的所有依赖是否已完成
67
+ * @param tasks 任务列表
68
+ * @param taskId 任务ID
69
+ * @returns 如果所有依赖都已完成则返回 true
70
+ */
71
+ export function areDependenciesMet(tasks, taskId) {
72
+ const dependencies = getTaskDependencies(tasks, taskId);
73
+ if (dependencies.length === 0) {
74
+ return true;
75
+ }
76
+ return dependencies.every((depId) => {
77
+ const depTask = tasks.find((t) => t.id === depId);
78
+ return depTask?.status === 'completed';
79
+ });
80
+ }
81
+ /**
82
+ * 获取未完成的依赖列表
83
+ * @param tasks 任务列表
84
+ * @param taskId 任务ID
85
+ * @returns 未完成的依赖任务ID列表
86
+ */
87
+ export function getUnmetDependencies(tasks, taskId) {
88
+ const dependencies = getTaskDependencies(tasks, taskId);
89
+ return dependencies.filter((depId) => {
90
+ const depTask = tasks.find((t) => t.id === depId);
91
+ return depTask?.status !== 'completed';
92
+ });
93
+ }
94
+ //# sourceMappingURL=dependency-resolver.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"dependency-resolver.js","sourceRoot":"","sources":["../../src/task-engine/dependency-resolver.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,6 @@
1
+ export * from './parser.js';
2
+ export * from './status-reducer.js';
3
+ export * from './dependency-resolver.js';
4
+ export * from './progress-calculator.js';
5
+ export * from './next-task-selector.js';
6
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/task-engine/index.ts"],"names":[],"mappings":"AAAA,cAAc,aAAa,CAAC;AAC5B,cAAc,qBAAqB,CAAC;AACpC,cAAc,0BAA0B,CAAC;AACzC,cAAc,0BAA0B,CAAC;AACzC,cAAc,yBAAyB,CAAC"}
@@ -0,0 +1,6 @@
1
+ export * from './parser.js';
2
+ export * from './status-reducer.js';
3
+ export * from './dependency-resolver.js';
4
+ export * from './progress-calculator.js';
5
+ export * from './next-task-selector.js';
6
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/task-engine/index.ts"],"names":[],"mappings":"AAAA,cAAc,aAAa,CAAC;AAC5B,cAAc,qBAAqB,CAAC;AACpC,cAAc,0BAA0B,CAAC;AACzC,cAAc,0BAA0B,CAAC;AACzC,cAAc,yBAAyB,CAAC"}
@@ -0,0 +1,18 @@
1
+ import type { Task, NextTaskInfo } from '../types.js';
2
+ /**
3
+ * 选择下一个可执行的任务
4
+ * 按优先级和预估时间排序,选择最优先且预估时间最短的任务
5
+ */
6
+ export declare function selectNextTask(tasks: Task[]): NextTaskInfo;
7
+ /**
8
+ * 获取无可执行任务的原因
9
+ */
10
+ export declare function getNextTaskReason(tasks: Task[]): string;
11
+ /**
12
+ * 获取下一个任务或无法执行的原因
13
+ */
14
+ export declare function getNextTaskOrReason(tasks: Task[]): {
15
+ next: NextTaskInfo;
16
+ reason?: string;
17
+ };
18
+ //# sourceMappingURL=next-task-selector.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"next-task-selector.d.ts","sourceRoot":"","sources":["../../src/task-engine/next-task-selector.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,IAAI,EAAgB,YAAY,EAAE,MAAM,aAAa,CAAC;AAsCpE;;;GAGG;AACH,wBAAgB,cAAc,CAAC,KAAK,EAAE,IAAI,EAAE,GAAG,YAAY,CA0B1D;AAED;;GAEG;AACH,wBAAgB,iBAAiB,CAAC,KAAK,EAAE,IAAI,EAAE,GAAG,MAAM,CA8BvD;AAED;;GAEG;AACH,wBAAgB,mBAAmB,CACjC,KAAK,EAAE,IAAI,EAAE,GACZ;IAAE,IAAI,EAAE,YAAY,CAAC;IAAC,MAAM,CAAC,EAAE,MAAM,CAAA;CAAE,CAMzC"}