@haoyiyin/workflow 0.2.10 → 0.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/dist/src/agents/contracts/implementer.d.ts +29 -0
- package/dist/src/agents/contracts/implementer.d.ts.map +1 -0
- package/dist/src/agents/contracts/implementer.js +94 -0
- package/dist/src/agents/contracts/implementer.js.map +1 -0
- package/dist/src/agents/contracts/index.d.ts +11 -0
- package/dist/src/agents/contracts/index.d.ts.map +1 -0
- package/dist/src/agents/contracts/index.js +11 -0
- package/dist/src/agents/contracts/index.js.map +1 -0
- package/dist/src/agents/contracts/planner.d.ts +25 -0
- package/dist/src/agents/contracts/planner.d.ts.map +1 -0
- package/dist/src/agents/contracts/planner.js +107 -0
- package/dist/src/agents/contracts/planner.js.map +1 -0
- package/dist/src/agents/contracts/router.d.ts +24 -0
- package/dist/src/agents/contracts/router.d.ts.map +1 -0
- package/dist/src/agents/contracts/router.js +137 -0
- package/dist/src/agents/contracts/router.js.map +1 -0
- package/dist/src/agents/contracts/verifier.d.ts +27 -0
- package/dist/src/agents/contracts/verifier.d.ts.map +1 -0
- package/dist/src/agents/contracts/verifier.js +115 -0
- package/dist/src/agents/contracts/verifier.js.map +1 -0
- package/dist/src/agents/dispatcher.d.ts +94 -51
- package/dist/src/agents/dispatcher.d.ts.map +1 -1
- package/dist/src/agents/dispatcher.js +207 -164
- package/dist/src/agents/dispatcher.js.map +1 -1
- package/dist/src/persistence/index.d.ts +4 -2
- package/dist/src/persistence/index.d.ts.map +1 -1
- package/dist/src/persistence/index.js +4 -1
- package/dist/src/persistence/index.js.map +1 -1
- package/dist/src/persistence/plan-md.d.ts +3 -2
- package/dist/src/persistence/plan-md.d.ts.map +1 -1
- package/dist/src/persistence/plan-md.js +47 -15
- package/dist/src/persistence/plan-md.js.map +1 -1
- package/dist/src/persistence/state-md.d.ts +2 -0
- package/dist/src/persistence/state-md.d.ts.map +1 -1
- package/dist/src/persistence/state-md.js +40 -22
- package/dist/src/persistence/state-md.js.map +1 -1
- package/dist/src/persistence/types.d.ts +35 -39
- package/dist/src/persistence/types.d.ts.map +1 -1
- package/dist/src/router/namespace/core/intent-router.d.ts +24 -0
- package/dist/src/router/namespace/core/intent-router.d.ts.map +1 -0
- package/dist/src/router/namespace/core/intent-router.js +190 -0
- package/dist/src/router/namespace/core/intent-router.js.map +1 -0
- package/dist/src/router/namespace/core/lifecycle-router.d.ts +28 -0
- package/dist/src/router/namespace/core/lifecycle-router.d.ts.map +1 -0
- package/dist/src/router/namespace/core/lifecycle-router.js +132 -0
- package/dist/src/router/namespace/core/lifecycle-router.js.map +1 -0
- package/dist/src/router/namespace/core/state-router.d.ts +32 -0
- package/dist/src/router/namespace/core/state-router.d.ts.map +1 -0
- package/dist/src/router/namespace/core/state-router.js +157 -0
- package/dist/src/router/namespace/core/state-router.js.map +1 -0
- package/dist/src/router/namespace/domain/code-router.d.ts +26 -0
- package/dist/src/router/namespace/domain/code-router.d.ts.map +1 -0
- package/dist/src/router/namespace/domain/code-router.js +171 -0
- package/dist/src/router/namespace/domain/code-router.js.map +1 -0
- package/dist/src/router/namespace/domain/debug-router.d.ts +25 -0
- package/dist/src/router/namespace/domain/debug-router.d.ts.map +1 -0
- package/dist/src/router/namespace/domain/debug-router.js +139 -0
- package/dist/src/router/namespace/domain/debug-router.js.map +1 -0
- package/dist/src/router/namespace/domain/plan-router.d.ts +29 -0
- package/dist/src/router/namespace/domain/plan-router.d.ts.map +1 -0
- package/dist/src/router/namespace/domain/plan-router.js +160 -0
- package/dist/src/router/namespace/domain/plan-router.js.map +1 -0
- package/dist/src/router/namespace/domain/review-router.d.ts +24 -0
- package/dist/src/router/namespace/domain/review-router.d.ts.map +1 -0
- package/dist/src/router/namespace/domain/review-router.js +116 -0
- package/dist/src/router/namespace/domain/review-router.js.map +1 -0
- package/dist/src/router/namespace/index.d.ts +19 -0
- package/dist/src/router/namespace/index.d.ts.map +1 -0
- package/dist/src/router/namespace/index.js +22 -0
- package/dist/src/router/namespace/index.js.map +1 -0
- package/dist/src/router/namespace/registry.d.ts +67 -0
- package/dist/src/router/namespace/registry.d.ts.map +1 -0
- package/dist/src/router/namespace/registry.js +197 -0
- package/dist/src/router/namespace/registry.js.map +1 -0
- package/dist/src/router/namespace/types.d.ts +124 -0
- package/dist/src/router/namespace/types.d.ts.map +1 -0
- package/dist/src/router/namespace/types.js +20 -0
- package/dist/src/router/namespace/types.js.map +1 -0
- package/dist/src/router/namespace/utility/fallback-router.d.ts +28 -0
- package/dist/src/router/namespace/utility/fallback-router.d.ts.map +1 -0
- package/dist/src/router/namespace/utility/fallback-router.js +88 -0
- package/dist/src/router/namespace/utility/fallback-router.js.map +1 -0
- package/dist/src/router/namespace/utility/quick-task-router.d.ts +28 -0
- package/dist/src/router/namespace/utility/quick-task-router.d.ts.map +1 -0
- package/dist/src/router/namespace/utility/quick-task-router.js +99 -0
- package/dist/src/router/namespace/utility/quick-task-router.js.map +1 -0
- package/dist/src/router/namespace/utility/research-router.d.ts +24 -0
- package/dist/src/router/namespace/utility/research-router.d.ts.map +1 -0
- package/dist/src/router/namespace/utility/research-router.js +84 -0
- package/dist/src/router/namespace/utility/research-router.js.map +1 -0
- package/dist/src/skills/agents-md/index.js +2 -2
- package/dist/src/skills/agents-md/index.js.map +1 -1
- package/dist/src/skills/execute-plan/index.d.ts +45 -65
- package/dist/src/skills/execute-plan/index.d.ts.map +1 -1
- package/dist/src/skills/execute-plan/index.js +325 -551
- package/dist/src/skills/execute-plan/index.js.map +1 -1
- package/dist/src/skills/index.d.ts +1 -0
- package/dist/src/skills/index.d.ts.map +1 -1
- package/dist/src/skills/index.js +1 -0
- package/dist/src/skills/index.js.map +1 -1
- package/dist/src/skills/quick-task/index.d.ts +4 -4
- package/dist/src/skills/quick-task/index.js +1 -1
- package/dist/src/skills/quick-task/index.js.map +1 -1
- package/dist/src/skills/review-diff/index.d.ts +6 -6
- package/dist/src/skills/review-diff/index.js +1 -1
- package/dist/src/skills/review-diff/index.js.map +1 -1
- package/dist/src/skills/router/index.d.ts +101 -0
- package/dist/src/skills/router/index.d.ts.map +1 -0
- package/dist/src/skills/router/index.js +450 -0
- package/dist/src/skills/router/index.js.map +1 -0
- package/dist/src/skills/router/types.d.ts +79 -0
- package/dist/src/skills/router/types.d.ts.map +1 -0
- package/dist/src/skills/router/types.js +8 -0
- package/dist/src/skills/router/types.js.map +1 -0
- package/dist/src/skills/systematic-debugging/index.js +1 -1
- package/dist/src/skills/systematic-debugging/index.js.map +1 -1
- package/dist/src/skills/tdd/index.d.ts +14 -14
- package/dist/src/skills/tdd/index.js +1 -1
- package/dist/src/skills/tdd/index.js.map +1 -1
- package/dist/src/skills/to-plan/index-enhanced.d.ts +4 -4
- package/dist/src/skills/to-plan/index-enhanced.d.ts.map +1 -1
- package/dist/src/skills/to-plan/index-enhanced.js +3 -5
- package/dist/src/skills/to-plan/index-enhanced.js.map +1 -1
- package/dist/src/skills/to-plan/index.d.ts +24 -91
- package/dist/src/skills/to-plan/index.d.ts.map +1 -1
- package/dist/src/skills/to-plan/index.js +214 -409
- package/dist/src/skills/to-plan/index.js.map +1 -1
- package/package.json +3 -5
- package/src/agents/contracts/implementer.ts +122 -0
- package/src/agents/contracts/index.ts +27 -0
- package/src/agents/contracts/planner.ts +129 -0
- package/src/agents/contracts/router.ts +168 -0
- package/src/agents/contracts/verifier.ts +137 -0
- package/src/agents/dispatcher.ts +387 -362
- package/src/persistence/index.ts +10 -4
- package/src/persistence/plan-md.ts +52 -18
- package/src/persistence/state-md.ts +45 -23
- package/src/persistence/types.ts +37 -40
- package/src/router/namespace/README.md +127 -0
- package/src/router/namespace/core/intent-router.ts +221 -0
- package/src/router/namespace/core/lifecycle-router.ts +156 -0
- package/src/router/namespace/core/state-router.ts +192 -0
- package/src/router/namespace/domain/code-router.ts +202 -0
- package/src/router/namespace/domain/debug-router.ts +167 -0
- package/src/router/namespace/domain/plan-router.ts +196 -0
- package/src/router/namespace/domain/review-router.ts +142 -0
- package/src/router/namespace/index.ts +84 -0
- package/src/router/namespace/registry.ts +242 -0
- package/src/router/namespace/types.ts +182 -0
- package/src/router/namespace/utility/fallback-router.ts +107 -0
- package/src/router/namespace/utility/quick-task-router.ts +121 -0
- package/src/router/namespace/utility/research-router.ts +105 -0
- package/src/skills/agents-md/index.ts +2 -2
- package/src/skills/execute-plan/index.ts +419 -673
- package/src/skills/index.ts +1 -0
- package/src/skills/quick-task/index.ts +1 -1
- package/src/skills/review-diff/index.ts +1 -1
- package/src/skills/router/SKILL.md +181 -0
- package/src/skills/router/index.ts +577 -0
- package/src/skills/router/types.ts +90 -0
- package/src/skills/systematic-debugging/index.ts +1 -1
- package/src/skills/tdd/index.ts +1 -1
- package/src/skills/to-plan/index-enhanced.ts +3 -5
- package/src/skills/to-plan/index.ts +231 -502
package/src/persistence/index.ts
CHANGED
|
@@ -1,8 +1,14 @@
|
|
|
1
1
|
/**
|
|
2
|
-
* Persistence layer
|
|
2
|
+
* Persistence layer entry point
|
|
3
|
+
*
|
|
4
|
+
* Provides STATE.md and PLAN.md management for workflow state persistence.
|
|
3
5
|
*/
|
|
6
|
+
|
|
7
|
+
// Managers
|
|
4
8
|
export { StateMdManager } from './state-md.js'
|
|
5
9
|
export { PlanMdManager } from './plan-md.js'
|
|
10
|
+
|
|
11
|
+
// Types
|
|
6
12
|
export type {
|
|
7
13
|
Task,
|
|
8
14
|
Wave,
|
|
@@ -11,7 +17,7 @@ export type {
|
|
|
11
17
|
VerificationResult,
|
|
12
18
|
DimensionResult,
|
|
13
19
|
WorkflowState,
|
|
14
|
-
StateMdManager as
|
|
15
|
-
PlanMdManager as
|
|
16
|
-
PersistenceManager
|
|
20
|
+
StateMdManager as StateMdManagerInterface,
|
|
21
|
+
PlanMdManager as PlanMdManagerInterface,
|
|
22
|
+
PersistenceManager,
|
|
17
23
|
} from './types.js'
|
|
@@ -3,7 +3,7 @@
|
|
|
3
3
|
*/
|
|
4
4
|
import { promises as fs } from 'fs'
|
|
5
5
|
import { dirname } from 'path'
|
|
6
|
-
import type { Plan, Task, PlanMdManager as IPlanMdManager } from './types.js'
|
|
6
|
+
import type { Plan, Task, Wave, PlanMdManager as IPlanMdManager } from './types.js'
|
|
7
7
|
|
|
8
8
|
export class PlanMdManager implements IPlanMdManager {
|
|
9
9
|
private planPath: string
|
|
@@ -20,9 +20,16 @@ export class PlanMdManager implements IPlanMdManager {
|
|
|
20
20
|
await fs.writeFile(this.planPath, content, 'utf-8')
|
|
21
21
|
}
|
|
22
22
|
|
|
23
|
-
async readPlan(): Promise<Plan> {
|
|
24
|
-
|
|
25
|
-
|
|
23
|
+
async readPlan(): Promise<Plan | null> {
|
|
24
|
+
try {
|
|
25
|
+
const content = await fs.readFile(this.planPath, 'utf-8')
|
|
26
|
+
return this.parsePlan(content)
|
|
27
|
+
} catch (error) {
|
|
28
|
+
if ((error as NodeJS.ErrnoException).code === 'ENOENT') {
|
|
29
|
+
return null
|
|
30
|
+
}
|
|
31
|
+
throw error
|
|
32
|
+
}
|
|
26
33
|
}
|
|
27
34
|
|
|
28
35
|
async updateTaskStatus(taskId: string, status: 'pending' | 'in_progress' | 'complete'): Promise<void> {
|
|
@@ -35,14 +42,37 @@ export class PlanMdManager implements IPlanMdManager {
|
|
|
35
42
|
await fs.writeFile(this.planPath, updated, 'utf-8')
|
|
36
43
|
}
|
|
37
44
|
|
|
45
|
+
async getNextPendingWave(): Promise<Wave | null> {
|
|
46
|
+
const plan = await this.readPlan()
|
|
47
|
+
if (!plan) {
|
|
48
|
+
return null
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
// Find first wave with pending tasks
|
|
52
|
+
for (const wave of plan.waves) {
|
|
53
|
+
const hasPendingTask = wave.tasks.some(task => task.status === 'pending')
|
|
54
|
+
if (hasPendingTask) {
|
|
55
|
+
return wave
|
|
56
|
+
}
|
|
57
|
+
}
|
|
58
|
+
|
|
59
|
+
return null
|
|
60
|
+
}
|
|
61
|
+
|
|
38
62
|
private generatePlanMarkdown(plan: Plan): string {
|
|
63
|
+
const getStatusChar = (status: Task['status']) => {
|
|
64
|
+
if (status === 'completed') return 'x'
|
|
65
|
+
if (status === 'in_progress') return '~'
|
|
66
|
+
return ' '
|
|
67
|
+
}
|
|
68
|
+
|
|
39
69
|
return `# Execution Plan
|
|
40
70
|
|
|
41
71
|
## Goal
|
|
42
72
|
${plan.goal}
|
|
43
73
|
|
|
44
74
|
## Tasks
|
|
45
|
-
${plan.tasks.map(t => `- [
|
|
75
|
+
${plan.tasks.map(t => `- [${getStatusChar(t.status)}] ${t.id}: ${t.description} (${t.estimatedComplexity})`).join('\n')}
|
|
46
76
|
|
|
47
77
|
## Dependencies
|
|
48
78
|
${Object.entries(plan.dependencies).length > 0
|
|
@@ -51,7 +81,7 @@ ${Object.entries(plan.dependencies).length > 0
|
|
|
51
81
|
}
|
|
52
82
|
|
|
53
83
|
## Waves
|
|
54
|
-
${plan.waves.map(w => `- ${w.id}: ${w.tasks.join(', ')}`).join('\n')}
|
|
84
|
+
${plan.waves.map(w => `- ${w.id}: ${w.tasks.map(t => t.id).join(', ')}`).join('\n')}
|
|
55
85
|
|
|
56
86
|
## Verification Criteria
|
|
57
87
|
${plan.verificationCriteria.map(c => `- ${c}`).join('\n')}
|
|
@@ -60,9 +90,6 @@ ${plan.verificationCriteria.map(c => `- ${c}`).join('\n')}
|
|
|
60
90
|
- Total Tasks: ${plan.tasks.length}
|
|
61
91
|
- Parallel Waves: ${plan.waves.length}
|
|
62
92
|
- Estimated Duration: ${plan.estimatedDuration}ms
|
|
63
|
-
|
|
64
|
-
## Rationale
|
|
65
|
-
${plan.rationale}
|
|
66
93
|
`
|
|
67
94
|
}
|
|
68
95
|
|
|
@@ -73,19 +100,22 @@ ${plan.rationale}
|
|
|
73
100
|
const wavesMatch = content.match(/## Waves\n([\s\S]*?)(?=\n## |$)/)
|
|
74
101
|
const criteriaMatch = content.match(/## Verification Criteria\n([\s\S]*?)(?=\n## |$)/)
|
|
75
102
|
const durationMatch = content.match(/- Estimated Duration: (\d+)/)
|
|
76
|
-
const rationaleMatch = content.match(/## Rationale\n([\s\S]*?)(?=\n## |$)/)
|
|
77
103
|
|
|
78
104
|
// Parse tasks
|
|
79
105
|
const tasks: Task[] = []
|
|
80
106
|
if (tasksMatch) {
|
|
81
107
|
const taskLines = tasksMatch[1].split('\n').filter(l => l.trim().startsWith('- ['))
|
|
82
108
|
for (const line of taskLines) {
|
|
83
|
-
const match = line.match(/- \[
|
|
109
|
+
const match = line.match(/- \[(.)\]\s+(\w+):\s+(.+)\s+\((\w+)\)/)
|
|
84
110
|
if (match) {
|
|
111
|
+
const statusChar = match[1]
|
|
112
|
+
const status = statusChar === 'x' ? 'completed' : statusChar === '~' ? 'in_progress' : 'pending'
|
|
85
113
|
tasks.push({
|
|
86
|
-
id: match[
|
|
87
|
-
description: match[
|
|
88
|
-
|
|
114
|
+
id: match[2],
|
|
115
|
+
description: match[3],
|
|
116
|
+
status,
|
|
117
|
+
dependencies: [],
|
|
118
|
+
estimatedComplexity: match[4] as 'low' | 'medium' | 'high'
|
|
89
119
|
})
|
|
90
120
|
}
|
|
91
121
|
}
|
|
@@ -103,16 +133,21 @@ ${plan.rationale}
|
|
|
103
133
|
}
|
|
104
134
|
}
|
|
105
135
|
|
|
136
|
+
// Build task map for wave parsing
|
|
137
|
+
const taskMap = new Map<string, Task>(tasks.map(t => [t.id, t]))
|
|
138
|
+
|
|
106
139
|
// Parse waves
|
|
107
|
-
const waves = []
|
|
140
|
+
const waves: Wave[] = []
|
|
108
141
|
if (wavesMatch) {
|
|
109
142
|
const waveLines = wavesMatch[1].split('\n').filter(l => l.trim().startsWith('- '))
|
|
110
143
|
for (const line of waveLines) {
|
|
111
144
|
const match = line.match(/- (\w+):\s*(.+)/)
|
|
112
145
|
if (match) {
|
|
146
|
+
const taskIds = match[2].split(',').map(s => s.trim()).filter(s => s)
|
|
147
|
+
const waveTasks = taskIds.map(id => taskMap.get(id)).filter((t): t is Task => t !== undefined)
|
|
113
148
|
waves.push({
|
|
114
149
|
id: match[1],
|
|
115
|
-
tasks:
|
|
150
|
+
tasks: waveTasks
|
|
116
151
|
})
|
|
117
152
|
}
|
|
118
153
|
}
|
|
@@ -134,8 +169,7 @@ ${plan.rationale}
|
|
|
134
169
|
dependencies,
|
|
135
170
|
waves,
|
|
136
171
|
verificationCriteria,
|
|
137
|
-
estimatedDuration: durationMatch ? parseInt(durationMatch[1], 10) : 0
|
|
138
|
-
rationale: rationaleMatch?.[1]?.trim() || ''
|
|
172
|
+
estimatedDuration: durationMatch ? parseInt(durationMatch[1], 10) : 0
|
|
139
173
|
}
|
|
140
174
|
}
|
|
141
175
|
}
|
|
@@ -36,10 +36,7 @@ ${goal}
|
|
|
36
36
|
<!-- Populated by verify phase -->
|
|
37
37
|
|
|
38
38
|
## Token Usage
|
|
39
|
-
|
|
40
|
-
- Execute Phase: 0
|
|
41
|
-
- Verify Phase: 0
|
|
42
|
-
- Total: 0 / 1000000
|
|
39
|
+
0
|
|
43
40
|
`
|
|
44
41
|
await fs.writeFile(this.statePath, content, 'utf-8')
|
|
45
42
|
}
|
|
@@ -65,7 +62,14 @@ ${goal}
|
|
|
65
62
|
|
|
66
63
|
async recordTaskComplete(taskId: string, result: TaskResult): Promise<void> {
|
|
67
64
|
const content = await fs.readFile(this.statePath, 'utf-8')
|
|
68
|
-
const entry = `- [x] ${taskId}:
|
|
65
|
+
const entry = `- [x] ${taskId}: ✓ (${result.duration}ms) - ${result.notes || ''}\n`
|
|
66
|
+
const updated = this.appendToSection(content, 'Completed Tasks', entry)
|
|
67
|
+
await fs.writeFile(this.statePath, updated, 'utf-8')
|
|
68
|
+
}
|
|
69
|
+
|
|
70
|
+
async recordTaskFailed(taskId: string, error?: string): Promise<void> {
|
|
71
|
+
const content = await fs.readFile(this.statePath, 'utf-8')
|
|
72
|
+
const entry = `- [x] ${taskId}: ✗ FAILED${error ? ` - ${error}` : ''}\n`
|
|
69
73
|
const updated = this.appendToSection(content, 'Completed Tasks', entry)
|
|
70
74
|
await fs.writeFile(this.statePath, updated, 'utf-8')
|
|
71
75
|
}
|
|
@@ -77,6 +81,15 @@ ${goal}
|
|
|
77
81
|
await fs.writeFile(this.statePath, updated, 'utf-8')
|
|
78
82
|
}
|
|
79
83
|
|
|
84
|
+
async updateTokenUsage(tokens: number): Promise<void> {
|
|
85
|
+
const content = await fs.readFile(this.statePath, 'utf-8')
|
|
86
|
+
const updated = content.replace(
|
|
87
|
+
/## Token Usage\n\d+/,
|
|
88
|
+
`## Token Usage\n${tokens}`
|
|
89
|
+
)
|
|
90
|
+
await fs.writeFile(this.statePath, updated, 'utf-8')
|
|
91
|
+
}
|
|
92
|
+
|
|
80
93
|
async readCurrentState(): Promise<WorkflowState> {
|
|
81
94
|
const content = await fs.readFile(this.statePath, 'utf-8')
|
|
82
95
|
return this.parseState(content)
|
|
@@ -91,7 +104,7 @@ ${plan.goal}
|
|
|
91
104
|
${plan.tasks.map(t => `- ${t.id}: ${t.description} (${t.estimatedComplexity})`).join('\n')}
|
|
92
105
|
|
|
93
106
|
### Waves (${plan.waves.length})
|
|
94
|
-
${plan.waves.map(w => `- ${w.id}: ${w.tasks.join(', ')}`).join('\n')}
|
|
107
|
+
${plan.waves.map(w => `- ${w.id}: ${w.tasks.map(t => t.id).join(', ')}`).join('\n')}
|
|
95
108
|
|
|
96
109
|
### Verification Criteria
|
|
97
110
|
${plan.verificationCriteria.map(c => `- ${c}`).join('\n')}
|
|
@@ -99,8 +112,8 @@ ${plan.verificationCriteria.map(c => `- ${c}`).join('\n')}
|
|
|
99
112
|
### Estimated Duration
|
|
100
113
|
${plan.estimatedDuration}ms
|
|
101
114
|
|
|
102
|
-
###
|
|
103
|
-
${plan.
|
|
115
|
+
### Dependencies
|
|
116
|
+
${Object.entries(plan.dependencies).map(([taskId, deps]) => `- ${taskId}: ${deps.join(', ') || 'none'}`).join('\n')}
|
|
104
117
|
`
|
|
105
118
|
}
|
|
106
119
|
|
|
@@ -141,27 +154,36 @@ ${results.join('\n')}
|
|
|
141
154
|
const phaseMatch = content.match(/- Phase: (\w+)/)
|
|
142
155
|
const goalMatch = content.match(/## Goal\n(.+)/)
|
|
143
156
|
const startedMatch = content.match(/- Started: (.+)/)
|
|
144
|
-
const
|
|
157
|
+
const lastUpdatedMatch = content.match(/- Last Updated: (.+)/)
|
|
158
|
+
const tokenMatch = content.match(/## Token Usage\n(\d+)/)
|
|
145
159
|
const completedMatch = content.match(/## Completed Tasks\n([\s\S]*?)(?=\n## |$)/)
|
|
146
160
|
|
|
147
|
-
const completedTasks =
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
161
|
+
const completedTasks: string[] = []
|
|
162
|
+
const failedTasks: string[] = []
|
|
163
|
+
|
|
164
|
+
if (completedMatch) {
|
|
165
|
+
const lines = completedMatch[1].split('\n').filter(l => l.trim().startsWith('- [x]'))
|
|
166
|
+
for (const line of lines) {
|
|
167
|
+
const taskIdMatch = line.match(/- \[x\] ([^:]+):/)
|
|
168
|
+
if (taskIdMatch) {
|
|
169
|
+
if (line.includes('✗ FAILED')) {
|
|
170
|
+
failedTasks.push(taskIdMatch[1])
|
|
171
|
+
} else {
|
|
172
|
+
completedTasks.push(taskIdMatch[1])
|
|
173
|
+
}
|
|
174
|
+
}
|
|
175
|
+
}
|
|
176
|
+
}
|
|
152
177
|
|
|
153
178
|
return {
|
|
154
179
|
goal: goalMatch?.[1] || '',
|
|
155
180
|
phase: (phaseMatch?.[1] as WorkflowState['phase']) || 'planning',
|
|
156
|
-
|
|
157
|
-
lastUpdated: new Date().toISOString(),
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
limit: 1000000,
|
|
163
|
-
percentage: 0
|
|
164
|
-
}
|
|
181
|
+
startedAt: startedMatch?.[1] || new Date().toISOString(),
|
|
182
|
+
lastUpdated: lastUpdatedMatch?.[1] || new Date().toISOString(),
|
|
183
|
+
completedTasks,
|
|
184
|
+
failedTasks,
|
|
185
|
+
totalTasks: 0,
|
|
186
|
+
tokenUsage: { used: tokenMatch ? parseInt(tokenMatch[1], 10) : 0, limit: 1000000, percentage: 0 }
|
|
165
187
|
}
|
|
166
188
|
}
|
|
167
189
|
}
|
package/src/persistence/types.ts
CHANGED
|
@@ -5,67 +5,45 @@
|
|
|
5
5
|
export interface Task {
|
|
6
6
|
id: string
|
|
7
7
|
description: string
|
|
8
|
+
status: 'pending' | 'in_progress' | 'completed' | 'failed'
|
|
9
|
+
dependencies: string[]
|
|
8
10
|
estimatedComplexity: 'low' | 'medium' | 'high'
|
|
9
11
|
relatedFiles?: string[]
|
|
10
|
-
verificationCriteria?: string[]
|
|
11
12
|
}
|
|
12
13
|
|
|
13
14
|
export interface Wave {
|
|
14
15
|
id: string
|
|
15
|
-
tasks:
|
|
16
|
+
tasks: Task[]
|
|
16
17
|
}
|
|
17
18
|
|
|
18
19
|
export interface Plan {
|
|
19
20
|
goal: string
|
|
20
21
|
tasks: Task[]
|
|
21
|
-
dependencies: Record<string, string[]>
|
|
22
22
|
waves: Wave[]
|
|
23
|
+
dependencies: Record<string, string[]>
|
|
23
24
|
verificationCriteria: string[]
|
|
24
25
|
estimatedDuration: number
|
|
25
|
-
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
export interface WorkflowState {
|
|
29
|
+
goal: string
|
|
30
|
+
phase: 'discovery' | 'planning' | 'executing' | 'verifying' | 'completed' | 'failed' | 'idle'
|
|
31
|
+
startedAt: string
|
|
32
|
+
lastUpdated: string
|
|
33
|
+
completedTasks: string[]
|
|
34
|
+
failedTasks: string[]
|
|
35
|
+
totalTasks: number
|
|
36
|
+
tokenUsage: { used: number; limit: number; percentage: number }
|
|
26
37
|
}
|
|
27
38
|
|
|
28
39
|
export interface TaskResult {
|
|
29
40
|
taskId: string
|
|
30
41
|
success: boolean
|
|
31
|
-
filesModified: string[]
|
|
32
|
-
testsAdded: string[]
|
|
33
42
|
duration: number
|
|
34
43
|
notes: string
|
|
44
|
+
filesModified?: string[]
|
|
45
|
+
testsAdded?: string[]
|
|
35
46
|
error?: string
|
|
36
|
-
phases?: { phase: string; status: string; command?: string; evidence?: string }[]
|
|
37
|
-
worktreePath?: string
|
|
38
|
-
branchName?: string
|
|
39
|
-
}
|
|
40
|
-
|
|
41
|
-
export interface VerificationResult {
|
|
42
|
-
success: boolean
|
|
43
|
-
dimensions: {
|
|
44
|
-
goals?: DimensionResult
|
|
45
|
-
quality?: DimensionResult
|
|
46
|
-
tests?: DimensionResult
|
|
47
|
-
}
|
|
48
|
-
}
|
|
49
|
-
|
|
50
|
-
export interface DimensionResult {
|
|
51
|
-
success: boolean
|
|
52
|
-
details?: unknown
|
|
53
|
-
evidence?: string[]
|
|
54
|
-
gaps?: string[]
|
|
55
|
-
}
|
|
56
|
-
|
|
57
|
-
export interface WorkflowState {
|
|
58
|
-
goal: string
|
|
59
|
-
phase: 'planning' | 'executing' | 'verifying' | 'complete'
|
|
60
|
-
started: string
|
|
61
|
-
lastUpdated: string
|
|
62
|
-
totalTasks: number
|
|
63
|
-
completedTasks: TaskResult[]
|
|
64
|
-
tokenUsage: {
|
|
65
|
-
used: number
|
|
66
|
-
limit: number
|
|
67
|
-
percentage: number
|
|
68
|
-
}
|
|
69
47
|
}
|
|
70
48
|
|
|
71
49
|
export interface StateMdManager {
|
|
@@ -73,17 +51,36 @@ export interface StateMdManager {
|
|
|
73
51
|
updatePhase(phase: WorkflowState['phase']): Promise<void>
|
|
74
52
|
recordPlan(plan: Plan): Promise<void>
|
|
75
53
|
recordTaskComplete(taskId: string, result: TaskResult): Promise<void>
|
|
54
|
+
recordTaskFailed(taskId: string, error?: string): Promise<void>
|
|
76
55
|
recordVerification(verification: VerificationResult): Promise<void>
|
|
56
|
+
updateTokenUsage(tokens: number): Promise<void>
|
|
77
57
|
readCurrentState(): Promise<WorkflowState>
|
|
78
58
|
}
|
|
79
59
|
|
|
80
60
|
export interface PlanMdManager {
|
|
81
61
|
writePlan(plan: Plan): Promise<void>
|
|
82
|
-
readPlan(): Promise<Plan>
|
|
62
|
+
readPlan(): Promise<Plan | null>
|
|
83
63
|
updateTaskStatus(taskId: string, status: 'pending' | 'in_progress' | 'complete'): Promise<void>
|
|
64
|
+
getNextPendingWave(): Promise<Wave | null>
|
|
84
65
|
}
|
|
85
66
|
|
|
86
67
|
export interface PersistenceManager {
|
|
87
68
|
state: StateMdManager
|
|
88
69
|
plan: PlanMdManager
|
|
89
70
|
}
|
|
71
|
+
|
|
72
|
+
export interface VerificationResult {
|
|
73
|
+
success: boolean
|
|
74
|
+
dimensions: {
|
|
75
|
+
goals?: DimensionResult
|
|
76
|
+
quality?: DimensionResult
|
|
77
|
+
tests?: DimensionResult
|
|
78
|
+
}
|
|
79
|
+
}
|
|
80
|
+
|
|
81
|
+
export interface DimensionResult {
|
|
82
|
+
success: boolean
|
|
83
|
+
details?: unknown
|
|
84
|
+
evidence?: string[]
|
|
85
|
+
gaps?: string[]
|
|
86
|
+
}
|
|
@@ -0,0 +1,127 @@
|
|
|
1
|
+
# Namespace 路由分层设计
|
|
2
|
+
|
|
3
|
+
## 架构概述
|
|
4
|
+
|
|
5
|
+
Namespace 路由分层设计将路由系统组织成层次化的命名空间,每个命名空间负责特定领域的路由决策。
|
|
6
|
+
|
|
7
|
+
```
|
|
8
|
+
Router (根命名空间)
|
|
9
|
+
├── Core (核心命名空间)
|
|
10
|
+
│ ├── LifecycleRouter - 生命周期阶段路由
|
|
11
|
+
│ ├── StateRouter - 状态感知路由
|
|
12
|
+
│ └── IntentRouter - 意图分类路由
|
|
13
|
+
├── Domain (领域命名空间)
|
|
14
|
+
│ ├── PlanRouter - 计划相关路由
|
|
15
|
+
│ ├── CodeRouter - 代码操作路由
|
|
16
|
+
│ ├── DebugRouter - 调试相关路由
|
|
17
|
+
│ └── ReviewRouter - 代码审查路由
|
|
18
|
+
└── Utility (工具命名空间)
|
|
19
|
+
├── QuickTaskRouter - 快速任务路由
|
|
20
|
+
├── ResearchRouter - 研究探索路由
|
|
21
|
+
└── FallbackRouter - 降级路由
|
|
22
|
+
```
|
|
23
|
+
|
|
24
|
+
## 分层原则
|
|
25
|
+
|
|
26
|
+
### Layer 1: 核心层 (Core)
|
|
27
|
+
负责基础路由决策:
|
|
28
|
+
- **LifecycleRouter**: 根据项目生命周期阶段选择可用技能
|
|
29
|
+
- **StateRouter**: 根据 STATE.md 和 PLAN.md 的状态进行路由
|
|
30
|
+
- **IntentRouter**: 基于用户意图的分类和匹配
|
|
31
|
+
|
|
32
|
+
### Layer 2: 领域层 (Domain)
|
|
33
|
+
负责特定领域的复杂路由:
|
|
34
|
+
- **PlanRouter**: 计划创建、执行、验证的完整流程
|
|
35
|
+
- **CodeRouter**: 代码编写、重构、测试相关的路由
|
|
36
|
+
- **DebugRouter**: 调试、错误诊断、修复建议
|
|
37
|
+
- **ReviewRouter**: 代码审查、质量检查
|
|
38
|
+
|
|
39
|
+
### Layer 3: 工具层 (Utility)
|
|
40
|
+
处理简单的、独立的路由决策:
|
|
41
|
+
- **QuickTaskRouter**: 小任务、快速修复
|
|
42
|
+
- **ResearchRouter**: 研究、探索、信息收集
|
|
43
|
+
- **FallbackRouter**: 当其他路由无法确定时使用
|
|
44
|
+
|
|
45
|
+
## 路由流程
|
|
46
|
+
|
|
47
|
+
```
|
|
48
|
+
用户请求
|
|
49
|
+
↓
|
|
50
|
+
[Core Layer]
|
|
51
|
+
- 检查生命周期
|
|
52
|
+
- 读取 STATE/PLAN
|
|
53
|
+
- 提取意图
|
|
54
|
+
↓
|
|
55
|
+
[Domain Layer] (如果匹配)
|
|
56
|
+
- 领域特定路由逻辑
|
|
57
|
+
- 复杂决策流程
|
|
58
|
+
↓
|
|
59
|
+
[Utility Layer] (如果 Domain 不匹配)
|
|
60
|
+
- 简单匹配
|
|
61
|
+
- 快速决策
|
|
62
|
+
↓
|
|
63
|
+
选择目标 Skill
|
|
64
|
+
```
|
|
65
|
+
|
|
66
|
+
## Namespace 接口
|
|
67
|
+
|
|
68
|
+
```typescript
|
|
69
|
+
// 命名空间路由接口
|
|
70
|
+
interface NamespaceRouter {
|
|
71
|
+
readonly name: string
|
|
72
|
+
readonly priority: number // 优先级,越高越先匹配
|
|
73
|
+
readonly patterns: string[] // 匹配模式
|
|
74
|
+
|
|
75
|
+
// 检查是否可以处理此请求
|
|
76
|
+
canRoute(context: RoutingContext): boolean | Promise<boolean>
|
|
77
|
+
|
|
78
|
+
// 执行路由决策
|
|
79
|
+
route(context: RoutingContext): RouteDecision | Promise<RouteDecision>
|
|
80
|
+
}
|
|
81
|
+
|
|
82
|
+
// 路由上下文
|
|
83
|
+
interface RoutingContext {
|
|
84
|
+
request: UserRequest
|
|
85
|
+
state: WorkflowState
|
|
86
|
+
plan: Plan | null
|
|
87
|
+
history: ConversationHistory[]
|
|
88
|
+
config: RouterConfig
|
|
89
|
+
}
|
|
90
|
+
|
|
91
|
+
// 路由决策
|
|
92
|
+
interface RouteDecision {
|
|
93
|
+
skill: string
|
|
94
|
+
confidence: number
|
|
95
|
+
reasoning: string
|
|
96
|
+
namespace: string // 来源命名空间
|
|
97
|
+
alternatives: AlternativeRoute[]
|
|
98
|
+
}
|
|
99
|
+
```
|
|
100
|
+
|
|
101
|
+
## 配置示例
|
|
102
|
+
|
|
103
|
+
```typescript
|
|
104
|
+
// router.config.ts
|
|
105
|
+
export const namespaceConfig: NamespaceConfig = {
|
|
106
|
+
core: {
|
|
107
|
+
enabled: true,
|
|
108
|
+
routers: ['lifecycle', 'state', 'intent'],
|
|
109
|
+
},
|
|
110
|
+
domain: {
|
|
111
|
+
enabled: true,
|
|
112
|
+
routers: ['plan', 'code', 'debug', 'review'],
|
|
113
|
+
},
|
|
114
|
+
utility: {
|
|
115
|
+
enabled: true,
|
|
116
|
+
routers: ['quick-task', 'research', 'fallback'],
|
|
117
|
+
},
|
|
118
|
+
}
|
|
119
|
+
```
|
|
120
|
+
|
|
121
|
+
## 扩展性
|
|
122
|
+
|
|
123
|
+
新增命名空间只需:
|
|
124
|
+
1. 创建命名空间目录
|
|
125
|
+
2. 实现 NamespaceRouter 接口
|
|
126
|
+
3. 在配置中注册
|
|
127
|
+
4. 系统自动加载并按优先级排序
|