@haoyiyin/workflow 0.2.11 → 0.3.1
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/pi-extension.d.ts +4 -3
- package/dist/src/pi-extension.d.ts.map +1 -1
- package/dist/src/pi-extension.js +36 -67
- package/dist/src/pi-extension.js.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/scripts/postinstall.js +42 -47
- 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/pi-extension.ts +38 -76
- 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 +81 -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/dist/src/extension/classifier.d.ts +0 -18
- package/dist/src/extension/classifier.d.ts.map +0 -1
- package/dist/src/extension/classifier.js +0 -143
- package/dist/src/extension/classifier.js.map +0 -1
- package/src/extension/classifier.ts +0 -160
|
@@ -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. 系统自动加载并按优先级排序
|
|
@@ -0,0 +1,221 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Intent Router - Core Layer
|
|
3
|
+
*
|
|
4
|
+
* 基于用户意图的分类进行路由决策
|
|
5
|
+
* 使用关键词和模式匹配提取意图
|
|
6
|
+
*/
|
|
7
|
+
|
|
8
|
+
import type {
|
|
9
|
+
NamespaceRouter,
|
|
10
|
+
RoutingContext,
|
|
11
|
+
RouteDecision,
|
|
12
|
+
NamespaceHealth,
|
|
13
|
+
AlternativeRoute,
|
|
14
|
+
} from '../types.js'
|
|
15
|
+
|
|
16
|
+
// 意图定义
|
|
17
|
+
interface IntentPattern {
|
|
18
|
+
name: string
|
|
19
|
+
patterns: RegExp[]
|
|
20
|
+
targetSkill: string
|
|
21
|
+
confidence: number
|
|
22
|
+
complexity: 'low' | 'medium' | 'high'
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
const INTENTS: IntentPattern[] = [
|
|
26
|
+
{
|
|
27
|
+
name: 'plan',
|
|
28
|
+
patterns: [
|
|
29
|
+
/plan|设计|架构|方案/i,
|
|
30
|
+
/how to implement|如何实现/i,
|
|
31
|
+
/architecture|结构/i,
|
|
32
|
+
/strategy|策略/i,
|
|
33
|
+
],
|
|
34
|
+
targetSkill: 'to-plan',
|
|
35
|
+
confidence: 0.85,
|
|
36
|
+
complexity: 'high',
|
|
37
|
+
},
|
|
38
|
+
{
|
|
39
|
+
name: 'execute',
|
|
40
|
+
patterns: [
|
|
41
|
+
/implement|实现|完成/i,
|
|
42
|
+
/build|创建|建立/i,
|
|
43
|
+
/develop|开发/i,
|
|
44
|
+
/execute|执行/i,
|
|
45
|
+
],
|
|
46
|
+
targetSkill: 'execute-plan',
|
|
47
|
+
confidence: 0.8,
|
|
48
|
+
complexity: 'high',
|
|
49
|
+
},
|
|
50
|
+
{
|
|
51
|
+
name: 'fix',
|
|
52
|
+
patterns: [
|
|
53
|
+
/fix|修复|解决/i,
|
|
54
|
+
/correct|修正/i,
|
|
55
|
+
/update|更新.*(typo|typo|错误)/i,
|
|
56
|
+
],
|
|
57
|
+
targetSkill: 'quick-task',
|
|
58
|
+
confidence: 0.75,
|
|
59
|
+
complexity: 'low',
|
|
60
|
+
},
|
|
61
|
+
{
|
|
62
|
+
name: 'debug',
|
|
63
|
+
patterns: [
|
|
64
|
+
/debug|调试/i,
|
|
65
|
+
/bug|错误|故障/i,
|
|
66
|
+
/error|异常/i,
|
|
67
|
+
/not working|不工作|失效/i,
|
|
68
|
+
/investigate|调查/i,
|
|
69
|
+
],
|
|
70
|
+
targetSkill: 'systematic-debugging',
|
|
71
|
+
confidence: 0.85,
|
|
72
|
+
complexity: 'medium',
|
|
73
|
+
},
|
|
74
|
+
{
|
|
75
|
+
name: 'review',
|
|
76
|
+
patterns: [
|
|
77
|
+
/review|审查|检查/i,
|
|
78
|
+
/audit|审核/i,
|
|
79
|
+
/check.*quality|检查.*质量/i,
|
|
80
|
+
/code review|代码审查/i,
|
|
81
|
+
],
|
|
82
|
+
targetSkill: 'review-diff',
|
|
83
|
+
confidence: 0.8,
|
|
84
|
+
complexity: 'medium',
|
|
85
|
+
},
|
|
86
|
+
{
|
|
87
|
+
name: 'test',
|
|
88
|
+
patterns: [
|
|
89
|
+
/test|测试/i,
|
|
90
|
+
/tdd|test.*driven/i,
|
|
91
|
+
/unit test|单元测试/i,
|
|
92
|
+
/coverage|覆盖率/i,
|
|
93
|
+
],
|
|
94
|
+
targetSkill: 'tdd',
|
|
95
|
+
confidence: 0.85,
|
|
96
|
+
complexity: 'medium',
|
|
97
|
+
},
|
|
98
|
+
{
|
|
99
|
+
name: 'research',
|
|
100
|
+
patterns: [
|
|
101
|
+
/research|研究/i,
|
|
102
|
+
/explore|探索/i,
|
|
103
|
+
/find out|查找/i,
|
|
104
|
+
/learn about|了解/i,
|
|
105
|
+
/what is|什么是/i,
|
|
106
|
+
/how does|如何.*工作/i,
|
|
107
|
+
],
|
|
108
|
+
targetSkill: 'research',
|
|
109
|
+
confidence: 0.7,
|
|
110
|
+
complexity: 'low',
|
|
111
|
+
},
|
|
112
|
+
{
|
|
113
|
+
name: 'docs',
|
|
114
|
+
patterns: [
|
|
115
|
+
/document|文档/i,
|
|
116
|
+
/claude\.md|agents\.md/i,
|
|
117
|
+
/readme|说明/i,
|
|
118
|
+
/update.*doc|更新.*文档/i,
|
|
119
|
+
],
|
|
120
|
+
targetSkill: 'agents-md',
|
|
121
|
+
confidence: 0.75,
|
|
122
|
+
complexity: 'low',
|
|
123
|
+
},
|
|
124
|
+
]
|
|
125
|
+
|
|
126
|
+
export class IntentRouter implements NamespaceRouter {
|
|
127
|
+
readonly name = 'intent'
|
|
128
|
+
readonly layer = 'core' as const
|
|
129
|
+
readonly priority = 80
|
|
130
|
+
readonly patterns = INTENTS.flatMap((i) => i.patterns)
|
|
131
|
+
|
|
132
|
+
private routeCount = 0
|
|
133
|
+
private successCount = 0
|
|
134
|
+
private totalLatency = 0
|
|
135
|
+
|
|
136
|
+
async canRoute(context: RoutingContext): Promise<boolean> {
|
|
137
|
+
// 检查是否能匹配到任何意图
|
|
138
|
+
const request = context.request.text.toLowerCase()
|
|
139
|
+
return INTENTS.some((intent) => intent.patterns.some((p) => p.test(request)))
|
|
140
|
+
}
|
|
141
|
+
|
|
142
|
+
async route(context: RoutingContext): Promise<RouteDecision> {
|
|
143
|
+
const startTime = Date.now()
|
|
144
|
+
const requestText = context.request.text.toLowerCase()
|
|
145
|
+
|
|
146
|
+
// 计算每个意图的匹配分数
|
|
147
|
+
const scored = INTENTS.map((intent) => {
|
|
148
|
+
let score = 0
|
|
149
|
+
for (const pattern of intent.patterns) {
|
|
150
|
+
if (pattern.test(requestText)) {
|
|
151
|
+
score += intent.confidence / intent.patterns.length
|
|
152
|
+
}
|
|
153
|
+
}
|
|
154
|
+
return { intent, score }
|
|
155
|
+
}).filter((s) => s.score > 0)
|
|
156
|
+
|
|
157
|
+
// 按分数排序
|
|
158
|
+
scored.sort((a, b) => b.score - a.score)
|
|
159
|
+
|
|
160
|
+
const best = scored[0]
|
|
161
|
+
const alternatives: AlternativeRoute[] = scored.slice(1, 4).map((s) => ({
|
|
162
|
+
skill: s.intent.targetSkill,
|
|
163
|
+
confidence: s.score,
|
|
164
|
+
reasoning: `Intent: ${s.intent.name}`,
|
|
165
|
+
}))
|
|
166
|
+
|
|
167
|
+
this.routeCount++
|
|
168
|
+
this.totalLatency += Date.now() - startTime
|
|
169
|
+
|
|
170
|
+
if (best) {
|
|
171
|
+
this.successCount++
|
|
172
|
+
return {
|
|
173
|
+
skill: best.intent.targetSkill,
|
|
174
|
+
confidence: Math.min(best.score, 1.0),
|
|
175
|
+
reasoning: `Intent matched: ${best.intent.name} (${best.intent.complexity} complexity)`,
|
|
176
|
+
namespace: this.name,
|
|
177
|
+
alternatives,
|
|
178
|
+
metadata: {
|
|
179
|
+
layer: this.layer,
|
|
180
|
+
processingTime: Date.now() - startTime,
|
|
181
|
+
hops: 1,
|
|
182
|
+
},
|
|
183
|
+
}
|
|
184
|
+
}
|
|
185
|
+
|
|
186
|
+
// 无匹配
|
|
187
|
+
return {
|
|
188
|
+
skill: 'quick-task',
|
|
189
|
+
confidence: 0.3,
|
|
190
|
+
reasoning: 'No clear intent matched',
|
|
191
|
+
namespace: this.name,
|
|
192
|
+
alternatives: [],
|
|
193
|
+
metadata: {
|
|
194
|
+
layer: this.layer,
|
|
195
|
+
processingTime: Date.now() - startTime,
|
|
196
|
+
hops: 1,
|
|
197
|
+
},
|
|
198
|
+
}
|
|
199
|
+
}
|
|
200
|
+
|
|
201
|
+
getSupportedSkills(): string[] {
|
|
202
|
+
return INTENTS.map((i) => i.targetSkill)
|
|
203
|
+
}
|
|
204
|
+
|
|
205
|
+
getHealth(): NamespaceHealth {
|
|
206
|
+
return {
|
|
207
|
+
name: this.name,
|
|
208
|
+
status: this.successRate() > 0.7 ? 'healthy' : 'degraded',
|
|
209
|
+
totalRoutes: this.routeCount,
|
|
210
|
+
successRate: this.successRate(),
|
|
211
|
+
avgLatency: this.routeCount > 0 ? this.totalLatency / this.routeCount : 0,
|
|
212
|
+
}
|
|
213
|
+
}
|
|
214
|
+
|
|
215
|
+
private successRate(): number {
|
|
216
|
+
return this.routeCount > 0 ? this.successCount / this.routeCount : 1.0
|
|
217
|
+
}
|
|
218
|
+
}
|
|
219
|
+
|
|
220
|
+
export const intentRouter = new IntentRouter()
|
|
221
|
+
export default intentRouter
|
|
@@ -0,0 +1,156 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Lifecycle Router - Core Layer
|
|
3
|
+
*
|
|
4
|
+
* 基于项目生命周期阶段进行路由决策
|
|
5
|
+
* 生命周期: idle → planning → executing → verifying → completed
|
|
6
|
+
*/
|
|
7
|
+
|
|
8
|
+
import type {
|
|
9
|
+
NamespaceRouter,
|
|
10
|
+
RoutingContext,
|
|
11
|
+
RouteDecision,
|
|
12
|
+
NamespaceHealth,
|
|
13
|
+
AlternativeRoute,
|
|
14
|
+
} from '../types.js'
|
|
15
|
+
|
|
16
|
+
// 各阶段可用的技能
|
|
17
|
+
const SKILLS_BY_PHASE: Record<string, string[]> = {
|
|
18
|
+
idle: ['to-plan', 'research', 'quick-task', 'agents-md'],
|
|
19
|
+
planning: ['to-plan', 'research', 'review-diff', 'agents-md'],
|
|
20
|
+
executing: ['execute-plan', 'quick-task', 'tdd', 'systematic-debugging'],
|
|
21
|
+
verifying: ['review-diff', 'systematic-debugging', 'execute-plan'],
|
|
22
|
+
completed: ['review-diff', 'agents-md', 'research'],
|
|
23
|
+
failed: ['systematic-debugging', 'to-plan', 'review-diff'],
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
export class LifecycleRouter implements NamespaceRouter {
|
|
27
|
+
readonly name = 'lifecycle'
|
|
28
|
+
readonly layer = 'core' as const
|
|
29
|
+
readonly priority = 90
|
|
30
|
+
readonly patterns = [
|
|
31
|
+
/plan|规划|设计/i,
|
|
32
|
+
/execute|执行|实现/i,
|
|
33
|
+
/debug|调试|fix/i,
|
|
34
|
+
/review|审查|review/i,
|
|
35
|
+
/complete|完成|结束/i,
|
|
36
|
+
]
|
|
37
|
+
|
|
38
|
+
private routeCount = 0
|
|
39
|
+
private successCount = 0
|
|
40
|
+
private totalLatency = 0
|
|
41
|
+
|
|
42
|
+
async canRoute(context: RoutingContext): Promise<boolean> {
|
|
43
|
+
// 总是可以检查生命周期
|
|
44
|
+
return true
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
async route(context: RoutingContext): Promise<RouteDecision> {
|
|
48
|
+
const startTime = Date.now()
|
|
49
|
+
const phase = context.state.phase
|
|
50
|
+
const availableSkills = SKILLS_BY_PHASE[phase] || SKILLS_BY_PHASE.idle
|
|
51
|
+
|
|
52
|
+
// 基于请求内容匹配最佳技能
|
|
53
|
+
const requestText = context.request.text.toLowerCase()
|
|
54
|
+
let bestSkill: string | null = null
|
|
55
|
+
let bestScore = 0
|
|
56
|
+
const alternatives: AlternativeRoute[] = []
|
|
57
|
+
|
|
58
|
+
for (const skill of availableSkills) {
|
|
59
|
+
const score = this.calculateSkillScore(skill, requestText, phase)
|
|
60
|
+
if (score > bestScore) {
|
|
61
|
+
// 当前最佳变为备选
|
|
62
|
+
if (bestSkill) {
|
|
63
|
+
alternatives.push({
|
|
64
|
+
skill: bestSkill,
|
|
65
|
+
confidence: bestScore,
|
|
66
|
+
reasoning: `Matched lifecycle phase ${phase}`,
|
|
67
|
+
})
|
|
68
|
+
}
|
|
69
|
+
bestSkill = skill
|
|
70
|
+
bestScore = score
|
|
71
|
+
} else if (score > 0.3) {
|
|
72
|
+
alternatives.push({
|
|
73
|
+
skill,
|
|
74
|
+
confidence: score,
|
|
75
|
+
reasoning: `Alternative for ${phase} phase`,
|
|
76
|
+
})
|
|
77
|
+
}
|
|
78
|
+
}
|
|
79
|
+
|
|
80
|
+
this.routeCount++
|
|
81
|
+
this.totalLatency += Date.now() - startTime
|
|
82
|
+
if (bestSkill) this.successCount++
|
|
83
|
+
|
|
84
|
+
return {
|
|
85
|
+
skill: bestSkill || 'quick-task',
|
|
86
|
+
confidence: bestScore || 0.5,
|
|
87
|
+
reasoning: `Lifecycle phase: ${phase}. Available: ${availableSkills.join(', ')}`,
|
|
88
|
+
namespace: this.name,
|
|
89
|
+
alternatives: alternatives.slice(0, 3),
|
|
90
|
+
metadata: {
|
|
91
|
+
layer: this.layer,
|
|
92
|
+
processingTime: Date.now() - startTime,
|
|
93
|
+
hops: 1,
|
|
94
|
+
},
|
|
95
|
+
}
|
|
96
|
+
}
|
|
97
|
+
|
|
98
|
+
/**
|
|
99
|
+
* 计算技能匹配分数
|
|
100
|
+
*/
|
|
101
|
+
private calculateSkillScore(skill: string, request: string, phase: string): number {
|
|
102
|
+
const keywordMap: Record<string, string[]> = {
|
|
103
|
+
'to-plan': ['plan', 'design', 'architecture', '规划', '设计'],
|
|
104
|
+
'execute-plan': ['implement', 'build', 'execute', '实现', '执行'],
|
|
105
|
+
'quick-task': ['fix', 'typo', 'rename', 'small', '快速', '修复'],
|
|
106
|
+
'review-diff': ['review', 'audit', 'check', '审查', '检查'],
|
|
107
|
+
'systematic-debugging': ['debug', 'bug', 'error', '调试', '错误'],
|
|
108
|
+
'tdd': ['test', 'tdd', '测试'],
|
|
109
|
+
'research': ['research', 'explore', 'learn', '研究', '探索'],
|
|
110
|
+
'agents-md': ['agent', 'claude.md', 'agents.md', '文档'],
|
|
111
|
+
}
|
|
112
|
+
|
|
113
|
+
const keywords = keywordMap[skill] || []
|
|
114
|
+
let score = 0
|
|
115
|
+
|
|
116
|
+
for (const keyword of keywords) {
|
|
117
|
+
if (request.includes(keyword.toLowerCase())) {
|
|
118
|
+
score += 0.2
|
|
119
|
+
}
|
|
120
|
+
}
|
|
121
|
+
|
|
122
|
+
// 根据生命周期阶段调整分数
|
|
123
|
+
const phaseBoost: Record<string, Record<string, number>> = {
|
|
124
|
+
planning: { 'to-plan': 0.3, 'research': 0.2 },
|
|
125
|
+
executing: { 'execute-plan': 0.3, 'tdd': 0.2, 'quick-task': 0.1 },
|
|
126
|
+
verifying: { 'review-diff': 0.3, 'systematic-debugging': 0.2 },
|
|
127
|
+
}
|
|
128
|
+
|
|
129
|
+
if (phaseBoost[phase]?.[skill]) {
|
|
130
|
+
score += phaseBoost[phase][skill]
|
|
131
|
+
}
|
|
132
|
+
|
|
133
|
+
return Math.min(score, 1.0)
|
|
134
|
+
}
|
|
135
|
+
|
|
136
|
+
getSupportedSkills(): string[] {
|
|
137
|
+
return Object.values(SKILLS_BY_PHASE).flat()
|
|
138
|
+
}
|
|
139
|
+
|
|
140
|
+
getHealth(): NamespaceHealth {
|
|
141
|
+
return {
|
|
142
|
+
name: this.name,
|
|
143
|
+
status: this.successRate() > 0.8 ? 'healthy' : 'degraded',
|
|
144
|
+
totalRoutes: this.routeCount,
|
|
145
|
+
successRate: this.successRate(),
|
|
146
|
+
avgLatency: this.routeCount > 0 ? this.totalLatency / this.routeCount : 0,
|
|
147
|
+
}
|
|
148
|
+
}
|
|
149
|
+
|
|
150
|
+
private successRate(): number {
|
|
151
|
+
return this.routeCount > 0 ? this.successCount / this.routeCount : 1.0
|
|
152
|
+
}
|
|
153
|
+
}
|
|
154
|
+
|
|
155
|
+
export const lifecycleRouter = new LifecycleRouter()
|
|
156
|
+
export default lifecycleRouter
|
|
@@ -0,0 +1,192 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* State Router - Core Layer
|
|
3
|
+
*
|
|
4
|
+
* 基于 STATE.md 和 PLAN.md 的状态进行路由决策
|
|
5
|
+
* 优先使用状态信号而非关键词匹配
|
|
6
|
+
*/
|
|
7
|
+
|
|
8
|
+
import type {
|
|
9
|
+
NamespaceRouter,
|
|
10
|
+
RoutingContext,
|
|
11
|
+
RouteDecision,
|
|
12
|
+
NamespaceHealth,
|
|
13
|
+
AlternativeRoute,
|
|
14
|
+
} from '../types.js'
|
|
15
|
+
|
|
16
|
+
export class StateRouter implements NamespaceRouter {
|
|
17
|
+
readonly name = 'state'
|
|
18
|
+
readonly layer = 'core' as const
|
|
19
|
+
readonly priority = 95 // 高于 lifecycle
|
|
20
|
+
readonly patterns = [
|
|
21
|
+
/state|状态/i,
|
|
22
|
+
/plan|计划/i,
|
|
23
|
+
/continue|继续/i,
|
|
24
|
+
/resume|恢复/i,
|
|
25
|
+
]
|
|
26
|
+
|
|
27
|
+
private routeCount = 0
|
|
28
|
+
private successCount = 0
|
|
29
|
+
private totalLatency = 0
|
|
30
|
+
|
|
31
|
+
async canRoute(context: RoutingContext): Promise<boolean> {
|
|
32
|
+
// 如果有 plan 或 state 信息,可以路由
|
|
33
|
+
return context.plan !== null || context.state.phase !== 'idle'
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
async route(context: RoutingContext): Promise<RouteDecision> {
|
|
37
|
+
const startTime = Date.now()
|
|
38
|
+
const { state, plan, request } = context
|
|
39
|
+
|
|
40
|
+
// 基于状态的路由决策
|
|
41
|
+
const decision = this.makeStateBasedDecision(state, plan, request.text)
|
|
42
|
+
|
|
43
|
+
this.routeCount++
|
|
44
|
+
this.totalLatency += Date.now() - startTime
|
|
45
|
+
this.successCount++
|
|
46
|
+
|
|
47
|
+
return {
|
|
48
|
+
...decision,
|
|
49
|
+
namespace: this.name,
|
|
50
|
+
metadata: {
|
|
51
|
+
layer: this.layer,
|
|
52
|
+
processingTime: Date.now() - startTime,
|
|
53
|
+
hops: 1,
|
|
54
|
+
},
|
|
55
|
+
}
|
|
56
|
+
}
|
|
57
|
+
|
|
58
|
+
/**
|
|
59
|
+
* 基于状态的路由决策
|
|
60
|
+
*/
|
|
61
|
+
private makeStateBasedDecision(
|
|
62
|
+
state: RoutingContext['state'],
|
|
63
|
+
plan: RoutingContext['plan'],
|
|
64
|
+
requestText: string
|
|
65
|
+
): Omit<RouteDecision, 'namespace' | 'metadata'> {
|
|
66
|
+
const alternatives: AlternativeRoute[] = []
|
|
67
|
+
|
|
68
|
+
// 规则1: 如果有 plan 且未完成,默认路由到 execute-plan
|
|
69
|
+
if (plan && state.phase === 'executing') {
|
|
70
|
+
const completedCount = state.completedTasks?.length || 0
|
|
71
|
+
const totalCount = plan.tasks?.length || 0
|
|
72
|
+
const progress = totalCount > 0 ? completedCount / totalCount : 0
|
|
73
|
+
|
|
74
|
+
// 检查是否继续执行
|
|
75
|
+
if (progress < 1.0) {
|
|
76
|
+
return {
|
|
77
|
+
skill: 'execute-plan',
|
|
78
|
+
confidence: 0.9,
|
|
79
|
+
reasoning: `Plan exists with ${completedCount}/${totalCount} tasks complete. Phase: ${state.phase}`,
|
|
80
|
+
alternatives: [
|
|
81
|
+
{ skill: 'quick-task', confidence: 0.3, reasoning: 'Small task bypass' },
|
|
82
|
+
],
|
|
83
|
+
}
|
|
84
|
+
}
|
|
85
|
+
}
|
|
86
|
+
|
|
87
|
+
// 规则2: 如果正在 verifying,路由到 review-diff
|
|
88
|
+
if (state.phase === 'verifying') {
|
|
89
|
+
return {
|
|
90
|
+
skill: 'review-diff',
|
|
91
|
+
confidence: 0.85,
|
|
92
|
+
reasoning: `Phase is ${state.phase}, need verification`,
|
|
93
|
+
alternatives: [
|
|
94
|
+
{ skill: 'systematic-debugging', confidence: 0.4, reasoning: 'If verification fails' },
|
|
95
|
+
],
|
|
96
|
+
}
|
|
97
|
+
}
|
|
98
|
+
|
|
99
|
+
// 规则3: 如果有 plan 但还没开始执行
|
|
100
|
+
if (plan && state.phase === 'planning') {
|
|
101
|
+
return {
|
|
102
|
+
skill: 'execute-plan',
|
|
103
|
+
confidence: 0.8,
|
|
104
|
+
reasoning: `Plan ready (${plan.tasks?.length || 0} tasks), waiting to execute`,
|
|
105
|
+
alternatives: [
|
|
106
|
+
{ skill: 'to-plan', confidence: 0.3, reasoning: 'Revise plan' },
|
|
107
|
+
],
|
|
108
|
+
}
|
|
109
|
+
}
|
|
110
|
+
|
|
111
|
+
// 规则4: 如果用户说 "continue" 或 "继续"
|
|
112
|
+
if (/^\s*(continue|resume|proceed|继续|恢复)/i.test(requestText)) {
|
|
113
|
+
if (plan) {
|
|
114
|
+
return {
|
|
115
|
+
skill: 'execute-plan',
|
|
116
|
+
confidence: 0.95,
|
|
117
|
+
reasoning: 'User requested to continue with existing plan',
|
|
118
|
+
alternatives: [],
|
|
119
|
+
}
|
|
120
|
+
}
|
|
121
|
+
}
|
|
122
|
+
|
|
123
|
+
// 规则5: 默认情况 - 检查是否需要创建 plan
|
|
124
|
+
if (!plan && state.phase === 'idle') {
|
|
125
|
+
// 请求复杂度检测
|
|
126
|
+
const isComplex = this.isComplexRequest(requestText)
|
|
127
|
+
if (isComplex) {
|
|
128
|
+
return {
|
|
129
|
+
skill: 'to-plan',
|
|
130
|
+
confidence: 0.75,
|
|
131
|
+
reasoning: 'No plan exists and request appears complex',
|
|
132
|
+
alternatives: [
|
|
133
|
+
{ skill: 'quick-task', confidence: 0.4, reasoning: 'Simple approach' },
|
|
134
|
+
{ skill: 'research', confidence: 0.3, reasoning: 'Need more info' },
|
|
135
|
+
],
|
|
136
|
+
}
|
|
137
|
+
}
|
|
138
|
+
}
|
|
139
|
+
|
|
140
|
+
// 默认返回 low confidence
|
|
141
|
+
return {
|
|
142
|
+
skill: 'quick-task',
|
|
143
|
+
confidence: 0.3,
|
|
144
|
+
reasoning: `State-based routing default: ${state.phase}, no plan`,
|
|
145
|
+
alternatives: [],
|
|
146
|
+
}
|
|
147
|
+
}
|
|
148
|
+
|
|
149
|
+
/**
|
|
150
|
+
* 判断请求是否复杂(需要创建 plan)
|
|
151
|
+
*/
|
|
152
|
+
private isComplexRequest(request: string): boolean {
|
|
153
|
+
const complexityIndicators = [
|
|
154
|
+
/implement|实现/i,
|
|
155
|
+
/feature|功能/i,
|
|
156
|
+
/refactor|重构/i,
|
|
157
|
+
/architecture|架构/i,
|
|
158
|
+
/design|设计/i,
|
|
159
|
+
/multiple|多个/i,
|
|
160
|
+
/steps?|步骤/i,
|
|
161
|
+
/phase|阶段/i,
|
|
162
|
+
]
|
|
163
|
+
|
|
164
|
+
const indicatorCount = complexityIndicators.filter((pattern) =>
|
|
165
|
+
pattern.test(request)
|
|
166
|
+
).length
|
|
167
|
+
|
|
168
|
+
// 如果匹配多个复杂度指标,认为是复杂请求
|
|
169
|
+
return indicatorCount >= 2 || request.length > 100
|
|
170
|
+
}
|
|
171
|
+
|
|
172
|
+
getSupportedSkills(): string[] {
|
|
173
|
+
return ['to-plan', 'execute-plan', 'quick-task', 'review-diff', 'systematic-debugging', 'research']
|
|
174
|
+
}
|
|
175
|
+
|
|
176
|
+
getHealth(): NamespaceHealth {
|
|
177
|
+
return {
|
|
178
|
+
name: this.name,
|
|
179
|
+
status: this.successRate() > 0.8 ? 'healthy' : 'degraded',
|
|
180
|
+
totalRoutes: this.routeCount,
|
|
181
|
+
successRate: this.successRate(),
|
|
182
|
+
avgLatency: this.routeCount > 0 ? this.totalLatency / this.routeCount : 0,
|
|
183
|
+
}
|
|
184
|
+
}
|
|
185
|
+
|
|
186
|
+
private successRate(): number {
|
|
187
|
+
return this.routeCount > 0 ? this.successCount / this.routeCount : 1.0
|
|
188
|
+
}
|
|
189
|
+
}
|
|
190
|
+
|
|
191
|
+
export const stateRouter = new StateRouter()
|
|
192
|
+
export default stateRouter
|