@winspan/claude-forge 8.34.0 → 8.36.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 +10 -30
- package/dist/capability/index.d.ts +6 -5
- package/dist/capability/index.d.ts.map +1 -1
- package/dist/capability/index.js +6 -5
- package/dist/capability/index.js.map +1 -1
- package/dist/capability/types.d.ts +5 -74
- package/dist/capability/types.d.ts.map +1 -1
- package/dist/capability/types.js +4 -1
- package/dist/capability/types.js.map +1 -1
- package/dist/core/ai/provider.d.ts +23 -1
- package/dist/core/ai/provider.d.ts.map +1 -1
- package/dist/core/ai/provider.js +67 -1
- package/dist/core/ai/provider.js.map +1 -1
- package/dist/core/ai/types.d.ts +28 -0
- package/dist/core/ai/types.d.ts.map +1 -1
- package/dist/core/storage/rows.d.ts +0 -36
- package/dist/core/storage/rows.d.ts.map +1 -1
- package/dist/core/storage/schema.sql +1 -45
- package/dist/core/storage/sqlite.d.ts +2 -79
- package/dist/core/storage/sqlite.d.ts.map +1 -1
- package/dist/core/storage/sqlite.js +3 -362
- package/dist/core/storage/sqlite.js.map +1 -1
- package/dist/core/utils/token-tracker.d.ts +0 -1
- package/dist/core/utils/token-tracker.d.ts.map +1 -1
- package/dist/core/utils/token-tracker.js +0 -1
- package/dist/core/utils/token-tracker.js.map +1 -1
- package/dist/daemon/handlers/post-tool-use.d.ts +1 -9
- package/dist/daemon/handlers/post-tool-use.d.ts.map +1 -1
- package/dist/daemon/handlers/post-tool-use.js +2 -99
- package/dist/daemon/handlers/post-tool-use.js.map +1 -1
- package/dist/daemon/handlers/stop.d.ts +1 -15
- package/dist/daemon/handlers/stop.d.ts.map +1 -1
- package/dist/daemon/handlers/stop.js +1 -95
- package/dist/daemon/handlers/stop.js.map +1 -1
- package/dist/daemon/handlers/user-prompt.d.ts +1 -5
- package/dist/daemon/handlers/user-prompt.d.ts.map +1 -1
- package/dist/daemon/handlers/user-prompt.js +29 -99
- package/dist/daemon/handlers/user-prompt.js.map +1 -1
- package/dist/daemon/index.d.ts.map +1 -1
- package/dist/daemon/index.js +9 -56
- package/dist/daemon/index.js.map +1 -1
- package/dist/engine/agent-router.d.ts +37 -0
- package/dist/engine/agent-router.d.ts.map +1 -1
- package/dist/engine/agent-router.js +58 -0
- package/dist/engine/agent-router.js.map +1 -1
- package/dist/engine/conventions/routing.yaml +31 -2
- package/dist/intelligence/classifier.d.ts +63 -43
- package/dist/intelligence/classifier.d.ts.map +1 -1
- package/dist/intelligence/classifier.js +256 -191
- package/dist/intelligence/classifier.js.map +1 -1
- package/dist/intelligence/context-gatherer.d.ts +101 -0
- package/dist/intelligence/context-gatherer.d.ts.map +1 -0
- package/dist/intelligence/context-gatherer.js +417 -0
- package/dist/intelligence/context-gatherer.js.map +1 -0
- package/dist/intelligence/cot-classifier.d.ts +95 -0
- package/dist/intelligence/cot-classifier.d.ts.map +1 -0
- package/dist/intelligence/cot-classifier.js +391 -0
- package/dist/intelligence/cot-classifier.js.map +1 -0
- package/dist/intelligence/execution-doc-builder.d.ts +90 -0
- package/dist/intelligence/execution-doc-builder.d.ts.map +1 -1
- package/dist/intelligence/execution-doc-builder.js +459 -42
- package/dist/intelligence/execution-doc-builder.js.map +1 -1
- package/dist/intelligence/intent-types.d.ts +13 -0
- package/dist/intelligence/intent-types.d.ts.map +1 -0
- package/dist/intelligence/intent-types.js +19 -0
- package/dist/intelligence/intent-types.js.map +1 -0
- package/dist/intelligence/multimodal-parser.d.ts +105 -0
- package/dist/intelligence/multimodal-parser.d.ts.map +1 -0
- package/dist/intelligence/multimodal-parser.js +425 -0
- package/dist/intelligence/multimodal-parser.js.map +1 -0
- package/dist/skills/official-skills.d.ts.map +1 -1
- package/dist/skills/official-skills.js +218 -20
- package/dist/skills/official-skills.js.map +1 -1
- package/dist/web/routes/status.d.ts.map +1 -1
- package/dist/web/routes/status.js +8 -10
- package/dist/web/routes/status.js.map +1 -1
- package/dist/web/routes/token-usage.d.ts +1 -1
- package/dist/web/routes/token-usage.d.ts.map +1 -1
- package/dist/web/routes/token-usage.js +1 -16
- package/dist/web/routes/token-usage.js.map +1 -1
- package/dist/web/routes/types.d.ts +0 -6
- package/dist/web/routes/types.d.ts.map +1 -1
- package/dist/web/routes/types.js.map +1 -1
- package/dist/web/server.d.ts +0 -6
- package/dist/web/server.d.ts.map +1 -1
- package/dist/web/server.js +0 -5
- package/dist/web/server.js.map +1 -1
- package/dist/web/static/assets/{AIConfig-DiUFET_Q.js → AIConfig-D4VglzCl.js} +2 -2
- package/dist/web/static/assets/{AIConfig-DiUFET_Q.js.map → AIConfig-D4VglzCl.js.map} +1 -1
- package/dist/web/static/assets/{Agents-bNNGbQnL.js → Agents-ne5lXc7V.js} +2 -2
- package/dist/web/static/assets/{Agents-bNNGbQnL.js.map → Agents-ne5lXc7V.js.map} +1 -1
- package/dist/web/static/assets/Dashboard-D4j0Zmek.js +2 -0
- package/dist/web/static/assets/Dashboard-D4j0Zmek.js.map +1 -0
- package/dist/web/static/assets/{Drawer-DOUcx6m1.js → Drawer-Lo5ihVP-.js} +2 -2
- package/dist/web/static/assets/{Drawer-DOUcx6m1.js.map → Drawer-Lo5ihVP-.js.map} +1 -1
- package/dist/web/static/assets/{Events-DQHP6Uaq.js → Events-DBJ1B7OW.js} +2 -2
- package/dist/web/static/assets/{Events-DQHP6Uaq.js.map → Events-DBJ1B7OW.js.map} +1 -1
- package/dist/web/static/assets/{ExecutionTrace-Co8ARdg-.js → ExecutionTrace-Du9XADc1.js} +2 -2
- package/dist/web/static/assets/{ExecutionTrace-Co8ARdg-.js.map → ExecutionTrace-Du9XADc1.js.map} +1 -1
- package/dist/web/static/assets/{Routing-BW3eGD-8.js → Routing-BNQ09OlH.js} +2 -2
- package/dist/web/static/assets/{Routing-BW3eGD-8.js.map → Routing-BNQ09OlH.js.map} +1 -1
- package/dist/web/static/assets/{SessionDetail-Cbd7Jwox.js → SessionDetail-BPrPyMNa.js} +2 -2
- package/dist/web/static/assets/{SessionDetail-Cbd7Jwox.js.map → SessionDetail-BPrPyMNa.js.map} +1 -1
- package/dist/web/static/assets/{Sessions-ZQSCgXyy.js → Sessions-o3EXsXz9.js} +2 -2
- package/dist/web/static/assets/{Sessions-ZQSCgXyy.js.map → Sessions-o3EXsXz9.js.map} +1 -1
- package/dist/web/static/assets/{Skills-C5-5zOSH.js → Skills-Czt5mkyc.js} +2 -2
- package/dist/web/static/assets/{Skills-C5-5zOSH.js.map → Skills-Czt5mkyc.js.map} +1 -1
- package/dist/web/static/assets/{export-CbQTOt71.js → export-C0mlC4AT.js} +2 -2
- package/dist/web/static/assets/{export-CbQTOt71.js.map → export-C0mlC4AT.js.map} +1 -1
- package/dist/web/static/assets/index-B1J7nBu0.js +3 -0
- package/dist/web/static/assets/index-B1J7nBu0.js.map +1 -0
- package/dist/web/static/assets/index-BVqk4bSO.css +1 -0
- package/dist/web/static/assets/{lucide-BanPULT1.js → lucide-Bu44HVAM.js} +33 -73
- package/dist/web/static/assets/lucide-Bu44HVAM.js.map +1 -0
- package/dist/web/static/index.html +3 -3
- package/package.json +2 -2
- package/dist/capability/execution-manager.d.ts +0 -96
- package/dist/capability/execution-manager.d.ts.map +0 -1
- package/dist/capability/execution-manager.js +0 -260
- package/dist/capability/execution-manager.js.map +0 -1
- package/dist/capability/executor/background-executor.d.ts +0 -58
- package/dist/capability/executor/background-executor.d.ts.map +0 -1
- package/dist/capability/executor/background-executor.js +0 -322
- package/dist/capability/executor/background-executor.js.map +0 -1
- package/dist/capability/executor/foreground-executor.d.ts +0 -26
- package/dist/capability/executor/foreground-executor.d.ts.map +0 -1
- package/dist/capability/executor/foreground-executor.js +0 -82
- package/dist/capability/executor/foreground-executor.js.map +0 -1
- package/dist/capability/executor/orchestrator.d.ts +0 -38
- package/dist/capability/executor/orchestrator.d.ts.map +0 -1
- package/dist/capability/executor/orchestrator.js +0 -158
- package/dist/capability/executor/orchestrator.js.map +0 -1
- package/dist/capability/executor/stream-parser.d.ts +0 -73
- package/dist/capability/executor/stream-parser.d.ts.map +0 -1
- package/dist/capability/executor/stream-parser.js +0 -56
- package/dist/capability/executor/stream-parser.js.map +0 -1
- package/dist/capability/executor/types.d.ts +0 -44
- package/dist/capability/executor/types.d.ts.map +0 -1
- package/dist/capability/executor/types.js +0 -9
- package/dist/capability/executor/types.js.map +0 -1
- package/dist/capability/executor/worker-auth-probe.d.ts +0 -30
- package/dist/capability/executor/worker-auth-probe.d.ts.map +0 -1
- package/dist/capability/executor/worker-auth-probe.js +0 -108
- package/dist/capability/executor/worker-auth-probe.js.map +0 -1
- package/dist/capability/methodologies/bmad.yaml +0 -81
- package/dist/capability/methodologies/code-quality-audit.yaml +0 -26
- package/dist/capability/methodologies/harness-engineering.yaml +0 -75
- package/dist/capability/methodologies/test-coverage-scan.yaml +0 -26
- package/dist/capability/methodology-planner.d.ts +0 -49
- package/dist/capability/methodology-planner.d.ts.map +0 -1
- package/dist/capability/methodology-planner.js +0 -306
- package/dist/capability/methodology-planner.js.map +0 -1
- package/dist/capability/methodology-registry.d.ts +0 -32
- package/dist/capability/methodology-registry.d.ts.map +0 -1
- package/dist/capability/methodology-registry.js +0 -113
- package/dist/capability/methodology-registry.js.map +0 -1
- package/dist/daemon/handlers/methodology-formatter.d.ts +0 -16
- package/dist/daemon/handlers/methodology-formatter.d.ts.map +0 -1
- package/dist/daemon/handlers/methodology-formatter.js +0 -119
- package/dist/daemon/handlers/methodology-formatter.js.map +0 -1
- package/dist/daemon/idle-detector.d.ts +0 -35
- package/dist/daemon/idle-detector.d.ts.map +0 -1
- package/dist/daemon/idle-detector.js +0 -56
- package/dist/daemon/idle-detector.js.map +0 -1
- package/dist/daemon/idle-trigger.d.ts +0 -53
- package/dist/daemon/idle-trigger.d.ts.map +0 -1
- package/dist/daemon/idle-trigger.js +0 -153
- package/dist/daemon/idle-trigger.js.map +0 -1
- package/dist/daemon/methodology-pending-queue.d.ts +0 -33
- package/dist/daemon/methodology-pending-queue.d.ts.map +0 -1
- package/dist/daemon/methodology-pending-queue.js +0 -120
- package/dist/daemon/methodology-pending-queue.js.map +0 -1
- package/dist/web/routes/methodology.d.ts +0 -12
- package/dist/web/routes/methodology.d.ts.map +0 -1
- package/dist/web/routes/methodology.js +0 -228
- package/dist/web/routes/methodology.js.map +0 -1
- package/dist/web/static/assets/Dashboard-Ciyyw6ph.js +0 -2
- package/dist/web/static/assets/Dashboard-Ciyyw6ph.js.map +0 -1
- package/dist/web/static/assets/Methodologies-CXNrDXwG.js +0 -5
- package/dist/web/static/assets/Methodologies-CXNrDXwG.js.map +0 -1
- package/dist/web/static/assets/MethodologyDetail-rV3W1utf.js +0 -2
- package/dist/web/static/assets/MethodologyDetail-rV3W1utf.js.map +0 -1
- package/dist/web/static/assets/index-DJK5beK6.js +0 -3
- package/dist/web/static/assets/index-DJK5beK6.js.map +0 -1
- package/dist/web/static/assets/index-phpuytMI.css +0 -1
- package/dist/web/static/assets/lucide-BanPULT1.js.map +0 -1
|
@@ -1,108 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* worker-auth-probe —— 轻量探测 claude CLI 是否拥有可用认证。
|
|
3
|
-
*
|
|
4
|
-
* 设计原则:
|
|
5
|
-
* - 不启动子进程、不做网络调用,只看 env / 磁盘文件
|
|
6
|
-
* - 宁可 false-negative(判 available=true 实际失败后由 worker 报错),
|
|
7
|
-
* 也不 false-positive 阻断能跑的场景
|
|
8
|
-
* - 只检查 env `ANTHROPIC_API_KEY` 和 `~/.claude/.credentials.json`,
|
|
9
|
-
* 不探测 macOS keychain(平台相关,成本高于收益)
|
|
10
|
-
*/
|
|
11
|
-
import { existsSync, readFileSync } from 'node:fs';
|
|
12
|
-
import { homedir } from 'node:os';
|
|
13
|
-
import path from 'node:path';
|
|
14
|
-
/**
|
|
15
|
-
* 后台 worker 认证缺失错误,带 `code` 便于上层(Web API)分流返回 503。
|
|
16
|
-
*/
|
|
17
|
-
export class WorkerAuthError extends Error {
|
|
18
|
-
code = 'AUTH_REQUIRED';
|
|
19
|
-
probe;
|
|
20
|
-
constructor(probe) {
|
|
21
|
-
super(`Background mode requires Claude authentication: ${probe.message}. ` +
|
|
22
|
-
'Set ANTHROPIC_API_KEY (or ANTHROPIC_AUTH_TOKEN for third-party proxies), or run `claude login` first.');
|
|
23
|
-
this.name = 'WorkerAuthError';
|
|
24
|
-
this.probe = probe;
|
|
25
|
-
}
|
|
26
|
-
}
|
|
27
|
-
/**
|
|
28
|
-
* 默认 OAuth 凭据文件路径:`~/.claude/.credentials.json`
|
|
29
|
-
* 官方 claude-code 在首次登录后写到这里。
|
|
30
|
-
*/
|
|
31
|
-
function defaultCredentialsPath() {
|
|
32
|
-
return path.join(homedir(), '.claude', '.credentials.json');
|
|
33
|
-
}
|
|
34
|
-
function isNonEmptyString(v) {
|
|
35
|
-
return typeof v === 'string' && v.trim().length > 0;
|
|
36
|
-
}
|
|
37
|
-
/**
|
|
38
|
-
* 粗判 credentials.json 是否"像"一份合法的 OAuth 凭据。
|
|
39
|
-
* 只要能 parse 出对象且含任何 token 形字段就算通过——实际有效性交给 worker 验证。
|
|
40
|
-
*/
|
|
41
|
-
function looksLikeOAuthCredentials(raw) {
|
|
42
|
-
try {
|
|
43
|
-
const parsed = JSON.parse(raw);
|
|
44
|
-
if (!parsed || typeof parsed !== 'object')
|
|
45
|
-
return false;
|
|
46
|
-
const obj = parsed;
|
|
47
|
-
// 常见字段:claudeAiOauth.accessToken / accessToken / oauth / tokens 等
|
|
48
|
-
// 宽松识别即可:有对象内容就认为配过
|
|
49
|
-
if (isNonEmptyString(obj.accessToken))
|
|
50
|
-
return true;
|
|
51
|
-
if (obj.claudeAiOauth && typeof obj.claudeAiOauth === 'object')
|
|
52
|
-
return true;
|
|
53
|
-
if (obj.oauth && typeof obj.oauth === 'object')
|
|
54
|
-
return true;
|
|
55
|
-
if (obj.tokens && typeof obj.tokens === 'object')
|
|
56
|
-
return true;
|
|
57
|
-
// 兜底:只要 JSON 不是空对象就当有配置
|
|
58
|
-
return Object.keys(obj).length > 0;
|
|
59
|
-
}
|
|
60
|
-
catch {
|
|
61
|
-
return false;
|
|
62
|
-
}
|
|
63
|
-
}
|
|
64
|
-
export function probeWorkerAuth(options = {}) {
|
|
65
|
-
// 1) env 优先
|
|
66
|
-
const envKey = process.env.ANTHROPIC_API_KEY;
|
|
67
|
-
if (isNonEmptyString(envKey)) {
|
|
68
|
-
return {
|
|
69
|
-
available: true,
|
|
70
|
-
method: 'api-key-env',
|
|
71
|
-
message: 'ANTHROPIC_API_KEY env is set',
|
|
72
|
-
};
|
|
73
|
-
}
|
|
74
|
-
// 1b) 第三方代理(如 iFlytek / OneHub)使用 ANTHROPIC_AUTH_TOKEN
|
|
75
|
-
const envToken = process.env.ANTHROPIC_AUTH_TOKEN;
|
|
76
|
-
if (isNonEmptyString(envToken)) {
|
|
77
|
-
return {
|
|
78
|
-
available: true,
|
|
79
|
-
method: 'api-key-env',
|
|
80
|
-
message: 'ANTHROPIC_AUTH_TOKEN env is set',
|
|
81
|
-
};
|
|
82
|
-
}
|
|
83
|
-
// 2) OAuth credentials 文件
|
|
84
|
-
const credPath = options.credentialsPath ?? defaultCredentialsPath();
|
|
85
|
-
if (existsSync(credPath)) {
|
|
86
|
-
try {
|
|
87
|
-
const raw = readFileSync(credPath, 'utf-8');
|
|
88
|
-
if (looksLikeOAuthCredentials(raw)) {
|
|
89
|
-
return {
|
|
90
|
-
available: true,
|
|
91
|
-
method: 'oauth-token',
|
|
92
|
-
message: `OAuth credentials found at ${credPath}`,
|
|
93
|
-
};
|
|
94
|
-
}
|
|
95
|
-
}
|
|
96
|
-
catch {
|
|
97
|
-
// ignore — 读失败当作不可用
|
|
98
|
-
}
|
|
99
|
-
}
|
|
100
|
-
// 3) 都没有
|
|
101
|
-
return {
|
|
102
|
-
available: false,
|
|
103
|
-
method: 'none',
|
|
104
|
-
message: 'no ANTHROPIC_API_KEY / ANTHROPIC_AUTH_TOKEN env and no OAuth credentials on disk ' +
|
|
105
|
-
`(expected ${credPath})`,
|
|
106
|
-
};
|
|
107
|
-
}
|
|
108
|
-
//# sourceMappingURL=worker-auth-probe.js.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"worker-auth-probe.js","sourceRoot":"","sources":["../../../src/capability/executor/worker-auth-probe.ts"],"names":[],"mappings":"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"}
|
|
@@ -1,81 +0,0 @@
|
|
|
1
|
-
id: bmad
|
|
2
|
-
name: "BMad (敏捷开发方法论)"
|
|
3
|
-
description: "Four-role agile development methodology"
|
|
4
|
-
|
|
5
|
-
trigger:
|
|
6
|
-
taskType:
|
|
7
|
-
- write_code
|
|
8
|
-
- add_feature
|
|
9
|
-
- implement
|
|
10
|
-
complexity:
|
|
11
|
-
- moderate
|
|
12
|
-
- complex
|
|
13
|
-
# keywords 命中才触发,避免 taskType + complexity 导致的误触发
|
|
14
|
-
# BMad 是四角色敏捷方法论,面向 story/sprint 级别的完整功能开发
|
|
15
|
-
keywords:
|
|
16
|
-
- 敏捷
|
|
17
|
-
- agile
|
|
18
|
-
- story
|
|
19
|
-
- 用户故事
|
|
20
|
-
- user story
|
|
21
|
-
- sprint
|
|
22
|
-
- 迭代
|
|
23
|
-
- 需求分析
|
|
24
|
-
- 产品需求
|
|
25
|
-
- 完整功能
|
|
26
|
-
- 端到端
|
|
27
|
-
- end-to-end
|
|
28
|
-
- 四角色
|
|
29
|
-
- bmad
|
|
30
|
-
|
|
31
|
-
# 阶段模板库
|
|
32
|
-
phase_templates:
|
|
33
|
-
analyze:
|
|
34
|
-
agent: researcher
|
|
35
|
-
prompt_template: "As Product Manager: Analyze requirements for {target}. Output: user stories, acceptance criteria, constraints. Document to docs/{target}-requirements.md"
|
|
36
|
-
description: "Product Manager analyzes requirements"
|
|
37
|
-
artifacts:
|
|
38
|
-
- type: file
|
|
39
|
-
pattern: "docs/**/*requirements*.md"
|
|
40
|
-
required: true
|
|
41
|
-
|
|
42
|
-
design:
|
|
43
|
-
agent: planner
|
|
44
|
-
prompt_template: "As Architect: Design technical solution for {target}. Based on requirements document. Output: architecture design, module structure, interfaces, data flow. Document to docs/{target}-design.md"
|
|
45
|
-
description: "Architect designs technical solution"
|
|
46
|
-
artifacts:
|
|
47
|
-
- type: file
|
|
48
|
-
pattern: "docs/**/*design*.md"
|
|
49
|
-
required: true
|
|
50
|
-
|
|
51
|
-
implement:
|
|
52
|
-
agent: coder
|
|
53
|
-
prompt_template: "As Developer: Implement {target} based on design document. Follow coding standards. Write clean, maintainable code."
|
|
54
|
-
description: "Developer implements the solution"
|
|
55
|
-
artifacts:
|
|
56
|
-
- type: file
|
|
57
|
-
pattern: "src/**/*.ts"
|
|
58
|
-
required: true
|
|
59
|
-
|
|
60
|
-
review:
|
|
61
|
-
agent: reviewer
|
|
62
|
-
prompt_template: "As Tech Lead: Review implementation of {target}. Check: code quality, security, performance, maintainability. Output review report to docs/{target}-review.md"
|
|
63
|
-
description: "Tech Lead reviews implementation"
|
|
64
|
-
artifacts:
|
|
65
|
-
- type: file
|
|
66
|
-
pattern: "docs/**/*review*.md"
|
|
67
|
-
required: true
|
|
68
|
-
|
|
69
|
-
# AI 决策规则
|
|
70
|
-
decision_rules:
|
|
71
|
-
- condition: "complexity == 'simple' && taskType == 'write_code'"
|
|
72
|
-
phases: ["implement"]
|
|
73
|
-
description: "Simple feature: just implement"
|
|
74
|
-
|
|
75
|
-
- condition: "complexity == 'moderate' && taskType == 'add_feature'"
|
|
76
|
-
phases: ["design", "implement", "review"]
|
|
77
|
-
description: "Moderate feature: design + implement + review"
|
|
78
|
-
|
|
79
|
-
- condition: "complexity == 'complex' && taskType == 'add_feature'"
|
|
80
|
-
phases: ["analyze", "design", "implement", "review"]
|
|
81
|
-
description: "Complex feature: full BMad workflow"
|
|
@@ -1,26 +0,0 @@
|
|
|
1
|
-
id: code-quality-audit
|
|
2
|
-
name: "代码质量审计"
|
|
3
|
-
description: "Automated code quality audit during idle time"
|
|
4
|
-
|
|
5
|
-
# Idle 触发配置
|
|
6
|
-
idle_trigger:
|
|
7
|
-
enabled: true
|
|
8
|
-
interval: 7200000 # 2 小时(毫秒)
|
|
9
|
-
priority: low
|
|
10
|
-
|
|
11
|
-
# 不设置 trigger,因为这是 idle 专用方法论
|
|
12
|
-
trigger:
|
|
13
|
-
taskType: []
|
|
14
|
-
complexity: []
|
|
15
|
-
keywords: []
|
|
16
|
-
|
|
17
|
-
# 单阶段审计任务
|
|
18
|
-
phase_templates:
|
|
19
|
-
audit:
|
|
20
|
-
agent: reviewer
|
|
21
|
-
prompt_template: "Audit code quality: check for code smells, security issues, performance bottlenecks. Output report to docs/code-quality-audit.md"
|
|
22
|
-
description: "Audit code quality"
|
|
23
|
-
artifacts:
|
|
24
|
-
- type: file
|
|
25
|
-
pattern: "docs/**/*audit*.md"
|
|
26
|
-
required: false
|
|
@@ -1,75 +0,0 @@
|
|
|
1
|
-
id: harness-engineering
|
|
2
|
-
name: "Harness Engineering"
|
|
3
|
-
description: "Safe refactoring methodology with test safety net"
|
|
4
|
-
|
|
5
|
-
trigger:
|
|
6
|
-
taskType:
|
|
7
|
-
- refactor
|
|
8
|
-
- migrate
|
|
9
|
-
- cleanup_code
|
|
10
|
-
complexity:
|
|
11
|
-
- moderate
|
|
12
|
-
- complex
|
|
13
|
-
# keywords 命中才触发,避免 taskType + complexity 导致的误触发
|
|
14
|
-
keywords:
|
|
15
|
-
- 重构
|
|
16
|
-
- refactor
|
|
17
|
-
- 迁移
|
|
18
|
-
- migrate
|
|
19
|
-
- 遗留代码
|
|
20
|
-
- legacy
|
|
21
|
-
- 技术债
|
|
22
|
-
- technical debt
|
|
23
|
-
- 改写
|
|
24
|
-
- rewrite
|
|
25
|
-
|
|
26
|
-
# 阶段模板库(供 AI Planner 选择)
|
|
27
|
-
phase_templates:
|
|
28
|
-
understand:
|
|
29
|
-
agent: researcher
|
|
30
|
-
prompt_template: "Read {target} and document current behavior. Focus on: inputs, outputs, side effects, dependencies. Output a behavior document to docs/{target}-behavior.md"
|
|
31
|
-
description: "Understand current implementation before making changes"
|
|
32
|
-
artifacts:
|
|
33
|
-
- type: file
|
|
34
|
-
pattern: "docs/**/*behavior*.md"
|
|
35
|
-
required: true
|
|
36
|
-
|
|
37
|
-
characterize:
|
|
38
|
-
agent: tester
|
|
39
|
-
prompt_template: "Based on the behavior document, create characterization tests for {target}. Tests should cover: normal paths, edge cases, error handling. Target coverage > 80%."
|
|
40
|
-
description: "Build test safety net before refactoring"
|
|
41
|
-
artifacts:
|
|
42
|
-
- type: file
|
|
43
|
-
pattern: "tests/**/*.test.ts"
|
|
44
|
-
required: true
|
|
45
|
-
- type: test_coverage
|
|
46
|
-
min: 80
|
|
47
|
-
|
|
48
|
-
refactor:
|
|
49
|
-
agent: refactor-specialist
|
|
50
|
-
prompt_template: "Refactor {target} while keeping tests passing. Focus on: {refactor_goal}. Run tests after each change."
|
|
51
|
-
description: "Make changes with test safety net"
|
|
52
|
-
artifacts:
|
|
53
|
-
- type: git_diff
|
|
54
|
-
|
|
55
|
-
verify:
|
|
56
|
-
agent: tester
|
|
57
|
-
prompt_template: "Run all tests and verify behavior consistency. Compare with original behavior document."
|
|
58
|
-
description: "Verify behavior remains consistent"
|
|
59
|
-
artifacts:
|
|
60
|
-
- type: test_pass
|
|
61
|
-
required: true
|
|
62
|
-
|
|
63
|
-
# AI 决策规则(作为参考,不是硬编码)
|
|
64
|
-
decision_rules:
|
|
65
|
-
- condition: "complexity == 'simple' && taskType == 'refactor'"
|
|
66
|
-
phases: ["characterize", "refactor", "verify"]
|
|
67
|
-
description: "Simple refactor: skip understand phase if code is straightforward"
|
|
68
|
-
|
|
69
|
-
- condition: "complexity == 'moderate' && taskType == 'refactor'"
|
|
70
|
-
phases: ["understand", "characterize", "refactor", "verify"]
|
|
71
|
-
description: "Moderate refactor: full Harness Engineering workflow"
|
|
72
|
-
|
|
73
|
-
- condition: "complexity == 'complex' && taskType == 'migrate'"
|
|
74
|
-
phases: ["understand", "characterize", "refactor", "verify"]
|
|
75
|
-
description: "Complex migration: full workflow with extra caution"
|
|
@@ -1,26 +0,0 @@
|
|
|
1
|
-
id: test-coverage-scan
|
|
2
|
-
name: "测试覆盖率扫描"
|
|
3
|
-
description: "Automated test coverage analysis during idle time"
|
|
4
|
-
|
|
5
|
-
# Idle 触发配置
|
|
6
|
-
idle_trigger:
|
|
7
|
-
enabled: true
|
|
8
|
-
interval: 3600000 # 1 小时(毫秒)
|
|
9
|
-
priority: low
|
|
10
|
-
|
|
11
|
-
# 不设置 trigger,因为这是 idle 专用方法论
|
|
12
|
-
trigger:
|
|
13
|
-
taskType: []
|
|
14
|
-
complexity: []
|
|
15
|
-
keywords: []
|
|
16
|
-
|
|
17
|
-
# 单阶段扫描任务
|
|
18
|
-
phase_templates:
|
|
19
|
-
scan:
|
|
20
|
-
agent: researcher
|
|
21
|
-
prompt_template: "Analyze test coverage for the project. Identify untested modules and critical paths. Output report to docs/test-coverage-report.md"
|
|
22
|
-
description: "Scan test coverage"
|
|
23
|
-
artifacts:
|
|
24
|
-
- type: test_coverage
|
|
25
|
-
min: 0
|
|
26
|
-
required: false
|
|
@@ -1,49 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Methodology Planner
|
|
3
|
-
*
|
|
4
|
-
* 使用 AI 动态生成执行计划
|
|
5
|
-
*/
|
|
6
|
-
import type { AIProvider } from '../core/ai/types.js';
|
|
7
|
-
import type { IntentAnalysis } from '../intelligence/classifier.js';
|
|
8
|
-
import type { Methodology, ExecutionPlan, PlannedPhase } from './types.js';
|
|
9
|
-
export declare class MethodologyPlanner {
|
|
10
|
-
private ai;
|
|
11
|
-
constructor(ai: AIProvider | null);
|
|
12
|
-
/**
|
|
13
|
-
* 根据任务和方法论,动态生成执行计划
|
|
14
|
-
*/
|
|
15
|
-
plan(userPrompt: string, intent: IntentAnalysis, methodology: Methodology): Promise<ExecutionPlan>;
|
|
16
|
-
/**
|
|
17
|
-
* 重新规划剩余 phase(失败反馈环)
|
|
18
|
-
*
|
|
19
|
-
* @returns 新的执行计划,如果 AI 认为无法恢复则返回 null
|
|
20
|
-
*/
|
|
21
|
-
replan(params: {
|
|
22
|
-
executionId: number;
|
|
23
|
-
failedPhaseIndex: number;
|
|
24
|
-
failureReason: string;
|
|
25
|
-
originalPlan: ExecutionPlan;
|
|
26
|
-
completedPhases: PlannedPhase[];
|
|
27
|
-
}): Promise<ExecutionPlan | null>;
|
|
28
|
-
/**
|
|
29
|
-
* 构建重规划的 prompt
|
|
30
|
-
*/
|
|
31
|
-
private buildReplanPrompt;
|
|
32
|
-
/**
|
|
33
|
-
* 构建 AI Planner 的 prompt
|
|
34
|
-
*/
|
|
35
|
-
private buildPlannerPrompt;
|
|
36
|
-
/**
|
|
37
|
-
* 解析 AI 响应
|
|
38
|
-
*/
|
|
39
|
-
private parsePlanResponse;
|
|
40
|
-
/**
|
|
41
|
-
* 降级方案:使用预定义规则
|
|
42
|
-
*/
|
|
43
|
-
private fallbackPlan;
|
|
44
|
-
/**
|
|
45
|
-
* 简单的规则匹配
|
|
46
|
-
*/
|
|
47
|
-
private matchRule;
|
|
48
|
-
}
|
|
49
|
-
//# sourceMappingURL=methodology-planner.d.ts.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"methodology-planner.d.ts","sourceRoot":"","sources":["../../src/capability/methodology-planner.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAEH,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,qBAAqB,CAAC;AACtD,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,+BAA+B,CAAC;AACpE,OAAO,KAAK,EAAE,WAAW,EAAE,aAAa,EAAE,YAAY,EAAE,MAAM,YAAY,CAAC;AAG3E,qBAAa,kBAAkB;IACjB,OAAO,CAAC,EAAE;gBAAF,EAAE,EAAE,UAAU,GAAG,IAAI;IAEzC;;OAEG;IACG,IAAI,CACR,UAAU,EAAE,MAAM,EAClB,MAAM,EAAE,cAAc,EACtB,WAAW,EAAE,WAAW,GACvB,OAAO,CAAC,aAAa,CAAC;IAqBzB;;;;OAIG;IACG,MAAM,CAAC,MAAM,EAAE;QACnB,WAAW,EAAE,MAAM,CAAC;QACpB,gBAAgB,EAAE,MAAM,CAAC;QACzB,aAAa,EAAE,MAAM,CAAC;QACtB,YAAY,EAAE,aAAa,CAAC;QAC5B,eAAe,EAAE,YAAY,EAAE,CAAC;KACjC,GAAG,OAAO,CAAC,aAAa,GAAG,IAAI,CAAC;IAsEjC;;OAEG;IACH,OAAO,CAAC,iBAAiB;IAiEzB;;OAEG;IACH,OAAO,CAAC,kBAAkB;IAwD1B;;OAEG;IACH,OAAO,CAAC,iBAAiB;IAuCzB;;OAEG;IACH,OAAO,CAAC,YAAY;IA+CpB;;OAEG;IACH,OAAO,CAAC,SAAS;CAgBlB"}
|
|
@@ -1,306 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Methodology Planner
|
|
3
|
-
*
|
|
4
|
-
* 使用 AI 动态生成执行计划
|
|
5
|
-
*/
|
|
6
|
-
import { logger } from '../core/utils/logger.js';
|
|
7
|
-
export class MethodologyPlanner {
|
|
8
|
-
ai;
|
|
9
|
-
constructor(ai) {
|
|
10
|
-
this.ai = ai;
|
|
11
|
-
}
|
|
12
|
-
/**
|
|
13
|
-
* 根据任务和方法论,动态生成执行计划
|
|
14
|
-
*/
|
|
15
|
-
async plan(userPrompt, intent, methodology) {
|
|
16
|
-
if (!this.ai) {
|
|
17
|
-
// 降级:使用默认规则
|
|
18
|
-
return this.fallbackPlan(userPrompt, intent, methodology);
|
|
19
|
-
}
|
|
20
|
-
try {
|
|
21
|
-
const prompt = this.buildPlannerPrompt(userPrompt, intent, methodology);
|
|
22
|
-
const response = await this.ai.complete(prompt, {
|
|
23
|
-
maxTokens: 2000,
|
|
24
|
-
});
|
|
25
|
-
const plan = this.parsePlanResponse(response, methodology);
|
|
26
|
-
logger.info(`[MethodologyPlanner] Generated plan: ${plan.phases.length} phases`);
|
|
27
|
-
return plan;
|
|
28
|
-
}
|
|
29
|
-
catch (err) {
|
|
30
|
-
logger.warn(`[MethodologyPlanner] AI planning failed: ${err}, using fallback`);
|
|
31
|
-
return this.fallbackPlan(userPrompt, intent, methodology);
|
|
32
|
-
}
|
|
33
|
-
}
|
|
34
|
-
/**
|
|
35
|
-
* 重新规划剩余 phase(失败反馈环)
|
|
36
|
-
*
|
|
37
|
-
* @returns 新的执行计划,如果 AI 认为无法恢复则返回 null
|
|
38
|
-
*/
|
|
39
|
-
async replan(params) {
|
|
40
|
-
if (!this.ai) {
|
|
41
|
-
logger.warn('[MethodologyPlanner] replan: no AI provider, cannot replan');
|
|
42
|
-
return null;
|
|
43
|
-
}
|
|
44
|
-
try {
|
|
45
|
-
const prompt = this.buildReplanPrompt(params);
|
|
46
|
-
const response = await this.ai.complete(prompt, {
|
|
47
|
-
maxTokens: 2000,
|
|
48
|
-
});
|
|
49
|
-
// 解析响应
|
|
50
|
-
let cleaned = response.trim();
|
|
51
|
-
if (cleaned.startsWith('```json')) {
|
|
52
|
-
cleaned = cleaned.slice(7);
|
|
53
|
-
}
|
|
54
|
-
if (cleaned.startsWith('```')) {
|
|
55
|
-
cleaned = cleaned.slice(3);
|
|
56
|
-
}
|
|
57
|
-
if (cleaned.endsWith('```')) {
|
|
58
|
-
cleaned = cleaned.slice(0, -3);
|
|
59
|
-
}
|
|
60
|
-
cleaned = cleaned.trim();
|
|
61
|
-
const parsed = JSON.parse(cleaned);
|
|
62
|
-
// 检查 AI 是否认为可以恢复
|
|
63
|
-
if (parsed.can_recover === false || !parsed.phases || parsed.phases.length === 0) {
|
|
64
|
-
logger.info(`[MethodologyPlanner] replan: AI determined recovery not possible: ${parsed.reason || 'no reason given'}`);
|
|
65
|
-
return null;
|
|
66
|
-
}
|
|
67
|
-
// 查找方法论定义(从 originalPlan 获取)
|
|
68
|
-
const methodologyId = params.originalPlan.methodology_id;
|
|
69
|
-
// 构建新的完整计划:已完成的 phase + 重规划的 phase
|
|
70
|
-
const newPhases = [
|
|
71
|
-
...params.completedPhases,
|
|
72
|
-
...parsed.phases.map((phase) => {
|
|
73
|
-
// 从原始计划中查找 phase template 信息
|
|
74
|
-
const originalPhase = params.originalPlan.phases.find(p => p.id === phase.id);
|
|
75
|
-
if (!originalPhase) {
|
|
76
|
-
throw new Error(`Unknown phase in replan: ${phase.id}`);
|
|
77
|
-
}
|
|
78
|
-
return {
|
|
79
|
-
id: phase.id,
|
|
80
|
-
agent: originalPhase.agent, // agent 绑定不变
|
|
81
|
-
prompt: phase.prompt,
|
|
82
|
-
rationale: phase.rationale,
|
|
83
|
-
artifacts: originalPhase.artifacts,
|
|
84
|
-
};
|
|
85
|
-
}),
|
|
86
|
-
];
|
|
87
|
-
const newPlan = {
|
|
88
|
-
phases: newPhases,
|
|
89
|
-
rationale: parsed.rationale || 'Replanned after phase failure',
|
|
90
|
-
methodology_id: methodologyId,
|
|
91
|
-
};
|
|
92
|
-
logger.info(`[MethodologyPlanner] replan: generated new plan with ${newPhases.length} total phases (${params.completedPhases.length} completed + ${parsed.phases.length} new)`);
|
|
93
|
-
return newPlan;
|
|
94
|
-
}
|
|
95
|
-
catch (err) {
|
|
96
|
-
logger.warn(`[MethodologyPlanner] replan failed: ${err}`);
|
|
97
|
-
return null;
|
|
98
|
-
}
|
|
99
|
-
}
|
|
100
|
-
/**
|
|
101
|
-
* 构建重规划的 prompt
|
|
102
|
-
*/
|
|
103
|
-
buildReplanPrompt(params) {
|
|
104
|
-
const failedPhase = params.originalPlan.phases[params.failedPhaseIndex];
|
|
105
|
-
const completedPhasesDesc = params.completedPhases.length > 0
|
|
106
|
-
? params.completedPhases.map((p, i) => ` ${i + 1}. ${p.id} (${p.agent}): ${p.prompt}`).join('\n')
|
|
107
|
-
: ' (none)';
|
|
108
|
-
const originalPlanDesc = params.originalPlan.phases
|
|
109
|
-
.map((p, i) => ` ${i + 1}. ${p.id} (${p.agent}): ${p.prompt}`)
|
|
110
|
-
.join('\n');
|
|
111
|
-
return `You are a methodology replanner. A phase in an execution plan has failed, and you need to decide if recovery is possible and generate a revised plan.
|
|
112
|
-
|
|
113
|
-
**Failed Phase:**
|
|
114
|
-
- Index: ${params.failedPhaseIndex}
|
|
115
|
-
- Phase ID: ${failedPhase.id}
|
|
116
|
-
- Agent: ${failedPhase.agent}
|
|
117
|
-
- Prompt: ${failedPhase.prompt}
|
|
118
|
-
- Failure Reason: ${params.failureReason}
|
|
119
|
-
|
|
120
|
-
**Original Complete Plan:**
|
|
121
|
-
${originalPlanDesc}
|
|
122
|
-
|
|
123
|
-
**Completed Phases (successful):**
|
|
124
|
-
${completedPhasesDesc}
|
|
125
|
-
|
|
126
|
-
**Your Task:**
|
|
127
|
-
1. Analyze the failure reason and determine if the remaining work can be completed with a revised plan
|
|
128
|
-
2. If recovery is possible, generate a NEW plan for the REMAINING phases (do NOT include already completed phases)
|
|
129
|
-
3. If recovery is NOT possible (e.g., fundamental requirement issue, blocker that cannot be worked around), indicate that
|
|
130
|
-
|
|
131
|
-
**Guidelines:**
|
|
132
|
-
- You can skip the failed phase if it's not critical
|
|
133
|
-
- You can replace the failed phase with alternative phases
|
|
134
|
-
- You can add new phases to work around the failure
|
|
135
|
-
- You can reorder remaining phases
|
|
136
|
-
- NEVER invent agent names — use only agents from the original plan
|
|
137
|
-
- Each phase must have a clear rationale explaining how it addresses the failure
|
|
138
|
-
|
|
139
|
-
**Output JSON (no markdown, just JSON):**
|
|
140
|
-
{
|
|
141
|
-
"can_recover": true | false,
|
|
142
|
-
"reason": "Brief explanation of why recovery is/isn't possible",
|
|
143
|
-
"phases": [
|
|
144
|
-
{
|
|
145
|
-
"id": "phase_id_from_original_plan",
|
|
146
|
-
"prompt": "Specific instruction for this phase",
|
|
147
|
-
"rationale": "How this phase helps recover from the failure"
|
|
148
|
-
}
|
|
149
|
-
],
|
|
150
|
-
"rationale": "Overall replan rationale"
|
|
151
|
-
}
|
|
152
|
-
|
|
153
|
-
**IMPORTANT:**
|
|
154
|
-
- Output ONLY valid JSON, no markdown code blocks
|
|
155
|
-
- If can_recover is false, phases array should be empty
|
|
156
|
-
- Do NOT include an "agent" field — it is determined by phase id from original plan
|
|
157
|
-
- Only use phase ids that exist in the original plan`;
|
|
158
|
-
}
|
|
159
|
-
/**
|
|
160
|
-
* 构建 AI Planner 的 prompt
|
|
161
|
-
*/
|
|
162
|
-
buildPlannerPrompt(userPrompt, intent, methodology) {
|
|
163
|
-
const phaseDescriptions = Object.entries(methodology.phase_templates)
|
|
164
|
-
.map(([id, template]) => `- ${id} (agent: ${template.agent}): ${template.description || template.prompt_template}`)
|
|
165
|
-
.join('\n');
|
|
166
|
-
const decisionRules = methodology.decision_rules
|
|
167
|
-
?.map(rule => `- ${rule.condition} → [${rule.phases.join(', ')}]: ${rule.description}`)
|
|
168
|
-
.join('\n') || 'No predefined rules';
|
|
169
|
-
return `You are a methodology planner for "${methodology.name}".
|
|
170
|
-
|
|
171
|
-
Task: ${userPrompt}
|
|
172
|
-
|
|
173
|
-
Intent Analysis:
|
|
174
|
-
- Task Type: ${intent.taskType}
|
|
175
|
-
- Complexity: ${intent.complexity}
|
|
176
|
-
- Requirement: ${intent.requirement}
|
|
177
|
-
|
|
178
|
-
Available Phases (phase id → agent binding is FIXED, do NOT change the agent):
|
|
179
|
-
${phaseDescriptions}
|
|
180
|
-
|
|
181
|
-
Decision Rules (as reference):
|
|
182
|
-
${decisionRules}
|
|
183
|
-
|
|
184
|
-
Your job: Generate an execution plan by selecting appropriate phases.
|
|
185
|
-
|
|
186
|
-
Guidelines:
|
|
187
|
-
1. Simple tasks (complexity: simple): Use minimal phases (1-2)
|
|
188
|
-
2. Moderate tasks (complexity: moderate): Use core phases (2-3)
|
|
189
|
-
3. Complex tasks (complexity: complex): Use full workflow (3-4+)
|
|
190
|
-
4. Consider task type: bug fix needs less phases than architecture change
|
|
191
|
-
5. Each phase must have a clear rationale
|
|
192
|
-
6. NEVER invent agent names — agent is bound by phase id above
|
|
193
|
-
|
|
194
|
-
Output JSON (no markdown, just JSON):
|
|
195
|
-
{
|
|
196
|
-
"phases": [
|
|
197
|
-
{
|
|
198
|
-
"id": "phase_id_from_available_phases",
|
|
199
|
-
"prompt": "Specific instruction for this phase",
|
|
200
|
-
"rationale": "Why this phase is needed"
|
|
201
|
-
}
|
|
202
|
-
],
|
|
203
|
-
"rationale": "Overall plan rationale"
|
|
204
|
-
}
|
|
205
|
-
|
|
206
|
-
IMPORTANT:
|
|
207
|
-
- Output ONLY valid JSON, no markdown code blocks.
|
|
208
|
-
- Do NOT include an "agent" field — it is determined by phase id.
|
|
209
|
-
- Only use phase ids listed in Available Phases.`;
|
|
210
|
-
}
|
|
211
|
-
/**
|
|
212
|
-
* 解析 AI 响应
|
|
213
|
-
*/
|
|
214
|
-
parsePlanResponse(response, methodology) {
|
|
215
|
-
// 移除可能的 markdown 代码块标记
|
|
216
|
-
let cleaned = response.trim();
|
|
217
|
-
if (cleaned.startsWith('```json')) {
|
|
218
|
-
cleaned = cleaned.slice(7);
|
|
219
|
-
}
|
|
220
|
-
if (cleaned.startsWith('```')) {
|
|
221
|
-
cleaned = cleaned.slice(3);
|
|
222
|
-
}
|
|
223
|
-
if (cleaned.endsWith('```')) {
|
|
224
|
-
cleaned = cleaned.slice(0, -3);
|
|
225
|
-
}
|
|
226
|
-
cleaned = cleaned.trim();
|
|
227
|
-
const parsed = JSON.parse(cleaned);
|
|
228
|
-
// 验证和补充 phases(agent 字段以 YAML template 为权威,忽略 AI 可能返回的 agent)
|
|
229
|
-
const phases = parsed.phases.map((phase) => {
|
|
230
|
-
const template = methodology.phase_templates[phase.id];
|
|
231
|
-
if (!template) {
|
|
232
|
-
throw new Error(`Unknown phase: ${phase.id}`);
|
|
233
|
-
}
|
|
234
|
-
return {
|
|
235
|
-
id: phase.id,
|
|
236
|
-
agent: template.agent,
|
|
237
|
-
prompt: phase.prompt,
|
|
238
|
-
rationale: phase.rationale,
|
|
239
|
-
artifacts: template.artifacts,
|
|
240
|
-
};
|
|
241
|
-
});
|
|
242
|
-
return {
|
|
243
|
-
phases,
|
|
244
|
-
rationale: parsed.rationale,
|
|
245
|
-
methodology_id: methodology.id,
|
|
246
|
-
};
|
|
247
|
-
}
|
|
248
|
-
/**
|
|
249
|
-
* 降级方案:使用预定义规则
|
|
250
|
-
*/
|
|
251
|
-
fallbackPlan(userPrompt, intent, methodology) {
|
|
252
|
-
logger.info('[MethodologyPlanner] Using fallback plan');
|
|
253
|
-
// 尝试匹配决策规则
|
|
254
|
-
if (methodology.decision_rules) {
|
|
255
|
-
for (const rule of methodology.decision_rules) {
|
|
256
|
-
if (this.matchRule(rule.condition, intent)) {
|
|
257
|
-
const phases = rule.phases.map(phaseId => {
|
|
258
|
-
const template = methodology.phase_templates[phaseId];
|
|
259
|
-
return {
|
|
260
|
-
id: phaseId,
|
|
261
|
-
agent: template.agent,
|
|
262
|
-
prompt: template.prompt_template.replace('{target}', userPrompt),
|
|
263
|
-
rationale: template.description || `Execute ${phaseId} phase`,
|
|
264
|
-
artifacts: template.artifacts,
|
|
265
|
-
};
|
|
266
|
-
});
|
|
267
|
-
return {
|
|
268
|
-
phases,
|
|
269
|
-
rationale: rule.description || 'Using predefined rule',
|
|
270
|
-
methodology_id: methodology.id,
|
|
271
|
-
};
|
|
272
|
-
}
|
|
273
|
-
}
|
|
274
|
-
}
|
|
275
|
-
// 默认:使用所有阶段
|
|
276
|
-
const allPhases = Object.entries(methodology.phase_templates).map(([id, template]) => ({
|
|
277
|
-
id,
|
|
278
|
-
agent: template.agent,
|
|
279
|
-
prompt: template.prompt_template.replace('{target}', userPrompt),
|
|
280
|
-
rationale: template.description || `Execute ${id} phase`,
|
|
281
|
-
artifacts: template.artifacts,
|
|
282
|
-
}));
|
|
283
|
-
return {
|
|
284
|
-
phases: allPhases,
|
|
285
|
-
rationale: 'Using full methodology workflow (fallback)',
|
|
286
|
-
methodology_id: methodology.id,
|
|
287
|
-
};
|
|
288
|
-
}
|
|
289
|
-
/**
|
|
290
|
-
* 简单的规则匹配
|
|
291
|
-
*/
|
|
292
|
-
matchRule(condition, intent) {
|
|
293
|
-
// 简单的字符串匹配实现
|
|
294
|
-
// 例如: "complexity == 'simple' && taskType == 'refactor'"
|
|
295
|
-
const complexityMatch = condition.match(/complexity\s*==\s*'(\w+)'/);
|
|
296
|
-
const taskTypeMatch = condition.match(/taskType\s*==\s*'(\w+)'/);
|
|
297
|
-
if (complexityMatch && complexityMatch[1] !== intent.complexity) {
|
|
298
|
-
return false;
|
|
299
|
-
}
|
|
300
|
-
if (taskTypeMatch && taskTypeMatch[1] !== intent.taskType) {
|
|
301
|
-
return false;
|
|
302
|
-
}
|
|
303
|
-
return true;
|
|
304
|
-
}
|
|
305
|
-
}
|
|
306
|
-
//# sourceMappingURL=methodology-planner.js.map
|