@winspan/claude-forge 0.5.3 → 0.6.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 +3 -3
- package/dist/ai-gateway/index.d.ts +26 -0
- package/dist/ai-gateway/index.d.ts.map +1 -0
- package/dist/ai-gateway/index.js +67 -0
- package/dist/ai-gateway/index.js.map +1 -0
- package/dist/ai-gateway/model-selector.d.ts +6 -0
- package/dist/ai-gateway/model-selector.d.ts.map +1 -0
- package/dist/ai-gateway/model-selector.js +36 -0
- package/dist/ai-gateway/model-selector.js.map +1 -0
- package/dist/ai-gateway/rate-limiter.d.ts +20 -0
- package/dist/ai-gateway/rate-limiter.d.ts.map +1 -0
- package/dist/ai-gateway/rate-limiter.js +45 -0
- package/dist/ai-gateway/rate-limiter.js.map +1 -0
- package/dist/ai-gateway/response-cache.d.ts +17 -0
- package/dist/ai-gateway/response-cache.d.ts.map +1 -0
- package/dist/ai-gateway/response-cache.js +44 -0
- package/dist/ai-gateway/response-cache.js.map +1 -0
- package/dist/ai-provider/types.d.ts +2 -0
- package/dist/ai-provider/types.d.ts.map +1 -1
- package/dist/ai-provider/types.js.map +1 -1
- package/dist/daemon/handlers/context-builder.d.ts +55 -0
- package/dist/daemon/handlers/context-builder.d.ts.map +1 -0
- package/dist/daemon/handlers/context-builder.js +429 -0
- package/dist/daemon/handlers/context-builder.js.map +1 -0
- package/dist/daemon/handlers/orchestration-context.d.ts +37 -0
- package/dist/daemon/handlers/orchestration-context.d.ts.map +1 -0
- package/dist/daemon/handlers/orchestration-context.js +2 -0
- package/dist/daemon/handlers/orchestration-context.js.map +1 -0
- package/dist/daemon/handlers/session-cleanup.js +5 -5
- package/dist/daemon/handlers/session-cleanup.js.map +1 -1
- package/dist/daemon/handlers/stages/01-failure-signal.d.ts +8 -0
- package/dist/daemon/handlers/stages/01-failure-signal.d.ts.map +1 -0
- package/dist/daemon/handlers/stages/01-failure-signal.js +39 -0
- package/dist/daemon/handlers/stages/01-failure-signal.js.map +1 -0
- package/dist/daemon/handlers/stages/02-active-intervention.d.ts +8 -0
- package/dist/daemon/handlers/stages/02-active-intervention.d.ts.map +1 -0
- package/dist/daemon/handlers/stages/02-active-intervention.js +27 -0
- package/dist/daemon/handlers/stages/02-active-intervention.js.map +1 -0
- package/dist/daemon/handlers/stages/03-init-prompt.d.ts +8 -0
- package/dist/daemon/handlers/stages/03-init-prompt.d.ts.map +1 -0
- package/dist/daemon/handlers/stages/03-init-prompt.js +24 -0
- package/dist/daemon/handlers/stages/03-init-prompt.js.map +1 -0
- package/dist/daemon/handlers/stages/04-skill-suggestions.d.ts +8 -0
- package/dist/daemon/handlers/stages/04-skill-suggestions.d.ts.map +1 -0
- package/dist/daemon/handlers/stages/04-skill-suggestions.js +23 -0
- package/dist/daemon/handlers/stages/04-skill-suggestions.js.map +1 -0
- package/dist/daemon/handlers/stages/05-conv-config.d.ts +10 -0
- package/dist/daemon/handlers/stages/05-conv-config.d.ts.map +1 -0
- package/dist/daemon/handlers/stages/05-conv-config.js +23 -0
- package/dist/daemon/handlers/stages/05-conv-config.js.map +1 -0
- package/dist/daemon/handlers/stages/06-engine-check.d.ts +8 -0
- package/dist/daemon/handlers/stages/06-engine-check.d.ts.map +1 -0
- package/dist/daemon/handlers/stages/06-engine-check.js +13 -0
- package/dist/daemon/handlers/stages/06-engine-check.js.map +1 -0
- package/dist/daemon/handlers/stages/07-pipeline-reply.d.ts +9 -0
- package/dist/daemon/handlers/stages/07-pipeline-reply.d.ts.map +1 -0
- package/dist/daemon/handlers/stages/07-pipeline-reply.js +44 -0
- package/dist/daemon/handlers/stages/07-pipeline-reply.js.map +1 -0
- package/dist/daemon/handlers/stages/08-esc-interrupt.d.ts +9 -0
- package/dist/daemon/handlers/stages/08-esc-interrupt.d.ts.map +1 -0
- package/dist/daemon/handlers/stages/08-esc-interrupt.js +52 -0
- package/dist/daemon/handlers/stages/08-esc-interrupt.js.map +1 -0
- package/dist/daemon/handlers/stages/09-pipeline-active.d.ts +8 -0
- package/dist/daemon/handlers/stages/09-pipeline-active.d.ts.map +1 -0
- package/dist/daemon/handlers/stages/09-pipeline-active.js +20 -0
- package/dist/daemon/handlers/stages/09-pipeline-active.js.map +1 -0
- package/dist/daemon/handlers/stages/10-cooldown.d.ts +9 -0
- package/dist/daemon/handlers/stages/10-cooldown.d.ts.map +1 -0
- package/dist/daemon/handlers/stages/10-cooldown.js +44 -0
- package/dist/daemon/handlers/stages/10-cooldown.js.map +1 -0
- package/dist/daemon/handlers/stages/11-intent-analysis.d.ts +8 -0
- package/dist/daemon/handlers/stages/11-intent-analysis.d.ts.map +1 -0
- package/dist/daemon/handlers/stages/11-intent-analysis.js +38 -0
- package/dist/daemon/handlers/stages/11-intent-analysis.js.map +1 -0
- package/dist/daemon/handlers/stages/12-strategy-advice.d.ts +8 -0
- package/dist/daemon/handlers/stages/12-strategy-advice.d.ts.map +1 -0
- package/dist/daemon/handlers/stages/12-strategy-advice.js +20 -0
- package/dist/daemon/handlers/stages/12-strategy-advice.js.map +1 -0
- package/dist/daemon/handlers/stages/13-template-route.d.ts +8 -0
- package/dist/daemon/handlers/stages/13-template-route.d.ts.map +1 -0
- package/dist/daemon/handlers/stages/13-template-route.js +49 -0
- package/dist/daemon/handlers/stages/13-template-route.js.map +1 -0
- package/dist/daemon/handlers/stages/14-plan-resume.d.ts +8 -0
- package/dist/daemon/handlers/stages/14-plan-resume.d.ts.map +1 -0
- package/dist/daemon/handlers/stages/14-plan-resume.js +51 -0
- package/dist/daemon/handlers/stages/14-plan-resume.js.map +1 -0
- package/dist/daemon/handlers/stages/15-plan-enforcement.d.ts +8 -0
- package/dist/daemon/handlers/stages/15-plan-enforcement.d.ts.map +1 -0
- package/dist/daemon/handlers/stages/15-plan-enforcement.js +41 -0
- package/dist/daemon/handlers/stages/15-plan-enforcement.js.map +1 -0
- package/dist/daemon/handlers/stages/16-intervention-level.d.ts +8 -0
- package/dist/daemon/handlers/stages/16-intervention-level.d.ts.map +1 -0
- package/dist/daemon/handlers/stages/16-intervention-level.js +24 -0
- package/dist/daemon/handlers/stages/16-intervention-level.js.map +1 -0
- package/dist/daemon/handlers/stages/17-simple-task.d.ts +8 -0
- package/dist/daemon/handlers/stages/17-simple-task.d.ts.map +1 -0
- package/dist/daemon/handlers/stages/17-simple-task.js +47 -0
- package/dist/daemon/handlers/stages/17-simple-task.js.map +1 -0
- package/dist/daemon/handlers/stages/18-complex-task.d.ts +11 -0
- package/dist/daemon/handlers/stages/18-complex-task.d.ts.map +1 -0
- package/dist/daemon/handlers/stages/18-complex-task.js +84 -0
- package/dist/daemon/handlers/stages/18-complex-task.js.map +1 -0
- package/dist/daemon/handlers/stages/19-moderate-task.d.ts +8 -0
- package/dist/daemon/handlers/stages/19-moderate-task.d.ts.map +1 -0
- package/dist/daemon/handlers/stages/19-moderate-task.js +62 -0
- package/dist/daemon/handlers/stages/19-moderate-task.js.map +1 -0
- package/dist/daemon/handlers/stages/stage-interface.d.ts +24 -0
- package/dist/daemon/handlers/stages/stage-interface.d.ts.map +1 -0
- package/dist/daemon/handlers/stages/stage-interface.js +2 -0
- package/dist/daemon/handlers/stages/stage-interface.js.map +1 -0
- package/dist/daemon/handlers/stop-handler.js +2 -2
- package/dist/daemon/handlers/stop-handler.js.map +1 -1
- package/dist/daemon/handlers/user-prompt-handler.d.ts +1 -115
- package/dist/daemon/handlers/user-prompt-handler.d.ts.map +1 -1
- package/dist/daemon/handlers/user-prompt-handler.js +76 -1089
- package/dist/daemon/handlers/user-prompt-handler.js.map +1 -1
- package/dist/daemon/index.d.ts.map +1 -1
- package/dist/daemon/index.js +3 -1
- package/dist/daemon/index.js.map +1 -1
- package/dist/storage/repositories/api-usage-repository.d.ts +28 -0
- package/dist/storage/repositories/api-usage-repository.d.ts.map +1 -0
- package/dist/storage/repositories/api-usage-repository.js +59 -0
- package/dist/storage/repositories/api-usage-repository.js.map +1 -0
- package/dist/storage/repositories/base-repository.d.ts +6 -0
- package/dist/storage/repositories/base-repository.d.ts.map +1 -0
- package/dist/storage/repositories/base-repository.js +7 -0
- package/dist/storage/repositories/base-repository.js.map +1 -0
- package/dist/storage/repositories/distill-repository.d.ts +36 -0
- package/dist/storage/repositories/distill-repository.d.ts.map +1 -0
- package/dist/storage/repositories/distill-repository.js +85 -0
- package/dist/storage/repositories/distill-repository.js.map +1 -0
- package/dist/storage/repositories/event-repository.d.ts +14 -0
- package/dist/storage/repositories/event-repository.d.ts.map +1 -0
- package/dist/storage/repositories/event-repository.js +171 -0
- package/dist/storage/repositories/event-repository.js.map +1 -0
- package/dist/storage/repositories/failure-repository.d.ts +22 -0
- package/dist/storage/repositories/failure-repository.d.ts.map +1 -0
- package/dist/storage/repositories/failure-repository.js +26 -0
- package/dist/storage/repositories/failure-repository.js.map +1 -0
- package/dist/storage/repositories/intent-rule-repository.d.ts +20 -0
- package/dist/storage/repositories/intent-rule-repository.d.ts.map +1 -0
- package/dist/storage/repositories/intent-rule-repository.js +38 -0
- package/dist/storage/repositories/intent-rule-repository.js.map +1 -0
- package/dist/storage/repositories/knowledge-repository.d.ts +46 -0
- package/dist/storage/repositories/knowledge-repository.d.ts.map +1 -0
- package/dist/storage/repositories/knowledge-repository.js +84 -0
- package/dist/storage/repositories/knowledge-repository.js.map +1 -0
- package/dist/storage/repositories/latency-repository.d.ts +21 -0
- package/dist/storage/repositories/latency-repository.d.ts.map +1 -0
- package/dist/storage/repositories/latency-repository.js +42 -0
- package/dist/storage/repositories/latency-repository.js.map +1 -0
- package/dist/storage/repositories/maintenance-repository.d.ts +18 -0
- package/dist/storage/repositories/maintenance-repository.d.ts.map +1 -0
- package/dist/storage/repositories/maintenance-repository.js +61 -0
- package/dist/storage/repositories/maintenance-repository.js.map +1 -0
- package/dist/storage/repositories/satisfaction-repository.d.ts +21 -0
- package/dist/storage/repositories/satisfaction-repository.d.ts.map +1 -0
- package/dist/storage/repositories/satisfaction-repository.js +26 -0
- package/dist/storage/repositories/satisfaction-repository.js.map +1 -0
- package/dist/storage/repositories/session-repository.d.ts +16 -0
- package/dist/storage/repositories/session-repository.d.ts.map +1 -0
- package/dist/storage/repositories/session-repository.js +69 -0
- package/dist/storage/repositories/session-repository.js.map +1 -0
- package/dist/storage/repositories/task-repository.d.ts +82 -0
- package/dist/storage/repositories/task-repository.d.ts.map +1 -0
- package/dist/storage/repositories/task-repository.js +198 -0
- package/dist/storage/repositories/task-repository.js.map +1 -0
- package/dist/storage/sqlite.d.ts +25 -0
- package/dist/storage/sqlite.d.ts.map +1 -1
- package/dist/storage/sqlite.js +27 -0
- package/dist/storage/sqlite.js.map +1 -1
- package/dist/utils/claude-api.d.ts.map +1 -1
- package/dist/utils/claude-api.js +3 -1
- package/dist/utils/claude-api.js.map +1 -1
- package/dist/utils/logger.d.ts +7 -0
- package/dist/utils/logger.d.ts.map +1 -1
- package/dist/utils/logger.js +22 -0
- package/dist/utils/logger.js.map +1 -1
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -7,10 +7,10 @@ SDLC 智能编排引擎 — 透明旁听 Claude Code 对话,让 Claude 越用
|
|
|
7
7
|
## 核心功能
|
|
8
8
|
|
|
9
9
|
- **意图识别**:自动分析每条指令的复杂度,决定走直接执行还是多阶段编排
|
|
10
|
-
- **Pattern 工作流**:AI 语义匹配用户意图,按预定义多阶段 Pattern 注入结构化执行指令;支持项目级 Pattern 持久化和 Thompson Sampling 多臂老虎机策略选择(✅ 2026-04-16)
|
|
10
|
+
- **Pattern 工作流**:AI 语义匹配用户意图,按预定义多阶段 Pattern 注入结构化执行指令;支持项目级 Pattern 持久化和 Thompson Sampling 多臂老虎机策略选择(✅ 2026-04-16);统一编排模板系统(TemplateRegistry + TemplateRouter)替代 PatternEngine,内置 builtin-feature/bugfix/refactor 三个模板,PatternEngine 标记废弃(✅ 2026-04-17);UserPromptHandler 重构为 19 个 Stage 流水线(OrchestrationPipeline),handle() 精简为调度循环,各 Stage 独立可测试(✅ 2026-04-17);Storage 层重构为 Repository 模式(12 个子 Repository,向后兼容)(✅ 2026-04-17);AI Gateway 统一入口(全局限流 maxConcurrent=3/minInterval=200ms + 内存缓存 TTL=5min + 分层模型策略 Haiku/Sonnet/Opus label 驱动)(✅ 2026-04-17);UserPromptHandler 单元测试补全(null 组合/冷却/pipeline 回复,8/8 通过)(✅ 2026-04-17)
|
|
11
11
|
- **技能编排**:根据意图自动匹配并注入高质量技能(TDD、调试、重构、代码审查等)
|
|
12
12
|
- **多 AI 提供商**:支持 Claude、OpenAI、Ollama 等多种 AI 提供商,可灵活切换
|
|
13
|
-
- **Pipeline 编排**:复杂任务 AI 智能评估复杂度(simple/moderate/complex)和任务类型(bugfix/feature/refactor/performance),动态规划阶段列表(3-6 阶段),每阶段完成时自动生成结构化产物文档;AI 失败时 Forge 管理项目保守判定为需要 Pipeline;支持 profile 阶段(性能分析)、复杂度自适应推进阈值、Pipeline 强制执行;SQLite Schema v7 新增 complexity/planned_phases/phase_artifacts/reasoning 字段;ArtifactManager 统一产物目录管理(docs/YYYY-MM-DD/);Write/Edit 无 Pipeline 时硬阻断(✅ 2026-04-16);simple 路径 Forge 管理项目有代码改动时提升为 moderate + requiresPipeline(✅ 2026-04-16);阶段推进使用 plannedPhases 动态顺序,活动阈值按复杂度调整,profile 阶段完整支持(✅ 2026-04-17);AI 智能编排完整实现(analyzer/store/phase-manager/artifact-generator 全部适配 v7 schema)(✅ 2026-04-17);Daemon 事件缓冲区提升至 512KB(✅ 2026-04-17);Thompson Sampling bug 修复(✅ 2026-04-17);OpenAI/Ollama Token 追踪补全(✅ 2026-04-17);cf query stats 增强(成本汇总/满意度趋势)(✅ 2026-04-17);计划文档同步(Plan Mode 产物自动同步到 docs/YYYY-MM-DD/架构设计/)(✅ 2026-04-17);阶段产物生成支持中文文件名和阶段子目录(✅ 2026-04-17);BaseProvider 接口改造(doComplete 返回 usage 对象,支持 token 追踪和成本计算)(✅ 2026-04-17);Storage 方法扩展(getTotalCost/getCostByModel/getRecentSessions)(✅ 2026-04-17)
|
|
13
|
+
- **Pipeline 编排**:复杂任务 AI 智能评估复杂度(simple/moderate/complex)和任务类型(bugfix/feature/refactor/performance),动态规划阶段列表(3-6 阶段),每阶段完成时自动生成结构化产物文档;AI 失败时 Forge 管理项目保守判定为需要 Pipeline;支持 profile 阶段(性能分析)、复杂度自适应推进阈值、Pipeline 强制执行;SQLite Schema v7 新增 complexity/planned_phases/phase_artifacts/reasoning 字段;ArtifactManager 统一产物目录管理(docs/YYYY-MM-DD/);Write/Edit 无 Pipeline 时硬阻断(✅ 2026-04-16);simple 路径 Forge 管理项目有代码改动时提升为 moderate + requiresPipeline(✅ 2026-04-16);阶段推进使用 plannedPhases 动态顺序,活动阈值按复杂度调整,profile 阶段完整支持(✅ 2026-04-17);AI 智能编排完整实现(analyzer/store/phase-manager/artifact-generator 全部适配 v7 schema)(✅ 2026-04-17);Daemon 事件缓冲区提升至 512KB(✅ 2026-04-17);Thompson Sampling bug 修复(✅ 2026-04-17);OpenAI/Ollama Token 追踪补全(✅ 2026-04-17);cf query stats 增强(成本汇总/满意度趋势)(✅ 2026-04-17);计划文档同步(Plan Mode 产物自动同步到 docs/YYYY-MM-DD/架构设计/)(✅ 2026-04-17);阶段产物生成支持中文文件名和阶段子目录(✅ 2026-04-17);BaseProvider 接口改造(doComplete 返回 usage 对象,支持 token 追踪和成本计算)(✅ 2026-04-17);Storage 方法扩展(getTotalCost/getCostByModel/getRecentSessions)(✅ 2026-04-17);SQLite Schema v9 新增 daemon_state 持久化表(✅ 2026-04-17);Storage 层重构为 Repository 模式(EventRepository/SessionRepository/TaskRepository 等 11 个子 Repository,向后兼容)(✅ 2026-04-17);AI Gateway 统一入口(全局限流 maxConcurrent=3/minInterval=200ms + 内存缓存 TTL=5min + 分层模型策略 Haiku/Sonnet/Opus)(✅ 2026-04-17)
|
|
14
14
|
- **阶段产物生成**:Pipeline 每个阶段完成时,AI 自动生成对应文档(需求分析/PRD、架构设计/详细设计、性能分析报告、代码改动说明、测试报告、审查报告),存放在 `{project}/docs/YYYY-MM-DD/阶段名/`(统一使用项目 docs/ 目录);产物文件名自动加时间戳前缀避免冲突;支持按复杂度和任务类型动态调整产物清单;优先使用 AI 规划的 phaseArtifacts,降级到静态映射;中文文件名和阶段子目录(✅ 2026-04-17);幂等性保证(已存在则跳过)(✅ 2026-04-17);阶段产物生成失败时阻断阶段推进(✅ 2026-04-17);支持最多 2 次重试,超时延长至 90s(✅ 2026-04-17)
|
|
15
15
|
- **质量门禁**:Pipeline 每阶段完成时强制触发 AI 审查,阶段质量不过则阻止推进;Stop 时有未解决 fail 项则阻断会话结束;支持 Convention must 规范注入;支持质量问题持久化和抑制规则(✅ 2026-04-16)
|
|
16
16
|
- **任务复盘分析**:每次会话结束后自动分析执行质量,检测失败信号(用户不满意/迭代请求),生成 `retrospective.md` 报告,并将数据写入 SQLite 供后续模式学习;支持满意度评分和学习闭环(✅ 2026-04-16)
|
|
@@ -145,7 +145,7 @@ Claude 读取 additionalContext,按指令执行
|
|
|
145
145
|
| `~/.claude-forge/daemon.log` | 守护进程日志 |
|
|
146
146
|
| `~/.claude-forge/events.jsonl` | 结构化事件日志(JSONL,按项目分类) |
|
|
147
147
|
| `~/.claude-forge/orchestration-config.json` | 技能编排关键词映射 |
|
|
148
|
-
| `~/.claude-forge/patterns/` | Pattern 工作流定义(YAML) |
|
|
148
|
+
| `~/.claude-forge/patterns/` | Pattern 工作流定义(YAML,自动被 TemplateRegistry 加载转换为 PipelineTemplate) |
|
|
149
149
|
| `{project}/.claude-forge/decisions.md` | 项目决策日志(含树索引 decisions.tree.json) |
|
|
150
150
|
| `{project}/.claude-forge/timeline.md` | 项目时间线 |
|
|
151
151
|
| `{project}/.claude-forge/retrospective.md` | 任务复盘日志(每次 Stop 自动追加) |
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
import type { AIProvider, CompletionOptions } from '../ai-provider/types.js';
|
|
2
|
+
export interface GatewayOptions {
|
|
3
|
+
maxConcurrent?: number;
|
|
4
|
+
minIntervalMs?: number;
|
|
5
|
+
cacheTtlMs?: number;
|
|
6
|
+
/** 不缓存的 label 列表(如蒸馏、精炼等每次都需要新结果的调用) */
|
|
7
|
+
noCacheLabels?: string[];
|
|
8
|
+
/** 启用分层模型策略(Haiku/Sonnet/Opus) */
|
|
9
|
+
enableModelTiering?: boolean;
|
|
10
|
+
}
|
|
11
|
+
/**
|
|
12
|
+
* AI Gateway — 包装 AIProvider,提供全局限流 + 内存缓存 + 统一日志
|
|
13
|
+
* 实现 AIProvider 接口,可透明替换现有调用
|
|
14
|
+
*/
|
|
15
|
+
export declare class AIGateway implements AIProvider {
|
|
16
|
+
private inner;
|
|
17
|
+
private rateLimiter;
|
|
18
|
+
private cache;
|
|
19
|
+
private noCacheLabels;
|
|
20
|
+
private modelSelector;
|
|
21
|
+
constructor(inner: AIProvider, opts?: GatewayOptions);
|
|
22
|
+
complete(prompt: string, label?: string, options?: CompletionOptions): Promise<string>;
|
|
23
|
+
getStats(): Readonly<import("../ai-provider/types.js").ApiCallStats>;
|
|
24
|
+
formatStats(): string;
|
|
25
|
+
}
|
|
26
|
+
//# sourceMappingURL=index.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/ai-gateway/index.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,UAAU,EAAE,iBAAiB,EAAE,MAAM,yBAAyB,CAAC;AAM7E,MAAM,WAAW,cAAc;IAC7B,aAAa,CAAC,EAAE,MAAM,CAAC;IACvB,aAAa,CAAC,EAAE,MAAM,CAAC;IACvB,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,wCAAwC;IACxC,aAAa,CAAC,EAAE,MAAM,EAAE,CAAC;IACzB,kCAAkC;IAClC,kBAAkB,CAAC,EAAE,OAAO,CAAC;CAC9B;AAOD;;;GAGG;AACH,qBAAa,SAAU,YAAW,UAAU;IAM9B,OAAO,CAAC,KAAK;IALzB,OAAO,CAAC,WAAW,CAAc;IACjC,OAAO,CAAC,KAAK,CAAgB;IAC7B,OAAO,CAAC,aAAa,CAAc;IACnC,OAAO,CAAC,aAAa,CAAuB;gBAExB,KAAK,EAAE,UAAU,EAAE,IAAI,GAAE,cAAmB;IAU1D,QAAQ,CAAC,MAAM,EAAE,MAAM,EAAE,KAAK,CAAC,EAAE,MAAM,EAAE,OAAO,CAAC,EAAE,iBAAiB,GAAG,OAAO,CAAC,MAAM,CAAC;IA6B5F,QAAQ;IAIR,WAAW,IAAI,MAAM;CAMtB"}
|
|
@@ -0,0 +1,67 @@
|
|
|
1
|
+
import { RateLimiter } from './rate-limiter.js';
|
|
2
|
+
import { ResponseCache } from './response-cache.js';
|
|
3
|
+
import { ModelSelector } from './model-selector.js';
|
|
4
|
+
import { logger } from '../utils/logger.js';
|
|
5
|
+
const DEFAULT_NO_CACHE_LABELS = new Set([
|
|
6
|
+
'蒸馏', 'CLAUDE.md精炼', '文档同步', '技能演化', '模式学习',
|
|
7
|
+
'阶段产物生成', '复盘分析', '规则提炼',
|
|
8
|
+
]);
|
|
9
|
+
/**
|
|
10
|
+
* AI Gateway — 包装 AIProvider,提供全局限流 + 内存缓存 + 统一日志
|
|
11
|
+
* 实现 AIProvider 接口,可透明替换现有调用
|
|
12
|
+
*/
|
|
13
|
+
export class AIGateway {
|
|
14
|
+
inner;
|
|
15
|
+
rateLimiter;
|
|
16
|
+
cache;
|
|
17
|
+
noCacheLabels;
|
|
18
|
+
modelSelector;
|
|
19
|
+
constructor(inner, opts = {}) {
|
|
20
|
+
this.inner = inner;
|
|
21
|
+
this.rateLimiter = new RateLimiter(opts.maxConcurrent ?? 3, opts.minIntervalMs ?? 200);
|
|
22
|
+
this.cache = new ResponseCache();
|
|
23
|
+
this.noCacheLabels = new Set([
|
|
24
|
+
...DEFAULT_NO_CACHE_LABELS,
|
|
25
|
+
...(opts.noCacheLabels ?? []),
|
|
26
|
+
]);
|
|
27
|
+
this.modelSelector = opts.enableModelTiering !== false ? new ModelSelector() : null;
|
|
28
|
+
}
|
|
29
|
+
async complete(prompt, label, options) {
|
|
30
|
+
// 可缓存的调用先查缓存
|
|
31
|
+
const cacheable = label ? !this.noCacheLabels.has(label) : false;
|
|
32
|
+
if (cacheable) {
|
|
33
|
+
const cached = this.cache.get(prompt, label);
|
|
34
|
+
if (cached !== undefined) {
|
|
35
|
+
logger.debug(`[AI Gateway] 缓存命中 label=${label ?? '-'}`);
|
|
36
|
+
return cached;
|
|
37
|
+
}
|
|
38
|
+
}
|
|
39
|
+
// 限流
|
|
40
|
+
await this.rateLimiter.acquire();
|
|
41
|
+
try {
|
|
42
|
+
// 分层模型策略:根据 label 选择模型,注入 options.model
|
|
43
|
+
const tieredOptions = {
|
|
44
|
+
...options,
|
|
45
|
+
...(this.modelSelector ? { model: this.modelSelector.selectModel(label) } : {}),
|
|
46
|
+
};
|
|
47
|
+
const result = await this.inner.complete(prompt, label, tieredOptions);
|
|
48
|
+
if (cacheable) {
|
|
49
|
+
this.cache.set(prompt, label, result);
|
|
50
|
+
}
|
|
51
|
+
return result;
|
|
52
|
+
}
|
|
53
|
+
finally {
|
|
54
|
+
this.rateLimiter.release();
|
|
55
|
+
}
|
|
56
|
+
}
|
|
57
|
+
getStats() {
|
|
58
|
+
return this.inner.getStats();
|
|
59
|
+
}
|
|
60
|
+
formatStats() {
|
|
61
|
+
const inner = this.inner.formatStats();
|
|
62
|
+
const hitRate = (this.cache.hitRate * 100).toFixed(1);
|
|
63
|
+
const limiter = this.rateLimiter.stats;
|
|
64
|
+
return `${inner}\n[AI Gateway] 缓存命中率: ${hitRate}% | 缓存条目: ${this.cache.size} | 并发: ${limiter.active}/${3}`;
|
|
65
|
+
}
|
|
66
|
+
}
|
|
67
|
+
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/ai-gateway/index.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"model-selector.d.ts","sourceRoot":"","sources":["../../src/ai-gateway/model-selector.ts"],"names":[],"mappings":"AAAA,MAAM,MAAM,SAAS,GAAG,OAAO,GAAG,QAAQ,GAAG,MAAM,CAAC;AA6BpD,qBAAa,aAAa;IACxB,UAAU,CAAC,KAAK,CAAC,EAAE,MAAM,GAAG,SAAS;IAKrC,WAAW,CAAC,KAAK,CAAC,EAAE,MAAM,GAAG,MAAM;CAGpC"}
|
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
/** label → 模型分层映射 */
|
|
2
|
+
const LABEL_TO_TIER = {
|
|
3
|
+
// Haiku(快速/低成本)
|
|
4
|
+
'意图分析': 'haiku',
|
|
5
|
+
'规则匹配': 'haiku',
|
|
6
|
+
'缓存检查': 'haiku',
|
|
7
|
+
'失败信号检测': 'haiku',
|
|
8
|
+
'上下文压缩': 'haiku',
|
|
9
|
+
// Sonnet(默认)
|
|
10
|
+
'阶段产物生成': 'sonnet',
|
|
11
|
+
'蒸馏': 'sonnet',
|
|
12
|
+
'质量门禁': 'sonnet',
|
|
13
|
+
'文档同步': 'sonnet',
|
|
14
|
+
'技能演化': 'sonnet',
|
|
15
|
+
// Opus(复杂推理)
|
|
16
|
+
'CLAUDE.md精炼': 'opus',
|
|
17
|
+
'架构分析': 'opus',
|
|
18
|
+
'模式学习': 'opus',
|
|
19
|
+
};
|
|
20
|
+
/** 各分层对应的模型 ID */
|
|
21
|
+
const TIER_TO_MODEL = {
|
|
22
|
+
haiku: 'claude-haiku-4-5-20251001',
|
|
23
|
+
sonnet: 'claude-sonnet-4-6',
|
|
24
|
+
opus: 'claude-opus-4-6',
|
|
25
|
+
};
|
|
26
|
+
export class ModelSelector {
|
|
27
|
+
selectTier(label) {
|
|
28
|
+
if (!label)
|
|
29
|
+
return 'sonnet';
|
|
30
|
+
return LABEL_TO_TIER[label] ?? 'sonnet';
|
|
31
|
+
}
|
|
32
|
+
selectModel(label) {
|
|
33
|
+
return TIER_TO_MODEL[this.selectTier(label)];
|
|
34
|
+
}
|
|
35
|
+
}
|
|
36
|
+
//# sourceMappingURL=model-selector.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"model-selector.js","sourceRoot":"","sources":["../../src/ai-gateway/model-selector.ts"],"names":[],"mappings":"AAEA,qBAAqB;AACrB,MAAM,aAAa,GAA8B;IAC/C,gBAAgB;IAChB,MAAM,EAAE,OAAO;IACf,MAAM,EAAE,OAAO;IACf,MAAM,EAAE,OAAO;IACf,QAAQ,EAAE,OAAO;IACjB,OAAO,EAAE,OAAO;IAChB,aAAa;IACb,QAAQ,EAAE,QAAQ;IAClB,IAAI,EAAE,QAAQ;IACd,MAAM,EAAE,QAAQ;IAChB,MAAM,EAAE,QAAQ;IAChB,MAAM,EAAE,QAAQ;IAChB,aAAa;IACb,aAAa,EAAE,MAAM;IACrB,MAAM,EAAE,MAAM;IACd,MAAM,EAAE,MAAM;CACf,CAAC;AAEF,kBAAkB;AAClB,MAAM,aAAa,GAA8B;IAC/C,KAAK,EAAE,2BAA2B;IAClC,MAAM,EAAE,mBAAmB;IAC3B,IAAI,EAAE,iBAAiB;CACxB,CAAC;AAEF,MAAM,OAAO,aAAa;IACxB,UAAU,CAAC,KAAc;QACvB,IAAI,CAAC,KAAK;YAAE,OAAO,QAAQ,CAAC;QAC5B,OAAO,aAAa,CAAC,KAAK,CAAC,IAAI,QAAQ,CAAC;IAC1C,CAAC;IAED,WAAW,CAAC,KAAc;QACxB,OAAO,aAAa,CAAC,IAAI,CAAC,UAAU,CAAC,KAAK,CAAC,CAAC,CAAC;IAC/C,CAAC;CACF"}
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* 全局 AI 调用限流器
|
|
3
|
+
* maxConcurrent=3:最多同时 3 个并发 AI 调用
|
|
4
|
+
* minIntervalMs=200:两次调用之间最小间隔 200ms
|
|
5
|
+
*/
|
|
6
|
+
export declare class RateLimiter {
|
|
7
|
+
private maxConcurrent;
|
|
8
|
+
private minIntervalMs;
|
|
9
|
+
private activeCount;
|
|
10
|
+
private queue;
|
|
11
|
+
private lastCallAt;
|
|
12
|
+
constructor(maxConcurrent?: number, minIntervalMs?: number);
|
|
13
|
+
acquire(): Promise<void>;
|
|
14
|
+
release(): void;
|
|
15
|
+
get stats(): {
|
|
16
|
+
active: number;
|
|
17
|
+
queued: number;
|
|
18
|
+
};
|
|
19
|
+
}
|
|
20
|
+
//# sourceMappingURL=rate-limiter.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"rate-limiter.d.ts","sourceRoot":"","sources":["../../src/ai-gateway/rate-limiter.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AACH,qBAAa,WAAW;IAMpB,OAAO,CAAC,aAAa;IACrB,OAAO,CAAC,aAAa;IANvB,OAAO,CAAC,WAAW,CAAK;IACxB,OAAO,CAAC,KAAK,CAAyB;IACtC,OAAO,CAAC,UAAU,CAAK;gBAGb,aAAa,SAAI,EACjB,aAAa,SAAM;IAGvB,OAAO,IAAI,OAAO,CAAC,IAAI,CAAC;IAqB9B,OAAO,IAAI,IAAI;IAQf,IAAI,KAAK,IAAI;QAAE,MAAM,EAAE,MAAM,CAAC;QAAC,MAAM,EAAE,MAAM,CAAA;KAAE,CAE9C;CACF"}
|
|
@@ -0,0 +1,45 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* 全局 AI 调用限流器
|
|
3
|
+
* maxConcurrent=3:最多同时 3 个并发 AI 调用
|
|
4
|
+
* minIntervalMs=200:两次调用之间最小间隔 200ms
|
|
5
|
+
*/
|
|
6
|
+
export class RateLimiter {
|
|
7
|
+
maxConcurrent;
|
|
8
|
+
minIntervalMs;
|
|
9
|
+
activeCount = 0;
|
|
10
|
+
queue = [];
|
|
11
|
+
lastCallAt = 0;
|
|
12
|
+
constructor(maxConcurrent = 3, minIntervalMs = 200) {
|
|
13
|
+
this.maxConcurrent = maxConcurrent;
|
|
14
|
+
this.minIntervalMs = minIntervalMs;
|
|
15
|
+
}
|
|
16
|
+
async acquire() {
|
|
17
|
+
return new Promise((resolve) => {
|
|
18
|
+
const tryAcquire = () => {
|
|
19
|
+
const now = Date.now();
|
|
20
|
+
const sinceLastCall = now - this.lastCallAt;
|
|
21
|
+
if (this.activeCount < this.maxConcurrent && sinceLastCall >= this.minIntervalMs) {
|
|
22
|
+
this.activeCount++;
|
|
23
|
+
this.lastCallAt = now;
|
|
24
|
+
resolve();
|
|
25
|
+
}
|
|
26
|
+
else {
|
|
27
|
+
const delay = Math.max(this.minIntervalMs - sinceLastCall, this.activeCount >= this.maxConcurrent ? 50 : 0);
|
|
28
|
+
setTimeout(tryAcquire, delay);
|
|
29
|
+
}
|
|
30
|
+
};
|
|
31
|
+
tryAcquire();
|
|
32
|
+
});
|
|
33
|
+
}
|
|
34
|
+
release() {
|
|
35
|
+
this.activeCount = Math.max(0, this.activeCount - 1);
|
|
36
|
+
if (this.queue.length > 0) {
|
|
37
|
+
const next = this.queue.shift();
|
|
38
|
+
next?.();
|
|
39
|
+
}
|
|
40
|
+
}
|
|
41
|
+
get stats() {
|
|
42
|
+
return { active: this.activeCount, queued: this.queue.length };
|
|
43
|
+
}
|
|
44
|
+
}
|
|
45
|
+
//# sourceMappingURL=rate-limiter.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"rate-limiter.js","sourceRoot":"","sources":["../../src/ai-gateway/rate-limiter.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AACH,MAAM,OAAO,WAAW;IAMZ;IACA;IANF,WAAW,GAAG,CAAC,CAAC;IAChB,KAAK,GAAsB,EAAE,CAAC;IAC9B,UAAU,GAAG,CAAC,CAAC;IAEvB,YACU,gBAAgB,CAAC,EACjB,gBAAgB,GAAG;QADnB,kBAAa,GAAb,aAAa,CAAI;QACjB,kBAAa,GAAb,aAAa,CAAM;IAC1B,CAAC;IAEJ,KAAK,CAAC,OAAO;QACX,OAAO,IAAI,OAAO,CAAO,CAAC,OAAO,EAAE,EAAE;YACnC,MAAM,UAAU,GAAG,GAAG,EAAE;gBACtB,MAAM,GAAG,GAAG,IAAI,CAAC,GAAG,EAAE,CAAC;gBACvB,MAAM,aAAa,GAAG,GAAG,GAAG,IAAI,CAAC,UAAU,CAAC;gBAC5C,IAAI,IAAI,CAAC,WAAW,GAAG,IAAI,CAAC,aAAa,IAAI,aAAa,IAAI,IAAI,CAAC,aAAa,EAAE,CAAC;oBACjF,IAAI,CAAC,WAAW,EAAE,CAAC;oBACnB,IAAI,CAAC,UAAU,GAAG,GAAG,CAAC;oBACtB,OAAO,EAAE,CAAC;gBACZ,CAAC;qBAAM,CAAC;oBACN,MAAM,KAAK,GAAG,IAAI,CAAC,GAAG,CACpB,IAAI,CAAC,aAAa,GAAG,aAAa,EAClC,IAAI,CAAC,WAAW,IAAI,IAAI,CAAC,aAAa,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,CAAC,CAChD,CAAC;oBACF,UAAU,CAAC,UAAU,EAAE,KAAK,CAAC,CAAC;gBAChC,CAAC;YACH,CAAC,CAAC;YACF,UAAU,EAAE,CAAC;QACf,CAAC,CAAC,CAAC;IACL,CAAC;IAED,OAAO;QACL,IAAI,CAAC,WAAW,GAAG,IAAI,CAAC,GAAG,CAAC,CAAC,EAAE,IAAI,CAAC,WAAW,GAAG,CAAC,CAAC,CAAC;QACrD,IAAI,IAAI,CAAC,KAAK,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC;YAC1B,MAAM,IAAI,GAAG,IAAI,CAAC,KAAK,CAAC,KAAK,EAAE,CAAC;YAChC,IAAI,EAAE,EAAE,CAAC;QACX,CAAC;IACH,CAAC;IAED,IAAI,KAAK;QACP,OAAO,EAAE,MAAM,EAAE,IAAI,CAAC,WAAW,EAAE,MAAM,EAAE,IAAI,CAAC,KAAK,CAAC,MAAM,EAAE,CAAC;IACjE,CAAC;CACF"}
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* AI 响应内存缓存
|
|
3
|
+
* key = SHA256(prompt + label) 前 16 字符
|
|
4
|
+
* TTL = 5 分钟(可配置)
|
|
5
|
+
*/
|
|
6
|
+
export declare class ResponseCache {
|
|
7
|
+
private cache;
|
|
8
|
+
private hits;
|
|
9
|
+
private misses;
|
|
10
|
+
get(prompt: string, label?: string): string | undefined;
|
|
11
|
+
set(prompt: string, label: string | undefined, value: string, ttlMs?: number): void;
|
|
12
|
+
invalidate(): void;
|
|
13
|
+
get hitRate(): number;
|
|
14
|
+
get size(): number;
|
|
15
|
+
private makeKey;
|
|
16
|
+
}
|
|
17
|
+
//# sourceMappingURL=response-cache.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"response-cache.d.ts","sourceRoot":"","sources":["../../src/ai-gateway/response-cache.ts"],"names":[],"mappings":"AAOA;;;;GAIG;AACH,qBAAa,aAAa;IACxB,OAAO,CAAC,KAAK,CAAiC;IAC9C,OAAO,CAAC,IAAI,CAAK;IACjB,OAAO,CAAC,MAAM,CAAK;IAEnB,GAAG,CAAC,MAAM,EAAE,MAAM,EAAE,KAAK,CAAC,EAAE,MAAM,GAAG,MAAM,GAAG,SAAS;IAavD,GAAG,CAAC,MAAM,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,GAAG,SAAS,EAAE,KAAK,EAAE,MAAM,EAAE,KAAK,SAAU,GAAG,IAAI;IAKpF,UAAU,IAAI,IAAI;IAIlB,IAAI,OAAO,IAAI,MAAM,CAGpB;IAED,IAAI,IAAI,IAAI,MAAM,CAEjB;IAED,OAAO,CAAC,OAAO;CAGhB"}
|
|
@@ -0,0 +1,44 @@
|
|
|
1
|
+
import { createHash } from 'crypto';
|
|
2
|
+
/**
|
|
3
|
+
* AI 响应内存缓存
|
|
4
|
+
* key = SHA256(prompt + label) 前 16 字符
|
|
5
|
+
* TTL = 5 分钟(可配置)
|
|
6
|
+
*/
|
|
7
|
+
export class ResponseCache {
|
|
8
|
+
cache = new Map();
|
|
9
|
+
hits = 0;
|
|
10
|
+
misses = 0;
|
|
11
|
+
get(prompt, label) {
|
|
12
|
+
const key = this.makeKey(prompt, label);
|
|
13
|
+
const entry = this.cache.get(key);
|
|
14
|
+
if (!entry) {
|
|
15
|
+
this.misses++;
|
|
16
|
+
return undefined;
|
|
17
|
+
}
|
|
18
|
+
if (Date.now() > entry.expiresAt) {
|
|
19
|
+
this.cache.delete(key);
|
|
20
|
+
this.misses++;
|
|
21
|
+
return undefined;
|
|
22
|
+
}
|
|
23
|
+
this.hits++;
|
|
24
|
+
return entry.value;
|
|
25
|
+
}
|
|
26
|
+
set(prompt, label, value, ttlMs = 300_000) {
|
|
27
|
+
const key = this.makeKey(prompt, label);
|
|
28
|
+
this.cache.set(key, { value, expiresAt: Date.now() + ttlMs });
|
|
29
|
+
}
|
|
30
|
+
invalidate() {
|
|
31
|
+
this.cache.clear();
|
|
32
|
+
}
|
|
33
|
+
get hitRate() {
|
|
34
|
+
const total = this.hits + this.misses;
|
|
35
|
+
return total === 0 ? 0 : this.hits / total;
|
|
36
|
+
}
|
|
37
|
+
get size() {
|
|
38
|
+
return this.cache.size;
|
|
39
|
+
}
|
|
40
|
+
makeKey(prompt, label) {
|
|
41
|
+
return createHash('sha256').update(`${label ?? ''}::${prompt}`).digest('hex').slice(0, 16);
|
|
42
|
+
}
|
|
43
|
+
}
|
|
44
|
+
//# sourceMappingURL=response-cache.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"response-cache.js","sourceRoot":"","sources":["../../src/ai-gateway/response-cache.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,UAAU,EAAE,MAAM,QAAQ,CAAC;AAOpC;;;;GAIG;AACH,MAAM,OAAO,aAAa;IAChB,KAAK,GAAG,IAAI,GAAG,EAAsB,CAAC;IACtC,IAAI,GAAG,CAAC,CAAC;IACT,MAAM,GAAG,CAAC,CAAC;IAEnB,GAAG,CAAC,MAAc,EAAE,KAAc;QAChC,MAAM,GAAG,GAAG,IAAI,CAAC,OAAO,CAAC,MAAM,EAAE,KAAK,CAAC,CAAC;QACxC,MAAM,KAAK,GAAG,IAAI,CAAC,KAAK,CAAC,GAAG,CAAC,GAAG,CAAC,CAAC;QAClC,IAAI,CAAC,KAAK,EAAE,CAAC;YAAC,IAAI,CAAC,MAAM,EAAE,CAAC;YAAC,OAAO,SAAS,CAAC;QAAC,CAAC;QAChD,IAAI,IAAI,CAAC,GAAG,EAAE,GAAG,KAAK,CAAC,SAAS,EAAE,CAAC;YACjC,IAAI,CAAC,KAAK,CAAC,MAAM,CAAC,GAAG,CAAC,CAAC;YACvB,IAAI,CAAC,MAAM,EAAE,CAAC;YACd,OAAO,SAAS,CAAC;QACnB,CAAC;QACD,IAAI,CAAC,IAAI,EAAE,CAAC;QACZ,OAAO,KAAK,CAAC,KAAK,CAAC;IACrB,CAAC;IAED,GAAG,CAAC,MAAc,EAAE,KAAyB,EAAE,KAAa,EAAE,KAAK,GAAG,OAAO;QAC3E,MAAM,GAAG,GAAG,IAAI,CAAC,OAAO,CAAC,MAAM,EAAE,KAAK,CAAC,CAAC;QACxC,IAAI,CAAC,KAAK,CAAC,GAAG,CAAC,GAAG,EAAE,EAAE,KAAK,EAAE,SAAS,EAAE,IAAI,CAAC,GAAG,EAAE,GAAG,KAAK,EAAE,CAAC,CAAC;IAChE,CAAC;IAED,UAAU;QACR,IAAI,CAAC,KAAK,CAAC,KAAK,EAAE,CAAC;IACrB,CAAC;IAED,IAAI,OAAO;QACT,MAAM,KAAK,GAAG,IAAI,CAAC,IAAI,GAAG,IAAI,CAAC,MAAM,CAAC;QACtC,OAAO,KAAK,KAAK,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC,IAAI,GAAG,KAAK,CAAC;IAC7C,CAAC;IAED,IAAI,IAAI;QACN,OAAO,IAAI,CAAC,KAAK,CAAC,IAAI,CAAC;IACzB,CAAC;IAEO,OAAO,CAAC,MAAc,EAAE,KAAc;QAC5C,OAAO,UAAU,CAAC,QAAQ,CAAC,CAAC,MAAM,CAAC,GAAG,KAAK,IAAI,EAAE,KAAK,MAAM,EAAE,CAAC,CAAC,MAAM,CAAC,KAAK,CAAC,CAAC,KAAK,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC;IAC7F,CAAC;CACF"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../../src/ai-provider/types.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAEH,MAAM,WAAW,iBAAiB;IAChC,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,WAAW,CAAC,EAAE,MAAM,CAAC;
|
|
1
|
+
{"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../../src/ai-provider/types.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAEH,MAAM,WAAW,iBAAiB;IAChC,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,0CAA0C;IAC1C,KAAK,CAAC,EAAE,MAAM,CAAC;CAChB;AAED,MAAM,WAAW,YAAY;IAC3B,UAAU,EAAE,MAAM,CAAC;IACnB,WAAW,EAAE,MAAM,CAAC;IACpB,cAAc,EAAE,MAAM,CAAC;IACvB,YAAY,EAAE,MAAM,CAAC;IACrB,mBAAmB,EAAE,MAAM,CAAC;IAC5B,mBAAmB;IACnB,aAAa,EAAE,MAAM,CAAC;IACtB,mBAAmB;IACnB,cAAc,EAAE,MAAM,CAAC;IACvB,6CAA6C;IAC7C,OAAO,EAAE,MAAM,CAAC,MAAM,EAAE;QAAE,KAAK,EAAE,MAAM,CAAC;QAAC,MAAM,EAAE,MAAM,CAAC;QAAC,SAAS,EAAE,MAAM,CAAC;QAAC,OAAO,EAAE,MAAM,CAAC;QAAC,QAAQ,EAAE,MAAM,CAAC;QAAC,SAAS,EAAE,MAAM,CAAA;KAAE,CAAC,CAAC;CACrI;AAED,MAAM,WAAW,UAAU;IACzB;;;;;OAKG;IACH,QAAQ,CAAC,MAAM,EAAE,MAAM,EAAE,KAAK,CAAC,EAAE,MAAM,EAAE,OAAO,CAAC,EAAE,iBAAiB,GAAG,OAAO,CAAC,MAAM,CAAC,CAAC;IAEvF;;OAEG;IACH,QAAQ,IAAI,QAAQ,CAAC,YAAY,CAAC,CAAC;IAEnC;;OAEG;IACH,WAAW,IAAI,MAAM,CAAC;CACvB;AAED,qBAAa,eAAgB,SAAQ,KAAK;gBAC5B,SAAS,EAAE,MAAM;CAI9B;AAED,qBAAa,gBAAiB,SAAQ,KAAK;;CAK1C"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"types.js","sourceRoot":"","sources":["../../src/ai-provider/types.ts"],"names":[],"mappings":"AAAA;;;GAGG;
|
|
1
|
+
{"version":3,"file":"types.js","sourceRoot":"","sources":["../../src/ai-provider/types.ts"],"names":[],"mappings":"AAAA;;;GAGG;AA6CH,MAAM,OAAO,eAAgB,SAAQ,KAAK;IACxC,YAAY,SAAiB;QAC3B,KAAK,CAAC,YAAY,SAAS,KAAK,CAAC,CAAC;QAClC,IAAI,CAAC,IAAI,GAAG,iBAAiB,CAAC;IAChC,CAAC;CACF;AAED,MAAM,OAAO,gBAAiB,SAAQ,KAAK;IACzC;QACE,KAAK,CAAC,oBAAoB,CAAC,CAAC;QAC5B,IAAI,CAAC,IAAI,GAAG,kBAAkB,CAAC;IACjC,CAAC;CACF"}
|
|
@@ -0,0 +1,55 @@
|
|
|
1
|
+
import type { HandlerContext } from '../handler-context.js';
|
|
2
|
+
import type { InjectionCache } from './orchestration-context.js';
|
|
3
|
+
import type { Convention, ConventionRole } from '../../convention/types.js';
|
|
4
|
+
import type { ActivePlanSummary } from '../../utils/plan-reader.js';
|
|
5
|
+
/**
|
|
6
|
+
* ContextBuilder — 上下文构建工具类
|
|
7
|
+
* 包含所有从 UserPromptHandler 提取的工具方法
|
|
8
|
+
*/
|
|
9
|
+
export declare class ContextBuilder {
|
|
10
|
+
private ctx;
|
|
11
|
+
constructor(ctx: HandlerContext);
|
|
12
|
+
/** 构建会话上下文:最近的用户输入 + 工具调用摘要 */
|
|
13
|
+
buildConversationHistory(sessionId: string, projectPath: string): string | undefined;
|
|
14
|
+
/** 构建用户画像上下文 */
|
|
15
|
+
buildProfileContext(projectPath: string, cache: Map<string, InjectionCache>): string | undefined;
|
|
16
|
+
/** 读取项目人设文本 */
|
|
17
|
+
private readProjectPersona;
|
|
18
|
+
/** 构建计划进度上下文 */
|
|
19
|
+
buildPlanStartContext(projectPath: string, cache: Map<string, InjectionCache>): string | undefined;
|
|
20
|
+
/** 读取技能优化建议文件,读取后立即删除 */
|
|
21
|
+
readAndDeleteSkillSuggestions(projectPath: string, cache: Map<string, InjectionCache>): string | undefined;
|
|
22
|
+
/** 判断用户输入是否含有代码变更意图 */
|
|
23
|
+
isCodeChangeIntent(requirement: string): boolean;
|
|
24
|
+
/** 知识图谱上下文:查找历史成功路径 */
|
|
25
|
+
buildGraphContext(keywords: string[], projectPath: string): Promise<string | undefined>;
|
|
26
|
+
/** FTS5 历史场景检索 */
|
|
27
|
+
buildSimilarSessionContext(keywords: string[], projectPath: string, cache: Map<string, InjectionCache>): string | undefined;
|
|
28
|
+
/** 增量读取 decisions.md 末尾 */
|
|
29
|
+
readDecisionsFile(projectPath: string, cache: Map<string, InjectionCache>, tailBytes?: number): {
|
|
30
|
+
tail: string;
|
|
31
|
+
fingerprint: string;
|
|
32
|
+
} | null;
|
|
33
|
+
/** 读取项目决策历史 */
|
|
34
|
+
readDecisionsContext(requirement: string, projectPath: string, cache: Map<string, InjectionCache>): Promise<string | undefined>;
|
|
35
|
+
/** 树索引推理检索 */
|
|
36
|
+
private readDecisionsViaTreeIndex;
|
|
37
|
+
/** 降级方案:关键词切片 */
|
|
38
|
+
private readDecisionsContextFallback;
|
|
39
|
+
/** 根据用户需求关键词推断当前最匹配的 Convention 角色 */
|
|
40
|
+
inferCurrentRole(requirement: string, conventions: Convention[]): ConventionRole | null;
|
|
41
|
+
/** 负向重启回溯修正 */
|
|
42
|
+
applyNegativeRestartPenalty(projectPath: string, currentSessionId: string): Promise<void>;
|
|
43
|
+
/** 构建用户上下文(供 IntentEngine 有状态分析) */
|
|
44
|
+
buildUserContext(projectPath: string): {
|
|
45
|
+
work_style: 'guided' | 'balanced' | 'autonomous';
|
|
46
|
+
experience_level: 'beginner' | 'intermediate' | 'expert';
|
|
47
|
+
skip_rate: number;
|
|
48
|
+
override_rate: number;
|
|
49
|
+
avg_satisfaction: number;
|
|
50
|
+
preferred_complexity: 'simple' | 'moderate' | 'complex';
|
|
51
|
+
};
|
|
52
|
+
/** 读取活跃计划摘要 */
|
|
53
|
+
readActivePlanSummary(projectPath: string): ActivePlanSummary | undefined;
|
|
54
|
+
}
|
|
55
|
+
//# sourceMappingURL=context-builder.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"context-builder.d.ts","sourceRoot":"","sources":["../../../src/daemon/handlers/context-builder.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,uBAAuB,CAAC;AAC5D,OAAO,KAAK,EAAwB,cAAc,EAAE,MAAM,4BAA4B,CAAC;AAEvF,OAAO,KAAK,EAAE,UAAU,EAAE,cAAc,EAAE,MAAM,2BAA2B,CAAC;AAC5E,OAAO,KAAK,EAAE,iBAAiB,EAAE,MAAM,4BAA4B,CAAC;AAUpE;;;GAGG;AACH,qBAAa,cAAc;IACb,OAAO,CAAC,GAAG;gBAAH,GAAG,EAAE,cAAc;IAEvC,+BAA+B;IAC/B,wBAAwB,CAAC,SAAS,EAAE,MAAM,EAAE,WAAW,EAAE,MAAM,GAAG,MAAM,GAAG,SAAS;IAiDpF,gBAAgB;IAChB,mBAAmB,CAAC,WAAW,EAAE,MAAM,EAAE,KAAK,EAAE,GAAG,CAAC,MAAM,EAAE,cAAc,CAAC,GAAG,MAAM,GAAG,SAAS;IAiBhG,eAAe;IACf,OAAO,CAAC,kBAAkB;IAmB1B,gBAAgB;IAChB,qBAAqB,CAAC,WAAW,EAAE,MAAM,EAAE,KAAK,EAAE,GAAG,CAAC,MAAM,EAAE,cAAc,CAAC,GAAG,MAAM,GAAG,SAAS;IAgBlG,yBAAyB;IACzB,6BAA6B,CAAC,WAAW,EAAE,MAAM,EAAE,KAAK,EAAE,GAAG,CAAC,MAAM,EAAE,cAAc,CAAC,GAAG,MAAM,GAAG,SAAS;IAuB1G,uBAAuB;IACvB,kBAAkB,CAAC,WAAW,EAAE,MAAM,GAAG,OAAO;IAIhD,uBAAuB;IACjB,iBAAiB,CAAC,QAAQ,EAAE,MAAM,EAAE,EAAE,WAAW,EAAE,MAAM,GAAG,OAAO,CAAC,MAAM,GAAG,SAAS,CAAC;IAkB7F,kBAAkB;IAClB,0BAA0B,CAAC,QAAQ,EAAE,MAAM,EAAE,EAAE,WAAW,EAAE,MAAM,EAAE,KAAK,EAAE,GAAG,CAAC,MAAM,EAAE,cAAc,CAAC,GAAG,MAAM,GAAG,SAAS;IAqC3H,2BAA2B;IAC3B,iBAAiB,CAAC,WAAW,EAAE,MAAM,EAAE,KAAK,EAAE,GAAG,CAAC,MAAM,EAAE,cAAc,CAAC,EAAE,SAAS,SAAO,GAAG;QAAE,IAAI,EAAE,MAAM,CAAC;QAAC,WAAW,EAAE,MAAM,CAAA;KAAE,GAAG,IAAI;IAkC1I,eAAe;IACT,oBAAoB,CAAC,WAAW,EAAE,MAAM,EAAE,WAAW,EAAE,MAAM,EAAE,KAAK,EAAE,GAAG,CAAC,MAAM,EAAE,cAAc,CAAC,GAAG,OAAO,CAAC,MAAM,GAAG,SAAS,CAAC;IAuCrI,cAAc;YACA,yBAAyB;IA4BvC,iBAAiB;IACjB,OAAO,CAAC,4BAA4B;IAyCpC,sCAAsC;IACtC,gBAAgB,CAAC,WAAW,EAAE,MAAM,EAAE,WAAW,EAAE,UAAU,EAAE,GAAG,cAAc,GAAG,IAAI;IAiCvF,eAAe;IACT,2BAA2B,CAAC,WAAW,EAAE,MAAM,EAAE,gBAAgB,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC;IAiC/F,oCAAoC;IACpC,gBAAgB,CAAC,WAAW,EAAE,MAAM,GAAG;QACrC,UAAU,EAAE,QAAQ,GAAG,UAAU,GAAG,YAAY,CAAC;QACjD,gBAAgB,EAAE,UAAU,GAAG,cAAc,GAAG,QAAQ,CAAC;QACzD,SAAS,EAAE,MAAM,CAAC;QAClB,aAAa,EAAE,MAAM,CAAC;QACtB,gBAAgB,EAAE,MAAM,CAAC;QACzB,oBAAoB,EAAE,QAAQ,GAAG,UAAU,GAAG,SAAS,CAAC;KACzD;IAgCD,eAAe;IACf,qBAAqB,CAAC,WAAW,EAAE,MAAM,GAAG,iBAAiB,GAAG,SAAS;CAG1E"}
|